From 07dcdc1f851e1aebe8099ccc80ab8d4976264203 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 3 Jun 2025 19:38:54 +0300 Subject: [PATCH] Percentage-based mana regeneration Hota-like mysticism. Bonus FULL_MANA_REGENERATION (Wizard well) has been replaced with MANA_PERCENTAGE_REGENERATION bonus. Wizard well now has new bonus with 100% value. --- AI/Nullkiller/AIUtility.cpp | 8 ++++---- config/artifacts.json | 4 ++-- docs/modders/Bonus/Bonus_Types.md | 6 ++++-- lib/bonuses/BonusEnum.h | 2 +- lib/mapObjects/CGHeroInstance.cpp | 7 ++++--- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/AI/Nullkiller/AIUtility.cpp b/AI/Nullkiller/AIUtility.cpp index 54466e15b..f5d18552e 100644 --- a/AI/Nullkiller/AIUtility.cpp +++ b/AI/Nullkiller/AIUtility.cpp @@ -410,9 +410,9 @@ double getArtifactBonusRelevance(const CGHeroInstance * hero, const std::shared_ if (bonus->subtype == BonusCustomSubtype::damageTypeMelee) return veryRelevant * (1 - getArmyPercentageWithBonus(BonusType::SHOOTER)); return 0; - case BonusType::FULL_MANA_REGENERATION: + case BonusType::MANA_PERCENTAGE_REGENERATION: case BonusType::MANA_REGENERATION: - return hero->mana < hero->manaLimit() ? relevant : notRelevant; + return hero->hasSpellbook() ? relevant : notRelevant; case BonusType::LEARN_BATTLE_SPELL_CHANCE: return hero->hasBonusOfType(BonusType::LEARN_BATTLE_SPELL_LEVEL_LIMIT) ? relevant : notRelevant; case BonusType::NO_DISTANCE_PENALTY: @@ -483,8 +483,8 @@ int32_t getArtifactBonusScoreImpl(const std::shared_ptr & bonus) return 0; case BonusType::CREATURE_GROWTH: return (1+bonus->subtype.getNum()) * bonus->val * 400; - case BonusType::FULL_MANA_REGENERATION: - return 15000; + case BonusType::MANA_PERCENTAGE_REGENERATION: + return bonus->val * 150; case BonusType::MANA_REGENERATION: return bonus->val * 500; case BonusType::SPELLS_OF_SCHOOL: diff --git a/config/artifacts.json b/config/artifacts.json index ff9938923..d0addb117 100644 --- a/config/artifacts.json +++ b/config/artifacts.json @@ -2219,8 +2219,8 @@ { "bonuses" : { "mana" : { - "type" : "FULL_MANA_REGENERATION", - "val" : 0, + "type" : "MANA_PERCENTAGE_REGENERATION", + "val" : 100, "valueType" : "BASE_NUMBER" } }, diff --git a/docs/modders/Bonus/Bonus_Types.md b/docs/modders/Bonus/Bonus_Types.md index d82160184..bda9d241e 100644 --- a/docs/modders/Bonus/Bonus_Types.md +++ b/docs/modders/Bonus/Bonus_Types.md @@ -105,9 +105,11 @@ Restores specific amount of mana points for affected heroes on new turn - val: amount of spell points to restore -### FULL_MANA_REGENERATION +### MANA_PERCENTAGE_REGENERATION -Restores entire mana pool for affected heroes on new turn +Restores specific percentage of mana pool for affected heroes on new turn. If hero has both MANA_REGENERATION and MANA_PERCENTAGE_REGENERATION, only bonus that gives more mana points will be active + +- val: percentage of spell points to restore ### NONEVIL_ALIGNMENT_MIX diff --git a/lib/bonuses/BonusEnum.h b/lib/bonuses/BonusEnum.h index be8113504..7781fb498 100644 --- a/lib/bonuses/BonusEnum.h +++ b/lib/bonuses/BonusEnum.h @@ -24,7 +24,7 @@ class JsonNode; BONUS_NAME(PRIMARY_SKILL) /*uses subtype to pick skill; additional info if set: 1 - only melee, 2 - only distance*/ \ BONUS_NAME(SIGHT_RADIUS) \ BONUS_NAME(MANA_REGENERATION) /*points per turn*/ \ - BONUS_NAME(FULL_MANA_REGENERATION) /*all mana points are replenished every day*/ \ + BONUS_NAME(MANA_PERCENTAGE_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(SURRENDER_DISCOUNT) /*%*/ \ BONUS_NAME(STACKS_SPEED) /*additional info - percent of speed bonus applied after direct bonuses; >0 - added, <0 - subtracted to this part*/ \ diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index dd5575ec0..13d75bc6f 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -1067,10 +1067,11 @@ int CGHeroInstance::getSightRadius() const si32 CGHeroInstance::manaRegain() const { - if (hasBonusOfType(BonusType::FULL_MANA_REGENERATION)) - return manaLimit(); + int percentageRegeneration = valOfBonuses(BonusType::MANA_PERCENTAGE_REGENERATION); + int regeneratedByPercentage = manaLimit() * percentageRegeneration / 100; + int regeneratedByValue = valOfBonuses(BonusType::MANA_REGENERATION); - return valOfBonuses(BonusType::MANA_REGENERATION); + return std::max(regeneratedByValue, regeneratedByPercentage); } si32 CGHeroInstance::getManaNewTurn() const