1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-10 22:31:40 +02:00

Remove pointer to boat from CGHeroInstance

This commit is contained in:
Ivan Savenko
2025-03-26 15:37:26 +00:00
parent 331debaa3f
commit 9e6397d1f9
24 changed files with 89 additions and 73 deletions

View File

@@ -124,7 +124,7 @@ void AIGateway::heroMoved(const TryMoveHero & details, bool verbose)
else if(details.result == TryMoveHero::EMBARK && hero)
{
//make sure AI not attempt to visit used boat
validateObject(hero->boat);
validateObject(hero->getBoat());
}
else if(details.result == TryMoveHero::DISEMBARK && o1)
{

View File

@@ -375,10 +375,10 @@ double getArtifactBonusRelevance(const CGHeroInstance * hero, const std::shared_
switch (bonus->type)
{
case BonusType::MOVEMENT:
if (hero->boat && bonus->subtype == BonusCustomSubtype::heroMovementSea)
if (hero->getBoat() && bonus->subtype == BonusCustomSubtype::heroMovementSea)
return veryRelevant;
if (!hero->boat && bonus->subtype == BonusCustomSubtype::heroMovementLand)
if (!hero->getBoat() && bonus->subtype == BonusCustomSubtype::heroMovementLand)
return relevant;
return notRelevant;
case BonusType::STACKS_SPEED:
@@ -395,9 +395,9 @@ double getArtifactBonusRelevance(const CGHeroInstance * hero, const std::shared_
return relevant; // spellpower / knowledge - always relevant
case BonusType::WATER_WALKING:
case BonusType::FLYING_MOVEMENT:
return hero->boat ? notRelevant : relevant; // boat can't fly
return hero->getBoat() ? notRelevant : relevant; // boat can't fly
case BonusType::WHIRLPOOL_PROTECTION:
return hero->boat ? relevant : notRelevant;
return hero->getBoat() ? relevant : notRelevant;
case BonusType::UNDEAD_RAISE_PERCENTAGE:
return hero->hasBonusOfType(BonusType::IMPROVED_NECROMANCY) ? veryRelevant : notRelevant;
case BonusType::SPELL_DAMAGE:

View File

@@ -22,10 +22,10 @@ void AIMemory::removeFromMemory(const CGObjectInstance * obj)
//TODO: Find better way to handle hero boat removal
if(auto hero = dynamic_cast<const CGHeroInstance *>(obj))
{
if(hero->boat)
if(hero->inBoat())
{
vstd::erase_if_present(visitableObjs, hero->boat);
vstd::erase_if_present(alreadyVisited, hero->boat);
vstd::erase_if_present(visitableObjs, hero->getBoat());
vstd::erase_if_present(alreadyVisited, hero->getBoat());
}
}
}

View File

@@ -23,7 +23,7 @@ StayAtTown::StayAtTown(const CGTownInstance * town, AIPath & path)
{
sethero(path.targetHero);
settown(town);
movementWasted = static_cast<float>(hero->movementPointsRemaining()) / hero->movementPointsLimit(!hero->boat) - path.movementCost();
movementWasted = static_cast<float>(hero->movementPointsRemaining()) / hero->movementPointsLimit(!hero->inBoat()) - path.movementCost();
vstd::amax(movementWasted, 0);
}

View File

@@ -969,7 +969,7 @@ void AINodeStorage::setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes)
if(actor->hero->tempOwner != ai->playerID)
{
bool onLand = !actor->hero->boat || actor->hero->boat->layer != EPathfindingLayer::SAIL;
bool onLand = !actor->hero->inBoat() || actor->hero->getBoat()->layer != EPathfindingLayer::SAIL;
actor->initialMovement = actor->hero->movementPointsLimit(onLand);
}

View File

@@ -43,7 +43,7 @@ ChainActor::ChainActor(const CGHeroInstance * hero, HeroRole heroRole, uint64_t
baseActor(this), carrierParent(nullptr), otherParent(nullptr), actorExchangeCount(1), armyCost(), actorAction()
{
initialPosition = hero->visitablePos();
layer = hero->boat ? hero->boat->layer : EPathfindingLayer::LAND;
layer = hero->inBoat() ? hero->getBoat()->layer : EPathfindingLayer::LAND;
initialMovement = hero->movementPointsRemaining();
initialTurn = 0;
armyValue = getHeroArmyStrengthWithCommander(hero, hero);

View File

@@ -298,7 +298,7 @@ void ObjectGraphCalculator::addObjectActor(const CGObjectInstance * obj)
if(cb->getTile(visitablePos)->isWater())
{
objectActor->boat = temporaryBoats.emplace_back(std::make_unique<CGBoat>(objectActor->cb)).get();
objectActor->setBoat(temporaryBoats.emplace_back(std::make_unique<CGBoat>(objectActor->cb)).get());
}
assert(objectActor->visitablePos() == visitablePos);
@@ -335,7 +335,7 @@ void ObjectGraphCalculator::addJunctionActor(const int3 & visitablePos, bool isV
if(isVirtualBoat || ai->cb->getTile(visitablePos)->isWater())
{
objectActor->boat = temporaryBoats.emplace_back(std::make_unique<CGBoat>(objectActor->cb)).get();
objectActor->setBoat(temporaryBoats.emplace_back(std::make_unique<CGBoat>(objectActor->cb)).get());
}
assert(objectActor->visitablePos() == visitablePos);

View File

@@ -111,7 +111,7 @@ std::optional<AIPathNode *> AINodeStorage::getOrCreateNode(const int3 & pos, con
std::vector<CGPathNode *> AINodeStorage::getInitialNodes()
{
auto hpos = hero->visitablePos();
auto initialNode = getOrCreateNode(hpos, hero->boat ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND, NORMAL_CHAIN).value();
auto initialNode = getOrCreateNode(hpos, hero->inBoat() ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND, NORMAL_CHAIN).value();
initialNode->turns = 0;
initialNode->moveRemains = hero->movementPointsRemaining();

View File

@@ -138,7 +138,7 @@ void VCAI::heroMoved(const TryMoveHero & details, bool verbose)
else if(details.result == TryMoveHero::EMBARK && hero)
{
//make sure AI not attempt to visit used boat
validateObject(hero->boat);
validateObject(hero->getBoat());
}
else if(details.result == TryMoveHero::DISEMBARK && o1)
{
@@ -448,13 +448,13 @@ void VCAI::objectRemoved(const CGObjectInstance * obj, const PlayerColor & initi
//TODO: Find better way to handle hero boat removal
if(auto hero = dynamic_cast<const CGHeroInstance *>(obj))
{
if(hero->boat)
if(hero->inBoat())
{
vstd::erase_if_present(visitableObjs, hero->boat);
vstd::erase_if_present(alreadyVisited, hero->boat);
vstd::erase_if_present(visitableObjs, hero->getBoat());
vstd::erase_if_present(alreadyVisited, hero->getBoat());
for(auto h : cb->getHeroesInfo())
unreserveObject(h, hero->boat);
unreserveObject(h, hero->getBoat());
}
}

View File

@@ -135,7 +135,7 @@ double MapRendererBaseContext::objectTransparency(ObjectInstanceID objectID, con
if(hero->isGarrisoned())
return 0;
if(hero->boat)
if(hero->inBoat())
return 0;
}
return 1;

View File

@@ -372,8 +372,8 @@ void MapViewController::fadeOutObject(const CGObjectInstance * obj)
if (obj->ID == Obj::HERO)
{
auto * hero = dynamic_cast<const CGHeroInstance*>(obj);
if (hero->boat)
movingObject = hero->boat;
if (hero->inBoat())
movingObject = hero->getBoat();
}
fadingOutContext->target = movingObject->id;
@@ -393,8 +393,8 @@ void MapViewController::fadeInObject(const CGObjectInstance * obj)
if (obj->ID == Obj::HERO)
{
auto * hero = dynamic_cast<const CGHeroInstance*>(obj);
if (hero->boat)
movingObject = hero->boat;
if (hero->inBoat())
movingObject = hero->getBoat();
}
fadingInContext->target = movingObject->id;
@@ -416,10 +416,10 @@ void MapViewController::removeObject(const CGObjectInstance * obj)
if (obj->ID == Obj::HERO)
{
auto * hero = dynamic_cast<const CGHeroInstance*>(obj);
if (hero->boat)
if (hero->inBoat())
{
view->invalidate(context, hero->boat->id);
state->removeObject(hero->boat);
view->invalidate(context, hero->getBoat()->id);
state->removeObject(hero->getBoat());
}
}
@@ -514,8 +514,8 @@ void MapViewController::onAfterHeroTeleported(const CGHeroInstance * obj, const
assert(!hasOngoingAnimations());
const CGObjectInstance * movingObject = obj;
if(obj->boat)
movingObject = obj->boat;
if(obj->inBoat())
movingObject = obj->getBoat();
removeObject(movingObject);
addObject(movingObject);
@@ -541,8 +541,8 @@ void MapViewController::onHeroMoved(const CGHeroInstance * obj, const int3 & fro
return;
const CGObjectInstance * movingObject = obj;
if(obj->boat)
movingObject = obj->boat;
if(obj->inBoat())
movingObject = obj->getBoat();
removeObject(movingObject);

View File

@@ -610,7 +610,7 @@ void CGameState::initHeroes()
boat->setAnchorPos(hero->anchorPos());
boat->appearance = handler->getTemplates().front();
map->addNewObject(boat);
hero->attachToBoat(boat.get());
hero->setBoat(boat.get());
}
}

View File

@@ -586,7 +586,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
if (cb->gameState()->getMap().getTile(boatPos).isWater())
{
smp.val = movementPointsLimit(false);
if (!boat)
if (!inBoat())
{
//Create a new boat for hero
cb->createBoat(boatPos, getBoatType(), h->getOwner());
@@ -635,7 +635,7 @@ std::string CGHeroInstance::getMovementPointsTextIfOwner(PlayerColor player) con
if(player == getOwner())
{
output += " " + LIBRARY->generaltexth->translate("vcmi.adventureMap.movementPointsHeroInfo");
boost::replace_first(output, "%POINTS", std::to_string(movementPointsLimit(!boat)));
boost::replace_first(output, "%POINTS", std::to_string(movementPointsLimit(!inBoat())));
boost::replace_first(output, "%REMAINING", std::to_string(movementPointsRemaining()));
}
@@ -1295,10 +1295,22 @@ int CGHeroInstance::maxSpellLevel() const
return std::min(GameConstants::SPELL_LEVELS, valOfBonuses(BonusType::MAX_LEARNABLE_SPELL_LEVEL));
}
void CGHeroInstance::attachToBoat(CGBoat* newBoat)
bool CGHeroInstance::inBoat() const
{
return boardedBoat.hasValue();
}
const CGBoat * CGHeroInstance::getBoat() const
{
if (boardedBoat.hasValue())
return dynamic_cast<const CGBoat*>(cb->getObjInstance(boardedBoat));
return nullptr;
}
void CGHeroInstance::setBoat(CGBoat* newBoat)
{
assert(newBoat);
boat = newBoat;
boardedBoat = newBoat->id;
attachTo(*newBoat);
newBoat->setBoardedHero(this);
}
@@ -1311,8 +1323,9 @@ void CGHeroInstance::deserializationFix()
void CGHeroInstance::boatDeserializationFix()
{
auto boat = cb->gameState()->getObjInstance(boardedBoat);
if (boat)
attachTo(const_cast<CGBoat&>(*boat));
attachTo(dynamic_cast<CGBoat&>(*boat));
}
CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(const bool isBattleOutsideTown) const
@@ -1351,7 +1364,7 @@ int CGHeroInstance::movementPointsAfterEmbark(int MPsBefore, int basicCost, bool
if(!ti->hasFreeShipBoarding())
return 0; // take all MPs by default
auto boatLayer = boat ? boat->layer : EPathfindingLayer::SAIL;
auto boatLayer = inBoat() ? getBoat()->layer : EPathfindingLayer::SAIL;
int mp1 = ti->getMaxMovePoints(disembark ? EPathfindingLayer::LAND : boatLayer);
int mp2 = ti->getMaxMovePoints(disembark ? boatLayer : EPathfindingLayer::LAND);

View File

@@ -69,6 +69,8 @@ private:
std::set<SpellID> spells; //known spells (spell IDs)
ObjectInstanceID visitedTown; //set if hero is visiting town or in the town garrison
ObjectInstanceID boardedBoat; //set to CGBoat when sailing
ui32 movement; //remaining movement points
bool inTownGarrison; // if hero is in town garrison
@@ -94,8 +96,6 @@ public:
std::string nameCustomTextId;
std::string biographyCustomTextId;
const CGBoat * boat = nullptr; //set to CGBoat when sailing
static constexpr si32 UNINITIALIZED_MANA = -1;
static constexpr ui32 UNINITIALIZED_MOVEMENT = -1;
static constexpr auto UNINITIALIZED_EXPERIENCE = std::numeric_limits<TExpType>::max();
@@ -160,6 +160,10 @@ public:
std::string getClassNameTranslated() const;
std::string getClassNameTextID() const;
bool inBoat() const;
const CGBoat * getBoat() const;
void setBoat(CGBoat * getBoat);
bool hasSpellbook() const;
int maxSpellLevel() const;
void addSpellToSpellbook(const SpellID & spell);
@@ -313,7 +317,6 @@ public:
void getCastDescription(const spells::Spell * spell, const battle::Units & attacked, MetaString & text) const override;
void spendMana(ServerCallback * server, const int spellCost) const override;
void attachToBoat(CGBoat* newBoat);
void boatDeserializationFix();
void deserializationFix();
void updateAppearance();
@@ -373,7 +376,7 @@ public:
h & moveDir;
h & skillsInfo;
h & visitedTown;
h & boat;
h & boardedBoat;
h & commander;
h & visitedObjects;
BONUS_TREE_DESERIALIZATION_FIX

View File

@@ -1226,11 +1226,11 @@ void RemoveObject::applyGs(CGameState *gs)
gs->heroesPool->addHeroToPool(beatenHero->getHeroTypeID());
//If hero on Boat is removed, the Boat disappears
if(beatenHero->boat)
if(beatenHero->inBoat())
{
beatenHero->detachFrom(const_cast<CGBoat&>(*beatenHero->boat));
gs->getMap().eraseObject(beatenHero->boat->id);
beatenHero->boat = nullptr;
beatenHero->detachFrom(const_cast<CGBoat&>(*beatenHero->getBoat()));
gs->getMap().eraseObject(beatenHero->getBoat()->id);
beatenHero->setBoat(nullptr);
}
return;
}
@@ -1321,26 +1321,26 @@ void TryMoveHero::applyGs(CGameState *gs)
assert(boat);
gs->getMap().removeBlockVisTiles(boat); //hero blockvis mask will be used, we don't need to duplicate it with boat
h->boat = boat;
h->setBoat(boat);
h->attachTo(*boat);
boat->setBoardedHero(h);
}
else if(result == DISEMBARK) //hero leaves boat to destination tile
{
auto * b = const_cast<CGBoat *>(h->boat);
auto * b = const_cast<CGBoat *>(h->getBoat());
b->direction = h->moveDir;
b->pos = start;
b->setBoardedHero(nullptr);
gs->getMap().addBlockVisTiles(b);
h->detachFrom(*b);
h->boat = nullptr;
h->setBoat(nullptr);
}
if(start!=end && (result == SUCCESS || result == TELEPORTATION || result == EMBARK || result == DISEMBARK))
{
gs->getMap().removeBlockVisTiles(h);
h->pos = end;
if(auto * b = const_cast<CGBoat *>(h->boat))
if(auto * b = const_cast<CGBoat *>(h->getBoat()))
b->pos = end;
gs->getMap().addBlockVisTiles(h);
}
@@ -1429,7 +1429,7 @@ void HeroRecruited::applyGs(CGameState *gs)
if (boat)
{
gs->getMap().removeBlockVisTiles(boat);
h->attachToBoat(boat);
h->setBoat(boat);
}
}
@@ -1463,7 +1463,7 @@ void GiveHero::applyGs(CGameState *gs)
if (boat)
{
gs->getMap().removeBlockVisTiles(boat);
h->attachToBoat(boat);
h->setBoat(boat);
}
}

View File

@@ -649,17 +649,17 @@ int CPathfinderHelper::getMovementCost(
bool isSailLayer;
if(indeterminate(isDstSailLayer))
isSailLayer = hero->boat && hero->boat->layer == EPathfindingLayer::SAIL && dt->isWater();
isSailLayer = hero->inBoat() && hero->getBoat()->layer == EPathfindingLayer::SAIL && dt->isWater();
else
isSailLayer = static_cast<bool>(isDstSailLayer);
bool isWaterLayer;
if(indeterminate(isDstWaterLayer))
isWaterLayer = ((hero->boat && hero->boat->layer == EPathfindingLayer::WATER) || ti->hasWaterWalking()) && dt->isWater();
isWaterLayer = ((hero->inBoat() && hero->getBoat()->layer == EPathfindingLayer::WATER) || ti->hasWaterWalking()) && dt->isWater();
else
isWaterLayer = static_cast<bool>(isDstWaterLayer);
bool isAirLayer = (hero->boat && hero->boat->layer == EPathfindingLayer::AIR) || ti->hasFlyingMovement();
bool isAirLayer = (hero->inBoat() && hero->getBoat()->layer == EPathfindingLayer::AIR) || ti->hasFlyingMovement();
int movementCost = getTileMovementCost(*dt, *ct, ti);
if(isSailLayer)

View File

@@ -126,7 +126,7 @@ void NodeStorage::resetTile(const int3 & tile, const EPathfindingLayer & layer,
std::vector<CGPathNode *> NodeStorage::getInitialNodes()
{
auto * initialNode = getNode(out.hpos, out.hero->boat ? out.hero->boat->layer : EPathfindingLayer::LAND);
auto * initialNode = getNode(out.hpos, out.hero->inBoat() ? out.hero->getBoat()->layer : EPathfindingLayer::LAND);
initialNode->turns = 0;
initialNode->moveRemains = out.hero->movementPointsRemaining();

View File

@@ -184,7 +184,7 @@ bool TurnInfo::isLayerAvailable(const EPathfindingLayer & layer) const
switch(layer.toEnum())
{
case EPathfindingLayer::AIR:
if(target && target->boat && target->boat->layer == EPathfindingLayer::AIR)
if(target && target->inBoat() && target->getBoat()->layer == EPathfindingLayer::AIR)
break;
if(!hasFlyingMovement())
@@ -193,7 +193,7 @@ bool TurnInfo::isLayerAvailable(const EPathfindingLayer & layer) const
break;
case EPathfindingLayer::WATER:
if(target && target->boat && target->boat->layer == EPathfindingLayer::WATER)
if(target && target->inBoat() && target->getBoat()->layer == EPathfindingLayer::WATER)
break;
if(!hasWaterWalking())

View File

@@ -145,7 +145,7 @@ void Rewardable::Interface::grantRewardAfterLevelup(const Rewardable::VisitInfo
smp.val = hero->movementPointsRemaining();
if (info.reward.movePercentage >= 0) // percent from max
smp.val = hero->movementPointsLimit(hero->boat && hero->boat->layer == EPathfindingLayer::SAIL) * info.reward.movePercentage / 100;
smp.val = hero->movementPointsLimit(hero->inBoat() && hero->getBoat()->layer == EPathfindingLayer::SAIL) * info.reward.movePercentage / 100;
smp.val = std::max<si32>(0, smp.val + info.reward.movePoints);
cb->setMovePoints(&smp);

View File

@@ -162,7 +162,7 @@ bool SummonBoatMechanics::canBeCastImpl(spells::Problem & problem, const CGameIn
if(!caster->getHeroCaster())
return false;
if(caster->getHeroCaster()->boat)
if(caster->getHeroCaster()->inBoat())
{
MetaString message = MetaString::createFromTextID("core.genrltxt.333");
caster->getCasterName(message);

View File

@@ -306,7 +306,7 @@ ObjectRect::~ObjectRect()
std::shared_ptr<QImage> MapHandler::findFlagBitmap(const CGHeroInstance * hero, int anim, const PlayerColor color, int group) const
{
if(!hero || hero->boat)
if(!hero || hero->inBoat())
return std::shared_ptr<QImage>();
return findFlagBitmapInternal(graphics->heroFlagAnimations.at(color.getNum()), anim, group, hero->moveDir, true);

View File

@@ -837,10 +837,10 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
}
}
const bool embarking = !h->boat && objectToVisit && objectToVisit->ID == Obj::BOAT;
const bool disembarking = h->boat
const bool embarking = !h->inBoat() && objectToVisit && objectToVisit->ID == Obj::BOAT;
const bool disembarking = h->inBoat()
&& t.isLand()
&& (dst == h->pos || (h->boat->layer == EPathfindingLayer::SAIL && !t.blocked()));
&& (dst == h->pos || (h->getBoat()->layer == EPathfindingLayer::SAIL && !t.blocked()));
//result structure for start - movement failed, no move points used
TryMoveHero tmh;
@@ -854,13 +854,13 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
auto pathfinderHelper = std::make_unique<CPathfinderHelper>(gameState(), h, PathfinderOptions(this));
auto ti = pathfinderHelper->getTurnInfo();
const bool canFly = ti->hasFlyingMovement() || (h->boat && h->boat->layer == EPathfindingLayer::AIR);
const bool canWalkOnSea = ti->hasWaterWalking() || (h->boat && h->boat->layer == EPathfindingLayer::WATER);
const bool canFly = ti->hasFlyingMovement() || (h->inBoat() && h->getBoat()->layer == EPathfindingLayer::AIR);
const bool canWalkOnSea = ti->hasWaterWalking() || (h->inBoat() && h->getBoat()->layer == EPathfindingLayer::WATER);
const int cost = pathfinderHelper->getMovementCost(h->visitablePos(), hmpos, nullptr, nullptr, h->movementPointsRemaining());
const bool movingOntoObstacle = t.blocked() && !t.visitable();
const bool objectCoastVisitable = objectToVisit && objectToVisit->isCoastVisitable();
const bool movingOntoWater = !h->boat && t.isWater() && !objectCoastVisitable;
const bool movingOntoWater = !h->inBoat() && t.isWater() && !objectCoastVisitable;
const auto complainRet = [&](const std::string & message)
{
@@ -891,7 +891,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
if(movingOntoWater && !canFly && !canWalkOnSea)
return complainRet("Cannot move hero, destination tile is on water!");
if(h->boat && h->boat->layer == EPathfindingLayer::SAIL && t.isLand() && t.blocked())
if(h->inBoat() && h->getBoat()->layer == EPathfindingLayer::SAIL && t.isLand() && t.blocked())
return complainRet("Cannot disembark hero, tile is blocked!");
if(distance(h->pos, dst) >= 1.5 && movementMode == EMovementMode::STANDARD)
@@ -961,13 +961,13 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
{
const CGObjectInstance * object = getObj(objectID);
if(h->boat && !object->isBlockedVisitable() && !h->boat->onboardVisitAllowed)
if(h->inBoat() && !object->isBlockedVisitable() && !h->getBoat()->onboardVisitAllowed)
return doMove(TryMoveHero::SUCCESS, this->IGNORE_GUARDS, DONT_VISIT_DEST, REMAINING_ON_TILE);
if (object != h && object->isBlockedVisitable() && !object->passableFor(h->tempOwner))
{
EVisitDest visitDest = VISIT_DEST;
if(h->boat && !h->boat->onboardVisitAllowed)
if(h->inBoat() && !h->getBoat()->onboardVisitAllowed)
visitDest = DONT_VISIT_DEST;
return doMove(TryMoveHero::BLOCKING_VISIT, this->IGNORE_GUARDS, visitDest, REMAINING_ON_TILE);
@@ -1035,7 +1035,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
else if (blockingVisit())
return true;
if(h->boat && !h->boat->onboardAssaultAllowed)
if(h->getBoat() && !h->getBoat()->onboardAssaultAllowed)
lookForGuards = IGNORE_GUARDS;
turnTimerHandler->setEndTurnAllowed(h->getOwner(), !movingOntoWater && !movingOntoObstacle);

View File

@@ -170,7 +170,7 @@ BattleID BattleProcessor::setupBattle(int3 tile, BattleSideArray<const CArmedIns
const TerrainType* terrainData = LIBRARY->terrainTypeHandler->getById(terrain);
battlefieldType = BattleField(*RandomGeneratorUtil::nextItem(terrainData->battleFields, gameHandler->getRandomGenerator()));
}
else if (heroes[BattleSide::ATTACKER] && heroes[BattleSide::ATTACKER]->boat && heroes[BattleSide::DEFENDER] && heroes[BattleSide::DEFENDER]->boat)
else if (heroes[BattleSide::ATTACKER] && heroes[BattleSide::ATTACKER]->inBoat() && heroes[BattleSide::DEFENDER] && heroes[BattleSide::DEFENDER]->inBoat())
battlefieldType = BattleField(*LIBRARY->identifiers()->getIdentifier("core", "battlefield.ship_to_ship"));
//send info about battles

View File

@@ -225,7 +225,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy
hr.hid = recruitedHero->getHeroTypeID();
hr.player = player;
hr.tile = recruitedHero->convertFromVisitablePos(targetPos );
if(gameHandler->getTile(targetPos)->isWater() && !recruitedHero->boat)
if(gameHandler->getTile(targetPos)->isWater() && !recruitedHero->inBoat())
{
//Create a new boat for hero
gameHandler->createBoat(targetPos, recruitedHero->getBoatType(), player);