1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

Teleport: rework code to support exit point selection for whirlpools

This commit is contained in:
ArseniyShestakov
2015-12-02 17:56:26 +03:00
parent f6de3f94ca
commit b5100bee94
7 changed files with 72 additions and 41 deletions

View File

@ -834,7 +834,7 @@ bool CGTeleport::isTeleport(const CGObjectInstance * obj)
bool CGTeleport::isConnected(const CGTeleport * src, const CGTeleport * dst)
{
return src && dst && src != dst && src->isChannelExit(dst->id);
return src && dst && src->isChannelExit(dst->id);
}
bool CGTeleport::isConnected(const CGObjectInstance * src, const CGObjectInstance * dst)
@ -913,7 +913,13 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
if(isEntrance())
{
if(cb->isTeleportChannelBidirectional(channel) && 1 < cb->getTeleportChannelExits(channel).size())
td.exits = cb->getTeleportChannelExits(channel);
{
auto exits = cb->getTeleportChannelExits(channel);
for(auto exit : exits)
{
td.exits.push_back(std::make_pair(exit, CGHeroInstance::convertPosition(cb->getObj(exit)->visitablePos(), true)));
}
}
if(cb->isTeleportChannelImpassable(channel))
{
@ -929,9 +935,9 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
cb->showTeleportDialog(&td);
}
void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const
void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
{
ObjectInstanceID objId(answer);
int3 dPos;
auto realExits = getAllExits(true);
if(!isEntrance() // Do nothing if hero visited exit only object
|| (!exits.size() && !realExits.size()) // Do nothing if there no exits on this channel
@ -939,14 +945,12 @@ void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer,
{
return;
}
else if(objId == ObjectInstanceID())
objId = getRandomExit(hero);
else if(vstd::isValidIndex(exits, answer))
dPos = exits[answer].second;
else
assert(vstd::contains(exits, objId)); // Likely cheating attempt: not random teleporter choosen, but it's not from provided list
dPos = CGHeroInstance::convertPosition(cb->getObj(getRandomExit(hero))->visitablePos(), true);
auto obj = cb->getObj(objId);
if(obj)
cb->moveHero(hero->id,CGHeroInstance::convertPosition(obj->pos,true) - getVisitableOffset(), true);
cb->moveHero(hero->id, dPos, true);
}
void CGMonolith::initObj()
@ -986,7 +990,10 @@ void CGSubterraneanGate::onHeroVisit( const CGHeroInstance * h ) const
td.impassable = true;
}
else
td.exits.push_back(getRandomExit(h));
{
auto exit = getRandomExit(h);
td.exits.push_back(std::make_pair(exit, CGHeroInstance::convertPosition(cb->getObj(exit)->visitablePos(), true)));
}
cb->showTeleportDialog(&td);
}
@ -1085,29 +1092,35 @@ void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const
cb->changeStackCount(StackLocation(h, targetstack), -countToTake);
}
else
td.exits = getAllExits(true);
{
auto exits = getAllExits();
for(auto exit : exits)
{
auto blockedPosList = cb->getObj(exit)->getBlockedPos();
for(auto bPos : blockedPosList)
td.exits.push_back(std::make_pair(exit, CGHeroInstance::convertPosition(bPos, true)));
}
}
cb->showTeleportDialog(&td);
}
void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const
void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
{
ObjectInstanceID objId(answer);
int3 dPos;
auto realExits = getAllExits();
if(!exits.size() && !realExits.size())
return;
else if(objId == ObjectInstanceID())
objId = getRandomExit(hero);
else if(vstd::isValidIndex(exits, answer))
dPos = exits[answer].second;
else
assert(vstd::contains(exits, objId)); // Likely cheating attempt: not random teleporter choosen, but it's not from provided list
auto obj = cb->getObj(objId);
if(obj)
{
auto obj = cb->getObj(getRandomExit(hero));
std::set<int3> tiles = obj->getBlockedPos();
auto & tile = *RandomGeneratorUtil::nextItem(tiles, cb->gameState()->getRandomGenerator());
cb->moveHero(hero->id, CGHeroInstance::convertPosition(tile, true), true);
dPos = CGHeroInstance::convertPosition(*RandomGeneratorUtil::nextItem(tiles, cb->gameState()->getRandomGenerator()), true);
}
cb->moveHero(hero->id, dPos, true);
}
bool CGWhirlpool::isProtected( const CGHeroInstance * h )