mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge pull request #144 from vcmi/fix/teleportMultiExitPoints
Support for exit selection between multiple teleport exit points
This commit is contained in:
commit
0a5e9c0fbe
@ -30,7 +30,7 @@ void CEmptyAI::showBlockingDialog(const std::string &text, const std::vector<Com
|
||||
cb->selectionMade(0, askID);
|
||||
}
|
||||
|
||||
void CEmptyAI::showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID)
|
||||
void CEmptyAI::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID)
|
||||
{
|
||||
cb->selectionMade(0, askID);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ public:
|
||||
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
||||
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
|
||||
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
|
||||
};
|
||||
|
||||
|
@ -98,6 +98,7 @@ VCAI::VCAI(void)
|
||||
LOG_TRACE(logAi);
|
||||
makingTurn = nullptr;
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
}
|
||||
|
||||
VCAI::~VCAI(void)
|
||||
@ -616,33 +617,46 @@ void VCAI::showBlockingDialog(const std::string &text, const std::vector<Compone
|
||||
});
|
||||
}
|
||||
|
||||
void VCAI::showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID)
|
||||
void VCAI::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "askID '%i', exits '%s'", askID % exits);
|
||||
// LOG_TRACE_PARAMS(logAi, "askID '%i', exits '%s'", askID % exits);
|
||||
NET_EVENT_HANDLER;
|
||||
status.addQuery(askID, boost::str(boost::format("Teleport dialog query with %d exits")
|
||||
% exits.size()));
|
||||
|
||||
ObjectInstanceID choosenExit;
|
||||
int choosenExit = -1;
|
||||
if(impassable)
|
||||
knownTeleportChannels[channel]->passability = TeleportChannel::IMPASSABLE;
|
||||
else
|
||||
else if(destinationTeleport != ObjectInstanceID() && destinationTeleportPos.valid())
|
||||
{
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, destinationTeleport))
|
||||
choosenExit = destinationTeleport;
|
||||
auto neededExit = std::make_pair(destinationTeleport, destinationTeleportPos);
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
||||
choosenExit = vstd::find_pos(exits, neededExit);
|
||||
}
|
||||
|
||||
if(!status.channelProbing())
|
||||
for(auto exit : exits)
|
||||
{
|
||||
if(status.channelProbing() && exit.first == destinationTeleport)
|
||||
{
|
||||
vstd::copy_if(exits, vstd::set_inserter(teleportChannelProbingList), [&](ObjectInstanceID id) -> bool
|
||||
choosenExit = vstd::find_pos(exits, exit);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Implement checking if visiting that teleport will uncovert any FoW
|
||||
// So far this is the best option to handle decision about probing
|
||||
auto obj = cb->getObj(exit.first, false);
|
||||
if(obj == nullptr && !vstd::contains(teleportChannelProbingList, exit.first) &&
|
||||
exit.first != destinationTeleport)
|
||||
{
|
||||
return !(vstd::contains(visitableObjs, cb->getObj(id)) || id == choosenExit);
|
||||
});
|
||||
teleportChannelProbingList.push_back(exit.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requestActionASAP([=]()
|
||||
{
|
||||
answerQuery(askID, choosenExit.getNum());
|
||||
answerQuery(askID, choosenExit);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1876,25 +1890,29 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
cb->moveHero(*h, CGHeroInstance::convertPosition(dst, true), transit);
|
||||
};
|
||||
|
||||
auto doTeleportMovement = [&](int3 dst, ObjectInstanceID exitId)
|
||||
auto doTeleportMovement = [&](ObjectInstanceID exitId, int3 exitPos)
|
||||
{
|
||||
destinationTeleport = exitId;
|
||||
cb->moveHero(*h, CGHeroInstance::convertPosition(dst, true));
|
||||
if(exitPos.valid())
|
||||
destinationTeleportPos = CGHeroInstance::convertPosition(exitPos, true);
|
||||
cb->moveHero(*h, h->pos);
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
afterMovementCheck();
|
||||
};
|
||||
|
||||
auto doChannelProbing = [&]() -> void
|
||||
{
|
||||
auto currentExit = getObj(CGHeroInstance::convertPosition(h->pos,false), false);
|
||||
assert(currentExit);
|
||||
auto currentPos = CGHeroInstance::convertPosition(h->pos,false);
|
||||
auto currentExit = getObj(currentPos, true)->id;
|
||||
|
||||
status.setChannelProbing(true);
|
||||
for(auto exit : teleportChannelProbingList)
|
||||
doTeleportMovement(CGHeroInstance::convertPosition(h->pos,false), exit);
|
||||
doTeleportMovement(exit, int3(-1));
|
||||
teleportChannelProbingList.clear();
|
||||
doTeleportMovement(CGHeroInstance::convertPosition(h->pos,false), currentExit->id);
|
||||
status.setChannelProbing(false);
|
||||
|
||||
doTeleportMovement(currentExit, currentPos);
|
||||
};
|
||||
|
||||
int i=path.nodes.size()-1;
|
||||
@ -1907,7 +1925,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
auto nextObject = getObj(nextCoord, false);
|
||||
if(CGTeleport::isConnected(currentObject, nextObject))
|
||||
{ //we use special login if hero standing on teleporter it's mean we need
|
||||
doTeleportMovement(currentCoord, nextObject->id);
|
||||
doTeleportMovement(nextObject->id, nextCoord);
|
||||
if(teleportChannelProbingList.size())
|
||||
doChannelProbing();
|
||||
|
||||
@ -2934,7 +2952,7 @@ void AIStatus::setMove(bool ongoing)
|
||||
void AIStatus::setChannelProbing(bool ongoing)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(mx);
|
||||
ongoingHeroMovement = ongoing;
|
||||
ongoingChannelProbing = ongoing;
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,7 @@ public:
|
||||
std::map<TeleportChannelID, shared_ptr<TeleportChannel> > knownTeleportChannels;
|
||||
std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
|
||||
ObjectInstanceID destinationTeleport;
|
||||
int3 destinationTeleportPos;
|
||||
std::vector<ObjectInstanceID> teleportChannelProbingList; //list of teleport channel exits that not visible and need to be (re-)explored
|
||||
//std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
|
||||
std::map<HeroPtr, std::set<const CGTownInstance *> > townVisitsThisWeek;
|
||||
@ -186,7 +187,7 @@ public:
|
||||
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; //TODO
|
||||
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
|
||||
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) override;
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
virtual void saveGame(COSer & h, const int version) override; //saving
|
||||
virtual void loadGame(CISer & h, const int version) override; //loading
|
||||
virtual void finish() override;
|
||||
@ -344,6 +345,14 @@ public:
|
||||
template <typename Handler> void serializeInternal(Handler &h, const int version)
|
||||
{
|
||||
h & knownTeleportChannels & knownSubterraneanGates & destinationTeleport;
|
||||
if(version >= 755)
|
||||
{
|
||||
h & destinationTeleportPos;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
destinationTeleportPos = int3(-1);
|
||||
}
|
||||
h & townVisitsThisWeek & lockedHeroes & reservedHeroesMap; //FIXME: cannot instantiate abstract class
|
||||
h & visitableObjs & alreadyVisited & reservedObjs;
|
||||
h & saving & status & battlename;
|
||||
|
@ -98,6 +98,7 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player)
|
||||
{
|
||||
logGlobal->traceStream() << "\tHuman player interface for player " << Player << " being constructed";
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
observerInDuelMode = false;
|
||||
howManyPeople++;
|
||||
GH.defActionsDef = 0;
|
||||
@ -1148,14 +1149,15 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v
|
||||
|
||||
}
|
||||
|
||||
void CPlayerInterface::showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID)
|
||||
void CPlayerInterface::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
ObjectInstanceID choosenExit;
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, destinationTeleport))
|
||||
choosenExit = destinationTeleport;
|
||||
int choosenExit = -1;
|
||||
auto neededExit = std::make_pair(destinationTeleport, destinationTeleportPos);
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
||||
choosenExit = vstd::find_pos(exits, neededExit);
|
||||
|
||||
cb->selectionMade(choosenExit.getNum(), askID);
|
||||
cb->selectionMade(choosenExit, askID);
|
||||
}
|
||||
|
||||
void CPlayerInterface::tileRevealed(const std::unordered_set<int3, ShashInt3> &pos)
|
||||
@ -1415,6 +1417,7 @@ void CPlayerInterface::requestRealized( PackageApplied *pa )
|
||||
&& stillMoveHero.get() == DURING_MOVE)
|
||||
{ // After teleportation via CGTeleport object is finished
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
stillMoveHero.setn(CONTINUE_MOVE);
|
||||
}
|
||||
}
|
||||
@ -2663,6 +2666,7 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
{
|
||||
CCS->soundh->stopSound(sh);
|
||||
destinationTeleport = nextObject->id;
|
||||
destinationTeleportPos = nextCoord;
|
||||
doMovement(h->pos, false);
|
||||
sh = CCS->soundh->playSound(CCS->soundh->horseSounds[currentTerrain], -1);
|
||||
continue;
|
||||
|
@ -89,6 +89,7 @@ class CPlayerInterface : public CGameInterface, public IUpdateable
|
||||
public:
|
||||
bool observerInDuelMode;
|
||||
ObjectInstanceID destinationTeleport; //contain -1 or object id if teleportation
|
||||
int3 destinationTeleportPos;
|
||||
|
||||
//minor interfaces
|
||||
CondSh<bool> *showingDialog; //indicates if dialog box is displayed
|
||||
@ -167,7 +168,7 @@ public:
|
||||
void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
|
||||
void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
|
||||
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
|
||||
void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
|
||||
void showPuzzleMap() override;
|
||||
void viewWorldMap() override;
|
||||
|
@ -855,7 +855,7 @@ std::vector<ObjectInstanceID> CGameInfoCallback::getVisibleTeleportObjects(std::
|
||||
{
|
||||
vstd::erase_if(ids, [&](ObjectInstanceID id) -> bool
|
||||
{
|
||||
auto obj = getObj(id);
|
||||
auto obj = getObj(id, false);
|
||||
return player != PlayerColor::UNFLAGGABLE && (!obj || !isVisible(obj->pos, player));
|
||||
});
|
||||
return ids;
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include "spells/ViewSpellInt.h"
|
||||
|
||||
#include "mapObjects/CObjectHandler.h"
|
||||
|
||||
/*
|
||||
* CGameInterface.h, part of VCMI engine
|
||||
*
|
||||
@ -94,7 +96,7 @@ public:
|
||||
|
||||
// all stacks operations between these objects become allowed, interface has to call onEnd when done
|
||||
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) = 0;
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) = 0;
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) = 0;
|
||||
virtual void finish(){}; //if for some reason we want to end
|
||||
|
||||
virtual void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions){};
|
||||
|
@ -1222,7 +1222,7 @@ struct TeleportDialog : public Query//2006
|
||||
|
||||
const CGHeroInstance *hero;
|
||||
TeleportChannelID channel;
|
||||
std::vector<ObjectInstanceID> exits;
|
||||
TTeleportExitsList exits;
|
||||
bool impassable;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
|
@ -22,6 +22,10 @@ class CGObjectInstance;
|
||||
struct MetaString;
|
||||
struct BattleResult;
|
||||
|
||||
// This one teleport-specific, but has to be available everywhere in callbacks and netpacks
|
||||
// For now it's will be there till teleports code refactored and moved into own file
|
||||
typedef std::vector<std::pair<ObjectInstanceID, int3>> TTeleportExitsList;
|
||||
|
||||
class DLL_LINKAGE IObjectInterface
|
||||
{
|
||||
public:
|
||||
|
@ -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 )
|
||||
|
@ -286,7 +286,7 @@ public:
|
||||
bool isEntrance() const;
|
||||
bool isExit() const;
|
||||
|
||||
virtual void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const = 0;
|
||||
virtual void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const = 0;
|
||||
|
||||
static bool isTeleport(const CGObjectInstance * dst);
|
||||
static bool isConnected(const CGTeleport * src, const CGTeleport * dst);
|
||||
@ -307,7 +307,7 @@ class DLL_LINKAGE CGMonolith : public CGTeleport
|
||||
|
||||
protected:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const override;
|
||||
void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const override;
|
||||
void initObj() override;
|
||||
|
||||
public:
|
||||
@ -334,7 +334,7 @@ public:
|
||||
class DLL_LINKAGE CGWhirlpool : public CGMonolith
|
||||
{
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const override;
|
||||
void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const override;
|
||||
static bool isProtected( const CGHeroInstance * h );
|
||||
|
||||
public:
|
||||
|
@ -1755,7 +1755,7 @@ bool CGameHandler::moveHero( ObjectInstanceID hid, int3 dst, ui8 teleporting, bo
|
||||
}
|
||||
|
||||
logGlobal->traceStream() << "Player " << asker << " wants to move hero "<< hid.getNum() << " from "<< h->pos << " to " << dst;
|
||||
const int3 hmpos = dst + int3(-1,0,0);
|
||||
const int3 hmpos = CGHeroInstance::convertPosition(dst, false);
|
||||
|
||||
if(!gs->map->isInTheMap(hmpos))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user