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

vcmi: move obligatory marker to CSkillHandler

It is working, now it is possible to
define other obligatory skills than wisdom or magic schools,
but only 2 types of obligatory skills exists - like wisdom and
like magic school
This commit is contained in:
Konstantin 2023-02-27 12:42:57 +03:00
parent 4acf3778ef
commit f26fac5562
5 changed files with 61 additions and 28 deletions

View File

@ -60,6 +60,14 @@
"type": "string", "type": "string",
"description": "localizable skill name" "description": "localizable skill name"
}, },
"obligatoryMajor":{
"type": "boolean",
"description": "This skill is major obligatory (like H3 Wisdom)"
},
"obligatoryMinor":{
"type": "boolean",
"description": "This skill is minor obligatory (like H3 Magic school)"
},
"gainChance" : { "gainChance" : {
"description" : "Chance for the skill to be offered on level-up (heroClass may override)", "description" : "Chance for the skill to be offered on level-up (heroClass may override)",
"anyOf" : [ "anyOf" : [

View File

@ -196,6 +196,7 @@
}, },
"wisdom" : { "wisdom" : {
"index" : 7, "index" : 7,
"obligatoryMajor" : true,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@ -401,6 +402,7 @@
}, },
"fireMagic" : { "fireMagic" : {
"index" : 14, "index" : 14,
"obligatoryMinor" : true,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@ -428,6 +430,7 @@
}, },
"airMagic" : { "airMagic" : {
"index" : 15, "index" : 15,
"obligatoryMinor" : true,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@ -455,6 +458,7 @@
}, },
"waterMagic" : { "waterMagic" : {
"index" : 16, "index" : 16,
"obligatoryMinor" : true,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {
@ -482,6 +486,7 @@
}, },
"earthMagic" : { "earthMagic" : {
"index" : 17, "index" : 17,
"obligatoryMinor" : true,
"base" : { "base" : {
"effects" : { "effects" : {
"main" : { "main" : {

View File

@ -33,8 +33,8 @@ CSkill::LevelInfo::~LevelInfo()
{ {
} }
CSkill::CSkill(SecondarySkill id, std::string identifier) CSkill::CSkill(SecondarySkill id, std::string identifier, bool obligatoryMajor, bool obligatoryMinor)
: id(id), identifier(identifier) : id(id), identifier(identifier), obligatoryMajor(obligatoryMajor), obligatoryMinor(obligatoryMinor)
{ {
gainChance[0] = gainChance[1] = 0; //affects CHeroClassHandler::afterLoadFinalization() gainChance[0] = gainChance[1] = 0; //affects CHeroClassHandler::afterLoadFinalization()
levels.resize(NSecondarySkill::levels.size() - 1); levels.resize(NSecondarySkill::levels.size() - 1);
@ -207,8 +207,11 @@ CSkill * CSkillHandler::loadFromJson(const std::string & scope, const JsonNode &
{ {
assert(identifier.find(':') == std::string::npos); assert(identifier.find(':') == std::string::npos);
assert(!scope.empty()); assert(!scope.empty());
bool major, minor;
CSkill * skill = new CSkill(SecondarySkill((si32)index), identifier); major = json["obligatoryMajor"].Bool();
minor = json["obligatoryMinor"].Bool();
CSkill * skill = new CSkill(SecondarySkill((si32)index), identifier, major, minor);
skill->modScope = scope; skill->modScope = scope;
VLC->generaltexth->registerString(scope, skill->getNameTextID(), json["name"].String()); VLC->generaltexth->registerString(scope, skill->getNameTextID(), json["name"].String());

View File

@ -51,9 +51,15 @@ private:
std::string identifier; std::string identifier;
public: public:
CSkill(SecondarySkill id = SecondarySkill::DEFAULT, std::string identifier = "default"); CSkill(SecondarySkill id = SecondarySkill::DEFAULT, std::string identifier = "default", bool obligatoryMajor = false, bool obligatoryMinor = false);
~CSkill(); ~CSkill();
enum class Obligatory : ui8
{
MAJOR = 0,
MINOR = 1,
};
int32_t getIndex() const override; int32_t getIndex() const override;
int32_t getIconIndex() const override; int32_t getIconIndex() const override;
std::string getJsonKey() const override; std::string getJsonKey() const override;
@ -70,6 +76,7 @@ public:
LevelInfo & at(int level); LevelInfo & at(int level);
std::string toString() const; std::string toString() const;
bool obligatory(Obligatory val) const { return val == Obligatory::MAJOR ? obligatoryMajor : obligatoryMinor; };
std::array<si32, 2> gainChance; // gainChance[0/1] = default gain chance on level-up for might/magic heroes std::array<si32, 2> gainChance; // gainChance[0/1] = default gain chance on level-up for might/magic heroes
@ -82,11 +89,16 @@ public:
h & identifier; h & identifier;
h & gainChance; h & gainChance;
h & levels; h & levels;
h & obligatoryMajor;
h & obligatoryMinor;
} }
friend class CSkillHandler; friend class CSkillHandler;
friend DLL_LINKAGE std::ostream & operator<<(std::ostream & out, const CSkill & skill); friend DLL_LINKAGE std::ostream & operator<<(std::ostream & out, const CSkill & skill);
friend DLL_LINKAGE std::ostream & operator<<(std::ostream & out, const CSkill::LevelInfo & info); friend DLL_LINKAGE std::ostream & operator<<(std::ostream & out, const CSkill::LevelInfo & info);
private:
bool obligatoryMajor;
bool obligatoryMinor;
}; };
class DLL_LINKAGE CSkillHandler: public CHandlerBase<SecondarySkill, Skill, CSkill, SkillService> class DLL_LINKAGE CSkillHandler: public CHandlerBase<SecondarySkill, Skill, CSkill, SkillService>

View File

@ -1145,28 +1145,41 @@ ArtBearer::ArtBearer CGHeroInstance::bearerType() const
std::vector<SecondarySkill> CGHeroInstance::getLevelUpProposedSecondarySkills() const std::vector<SecondarySkill> CGHeroInstance::getLevelUpProposedSecondarySkills() const
{ {
std::vector<SecondarySkill> obligatorySkills; //hero is offered magic school or wisdom if possible std::vector<SecondarySkill> obligatorySkills; //hero is offered magic school or wisdom if possible
if (!skillsInfo.wisdomCounter)
{
if (canLearnSkill(SecondarySkill::WISDOM))
obligatorySkills.emplace_back(SecondarySkill::WISDOM);
}
if (!skillsInfo.magicSchoolCounter)
{
std::vector<SecondarySkill> ss =
{
SecondarySkill::FIRE_MAGIC, SecondarySkill::AIR_MAGIC, SecondarySkill::WATER_MAGIC, SecondarySkill::EARTH_MAGIC
};
auto getObligatorySkills = [](CSkill::Obligatory obl){
std::vector<SecondarySkill> obligatory = {};
for(int i = 0; i < VLC->skillh->size(); i++)
if((*VLC->skillh)[SecondarySkill(i)]->obligatory(obl))
{
obligatory.emplace_back(i);
break;
}
return obligatory;
};
auto selectObligatorySkill = [&](std::vector<SecondarySkill>& ss) -> void
{
std::shuffle(ss.begin(), ss.end(), skillsInfo.rand.getStdGenerator()); std::shuffle(ss.begin(), ss.end(), skillsInfo.rand.getStdGenerator());
for(const auto & skill : ss) for(const auto & skill : ss)
{ {
if (canLearnSkill(skill)) //only schools hero doesn't know yet if (canLearnSkill(skill)) //only skills hero doesn't know yet
{ {
obligatorySkills.push_back(skill); obligatorySkills.push_back(skill);
break; //only one break; //only one
} }
} }
};
if (!skillsInfo.wisdomCounter)
{
auto obligatory = getObligatorySkills(CSkill::Obligatory::MAJOR);
selectObligatorySkill(obligatory);
}
if (!skillsInfo.magicSchoolCounter)
{
auto obligatory = getObligatorySkills(CSkill::Obligatory::MINOR);
selectObligatorySkill(obligatory);
} }
std::vector<SecondarySkill> skills; std::vector<SecondarySkill> skills;
@ -1339,20 +1352,12 @@ void CGHeroInstance::levelUp(const std::vector<SecondarySkill> & skills)
//deterministic secondary skills //deterministic secondary skills
skillsInfo.magicSchoolCounter = (skillsInfo.magicSchoolCounter + 1) % maxlevelsToMagicSchool(); skillsInfo.magicSchoolCounter = (skillsInfo.magicSchoolCounter + 1) % maxlevelsToMagicSchool();
skillsInfo.wisdomCounter = (skillsInfo.wisdomCounter + 1) % maxlevelsToWisdom(); skillsInfo.wisdomCounter = (skillsInfo.wisdomCounter + 1) % maxlevelsToWisdom();
if(vstd::contains(skills, SecondarySkill::WISDOM)) for(const auto & skill : skills)
{ {
skillsInfo.resetWisdomCounter(); if((*VLC->skillh)[skill]->obligatory(CSkill::Obligatory::MAJOR))
} skillsInfo.resetWisdomCounter();
if((*VLC->skillh)[skill]->obligatory(CSkill::Obligatory::MINOR))
SecondarySkill spellSchools[] = {
SecondarySkill::FIRE_MAGIC, SecondarySkill::AIR_MAGIC, SecondarySkill::WATER_MAGIC, SecondarySkill::EARTH_MAGIC};
for(const auto & skill : spellSchools)
{
if(vstd::contains(skills, skill))
{
skillsInfo.resetMagicSchoolCounter(); skillsInfo.resetMagicSchoolCounter();
break;
}
} }
//update specialty and other bonuses that scale with level //update specialty and other bonuses that scale with level