瀏覽代碼

added bonus type SECONDARY_SKILL_VAL2; refactored CSkillHandler::defaultBonus; made eagleEye level bonus-based

Henning Koehler 8 年之前
父節點
當前提交
25e6b5cc07
共有 5 個文件被更改,包括 92 次插入32 次删除
  1. 53 0
      config/skills.json
  2. 35 28
      lib/CSkillHandler.cpp
  3. 1 1
      lib/CSkillHandler.h
  4. 1 0
      lib/HeroBonus.h
  5. 2 3
      server/CGameHandler.cpp

+ 53 - 0
config/skills.json

@@ -369,6 +369,59 @@
             ]
         }
     },
+    "eagleEye" : {
+        "basic" : {
+            "description" : "",
+            "effects" : [
+                {
+                    "subtype" : "skill.eagleEye",
+                    "type" : "SECONDARY_SKILL_PREMY",
+                    "val" : 40,
+                    "valueType" : "BASE_NUMBER"
+                },
+                {
+                    "subtype" : "skill.eagleEye",
+                    "type" : "SECONDARY_SKILL_VAL2",
+                    "val" : 2,
+                    "valueType" : "BASE_NUMBER"
+                }
+            ]
+        },
+        "advanced" : {
+            "description" : "",
+            "effects" : [
+                {
+                    "subtype" : "skill.eagleEye",
+                    "type" : "SECONDARY_SKILL_PREMY",
+                    "val" : 50,
+                    "valueType" : "BASE_NUMBER"
+                },
+                {
+                    "subtype" : "skill.eagleEye",
+                    "type" : "SECONDARY_SKILL_VAL2",
+                    "val" : 3,
+                    "valueType" : "BASE_NUMBER"
+                }
+            ]
+        },
+        "expert" : {
+            "description" : "",
+            "effects" : [
+                {
+                    "subtype" : "skill.eagleEye",
+                    "type" : "SECONDARY_SKILL_PREMY",
+                    "val" : 60,
+                    "valueType" : "BASE_NUMBER"
+                },
+                {
+                    "subtype" : "skill.eagleEye",
+                    "type" : "SECONDARY_SKILL_VAL2",
+                    "val" : 4,
+                    "valueType" : "BASE_NUMBER"
+                }
+            ]
+        }
+    },
     "estates" : {
         "basic" : {
             "description" : "With Basic Estates, a hero contributes 125 gold per day to your cause.",

+ 35 - 28
lib/CSkillHandler.cpp

@@ -54,6 +54,7 @@ CSkill::~CSkill()
 void CSkill::addNewBonus(const std::shared_ptr<Bonus>& b, int level)
 {
     b->source = Bonus::SECONDARY_SKILL;
+	b->sid = id;
     b->duration = Bonus::PERMANENT;
     b->description = identifier;
     levels[level-1].effects.push_back(b);
@@ -104,7 +105,8 @@ CSkillHandler::CSkillHandler()
     {
         CSkill * skill = new CSkill(SecondarySkill(id));
         for(int level = 1; level < NSecondarySkill::levels.size(); level++)
-            skill->addNewBonus(defaultBonus(SecondarySkill(id), level), level);
+			for (auto bonus : defaultBonus(SecondarySkill(id), level))
+				skill->addNewBonus(bonus, level);
         objects.push_back(skill);
     }
 }
@@ -209,56 +211,61 @@ std::vector<bool> CSkillHandler::getDefaultAllowed() const
 }
 
 // HMM3 default bonus provided by secondary skill
-const std::shared_ptr<Bonus> CSkillHandler::defaultBonus(SecondarySkill skill, int level) const
+std::vector<std::shared_ptr<Bonus>> CSkillHandler::defaultBonus(SecondarySkill skill, int level) const
 {
-	Bonus::BonusType bonusType = Bonus::SECONDARY_SKILL_PREMY;
-	Bonus::ValueType valueType = Bonus::BASE_NUMBER;
-	int bonusVal = level;
+	std::vector<std::shared_ptr<Bonus>> result;
 
-	switch (skill)
+	// add bonus based on current values - useful for adding multiple bonuses easily
+	auto addBonus = [=,&result](int bonusVal, Bonus::BonusType bonusType = Bonus::SECONDARY_SKILL_PREMY) {
+		int subtype = (bonusType == Bonus::SECONDARY_SKILL_PREMY || bonusType == Bonus::SECONDARY_SKILL_VAL2) ? skill : 0;
+		result.push_back(std::make_shared<Bonus>(Bonus::PERMANENT, bonusType, Bonus::SECONDARY_SKILL, bonusVal, skill, subtype, Bonus::BASE_NUMBER));
+	};
+
+	switch(skill)
 	{
 	case SecondarySkill::PATHFINDING:
-		bonusVal = 25 * level; break;
+		addBonus(25 * level); break;
 	case SecondarySkill::ARCHERY:
-		bonusVal = 5 + 5 * level * level; break;
+		addBonus(5 + 5 * level * level); break;
 	case SecondarySkill::LOGISTICS:
-		bonusVal = 10 * level; break;
+		addBonus(10 * level); break;
 	case SecondarySkill::SCOUTING:
-		bonusType = Bonus::SIGHT_RADIOUS; break;
+		addBonus(level, Bonus::SIGHT_RADIOUS); break;
 	case SecondarySkill::DIPLOMACY:
-		bonusType = Bonus::SURRENDER_DISCOUNT;
-		bonusVal = 20 * level; break;
+		addBonus(20 * level, Bonus::SURRENDER_DISCOUNT); break;
 	case SecondarySkill::NAVIGATION:
-		bonusVal = 50 * level; break;
+		addBonus(50 * level); break;
 	case SecondarySkill::LEADERSHIP:
-		bonusType = Bonus::MORALE; break;
+		addBonus(level, Bonus::MORALE); break;
 	case SecondarySkill::LUCK:
-		bonusType = Bonus::LUCK; break;
+		addBonus(level, Bonus::LUCK); break;
 	case SecondarySkill::EAGLE_EYE:
-		bonusVal = 30 + 10 * level; break;
+		addBonus(30 + 10 * level);
+		addBonus(1 + level, Bonus::SECONDARY_SKILL_VAL2);
+		break;
 	case SecondarySkill::NECROMANCY:
-		bonusVal = 10 * level; break;
+		addBonus(10 * level); break;
 	case SecondarySkill::ESTATES:
-		bonusVal = 125 << (level-1); break;
+		addBonus(125 << (level-1)); break;
 	case SecondarySkill::TACTICS:
-		bonusVal = 1 + 2 * level; break;
+		addBonus(1 + 2 * level); break;
 	case SecondarySkill::LEARNING:
-		bonusVal = 5 * level; break;
+		addBonus(5 * level); break;
 	case SecondarySkill::OFFENCE:
-		bonusVal = 10 * level; break;
+		addBonus(10 * level); break;
 	case SecondarySkill::ARMORER:
-		bonusVal = 5 * level; break;
+		addBonus(5 * level); break;
 	case SecondarySkill::INTELLIGENCE:
-		bonusVal = 25 << (level-1); break;
+		addBonus(25 << (level-1)); break;
 	case SecondarySkill::SORCERY:
-		bonusVal = 5 * level; break;
+		addBonus(5 * level); break;
 	case SecondarySkill::RESISTANCE:
-		bonusVal = 5 << (level-1); break;
+		addBonus(5 << (level-1)); break;
 	case SecondarySkill::FIRST_AID:
-		bonusVal = 25 + 25 * level; break;
+		addBonus(25 + 25 * level); break;
 	default:
-		break;
+		addBonus(level); break;
 	}
 
-	return std::make_shared<Bonus>(Bonus::PERMANENT, bonusType, Bonus::SECONDARY_SKILL, bonusVal, skill, skill, valueType);
+	return result;
 }

+ 1 - 1
lib/CSkillHandler.h

@@ -84,5 +84,5 @@ public:
 
 protected:
     CSkill * loadFromJson(const JsonNode & json, const std::string & identifier) override;
-    const std::shared_ptr<Bonus> defaultBonus(SecondarySkill skill, int level) const;
+	std::vector<std::shared_ptr<Bonus>> defaultBonus(SecondarySkill skill, int level) const;
 };

+ 1 - 0
lib/HeroBonus.h

@@ -95,6 +95,7 @@ private:
 	BONUS_NAME(FULL_MANA_REGENERATION) /*all mana points are replenished every day*/  \
 	BONUS_NAME(NONEVIL_ALIGNMENT_MIX) /*good and neutral creatures can be mixed without morale penalty*/  \
 	BONUS_NAME(SECONDARY_SKILL_PREMY) /*%*/  \
+	BONUS_NAME(SECONDARY_SKILL_VAL2) /*for secondary skills that have multiple effects, like eagle eye (max level and chance)*/  \
 	BONUS_NAME(SURRENDER_DISCOUNT) /*%*/  \
 	BONUS_NAME(STACKS_SPEED)  /*additional info - percent of speed bonus applied after direct bonuses; >0 - added, <0 - subtracted to this part*/ \
 	BONUS_NAME(FLYING_MOVEMENT) /*value - penalty percentage*/ \

+ 2 - 3
server/CGameHandler.cpp

@@ -592,12 +592,11 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
 
 	if (finishingBattle->winnerHero)
 	{
-		if (int eagleEyeLevel = finishingBattle->winnerHero->getSecSkillLevel(SecondarySkill::EAGLE_EYE))
+		if (int eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_VAL2, SecondarySkill::EAGLE_EYE))
 		{
-			int maxLevel = eagleEyeLevel + 1;
 			double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::EAGLE_EYE);
 			for (const CSpell *sp : gs->curB->sides.at(!battleResult.data->winner).usedSpellsHistory)
-				if (sp->level <= maxLevel && !vstd::contains(finishingBattle->winnerHero->spells, sp->id) && getRandomGenerator().nextInt(99) < eagleEyeChance)
+				if (sp->level <= eagleEyeLevel && !vstd::contains(finishingBattle->winnerHero->spells, sp->id) && getRandomGenerator().nextInt(99) < eagleEyeChance)
 					cs.spells.insert(sp->id);
 		}
 	}