A huge thank you to Evil Hero for pointing out a serious oversight in my coding. Here are the corrections that need to be made to the code so that the skill increase is only affecting each specific, individual monster, and not affecting the skill of the entire MonsterType class.
First, in monster.h, right above
int32_t getDefense() final;
, we need to create a new function to get the local skill (we'll use this later):
C++:
int32_t getSkill() const {
return skill;
}
We also need to declare
skill
and
tries
as new variables for the
Monster
class specifically. Underneath
uint64_t skillTries = 0;
add:
C++:
int32_t skill = 0;
int64_t tries = 0;
Now, in monster.cpp, in
Monster::Monster
, underneath
skillTries = 0;
, we need to initialize these variables. But, we aren't going to initialize them as 0, we're going to initialize them as whatever that particular monster's skill is:
C++:
skill = mType->info.skill;
tries = mType->info.tries;
Now, we're going to modify
skill
and
tries
that are tied to the specific monster, not the entire mType. So, we need to change anywhere in the function
void Monster::addSkillAdvance
that was incorrectly referencing
info.skills
or
info.tries
. Also, I added an important additional check to prevent an infinite 'while' loop:
C++:
void Monster::addSkillAdvance(int count) {
const float TRIES_INCREASE_FACTOR = (float)mType->info.multiplier / 1000; // unchanged
const uint64_t MAX_TRIES_VALUE = std::numeric_limits<uint64_t>::max(); // unchanged
skillTries += count;// unchanged, skillTries was already specific to Monster
uint64_t levelUpThreshold = tries; //this changed, now referencing the specific tries value
if (levelUpThreshold == 0) {//IMPORTANT! If a monster summons a creature with tries=0, your game will freeze due to infinite loop without this check! For example, novices of the cult summon chickens!
return;
}
while (skillTries >= levelUpThreshold) { // unchanged
skillTries -= levelUpThreshold;// unchanged
skill++;//changed, incrementing the specific monster's skill
levelUpThreshold *= TRIES_INCREASE_FACTOR; // unchanged
if (levelUpThreshold > MAX_TRIES_VALUE) { // unchanged
std::cout << "Overflow detected. Exiting function." << std::endl;
return;
}
tries = static_cast<uint64_t>(levelUpThreshold); //changed, need to write back to tries for the specific Monster
}
}
This is not all, however. There are other functions that use a monster's skill value, and those functions are referencing
mType->info.skill
either directly or indirectly. This means that while a specific monster's skills might be leveling up, all of the important formulas (damage, defense) aren't even using the new level!
So, a little further down in monster.cpp, in
int32_t Monster::getDefense()
, we need to change this line
int32_t defenseSkill = mType->info.skill;
to this:
C++:
int32_t defenseSkill = skill;//when calculating a monsters defense, which happens anytime they take a hit, now we will use the newly-created skill variable that is specific to each individual monster
Finally, we need to do something similar in combat.cpp. Find the function
void Combat::getAttackValue
and at the very bottom, the last
else if
statement, change
skillValue = monster->mType->info.skill;
to:
C++:
skillValue = monster->getSkill();//reference our newly created getSkill function from the first step, this returns the skill value specific to the individual monster
Here is a snapshot of it working live (I boosted the skill gain rate by 10x to make it quicker to see the difference):
Then, after they had all trained up a bit, I hit each one of the spiders individually with a melee attack, and they each have their own defense value based on how long they had been training:
Thanks again to Evil Hero for pointing out my mistake. Now, it should now be working as intended!