1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00

Merge pull request #4735 from IvanSavenko/private_pos

Reduce usages of ambiguos CGObjectInstance::pos
This commit is contained in:
Ivan Savenko 2024-10-10 15:00:50 +03:00 committed by GitHub
commit 5aebf287b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 142 additions and 150 deletions

View File

@ -864,7 +864,7 @@ void AIGateway::makeTurn()
void AIGateway::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h) void AIGateway::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
{ {
LOG_TRACE_PARAMS(logAi, "Hero %s and object %s at %s", h->getNameTranslated() % obj->getObjectName() % obj->pos.toString()); LOG_TRACE_PARAMS(logAi, "Hero %s and object %s at %s", h->getNameTranslated() % obj->getObjectName() % obj->anchorPos().toString());
switch(obj->ID) switch(obj->ID)
{ {
case Obj::TOWN: case Obj::TOWN:
@ -1455,7 +1455,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
void AIGateway::buildStructure(const CGTownInstance * t, BuildingID building) void AIGateway::buildStructure(const CGTownInstance * t, BuildingID building)
{ {
auto name = t->town->buildings.at(building)->getNameTranslated(); auto name = t->town->buildings.at(building)->getNameTranslated();
logAi->debug("Player %d will build %s in town of %s at %s", ai->playerID, name, t->getNameTranslated(), t->pos.toString()); logAi->debug("Player %d will build %s in town of %s at %s", ai->playerID, name, t->getNameTranslated(), t->anchorPos().toString());
cb->buildBuilding(t, building); //just do this; cb->buildBuilding(t, building); //just do this;
} }

View File

@ -52,7 +52,7 @@ void BuildThis::accept(AIGateway * ai)
if(cb->canBuildStructure(town, b) == EBuildingState::ALLOWED) if(cb->canBuildStructure(town, b) == EBuildingState::ALLOWED)
{ {
logAi->debug("Player %d will build %s in town of %s at %s", logAi->debug("Player %d will build %s in town of %s at %s",
ai->playerID, town->town->buildings.at(b)->getNameTranslated(), town->getNameTranslated(), town->pos.toString()); ai->playerID, town->town->buildings.at(b)->getNameTranslated(), town->getNameTranslated(), town->anchorPos().toString());
cb->buildBuilding(town, b); cb->buildBuilding(town, b);
return; return;

View File

@ -46,7 +46,7 @@ TSubgoal FindObj::whatToDoToAchieve()
} }
} }
} }
if(o && ai->isAccessible(o->pos)) //we don't use isAccessibleForHero as we don't know which hero it is if(o && ai->isAccessible(o->visitablePos())) //we don't use isAccessibleForHero as we don't know which hero it is
return sptr(VisitObj(o->id.getNum())); return sptr(VisitObj(o->id.getNum()));
else else
return sptr(Explore()); return sptr(Explore());

View File

@ -1032,7 +1032,7 @@ void VCAI::mainLoop()
void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h) void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
{ {
LOG_TRACE_PARAMS(logAi, "Hero %s and object %s at %s", h->getNameTranslated() % obj->getObjectName() % obj->pos.toString()); LOG_TRACE_PARAMS(logAi, "Hero %s and object %s at %s", h->getNameTranslated() % obj->getObjectName() % obj->anchorPos().toString());
switch(obj->ID) switch(obj->ID)
{ {
case Obj::TOWN: case Obj::TOWN:
@ -1417,11 +1417,11 @@ void VCAI::wander(HeroPtr h)
//TODO pick the truly best //TODO pick the truly best
const CGTownInstance * t = *boost::max_element(townsNotReachable, compareReinforcements); const CGTownInstance * t = *boost::max_element(townsNotReachable, compareReinforcements);
logAi->debug("%s can't reach any town, we'll try to make our way to %s at %s", h->getNameTranslated(), t->getNameTranslated(), t->visitablePos().toString()); logAi->debug("%s can't reach any town, we'll try to make our way to %s at %s", h->getNameTranslated(), t->getNameTranslated(), t->visitablePos().toString());
int3 pos1 = h->pos; int3 posBefore = h->visitablePos();
striveToGoal(sptr(Goals::ClearWayTo(t->visitablePos()).sethero(h))); //TODO: drop "strive", add to mainLoop striveToGoal(sptr(Goals::ClearWayTo(t->visitablePos()).sethero(h))); //TODO: drop "strive", add to mainLoop
//if out hero is stuck, we may need to request another hero to clear the way we see //if out hero is stuck, we may need to request another hero to clear the way we see
if(pos1 == h->pos && h == primaryHero()) //hero can't move if(posBefore == h->visitablePos() && h == primaryHero()) //hero can't move
{ {
if(canRecruitAnyHero(t)) if(canRecruitAnyHero(t))
recruitHero(t); recruitHero(t);
@ -1471,7 +1471,7 @@ void VCAI::wander(HeroPtr h)
{ {
auto chosenObject = cb->getObjInstance(ObjectInstanceID(bestObjectGoal->objid)); auto chosenObject = cb->getObjInstance(ObjectInstanceID(bestObjectGoal->objid));
if(chosenObject != nullptr) if(chosenObject != nullptr)
logAi->debug("Of all %d destinations, object %s at pos=%s seems nice", dests.size(), chosenObject->getObjectName(), chosenObject->pos.toString()); logAi->debug("Of all %d destinations, object %s at pos=%s seems nice", dests.size(), chosenObject->getObjectName(), chosenObject->anchorPos().toString());
} }
else else
logAi->debug("Trying to realize goal of type %s as part of wandering.", bestObjectGoal->name()); logAi->debug("Trying to realize goal of type %s as part of wandering.", bestObjectGoal->name());
@ -1995,7 +1995,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
void VCAI::buildStructure(const CGTownInstance * t, BuildingID building) void VCAI::buildStructure(const CGTownInstance * t, BuildingID building)
{ {
auto name = t->town->buildings.at(building)->getNameTranslated(); auto name = t->town->buildings.at(building)->getNameTranslated();
logAi->debug("Player %d will build %s in town of %s at %s", ai->playerID, name, t->getNameTranslated(), t->pos.toString()); logAi->debug("Player %d will build %s in town of %s at %s", ai->playerID, name, t->getNameTranslated(), t->anchorPos().toString());
cb->buildBuilding(t, building); //just do this; cb->buildBuilding(t, building); //just do this;
} }
@ -2081,7 +2081,7 @@ void VCAI::tryRealize(Goals::BuildThis & g)
if (cb->canBuildStructure(t, b) == EBuildingState::ALLOWED) if (cb->canBuildStructure(t, b) == EBuildingState::ALLOWED)
{ {
logAi->debug("Player %d will build %s in town of %s at %s", logAi->debug("Player %d will build %s in town of %s at %s",
playerID, t->town->buildings.at(b)->getNameTranslated(), t->getNameTranslated(), t->pos.toString()); playerID, t->town->buildings.at(b)->getNameTranslated(), t->getNameTranslated(), t->anchorPos().toString());
cb->buildBuilding(t, b); cb->buildBuilding(t, b);
throw goalFulfilledException(sptr(g)); throw goalFulfilledException(sptr(g));
} }

View File

@ -375,7 +375,7 @@ void HeroMovementController::sendMovementRequest(const CGHeroInstance * h, const
{ {
updateMovementSound(h, currNode.coord, nextNode.coord, nextNode.action); updateMovementSound(h, currNode.coord, nextNode.coord, nextNode.action);
assert(h->pos.z == nextNode.coord.z); // Z should change only if it's movement via teleporter and in this case this code shouldn't be executed at all assert(h->anchorPos().z == nextNode.coord.z); // Z should change only if it's movement via teleporter and in this case this code shouldn't be executed at all
logGlobal->trace("Requesting hero movement to %s", nextNode.coord.toString()); logGlobal->trace("Requesting hero movement to %s", nextNode.coord.toString());

View File

@ -81,9 +81,9 @@ void MapAudioPlayer::addObject(const CGObjectInstance * obj)
{ {
for(int fy = 0; fy < obj->getHeight(); ++fy) for(int fy = 0; fy < obj->getHeight(); ++fy)
{ {
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z); int3 currTile(obj->anchorPos().x - fx, obj->anchorPos().y - fy, obj->anchorPos().z);
if(LOCPLINT->cb->isInTheMap(currTile) && obj->coveringAt(currTile.x, currTile.y)) if(LOCPLINT->cb->isInTheMap(currTile) && obj->coveringAt(currTile))
objects[currTile.z][currTile.x][currTile.y].push_back(obj->id); objects[currTile.z][currTile.x][currTile.y].push_back(obj->id);
} }
} }
@ -108,7 +108,7 @@ void MapAudioPlayer::addObject(const CGObjectInstance * obj)
for(const auto & tile : tiles) for(const auto & tile : tiles)
{ {
int3 currTile = obj->pos + tile; int3 currTile = obj->anchorPos() + tile;
if(LOCPLINT->cb->isInTheMap(currTile)) if(LOCPLINT->cb->isInTheMap(currTile))
objects[currTile.z][currTile.x][currTile.y].push_back(obj->id); objects[currTile.z][currTile.x][currTile.y].push_back(obj->id);

View File

@ -591,8 +591,8 @@ void MapRendererOverlay::renderTile(IMapRendererContext & context, Canvas & targ
if(context.objectTransparency(objectID, coordinates) > 0 && !context.isActiveHero(object)) if(context.objectTransparency(objectID, coordinates) > 0 && !context.isActiveHero(object))
{ {
visitable |= object->visitableAt(coordinates.x, coordinates.y); visitable |= object->visitableAt(coordinates);
blocking |= object->blockingAt(coordinates.x, coordinates.y); blocking |= object->blockingAt(coordinates);
} }
} }

View File

@ -120,7 +120,7 @@ size_t MapRendererBaseContext::objectGroupIndex(ObjectInstanceID objectID) const
Point MapRendererBaseContext::objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const Point MapRendererBaseContext::objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const
{ {
const CGObjectInstance * object = getObject(objectID); const CGObjectInstance * object = getObject(objectID);
int3 offsetTiles(object->getPosition() - coordinates); int3 offsetTiles(object->anchorPos() - coordinates);
return Point(offsetTiles) * Point(32, 32); return Point(offsetTiles) * Point(32, 32);
} }
@ -498,7 +498,7 @@ size_t MapRendererWorldViewContext::overlayImageIndex(const int3 & coordinates)
{ {
const auto * object = getObject(objectID); const auto * object = getObject(objectID);
if(!object->visitableAt(coordinates.x, coordinates.y)) if(!object->visitableAt(coordinates))
continue; continue;
ObjectPosInfo info(object); ObjectPosInfo info(object);

View File

@ -49,9 +49,9 @@ void MapRendererContextState::addObject(const CGObjectInstance * obj)
{ {
for(int fy = 0; fy < obj->getHeight(); ++fy) for(int fy = 0; fy < obj->getHeight(); ++fy)
{ {
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z); int3 currTile(obj->anchorPos().x - fx, obj->anchorPos().y - fy, obj->anchorPos().z);
if(LOCPLINT->cb->isInTheMap(currTile) && obj->coveringAt(currTile.x, currTile.y)) if(LOCPLINT->cb->isInTheMap(currTile) && obj->coveringAt(currTile))
{ {
auto & container = objects[currTile.z][currTile.x][currTile.y]; auto & container = objects[currTile.z][currTile.x][currTile.y];
@ -73,7 +73,7 @@ void MapRendererContextState::addMovingObject(const CGObjectInstance * object, c
{ {
for(int y = yFrom; y <= yDest; ++y) for(int y = yFrom; y <= yDest; ++y)
{ {
int3 currTile(x, y, object->pos.z); int3 currTile(x, y, object->anchorPos().z);
if(LOCPLINT->cb->isInTheMap(currTile)) if(LOCPLINT->cb->isInTheMap(currTile))
{ {

View File

@ -317,7 +317,7 @@ bool MapViewController::isEventVisible(const CGObjectInstance * obj, const Playe
if(obj->isVisitable()) if(obj->isVisitable())
return context->isVisible(obj->visitablePos()); return context->isVisible(obj->visitablePos());
else else
return context->isVisible(obj->pos); return context->isVisible(obj->anchorPos());
} }
bool MapViewController::isEventVisible(const CGHeroInstance * obj, const int3 & from, const int3 & dest) bool MapViewController::isEventVisible(const CGHeroInstance * obj, const int3 & from, const int3 & dest)

View File

@ -59,7 +59,7 @@ std::string CMapHandler::getTerrainDescr(const int3 & pos, bool rightClick) cons
for(const auto & object : map->objects) for(const auto & object : map->objects)
{ {
if(object && object->coveringAt(pos.x, pos.y) && object->pos.z == pos.z && object->isTile2Terrain()) if(object && object->coveringAt(pos) && object->isTile2Terrain())
{ {
result = object->getObjectName(); result = object->getObjectName();
break; break;
@ -103,15 +103,15 @@ bool CMapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObj
for(const auto & aOffset : a->getBlockedOffsets()) for(const auto & aOffset : a->getBlockedOffsets())
{ {
int3 testTarget = a->pos + aOffset + int3(0, 1, 0); int3 testTarget = a->anchorPos() + aOffset + int3(0, 1, 0);
if(b->blockingAt(testTarget.x, testTarget.y)) if(b->blockingAt(testTarget))
bBlocksA += 1; bBlocksA += 1;
} }
for(const auto & bOffset : b->getBlockedOffsets()) for(const auto & bOffset : b->getBlockedOffsets())
{ {
int3 testTarget = b->pos + bOffset + int3(0, 1, 0); int3 testTarget = b->anchorPos() + bOffset + int3(0, 1, 0);
if(a->blockingAt(testTarget.x, testTarget.y)) if(a->blockingAt(testTarget))
aBlocksB += 1; aBlocksB += 1;
} }
@ -126,8 +126,8 @@ bool CMapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObj
return aBlocksB < bBlocksA; return aBlocksB < bBlocksA;
// object that don't have clear priority via tile blocking will appear based on their row // object that don't have clear priority via tile blocking will appear based on their row
if(a->pos.y != b->pos.y) if(a->anchorPos().y != b->anchorPos().y)
return a->pos.y < b->pos.y; return a->anchorPos().y < b->anchorPos().y;
// heroes should appear on top of objects on the same tile // heroes should appear on top of objects on the same tile
if(b->ID==Obj::HERO && a->ID!=Obj::HERO) if(b->ID==Obj::HERO && a->ID!=Obj::HERO)

View File

@ -78,7 +78,7 @@ void CQuestMinimap::addQuestMarks (const QuestInfo * q)
int3 tile; int3 tile;
if (q->obj) if (q->obj)
tile = q->obj->pos; tile = q->obj->visitablePos();
else else
tile = q->tile; tile = q->tile;
@ -104,7 +104,7 @@ void CQuestMinimap::update()
void CQuestMinimap::iconClicked() void CQuestMinimap::iconClicked()
{ {
if(currentQuest->obj) if(currentQuest->obj)
adventureInt->centerOnTile(currentQuest->obj->pos); adventureInt->centerOnTile(currentQuest->obj->visitablePos());
//moveAdvMapSelection(); //moveAdvMapSelection();
} }

View File

@ -539,7 +539,7 @@ EDiggingStatus CGameInfoCallback::getTileDigStatus(int3 tile, bool verbose) cons
for(const auto & object : gs->map->objects) for(const auto & object : gs->map->objects)
{ {
if(object && object->ID == Obj::HOLE && object->pos == tile) if(object && object->ID == Obj::HOLE && object->anchorPos() == tile)
return EDiggingStatus::TILE_OCCUPIED; return EDiggingStatus::TILE_OCCUPIED;
} }
return getTile(tile)->getDiggingStatus(); return getTile(tile)->getDiggingStatus();

View File

@ -449,7 +449,7 @@ void CGameState::initGrailPosition()
//remove tiles with holes //remove tiles with holes
for(auto & elem : map->objects) for(auto & elem : map->objects)
if(elem && elem->ID == Obj::HOLE) if(elem && elem->ID == Obj::HOLE)
allowedPos -= elem->pos; allowedPos -= elem->anchorPos();
if(!allowedPos.empty()) if(!allowedPos.empty())
{ {
@ -495,7 +495,7 @@ void CGameState::randomizeMapObjects()
{ {
for (int j = 0; j < object->getHeight() ; j++) for (int j = 0; j < object->getHeight() ; j++)
{ {
int3 pos = object->pos - int3(i,j,0); int3 pos = object->anchorPos() - int3(i,j,0);
if(map->isInTheMap(pos)) map->getTile(pos).extTileFlags |= 128; if(map->isInTheMap(pos)) map->getTile(pos).extTileFlags |= 128;
} }
} }
@ -530,7 +530,7 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy
{ {
for(auto town : map->towns) for(auto town : map->towns)
{ {
if(town->getPosition() == townPos) if(town->anchorPos() == townPos)
{ {
townPos = town->visitablePos(); townPos = town->visitablePos();
break; break;
@ -545,8 +545,7 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy
hero->setHeroType(heroTypeId); hero->setHeroType(heroTypeId);
hero->tempOwner = playerColor; hero->tempOwner = playerColor;
hero->pos = townPos; hero->setAnchorPos(townPos + hero->getVisitableOffset());
hero->pos += hero->getVisitableOffset();
map->getEditManager()->insertObject(hero); map->getEditManager()->insertObject(hero);
} }
@ -614,7 +613,7 @@ void CGameState::initHeroes()
auto boat = dynamic_cast<CGBoat*>(handler->create(callback, nullptr)); auto boat = dynamic_cast<CGBoat*>(handler->create(callback, nullptr));
handler->configureObject(boat, gs->getRandomGenerator()); handler->configureObject(boat, gs->getRandomGenerator());
boat->pos = hero->pos; boat->setAnchorPos(hero->anchorPos());
boat->appearance = handler->getTemplates().front(); boat->appearance = handler->getTemplates().front();
boat->id = ObjectInstanceID(static_cast<si32>(gs->map->objects.size())); boat->id = ObjectInstanceID(static_cast<si32>(gs->map->objects.size()));
@ -964,22 +963,18 @@ void CGameState::placeHeroesInTowns()
{ {
for(CGTownInstance * t : player.second.getTowns()) for(CGTownInstance * t : player.second.getTowns())
{ {
if(h->visitablePos().z != t->visitablePos().z) bool heroOnTownBlockableTile = t->blockingAt(h->visitablePos());
continue;
bool heroOnTownBlockableTile = t->blockingAt(h->visitablePos().x, h->visitablePos().y);
// current hero position is at one of blocking tiles of current town // current hero position is at one of blocking tiles of current town
// assume that this hero should be visiting the town (H3M format quirk) and move hero to correct position // assume that this hero should be visiting the town (H3M format quirk) and move hero to correct position
if (heroOnTownBlockableTile) if (heroOnTownBlockableTile)
{ {
int3 correctedPos = h->convertFromVisitablePos(t->visitablePos());
map->removeBlockVisTiles(h); map->removeBlockVisTiles(h);
h->pos = correctedPos; int3 correctedPos = h->convertFromVisitablePos(t->visitablePos());
h->setAnchorPos(correctedPos);
map->addBlockVisTiles(h); map->addBlockVisTiles(h);
assert(t->visitableAt(h->visitablePos().x, h->visitablePos().y)); assert(t->visitableAt(h->visitablePos()));
} }
} }
} }
@ -1001,7 +996,7 @@ void CGameState::initVisitingAndGarrisonedHeroes()
if(h->visitablePos().z != t->visitablePos().z) if(h->visitablePos().z != t->visitablePos().z)
continue; continue;
if (t->visitableAt(h->visitablePos().x, h->visitablePos().y)) if (t->visitableAt(h->visitablePos()))
{ {
assert(t->visitingHero == nullptr); assert(t->visitingHero == nullptr);
t->setVisitingHero(h); t->setVisitingHero(h);
@ -1066,7 +1061,7 @@ BattleField CGameState::battleGetBattlefieldType(int3 tile, vstd::RNG & rand)
for(auto &obj : map->objects) for(auto &obj : map->objects)
{ {
//look only for objects covering given tile //look only for objects covering given tile
if( !obj || obj->pos.z != tile.z || !obj->coveringAt(tile.x, tile.y)) if( !obj || !obj->coveringAt(tile))
continue; continue;
auto customBattlefield = obj->getBattlefield(); auto customBattlefield = obj->getBattlefield();
@ -1250,10 +1245,10 @@ bool CGameState::isVisible(const CGObjectInstance * obj, const std::optional<Pla
{ {
for(int fx=0; fx < obj->getWidth(); ++fx) for(int fx=0; fx < obj->getWidth(); ++fx)
{ {
int3 pos = obj->pos + int3(-fx, -fy, 0); int3 pos = obj->anchorPos() + int3(-fx, -fy, 0);
if ( map->isInTheMap(pos) && if ( map->isInTheMap(pos) &&
obj->coveringAt(pos.x, pos.y) && obj->coveringAt(pos) &&
isVisible(pos, *player)) isVisible(pos, *player))
return true; return true;
} }

View File

@ -368,7 +368,7 @@ void CGameStateCampaign::replaceHeroesPlaceholders()
heroToPlace->id = campaignHeroReplacement.heroPlaceholderId; heroToPlace->id = campaignHeroReplacement.heroPlaceholderId;
if(heroPlaceholder->tempOwner.isValidPlayer()) if(heroPlaceholder->tempOwner.isValidPlayer())
heroToPlace->tempOwner = heroPlaceholder->tempOwner; heroToPlace->tempOwner = heroPlaceholder->tempOwner;
heroToPlace->pos = heroPlaceholder->pos; heroToPlace->setAnchorPos(heroPlaceholder->anchorPos());
heroToPlace->type = heroToPlace->getHeroType().toHeroType(); heroToPlace->type = heroToPlace->getHeroType().toHeroType();
heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front(); heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front();
@ -655,7 +655,7 @@ void CGameStateCampaign::initTowns()
if (!owner->human) if (!owner->human)
continue; continue;
if (town->pos != pi.posOfMainTown) if (town->anchorPos() != pi.posOfMainTown)
continue; continue;
BuildingID newBuilding; BuildingID newBuilding;

View File

@ -33,7 +33,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const
if(stacks.empty()) if(stacks.empty())
{ {
//should not happen... //should not happen...
logGlobal->error("Invalid stack at tile %s: subID=%d; id=%d", pos.toString(), getCreature(), id.getNum()); logGlobal->error("Invalid stack at tile %s: subID=%d; id=%d", anchorPos().toString(), getCreature(), id.getNum());
return "INVALID_STACK"; return "INVALID_STACK";
} }
@ -562,7 +562,7 @@ bool CGCreature::containsUpgradedStack() const
float c = 5325.181015f; float c = 5325.181015f;
float d = 32788.727920f; float d = 32788.727920f;
int val = static_cast<int>(std::floor(a * pos.x + b * pos.y + c * pos.z + d)); int val = static_cast<int>(std::floor(a * visitablePos().x + b * visitablePos().y + c * visitablePos().z + d));
return ((val % 32768) % 100) < 50; return ((val % 32768) % 100) < 50;
} }
@ -591,7 +591,7 @@ int CGCreature::getNumberOfStacks(const CGHeroInstance *hero) const
ui32 c = 1943276003u; ui32 c = 1943276003u;
ui32 d = 3174620878u; ui32 d = 3174620878u;
ui32 R1 = a * static_cast<ui32>(pos.x) + b * static_cast<ui32>(pos.y) + c * static_cast<ui32>(pos.z) + d; ui32 R1 = a * static_cast<ui32>(visitablePos().x) + b * static_cast<ui32>(visitablePos().y) + c * static_cast<ui32>(visitablePos().z) + d;
ui32 R2 = (R1 >> 16) & 0x7fff; ui32 R2 = (R1 >> 16) & 0x7fff;
int R4 = R2 % 100 + 1; int R4 = R2 % 100 + 1;

View File

@ -1514,11 +1514,11 @@ bool CGHeroInstance::hasVisions(const CGObjectInstance * target, BonusSubtypeID
if (visionsMultiplier > 0) if (visionsMultiplier > 0)
vstd::amax(visionsRange, 3); //minimum range is 3 tiles, but only if VISIONS bonus present vstd::amax(visionsRange, 3); //minimum range is 3 tiles, but only if VISIONS bonus present
const int distance = static_cast<int>(target->pos.dist2d(visitablePos())); const int distance = static_cast<int>(target->anchorPos().dist2d(visitablePos()));
//logGlobal->debug(boost::str(boost::format("Visions: dist %d, mult %d, range %d") % distance % visionsMultiplier % visionsRange)); //logGlobal->debug(boost::str(boost::format("Visions: dist %d, mult %d, range %d") % distance % visionsMultiplier % visionsRange));
return (distance < visionsRange) && (target->pos.z == pos.z); return (distance < visionsRange) && (target->anchorPos().z == anchorPos().z);
} }
std::string CGHeroInstance::getHeroTypeName() const std::string CGHeroInstance::getHeroTypeName() const

View File

@ -54,14 +54,14 @@ MapObjectSubID CGObjectInstance::getObjTypeIndex() const
return subID; return subID;
} }
int3 CGObjectInstance::getPosition() const int3 CGObjectInstance::anchorPos() const
{ {
return pos; return pos;
} }
int3 CGObjectInstance::getTopVisiblePos() const int3 CGObjectInstance::getTopVisiblePos() const
{ {
return pos - appearance->getTopVisibleOffset(); return anchorPos() - appearance->getTopVisibleOffset();
} }
void CGObjectInstance::setOwner(const PlayerColor & ow) void CGObjectInstance::setOwner(const PlayerColor & ow)
@ -69,6 +69,11 @@ void CGObjectInstance::setOwner(const PlayerColor & ow)
tempOwner = ow; tempOwner = ow;
} }
void CGObjectInstance::setAnchorPos(int3 newPos)
{
pos = newPos;
}
int CGObjectInstance::getWidth() const int CGObjectInstance::getWidth() const
{ {
return appearance->getWidth(); return appearance->getWidth();
@ -79,32 +84,19 @@ int CGObjectInstance::getHeight() const
return appearance->getHeight(); return appearance->getHeight();
} }
bool CGObjectInstance::visitableAt(int x, int y) const
{
return appearance->isVisitableAt(pos.x - x, pos.y - y);
}
bool CGObjectInstance::blockingAt(int x, int y) const
{
return appearance->isBlockedAt(pos.x - x, pos.y - y);
}
bool CGObjectInstance::coveringAt(int x, int y) const
{
return appearance->isVisibleAt(pos.x - x, pos.y - y);
}
bool CGObjectInstance::visitableAt(const int3 & testPos) const bool CGObjectInstance::visitableAt(const int3 & testPos) const
{ {
return pos.z == testPos.z && appearance->isVisitableAt(pos.x - testPos.x, pos.y - testPos.y); return anchorPos().z == testPos.z && appearance->isVisitableAt(anchorPos().x - testPos.x, anchorPos().y - testPos.y);
} }
bool CGObjectInstance::blockingAt(const int3 & testPos) const bool CGObjectInstance::blockingAt(const int3 & testPos) const
{ {
return pos.z == testPos.z && appearance->isBlockedAt(pos.x - testPos.x, pos.y - testPos.y); return anchorPos().z == testPos.z && appearance->isBlockedAt(anchorPos().x - testPos.x, anchorPos().y - testPos.y);
} }
bool CGObjectInstance::coveringAt(const int3 & testPos) const bool CGObjectInstance::coveringAt(const int3 & testPos) const
{ {
return pos.z == testPos.z && appearance->isVisibleAt(pos.x - testPos.x, pos.y - testPos.y); return anchorPos().z == testPos.z && appearance->isVisibleAt(anchorPos().x - testPos.x, anchorPos().y - testPos.y);
} }
std::set<int3> CGObjectInstance::getBlockedPos() const std::set<int3> CGObjectInstance::getBlockedPos() const
@ -115,7 +107,7 @@ std::set<int3> CGObjectInstance::getBlockedPos() const
for(int h=0; h<getHeight(); ++h) for(int h=0; h<getHeight(); ++h)
{ {
if(appearance->isBlockedAt(w, h)) if(appearance->isBlockedAt(w, h))
ret.insert(int3(pos.x - w, pos.y - h, pos.z)); ret.insert(int3(anchorPos().x - w, anchorPos().y - h, anchorPos().z));
} }
} }
return ret; return ret;
@ -215,6 +207,8 @@ int CGObjectInstance::getSightRadius() const
int3 CGObjectInstance::getVisitableOffset() const int3 CGObjectInstance::getVisitableOffset() const
{ {
if (!isVisitable())
throw std::runtime_error("Attempt to access visitable offset of a non-visitable object!");
return appearance->getVisitableOffset(); return appearance->getVisitableOffset();
} }
@ -313,6 +307,9 @@ void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
int3 CGObjectInstance::visitablePos() const int3 CGObjectInstance::visitablePos() const
{ {
if (!isVisitable())
throw std::runtime_error("Attempt to access visitable position on a non-visitable object!");
return pos - getVisitableOffset(); return pos - getVisitableOffset();
} }

View File

@ -28,8 +28,6 @@ using TObjectTypeHandler = std::shared_ptr<AObjectTypeHandler>;
class DLL_LINKAGE CGObjectInstance : public IObjectInterface class DLL_LINKAGE CGObjectInstance : public IObjectInterface
{ {
public: public:
/// Position of bottom-right corner of object on map
int3 pos;
/// Type of object, e.g. town, hero, creature. /// Type of object, e.g. town, hero, creature.
MapObjectID ID; MapObjectID ID;
/// Subtype of object, depends on type /// Subtype of object, depends on type
@ -41,6 +39,9 @@ public:
/// Defines appearance of object on map (animation, blocked tiles, blit order, etc) /// Defines appearance of object on map (animation, blocked tiles, blit order, etc)
std::shared_ptr<const ObjectTemplate> appearance; std::shared_ptr<const ObjectTemplate> appearance;
/// Position of bottom-right corner of object on map
int3 pos;
std::string instanceName; std::string instanceName;
std::string typeName; std::string typeName;
std::string subTypeName; std::string subTypeName;
@ -62,21 +63,19 @@ public:
return this->tempOwner; return this->tempOwner;
} }
void setOwner(const PlayerColor & ow); void setOwner(const PlayerColor & ow);
void setAnchorPos(int3 pos);
/** APPEARANCE ACCESSORS **/ /** APPEARANCE ACCESSORS **/
int getWidth() const; //returns width of object graphic in tiles int getWidth() const; //returns width of object graphic in tiles
int getHeight() const; //returns height of object graphic in tiles int getHeight() const; //returns height of object graphic in tiles
int3 visitablePos() const override; int3 visitablePos() const override;
int3 getPosition() const override; int3 anchorPos() const override;
int3 getTopVisiblePos() const; int3 getTopVisiblePos() const;
bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) (h3m pos)
bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) (h3m pos)
bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) (h3m pos)
bool visitableAt(const int3 & pos) const; //returns true if object is visitable at location (x, y) (h3m pos) bool visitableAt(const int3 & pos) const; //returns true if object is visitable at location
bool blockingAt (const int3 & pos) const; //returns true if object is blocking location (x, y) (h3m pos) bool blockingAt (const int3 & pos) const; //returns true if object is blocking location
bool coveringAt (const int3 & pos) const; //returns true if object covers with picture location (x, y) (h3m pos) bool coveringAt (const int3 & pos) const; //returns true if object covers with picture location
std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object
const std::set<int3> & getBlockedOffsets() const; //returns set of relative positions blocked by this object const std::set<int3> & getBlockedOffsets() const; //returns set of relative positions blocked by this object

View File

@ -954,7 +954,7 @@ TResources CGTownInstance::getBuildingCost(const BuildingID & buildingID) const
return town->buildings.at(buildingID)->resources; return town->buildings.at(buildingID)->resources;
else else
{ {
logGlobal->error("Town %s at %s has no possible building %d!", getNameTranslated(), pos.toString(), buildingID.toEnum()); logGlobal->error("Town %s at %s has no possible building %d!", getNameTranslated(), anchorPos().toString(), buildingID.toEnum());
return TResources(); return TResources();
} }

View File

@ -56,8 +56,6 @@ class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public I
std::set<BuildingID> builtBuildings; std::set<BuildingID> builtBuildings;
public: public:
using CGDwelling::getPosition;
enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3}; enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3};
CTownAndVisitingHero townAndVis; CTownAndVisitingHero townAndVis;

View File

@ -614,7 +614,7 @@ void CGSeerHut::onHeroVisit(const CGHeroInstance * h) const
int CGSeerHut::checkDirection() const int CGSeerHut::checkDirection() const
{ {
int3 cord = getCreatureToKill(false)->pos; int3 cord = getCreatureToKill(false)->visitablePos();
if(static_cast<double>(cord.x) / static_cast<double>(cb->getMapSize().x) < 0.34) //north if(static_cast<double>(cord.x) / static_cast<double>(cb->getMapSize().x) < 0.34) //north
{ {
if(static_cast<double>(cord.y) / static_cast<double>(cb->getMapSize().y) < 0.34) //northwest if(static_cast<double>(cord.y) / static_cast<double>(cb->getMapSize().y) < 0.34) //northwest

View File

@ -145,7 +145,7 @@ void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visit
out.appendLocalString(EMetaText::ADVOB_TXT, 189); out.appendLocalString(EMetaText::ADVOB_TXT, 189);
break; break;
case NO_WATER: case NO_WATER:
logGlobal->error("Shipyard without water at tile %s! ", getObject()->getPosition().toString()); logGlobal->error("Shipyard without water at tile %s! ", getObject()->anchorPos().toString());
return; return;
} }
} }

View File

@ -47,7 +47,7 @@ public:
virtual PlayerColor getOwner() const = 0; virtual PlayerColor getOwner() const = 0;
virtual int3 visitablePos() const = 0; virtual int3 visitablePos() const = 0;
virtual int3 getPosition() const = 0; virtual int3 anchorPos() const = 0;
virtual void onHeroVisit(const CGHeroInstance * h) const; virtual void onHeroVisit(const CGHeroInstance * h) const;
virtual void onHeroLeave(const CGHeroInstance * h) const; virtual void onHeroLeave(const CGHeroInstance * h) const;

View File

@ -111,7 +111,7 @@ void CGMine::initObj(vstd::RNG & rand)
} }
else else
{ {
logGlobal->error("Abandoned mine at (%s) has no valid resource candidates!", pos.toString()); logGlobal->error("Abandoned mine at (%s) has no valid resource candidates!", anchorPos().toString());
producedResource = GameResID::GOLD; producedResource = GameResID::GOLD;
} }
} }
@ -510,11 +510,11 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
if(cb->isTeleportChannelImpassable(channel)) if(cb->isTeleportChannelImpassable(channel))
{ {
logGlobal->debug("Cannot find corresponding exit monolith for %d at %s", id.getNum(), pos.toString()); logGlobal->debug("Cannot find corresponding exit monolith for %d at %s", id.getNum(), anchorPos().toString());
td.impassable = true; td.impassable = true;
} }
else if(getRandomExit(h) == ObjectInstanceID()) else if(getRandomExit(h) == ObjectInstanceID())
logGlobal->debug("All exits blocked for monolith %d at %s", id.getNum(), pos.toString()); logGlobal->debug("All exits blocked for monolith %d at %s", id.getNum(), anchorPos().toString());
} }
else else
h->showInfoDialog(70); h->showInfoDialog(70);
@ -574,7 +574,7 @@ void CGSubterraneanGate::onHeroVisit( const CGHeroInstance * h ) const
if(cb->isTeleportChannelImpassable(channel)) if(cb->isTeleportChannelImpassable(channel))
{ {
h->showInfoDialog(153);//Just inside the entrance you find a large pile of rubble blocking the tunnel. You leave discouraged. h->showInfoDialog(153);//Just inside the entrance you find a large pile of rubble blocking the tunnel. You leave discouraged.
logGlobal->debug("Cannot find exit subterranean gate for %d at %s", id.getNum(), pos.toString()); logGlobal->debug("Cannot find exit subterranean gate for %d at %s", id.getNum(), anchorPos().toString());
td.impassable = true; td.impassable = true;
} }
else else
@ -602,13 +602,13 @@ void CGSubterraneanGate::postInit(IGameCallback * cb) //matches subterranean gat
auto * hlp = dynamic_cast<CGSubterraneanGate *>(cb->gameState()->getObjInstance(obj->id)); auto * hlp = dynamic_cast<CGSubterraneanGate *>(cb->gameState()->getObjInstance(obj->id));
if(hlp) if(hlp)
gatesSplit[hlp->pos.z].push_back(hlp); gatesSplit[hlp->visitablePos().z].push_back(hlp);
} }
//sort by position //sort by position
std::sort(gatesSplit[0].begin(), gatesSplit[0].end(), [](const CGObjectInstance * a, const CGObjectInstance * b) std::sort(gatesSplit[0].begin(), gatesSplit[0].end(), [](const CGObjectInstance * a, const CGObjectInstance * b)
{ {
return a->pos < b->pos; return a->visitablePos() < b->visitablePos();
}); });
auto assignToChannel = [&](CGSubterraneanGate * obj) auto assignToChannel = [&](CGSubterraneanGate * obj)
@ -631,7 +631,7 @@ void CGSubterraneanGate::postInit(IGameCallback * cb) //matches subterranean gat
CGSubterraneanGate *checked = gatesSplit[1][j]; CGSubterraneanGate *checked = gatesSplit[1][j];
if(checked->channel != TeleportChannelID()) if(checked->channel != TeleportChannelID())
continue; continue;
si32 hlp = checked->pos.dist2dSQ(objCurrent->pos); si32 hlp = checked->visitablePos().dist2dSQ(objCurrent->visitablePos());
if(hlp < best.second) if(hlp < best.second)
{ {
best.first = j; best.first = j;
@ -657,11 +657,11 @@ void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const
TeleportDialog td(h->id, channel); TeleportDialog td(h->id, channel);
if(cb->isTeleportChannelImpassable(channel)) if(cb->isTeleportChannelImpassable(channel))
{ {
logGlobal->debug("Cannot find exit whirlpool for %d at %s", id.getNum(), pos.toString()); logGlobal->debug("Cannot find exit whirlpool for %d at %s", id.getNum(), anchorPos().toString());
td.impassable = true; td.impassable = true;
} }
else if(getRandomExit(h) == ObjectInstanceID()) else if(getRandomExit(h) == ObjectInstanceID())
logGlobal->debug("All exits are blocked for whirlpool %d at %s", id.getNum(), pos.toString()); logGlobal->debug("All exits are blocked for whirlpool %d at %s", id.getNum(), anchorPos().toString());
if(!isProtected(h)) if(!isProtected(h))
{ {
@ -1086,9 +1086,9 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
for(const auto & eye : eyes) for(const auto & eye : eyes)
{ {
cb->getTilesInRange (fw.tiles, eye->pos, 10, ETileVisibility::HIDDEN, h->tempOwner); cb->getTilesInRange (fw.tiles, eye->visitablePos(), 10, ETileVisibility::HIDDEN, h->tempOwner);
cb->sendAndApply(fw); cb->sendAndApply(fw);
cv.pos = eye->pos; cv.pos = eye->visitablePos();
cb->sendAndApply(cv); cb->sendAndApply(cv);
} }

View File

@ -56,9 +56,9 @@ int3 TownBuildingInstance::visitablePos() const
return town->visitablePos(); return town->visitablePos();
} }
int3 TownBuildingInstance::getPosition() const int3 TownBuildingInstance::anchorPos() const
{ {
return town->getPosition(); return town->anchorPos();
} }
TownRewardableBuildingInstance::TownRewardableBuildingInstance(IGameCallback *cb) TownRewardableBuildingInstance::TownRewardableBuildingInstance(IGameCallback *cb)

View File

@ -38,7 +38,7 @@ public:
const IOwnableObject * asOwnable() const override; const IOwnableObject * asOwnable() const override;
int3 visitablePos() const override; int3 visitablePos() const override;
int3 getPosition() const override; int3 anchorPos() const override;
template <typename Handler> void serialize(Handler &h) template <typename Handler> void serialize(Handler &h)
{ {

View File

@ -232,22 +232,22 @@ CMap::~CMap()
void CMap::removeBlockVisTiles(CGObjectInstance * obj, bool total) void CMap::removeBlockVisTiles(CGObjectInstance * obj, bool total)
{ {
const int zVal = obj->pos.z; const int zVal = obj->anchorPos().z;
for(int fx = 0; fx < obj->getWidth(); ++fx) for(int fx = 0; fx < obj->getWidth(); ++fx)
{ {
int xVal = obj->pos.x - fx; int xVal = obj->anchorPos().x - fx;
for(int fy = 0; fy < obj->getHeight(); ++fy) for(int fy = 0; fy < obj->getHeight(); ++fy)
{ {
int yVal = obj->pos.y - fy; int yVal = obj->anchorPos().y - fy;
if(xVal>=0 && xVal < width && yVal>=0 && yVal < height) if(xVal>=0 && xVal < width && yVal>=0 && yVal < height)
{ {
TerrainTile & curt = terrain[zVal][xVal][yVal]; TerrainTile & curt = terrain[zVal][xVal][yVal];
if(total || obj->visitableAt(xVal, yVal)) if(total || obj->visitableAt(int3(xVal, yVal, zVal)))
{ {
curt.visitableObjects -= obj; curt.visitableObjects -= obj;
curt.visitable = curt.visitableObjects.size(); curt.visitable = curt.visitableObjects.size();
} }
if(total || obj->blockingAt(xVal, yVal)) if(total || obj->blockingAt(int3(xVal, yVal, zVal)))
{ {
curt.blockingObjects -= obj; curt.blockingObjects -= obj;
curt.blocked = curt.blockingObjects.size(); curt.blocked = curt.blockingObjects.size();
@ -259,22 +259,22 @@ void CMap::removeBlockVisTiles(CGObjectInstance * obj, bool total)
void CMap::addBlockVisTiles(CGObjectInstance * obj) void CMap::addBlockVisTiles(CGObjectInstance * obj)
{ {
const int zVal = obj->pos.z; const int zVal = obj->anchorPos().z;
for(int fx = 0; fx < obj->getWidth(); ++fx) for(int fx = 0; fx < obj->getWidth(); ++fx)
{ {
int xVal = obj->pos.x - fx; int xVal = obj->anchorPos().x - fx;
for(int fy = 0; fy < obj->getHeight(); ++fy) for(int fy = 0; fy < obj->getHeight(); ++fy)
{ {
int yVal = obj->pos.y - fy; int yVal = obj->anchorPos().y - fy;
if(xVal>=0 && xVal < width && yVal >= 0 && yVal < height) if(xVal>=0 && xVal < width && yVal >= 0 && yVal < height)
{ {
TerrainTile & curt = terrain[zVal][xVal][yVal]; TerrainTile & curt = terrain[zVal][xVal][yVal];
if(obj->visitableAt(xVal, yVal)) if(obj->visitableAt(int3(xVal, yVal, zVal)))
{ {
curt.visitableObjects.push_back(obj); curt.visitableObjects.push_back(obj);
curt.visitable = true; curt.visitable = true;
} }
if(obj->blockingAt(xVal, yVal)) if(obj->blockingAt(int3(xVal, yVal, zVal)))
{ {
curt.blockingObjects.push_back(obj); curt.blockingObjects.push_back(obj);
curt.blocked = true; curt.blocked = true;
@ -444,14 +444,14 @@ const CGObjectInstance * CMap::getObjectiveObjectFrom(const int3 & pos, Obj type
bestMatch = object; bestMatch = object;
else else
{ {
if (object->pos.dist2dSQ(pos) < bestMatch->pos.dist2dSQ(pos)) if (object->anchorPos().dist2dSQ(pos) < bestMatch->anchorPos().dist2dSQ(pos))
bestMatch = object;// closer than one we already found bestMatch = object;// closer than one we already found
} }
} }
} }
assert(bestMatch != nullptr); // if this happens - victory conditions or map itself is very, very broken assert(bestMatch != nullptr); // if this happens - victory conditions or map itself is very, very broken
logGlobal->error("Will use %s from %s", bestMatch->getObjectName(), bestMatch->pos.toString()); logGlobal->error("Will use %s from %s", bestMatch->getObjectName(), bestMatch->anchorPos().toString());
return bestMatch; return bestMatch;
} }
@ -635,7 +635,7 @@ void CMap::addNewObject(CGObjectInstance * obj)
void CMap::moveObject(CGObjectInstance * obj, const int3 & pos) void CMap::moveObject(CGObjectInstance * obj, const int3 & pos)
{ {
removeBlockVisTiles(obj); removeBlockVisTiles(obj);
obj->pos = pos; obj->setAnchorPos(pos);
addBlockVisTiles(obj); addBlockVisTiles(obj);
} }
@ -803,7 +803,7 @@ void CMap::reindexObjects()
if (lhs->isRemovable() && !rhs->isRemovable()) if (lhs->isRemovable() && !rhs->isRemovable())
return false; return false;
return lhs->pos.y < rhs->pos.y; return lhs->anchorPos().y < rhs->anchorPos().y;
}); });
// instanceNames don't change // instanceNames don't change

View File

@ -615,7 +615,7 @@ std::string CInsertObjectOperation::getLabel() const
CMoveObjectOperation::CMoveObjectOperation(CMap* map, CGObjectInstance* obj, const int3& targetPosition) CMoveObjectOperation::CMoveObjectOperation(CMap* map, CGObjectInstance* obj, const int3& targetPosition)
: CMapOperation(map), : CMapOperation(map),
obj(obj), obj(obj),
initialPos(obj->pos), initialPos(obj->anchorPos()),
targetPos(targetPosition) targetPos(targetPosition)
{ {
} }

View File

@ -913,7 +913,7 @@ void CMapLoaderH3M::loadArtifactsOfHero(CGHeroInstance * hero)
if(!hero->artifactsWorn.empty() || !hero->artifactsInBackpack.empty()) if(!hero->artifactsWorn.empty() || !hero->artifactsInBackpack.empty())
{ {
logGlobal->debug("Hero %d at %s has set artifacts twice (in map properties and on adventure map instance). Using the latter set...", hero->getHeroType().getNum(), hero->pos.toString()); logGlobal->debug("Hero %d at %s has set artifacts twice (in map properties and on adventure map instance). Using the latter set...", hero->getHeroType().getNum(), hero->anchorPos().toString());
hero->artifactsInBackpack.clear(); hero->artifactsInBackpack.clear();
while(!hero->artifactsWorn.empty()) while(!hero->artifactsWorn.empty())
@ -1651,7 +1651,7 @@ void CMapLoaderH3M::readObjects()
if(!newObject) if(!newObject)
continue; continue;
newObject->pos = mapPosition; newObject->setAnchorPos(mapPosition);
newObject->ID = objectTemplate->id; newObject->ID = objectTemplate->id;
newObject->id = objectInstanceID; newObject->id = objectInstanceID;
if(newObject->ID != Obj::HERO && newObject->ID != Obj::HERO_PLACEHOLDER && newObject->ID != Obj::PRISON) if(newObject->ID != Obj::HERO && newObject->ID != Obj::HERO_PLACEHOLDER && newObject->ID != Obj::PRISON)

View File

@ -1072,7 +1072,7 @@ void CMapLoaderJson::MapObjectLoader::construct()
instance->id = ObjectInstanceID(static_cast<si32>(owner->map->objects.size())); instance->id = ObjectInstanceID(static_cast<si32>(owner->map->objects.size()));
instance->instanceName = jsonKey; instance->instanceName = jsonKey;
instance->pos = pos; instance->setAnchorPos(pos);
owner->map->addNewObject(instance); owner->map->addNewObject(instance);
} }

View File

@ -1047,7 +1047,7 @@ void ChangeObjPos::applyGs(CGameState *gs)
return; return;
} }
gs->map->removeBlockVisTiles(obj); gs->map->removeBlockVisTiles(obj);
obj->pos = nPos + obj->getVisitableOffset(); obj->setAnchorPos(nPos + obj->getVisitableOffset());
gs->map->addBlockVisTiles(obj); gs->map->addBlockVisTiles(obj);
} }
@ -1467,7 +1467,7 @@ void GiveHero::applyGs(CGameState *gs)
h->setOwner(player); h->setOwner(player);
h->setMovementPoints(h->movementPointsLimit(true)); h->setMovementPoints(h->movementPointsLimit(true));
h->pos = h->convertFromVisitablePos(oldVisitablePos); h->setAnchorPos(h->convertFromVisitablePos(oldVisitablePos));
gs->map->heroesOnMap.emplace_back(h); gs->map->heroesOnMap.emplace_back(h);
gs->getPlayerState(h->getOwner())->addOwnedObject(h); gs->getPlayerState(h->getOwner())->addOwnedObject(h);

View File

@ -87,7 +87,7 @@ const rmg::Area & Object::Instance::getAccessibleArea() const
void Object::Instance::setPosition(const int3 & position) void Object::Instance::setPosition(const int3 & position)
{ {
dPosition = position; dPosition = position;
dObject.pos = dPosition + dParent.getPosition(); dObject.setAnchorPos(dPosition + dParent.getPosition());
dBlockedAreaCache.clear(); dBlockedAreaCache.clear();
dAccessibleAreaCache.clear(); dAccessibleAreaCache.clear();
@ -96,21 +96,21 @@ void Object::Instance::setPosition(const int3 & position)
void Object::Instance::setPositionRaw(const int3 & position) void Object::Instance::setPositionRaw(const int3 & position)
{ {
if(!dObject.pos.valid()) if(!dObject.anchorPos().valid())
{ {
dObject.pos = dPosition + dParent.getPosition(); dObject.setAnchorPos(dPosition + dParent.getPosition());
dBlockedAreaCache.clear(); dBlockedAreaCache.clear();
dAccessibleAreaCache.clear(); dAccessibleAreaCache.clear();
dParent.clearCachedArea(); dParent.clearCachedArea();
} }
auto shift = position + dParent.getPosition() - dObject.pos; auto shift = position + dParent.getPosition() - dObject.anchorPos();
dAccessibleAreaCache.translate(shift); dAccessibleAreaCache.translate(shift);
dBlockedAreaCache.translate(shift); dBlockedAreaCache.translate(shift);
dPosition = position; dPosition = position;
dObject.pos = dPosition + dParent.getPosition(); dObject.setAnchorPos(dPosition + dParent.getPosition());
} }
void Object::Instance::setAnyTemplate(vstd::RNG & rng) void Object::Instance::setAnyTemplate(vstd::RNG & rng)
@ -497,12 +497,12 @@ void Object::Instance::finalize(RmgMap & map, vstd::RNG & rng)
} }
if (dObject.isVisitable() && !map.isOnMap(dObject.visitablePos())) if (dObject.isVisitable() && !map.isOnMap(dObject.visitablePos()))
throw rmgException(boost::str(boost::format("Visitable tile %s of object %d at %s is outside the map") % dObject.visitablePos().toString() % dObject.id % dObject.pos.toString())); throw rmgException(boost::str(boost::format("Visitable tile %s of object %d at %s is outside the map") % dObject.visitablePos().toString() % dObject.id % dObject.anchorPos().toString()));
for(const auto & tile : dObject.getBlockedPos()) for(const auto & tile : dObject.getBlockedPos())
{ {
if(!map.isOnMap(tile)) if(!map.isOnMap(tile))
throw rmgException(boost::str(boost::format("Tile %s of object %d at %s is outside the map") % tile.toString() % dObject.id % dObject.pos.toString())); throw rmgException(boost::str(boost::format("Tile %s of object %d at %s is outside the map") % tile.toString() % dObject.id % dObject.anchorPos().toString()));
} }
for(const auto & tile : getBlockedArea().getTilesVector()) for(const auto & tile : getBlockedArea().getTilesVector())

View File

@ -112,7 +112,7 @@ void QuestArtifactPlacer::placeQuestArtifacts(vstd::RNG & rand)
logGlobal->trace("Replacing %s at %s with the quest artifact %s", logGlobal->trace("Replacing %s at %s with the quest artifact %s",
objectToReplace->getObjectName(), objectToReplace->getObjectName(),
objectToReplace->getPosition().toString(), objectToReplace->anchorPos().toString(),
VLC->artifacts()->getById(artifactToPlace)->getNameTranslated()); VLC->artifacts()->getById(artifactToPlace)->getNameTranslated());
//Update appearance. Terrain is irrelevant. //Update appearance. Terrain is irrelevant.
@ -121,7 +121,7 @@ void QuestArtifactPlacer::placeQuestArtifacts(vstd::RNG & rand)
auto templates = handler->getTemplates(); auto templates = handler->getTemplates();
//artifactToReplace->appearance = templates.front(); //artifactToReplace->appearance = templates.front();
newObj->appearance = templates.front(); newObj->appearance = templates.front();
newObj->pos = objectToReplace->pos; newObj->setAnchorPos(objectToReplace->anchorPos());
mapProxy->insertObject(newObj); mapProxy->insertObject(newObj);
mapProxy->removeObject(objectToReplace); mapProxy->removeObject(objectToReplace);
break; break;

View File

@ -209,7 +209,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
if(b->hero || b->layer != EPathfindingLayer::SAIL) if(b->hero || b->layer != EPathfindingLayer::SAIL)
continue; //we're looking for unoccupied boat continue; //we're looking for unoccupied boat
double nDist = b->pos.dist2d(parameters.caster->getHeroCaster()->visitablePos()); double nDist = b->visitablePos().dist2d(parameters.caster->getHeroCaster()->visitablePos());
if(!nearest || nDist < dist) //it's first boat or closer than previous if(!nearest || nDist < dist) //it's first boat or closer than previous
{ {
nearest = b; nearest = b;
@ -669,11 +669,11 @@ const CGTownInstance * TownPortalMechanics::findNearestTown(SpellCastEnvironment
return nullptr; return nullptr;
auto nearest = pool.cbegin(); //nearest town's iterator auto nearest = pool.cbegin(); //nearest town's iterator
si32 dist = (*nearest)->pos.dist2dSQ(parameters.caster->getHeroCaster()->pos); si32 dist = (*nearest)->visitablePos().dist2dSQ(parameters.caster->getHeroCaster()->visitablePos());
for(auto i = nearest + 1; i != pool.cend(); ++i) for(auto i = nearest + 1; i != pool.cend(); ++i)
{ {
si32 curDist = (*i)->pos.dist2dSQ(parameters.caster->getHeroCaster()->pos); si32 curDist = (*i)->visitablePos().dist2dSQ(parameters.caster->getHeroCaster()->visitablePos());
if(curDist < dist) if(curDist < dist)
{ {

View File

@ -379,7 +379,7 @@ void MapHandler::drawObjects(QPainter & painter, int x, int y, int z, const std:
if(objData.objBitmap) if(objData.objBitmap)
{ {
auto pos = obj->getPosition(); auto pos = obj->anchorPos();
painter.drawImage(QPoint(x * tileSize, y * tileSize), *objData.objBitmap, object.rect, Qt::AutoColor | Qt::NoOpaqueDetection); painter.drawImage(QPoint(x * tileSize, y * tileSize), *objData.objBitmap, object.rect, Qt::AutoColor | Qt::NoOpaqueDetection);

View File

@ -115,7 +115,7 @@ std::string AbstractSettings::getMonsterName(const CMap & map, int objectIdx)
std::string name; std::string name;
if(auto monster = dynamic_cast<const CGCreature*>(map.objects[objectIdx].get())) if(auto monster = dynamic_cast<const CGCreature*>(map.objects[objectIdx].get()))
{ {
name = boost::str(boost::format("%1% at %2%") % monster->getObjectName() % monster->getPosition().toString()); name = boost::str(boost::format("%1% at %2%") % monster->getObjectName() % monster->anchorPos().toString());
} }
return name; return name;
} }

View File

@ -425,7 +425,7 @@ void ObjectsLayer::setDirty(const CGObjectInstance * object)
{ {
for(int i = 0; i < object->getWidth(); ++i) for(int i = 0; i < object->getWidth(); ++i)
{ {
setDirty(object->getPosition().x - i, object->getPosition().y - j); setDirty(object->anchorPos().x - i, object->anchorPos().y - j);
} }
} }
} }
@ -479,7 +479,7 @@ void SelectionObjectsLayer::draw()
{ {
if(obj != newObject) if(obj != newObject)
{ {
QRect bbox(obj->getPosition().x, obj->getPosition().y, 1, 1); QRect bbox(obj->anchorPos().x, obj->anchorPos().y, 1, 1);
for(auto & t : obj->getBlockedPos()) for(auto & t : obj->getBlockedPos())
{ {
QPoint topLeft(std::min(t.x, bbox.topLeft().x()), std::min(t.y, bbox.topLeft().y())); QPoint topLeft(std::min(t.x, bbox.topLeft().x()), std::min(t.y, bbox.topLeft().y()));
@ -496,7 +496,7 @@ void SelectionObjectsLayer::draw()
if(selectionMode == SelectionMode::MOVEMENT && (shift.x() || shift.y())) if(selectionMode == SelectionMode::MOVEMENT && (shift.x() || shift.y()))
{ {
painter.setOpacity(0.7); painter.setOpacity(0.7);
auto newPos = QPoint(obj->getPosition().x, obj->getPosition().y) + shift; auto newPos = QPoint(obj->anchorPos().x, obj->anchorPos().y) + shift;
handler->drawObjectAt(painter, obj, newPos.x(), newPos.y()); handler->drawObjectAt(painter, obj, newPos.x(), newPos.y());
} }
} }
@ -517,7 +517,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGO
if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj)) if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj))
continue; continue;
if(object.obj->visitableAt(x, y)) if(object.obj->visitableAt(int3(x, y, scene->level)))
{ {
return const_cast<CGObjectInstance*>(object.obj); return const_cast<CGObjectInstance*>(object.obj);
} }
@ -529,7 +529,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGO
if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj)) if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj))
continue; continue;
if(object.obj->blockingAt(x, y)) if(object.obj->blockingAt(int3(x, y, scene->level)))
{ {
return const_cast<CGObjectInstance*>(object.obj); return const_cast<CGObjectInstance*>(object.obj);
} }
@ -541,7 +541,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGO
if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj)) if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj))
continue; continue;
if(object.obj->coveringAt(x, y)) if(object.obj->coveringAt(int3(x, y, scene->level)))
{ {
return const_cast<CGObjectInstance*>(object.obj); return const_cast<CGObjectInstance*>(object.obj);
} }

View File

@ -804,7 +804,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
return false; return false;
} }
logGlobal->trace("Player %d (%s) wants to move hero %d from %s to %s", asker, asker.toString(), hid.getNum(), h->pos.toString(), dst.toString()); logGlobal->trace("Player %d (%s) wants to move hero %d from %s to %s", asker, asker.toString(), hid.getNum(), h->anchorPos().toString(), dst.toString());
const int3 hmpos = h->convertToVisitablePos(dst); const int3 hmpos = h->convertToVisitablePos(dst);
if (!gs->map->isInTheMap(hmpos)) if (!gs->map->isInTheMap(hmpos))
@ -903,7 +903,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
// should be called if hero changes tile but before applying TryMoveHero package // should be called if hero changes tile but before applying TryMoveHero package
auto leaveTile = [&]() auto leaveTile = [&]()
{ {
for (CGObjectInstance *obj : gs->map->getTile(int3(h->pos.x-1, h->pos.y, h->pos.z)).visitableObjects) for (CGObjectInstance *obj : gs->map->getTile(h->visitablePos()).visitableObjects)
{ {
obj->onHeroLeave(h); obj->onHeroLeave(h);
} }
@ -4223,8 +4223,11 @@ CGObjectInstance * CGameHandler::createNewObject(const int3 & visitablePosition,
else else
o->appearance = handler->getTemplates().front(); o->appearance = handler->getTemplates().front();
if (o->isVisitable())
o->setAnchorPos(visitablePosition + o->getVisitableOffset());
else
o->setAnchorPos(visitablePosition);
o->pos = visitablePosition + o->getVisitableOffset();
return o; return o;
} }

View File

@ -283,7 +283,7 @@ void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack)
gh.throwAndComplain(&pack, "Can not trade - no hero!"); gh.throwAndComplain(&pack, "Can not trade - no hero!");
// TODO: check that object is actually being visited (e.g. Query exists) // TODO: check that object is actually being visited (e.g. Query exists)
if (!object->visitableAt(hero->visitablePos().x, hero->visitablePos().y)) if (!object->visitableAt(hero->visitablePos()))
gh.throwAndComplain(&pack, "Can not trade - object not visited!"); gh.throwAndComplain(&pack, "Can not trade - object not visited!");
if (object->getOwner().isValidPlayer() && gh.getPlayerRelations(object->getOwner(), hero->getOwner()) == PlayerRelations::ENEMIES) if (object->getOwner().isValidPlayer() && gh.getPlayerRelations(object->getOwner(), hero->getOwner()) == PlayerRelations::ENEMIES)