mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-15 00:05:02 +02:00
Remove pointer to objects from TerrainTile
This commit is contained in:
@ -1332,8 +1332,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
|
|||||||
{
|
{
|
||||||
auto tile = cb->getTile(coord, false);
|
auto tile = cb->getTile(coord, false);
|
||||||
assert(tile);
|
assert(tile);
|
||||||
return tile->topVisitableObj(ignoreHero);
|
return cb->getObj(tile->topVisitableObj(ignoreHero));
|
||||||
//return cb->getTile(coord,false)->topVisitableObj(ignoreHero);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto isTeleportAction = [&](EPathNodeAction action) -> bool
|
auto isTeleportAction = [&](EPathNodeAction action) -> bool
|
||||||
|
@ -202,7 +202,7 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
|
|||||||
}
|
}
|
||||||
else if(!fromWater) // do not try to board when in water sector
|
else if(!fromWater) // do not try to board when in water sector
|
||||||
{
|
{
|
||||||
if(t->visitableObjects.size() == 1 && t->topVisitableId() == Obj::BOAT)
|
if(t->visitableObjects.size() == 1 && cb->getObjInstance(t->topVisitableObj())->ID == Obj::BOAT)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -192,7 +192,7 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
|
|||||||
}
|
}
|
||||||
else if(!fromWater) // do not try to board when in water sector
|
else if(!fromWater) // do not try to board when in water sector
|
||||||
{
|
{
|
||||||
if(t->visitableObjects.size() == 1 && t->topVisitableId() == Obj::BOAT)
|
if(t->visitableObjects.size() == 1 && cb->getObjInstance(t->topVisitableObj())->ID == Obj::BOAT)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -200,9 +200,11 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
|
|||||||
|
|
||||||
bool isBlockedBorderGate(int3 tileToHit) //TODO: is that function needed? should be handled by pathfinder
|
bool isBlockedBorderGate(int3 tileToHit) //TODO: is that function needed? should be handled by pathfinder
|
||||||
{
|
{
|
||||||
if(cb->getTile(tileToHit)->topVisitableId() != Obj::BORDER_GATE)
|
const auto * object = cb->getTopObj(tileToHit);
|
||||||
|
if( object && object->id != Obj::BORDER_GATE)
|
||||||
return false;
|
return false;
|
||||||
auto gate = dynamic_cast<const CGKeys *>(cb->getTile(tileToHit)->topVisitableObj());
|
|
||||||
|
auto gate = dynamic_cast<const CGKeys *>(object);
|
||||||
return !gate->passableFor(ai->playerID);
|
return !gate->passableFor(ai->playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ Goals::TSubgoal PathfindingManager::clearWayTo(HeroPtr hero, int3 firstTileToGet
|
|||||||
if(isBlockedBorderGate(firstTileToGet))
|
if(isBlockedBorderGate(firstTileToGet))
|
||||||
{
|
{
|
||||||
//FIXME: this way we'll not visit gate and activate quest :?
|
//FIXME: this way we'll not visit gate and activate quest :?
|
||||||
return sptr(Goals::FindObj(Obj::KEYMASTER, cb->getTile(firstTileToGet)->visitableObjects.back()->getObjTypeIndex()));
|
return sptr(Goals::FindObj(Obj::KEYMASTER, cb->getTopObj(firstTileToGet)->getObjTypeIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto topObj = cb->getTopObj(firstTileToGet);
|
auto topObj = cb->getTopObj(firstTileToGet);
|
||||||
|
@ -1868,10 +1868,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
|||||||
|
|
||||||
auto getObj = [&](int3 coord, bool ignoreHero)
|
auto getObj = [&](int3 coord, bool ignoreHero)
|
||||||
{
|
{
|
||||||
auto tile = cb->getTile(coord, false);
|
return cb->getObj(cb->getTile(coord)->topVisitableObj(ignoreHero));
|
||||||
assert(tile);
|
|
||||||
return tile->topVisitableObj(ignoreHero);
|
|
||||||
//return cb->getTile(coord,false)->topVisitableObj(ignoreHero);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto isTeleportAction = [&](EPathNodeAction action) -> bool
|
auto isTeleportAction = [&](EPathNodeAction action) -> bool
|
||||||
|
@ -595,7 +595,7 @@ void ApplyClientNetPackVisitor::visitSetAvailableCreatures(SetAvailableCreatures
|
|||||||
|
|
||||||
PlayerColor p;
|
PlayerColor p;
|
||||||
if(dw->ID == Obj::WAR_MACHINE_FACTORY) //War Machines Factory is not flaggable, it's "owned" by visitor
|
if(dw->ID == Obj::WAR_MACHINE_FACTORY) //War Machines Factory is not flaggable, it's "owned" by visitor
|
||||||
p = cl.getTile(dw->visitablePos())->visitableObjects.back()->tempOwner;
|
p = cl.getObjInstance(cl.getTile(dw->visitablePos())->visitableObjects.back())->getOwner();
|
||||||
else
|
else
|
||||||
p = dw->tempOwner;
|
p = dw->tempOwner;
|
||||||
|
|
||||||
@ -1016,7 +1016,9 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
|||||||
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
|
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
|
||||||
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
|
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
|
||||||
const auto market = cl.getMarket(pack.object);
|
const auto market = cl.getMarket(pack.object);
|
||||||
callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, hero, pack.queryID);
|
const auto * tile = cl.getTile(obj->visitablePos());
|
||||||
|
const auto * topObject = cl.getObjInstance(tile->visitableObjects.back());
|
||||||
|
callInterfaceIfPresent(cl, topObject->getOwner(), &IGameEventsReceiver::showMarketWindow, market, hero, pack.queryID);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EOpenWindowMode::HILL_FORT_WINDOW:
|
case EOpenWindowMode::HILL_FORT_WINDOW:
|
||||||
@ -1025,7 +1027,9 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
|||||||
//displays Hill fort window
|
//displays Hill fort window
|
||||||
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
|
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
|
||||||
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
|
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
|
||||||
callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showHillFortWindow, obj, hero);
|
const auto * tile = cl.getTile(obj->visitablePos());
|
||||||
|
const auto * topObject = cl.getObjInstance(tile->visitableObjects.back());
|
||||||
|
callInterfaceIfPresent(cl, topObject->getOwner(), &IGameEventsReceiver::showHillFortWindow, obj, hero);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EOpenWindowMode::PUZZLE_MAP:
|
case EOpenWindowMode::PUZZLE_MAP:
|
||||||
@ -1076,7 +1080,10 @@ void ApplyClientNetPackVisitor::visitSetAvailableArtifacts(SetAvailableArtifacts
|
|||||||
{
|
{
|
||||||
const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(cl.getObj(ObjectInstanceID(pack.id)));
|
const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(cl.getObj(ObjectInstanceID(pack.id)));
|
||||||
assert(bm);
|
assert(bm);
|
||||||
callInterfaceIfPresent(cl, cl.getTile(bm->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::availableArtifactsChanged, bm);
|
const auto * tile = cl.getTile(bm->visitablePos());
|
||||||
|
const auto * topObject = cl.getObjInstance(tile->visitableObjects.back());
|
||||||
|
|
||||||
|
callInterfaceIfPresent(cl, topObject->getOwner(), &IGameEventsReceiver::availableArtifactsChanged, bm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,9 @@ ColorRGBA CMinimapInstance::getTileColor(const int3 & pos) const
|
|||||||
return Colors::BLACK;
|
return Colors::BLACK;
|
||||||
|
|
||||||
// if object at tile is owned - it will be colored as its owner
|
// if object at tile is owned - it will be colored as its owner
|
||||||
for (const CGObjectInstance *obj : tile->blockingObjects)
|
for (const ObjectInstanceID objectID : tile->blockingObjects)
|
||||||
{
|
{
|
||||||
|
const auto * obj = GAME->interface()->cb->getObj(objectID);
|
||||||
PlayerColor player = obj->getOwner();
|
PlayerColor player = obj->getOwner();
|
||||||
if(player == PlayerColor::NEUTRAL)
|
if(player == PlayerColor::NEUTRAL)
|
||||||
return graphics->neutralColor;
|
return graphics->neutralColor;
|
||||||
|
@ -278,10 +278,12 @@ std::string MapRendererAdventureContext::overlayText(const int3 & coordinates) c
|
|||||||
if (!tile.visitable())
|
if (!tile.visitable())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if ( tile.visitableObjects.back()->ID == Obj::EVENT)
|
const auto * object = getObject(tile.visitableObjects.back());
|
||||||
|
|
||||||
|
if ( object->ID == Obj::EVENT)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return tile.visitableObjects.back()->getObjectName();
|
return object->getObjectName();
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorRGBA MapRendererAdventureContext::overlayTextColor(const int3 & coordinates) const
|
ColorRGBA MapRendererAdventureContext::overlayTextColor(const int3 & coordinates) const
|
||||||
@ -294,7 +296,7 @@ ColorRGBA MapRendererAdventureContext::overlayTextColor(const int3 & coordinates
|
|||||||
if (!tile.visitable())
|
if (!tile.visitable())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const auto * object = tile.visitableObjects.back();
|
const auto * object = getObject(tile.visitableObjects.back());
|
||||||
|
|
||||||
if (object->getOwner() == GAME->interface()->playerID)
|
if (object->getOwner() == GAME->interface()->playerID)
|
||||||
return { 0, 192, 0};
|
return { 0, 192, 0};
|
||||||
|
@ -74,9 +74,10 @@ std::shared_ptr<CanvasImage> CMapOverviewWidget::createMinimapForLayer(std::uniq
|
|||||||
|
|
||||||
if(drawPlayerElements)
|
if(drawPlayerElements)
|
||||||
// if object at tile is owned - it will be colored as its owner
|
// if object at tile is owned - it will be colored as its owner
|
||||||
for (const CGObjectInstance *obj : tile.blockingObjects)
|
for (ObjectInstanceID objectID : tile.blockingObjects)
|
||||||
{
|
{
|
||||||
PlayerColor player = obj->getOwner();
|
const auto * object = map->getObject(objectID);
|
||||||
|
PlayerColor player = object->getOwner();
|
||||||
if(player == PlayerColor::NEUTRAL)
|
if(player == PlayerColor::NEUTRAL)
|
||||||
{
|
{
|
||||||
color = graphics->neutralColor;
|
color = graphics->neutralColor;
|
||||||
|
@ -866,7 +866,7 @@ TerrainId CStackInstance::getNativeTerrain() const
|
|||||||
|
|
||||||
TerrainId CStackInstance::getCurrentTerrain() const
|
TerrainId CStackInstance::getCurrentTerrain() const
|
||||||
{
|
{
|
||||||
return armyObj->getCurrentTerrain();
|
return getArmy()->getCurrentTerrain();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStackInstance::deserializationFix()
|
void CStackInstance::deserializationFix()
|
||||||
|
@ -453,8 +453,8 @@ std::vector <const CGObjectInstance *> CGameInfoCallback::getBlockingObjs( int3
|
|||||||
const TerrainTile *t = getTile(pos);
|
const TerrainTile *t = getTile(pos);
|
||||||
ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
|
ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
|
||||||
|
|
||||||
for(const CGObjectInstance * obj : t->blockingObjects)
|
for(const auto & objID : t->blockingObjects)
|
||||||
ret.push_back(obj);
|
ret.push_back(getObj(objID));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,10 +464,12 @@ std::vector <const CGObjectInstance *> CGameInfoCallback::getVisitableObjs(int3
|
|||||||
const TerrainTile *t = getTile(pos, verbose);
|
const TerrainTile *t = getTile(pos, verbose);
|
||||||
ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!t, verbose, pos.toString() + " is not visible!", ret);
|
ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!t, verbose, pos.toString() + " is not visible!", ret);
|
||||||
|
|
||||||
for(const CGObjectInstance * obj : t->visitableObjects)
|
for(const auto & objID : t->visitableObjects)
|
||||||
{
|
{
|
||||||
if(!getPlayerID().has_value() || obj->ID != Obj::EVENT) //hide events from players
|
const auto & object = getObj(objID);
|
||||||
ret.push_back(obj);
|
|
||||||
|
if(!getPlayerID().has_value() || object->ID != Obj::EVENT) //hide events from players
|
||||||
|
ret.push_back(object);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -492,9 +494,12 @@ std::vector <const CGObjectInstance *> CGameInfoCallback::getFlaggableObjects(in
|
|||||||
std::vector<const CGObjectInstance *> ret;
|
std::vector<const CGObjectInstance *> ret;
|
||||||
const TerrainTile *t = getTile(pos);
|
const TerrainTile *t = getTile(pos);
|
||||||
ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
|
ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
|
||||||
for(const CGObjectInstance *obj : t->blockingObjects)
|
for(const auto & objectID : t->blockingObjects)
|
||||||
|
{
|
||||||
|
const auto * obj = getObj(objectID);
|
||||||
if(obj->tempOwner != PlayerColor::UNFLAGGABLE)
|
if(obj->tempOwner != PlayerColor::UNFLAGGABLE)
|
||||||
ret.push_back(obj);
|
ret.push_back(obj);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,7 +729,8 @@ bool CGameInfoCallback::isOwnedOrVisited(const CGObjectInstance *obj) const
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
const TerrainTile *t = getTile(obj->visitablePos()); //get entrance tile
|
const TerrainTile *t = getTile(obj->visitablePos()); //get entrance tile
|
||||||
const CGObjectInstance *visitor = t->visitableObjects.back(); //visitong hero if present or the object itself at last
|
const ObjectInstanceID visitorID = t->visitableObjects.back(); //visitong hero if present or the object itself at last
|
||||||
|
const CGObjectInstance * visitor = getObj(visitorID);
|
||||||
return visitor->ID == Obj::HERO && canGetFullInfo(visitor); //owned or allied hero is a visitor
|
return visitor->ID == Obj::HERO && canGetFullInfo(visitor); //owned or allied hero is a visitor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1030,7 +1030,8 @@ BattleField CGameState::battleGetBattlefieldType(int3 tile, vstd::RNG & rand)
|
|||||||
|
|
||||||
const TerrainTile &t = map->getTile(tile);
|
const TerrainTile &t = map->getTile(tile);
|
||||||
|
|
||||||
auto * topObject = t.visitableObjects.front();
|
ObjectInstanceID topObjectID = t.visitableObjects.front();
|
||||||
|
const CGObjectInstance * topObject = gs->getObjInstance(topObjectID);
|
||||||
if(topObject && topObject->getBattlefield() != BattleField::NONE)
|
if(topObject && topObject->getBattlefield() != BattleField::NONE)
|
||||||
{
|
{
|
||||||
return topObject->getBattlefield();
|
return topObject->getBattlefield();
|
||||||
@ -1129,9 +1130,9 @@ void CGameState::calculatePaths(const std::shared_ptr<PathfinderConfig> & config
|
|||||||
* @return int3(-1, -1, -1) if the tile is unguarded, or the position of
|
* @return int3(-1, -1, -1) if the tile is unguarded, or the position of
|
||||||
* the monster guarding the tile.
|
* the monster guarding the tile.
|
||||||
*/
|
*/
|
||||||
std::vector<CGObjectInstance*> CGameState::guardingCreatures (int3 pos) const
|
std::vector<const CGObjectInstance*> CGameState::guardingCreatures (int3 pos) const
|
||||||
{
|
{
|
||||||
std::vector<CGObjectInstance*> guards;
|
std::vector<const CGObjectInstance*> guards;
|
||||||
const int3 originalPos = pos;
|
const int3 originalPos = pos;
|
||||||
if (!map->isInTheMap(pos))
|
if (!map->isInTheMap(pos))
|
||||||
return guards;
|
return guards;
|
||||||
@ -1139,12 +1140,13 @@ std::vector<CGObjectInstance*> CGameState::guardingCreatures (int3 pos) const
|
|||||||
const TerrainTile &posTile = map->getTile(pos);
|
const TerrainTile &posTile = map->getTile(pos);
|
||||||
if (posTile.visitable())
|
if (posTile.visitable())
|
||||||
{
|
{
|
||||||
for (CGObjectInstance* obj : posTile.visitableObjects)
|
for (ObjectInstanceID objectID : posTile.visitableObjects)
|
||||||
{
|
{
|
||||||
if(obj->isBlockedVisitable())
|
const CGObjectInstance * object = getObjInstance(objectID);
|
||||||
|
if(object->isBlockedVisitable())
|
||||||
{
|
{
|
||||||
if (obj->ID == Obj::MONSTER) // Monster
|
if (object->ID == Obj::MONSTER) // Monster
|
||||||
guards.push_back(obj);
|
guards.push_back(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1158,11 +1160,13 @@ std::vector<CGObjectInstance*> CGameState::guardingCreatures (int3 pos) const
|
|||||||
const auto & tile = map->getTile(pos);
|
const auto & tile = map->getTile(pos);
|
||||||
if (tile.visitable() && (tile.isWater() == posTile.isWater()))
|
if (tile.visitable() && (tile.isWater() == posTile.isWater()))
|
||||||
{
|
{
|
||||||
for (CGObjectInstance* obj : tile.visitableObjects)
|
for (ObjectInstanceID objectID : tile.visitableObjects)
|
||||||
{
|
{
|
||||||
if (obj->ID == Obj::MONSTER && map->checkForVisitableDir(pos, &map->getTile(originalPos), originalPos)) // Monster being able to attack investigated tile
|
const CGObjectInstance * object = getObjInstance(objectID);
|
||||||
|
|
||||||
|
if (object->ID == Obj::MONSTER && map->checkForVisitableDir(pos, &map->getTile(originalPos), originalPos)) // Monster being able to attack investigated tile
|
||||||
{
|
{
|
||||||
guards.push_back(obj);
|
guards.push_back(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ public:
|
|||||||
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile
|
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile
|
||||||
void calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const override;
|
void calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const override;
|
||||||
int3 guardingCreaturePosition (int3 pos) const override;
|
int3 guardingCreaturePosition (int3 pos) const override;
|
||||||
std::vector<CGObjectInstance*> guardingCreatures (int3 pos) const;
|
std::vector<const CGObjectInstance*> guardingCreatures (int3 pos) const;
|
||||||
|
|
||||||
/// Gets a artifact ID randomly and removes the selected artifact from this handler.
|
/// Gets a artifact ID randomly and removes the selected artifact from this handler.
|
||||||
ArtifactID pickRandomArtifact(vstd::RNG & rand, int flags);
|
ArtifactID pickRandomArtifact(vstd::RNG & rand, int flags);
|
||||||
|
@ -96,9 +96,12 @@ int3 IBoatGenerator::bestLocation() const
|
|||||||
if (tile->blocked())
|
if (tile->blocked())
|
||||||
{
|
{
|
||||||
bool hasBoat = false;
|
bool hasBoat = false;
|
||||||
for (auto const * object : tile->blockingObjects)
|
for (auto const & objectID : tile->blockingObjects)
|
||||||
|
{
|
||||||
|
const auto * object = getObject()->cb->getObj(objectID);
|
||||||
if (object->ID == Obj::BOAT || object->ID == Obj::HERO)
|
if (object->ID == Obj::BOAT || object->ID == Obj::HERO)
|
||||||
hasBoat = true;
|
hasBoat = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasBoat)
|
if (!hasBoat)
|
||||||
continue; // tile is blocked, but not by boat -> check next potential position
|
continue; // tile is blocked, but not by boat -> check next potential position
|
||||||
@ -122,7 +125,9 @@ IBoatGenerator::EGeneratorState IBoatGenerator::shipyardStatus() const
|
|||||||
if(t->blockingObjects.empty())
|
if(t->blockingObjects.empty())
|
||||||
return GOOD; //OK
|
return GOOD; //OK
|
||||||
|
|
||||||
if(t->blockingObjects.front()->ID == Obj::BOAT || t->blockingObjects.front()->ID == Obj::HERO)
|
auto blockerObject = getObject()->cb->getObjInstance(t->blockingObjects.front());
|
||||||
|
|
||||||
|
if(blockerObject->ID == Obj::BOAT || blockerObject->ID == Obj::HERO)
|
||||||
return BOAT_ALREADY_BUILT; //blocked with boat
|
return BOAT_ALREADY_BUILT; //blocked with boat
|
||||||
|
|
||||||
return TILE_BLOCKED; //blocked
|
return TILE_BLOCKED; //blocked
|
||||||
|
@ -322,14 +322,16 @@ bool CGTeleport::isConnected(const CGObjectInstance * src, const CGObjectInstanc
|
|||||||
|
|
||||||
bool CGTeleport::isExitPassable(CGameState * gs, const CGHeroInstance * h, const CGObjectInstance * obj)
|
bool CGTeleport::isExitPassable(CGameState * gs, const CGHeroInstance * h, const CGObjectInstance * obj)
|
||||||
{
|
{
|
||||||
auto * objTopVisObj = gs->getMap().getTile(obj->visitablePos()).topVisitableObj();
|
ObjectInstanceID topObjectID = gs->getMap().getTile(obj->visitablePos()).topVisitableObj();
|
||||||
if(objTopVisObj->ID == Obj::HERO)
|
const CGObjectInstance * topObject = gs->getObjInstance(topObjectID);
|
||||||
|
|
||||||
|
if(topObject->ID == Obj::HERO)
|
||||||
{
|
{
|
||||||
if(h->id == objTopVisObj->id) // Just to be sure it's won't happen.
|
if(h->id == topObject->id) // Just to be sure it's won't happen.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check if it's friendly hero or not
|
// Check if it's friendly hero or not
|
||||||
if(gs->getPlayerRelations(h->tempOwner, objTopVisObj->tempOwner) != PlayerRelations::ENEMIES)
|
if(gs->getPlayerRelations(h->tempOwner, topObject->tempOwner) != PlayerRelations::ENEMIES)
|
||||||
{
|
{
|
||||||
// Exchange between heroes only possible via subterranean gates
|
// Exchange between heroes only possible via subterranean gates
|
||||||
if(!dynamic_cast<const CGSubterraneanGate *>(obj))
|
if(!dynamic_cast<const CGSubterraneanGate *>(obj))
|
||||||
|
@ -143,15 +143,10 @@ bool TerrainTile::isClear(const TerrainTile * from) const
|
|||||||
return entrableTerrain(from) && !blocked();
|
return entrableTerrain(from) && !blocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
Obj TerrainTile::topVisitableId(bool excludeTop) const
|
ObjectInstanceID TerrainTile::topVisitableObj(bool excludeTop) const
|
||||||
{
|
|
||||||
return topVisitableObj(excludeTop) ? topVisitableObj(excludeTop)->ID : Obj(Obj::NO_OBJ);
|
|
||||||
}
|
|
||||||
|
|
||||||
CGObjectInstance * TerrainTile::topVisitableObj(bool excludeTop) const
|
|
||||||
{
|
{
|
||||||
if(visitableObjects.empty() || (excludeTop && visitableObjects.size() == 1))
|
if(visitableObjects.empty() || (excludeTop && visitableObjects.size() == 1))
|
||||||
return nullptr;
|
return {};
|
||||||
|
|
||||||
if(excludeTop)
|
if(excludeTop)
|
||||||
return visitableObjects[visitableObjects.size()-2];
|
return visitableObjects[visitableObjects.size()-2];
|
||||||
@ -202,10 +197,10 @@ void CMap::removeBlockVisTiles(CGObjectInstance * obj, bool total)
|
|||||||
{
|
{
|
||||||
TerrainTile & curt = terrain[zVal][xVal][yVal];
|
TerrainTile & curt = terrain[zVal][xVal][yVal];
|
||||||
if(total || obj->visitableAt(int3(xVal, yVal, zVal)))
|
if(total || obj->visitableAt(int3(xVal, yVal, zVal)))
|
||||||
curt.visitableObjects -= obj;
|
curt.visitableObjects -= obj->id;
|
||||||
|
|
||||||
if(total || obj->blockingAt(int3(xVal, yVal, zVal)))
|
if(total || obj->blockingAt(int3(xVal, yVal, zVal)))
|
||||||
curt.blockingObjects -= obj;
|
curt.blockingObjects -= obj->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,10 +219,10 @@ void CMap::addBlockVisTiles(CGObjectInstance * obj)
|
|||||||
{
|
{
|
||||||
TerrainTile & curt = terrain[zVal][xVal][yVal];
|
TerrainTile & curt = terrain[zVal][xVal][yVal];
|
||||||
if(obj->visitableAt(int3(xVal, yVal, zVal)))
|
if(obj->visitableAt(int3(xVal, yVal, zVal)))
|
||||||
curt.visitableObjects.push_back(obj);
|
curt.visitableObjects.push_back(obj->id);
|
||||||
|
|
||||||
if(obj->blockingAt(int3(xVal, yVal, zVal)))
|
if(obj->blockingAt(int3(xVal, yVal, zVal)))
|
||||||
curt.blockingObjects.push_back(obj);
|
curt.blockingObjects.push_back(obj->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,12 +295,12 @@ bool CMap::checkForVisitableDir(const int3 & src, const TerrainTile * pom, const
|
|||||||
{
|
{
|
||||||
if (!pom->entrableTerrain()) //rock is never accessible
|
if (!pom->entrableTerrain()) //rock is never accessible
|
||||||
return false;
|
return false;
|
||||||
for(auto * obj : pom->visitableObjects) //checking destination tile
|
for(const auto & objID : pom->visitableObjects) //checking destination tile
|
||||||
{
|
{
|
||||||
if(!vstd::contains(pom->blockingObjects, obj)) //this visitable object is not blocking, ignore
|
if(!vstd::contains(pom->blockingObjects, objID)) //this visitable object is not blocking, ignore
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!obj->appearance->isVisitableFrom(src.x - dst.x, src.y - dst.y))
|
if (!getObject(objID)->appearance->isVisitableFrom(src.x - dst.x, src.y - dst.y))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -320,9 +315,10 @@ int3 CMap::guardingCreaturePosition (int3 pos) const
|
|||||||
const TerrainTile &posTile = getTile(pos);
|
const TerrainTile &posTile = getTile(pos);
|
||||||
if (posTile.visitable())
|
if (posTile.visitable())
|
||||||
{
|
{
|
||||||
for (CGObjectInstance* obj : posTile.visitableObjects)
|
for (const auto & objID : posTile.visitableObjects)
|
||||||
{
|
{
|
||||||
if (obj->ID == Obj::MONSTER)
|
const auto * object = getObject(objID);
|
||||||
|
if (object->ID == Obj::MONSTER)
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,12 +336,11 @@ int3 CMap::guardingCreaturePosition (int3 pos) const
|
|||||||
const auto & tile = getTile(pos);
|
const auto & tile = getTile(pos);
|
||||||
if (tile.visitable() && (tile.isWater() == water))
|
if (tile.visitable() && (tile.isWater() == water))
|
||||||
{
|
{
|
||||||
for (CGObjectInstance* obj : tile.visitableObjects)
|
for (const auto & objID : tile.visitableObjects)
|
||||||
{
|
{
|
||||||
if (obj->ID == Obj::MONSTER && checkForVisitableDir(pos, &posTile, originalPos)) // Monster being able to attack investigated tile
|
const auto * object = getObject(objID);
|
||||||
{
|
if (object->ID == Obj::MONSTER && checkForVisitableDir(pos, &posTile, originalPos)) // Monster being able to attack investigated tile
|
||||||
return pos;
|
return pos;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,8 +356,9 @@ int3 CMap::guardingCreaturePosition (int3 pos) const
|
|||||||
|
|
||||||
const CGObjectInstance * CMap::getObjectiveObjectFrom(const int3 & pos, Obj type)
|
const CGObjectInstance * CMap::getObjectiveObjectFrom(const int3 & pos, Obj type)
|
||||||
{
|
{
|
||||||
for (CGObjectInstance * object : getTile(pos).visitableObjects)
|
for(const auto & objID : getTile(pos).visitableObjects)
|
||||||
{
|
{
|
||||||
|
const auto * object = getObject(objID);
|
||||||
if (object->ID == type)
|
if (object->ID == type)
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,7 @@ struct DLL_LINKAGE TerrainTile
|
|||||||
/// Checks for blocking objects and terraint type (water / land).
|
/// Checks for blocking objects and terraint type (water / land).
|
||||||
bool isClear(const TerrainTile * from = nullptr) const;
|
bool isClear(const TerrainTile * from = nullptr) const;
|
||||||
/// Gets the ID of the top visitable object or -1 if there is none.
|
/// Gets the ID of the top visitable object or -1 if there is none.
|
||||||
Obj topVisitableId(bool excludeTop = false) const;
|
ObjectInstanceID topVisitableObj(bool excludeTop = false) const;
|
||||||
CGObjectInstance * topVisitableObj(bool excludeTop = false) const;
|
|
||||||
inline bool isWater() const;
|
inline bool isWater() const;
|
||||||
inline bool isLand() const;
|
inline bool isLand() const;
|
||||||
EDiggingStatus getDiggingStatus(bool excludeTop = true) const;
|
EDiggingStatus getDiggingStatus(bool excludeTop = true) const;
|
||||||
@ -127,8 +126,8 @@ struct DLL_LINKAGE TerrainTile
|
|||||||
/// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favorable Winds effect
|
/// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favorable Winds effect
|
||||||
ui8 extTileFlags;
|
ui8 extTileFlags;
|
||||||
|
|
||||||
std::vector<CGObjectInstance *> visitableObjects;
|
std::vector<ObjectInstanceID> visitableObjects;
|
||||||
std::vector<CGObjectInstance *> blockingObjects;
|
std::vector<ObjectInstanceID> blockingObjects;
|
||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
void serialize(Handler & h)
|
void serialize(Handler & h)
|
||||||
|
@ -2741,11 +2741,13 @@ void CMapLoaderH3M::afterRead()
|
|||||||
|
|
||||||
const CGObjectInstance * mainTown = nullptr;
|
const CGObjectInstance * mainTown = nullptr;
|
||||||
|
|
||||||
for(auto * obj : t.visitableObjects)
|
for(ObjectInstanceID objID : t.visitableObjects)
|
||||||
{
|
{
|
||||||
if(obj->ID == Obj::TOWN || obj->ID == Obj::RANDOM_TOWN)
|
const CGObjectInstance * object = map->getObject(objID);
|
||||||
|
|
||||||
|
if(object->ID == Obj::TOWN || object->ID == Obj::RANDOM_TOWN)
|
||||||
{
|
{
|
||||||
mainTown = obj;
|
mainTown = object;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1313,9 +1313,11 @@ void TryMoveHero::applyGs(CGameState *gs)
|
|||||||
|
|
||||||
if(result == EMBARK) //hero enters boat at destination tile
|
if(result == EMBARK) //hero enters boat at destination tile
|
||||||
{
|
{
|
||||||
|
const TerrainTile &tt = gs->getMap().getTile(h->convertToVisitablePos(end));
|
||||||
assert(destTile.visitableObjects.size() >= 1 && destTile.visitableObjects.back()->ID == Obj::BOAT); //the only visitable object at destination is Boat
|
ObjectInstanceID topObjectID = tt.visitableObjects.back();
|
||||||
auto * boat = dynamic_cast<CGBoat *>(destTile.visitableObjects.back());
|
CGObjectInstance * topObject = gs->getObjInstance(topObjectID);
|
||||||
|
assert(tt.visitableObjects.size() >= 1 && topObject->ID == Obj::BOAT); //the only visitable object at destination is Boat
|
||||||
|
auto * boat = dynamic_cast<CGBoat *>(topObject);
|
||||||
assert(boat);
|
assert(boat);
|
||||||
|
|
||||||
gs->getMap().removeBlockVisTiles(boat); //hero blockvis mask will be used, we don't need to duplicate it with boat
|
gs->getMap().removeBlockVisTiles(boat); //hero blockvis mask will be used, we don't need to duplicate it with boat
|
||||||
|
@ -103,6 +103,7 @@ PathNodeInfo::PathNodeInfo()
|
|||||||
void PathNodeInfo::setNode(CGameState * gs, CGPathNode * n)
|
void PathNodeInfo::setNode(CGameState * gs, CGPathNode * n)
|
||||||
{
|
{
|
||||||
node = n;
|
node = n;
|
||||||
|
guarded = false;
|
||||||
|
|
||||||
if(coord != node->coord)
|
if(coord != node->coord)
|
||||||
{
|
{
|
||||||
@ -110,23 +111,25 @@ void PathNodeInfo::setNode(CGameState * gs, CGPathNode * n)
|
|||||||
|
|
||||||
coord = node->coord;
|
coord = node->coord;
|
||||||
tile = gs->getTile(coord);
|
tile = gs->getTile(coord);
|
||||||
nodeObject = tile->topVisitableObj();
|
nodeObject = nullptr;
|
||||||
|
nodeHero = nullptr;
|
||||||
|
|
||||||
if(nodeObject && nodeObject->ID == Obj::HERO)
|
ObjectInstanceID topObjectID = tile->topVisitableObj();
|
||||||
|
if (topObjectID.hasValue())
|
||||||
{
|
{
|
||||||
nodeHero = dynamic_cast<const CGHeroInstance *>(nodeObject);
|
nodeObject = gs->getObjInstance(topObjectID);
|
||||||
nodeObject = tile->topVisitableObj(true);
|
|
||||||
|
|
||||||
if(!nodeObject)
|
if (nodeObject->ID == Obj::HERO)
|
||||||
nodeObject = nodeHero;
|
{
|
||||||
}
|
nodeHero = dynamic_cast<const CGHeroInstance *>(nodeObject);
|
||||||
else
|
ObjectInstanceID bottomObjectID = tile->topVisitableObj(true);
|
||||||
{
|
|
||||||
nodeHero = nullptr;
|
if (bottomObjectID.hasValue())
|
||||||
|
nodeObject = gs->getObjInstance(bottomObjectID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
guarded = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathNodeInfo::updateInfo(CPathfinderHelper * hlp, CGameState * gs)
|
void PathNodeInfo::updateInfo(CPathfinderHelper * hlp, CGameState * gs)
|
||||||
|
@ -251,7 +251,8 @@ TeleporterTilesVector CPathfinderHelper::getAllowedTeleportChannelExits(const Te
|
|||||||
auto pos = obj->getBlockedPos();
|
auto pos = obj->getBlockedPos();
|
||||||
for(const auto & p : pos)
|
for(const auto & p : pos)
|
||||||
{
|
{
|
||||||
if(gs->getMap().getTile(p).topVisitableId() == obj->ID)
|
ObjectInstanceID topObject = gs->getMap().getTile(p).topVisitableObj();
|
||||||
|
if(topObject.hasValue() && getObj(topObject)->ID == obj->ID)
|
||||||
allowedExits.push_back(p);
|
allowedExits.push_back(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,10 @@ namespace PathfinderUtil
|
|||||||
case ELayer::SAIL:
|
case ELayer::SAIL:
|
||||||
if(tinfo.visitable())
|
if(tinfo.visitable())
|
||||||
{
|
{
|
||||||
if(tinfo.visitableObjects.front()->ID == Obj::SANCTUARY && tinfo.visitableObjects.back()->ID == Obj::HERO && tinfo.visitableObjects.back()->tempOwner != player) //non-owned hero stands on Sanctuary
|
auto frontVisitable = gs->getObjInstance(tinfo.visitableObjects.front());
|
||||||
|
auto backVisitable = gs->getObjInstance(tinfo.visitableObjects.front());
|
||||||
|
|
||||||
|
if(frontVisitable->ID == Obj::SANCTUARY && backVisitable->ID == Obj::HERO && backVisitable->getOwner() != player) //non-owned hero stands on Sanctuary
|
||||||
{
|
{
|
||||||
return EPathAccessibility::BLOCKED;
|
return EPathAccessibility::BLOCKED;
|
||||||
}
|
}
|
||||||
@ -43,8 +46,10 @@ namespace PathfinderUtil
|
|||||||
bool hasBlockedVisitable = false;
|
bool hasBlockedVisitable = false;
|
||||||
bool hasVisitable = false;
|
bool hasVisitable = false;
|
||||||
|
|
||||||
for(const CGObjectInstance * obj : tinfo.visitableObjects)
|
for(const auto objID : tinfo.visitableObjects)
|
||||||
{
|
{
|
||||||
|
auto obj = gs->getObjInstance(objID);
|
||||||
|
|
||||||
if(obj->isBlockedVisitable())
|
if(obj->isBlockedVisitable())
|
||||||
hasBlockedVisitable = true;
|
hasBlockedVisitable = true;
|
||||||
else if(!obj->passableFor(player) && obj->ID != Obj::EVENT)
|
else if(!obj->passableFor(player) && obj->ID != Obj::EVENT)
|
||||||
|
@ -262,7 +262,11 @@ bool ScuttleBoatMechanics::canBeCastAtImpl(spells::Problem & problem, const CGam
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const TerrainTile * t = cb->getTile(pos);
|
const TerrainTile * t = cb->getTile(pos);
|
||||||
if(!t || t->visitableObjects.empty() || t->visitableObjects.back()->ID != Obj::BOAT)
|
if(!t || t->visitableObjects.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const CGObjectInstance * topObject = cb->getObj(t->visitableObjects.back());
|
||||||
|
if (topObject->ID != Obj::BOAT)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -286,7 +290,7 @@ ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(SpellCastEnvironmen
|
|||||||
|
|
||||||
RemoveObject ro;
|
RemoveObject ro;
|
||||||
ro.initiator = parameters.caster->getCasterOwner();
|
ro.initiator = parameters.caster->getCasterOwner();
|
||||||
ro.objectID = t.visitableObjects.back()->id;
|
ro.objectID = t.visitableObjects.back();
|
||||||
env->apply(ro);
|
env->apply(ro);
|
||||||
return ESpellCastResult::OK;
|
return ESpellCastResult::OK;
|
||||||
}
|
}
|
||||||
@ -476,7 +480,8 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
{
|
{
|
||||||
const TerrainTile & tile = env->getMap()->getTile(parameters.pos);
|
const TerrainTile & tile = env->getMap()->getTile(parameters.pos);
|
||||||
|
|
||||||
auto * const topObj = tile.topVisitableObj(false);
|
ObjectInstanceID topObjID = tile.topVisitableObj(false);
|
||||||
|
const CGObjectInstance * topObj = env->getMap()->getObject(topObjID);
|
||||||
|
|
||||||
if(!topObj)
|
if(!topObj)
|
||||||
{
|
{
|
||||||
@ -556,7 +561,9 @@ void TownPortalMechanics::endCast(SpellCastEnvironment * env, const AdventureSpe
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
const TerrainTile & tile = env->getMap()->getTile(parameters.pos);
|
const TerrainTile & tile = env->getMap()->getTile(parameters.pos);
|
||||||
auto * const topObj = tile.topVisitableObj(false);
|
ObjectInstanceID topObjID = tile.topVisitableObj(false);
|
||||||
|
const CGObjectInstance * topObj = env->getMap()->getObject(topObjID);
|
||||||
|
|
||||||
destination = dynamic_cast<const CGTownInstance*>(topObj);
|
destination = dynamic_cast<const CGTownInstance*>(topObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,12 +128,17 @@ void ObjectPickerLayer::highlight(std::function<bool(const CGObjectInstance *)>
|
|||||||
for(int i = 0; i < map->width; ++i)
|
for(int i = 0; i < map->width; ++i)
|
||||||
{
|
{
|
||||||
auto tl = map->getTile(int3(i, j, scene->level));
|
auto tl = map->getTile(int3(i, j, scene->level));
|
||||||
auto * obj = tl.topVisitableObj();
|
ObjectInstanceID objID = tl.topVisitableObj();
|
||||||
if(!obj && !tl.blockingObjects.empty())
|
if(!objID.hasValue() && !tl.blockingObjects.empty())
|
||||||
obj = tl.blockingObjects.front();
|
objID = tl.blockingObjects.front();
|
||||||
|
|
||||||
|
if (objID.hasValue())
|
||||||
|
{
|
||||||
|
const CGObjectInstance * obj = map->getObject(objID);
|
||||||
|
|
||||||
if(obj && predicate(obj))
|
if(obj && predicate(obj))
|
||||||
possibleObjects.insert(obj);
|
possibleObjects.insert(obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -826,13 +826,17 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
|
|||||||
CGObjectInstance * guardian = nullptr;
|
CGObjectInstance * guardian = nullptr;
|
||||||
|
|
||||||
if (!t.visitableObjects.empty())
|
if (!t.visitableObjects.empty())
|
||||||
objectToVisit = t.visitableObjects.back();
|
objectToVisit = gameState()->getObjInstance(t.visitableObjects.back());
|
||||||
|
|
||||||
if (isInTheMap(guardPos))
|
if (isInTheMap(guardPos))
|
||||||
{
|
{
|
||||||
for (auto const & object : getTile(guardPos)->visitableObjects)
|
for (auto const & objectID : getTile(guardPos)->visitableObjects)
|
||||||
|
{
|
||||||
|
auto object = gameState()->getObjInstance(objectID);
|
||||||
|
|
||||||
if (object->ID == MapObjectID::MONSTER) // exclude other objects, such as hero flying above monster
|
if (object->ID == MapObjectID::MONSTER) // exclude other objects, such as hero flying above monster
|
||||||
guardian = object;
|
guardian = object;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool embarking = !h->boat && objectToVisit && objectToVisit->ID == Obj::BOAT;
|
const bool embarking = !h->boat && objectToVisit && objectToVisit->ID == Obj::BOAT;
|
||||||
@ -909,10 +913,9 @@ 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->getMap().getTile(h->visitablePos()).visitableObjects)
|
for(const auto & objID : gs->getMap().getTile(h->visitablePos()).visitableObjects)
|
||||||
{
|
gameState()->getObjInstance(objID)->onHeroLeave(h);
|
||||||
obj->onHeroLeave(h);
|
|
||||||
}
|
|
||||||
this->getTilesInRange(tmh.fowRevealed, h->getSightCenter()+(tmh.end-tmh.start), h->getSightRadius(), ETileVisibility::HIDDEN, h->tempOwner);
|
this->getTilesInRange(tmh.fowRevealed, h->getSightCenter()+(tmh.end-tmh.start), h->getSightRadius(), ETileVisibility::HIDDEN, h->tempOwner);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -956,12 +959,14 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
|
|||||||
//interaction with blocking object (like resources)
|
//interaction with blocking object (like resources)
|
||||||
auto blockingVisit = [&]() -> bool
|
auto blockingVisit = [&]() -> bool
|
||||||
{
|
{
|
||||||
for (CGObjectInstance *obj : t.visitableObjects)
|
for (ObjectInstanceID objectID : t.visitableObjects)
|
||||||
{
|
{
|
||||||
if(h->boat && !obj->isBlockedVisitable() && !h->boat->onboardVisitAllowed)
|
const CGObjectInstance * object = getObj(objectID);
|
||||||
|
|
||||||
|
if(h->boat && !object->isBlockedVisitable() && !h->boat->onboardVisitAllowed)
|
||||||
return doMove(TryMoveHero::SUCCESS, this->IGNORE_GUARDS, DONT_VISIT_DEST, REMAINING_ON_TILE);
|
return doMove(TryMoveHero::SUCCESS, this->IGNORE_GUARDS, DONT_VISIT_DEST, REMAINING_ON_TILE);
|
||||||
|
|
||||||
if (obj != h && obj->isBlockedVisitable() && !obj->passableFor(h->tempOwner))
|
if (object != h && object->isBlockedVisitable() && !object->passableFor(h->tempOwner))
|
||||||
{
|
{
|
||||||
EVisitDest visitDest = VISIT_DEST;
|
EVisitDest visitDest = VISIT_DEST;
|
||||||
if(h->boat && !h->boat->onboardVisitAllowed)
|
if(h->boat && !h->boat->onboardVisitAllowed)
|
||||||
@ -3657,10 +3662,10 @@ void CGameHandler::visitObjectOnTile(const TerrainTile &t, const CGHeroInstance
|
|||||||
if (!t.visitableObjects.empty())
|
if (!t.visitableObjects.empty())
|
||||||
{
|
{
|
||||||
//to prevent self-visiting heroes on space press
|
//to prevent self-visiting heroes on space press
|
||||||
if (t.visitableObjects.back() != h)
|
if (t.visitableObjects.back() != h->id)
|
||||||
objectVisited(t.visitableObjects.back(), h);
|
objectVisited(gameState()->getObjInstance(t.visitableObjects.back()), h);
|
||||||
else if (t.visitableObjects.size() > 1)
|
else if (t.visitableObjects.size() > 1)
|
||||||
objectVisited(*(t.visitableObjects.end()-2),h);
|
objectVisited(gameState()->getObjInstance(*(t.visitableObjects.end()-2)),h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gameHandler->getTile(mapObject->visitablePos())->visitableObjects.back() != mapObject && gameHandler->complain("Tavern entry must be unoccupied!"))
|
if(gameHandler->getTile(mapObject->visitablePos())->visitableObjects.back() != mapObject->id && gameHandler->complain("Tavern entry must be unoccupied!"))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user