1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +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) 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(); limPtr->faction = building->town->faction->getId();
} }
//JsonUtils::parseBuildingBonus produces UNKNOWN type propagator instead of empty. //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::NONE = FactionID(-2);
const FactionID FactionID::ANY = FactionID(-1); const FactionID FactionID::DEFAULT = FactionID(-1);
const FactionID FactionID::CASTLE = FactionID(0); const FactionID FactionID::CASTLE = FactionID(0);
const FactionID FactionID::RAMPART = FactionID(1); const FactionID FactionID::RAMPART = FactionID(1);
const FactionID FactionID::TOWER = FactionID(2); const FactionID FactionID::TOWER = FactionID(2);
@ -206,7 +206,7 @@ si32 FactionID::decode(const std::string & identifier)
if(rawId) if(rawId)
return rawId.get(); return rawId.get();
else else
return FactionID::ANY; return FactionID::DEFAULT;
} }
std::string FactionID::encode(const si32 index) 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) INSTID_LIKE_CLASS_COMMON(FactionID, si32)
DLL_LINKAGE static const FactionID NONE; 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 CASTLE;
DLL_LINKAGE static const FactionID RAMPART; DLL_LINKAGE static const FactionID RAMPART;
DLL_LINKAGE static const FactionID TOWER; 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)}, {"DRAGON_NATURE", std::make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)},
{"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)}, {"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)},
{"CREATURE_NATIVE_TERRAIN", std::make_shared<CreatureTerrainLimiter>()}, {"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>()}, {"CREATURES_ONLY", std::make_shared<CreatureLevelLimiter>()},
{"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()}, {"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()},
}; };
@ -2366,30 +2367,46 @@ JsonNode CreatureTerrainLimiter::toJsonNode() const
return root; return root;
} }
CreatureFactionLimiter::CreatureFactionLimiter(FactionID creatureFaction) FactionLimiter::FactionLimiter(FactionID creatureFaction)
: faction(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); const auto * bearer = dynamic_cast<const INativeTerrainProvider*>(&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 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(); fmt % VLC->factions()->getByIndex(faction)->getJsonKey();
return fmt.str(); return fmt.str();
} }
JsonNode CreatureFactionLimiter::toJsonNode() const JsonNode FactionLimiter::toJsonNode() const
{ {
JsonNode root(JsonNode::JsonType::DATA_STRUCT); 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())); root["parameters"].Vector().push_back(JsonUtils::stringNode(VLC->factions()->getByIndex(faction)->getJsonKey()));
return root; return root;
@ -2498,23 +2515,13 @@ ILimiter::EDecision StackOwnerLimiter::limit(const BonusLimitationContext &conte
return ILimiter::EDecision::DISCARD; return ILimiter::EDecision::DISCARD;
} }
StackOwnerLimiter::StackOwnerLimiter()
: owner(-1)
{
}
StackOwnerLimiter::StackOwnerLimiter(const PlayerColor & Owner): StackOwnerLimiter::StackOwnerLimiter(const PlayerColor & Owner):
owner(Owner) owner(Owner)
{ {
} }
OppositeSideLimiter::OppositeSideLimiter(): OppositeSideLimiter::OppositeSideLimiter(PlayerColor Owner):
owner(PlayerColor::CANNOT_DETERMINE) owner(std::move(Owner))
{
}
OppositeSideLimiter::OppositeSideLimiter(const PlayerColor & Owner):
owner(Owner)
{ {
} }
@ -2527,6 +2534,11 @@ ILimiter::EDecision OppositeSideLimiter::limit(const BonusLimitationContext & co
// Aggregate/Boolean Limiters // Aggregate/Boolean Limiters
AggregateLimiter::AggregateLimiter(std::vector<TLimiterPtr> limiters):
limiters(std::move(limiters))
{
}
void AggregateLimiter::add(const TLimiterPtr & limiter) void AggregateLimiter::add(const TLimiterPtr & limiter)
{ {
if(limiter) if(limiter)
@ -2548,6 +2560,11 @@ const std::string & AllOfLimiter::getAggregator() const
return aggregator; return aggregator;
} }
AllOfLimiter::AllOfLimiter(std::vector<TLimiterPtr> limiters):
AggregateLimiter(limiters)
{
}
ILimiter::EDecision AllOfLimiter::limit(const BonusLimitationContext & context) const ILimiter::EDecision AllOfLimiter::limit(const BonusLimitationContext & context) const
{ {
bool wasntSure = false; bool wasntSure = false;
@ -2570,6 +2587,11 @@ const std::string & AnyOfLimiter::getAggregator() const
return aggregator; return aggregator;
} }
AnyOfLimiter::AnyOfLimiter(std::vector<TLimiterPtr> limiters):
AggregateLimiter(limiters)
{
}
ILimiter::EDecision AnyOfLimiter::limit(const BonusLimitationContext & context) const ILimiter::EDecision AnyOfLimiter::limit(const BonusLimitationContext & context) const
{ {
bool wasntSure = false; bool wasntSure = false;
@ -2592,6 +2614,11 @@ const std::string & NoneOfLimiter::getAggregator() const
return aggregator; return aggregator;
} }
NoneOfLimiter::NoneOfLimiter(std::vector<TLimiterPtr> limiters):
AggregateLimiter(limiters)
{
}
ILimiter::EDecision NoneOfLimiter::limit(const BonusLimitationContext & context) const ILimiter::EDecision NoneOfLimiter::limit(const BonusLimitationContext & context) const
{ {
bool wasntSure = false; bool wasntSure = false;

View File

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

View File

@ -749,9 +749,9 @@ std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
else else
return std::make_shared<CreatureAlignmentLimiter>(static_cast<EAlignment>(alignment)); 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) VLC->modh->identifiers.requestIdentifier("faction", parameters[0], [=](si32 faction)
{ {
factionLimiter->faction = FactionID(faction); factionLimiter->faction = FactionID(faction);

View File

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