1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-23 12:08:45 +02:00

CGSubterraneanGate: fix pairing and always assign all gates to channel

Before gates on underground layer didn't had any channel assigned and of course any function that attempt to check -1 channel caused crash.
Also I find out that at point postInit executed It's possible to get mutable gamestate via gameState() callback so we don't need to pass it there.
This commit is contained in:
ArseniyShestakov 2015-03-11 17:17:21 +03:00
parent f3cdadf142
commit 17f3f94ca6
3 changed files with 19 additions and 11 deletions

View File

@ -1867,7 +1867,7 @@ void CGameState::initMapObjects()
} }
} }
} }
CGSubterraneanGate::postInit(gs); //pairing subterranean gates CGSubterraneanGate::postInit(); //pairing subterranean gates
map->calculateGuardingGreaturePositions(); //calculate once again when all the guards are placed and initialized map->calculateGuardingGreaturePositions(); //calculate once again when all the guards are placed and initialized
} }

View File

@ -996,13 +996,13 @@ void CGSubterraneanGate::initObj()
type = BOTH; type = BOTH;
} }
void CGSubterraneanGate::postInit( CGameState * gs ) //matches subterranean gates into pairs void CGSubterraneanGate::postInit() //matches subterranean gates into pairs
{ {
//split on underground and surface gates //split on underground and surface gates
std::vector<CGSubterraneanGate *> gatesSplit[2]; //surface and underground gates std::vector<CGSubterraneanGate *> gatesSplit[2]; //surface and underground gates
for(auto & obj : cb->gameState()->map->objects) for(auto & obj : cb->gameState()->map->objects)
{ {
auto hlp = dynamic_cast<CGSubterraneanGate *>(gs->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->pos.z].push_back(hlp);
} }
@ -1013,6 +1013,15 @@ void CGSubterraneanGate::postInit( CGameState * gs ) //matches subterranean gate
return a->pos < b->pos; return a->pos < b->pos;
}); });
auto assignToChannel = [&](CGSubterraneanGate * obj)
{
if(obj->channel == TeleportChannelID())
{ // if object not linked to channel then create new channel
obj->channel = TeleportChannelID(cb->gameState()->map->teleportChannels.size());
addToChannel(cb->gameState()->map->teleportChannels, obj);
}
};
for(size_t i = 0; i < gatesSplit[0].size(); i++) for(size_t i = 0; i < gatesSplit[0].size(); i++)
{ {
CGSubterraneanGate * objCurrent = gatesSplit[0][i]; CGSubterraneanGate * objCurrent = gatesSplit[0][i];
@ -1022,7 +1031,7 @@ void CGSubterraneanGate::postInit( CGameState * gs ) //matches subterranean gate
for(int j = 0; j < gatesSplit[1].size(); j++) for(int j = 0; j < gatesSplit[1].size(); j++)
{ {
CGSubterraneanGate *checked = gatesSplit[1][j]; CGSubterraneanGate *checked = gatesSplit[1][j];
if(!checked) if(checked->channel != TeleportChannelID())
continue; continue;
si32 hlp = checked->pos.dist2dSQ(objCurrent->pos); si32 hlp = checked->pos.dist2dSQ(objCurrent->pos);
if(hlp < best.second) if(hlp < best.second)
@ -1032,18 +1041,17 @@ void CGSubterraneanGate::postInit( CGameState * gs ) //matches subterranean gate
} }
} }
if(objCurrent->channel == TeleportChannelID()) assignToChannel(objCurrent);
{ // if object not linked to channel then create new channel
objCurrent->channel = TeleportChannelID(gs->map->teleportChannels.size());
addToChannel(cb->gameState()->map->teleportChannels, objCurrent);
}
if(best.first >= 0) //found pair if(best.first >= 0) //found pair
{ {
gatesSplit[1][best.first]->channel = objCurrent->channel; gatesSplit[1][best.first]->channel = objCurrent->channel;
addToChannel(cb->gameState()->map->teleportChannels, gatesSplit[1][best.first]); addToChannel(cb->gameState()->map->teleportChannels, gatesSplit[1][best.first]);
} }
} }
// we should assign empty channels to underground gates if they don't have matching overground gates
for(size_t i = 0; i < gatesSplit[1].size(); i++)
assignToChannel(gatesSplit[1][i]);
} }
void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const

View File

@ -315,7 +315,7 @@ class DLL_LINKAGE CGSubterraneanGate : public CGMonolith
public: public:
void onHeroVisit(const CGHeroInstance * h) const override; void onHeroVisit(const CGHeroInstance * h) const override;
void initObj() override; void initObj() override;
static void postInit(CGameState * gs); static void postInit();
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {