1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +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
}

View File

@ -996,13 +996,13 @@ void CGSubterraneanGate::initObj()
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
std::vector<CGSubterraneanGate *> gatesSplit[2]; //surface and underground gates
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)
gatesSplit[hlp->pos.z].push_back(hlp);
}
@ -1013,6 +1013,15 @@ void CGSubterraneanGate::postInit( CGameState * gs ) //matches subterranean gate
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++)
{
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++)
{
CGSubterraneanGate *checked = gatesSplit[1][j];
if(!checked)
if(checked->channel != TeleportChannelID())
continue;
si32 hlp = checked->pos.dist2dSQ(objCurrent->pos);
if(hlp < best.second)
@ -1032,18 +1041,17 @@ void CGSubterraneanGate::postInit( CGameState * gs ) //matches subterranean gate
}
}
if(objCurrent->channel == TeleportChannelID())
{ // if object not linked to channel then create new channel
objCurrent->channel = TeleportChannelID(gs->map->teleportChannels.size());
addToChannel(cb->gameState()->map->teleportChannels, objCurrent);
}
assignToChannel(objCurrent);
if(best.first >= 0) //found pair
{
gatesSplit[1][best.first]->channel = objCurrent->channel;
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

View File

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