mirror of
https://github.com/vcmi/vcmi.git
synced 2025-05-27 22:47:48 +02:00
Implemented basic version of configurable Witch Hut
This commit is contained in:
parent
79b7518b0e
commit
fd01a25352
@ -528,13 +528,16 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float RewardEvaluator::evaluateWitchHutSkillScore(const CGWitchHut * hut, const CGHeroInstance * hero, HeroRole role) const
|
float RewardEvaluator::evaluateWitchHutSkillScore(const CGObjectInstance * hut, const CGHeroInstance * hero, HeroRole role) const
|
||||||
{
|
{
|
||||||
|
auto rewardable = dynamic_cast<const CRewardableObject *>(hut);
|
||||||
|
assert(rewardable);
|
||||||
|
|
||||||
|
auto skill = SecondarySkill(*rewardable->configuration.getVariable("secondarySkill", "gainedSkill"));
|
||||||
|
|
||||||
if(!hut->wasVisited(hero->tempOwner))
|
if(!hut->wasVisited(hero->tempOwner))
|
||||||
return role == HeroRole::SCOUT ? 2 : 0;
|
return role == HeroRole::SCOUT ? 2 : 0;
|
||||||
|
|
||||||
auto skill = SecondarySkill(hut->ability);
|
|
||||||
|
|
||||||
if(hero->getSecSkillLevel(skill) != SecSkillLevel::NONE
|
if(hero->getSecSkillLevel(skill) != SecSkillLevel::NONE
|
||||||
|| hero->secSkills.size() >= GameConstants::SKILL_PER_HERO)
|
|| hero->secSkills.size() >= GameConstants::SKILL_PER_HERO)
|
||||||
return 0;
|
return 0;
|
||||||
@ -575,7 +578,7 @@ float RewardEvaluator::getSkillReward(const CGObjectInstance * target, const CGH
|
|||||||
case Obj::LIBRARY_OF_ENLIGHTENMENT:
|
case Obj::LIBRARY_OF_ENLIGHTENMENT:
|
||||||
return 8;
|
return 8;
|
||||||
case Obj::WITCH_HUT:
|
case Obj::WITCH_HUT:
|
||||||
return evaluateWitchHutSkillScore(dynamic_cast<const CGWitchHut *>(target), hero, role);
|
return evaluateWitchHutSkillScore(target, hero, role);
|
||||||
case Obj::PANDORAS_BOX:
|
case Obj::PANDORAS_BOX:
|
||||||
//Can contains experience, spells, or skills (only on custom maps)
|
//Can contains experience, spells, or skills (only on custom maps)
|
||||||
return 2.5f;
|
return 2.5f;
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class CGWitchHut;
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
namespace NKAI
|
namespace NKAI
|
||||||
@ -43,7 +41,7 @@ public:
|
|||||||
float getResourceRequirementStrength(int resType) const;
|
float getResourceRequirementStrength(int resType) const;
|
||||||
float getStrategicalValue(const CGObjectInstance * target) const;
|
float getStrategicalValue(const CGObjectInstance * target) const;
|
||||||
float getTotalResourceRequirementStrength(int resType) const;
|
float getTotalResourceRequirementStrength(int resType) const;
|
||||||
float evaluateWitchHutSkillScore(const CGWitchHut * hut, const CGHeroInstance * hero, HeroRole role) const;
|
float evaluateWitchHutSkillScore(const CGObjectInstance * hut, const CGHeroInstance * hero, HeroRole role) const;
|
||||||
float getSkillReward(const CGObjectInstance * target, const CGHeroInstance * hero, HeroRole role) const;
|
float getSkillReward(const CGObjectInstance * target, const CGHeroInstance * hero, HeroRole role) const;
|
||||||
int32_t getGoldReward(const CGObjectInstance * target, const CGHeroInstance * hero) const;
|
int32_t getGoldReward(const CGObjectInstance * target, const CGHeroInstance * hero) const;
|
||||||
uint64_t getUpgradeArmyReward(const CGTownInstance * town, const BuildingInfo & bi) const;
|
uint64_t getUpgradeArmyReward(const CGTownInstance * town, const BuildingInfo & bi) const;
|
||||||
|
@ -90,7 +90,7 @@ Goals::TSubgoal ResourceManager::collectResourcesForOurGoal(ResourceObjective &o
|
|||||||
{
|
{
|
||||||
auto allResources = cb->getResourceAmount();
|
auto allResources = cb->getResourceAmount();
|
||||||
auto income = estimateIncome();
|
auto income = estimateIncome();
|
||||||
GameResID resourceType = EGameResID::INVALID;
|
GameResID resourceType = EGameResID::NONE;
|
||||||
TResource amountToCollect = 0;
|
TResource amountToCollect = 0;
|
||||||
|
|
||||||
using resPair = std::pair<GameResID, TResource>;
|
using resPair = std::pair<GameResID, TResource>;
|
||||||
@ -129,7 +129,7 @@ Goals::TSubgoal ResourceManager::collectResourcesForOurGoal(ResourceObjective &o
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (resourceType == EGameResID::INVALID) //no needed resources has 0 income,
|
if (resourceType == EGameResID::NONE) //no needed resources has 0 income,
|
||||||
{
|
{
|
||||||
//find the one which takes longest to collect
|
//find the one which takes longest to collect
|
||||||
using timePair = std::pair<GameResID, float>;
|
using timePair = std::pair<GameResID, float>;
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
"config/objects/moddables.json",
|
"config/objects/moddables.json",
|
||||||
"config/objects/creatureBanks.json",
|
"config/objects/creatureBanks.json",
|
||||||
"config/objects/dwellings.json",
|
"config/objects/dwellings.json",
|
||||||
|
"config/objects/rewardableGeneric.json",
|
||||||
"config/objects/rewardableOncePerWeek.json",
|
"config/objects/rewardableOncePerWeek.json",
|
||||||
"config/objects/rewardablePickable.json",
|
"config/objects/rewardablePickable.json",
|
||||||
"config/objects/rewardableOnceVisitable.json",
|
"config/objects/rewardableOnceVisitable.json",
|
||||||
|
@ -587,26 +587,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"witchHut" : {
|
|
||||||
"index" :113,
|
|
||||||
"handler" : "witch",
|
|
||||||
"base" : {
|
|
||||||
"sounds" : {
|
|
||||||
"visit" : ["GAZEBO"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"types" : {
|
|
||||||
"object" : {
|
|
||||||
"index" : 0,
|
|
||||||
"aiValue" : 1500,
|
|
||||||
"rmg" : {
|
|
||||||
"zoneLimit" : 3,
|
|
||||||
"value" : 1500,
|
|
||||||
"rarity" : 80
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"questGuard" : {
|
"questGuard" : {
|
||||||
"index" :215,
|
"index" :215,
|
||||||
"handler" : "questGuard",
|
"handler" : "questGuard",
|
||||||
|
@ -220,7 +220,7 @@ Keep in mind, that all randomization is performed on map load and on object rese
|
|||||||
```jsonc
|
```jsonc
|
||||||
"resources": [
|
"resources": [
|
||||||
{
|
{
|
||||||
"list" : [ "wood", "ore" ],
|
"anyOf" : [ "wood", "ore" ],
|
||||||
"amount" : 10
|
"amount" : 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ private:
|
|||||||
std::string identifier;
|
std::string identifier;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSkill(const SecondarySkill & id = SecondarySkill::DEFAULT, std::string identifier = "default", bool obligatoryMajor = false, bool obligatoryMinor = false);
|
CSkill(const SecondarySkill & id = SecondarySkill::NONE, std::string identifier = "default", bool obligatoryMajor = false, bool obligatoryMinor = false);
|
||||||
~CSkill() = default;
|
~CSkill() = default;
|
||||||
|
|
||||||
enum class Obligatory : ui8
|
enum class Obligatory : ui8
|
||||||
|
@ -32,38 +32,71 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
namespace JsonRandom
|
namespace JsonRandom
|
||||||
{
|
{
|
||||||
si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue)
|
si32 loadVariable(std::string variableGroup, const std::string & value, const Variables & variables, si32 defaultValue)
|
||||||
|
{
|
||||||
|
if (value.empty() || value[0] != '@')
|
||||||
|
{
|
||||||
|
logMod->warn("Invalid syntax in load value! Can not load value from '%s'", value);
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string variableID = variableGroup + value;
|
||||||
|
|
||||||
|
if (variables.count(variableID) == 0)
|
||||||
|
{
|
||||||
|
logMod->warn("Invalid syntax in load value! Unknown variable '%s'", value);
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return variables.at(variableID);
|
||||||
|
}
|
||||||
|
|
||||||
|
si32 loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue)
|
||||||
{
|
{
|
||||||
if(value.isNull())
|
if(value.isNull())
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
if(value.isNumber())
|
if(value.isNumber())
|
||||||
return static_cast<si32>(value.Float());
|
return static_cast<si32>(value.Float());
|
||||||
|
if (value.isString())
|
||||||
|
return loadVariable("number", value.String(), variables, defaultValue);
|
||||||
|
|
||||||
if(value.isVector())
|
if(value.isVector())
|
||||||
{
|
{
|
||||||
const auto & vector = value.Vector();
|
const auto & vector = value.Vector();
|
||||||
|
|
||||||
size_t index= rng.getIntRange(0, vector.size()-1)();
|
size_t index= rng.getIntRange(0, vector.size()-1)();
|
||||||
return loadValue(vector[index], rng, 0);
|
return loadValue(vector[index], rng, variables, 0);
|
||||||
}
|
}
|
||||||
if(value.isStruct())
|
if(value.isStruct())
|
||||||
{
|
{
|
||||||
if (!value["amount"].isNull())
|
if (!value["amount"].isNull())
|
||||||
return static_cast<si32>(loadValue(value["amount"], rng, defaultValue));
|
return static_cast<si32>(loadValue(value["amount"], rng, variables, defaultValue));
|
||||||
si32 min = static_cast<si32>(loadValue(value["min"], rng, 0));
|
si32 min = static_cast<si32>(loadValue(value["min"], rng, variables, 0));
|
||||||
si32 max = static_cast<si32>(loadValue(value["max"], rng, 0));
|
si32 max = static_cast<si32>(loadValue(value["max"], rng, variables, 0));
|
||||||
return rng.getIntRange(min, max)();
|
return rng.getIntRange(min, max)();
|
||||||
}
|
}
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename IdentifierType>
|
template<typename IdentifierType>
|
||||||
IdentifierType decodeKey(const JsonNode & value)
|
IdentifierType decodeKey(const std::string & modScope, const std::string & value, const Variables & variables)
|
||||||
{
|
{
|
||||||
|
if (value.empty() || value[0] != '@')
|
||||||
|
return IdentifierType(*VLC->identifiers()->getIdentifier(modScope, IdentifierType::entityType(), value));
|
||||||
|
else
|
||||||
|
return loadVariable(IdentifierType::entityType(), value, variables, IdentifierType::NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename IdentifierType>
|
||||||
|
IdentifierType decodeKey(const JsonNode & value, const Variables & variables)
|
||||||
|
{
|
||||||
|
if (value.String().empty() || value.String()[0] != '@')
|
||||||
return IdentifierType(*VLC->identifiers()->getIdentifier(IdentifierType::entityType(), value));
|
return IdentifierType(*VLC->identifiers()->getIdentifier(IdentifierType::entityType(), value));
|
||||||
|
else
|
||||||
|
return loadVariable(IdentifierType::entityType(), value.String(), variables, IdentifierType::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
PrimarySkill decodeKey(const JsonNode & value)
|
PrimarySkill decodeKey(const JsonNode & value, const Variables & variables)
|
||||||
{
|
{
|
||||||
return PrimarySkill(*VLC->identifiers()->getIdentifier("primarySkill", value));
|
return PrimarySkill(*VLC->identifiers()->getIdentifier("primarySkill", value));
|
||||||
}
|
}
|
||||||
@ -143,7 +176,7 @@ namespace JsonRandom
|
|||||||
|
|
||||||
if (!value["level"].isNull())
|
if (!value["level"].isNull())
|
||||||
{
|
{
|
||||||
int32_t spellLevel = value["level"].Float();
|
int32_t spellLevel = value["level"].Integer();
|
||||||
|
|
||||||
vstd::erase_if(result, [=](const SpellID & spell)
|
vstd::erase_if(result, [=](const SpellID & spell)
|
||||||
{
|
{
|
||||||
@ -164,17 +197,17 @@ namespace JsonRandom
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename IdentifierType>
|
template<typename IdentifierType>
|
||||||
std::set<IdentifierType> filterKeys(const JsonNode & value, const std::set<IdentifierType> & valuesSet)
|
std::set<IdentifierType> filterKeys(const JsonNode & value, const std::set<IdentifierType> & valuesSet, const Variables & variables)
|
||||||
{
|
{
|
||||||
if(value.isString())
|
if(value.isString())
|
||||||
return { decodeKey<IdentifierType>(value) };
|
return { decodeKey<IdentifierType>(value, variables) };
|
||||||
|
|
||||||
assert(value.isStruct());
|
assert(value.isStruct());
|
||||||
|
|
||||||
if(value.isStruct())
|
if(value.isStruct())
|
||||||
{
|
{
|
||||||
if(!value["type"].isNull())
|
if(!value["type"].isNull())
|
||||||
return filterKeys(value["type"], valuesSet);
|
return filterKeys(value["type"], valuesSet, variables);
|
||||||
|
|
||||||
std::set<IdentifierType> filteredTypes = filterKeysTyped(value, valuesSet);
|
std::set<IdentifierType> filteredTypes = filterKeysTyped(value, valuesSet);
|
||||||
|
|
||||||
@ -183,7 +216,7 @@ namespace JsonRandom
|
|||||||
std::set<IdentifierType> filteredAnyOf;
|
std::set<IdentifierType> filteredAnyOf;
|
||||||
for (auto const & entry : value["anyOf"].Vector())
|
for (auto const & entry : value["anyOf"].Vector())
|
||||||
{
|
{
|
||||||
std::set<IdentifierType> subset = filterKeys(entry, valuesSet);
|
std::set<IdentifierType> subset = filterKeys(entry, valuesSet, variables);
|
||||||
filteredAnyOf.insert(subset.begin(), subset.end());
|
filteredAnyOf.insert(subset.begin(), subset.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +230,7 @@ namespace JsonRandom
|
|||||||
{
|
{
|
||||||
for (auto const & entry : value["noneOf"].Vector())
|
for (auto const & entry : value["noneOf"].Vector())
|
||||||
{
|
{
|
||||||
std::set<IdentifierType> subset = filterKeys(entry, valuesSet);
|
std::set<IdentifierType> subset = filterKeys(entry, valuesSet, variables);
|
||||||
for (auto bannedEntry : subset )
|
for (auto bannedEntry : subset )
|
||||||
filteredTypes.erase(bannedEntry);
|
filteredTypes.erase(bannedEntry);
|
||||||
}
|
}
|
||||||
@ -208,25 +241,25 @@ namespace JsonRandom
|
|||||||
return valuesSet;
|
return valuesSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
TResources loadResources(const JsonNode & value, CRandomGenerator & rng)
|
TResources loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
TResources ret;
|
TResources ret;
|
||||||
|
|
||||||
if (value.isVector())
|
if (value.isVector())
|
||||||
{
|
{
|
||||||
for (const auto & entry : value.Vector())
|
for (const auto & entry : value.Vector())
|
||||||
ret += loadResource(entry, rng);
|
ret += loadResource(entry, rng, variables);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i=0; i<GameConstants::RESOURCE_QUANTITY; i++)
|
for (size_t i=0; i<GameConstants::RESOURCE_QUANTITY; i++)
|
||||||
{
|
{
|
||||||
ret[i] = loadValue(value[GameConstants::RESOURCE_NAMES[i]], rng);
|
ret[i] = loadValue(value[GameConstants::RESOURCE_NAMES[i]], rng, variables);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
TResources loadResource(const JsonNode & value, CRandomGenerator & rng)
|
TResources loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
std::set<GameResID> defaultResources{
|
std::set<GameResID> defaultResources{
|
||||||
GameResID::WOOD,
|
GameResID::WOOD,
|
||||||
@ -238,9 +271,9 @@ namespace JsonRandom
|
|||||||
GameResID::GOLD
|
GameResID::GOLD
|
||||||
};
|
};
|
||||||
|
|
||||||
std::set<GameResID> potentialPicks = filterKeys(value, defaultResources);
|
std::set<GameResID> potentialPicks = filterKeys(value, defaultResources, variables);
|
||||||
GameResID resourceID = *RandomGeneratorUtil::nextItem(potentialPicks, rng);
|
GameResID resourceID = *RandomGeneratorUtil::nextItem(potentialPicks, rng);
|
||||||
si32 resourceAmount = loadValue(value, rng, 0);
|
si32 resourceAmount = loadValue(value, rng, variables, 0);
|
||||||
|
|
||||||
TResources ret;
|
TResources ret;
|
||||||
ret[resourceID] = resourceAmount;
|
ret[resourceID] = resourceAmount;
|
||||||
@ -248,14 +281,14 @@ namespace JsonRandom
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng)
|
std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
std::vector<si32> ret;
|
std::vector<si32> ret;
|
||||||
if(value.isStruct())
|
if(value.isStruct())
|
||||||
{
|
{
|
||||||
for(const auto & name : NPrimarySkill::names)
|
for(const auto & name : NPrimarySkill::names)
|
||||||
{
|
{
|
||||||
ret.push_back(loadValue(value[name], rng));
|
ret.push_back(loadValue(value[name], rng, variables));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(value.isVector())
|
if(value.isVector())
|
||||||
@ -271,25 +304,36 @@ namespace JsonRandom
|
|||||||
|
|
||||||
for(const auto & element : value.Vector())
|
for(const auto & element : value.Vector())
|
||||||
{
|
{
|
||||||
std::set<PrimarySkill> potentialPicks = filterKeys(element, defaultSkills);
|
std::set<PrimarySkill> potentialPicks = filterKeys(element, defaultSkills, variables);
|
||||||
PrimarySkill skillID = *RandomGeneratorUtil::nextItem(potentialPicks, rng);
|
PrimarySkill skillID = *RandomGeneratorUtil::nextItem(potentialPicks, rng);
|
||||||
|
|
||||||
defaultSkills.erase(skillID);
|
defaultSkills.erase(skillID);
|
||||||
ret[static_cast<int>(skillID)] += loadValue(element, rng);
|
ret[static_cast<int>(skillID)] += loadValue(element, rng, variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<SecondarySkill, si32> loadSecondary(const JsonNode & value, CRandomGenerator & rng)
|
SecondarySkill loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
|
{
|
||||||
|
std::set<SecondarySkill> defaultSkills;
|
||||||
|
for(const auto & skill : VLC->skillh->objects)
|
||||||
|
if (IObjectInterface::cb->isAllowed(2, skill->getIndex()))
|
||||||
|
defaultSkills.insert(skill->getId());
|
||||||
|
|
||||||
|
std::set<SecondarySkill> potentialPicks = filterKeys(value, defaultSkills, variables);
|
||||||
|
return *RandomGeneratorUtil::nextItem(potentialPicks, rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<SecondarySkill, si32> loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
std::map<SecondarySkill, si32> ret;
|
std::map<SecondarySkill, si32> ret;
|
||||||
if(value.isStruct())
|
if(value.isStruct())
|
||||||
{
|
{
|
||||||
for(const auto & pair : value.Struct())
|
for(const auto & pair : value.Struct())
|
||||||
{
|
{
|
||||||
SecondarySkill id(VLC->identifiers()->getIdentifier(pair.second.meta, "skill", pair.first).value());
|
SecondarySkill id = decodeKey<SecondarySkill>(pair.second.meta, pair.first, variables);
|
||||||
ret[id] = loadValue(pair.second, rng);
|
ret[id] = loadValue(pair.second, rng, variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(value.isVector())
|
if(value.isVector())
|
||||||
@ -301,45 +345,45 @@ namespace JsonRandom
|
|||||||
|
|
||||||
for(const auto & element : value.Vector())
|
for(const auto & element : value.Vector())
|
||||||
{
|
{
|
||||||
std::set<SecondarySkill> potentialPicks = filterKeys(element, defaultSkills);
|
std::set<SecondarySkill> potentialPicks = filterKeys(element, defaultSkills, variables);
|
||||||
SecondarySkill skillID = *RandomGeneratorUtil::nextItem(potentialPicks, rng);
|
SecondarySkill skillID = *RandomGeneratorUtil::nextItem(potentialPicks, rng);
|
||||||
|
|
||||||
defaultSkills.erase(skillID); //avoid dupicates
|
defaultSkills.erase(skillID); //avoid dupicates
|
||||||
ret[skillID] = loadValue(element, rng);
|
ret[skillID] = loadValue(element, rng, variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng)
|
ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
std::set<ArtifactID> allowedArts;
|
std::set<ArtifactID> allowedArts;
|
||||||
for (auto const * artifact : VLC->arth->allowedArtifacts)
|
for (auto const * artifact : VLC->arth->allowedArtifacts)
|
||||||
allowedArts.insert(artifact->getId());
|
allowedArts.insert(artifact->getId());
|
||||||
|
|
||||||
std::set<ArtifactID> potentialPicks = filterKeys(value, allowedArts);
|
std::set<ArtifactID> potentialPicks = filterKeys(value, allowedArts, variables);
|
||||||
|
|
||||||
return VLC->arth->pickRandomArtifact(rng, potentialPicks);
|
return VLC->arth->pickRandomArtifact(rng, potentialPicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng)
|
std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
std::vector<ArtifactID> ret;
|
std::vector<ArtifactID> ret;
|
||||||
for (const JsonNode & entry : value.Vector())
|
for (const JsonNode & entry : value.Vector())
|
||||||
{
|
{
|
||||||
ret.push_back(loadArtifact(entry, rng));
|
ret.push_back(loadArtifact(entry, rng, variables));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, std::vector<SpellID> spells)
|
SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
std::set<SpellID> defaultSpells;
|
std::set<SpellID> defaultSpells;
|
||||||
for(const auto & spell : VLC->spellh->objects)
|
for(const auto & spell : VLC->spellh->objects)
|
||||||
if (IObjectInterface::cb->isAllowed(0, spell->getIndex()))
|
if (IObjectInterface::cb->isAllowed(0, spell->getIndex()))
|
||||||
defaultSpells.insert(spell->getId());
|
defaultSpells.insert(spell->getId());
|
||||||
|
|
||||||
std::set<SpellID> potentialPicks = filterKeys(value, defaultSpells);
|
std::set<SpellID> potentialPicks = filterKeys(value, defaultSpells, variables);
|
||||||
|
|
||||||
if (potentialPicks.empty())
|
if (potentialPicks.empty())
|
||||||
{
|
{
|
||||||
@ -349,12 +393,12 @@ namespace JsonRandom
|
|||||||
return *RandomGeneratorUtil::nextItem(potentialPicks, rng);
|
return *RandomGeneratorUtil::nextItem(potentialPicks, rng);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const std::vector<SpellID> & spells)
|
std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
std::vector<SpellID> ret;
|
std::vector<SpellID> ret;
|
||||||
for (const JsonNode & entry : value.Vector())
|
for (const JsonNode & entry : value.Vector())
|
||||||
{
|
{
|
||||||
ret.push_back(loadSpell(entry, rng, spells));
|
ret.push_back(loadSpell(entry, rng, variables));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -399,7 +443,7 @@ namespace JsonRandom
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng)
|
CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
CStackBasicDescriptor stack;
|
CStackBasicDescriptor stack;
|
||||||
|
|
||||||
@ -408,7 +452,7 @@ namespace JsonRandom
|
|||||||
if (!creature->special)
|
if (!creature->special)
|
||||||
defaultCreatures.insert(creature->getId());
|
defaultCreatures.insert(creature->getId());
|
||||||
|
|
||||||
std::set<CreatureID> potentialPicks = filterKeys(value, defaultCreatures);
|
std::set<CreatureID> potentialPicks = filterKeys(value, defaultCreatures, variables);
|
||||||
CreatureID pickedCreature;
|
CreatureID pickedCreature;
|
||||||
|
|
||||||
if (!potentialPicks.empty())
|
if (!potentialPicks.empty())
|
||||||
@ -417,7 +461,7 @@ namespace JsonRandom
|
|||||||
logMod->warn("Failed to select suitable random creature!");
|
logMod->warn("Failed to select suitable random creature!");
|
||||||
|
|
||||||
stack.type = VLC->creh->objects[pickedCreature];
|
stack.type = VLC->creh->objects[pickedCreature];
|
||||||
stack.count = loadValue(value, rng);
|
stack.count = loadValue(value, rng, variables);
|
||||||
if (!value["upgradeChance"].isNull() && !stack.type->upgrades.empty())
|
if (!value["upgradeChance"].isNull() && !stack.type->upgrades.empty())
|
||||||
{
|
{
|
||||||
if (int(value["upgradeChance"].Float()) > rng.nextInt(99)) // select random upgrade
|
if (int(value["upgradeChance"].Float()) > rng.nextInt(99)) // select random upgrade
|
||||||
@ -428,17 +472,17 @@ namespace JsonRandom
|
|||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng)
|
std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
|
||||||
{
|
{
|
||||||
std::vector<CStackBasicDescriptor> ret;
|
std::vector<CStackBasicDescriptor> ret;
|
||||||
for (const JsonNode & node : value.Vector())
|
for (const JsonNode & node : value.Vector())
|
||||||
{
|
{
|
||||||
ret.push_back(loadCreature(node, rng));
|
ret.push_back(loadCreature(node, rng, variables));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value)
|
std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value, const Variables & variables)
|
||||||
{
|
{
|
||||||
std::vector<RandomStackInfo> ret;
|
std::vector<RandomStackInfo> ret;
|
||||||
for (const JsonNode & node : value.Vector())
|
for (const JsonNode & node : value.Vector())
|
||||||
@ -464,13 +508,6 @@ namespace JsonRandom
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::vector<Component> loadComponents(const JsonNode & value)
|
|
||||||
//{
|
|
||||||
// std::vector<Component> ret;
|
|
||||||
// return ret;
|
|
||||||
// //TODO
|
|
||||||
//}
|
|
||||||
|
|
||||||
std::vector<Bonus> DLL_LINKAGE loadBonuses(const JsonNode & value)
|
std::vector<Bonus> DLL_LINKAGE loadBonuses(const JsonNode & value)
|
||||||
{
|
{
|
||||||
std::vector<Bonus> ret;
|
std::vector<Bonus> ret;
|
||||||
|
@ -24,6 +24,8 @@ class CStackBasicDescriptor;
|
|||||||
|
|
||||||
namespace JsonRandom
|
namespace JsonRandom
|
||||||
{
|
{
|
||||||
|
using Variables = std::map<std::string, int>;
|
||||||
|
|
||||||
struct DLL_LINKAGE RandomStackInfo
|
struct DLL_LINKAGE RandomStackInfo
|
||||||
{
|
{
|
||||||
std::vector<const CCreature *> allowedCreatures;
|
std::vector<const CCreature *> allowedCreatures;
|
||||||
@ -31,29 +33,29 @@ namespace JsonRandom
|
|||||||
si32 maxAmount;
|
si32 maxAmount;
|
||||||
};
|
};
|
||||||
|
|
||||||
DLL_LINKAGE si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0);
|
DLL_LINKAGE si32 loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue = 0);
|
||||||
|
|
||||||
DLL_LINKAGE TResources loadResources(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE TResources loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
DLL_LINKAGE TResources loadResource(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE TResources loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
DLL_LINKAGE std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
DLL_LINKAGE std::map<SecondarySkill, si32> loadSecondary(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE SecondarySkill loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
|
DLL_LINKAGE std::map<SecondarySkill, si32> loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
|
|
||||||
DLL_LINKAGE ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
DLL_LINKAGE std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
|
|
||||||
DLL_LINKAGE SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, std::vector<SpellID> spells = {});
|
DLL_LINKAGE SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
DLL_LINKAGE std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const std::vector<SpellID> & spells = {});
|
DLL_LINKAGE std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
|
|
||||||
DLL_LINKAGE CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
DLL_LINKAGE std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
|
||||||
DLL_LINKAGE std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value);
|
DLL_LINKAGE std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value, const Variables & variables);
|
||||||
|
|
||||||
DLL_LINKAGE std::vector<PlayerColor> loadColors(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE std::vector<PlayerColor> loadColors(const JsonNode & value, CRandomGenerator & rng);
|
||||||
DLL_LINKAGE std::vector<HeroTypeID> loadHeroes(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE std::vector<HeroTypeID> loadHeroes(const JsonNode & value, CRandomGenerator & rng);
|
||||||
DLL_LINKAGE std::vector<HeroClassID> loadHeroClasses(const JsonNode & value, CRandomGenerator & rng);
|
DLL_LINKAGE std::vector<HeroClassID> loadHeroClasses(const JsonNode & value, CRandomGenerator & rng);
|
||||||
|
|
||||||
DLL_LINKAGE std::vector<Bonus> loadBonuses(const JsonNode & value);
|
DLL_LINKAGE std::vector<Bonus> loadBonuses(const JsonNode & value);
|
||||||
//DLL_LINKAGE std::vector<Component> loadComponents(const JsonNode & value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -308,8 +308,7 @@ class SecondarySkillBase : public IdentifierBase
|
|||||||
public:
|
public:
|
||||||
enum Type : int32_t
|
enum Type : int32_t
|
||||||
{
|
{
|
||||||
WRONG = -2,
|
NONE = -1,
|
||||||
DEFAULT = -1,
|
|
||||||
PATHFINDING = 0,
|
PATHFINDING = 0,
|
||||||
ARCHERY,
|
ARCHERY,
|
||||||
LOGISTICS,
|
LOGISTICS,
|
||||||
@ -938,7 +937,7 @@ public:
|
|||||||
COUNT,
|
COUNT,
|
||||||
|
|
||||||
WOOD_AND_ORE = 127, // special case for town bonus resource
|
WOOD_AND_ORE = 127, // special case for town bonus resource
|
||||||
INVALID = -1
|
NONE = -1
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,17 +37,15 @@ void CBankInstanceConstructor::initTypeData(const JsonNode & input)
|
|||||||
BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRandomGenerator & rng) const
|
BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRandomGenerator & rng) const
|
||||||
{
|
{
|
||||||
BankConfig bc;
|
BankConfig bc;
|
||||||
|
JsonRandom::Variables emptyVariables;
|
||||||
|
|
||||||
bc.chance = static_cast<ui32>(level["chance"].Float());
|
bc.chance = static_cast<ui32>(level["chance"].Float());
|
||||||
bc.guards = JsonRandom::loadCreatures(level["guards"], rng);
|
bc.guards = JsonRandom::loadCreatures(level["guards"], rng, emptyVariables);
|
||||||
|
|
||||||
std::vector<SpellID> spells;
|
|
||||||
IObjectInterface::cb->getAllowedSpells(spells);
|
|
||||||
|
|
||||||
bc.resources = ResourceSet(level["reward"]["resources"]);
|
bc.resources = ResourceSet(level["reward"]["resources"]);
|
||||||
bc.creatures = JsonRandom::loadCreatures(level["reward"]["creatures"], rng);
|
bc.creatures = JsonRandom::loadCreatures(level["reward"]["creatures"], rng, emptyVariables);
|
||||||
bc.artifacts = JsonRandom::loadArtifacts(level["reward"]["artifacts"], rng);
|
bc.artifacts = JsonRandom::loadArtifacts(level["reward"]["artifacts"], rng, emptyVariables);
|
||||||
bc.spells = JsonRandom::loadSpells(level["reward"]["spells"], rng, spells);
|
bc.spells = JsonRandom::loadSpells(level["reward"]["spells"], rng, emptyVariables);
|
||||||
|
|
||||||
return bc;
|
return bc;
|
||||||
}
|
}
|
||||||
@ -105,10 +103,12 @@ static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature *
|
|||||||
|
|
||||||
IObjectInfo::CArmyStructure CBankInfo::minGuards() const
|
IObjectInfo::CArmyStructure CBankInfo::minGuards() const
|
||||||
{
|
{
|
||||||
|
JsonRandom::Variables emptyVariables;
|
||||||
|
|
||||||
std::vector<IObjectInfo::CArmyStructure> armies;
|
std::vector<IObjectInfo::CArmyStructure> armies;
|
||||||
for(auto configEntry : config)
|
for(auto configEntry : config)
|
||||||
{
|
{
|
||||||
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"]);
|
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"], emptyVariables);
|
||||||
IObjectInfo::CArmyStructure army;
|
IObjectInfo::CArmyStructure army;
|
||||||
for(auto & stack : stacks)
|
for(auto & stack : stacks)
|
||||||
{
|
{
|
||||||
@ -126,10 +126,12 @@ IObjectInfo::CArmyStructure CBankInfo::minGuards() const
|
|||||||
|
|
||||||
IObjectInfo::CArmyStructure CBankInfo::maxGuards() const
|
IObjectInfo::CArmyStructure CBankInfo::maxGuards() const
|
||||||
{
|
{
|
||||||
|
JsonRandom::Variables emptyVariables;
|
||||||
|
|
||||||
std::vector<IObjectInfo::CArmyStructure> armies;
|
std::vector<IObjectInfo::CArmyStructure> armies;
|
||||||
for(auto configEntry : config)
|
for(auto configEntry : config)
|
||||||
{
|
{
|
||||||
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"]);
|
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"], emptyVariables);
|
||||||
IObjectInfo::CArmyStructure army;
|
IObjectInfo::CArmyStructure army;
|
||||||
for(auto & stack : stacks)
|
for(auto & stack : stacks)
|
||||||
{
|
{
|
||||||
@ -147,12 +149,13 @@ IObjectInfo::CArmyStructure CBankInfo::maxGuards() const
|
|||||||
|
|
||||||
TPossibleGuards CBankInfo::getPossibleGuards() const
|
TPossibleGuards CBankInfo::getPossibleGuards() const
|
||||||
{
|
{
|
||||||
|
JsonRandom::Variables emptyVariables;
|
||||||
TPossibleGuards out;
|
TPossibleGuards out;
|
||||||
|
|
||||||
for(const JsonNode & configEntry : config)
|
for(const JsonNode & configEntry : config)
|
||||||
{
|
{
|
||||||
const JsonNode & guardsInfo = configEntry["guards"];
|
const JsonNode & guardsInfo = configEntry["guards"];
|
||||||
auto stacks = JsonRandom::evaluateCreatures(guardsInfo);
|
auto stacks = JsonRandom::evaluateCreatures(guardsInfo, emptyVariables);
|
||||||
IObjectInfo::CArmyStructure army;
|
IObjectInfo::CArmyStructure army;
|
||||||
|
|
||||||
|
|
||||||
@ -187,12 +190,13 @@ std::vector<PossibleReward<TResources>> CBankInfo::getPossibleResourcesReward()
|
|||||||
|
|
||||||
std::vector<PossibleReward<CStackBasicDescriptor>> CBankInfo::getPossibleCreaturesReward() const
|
std::vector<PossibleReward<CStackBasicDescriptor>> CBankInfo::getPossibleCreaturesReward() const
|
||||||
{
|
{
|
||||||
|
JsonRandom::Variables emptyVariables;
|
||||||
std::vector<PossibleReward<CStackBasicDescriptor>> aproximateReward;
|
std::vector<PossibleReward<CStackBasicDescriptor>> aproximateReward;
|
||||||
|
|
||||||
for(const JsonNode & configEntry : config)
|
for(const JsonNode & configEntry : config)
|
||||||
{
|
{
|
||||||
const JsonNode & guardsInfo = configEntry["reward"]["creatures"];
|
const JsonNode & guardsInfo = configEntry["reward"]["creatures"];
|
||||||
auto stacks = JsonRandom::evaluateCreatures(guardsInfo);
|
auto stacks = JsonRandom::evaluateCreatures(guardsInfo, emptyVariables);
|
||||||
|
|
||||||
for(auto stack : stacks)
|
for(auto stack : stacks)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +95,6 @@ CObjectClassesHandler::CObjectClassesHandler()
|
|||||||
SET_HANDLER("monolith", CGMonolith);
|
SET_HANDLER("monolith", CGMonolith);
|
||||||
SET_HANDLER("subterraneanGate", CGSubterraneanGate);
|
SET_HANDLER("subterraneanGate", CGSubterraneanGate);
|
||||||
SET_HANDLER("whirlpool", CGWhirlpool);
|
SET_HANDLER("whirlpool", CGWhirlpool);
|
||||||
SET_HANDLER("witch", CGWitchHut);
|
|
||||||
SET_HANDLER("terrain", CGTerrainPatch);
|
SET_HANDLER("terrain", CGTerrainPatch);
|
||||||
|
|
||||||
#undef SET_HANDLER_CLASS
|
#undef SET_HANDLER_CLASS
|
||||||
|
@ -35,7 +35,6 @@ public:
|
|||||||
{
|
{
|
||||||
AObjectTypeHandler::serialize(h, version);
|
AObjectTypeHandler::serialize(h, version);
|
||||||
|
|
||||||
if (version >= 816)
|
|
||||||
h & objectInfo;
|
h & objectInfo;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -256,9 +256,11 @@ void MarketInstanceConstructor::initializeObject(CGMarket * market) const
|
|||||||
|
|
||||||
void MarketInstanceConstructor::randomizeObject(CGMarket * object, CRandomGenerator & rng) const
|
void MarketInstanceConstructor::randomizeObject(CGMarket * object, CRandomGenerator & rng) const
|
||||||
{
|
{
|
||||||
|
JsonRandom::Variables emptyVariables;
|
||||||
|
|
||||||
if(auto * university = dynamic_cast<CGUniversity *>(object))
|
if(auto * university = dynamic_cast<CGUniversity *>(object))
|
||||||
{
|
{
|
||||||
for(auto skill : JsonRandom::loadSecondary(predefinedOffer, rng))
|
for(auto skill : JsonRandom::loadSecondaries(predefinedOffer, rng, emptyVariables))
|
||||||
university->skills.push_back(skill.first.getNum());
|
university->skills.push_back(skill.first.getNum());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,8 @@ void DwellingInstanceConstructor::randomizeObject(CGDwelling * object, CRandomGe
|
|||||||
}
|
}
|
||||||
else if(guards.getType() == JsonNode::JsonType::DATA_VECTOR) //custom guards (eg. Elemental Conflux)
|
else if(guards.getType() == JsonNode::JsonType::DATA_VECTOR) //custom guards (eg. Elemental Conflux)
|
||||||
{
|
{
|
||||||
for(auto & stack : JsonRandom::loadCreatures(guards, rng))
|
JsonRandom::Variables emptyVariables;
|
||||||
|
for(auto & stack : JsonRandom::loadCreatures(guards, rng, emptyVariables))
|
||||||
{
|
{
|
||||||
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->getId(), stack.count));
|
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->getId(), stack.count));
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ void ShrineInstanceConstructor::initTypeData(const JsonNode & config)
|
|||||||
|
|
||||||
void ShrineInstanceConstructor::randomizeObject(CGShrine * shrine, CRandomGenerator & rng) const
|
void ShrineInstanceConstructor::randomizeObject(CGShrine * shrine, CRandomGenerator & rng) const
|
||||||
{
|
{
|
||||||
|
JsonRandom::Variables emptyVariables;
|
||||||
|
|
||||||
auto visitTextParameter = parameters["visitText"];
|
auto visitTextParameter = parameters["visitText"];
|
||||||
|
|
||||||
if (visitTextParameter.isNumber())
|
if (visitTextParameter.isNumber())
|
||||||
@ -31,12 +33,7 @@ void ShrineInstanceConstructor::randomizeObject(CGShrine * shrine, CRandomGenera
|
|||||||
shrine->visitText.appendRawString(visitTextParameter.String());
|
shrine->visitText.appendRawString(visitTextParameter.String());
|
||||||
|
|
||||||
if(shrine->spell == SpellID::NONE) // shrine has no predefined spell
|
if(shrine->spell == SpellID::NONE) // shrine has no predefined spell
|
||||||
{
|
shrine->spell =JsonRandom::loadSpell(parameters["spell"], rng, emptyVariables);
|
||||||
std::vector<SpellID> possibilities;
|
|
||||||
shrine->cb->getAllowedSpells(possibilities);
|
|
||||||
|
|
||||||
shrine->spell =JsonRandom::loadSpell(parameters["spell"], rng, possibilities);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -253,7 +253,7 @@ CGHeroInstance::CGHeroInstance():
|
|||||||
{
|
{
|
||||||
setNodeType(HERO);
|
setNodeType(HERO);
|
||||||
ID = Obj::HERO;
|
ID = Obj::HERO;
|
||||||
secSkills.emplace_back(SecondarySkill::DEFAULT, -1);
|
secSkills.emplace_back(SecondarySkill::NONE, -1);
|
||||||
blockVisit = true;
|
blockVisit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
|
|||||||
pushPrimSkill(static_cast<PrimarySkill>(g), type->heroClass->primarySkillInitial[g]);
|
pushPrimSkill(static_cast<PrimarySkill>(g), type->heroClass->primarySkillInitial[g]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(secSkills.size() == 1 && secSkills[0] == std::pair<SecondarySkill,ui8>(SecondarySkill::DEFAULT, -1)) //set secondary skills to default
|
if(secSkills.size() == 1 && secSkills[0] == std::pair<SecondarySkill,ui8>(SecondarySkill::NONE, -1)) //set secondary skills to default
|
||||||
secSkills = type->secSkillsInit;
|
secSkills = type->secSkillsInit;
|
||||||
|
|
||||||
if (gender == EHeroGender::DEFAULT)
|
if (gender == EHeroGender::DEFAULT)
|
||||||
@ -1580,7 +1580,7 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
|
|||||||
bool normalSkills = false;
|
bool normalSkills = false;
|
||||||
for(const auto & p : secSkills)
|
for(const auto & p : secSkills)
|
||||||
{
|
{
|
||||||
if(p.first == SecondarySkill(SecondarySkill::DEFAULT))
|
if(p.first == SecondarySkill(SecondarySkill::NONE))
|
||||||
defaultSkills = true;
|
defaultSkills = true;
|
||||||
else
|
else
|
||||||
normalSkills = true;
|
normalSkills = true;
|
||||||
@ -1618,7 +1618,7 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
|
|||||||
secSkills.clear();
|
secSkills.clear();
|
||||||
if(secondarySkills.getType() == JsonNode::JsonType::DATA_NULL)
|
if(secondarySkills.getType() == JsonNode::JsonType::DATA_NULL)
|
||||||
{
|
{
|
||||||
secSkills.emplace_back(SecondarySkill::DEFAULT, -1);
|
secSkills.emplace_back(SecondarySkill::NONE, -1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -90,7 +90,6 @@ public:
|
|||||||
|
|
||||||
// POSSIBLE
|
// POSSIBLE
|
||||||
// class DLL_LINKAGE CGSignBottle : public CGObjectInstance //signs and ocean bottles
|
// class DLL_LINKAGE CGSignBottle : public CGObjectInstance //signs and ocean bottles
|
||||||
// class DLL_LINKAGE CGWitchHut : public CPlayersVisited
|
|
||||||
// class DLL_LINKAGE CGScholar : public CGObjectInstance
|
// class DLL_LINKAGE CGScholar : public CGObjectInstance
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -842,98 +842,6 @@ void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGWitchHut::initObj(CRandomGenerator & rand)
|
|
||||||
{
|
|
||||||
if (allowedAbilities.empty()) //this can happen for RMG and RoE maps.
|
|
||||||
{
|
|
||||||
auto defaultAllowed = VLC->skillh->getDefaultAllowed();
|
|
||||||
|
|
||||||
// Necromancy and Leadership can't be learned by default
|
|
||||||
defaultAllowed[SecondarySkill::NECROMANCY] = false;
|
|
||||||
defaultAllowed[SecondarySkill::LEADERSHIP] = false;
|
|
||||||
|
|
||||||
for(int i = 0; i < defaultAllowed.size(); i++)
|
|
||||||
if (defaultAllowed[i] && cb->isAllowed(2, i))
|
|
||||||
allowedAbilities.insert(SecondarySkill(i));
|
|
||||||
}
|
|
||||||
ability = *RandomGeneratorUtil::nextItem(allowedAbilities, rand);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.type = EInfoWindowMode::AUTO;
|
|
||||||
iw.player = h->getOwner();
|
|
||||||
if(!wasVisited(h->tempOwner))
|
|
||||||
cb->setObjProperty(id, CGWitchHut::OBJPROP_VISITED, h->tempOwner.getNum());
|
|
||||||
ui32 txt_id;
|
|
||||||
if(h->getSecSkillLevel(SecondarySkill(ability))) //you already know this skill
|
|
||||||
{
|
|
||||||
txt_id =172;
|
|
||||||
}
|
|
||||||
else if(!h->canLearnSkill()) //already all skills slots used
|
|
||||||
{
|
|
||||||
txt_id = 173;
|
|
||||||
}
|
|
||||||
else //give sec skill
|
|
||||||
{
|
|
||||||
iw.components.emplace_back(Component::EComponentType::SEC_SKILL, ability, 1, 0);
|
|
||||||
txt_id = 171;
|
|
||||||
cb->changeSecSkill(h, SecondarySkill(ability), 1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
iw.text.appendLocalString(EMetaText::ADVOB_TXT,txt_id);
|
|
||||||
iw.text.replaceLocalString(EMetaText::SEC_SKILL_NAME, ability);
|
|
||||||
cb->showInfoDialog(&iw);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CGWitchHut::getHoverText(PlayerColor player) const
|
|
||||||
{
|
|
||||||
std::string hoverName = getObjectName();
|
|
||||||
if(wasVisited(player))
|
|
||||||
{
|
|
||||||
hoverName += "\n" + VLC->generaltexth->allTexts[356]; // + (learn %s)
|
|
||||||
boost::algorithm::replace_first(hoverName, "%s", VLC->skillh->getByIndex(ability)->getNameTranslated());
|
|
||||||
}
|
|
||||||
return hoverName;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CGWitchHut::getHoverText(const CGHeroInstance * hero) const
|
|
||||||
{
|
|
||||||
std::string hoverName = getHoverText(hero->tempOwner);
|
|
||||||
if(wasVisited(hero->tempOwner) && hero->getSecSkillLevel(SecondarySkill(ability))) //hero knows that ability
|
|
||||||
hoverName += "\n\n" + VLC->generaltexth->allTexts[357]; // (Already learned)
|
|
||||||
return hoverName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGWitchHut::serializeJsonOptions(JsonSerializeFormat & handler)
|
|
||||||
{
|
|
||||||
//TODO: unify allowed abilities with others - make them std::vector<bool>
|
|
||||||
|
|
||||||
std::vector<bool> temp;
|
|
||||||
size_t skillCount = VLC->skillh->size();
|
|
||||||
temp.resize(skillCount, false);
|
|
||||||
|
|
||||||
auto standard = VLC->skillh->getDefaultAllowed(); //todo: for WitchHut default is all except Leadership and Necromancy
|
|
||||||
|
|
||||||
if(handler.saving)
|
|
||||||
{
|
|
||||||
for(SecondarySkill i(0); i < SecondarySkill(skillCount); ++i)
|
|
||||||
if(vstd::contains(allowedAbilities, i))
|
|
||||||
temp[i] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.serializeLIC("allowedSkills", &CSkillHandler::decodeSkill, &CSkillHandler::encodeSkill, standard, temp);
|
|
||||||
|
|
||||||
if(!handler.saving)
|
|
||||||
{
|
|
||||||
allowedAbilities.clear();
|
|
||||||
for(si32 i = 0; i < skillCount; ++i)
|
|
||||||
if(temp[i])
|
|
||||||
allowedAbilities.insert(SecondarySkill(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const
|
void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
|
@ -57,26 +57,6 @@ protected:
|
|||||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CGWitchHut : public CTeamVisited
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::set<SecondarySkill> allowedAbilities;
|
|
||||||
SecondarySkill ability;
|
|
||||||
|
|
||||||
std::string getHoverText(PlayerColor player) const override;
|
|
||||||
std::string getHoverText(const CGHeroInstance * hero) const override;
|
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
|
||||||
void initObj(CRandomGenerator & rand) override;
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & static_cast<CTeamVisited&>(*this);
|
|
||||||
h & allowedAbilities;
|
|
||||||
h & ability;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DLL_LINKAGE CGScholar : public CGObjectInstance
|
class DLL_LINKAGE CGScholar : public CGObjectInstance
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -1139,23 +1139,40 @@ CGObjectInstance * CMapLoaderH3M::readSign(const int3 & mapPosition)
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGObjectInstance * CMapLoaderH3M::readWitchHut()
|
CGObjectInstance * CMapLoaderH3M::readWitchHut(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
|
||||||
{
|
{
|
||||||
auto * object = new CGWitchHut();
|
auto * object = readGeneric(position, objectTemplate);
|
||||||
|
auto * rewardable = dynamic_cast<CRewardableObject*>(object);
|
||||||
|
|
||||||
|
assert(rewardable);
|
||||||
|
|
||||||
// AB and later maps have allowed abilities defined in H3M
|
// AB and later maps have allowed abilities defined in H3M
|
||||||
if(features.levelAB)
|
if(features.levelAB)
|
||||||
{
|
{
|
||||||
reader->readBitmaskSkills(object->allowedAbilities, false);
|
std::set<SecondarySkill> allowedAbilities;
|
||||||
|
reader->readBitmaskSkills(allowedAbilities, false);
|
||||||
|
|
||||||
if(object->allowedAbilities.size() != 1)
|
if(allowedAbilities.size() != 1)
|
||||||
{
|
{
|
||||||
auto defaultAllowed = VLC->skillh->getDefaultAllowed();
|
auto defaultAllowed = VLC->skillh->getDefaultAllowed();
|
||||||
|
|
||||||
for(int skillID = 0; skillID < VLC->skillh->size(); ++skillID)
|
for(int skillID = 0; skillID < VLC->skillh->size(); ++skillID)
|
||||||
if(defaultAllowed[skillID])
|
if(defaultAllowed[skillID])
|
||||||
object->allowedAbilities.insert(SecondarySkill(skillID));
|
allowedAbilities.insert(SecondarySkill(skillID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonVector anyOfList;
|
||||||
|
|
||||||
|
for (auto const & skill : allowedAbilities)
|
||||||
|
{
|
||||||
|
JsonNode entry;
|
||||||
|
entry.String() = VLC->skills()->getById(skill)->getJsonKey();
|
||||||
|
anyOfList.push_back(entry);
|
||||||
|
}
|
||||||
|
JsonNode variable;
|
||||||
|
variable.Vector() = anyOfList;
|
||||||
|
|
||||||
|
rewardable->configuration.presetVariable("secondarySkill", "gainedSkill", variable);
|
||||||
}
|
}
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
@ -1458,7 +1475,7 @@ CGObjectInstance * CMapLoaderH3M::readObject(std::shared_ptr<const ObjectTemplat
|
|||||||
return readSeerHut(mapPosition, objectInstanceID);
|
return readSeerHut(mapPosition, objectInstanceID);
|
||||||
|
|
||||||
case Obj::WITCH_HUT:
|
case Obj::WITCH_HUT:
|
||||||
return readWitchHut();
|
return readWitchHut(mapPosition, objectTemplate);
|
||||||
case Obj::SCHOLAR:
|
case Obj::SCHOLAR:
|
||||||
return readScholar();
|
return readScholar();
|
||||||
|
|
||||||
@ -1717,7 +1734,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
|
|||||||
{
|
{
|
||||||
if(!object->secSkills.empty())
|
if(!object->secSkills.empty())
|
||||||
{
|
{
|
||||||
if(object->secSkills[0].first != SecondarySkill::DEFAULT)
|
if(object->secSkills[0].first != SecondarySkill::NONE)
|
||||||
logGlobal->debug("Map '%s': Hero %s subID=%d has set secondary skills twice (in map properties and on adventure map instance). Using the latter set...", mapName, object->getNameTextID(), object->subID);
|
logGlobal->debug("Map '%s': Hero %s subID=%d has set secondary skills twice (in map properties and on adventure map instance). Using the latter set...", mapName, object->getNameTextID(), object->subID);
|
||||||
object->secSkills.clear();
|
object->secSkills.clear();
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ private:
|
|||||||
CGObjectInstance * readSeerHut(const int3 & initialPos, const ObjectInstanceID & idToBeGiven);
|
CGObjectInstance * readSeerHut(const int3 & initialPos, const ObjectInstanceID & idToBeGiven);
|
||||||
CGObjectInstance * readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
CGObjectInstance * readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||||
CGObjectInstance * readSign(const int3 & position);
|
CGObjectInstance * readSign(const int3 & position);
|
||||||
CGObjectInstance * readWitchHut();
|
CGObjectInstance * readWitchHut(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
|
||||||
CGObjectInstance * readScholar();
|
CGObjectInstance * readScholar();
|
||||||
CGObjectInstance * readGarrison(const int3 & mapPosition);
|
CGObjectInstance * readGarrison(const int3 & mapPosition);
|
||||||
CGObjectInstance * readArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
CGObjectInstance * readArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||||
|
@ -147,7 +147,6 @@ void registerTypesMapObjectTypes(Serializer &s)
|
|||||||
REGISTER_GENERIC_HANDLER(CGWhirlpool);
|
REGISTER_GENERIC_HANDLER(CGWhirlpool);
|
||||||
REGISTER_GENERIC_HANDLER(CGTownInstance);
|
REGISTER_GENERIC_HANDLER(CGTownInstance);
|
||||||
REGISTER_GENERIC_HANDLER(CGUniversity);
|
REGISTER_GENERIC_HANDLER(CGUniversity);
|
||||||
REGISTER_GENERIC_HANDLER(CGWitchHut);
|
|
||||||
REGISTER_GENERIC_HANDLER(HillFort);
|
REGISTER_GENERIC_HANDLER(HillFort);
|
||||||
|
|
||||||
#undef REGISTER_GENERIC_HANDLER
|
#undef REGISTER_GENERIC_HANDLER
|
||||||
@ -177,7 +176,6 @@ void registerTypesMapObjects2(Serializer &s)
|
|||||||
s.template registerType<CGObjectInstance, CRewardableObject>();
|
s.template registerType<CGObjectInstance, CRewardableObject>();
|
||||||
|
|
||||||
s.template registerType<CGObjectInstance, CTeamVisited>();
|
s.template registerType<CGObjectInstance, CTeamVisited>();
|
||||||
s.template registerType<CTeamVisited, CGWitchHut>();
|
|
||||||
s.template registerType<CTeamVisited, CGShrine>();
|
s.template registerType<CTeamVisited, CGShrine>();
|
||||||
s.template registerType<CTeamVisited, CCartographer>();
|
s.template registerType<CTeamVisited, CCartographer>();
|
||||||
s.template registerType<CTeamVisited, CGObelisk>();
|
s.template registerType<CTeamVisited, CGObelisk>();
|
||||||
|
@ -24,6 +24,38 @@ ui16 Rewardable::Configuration::getResetDuration() const
|
|||||||
return resetParameters.period;
|
return resetParameters.period;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<int> Rewardable::Configuration::getVariable(const std::string & category, const std::string & name) const
|
||||||
|
{
|
||||||
|
std::string variableID = category + '@' + name;
|
||||||
|
|
||||||
|
if (variables.values.count(variableID))
|
||||||
|
return variables.values.at(variableID);
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode Rewardable::Configuration::getPresetVariable(const std::string & category, const std::string & name) const
|
||||||
|
{
|
||||||
|
std::string variableID = category + '@' + name;
|
||||||
|
|
||||||
|
if (variables.values.count(variableID))
|
||||||
|
return variables.preset.at(variableID);
|
||||||
|
else
|
||||||
|
return JsonNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rewardable::Configuration::presetVariable(const std::string & category, const std::string & name, const JsonNode & value)
|
||||||
|
{
|
||||||
|
std::string variableID = category + '@' + name;
|
||||||
|
variables.preset[variableID] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rewardable::Configuration::initVariable(const std::string & category, const std::string & name, int value)
|
||||||
|
{
|
||||||
|
std::string variableID = category + '@' + name;
|
||||||
|
variables.values[variableID] = value;
|
||||||
|
}
|
||||||
|
|
||||||
void Rewardable::ResetInfo::serializeJson(JsonSerializeFormat & handler)
|
void Rewardable::ResetInfo::serializeJson(JsonSerializeFormat & handler)
|
||||||
{
|
{
|
||||||
handler.serializeInt("period", period);
|
handler.serializeInt("period", period);
|
||||||
@ -39,6 +71,11 @@ void Rewardable::VisitInfo::serializeJson(JsonSerializeFormat & handler)
|
|||||||
handler.serializeInt("visitType", visitType);
|
handler.serializeInt("visitType", visitType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Rewardable::Variables::serializeJson(JsonSerializeFormat & handler)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
void Rewardable::Configuration::serializeJson(JsonSerializeFormat & handler)
|
void Rewardable::Configuration::serializeJson(JsonSerializeFormat & handler)
|
||||||
{
|
{
|
||||||
handler.serializeStruct("onSelect", onSelect);
|
handler.serializeStruct("onSelect", onSelect);
|
||||||
|
@ -62,7 +62,6 @@ struct DLL_LINKAGE ResetInfo
|
|||||||
/// if true - reset list of visitors (heroes & players) on reset
|
/// if true - reset list of visitors (heroes & players) on reset
|
||||||
bool visitors;
|
bool visitors;
|
||||||
|
|
||||||
|
|
||||||
/// if true - re-randomize rewards on a new week
|
/// if true - re-randomize rewards on a new week
|
||||||
bool rewards;
|
bool rewards;
|
||||||
|
|
||||||
@ -98,6 +97,23 @@ struct DLL_LINKAGE VisitInfo
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DLL_LINKAGE Variables
|
||||||
|
{
|
||||||
|
/// List of variables used by this object in their current values
|
||||||
|
std::map<std::string, int> values;
|
||||||
|
|
||||||
|
/// List of per-instance preconfigured variables, e.g. from map
|
||||||
|
std::map<std::string, JsonNode> preset;
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & values;
|
||||||
|
h & preset;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// Base class that can handle granting rewards to visiting heroes.
|
/// Base class that can handle granting rewards to visiting heroes.
|
||||||
struct DLL_LINKAGE Configuration
|
struct DLL_LINKAGE Configuration
|
||||||
{
|
{
|
||||||
@ -116,6 +132,9 @@ struct DLL_LINKAGE Configuration
|
|||||||
/// how and when should the object be reset
|
/// how and when should the object be reset
|
||||||
Rewardable::ResetInfo resetParameters;
|
Rewardable::ResetInfo resetParameters;
|
||||||
|
|
||||||
|
/// List of variables shoread between all limiters and rewards
|
||||||
|
Rewardable::Variables variables;
|
||||||
|
|
||||||
/// if true - player can refuse visiting an object (e.g. Tomb)
|
/// if true - player can refuse visiting an object (e.g. Tomb)
|
||||||
bool canRefuse = false;
|
bool canRefuse = false;
|
||||||
|
|
||||||
@ -125,6 +144,11 @@ struct DLL_LINKAGE Configuration
|
|||||||
EVisitMode getVisitMode() const;
|
EVisitMode getVisitMode() const;
|
||||||
ui16 getResetDuration() const;
|
ui16 getResetDuration() const;
|
||||||
|
|
||||||
|
std::optional<int> getVariable(const std::string & category, const std::string & name) const;
|
||||||
|
JsonNode getPresetVariable(const std::string & category, const std::string & name) const;
|
||||||
|
void presetVariable(const std::string & category, const std::string & name, const JsonNode & value);
|
||||||
|
void initVariable(const std::string & category, const std::string & name, int value);
|
||||||
|
|
||||||
void serializeJson(JsonSerializeFormat & handler);
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
@ -102,26 +102,23 @@ Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Conf
|
|||||||
|
|
||||||
void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const
|
void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const
|
||||||
{
|
{
|
||||||
std::vector<SpellID> spells;
|
auto const & variables = object.variables.values;
|
||||||
IObjectInterface::cb->getAllowedSpells(spells);
|
|
||||||
|
|
||||||
|
limiter.dayOfWeek = JsonRandom::loadValue(source["dayOfWeek"], rng, variables);
|
||||||
|
limiter.daysPassed = JsonRandom::loadValue(source["daysPassed"], rng, variables);
|
||||||
|
limiter.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng, variables);
|
||||||
|
limiter.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng, variables);
|
||||||
|
|
||||||
limiter.dayOfWeek = JsonRandom::loadValue(source["dayOfWeek"], rng);
|
limiter.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng, variables);
|
||||||
limiter.daysPassed = JsonRandom::loadValue(source["daysPassed"], rng);
|
limiter.manaPoints = JsonRandom::loadValue(source["manaPoints"], rng, variables);
|
||||||
limiter.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng);
|
|
||||||
limiter.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng)
|
|
||||||
+ JsonRandom::loadValue(source["minLevel"], rng); // VCMI 1.1 compatibilty
|
|
||||||
|
|
||||||
limiter.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng);
|
limiter.resources = JsonRandom::loadResources(source["resources"], rng, variables);
|
||||||
limiter.manaPoints = JsonRandom::loadValue(source["manaPoints"], rng);
|
|
||||||
|
|
||||||
limiter.resources = JsonRandom::loadResources(source["resources"], rng);
|
limiter.primary = JsonRandom::loadPrimary(source["primary"], rng, variables);
|
||||||
|
limiter.secondary = JsonRandom::loadSecondaries(source["secondary"], rng, variables);
|
||||||
limiter.primary = JsonRandom::loadPrimary(source["primary"], rng);
|
limiter.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng, variables);
|
||||||
limiter.secondary = JsonRandom::loadSecondary(source["secondary"], rng);
|
limiter.spells = JsonRandom::loadSpells(source["spells"], rng, variables);
|
||||||
limiter.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng);
|
limiter.creatures = JsonRandom::loadCreatures(source["creatures"], rng, variables);
|
||||||
limiter.spells = JsonRandom::loadSpells(source["spells"], rng, spells);
|
|
||||||
limiter.creatures = JsonRandom::loadCreatures(source["creatures"], rng);
|
|
||||||
|
|
||||||
limiter.players = JsonRandom::loadColors(source["colors"], rng);
|
limiter.players = JsonRandom::loadColors(source["colors"], rng);
|
||||||
limiter.heroes = JsonRandom::loadHeroes(source["heroes"], rng);
|
limiter.heroes = JsonRandom::loadHeroes(source["heroes"], rng);
|
||||||
@ -134,36 +131,32 @@ void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRan
|
|||||||
|
|
||||||
void Rewardable::Info::configureReward(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Reward & reward, const JsonNode & source) const
|
void Rewardable::Info::configureReward(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Reward & reward, const JsonNode & source) const
|
||||||
{
|
{
|
||||||
reward.resources = JsonRandom::loadResources(source["resources"], rng);
|
auto const & variables = object.variables.values;
|
||||||
|
|
||||||
reward.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng)
|
reward.resources = JsonRandom::loadResources(source["resources"], rng, variables);
|
||||||
+ JsonRandom::loadValue(source["gainedExp"], rng); // VCMI 1.1 compatibilty
|
|
||||||
|
|
||||||
reward.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng)
|
reward.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng, variables);
|
||||||
+ JsonRandom::loadValue(source["gainedLevels"], rng); // VCMI 1.1 compatibilty
|
reward.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng, variables);
|
||||||
|
|
||||||
reward.manaDiff = JsonRandom::loadValue(source["manaPoints"], rng);
|
reward.manaDiff = JsonRandom::loadValue(source["manaPoints"], rng, variables);
|
||||||
reward.manaOverflowFactor = JsonRandom::loadValue(source["manaOverflowFactor"], rng);
|
reward.manaOverflowFactor = JsonRandom::loadValue(source["manaOverflowFactor"], rng, variables);
|
||||||
reward.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng, -1);
|
reward.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng, variables, -1);
|
||||||
|
|
||||||
reward.movePoints = JsonRandom::loadValue(source["movePoints"], rng);
|
reward.movePoints = JsonRandom::loadValue(source["movePoints"], rng, variables);
|
||||||
reward.movePercentage = JsonRandom::loadValue(source["movePercentage"], rng, -1);
|
reward.movePercentage = JsonRandom::loadValue(source["movePercentage"], rng, variables, -1);
|
||||||
|
|
||||||
reward.removeObject = source["removeObject"].Bool();
|
reward.removeObject = source["removeObject"].Bool();
|
||||||
reward.bonuses = JsonRandom::loadBonuses(source["bonuses"]);
|
reward.bonuses = JsonRandom::loadBonuses(source["bonuses"]);
|
||||||
|
|
||||||
reward.primary = JsonRandom::loadPrimary(source["primary"], rng);
|
reward.primary = JsonRandom::loadPrimary(source["primary"], rng, variables);
|
||||||
reward.secondary = JsonRandom::loadSecondary(source["secondary"], rng);
|
reward.secondary = JsonRandom::loadSecondaries(source["secondary"], rng, variables);
|
||||||
|
|
||||||
std::vector<SpellID> spells;
|
reward.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng, variables);
|
||||||
IObjectInterface::cb->getAllowedSpells(spells);
|
reward.spells = JsonRandom::loadSpells(source["spells"], rng, variables);
|
||||||
|
reward.creatures = JsonRandom::loadCreatures(source["creatures"], rng, variables);
|
||||||
reward.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng);
|
|
||||||
reward.spells = JsonRandom::loadSpells(source["spells"], rng, spells);
|
|
||||||
reward.creatures = JsonRandom::loadCreatures(source["creatures"], rng);
|
|
||||||
if(!source["spellCast"].isNull() && source["spellCast"].isStruct())
|
if(!source["spellCast"].isNull() && source["spellCast"].isStruct())
|
||||||
{
|
{
|
||||||
reward.spellCast.first = JsonRandom::loadSpell(source["spellCast"]["spell"], rng);
|
reward.spellCast.first = JsonRandom::loadSpell(source["spellCast"]["spell"], rng, variables);
|
||||||
reward.spellCast.second = source["spellCast"]["schoolLevel"].Integer();
|
reward.spellCast.second = source["spellCast"]["schoolLevel"].Integer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,11 +178,48 @@ void Rewardable::Info::configureResetInfo(Rewardable::Configuration & object, CR
|
|||||||
resetParameters.rewards = source["rewards"].Bool();
|
resetParameters.rewards = source["rewards"].Bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Rewardable::Info::configureVariables(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const
|
||||||
|
{
|
||||||
|
for(const auto & category : source.Struct())
|
||||||
|
{
|
||||||
|
for(const auto & entry : category.second.Struct())
|
||||||
|
{
|
||||||
|
JsonNode preset = object.getPresetVariable(category.first, entry.first);
|
||||||
|
int32_t value = -1;
|
||||||
|
|
||||||
|
if (category.first == "number")
|
||||||
|
value = JsonRandom::loadValue(entry.second, rng, object.variables.values);
|
||||||
|
|
||||||
|
if (category.first == "artifact")
|
||||||
|
value = JsonRandom::loadArtifact(entry.second, rng, object.variables.values).getNum();
|
||||||
|
|
||||||
|
if (category.first == "spell")
|
||||||
|
value = JsonRandom::loadSpell(entry.second, rng, object.variables.values).getNum();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// if (category.first == "creature")
|
||||||
|
// value = JsonRandom::loadCreature(entry.second, rng, object.variables.values).type->getId();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// if (category.first == "resource")
|
||||||
|
// value = JsonRandom::loadResource(entry.second, rng, object.variables.values).getNum();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// if (category.first == "primarySkill")
|
||||||
|
// value = JsonRandom::loadCreature(entry.second, rng, object.variables.values).getNum();
|
||||||
|
|
||||||
|
if (category.first == "secondarySkill")
|
||||||
|
value = JsonRandom::loadSecondary(entry.second, rng, object.variables.values).getNum();
|
||||||
|
|
||||||
|
object.initVariable(category.first, entry.first, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Rewardable::Info::configureRewards(
|
void Rewardable::Info::configureRewards(
|
||||||
Rewardable::Configuration & object,
|
Rewardable::Configuration & object,
|
||||||
CRandomGenerator & rng, const
|
CRandomGenerator & rng, const
|
||||||
JsonNode & source,
|
JsonNode & source,
|
||||||
std::map<si32, si32> & thrownDice,
|
|
||||||
Rewardable::EEventType event,
|
Rewardable::EEventType event,
|
||||||
const std::string & modeName) const
|
const std::string & modeName) const
|
||||||
{
|
{
|
||||||
@ -200,21 +230,27 @@ void Rewardable::Info::configureRewards(
|
|||||||
if (!reward["appearChance"].isNull())
|
if (!reward["appearChance"].isNull())
|
||||||
{
|
{
|
||||||
JsonNode chance = reward["appearChance"];
|
JsonNode chance = reward["appearChance"];
|
||||||
si32 diceID = static_cast<si32>(chance["dice"].Float());
|
std::string diceID = std::to_string(chance["dice"].Integer());
|
||||||
|
|
||||||
if (thrownDice.count(diceID) == 0)
|
auto diceValue = object.getVariable("dice", diceID);
|
||||||
thrownDice[diceID] = rng.getIntRange(0, 99)();
|
|
||||||
|
if (!diceValue.has_value())
|
||||||
|
{
|
||||||
|
object.initVariable("dice", diceID, rng.getIntRange(0, 99)());
|
||||||
|
diceValue = object.getVariable("dice", diceID);
|
||||||
|
}
|
||||||
|
assert(diceValue.has_value());
|
||||||
|
|
||||||
if (!chance["min"].isNull())
|
if (!chance["min"].isNull())
|
||||||
{
|
{
|
||||||
int min = static_cast<int>(chance["min"].Float());
|
int min = static_cast<int>(chance["min"].Float());
|
||||||
if (min > thrownDice[diceID])
|
if (min > *diceValue)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!chance["max"].isNull())
|
if (!chance["max"].isNull())
|
||||||
{
|
{
|
||||||
int max = static_cast<int>(chance["max"].Float());
|
int max = static_cast<int>(chance["max"].Float());
|
||||||
if (max <= thrownDice[diceID])
|
if (max <= *diceValue)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,11 +276,11 @@ void Rewardable::Info::configureObject(Rewardable::Configuration & object, CRand
|
|||||||
{
|
{
|
||||||
object.info.clear();
|
object.info.clear();
|
||||||
|
|
||||||
std::map<si32, si32> thrownDice;
|
configureVariables(object, rng, parameters["variables"]);
|
||||||
|
|
||||||
configureRewards(object, rng, parameters["rewards"], thrownDice, Rewardable::EEventType::EVENT_FIRST_VISIT, "rewards");
|
configureRewards(object, rng, parameters["rewards"], Rewardable::EEventType::EVENT_FIRST_VISIT, "rewards");
|
||||||
configureRewards(object, rng, parameters["onVisited"], thrownDice, Rewardable::EEventType::EVENT_ALREADY_VISITED, "onVisited");
|
configureRewards(object, rng, parameters["onVisited"], Rewardable::EEventType::EVENT_ALREADY_VISITED, "onVisited");
|
||||||
configureRewards(object, rng, parameters["onEmpty"], thrownDice, Rewardable::EEventType::EVENT_NOT_AVAILABLE, "onEmpty");
|
configureRewards(object, rng, parameters["onEmpty"], Rewardable::EEventType::EVENT_NOT_AVAILABLE, "onEmpty");
|
||||||
|
|
||||||
object.onSelect = loadMessage(parameters["onSelectMessage"], TextIdentifier(objectTextID, "onSelect"));
|
object.onSelect = loadMessage(parameters["onSelectMessage"], TextIdentifier(objectTextID, "onSelect"));
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@ class DLL_LINKAGE Info : public IObjectInfo
|
|||||||
JsonNode parameters;
|
JsonNode parameters;
|
||||||
std::string objectTextID;
|
std::string objectTextID;
|
||||||
|
|
||||||
void configureRewards(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source, std::map<si32, si32> & thrownDice, Rewardable::EEventType mode, const std::string & textPrefix) const;
|
void configureVariables(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const;
|
||||||
|
void configureRewards(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source, Rewardable::EEventType mode, const std::string & textPrefix) const;
|
||||||
|
|
||||||
void configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const;
|
void configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const;
|
||||||
Rewardable::LimitersList configureSublimiters(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const;
|
Rewardable::LimitersList configureSublimiters(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const;
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../CCreatureSet.h"
|
|
||||||
#include "../ResourceSet.h"
|
|
||||||
#include "../spells/ExternalCaster.h"
|
#include "../spells/ExternalCaster.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user