mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-29 23:07:48 +02:00
Merge pull request #144 from vcmi/fix/teleportMultiExitPoints
Support for exit selection between multiple teleport exit points
This commit is contained in:
@@ -836,7 +836,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)
|
||||
@@ -915,7 +915,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))
|
||||
{
|
||||
@@ -931,9 +937,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
|
||||
@@ -941,14 +947,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()
|
||||
@@ -988,7 +992,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);
|
||||
}
|
||||
@@ -1087,29 +1094,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 )
|
||||
|
||||
Reference in New Issue
Block a user