1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

vcmi: slightly rework limiters

1. Add vector to aggregates
2. Rework CreatureFactionLimiter to FactionLimiter
This commit is contained in:
Konstantin 2023-04-09 04:36:16 +03:00
parent 7326980bd4
commit dd196f2aa8
7 changed files with 75 additions and 36 deletions

View File

@ -569,9 +569,9 @@ void CTownHandler::loadSpecialBuildingBonuses(const JsonNode & source, BonusList
if(bonus->limiter != nullptr)
{
auto * limPtr = dynamic_cast<CreatureFactionLimiter *>(bonus->limiter.get());
auto * limPtr = dynamic_cast<FactionLimiter *>(bonus->limiter.get());
if(limPtr != nullptr && limPtr->faction == FactionID::ANY)
if(limPtr != nullptr && limPtr->faction == FactionID::DEFAULT)
limPtr->faction = building->town->faction->getId();
}
//JsonUtils::parseBuildingBonus produces UNKNOWN type propagator instead of empty.

View File

@ -188,7 +188,7 @@ std::string PlayerColor::getStrCap(bool L10n) const
}
const FactionID FactionID::NONE = FactionID(-2);
const FactionID FactionID::ANY = FactionID(-1);
const FactionID FactionID::DEFAULT = FactionID(-1);
const FactionID FactionID::CASTLE = FactionID(0);
const FactionID FactionID::RAMPART = FactionID(1);
const FactionID FactionID::TOWER = FactionID(2);
@ -206,7 +206,7 @@ si32 FactionID::decode(const std::string & identifier)
if(rawId)
return rawId.get();
else
return FactionID::ANY;
return FactionID::DEFAULT;
}
std::string FactionID::encode(const si32 index)

View File

@ -443,7 +443,7 @@ class FactionID : public BaseForID<FactionID, int32_t>
INSTID_LIKE_CLASS_COMMON(FactionID, si32)
DLL_LINKAGE static const FactionID NONE;
DLL_LINKAGE static const FactionID ANY;
DLL_LINKAGE static const FactionID DEFAULT;
DLL_LINKAGE static const FactionID CASTLE;
DLL_LINKAGE static const FactionID RAMPART;
DLL_LINKAGE static const FactionID TOWER;

View File

@ -75,7 +75,8 @@ const std::map<std::string, TLimiterPtr> bonusLimiterMap =
{"DRAGON_NATURE", std::make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)},
{"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)},
{"CREATURE_NATIVE_TERRAIN", std::make_shared<CreatureTerrainLimiter>()},
{"CREATURE_FACTION", std::make_shared<CreatureFactionLimiter>()},
{"CREATURE_FACTION", std::make_shared<AllOfLimiter>(std::initializer_list<TLimiterPtr>{std::make_shared<CreatureLevelLimiter>(), std::make_shared<FactionLimiter>()})},
{"SAME_FACTION", std::make_shared<FactionLimiter>()},
{"CREATURES_ONLY", std::make_shared<CreatureLevelLimiter>()},
{"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()},
};
@ -2366,30 +2367,46 @@ JsonNode CreatureTerrainLimiter::toJsonNode() const
return root;
}
CreatureFactionLimiter::CreatureFactionLimiter(FactionID creatureFaction)
FactionLimiter::FactionLimiter(FactionID creatureFaction)
: faction(creatureFaction)
{
}
ILimiter::EDecision CreatureFactionLimiter::limit(const BonusLimitationContext &context) const
ILimiter::EDecision FactionLimiter::limit(const BonusLimitationContext &context) const
{
const CCreature *c = retrieveCreature(&context.node);
auto accept = c && (c->getFactionIndex() == faction || faction == FactionID::ANY);
return accept ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; //drop bonus for non-creatures or non-native residents
const auto * bearer = dynamic_cast<const INativeTerrainProvider*>(&context.node);
if(bearer)
{
if(faction != FactionID::DEFAULT)
return bearer->getFaction() == faction ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
switch(context.b->source)
{
case Bonus::CREATURE_ABILITY:
return faction == CreatureID(context.b->sid).toCreature()->getFaction() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
case Bonus::TOWN_STRUCTURE:
return faction == FactionID(Bonus::getHighFromSid32(context.b->sid)) ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
//TODO: other sources of bonuses
}
}
return ILimiter::EDecision::DISCARD; //Discard by default
}
std::string CreatureFactionLimiter::toString() const
std::string FactionLimiter::toString() const
{
boost::format fmt("CreatureFactionLimiter(faction=%s)");
boost::format fmt("FactionLimiter(faction=%s)");
fmt % VLC->factions()->getByIndex(faction)->getJsonKey();
return fmt.str();
}
JsonNode CreatureFactionLimiter::toJsonNode() const
JsonNode FactionLimiter::toJsonNode() const
{
JsonNode root(JsonNode::JsonType::DATA_STRUCT);
root["type"].String() = "CREATURE_FACTION_LIMITER";
root["type"].String() = "FACTION_LIMITER";
root["parameters"].Vector().push_back(JsonUtils::stringNode(VLC->factions()->getByIndex(faction)->getJsonKey()));
return root;
@ -2498,23 +2515,13 @@ ILimiter::EDecision StackOwnerLimiter::limit(const BonusLimitationContext &conte
return ILimiter::EDecision::DISCARD;
}
StackOwnerLimiter::StackOwnerLimiter()
: owner(-1)
{
}
StackOwnerLimiter::StackOwnerLimiter(const PlayerColor & Owner):
owner(Owner)
{
}
OppositeSideLimiter::OppositeSideLimiter():
owner(PlayerColor::CANNOT_DETERMINE)
{
}
OppositeSideLimiter::OppositeSideLimiter(const PlayerColor & Owner):
owner(Owner)
OppositeSideLimiter::OppositeSideLimiter(PlayerColor Owner):
owner(std::move(Owner))
{
}
@ -2527,6 +2534,11 @@ ILimiter::EDecision OppositeSideLimiter::limit(const BonusLimitationContext & co
// Aggregate/Boolean Limiters
AggregateLimiter::AggregateLimiter(std::vector<TLimiterPtr> limiters):
limiters(std::move(limiters))
{
}
void AggregateLimiter::add(const TLimiterPtr & limiter)
{
if(limiter)
@ -2548,6 +2560,11 @@ const std::string & AllOfLimiter::getAggregator() const
return aggregator;
}
AllOfLimiter::AllOfLimiter(std::vector<TLimiterPtr> limiters):
AggregateLimiter(limiters)
{
}
ILimiter::EDecision AllOfLimiter::limit(const BonusLimitationContext & context) const
{
bool wasntSure = false;
@ -2570,6 +2587,11 @@ const std::string & AnyOfLimiter::getAggregator() const
return aggregator;
}
AnyOfLimiter::AnyOfLimiter(std::vector<TLimiterPtr> limiters):
AggregateLimiter(limiters)
{
}
ILimiter::EDecision AnyOfLimiter::limit(const BonusLimitationContext & context) const
{
bool wasntSure = false;
@ -2592,6 +2614,11 @@ const std::string & NoneOfLimiter::getAggregator() const
return aggregator;
}
NoneOfLimiter::NoneOfLimiter(std::vector<TLimiterPtr> limiters):
AggregateLimiter(limiters)
{
}
ILimiter::EDecision NoneOfLimiter::limit(const BonusLimitationContext & context) const
{
bool wasntSure = false;

View File

@ -523,6 +523,16 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
return (high << 16) + low;
}
STRONG_INLINE static ui32 getHighFromSid32(ui32 sid)
{
return sid >> 16;
}
STRONG_INLINE static ui32 getLowFromSid32(ui32 sid)
{
return sid & 0x0000FFFF;
}
std::string Description(boost::optional<si32> customValue = {}) const;
JsonNode toJsonNode() const;
std::string nameForBonus() const; // generate suitable name for bonus - e.g. for storing in json struct
@ -996,6 +1006,7 @@ class DLL_LINKAGE AggregateLimiter : public ILimiter
protected:
std::vector<TLimiterPtr> limiters;
virtual const std::string & getAggregator() const = 0;
AggregateLimiter(std::vector<TLimiterPtr> limiters = {});
public:
void add(const TLimiterPtr & limiter);
JsonNode toJsonNode() const override;
@ -1012,6 +1023,7 @@ class DLL_LINKAGE AllOfLimiter : public AggregateLimiter
protected:
const std::string & getAggregator() const override;
public:
AllOfLimiter(std::vector<TLimiterPtr> limiters = {});
static const std::string aggregator;
EDecision limit(const BonusLimitationContext & context) const override;
};
@ -1021,6 +1033,7 @@ class DLL_LINKAGE AnyOfLimiter : public AggregateLimiter
protected:
const std::string & getAggregator() const override;
public:
AnyOfLimiter(std::vector<TLimiterPtr> limiters = {});
static const std::string aggregator;
EDecision limit(const BonusLimitationContext & context) const override;
};
@ -1030,6 +1043,7 @@ class DLL_LINKAGE NoneOfLimiter : public AggregateLimiter
protected:
const std::string & getAggregator() const override;
public:
NoneOfLimiter(std::vector<TLimiterPtr> limiters = {});
static const std::string aggregator;
EDecision limit(const BonusLimitationContext & context) const override;
};
@ -1127,11 +1141,11 @@ public:
}
};
class DLL_LINKAGE CreatureFactionLimiter : public ILimiter //applies only to creatures of given faction
class DLL_LINKAGE FactionLimiter : public ILimiter //applies only to creatures of given faction
{
public:
FactionID faction;
CreatureFactionLimiter(FactionID faction = FactionID::ANY);
FactionLimiter(FactionID faction = FactionID::DEFAULT);
EDecision limit(const BonusLimitationContext &context) const override;
std::string toString() const override;
@ -1165,8 +1179,7 @@ class DLL_LINKAGE StackOwnerLimiter : public ILimiter //applies only to creature
{
public:
PlayerColor owner;
StackOwnerLimiter();
StackOwnerLimiter(const PlayerColor & Owner);
StackOwnerLimiter(const PlayerColor & Owner = PlayerColor::NEUTRAL);
EDecision limit(const BonusLimitationContext &context) const override;
@ -1181,8 +1194,7 @@ class DLL_LINKAGE OppositeSideLimiter : public ILimiter //applies only to creatu
{
public:
PlayerColor owner;
OppositeSideLimiter();
OppositeSideLimiter(const PlayerColor & Owner);
OppositeSideLimiter(PlayerColor Owner = PlayerColor::CANNOT_DETERMINE);
EDecision limit(const BonusLimitationContext &context) const override;

View File

@ -749,9 +749,9 @@ std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
else
return std::make_shared<CreatureAlignmentLimiter>(static_cast<EAlignment>(alignment));
}
else if(limiterType == "CREATURE_FACTION_LIMITER")
else if(limiterType == "FACTION_LIMITER")
{
std::shared_ptr<CreatureFactionLimiter> factionLimiter = std::make_shared<CreatureFactionLimiter>();
std::shared_ptr<FactionLimiter> factionLimiter = std::make_shared<FactionLimiter>();
VLC->modh->identifiers.requestIdentifier("faction", parameters[0], [=](si32 faction)
{
factionLimiter->faction = FactionID(faction);

View File

@ -179,7 +179,7 @@ void registerTypesMapObjects2(Serializer &s)
s.template registerType<ILimiter, CCreatureTypeLimiter>();
s.template registerType<ILimiter, HasAnotherBonusLimiter>();
s.template registerType<ILimiter, CreatureTerrainLimiter>();
s.template registerType<ILimiter, CreatureFactionLimiter>();
s.template registerType<ILimiter, FactionLimiter>();
s.template registerType<ILimiter, CreatureLevelLimiter>();
s.template registerType<ILimiter, CreatureAlignmentLimiter>();
s.template registerType<ILimiter, RankRangeLimiter>();