mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge pull request #3786 from IvanSavenko/instant_movement
Instant movement
This commit is contained in:
commit
21dff9413e
@ -1230,7 +1230,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
{
|
||||
//FIXME: this assertion fails also if AI moves onto defeated guarded object
|
||||
//assert(cb->getVisitableObjs(dst).size() > 1); //there's no point in revisiting tile where there is no visitable object
|
||||
cb->moveHero(*h, h->convertFromVisitablePos(dst));
|
||||
cb->moveHero(*h, h->convertFromVisitablePos(dst), false);
|
||||
afterMovementCheck(); // TODO: is it feasible to hero get killed there if game work properly?
|
||||
// If revisiting, teleport probing is never done, and so the entries into the list would remain unused and uncleared
|
||||
teleportChannelProbingList.clear();
|
||||
@ -1292,7 +1292,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
destinationTeleport = exitId;
|
||||
if(exitPos.valid())
|
||||
destinationTeleportPos = h->convertFromVisitablePos(exitPos);
|
||||
cb->moveHero(*h, h->pos);
|
||||
cb->moveHero(*h, h->pos, false);
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
afterMovementCheck();
|
||||
|
@ -1837,7 +1837,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
{
|
||||
//FIXME: this assertion fails also if AI moves onto defeated guarded object
|
||||
assert(cb->getVisitableObjs(dst).size() > 1); //there's no point in revisiting tile where there is no visitable object
|
||||
cb->moveHero(*h, h->convertFromVisitablePos(dst));
|
||||
cb->moveHero(*h, h->convertFromVisitablePos(dst), false);
|
||||
afterMovementCheck(); // TODO: is it feasible to hero get killed there if game work properly?
|
||||
// If revisiting, teleport probing is never done, and so the entries into the list would remain unused and uncleared
|
||||
teleportChannelProbingList.clear();
|
||||
@ -1899,7 +1899,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
destinationTeleport = exitId;
|
||||
if(exitPos.valid())
|
||||
destinationTeleportPos = h->convertFromVisitablePos(exitPos);
|
||||
cb->moveHero(*h, h->pos);
|
||||
cb->moveHero(*h, h->pos, false);
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
afterMovementCheck();
|
||||
|
@ -34,11 +34,16 @@ bool CCallback::teleportHero(const CGHeroInstance *who, const CGTownInstance *wh
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCallback::moveHero(const CGHeroInstance *h, int3 dst, bool transit)
|
||||
void CCallback::moveHero(const CGHeroInstance *h, const int3 & destination, bool transit)
|
||||
{
|
||||
MoveHero pack(dst,h->id,transit);
|
||||
MoveHero pack({destination}, h->id, transit);
|
||||
sendRequest(&pack);
|
||||
}
|
||||
|
||||
void CCallback::moveHero(const CGHeroInstance *h, const std::vector<int3> & path, bool transit)
|
||||
{
|
||||
MoveHero pack(path, h->id, transit);
|
||||
sendRequest(&pack);
|
||||
return true;
|
||||
}
|
||||
|
||||
int CCallback::selectionMade(int selection, QueryID queryID)
|
||||
|
@ -67,7 +67,8 @@ class IGameActionCallback
|
||||
{
|
||||
public:
|
||||
//hero
|
||||
virtual bool moveHero(const CGHeroInstance *h, int3 dst, bool transit) =0; //dst must be free, neighbouring tile (this function can move hero only by one tile)
|
||||
virtual void moveHero(const CGHeroInstance *h, const std::vector<int3> & path, bool transit) =0; //moves hero alongside provided path
|
||||
virtual void moveHero(const CGHeroInstance *h, const int3 & destination, bool transit) =0; //moves hero alongside provided path
|
||||
virtual bool dismissHero(const CGHeroInstance * hero)=0; //dismisses given hero; true - successfuly, false - not successfuly
|
||||
virtual void dig(const CGObjectInstance *hero)=0;
|
||||
virtual void castSpell(const CGHeroInstance *hero, SpellID spellID, const int3 &pos = int3(-1, -1, -1))=0; //cast adventure map spell
|
||||
@ -159,7 +160,8 @@ public:
|
||||
void unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
|
||||
//commands
|
||||
bool moveHero(const CGHeroInstance *h, int3 dst, bool transit = false) override; //dst must be free, neighbouring tile (this function can move hero only by one tile)
|
||||
void moveHero(const CGHeroInstance *h, const std::vector<int3> & path, bool transit) override;
|
||||
void moveHero(const CGHeroInstance *h, const int3 & destination, bool transit) override;
|
||||
bool teleportHero(const CGHeroInstance *who, const CGTownInstance *where);
|
||||
int selectionMade(int selection, QueryID queryID) override;
|
||||
int sendQueryReply(std::optional<int32_t> reply, QueryID queryID) override;
|
||||
|
@ -518,15 +518,15 @@ void CClient::handlePack(CPack * pack)
|
||||
if(apply)
|
||||
{
|
||||
apply->applyOnClBefore(this, pack);
|
||||
logNetwork->trace("\tMade first apply on cl: %s", typeid(pack).name());
|
||||
logNetwork->trace("\tMade first apply on cl: %s", typeid(*pack).name());
|
||||
gs->apply(pack);
|
||||
logNetwork->trace("\tApplied on gs: %s", typeid(pack).name());
|
||||
logNetwork->trace("\tApplied on gs: %s", typeid(*pack).name());
|
||||
apply->applyOnClAfter(this, pack);
|
||||
logNetwork->trace("\tMade second apply on cl: %s", typeid(pack).name());
|
||||
logNetwork->trace("\tMade second apply on cl: %s", typeid(*pack).name());
|
||||
}
|
||||
else
|
||||
{
|
||||
logNetwork->error("Message %s cannot be applied, cannot find applier!", typeid(pack).name());
|
||||
logNetwork->error("Message %s cannot be applied, cannot find applier!", typeid(*pack).name());
|
||||
}
|
||||
delete pack;
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ void HeroMovementController::onMoveHeroApplied()
|
||||
}
|
||||
else
|
||||
{
|
||||
moveOnce(hero, LOCPLINT->localState->getPath(hero));
|
||||
sendMovementRequest(hero, LOCPLINT->localState->getPath(hero));
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,28 +335,27 @@ bool HeroMovementController::canHeroStopAtNode(const CGPathNode & node) const
|
||||
void HeroMovementController::requestMovementStart(const CGHeroInstance * h, const CGPath & path)
|
||||
{
|
||||
assert(duringMovement == false);
|
||||
|
||||
duringMovement = true;
|
||||
currentlyMovingHero = h;
|
||||
|
||||
CCS->curh->hide();
|
||||
moveOnce(h, path);
|
||||
sendMovementRequest(h, path);
|
||||
}
|
||||
|
||||
void HeroMovementController::moveOnce(const CGHeroInstance * h, const CGPath & path)
|
||||
void HeroMovementController::sendMovementRequest(const CGHeroInstance * h, const CGPath & path)
|
||||
{
|
||||
// Moves hero once, sends request to server and immediately returns
|
||||
// movement alongside paths will be done on receiving response from server
|
||||
|
||||
assert(duringMovement == true);
|
||||
|
||||
int heroMovementSpeed = settings["adventure"]["heroMoveTime"].Integer();
|
||||
bool useMovementBatching = heroMovementSpeed == 0;
|
||||
|
||||
const auto & currNode = path.currNode();
|
||||
const auto & nextNode = path.nextNode();
|
||||
|
||||
assert(nextNode.turns == 0);
|
||||
assert(currNode.coord == h->visitablePos());
|
||||
|
||||
int3 nextCoord = h->convertFromVisitablePos(nextNode.coord);
|
||||
|
||||
if(nextNode.isTeleportAction())
|
||||
{
|
||||
stopMovementSound();
|
||||
@ -364,7 +363,8 @@ void HeroMovementController::moveOnce(const CGHeroInstance * h, const CGPath & p
|
||||
LOCPLINT->cb->moveHero(h, h->pos, false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
if (!useMovementBatching)
|
||||
{
|
||||
updateMovementSound(h, currNode.coord, nextNode.coord, nextNode.action);
|
||||
|
||||
@ -373,7 +373,44 @@ void HeroMovementController::moveOnce(const CGHeroInstance * h, const CGPath & p
|
||||
logGlobal->trace("Requesting hero movement to %s", nextNode.coord.toString());
|
||||
|
||||
bool useTransit = nextNode.layer == EPathfindingLayer::AIR || nextNode.layer == EPathfindingLayer::WATER;
|
||||
int3 nextCoord = h->convertFromVisitablePos(nextNode.coord);
|
||||
|
||||
LOCPLINT->cb->moveHero(h, nextCoord, useTransit);
|
||||
return;
|
||||
}
|
||||
|
||||
bool useTransitAtStart = path.nextNode().layer == EPathfindingLayer::AIR || path.nextNode().layer == EPathfindingLayer::WATER;
|
||||
std::vector<int3> pathToMove;
|
||||
|
||||
for (auto const & node : boost::adaptors::reverse(path.nodes))
|
||||
{
|
||||
if (node.coord == h->visitablePos())
|
||||
continue; // first node, ignore - this is hero current position
|
||||
|
||||
if(node.isTeleportAction())
|
||||
break; // pause after monolith / subterra gates
|
||||
|
||||
if (node.turns != 0)
|
||||
break; // ran out of move points
|
||||
|
||||
bool useTransitHere = node.layer == EPathfindingLayer::AIR || node.layer == EPathfindingLayer::WATER;
|
||||
if (useTransitHere != useTransitAtStart)
|
||||
break;
|
||||
|
||||
int3 coord = h->convertFromVisitablePos(node.coord);
|
||||
pathToMove.push_back(coord);
|
||||
|
||||
if (LOCPLINT->cb->guardingCreaturePosition(node.coord) != int3(-1, -1, -1))
|
||||
break; // we reached zone-of-control of wandering monster
|
||||
|
||||
if (!LOCPLINT->cb->getVisitableObjs(node.coord).empty())
|
||||
break; // we reached event, garrison or some other visitable object - end this movement batch
|
||||
}
|
||||
|
||||
assert(!pathToMove.empty());
|
||||
if (!pathToMove.empty())
|
||||
{
|
||||
updateMovementSound(h, currNode.coord, nextNode.coord, nextNode.action);
|
||||
LOCPLINT->cb->moveHero(h, pathToMove, useTransitAtStart);
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,9 @@ class HeroMovementController
|
||||
|
||||
void updatePath(const CGHeroInstance * hero, const TryMoveHero & details);
|
||||
|
||||
/// Moves hero 1 tile / path node
|
||||
void moveOnce(const CGHeroInstance * h, const CGPath & path);
|
||||
/// Sends one request to server to move selected hero alongside path.
|
||||
/// Automatically selects between single-tile and multi-tile movement modes
|
||||
void sendMovementRequest(const CGHeroInstance * h, const CGPath & path);
|
||||
|
||||
void endMove(const CGHeroInstance * h);
|
||||
|
||||
|
@ -314,7 +314,7 @@ void AdventureMapShortcuts::visitObject()
|
||||
const CGHeroInstance *h = LOCPLINT->localState->getCurrentHero();
|
||||
|
||||
if(h)
|
||||
LOCPLINT->cb->moveHero(h, h->pos);
|
||||
LOCPLINT->cb->moveHero(h, h->pos, false);
|
||||
}
|
||||
|
||||
void AdventureMapShortcuts::openObject()
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/ColorFilter.h"
|
||||
#include "../render/Graphics.h"
|
||||
|
||||
#include "../battle/BattleInterface.h"
|
||||
#include "../battle/BattleInterfaceClasses.h"
|
||||
@ -177,7 +178,7 @@ CAnimImage::CAnimImage(const AnimationPath & name, size_t Frame, size_t Group, i
|
||||
{
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
anim = GH.renderHandler().loadAnimation(name);
|
||||
anim = graphics->getAnimation(name);
|
||||
init();
|
||||
}
|
||||
|
||||
|
@ -59,22 +59,23 @@ struct DLL_LINKAGE DismissHero : public CPackForServer
|
||||
struct DLL_LINKAGE MoveHero : public CPackForServer
|
||||
{
|
||||
MoveHero() = default;
|
||||
MoveHero(const int3 & Dest, const ObjectInstanceID & HID, bool Transit)
|
||||
: dest(Dest)
|
||||
MoveHero(const std::vector<int3> & path, const ObjectInstanceID & HID, bool Transit)
|
||||
: path(path)
|
||||
, hid(HID)
|
||||
, transit(Transit)
|
||||
{
|
||||
}
|
||||
int3 dest;
|
||||
std::vector<int3> path;
|
||||
ObjectInstanceID hid;
|
||||
bool transit = false;
|
||||
|
||||
void visitTyped(ICPackVisitor & visitor) override;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h)
|
||||
template<typename Handler>
|
||||
void serialize(Handler & h)
|
||||
{
|
||||
h & static_cast<CPackForServer &>(*this);
|
||||
h & dest;
|
||||
h & path;
|
||||
h & hid;
|
||||
h & transit;
|
||||
}
|
||||
|
@ -59,7 +59,17 @@ void ApplyGhNetPackVisitor::visitDismissHero(DismissHero & pack)
|
||||
void ApplyGhNetPackVisitor::visitMoveHero(MoveHero & pack)
|
||||
{
|
||||
gh.throwIfWrongOwner(&pack, pack.hid);
|
||||
result = gh.moveHero(pack.hid, pack.dest, 0, pack.transit, pack.player);
|
||||
|
||||
for (auto const & dest : pack.path)
|
||||
{
|
||||
if (!gh.moveHero(pack.hid, dest, 0, pack.transit, pack.player))
|
||||
{
|
||||
result = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
void ApplyGhNetPackVisitor::visitCastleTeleportHero(CastleTeleportHero & pack)
|
||||
|
Loading…
Reference in New Issue
Block a user