1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-29 23:07:48 +02:00

Extract library entity randomization logic to separate class

This commit is contained in:
Ivan Savenko
2025-05-16 17:20:56 +03:00
parent 184e841b16
commit 54a46b77a9
55 changed files with 605 additions and 441 deletions

View File

@@ -24,6 +24,7 @@ class ObjectTemplate;
class CGObjectInstance;
class IObjectInfo;
class IGameInfoCallback;
class IGameRandomizer;
/// Class responsible for creation of objects of specific type & subtype
class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
@@ -122,7 +123,7 @@ public:
/// Configures object properties. Should be re-entrable, resetting state of the object if necessarily
/// This should set remaining properties, including randomized or depending on map
virtual void configureObject(CGObjectInstance * object, vstd::RNG & rng) const = 0;
virtual void configureObject(CGObjectInstance * object, IGameRandomizer & gameRandomizer) const = 0;
/// Returns object configuration, if available. Otherwise returns NULL
virtual std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const;

View File

@@ -17,14 +17,14 @@ VCMI_LIB_NAMESPACE_BEGIN
template<class ObjectType>
class CDefaultObjectTypeHandler : public AObjectTypeHandler
{
void configureObject(CGObjectInstance * object, vstd::RNG & rng) const final
void configureObject(CGObjectInstance * object, IGameRandomizer & gameRandomizer) const final
{
ObjectType * castedObject = dynamic_cast<ObjectType*>(object);
if(castedObject == nullptr)
throw std::runtime_error("Unexpected object type!");
randomizeObject(castedObject, rng);
randomizeObject(castedObject, gameRandomizer);
}
std::shared_ptr<CGObjectInstance> create(IGameInfoCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const final
@@ -43,7 +43,7 @@ class CDefaultObjectTypeHandler : public AObjectTypeHandler
protected:
virtual void initializeObject(ObjectType * object) const {}
virtual void randomizeObject(ObjectType * object, vstd::RNG & rng) const {}
virtual void randomizeObject(ObjectType * object, IGameRandomizer & gameRandomizer) const {}
virtual std::shared_ptr<ObjectType> createObject(IGameInfoCallback * cb) const
{
return std::make_shared<ObjectType>(cb);

View File

@@ -55,13 +55,13 @@ void CRewardableConstructor::assignBonuses(std::vector<Bonus> & bonuses, MapObje
}
}
Rewardable::Configuration CRewardableConstructor::generateConfiguration(IGameInfoCallback * cb, vstd::RNG & rand, MapObjectID objectID, const std::map<std::string, JsonNode> & presetVariables) const
Rewardable::Configuration CRewardableConstructor::generateConfiguration(IGameInfoCallback * cb, IGameRandomizer & gameRandomizer, MapObjectID objectID, const std::map<std::string, JsonNode> & presetVariables) const
{
Rewardable::Configuration result;
result.variables.preset = presetVariables;
try {
objectInfo.configureObject(result, rand, cb);
objectInfo.configureObject(result, gameRandomizer, cb);
}
catch (const JsonRandomizationException & e)
{
@@ -78,14 +78,14 @@ Rewardable::Configuration CRewardableConstructor::generateConfiguration(IGameInf
return result;
}
void CRewardableConstructor::configureObject(CGObjectInstance * object, vstd::RNG & rng) const
void CRewardableConstructor::configureObject(CGObjectInstance * object, IGameRandomizer & gameRandomizer) const
{
auto * rewardableObject = dynamic_cast<CRewardableObject*>(object);
if (!rewardableObject)
throw std::runtime_error("Object " + std::to_string(object->getObjGroupIndex()) + ", " + std::to_string(object->getObjTypeIndex()) + " is not a rewardable object!" );
rewardableObject->configuration = generateConfiguration(object->cb, rng, object->ID, rewardableObject->configuration.variables.preset);
rewardableObject->configuration = generateConfiguration(object->cb, gameRandomizer, object->ID, rewardableObject->configuration.variables.preset);
rewardableObject->initializeGuards();
if (rewardableObject->configuration.info.empty())

View File

@@ -30,11 +30,11 @@ public:
std::shared_ptr<CGObjectInstance> create(IGameInfoCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
void configureObject(CGObjectInstance * object, vstd::RNG & rng) const override;
void configureObject(CGObjectInstance * object, IGameRandomizer & gameRandomizer) const override;
std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override;
Rewardable::Configuration generateConfiguration(IGameInfoCallback * cb, vstd::RNG & rand, MapObjectID objectID, const std::map<std::string, JsonNode> & presetVariables) const;
Rewardable::Configuration generateConfiguration(IGameInfoCallback * cb, IGameRandomizer & gameRandomizer, MapObjectID objectID, const std::map<std::string, JsonNode> & presetVariables) const;
};
VCMI_LIB_NAMESPACE_END

View File

@@ -79,16 +79,16 @@ int ResourceInstanceConstructor::getAmountMultiplier() const
return config["amountMultiplier"].Integer();
}
void ResourceInstanceConstructor::randomizeObject(CGResource * object, vstd::RNG & rng) const
void ResourceInstanceConstructor::randomizeObject(CGResource * object, IGameRandomizer & gameRandomizer) const
{
if (object->amount != CGResource::RANDOM_AMOUNT)
return;
JsonRandom randomizer(object->cb);
JsonRandom randomizer(object->cb, gameRandomizer);
JsonRandom::Variables dummy;
if (!config["amounts"].isNull())
object->amount = randomizer.loadValue(config["amounts"], rng, dummy, 0) * getAmountMultiplier();
object->amount = randomizer.loadValue(config["amounts"], dummy, 0) * getAmountMultiplier();
else
object->amount = 5 * getAmountMultiplier();
}
@@ -136,7 +136,7 @@ void CTownInstanceConstructor::initializeObject(CGTownInstance * obj) const
obj->tempOwner = PlayerColor::NEUTRAL;
}
void CTownInstanceConstructor::randomizeObject(CGTownInstance * object, vstd::RNG & rng) const
void CTownInstanceConstructor::randomizeObject(CGTownInstance * object, IGameRandomizer & gameRandomizer) const
{
auto templ = getOverride(object->cb->getTile(object->pos)->getTerrainID(), object);
if(templ)
@@ -227,7 +227,7 @@ std::shared_ptr<const ObjectTemplate> CHeroInstanceConstructor::getOverride(Terr
return candidateBase;
}
void CHeroInstanceConstructor::randomizeObject(CGHeroInstance * object, vstd::RNG & rng) const
void CHeroInstanceConstructor::randomizeObject(CGHeroInstance * object, IGameRandomizer & gameRandomizer) const
{
}
@@ -340,14 +340,14 @@ const std::set<EMarketMode> & MarketInstanceConstructor::availableModes() const
return marketModes;
}
void MarketInstanceConstructor::randomizeObject(CGMarket * object, vstd::RNG & rng) const
void MarketInstanceConstructor::randomizeObject(CGMarket * object, IGameRandomizer & gameRandomizer) const
{
JsonRandom randomizer(object->cb);
JsonRandom randomizer(object->cb, gameRandomizer);
JsonRandom::Variables emptyVariables;
if(auto * university = dynamic_cast<CGUniversity *>(object))
{
for(auto skill : randomizer.loadSecondaries(predefinedOffer, rng, emptyVariables))
for(auto skill : randomizer.loadSecondaries(predefinedOffer, emptyVariables))
university->skills.push_back(skill.first);
}
}

View File

@@ -61,7 +61,7 @@ public:
int getAmountMultiplier() const;
int getBaseAmount(vstd::RNG & rng) const;
void randomizeObject(CGResource * object, vstd::RNG & rng) const override;
void randomizeObject(CGResource * object, IGameRandomizer & gameRandomizer) const override;
};
class CTownInstanceConstructor : public CDefaultObjectTypeHandler<CGTownInstance>
@@ -76,7 +76,7 @@ public:
std::map<std::string, LogicalExpression<BuildingID>> filters;
void initializeObject(CGTownInstance * object) const override;
void randomizeObject(CGTownInstance * object, vstd::RNG & rng) const override;
void randomizeObject(CGTownInstance * object, IGameRandomizer & gameRandomizer) const override;
void afterLoadFinalization() override;
bool hasNameTextID() const override;
@@ -99,7 +99,7 @@ class CHeroInstanceConstructor : public CDefaultObjectTypeHandler<CGHeroInstance
void initTypeData(const JsonNode & input) override;
public:
void randomizeObject(CGHeroInstance * object, vstd::RNG & rng) const override;
void randomizeObject(CGHeroInstance * object, IGameRandomizer & gameRandomizer) const override;
bool hasNameTextID() const override;
std::string getNameTextID() const override;
@@ -138,7 +138,7 @@ class MarketInstanceConstructor : public CDefaultObjectTypeHandler<CGMarket>
void initTypeData(const JsonNode & config) override;
public:
std::shared_ptr<CGMarket> createObject(IGameInfoCallback * cb) const override;
void randomizeObject(CGMarket * object, vstd::RNG & rng) const override;
void randomizeObject(CGMarket * object, IGameRandomizer & gameRandomizer) const override;
const std::set<EMarketMode> & availableModes() const;
bool hasDescription() const;

View File

@@ -100,9 +100,9 @@ void DwellingInstanceConstructor::initializeObject(CGDwelling * obj) const
}
}
void DwellingInstanceConstructor::randomizeObject(CGDwelling * dwelling, vstd::RNG &rng) const
void DwellingInstanceConstructor::randomizeObject(CGDwelling * dwelling, IGameRandomizer & gameRandomizer) const
{
JsonRandom randomizer(dwelling->cb);
JsonRandom randomizer(dwelling->cb, gameRandomizer);
dwelling->creatures.clear();
dwelling->creatures.reserve(availableCreatures.size());
@@ -128,7 +128,7 @@ void DwellingInstanceConstructor::randomizeObject(CGDwelling * dwelling, vstd::R
{
//custom guards (eg. Elemental Conflux)
JsonRandom::Variables emptyVariables;
for(auto & stack : randomizer.loadCreatures(guards, rng, emptyVariables))
for(auto & stack : randomizer.loadCreatures(guards, emptyVariables))
{
dwelling->putStack(SlotID(dwelling->stacksCount()), std::make_unique<CStackInstance>(dwelling->cb, stack.getId(), stack.getCount()));
}

View File

@@ -34,7 +34,7 @@ public:
bool hasNameTextID() const override;
void initializeObject(CGDwelling * object) const override;
void randomizeObject(CGDwelling * object, vstd::RNG & rng) const override;
void randomizeObject(CGDwelling * object, IGameRandomizer & gameRandomizer) const override;
bool isBannedForRandomDwelling() const;
bool producesCreature(const CCreature * crea) const;