mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Implemented support for "coast visitable" objects:
- objects marked as coast visitable can be visited from land even when placed in water - added isBlockedVisitable and isCoastVisitable method to CGObjectInstance - implemented json config for these properties in banks
This commit is contained in:
parent
a84ccb37c2
commit
f7b27da00e
@ -266,7 +266,7 @@ bool isBlockVisitObj(const int3 & pos)
|
||||
{
|
||||
if(auto obj = cb->getTopObj(pos))
|
||||
{
|
||||
if(obj->blockVisit) //we can't stand on that object
|
||||
if(obj->isBlockedVisitable()) //we can't stand on that object
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ bool isBlockVisitObj(const int3 & pos)
|
||||
{
|
||||
if(auto obj = cb->getTopObj(pos))
|
||||
{
|
||||
if(obj->blockVisit) //we can't stand on that object
|
||||
if(obj->isBlockedVisitable()) //we can't stand on that object
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -155,7 +155,7 @@ namespace Goals
|
||||
|
||||
// picking up resources does not yield any exploration at all.
|
||||
// if it blocks the way to some explorable tile AIPathfinder will take care of it
|
||||
if(obj && obj->blockVisit)
|
||||
if(obj && obj->isBlockedVisitable())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -640,6 +640,8 @@
|
||||
"shipwreck" : {
|
||||
"index" : 0,
|
||||
"resetDuration" : 0,
|
||||
"blockedVisitable" : true,
|
||||
"coastVisitable" : true,
|
||||
"name" : "Shipwreck",
|
||||
"aiValue" : 2000,
|
||||
"rmg" : {
|
||||
@ -732,6 +734,7 @@
|
||||
"derelictShip" : {
|
||||
"index" : 0,
|
||||
"resetDuration" : 0,
|
||||
"blockedVisitable" : true,
|
||||
"name" : "Derelict Ship",
|
||||
"aiValue" : 4000,
|
||||
"rmg" : {
|
||||
|
@ -1900,7 +1900,7 @@ std::vector<CGObjectInstance*> CGameState::guardingCreatures (int3 pos) const
|
||||
{
|
||||
for (CGObjectInstance* obj : posTile.visitableObjects)
|
||||
{
|
||||
if(obj->blockVisit)
|
||||
if(obj->isBlockedVisitable())
|
||||
{
|
||||
if (obj->ID == Obj::MONSTER) // Monster
|
||||
guards.push_back(obj);
|
||||
|
@ -30,6 +30,8 @@ void CBankInstanceConstructor::initTypeData(const JsonNode & input)
|
||||
|
||||
levels = input["levels"].Vector();
|
||||
bankResetDuration = static_cast<si32>(input["resetDuration"].Float());
|
||||
blockVisit = input["blockedVisitable"].Bool();
|
||||
coastVisitable = input["coastVisitable"].Bool();
|
||||
}
|
||||
|
||||
BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRandomGenerator & rng) const
|
||||
@ -58,6 +60,8 @@ BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRan
|
||||
void CBankInstanceConstructor::randomizeObject(CBank * bank, CRandomGenerator & rng) const
|
||||
{
|
||||
bank->resetDuration = bankResetDuration;
|
||||
bank->blockVisit = blockVisit;
|
||||
bank->coastVisitable = coastVisitable;
|
||||
|
||||
si32 totalChance = 0;
|
||||
for(const auto & node : levels)
|
||||
|
@ -80,12 +80,18 @@ class CBankInstanceConstructor : public CDefaultObjectTypeHandler<CBank>
|
||||
BankConfig generateConfig(const JsonNode & conf, CRandomGenerator & rng) const;
|
||||
|
||||
JsonVector levels;
|
||||
|
||||
// all banks of this type will be reset N days after clearing,
|
||||
si32 bankResetDuration = 0;
|
||||
|
||||
// bank is only visitable from adjacent tile
|
||||
bool blockVisit;
|
||||
// bank is visitable from land even when bank is on water tile
|
||||
bool coastVisitable;
|
||||
protected:
|
||||
void initTypeData(const JsonNode & input) override;
|
||||
|
||||
public:
|
||||
// all banks of this type will be reset N days after clearing,
|
||||
si32 bankResetDuration = 0;
|
||||
|
||||
void randomizeObject(CBank * object, CRandomGenerator & rng) const override;
|
||||
|
||||
@ -97,6 +103,8 @@ public:
|
||||
{
|
||||
h & levels;
|
||||
h & bankResetDuration;
|
||||
h & blockVisit;
|
||||
h & coastVisitable;
|
||||
h & static_cast<CDefaultObjectTypeHandler<CBank>&>(*this);
|
||||
}
|
||||
};
|
||||
|
@ -43,6 +43,11 @@ void CBank::initObj(CRandomGenerator & rand)
|
||||
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand);
|
||||
}
|
||||
|
||||
bool CBank::isCoastVisitable() const
|
||||
{
|
||||
return coastVisitable;
|
||||
}
|
||||
|
||||
std::string CBank::getHoverText(PlayerColor player) const
|
||||
{
|
||||
// TODO: record visited players
|
||||
|
@ -21,6 +21,7 @@ class DLL_LINKAGE CBank : public CArmedInstance
|
||||
std::unique_ptr<BankConfig> bc;
|
||||
ui32 daycounter;
|
||||
ui32 resetDuration;
|
||||
bool coastVisitable;
|
||||
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
void doVisit(const CGHeroInstance * hero) const;
|
||||
@ -35,6 +36,7 @@ public:
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
void newTurn(CRandomGenerator & rand) const override;
|
||||
bool wasVisited (PlayerColor player) const override;
|
||||
bool isCoastVisitable() const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
@ -45,6 +47,7 @@ public:
|
||||
h & daycounter;
|
||||
h & bc;
|
||||
h & resetDuration;
|
||||
h & coastVisitable;
|
||||
}
|
||||
|
||||
friend class CBankInstanceConstructor;
|
||||
|
@ -122,6 +122,11 @@ TerrainId CGHeroInstance::getNativeTerrain() const
|
||||
return nativeTerrain;
|
||||
}
|
||||
|
||||
bool CGHeroInstance::isCoastVisitable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
BattleField CGHeroInstance::getBattlefield() const
|
||||
{
|
||||
return BattleField::NONE;
|
||||
|
@ -286,6 +286,7 @@ public:
|
||||
|
||||
void updateFrom(const JsonNode & data) override;
|
||||
|
||||
bool isCoastVisitable() const override;
|
||||
BattleField getBattlefield() const override;
|
||||
protected:
|
||||
void setPropertyDer(ui8 what, ui32 val) override;//synchr
|
||||
|
@ -282,6 +282,16 @@ bool CGObjectInstance::isVisitable() const
|
||||
return appearance->isVisitable();
|
||||
}
|
||||
|
||||
bool CGObjectInstance::isBlockedVisitable() const
|
||||
{
|
||||
return blockVisit;
|
||||
}
|
||||
|
||||
bool CGObjectInstance::isCoastVisitable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CGObjectInstance::passableFor(PlayerColor color) const
|
||||
{
|
||||
return false;
|
||||
|
@ -34,8 +34,6 @@ public:
|
||||
ObjectInstanceID id;
|
||||
/// Defines appearance of object on map (animation, blocked tiles, blit order, etc)
|
||||
std::shared_ptr<const ObjectTemplate> appearance;
|
||||
/// If true hero can visit this object only from neighbouring tiles and can't stand on this object
|
||||
bool blockVisit;
|
||||
|
||||
std::string instanceName;
|
||||
std::string typeName;
|
||||
@ -49,6 +47,8 @@ public:
|
||||
|
||||
/// "center" tile from which the sight distance is calculated
|
||||
int3 getSightCenter() const;
|
||||
/// If true hero can visit this object only from neighbouring tiles and can't stand on this object
|
||||
bool blockVisit;
|
||||
|
||||
PlayerColor getOwner() const override
|
||||
{
|
||||
@ -68,7 +68,15 @@ public:
|
||||
bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) (h3m pos)
|
||||
std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object
|
||||
std::set<int3> getBlockedOffsets() const; //returns set of relative positions blocked by this object
|
||||
bool isVisitable() const; //returns true if object is visitable
|
||||
|
||||
/// returns true if object is visitable
|
||||
bool isVisitable() const;
|
||||
|
||||
/// If true hero can visit this object only from neighbouring tiles and can't stand on this object
|
||||
virtual bool isBlockedVisitable() const;
|
||||
|
||||
/// If true this object can be visited by hero standing on the coast
|
||||
virtual bool isCoastVisitable() const;
|
||||
|
||||
virtual BattleField getBattlefield() const;
|
||||
|
||||
|
@ -246,7 +246,6 @@ public:
|
||||
{
|
||||
h & static_cast<IQuestObject&>(*this);
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & blockVisit;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1294,6 +1294,11 @@ CGBoat::CGBoat()
|
||||
layer = EPathfindingLayer::EEPathfindingLayer::SAIL;
|
||||
}
|
||||
|
||||
bool CGBoat::isCoastVisitable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGSirens::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = true;
|
||||
|
@ -359,6 +359,7 @@ public:
|
||||
std::array<std::string, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
|
||||
|
||||
CGBoat();
|
||||
bool isCoastVisitable() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -313,7 +313,7 @@ int3 CMap::guardingCreaturePosition (int3 pos) const
|
||||
{
|
||||
for (CGObjectInstance* obj : posTile.visitableObjects)
|
||||
{
|
||||
if(obj->blockVisit)
|
||||
if(obj->isBlockedVisitable())
|
||||
{
|
||||
if (obj->ID == Obj::MONSTER) // Monster
|
||||
return pos;
|
||||
|
@ -42,7 +42,7 @@ namespace PathfinderUtil
|
||||
{
|
||||
for(const CGObjectInstance * obj : tinfo.visitableObjects)
|
||||
{
|
||||
if(obj->blockVisit)
|
||||
if(obj->isBlockedVisitable())
|
||||
return EPathAccessibility::BLOCKVIS;
|
||||
else if(obj->passableFor(player))
|
||||
return EPathAccessibility::ACCESSIBLE;
|
||||
|
@ -157,7 +157,7 @@ void DestinationActionRule::process(
|
||||
}
|
||||
else if(destination.isGuardianTile)
|
||||
action = EPathNodeAction::BATTLE;
|
||||
else if(destination.nodeObject->blockVisit && !(pathfinderConfig->options.useCastleGate && destination.nodeObject->ID == Obj::TOWN))
|
||||
else if(destination.nodeObject->isBlockedVisitable() && !(pathfinderConfig->options.useCastleGate && destination.nodeObject->ID == Obj::TOWN))
|
||||
action = EPathNodeAction::BLOCKING_VISIT;
|
||||
|
||||
if(action == EPathNodeAction::NORMAL)
|
||||
@ -301,7 +301,7 @@ PathfinderBlockingRule::BlockingReason MovementToDestinationRule::getBlockingRea
|
||||
if(!destination.isNodeObjectVisitable())
|
||||
return BlockingReason::DESTINATION_BLOCKED;
|
||||
|
||||
if(destination.nodeObject->ID != Obj::BOAT && !destination.nodeHero)
|
||||
if(!destination.nodeHero && !destination.nodeObject->isCoastVisitable())
|
||||
return BlockingReason::DESTINATION_BLOCKED;
|
||||
}
|
||||
else if(destination.isNodeObjectVisitable() && destination.nodeObject->ID == Obj::BOAT)
|
||||
|
@ -2294,7 +2294,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
|
||||
//OR hero is on land and dest is water and (there is not present only one object - boat)
|
||||
if (((!t.terType->isPassable() || (t.blocked && !t.visitable && !canFly))
|
||||
&& complain("Cannot move hero, destination tile is blocked!"))
|
||||
|| ((!h->boat && !canWalkOnSea && !canFly && t.terType->isWater() && (t.visitableObjects.size() < 1 || (t.visitableObjects.back()->ID != Obj::BOAT && t.visitableObjects.back()->ID != Obj::HERO))) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276)
|
||||
|| ((!h->boat && !canWalkOnSea && !canFly && t.terType->isWater() && (t.visitableObjects.size() < 1 || !t.visitableObjects.back()->isCoastVisitable())) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276)
|
||||
&& complain("Cannot move hero, destination tile is on water!"))
|
||||
|| ((h->boat && h->boat->layer == EPathfindingLayer::SAIL && t.terType->isLand() && t.blocked)
|
||||
&& complain("Cannot disembark hero, tile is blocked!"))
|
||||
@ -2369,10 +2369,10 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
|
||||
{
|
||||
for (CGObjectInstance *obj : t.visitableObjects)
|
||||
{
|
||||
if(h->boat && !obj->blockVisit && !h->boat->onboardVisitAllowed)
|
||||
if(h->boat && !obj->isBlockedVisitable() && !h->boat->onboardVisitAllowed)
|
||||
return doMove(TryMoveHero::SUCCESS, this->IGNORE_GUARDS, DONT_VISIT_DEST, REMAINING_ON_TILE);
|
||||
|
||||
if (obj != h && obj->blockVisit && !obj->passableFor(h->tempOwner))
|
||||
if (obj != h && obj->isBlockedVisitable() && !obj->passableFor(h->tempOwner))
|
||||
{
|
||||
EVisitDest visitDest = VISIT_DEST;
|
||||
if(h->boat && !h->boat->onboardVisitAllowed)
|
||||
|
Loading…
Reference in New Issue
Block a user