Кровь некроманта: цена банки — 90% от максимального HP, не текущего (#87)

Было: 90% текущего HP на момент выдачи — очередь банок дешевела
геометрически, убить могло только при 1-4 HP. Стало: RoundToInt(
GetMaxHealth()*0.9); не хватило — HP уходит в 0, ваниль убивает
на следующем апдейте (disease). Выжить можно только при строго
больше 90% максимума.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-11-02 23:05:45 +03:00
co-authored by Claude Code
parent 340e1367aa
commit 0fdfe952c5
3 changed files with 25 additions and 11 deletions
+25 -11
View File
@@ -25,9 +25,11 @@ namespace NecromancerTome
/// something adjacent, but it takes exactly ONE item name, not "any item of a category",
/// and its actual runtime enforcement point wasn't confirmed by decompilation either -
/// not risking an untested mechanism for this).
/// 2. "При крафте нужно отнимать у персонажа 90% имеющегося ХП" - crafting this recipe
/// costs 90% of the player's CURRENT health. Recipes have no cost hook beyond their
/// ingredient list at all.
/// 2. "При крафте нужно отнимать у персонажа 90% имеющегося ХП" (2026-08-30), corrected
/// by the user on 2026-11-02: reading CURRENT health there was a bug. The cost is 90%
/// of the player's MAXIMUM health, and a necromancer whose current health is below
/// that dies from the ritual. Recipes have no cost hook beyond their ingredient list
/// at all.
///
/// "любого ножа" (ANY knife) is detected via ItemClass.DisplayType == "meleeKnife" - decompiled
/// Data/Config/items.xml directly: every real vanilla knife (meleeWpnBladeT0BoneKnife,
@@ -200,12 +202,24 @@ namespace NecromancerTome
{
return;
}
// Deliberately not clamped to leave the player at least 1 HP - the user asked for a
// straight 90% cost, and a blood ritual that can genuinely kill you if you're already
// badly hurt fits the theme. AddHealth is the same safe, non-combat HP-modification
// API vanilla itself uses (decompiled EntityAlive.AddHealth) - not DamageEntity/
// 90% of MAXIMUM health, per the user's correction of 2026-11-02 ("Это баг. Должно
// быть 90% от максимального здоровья. Таким образом, некромант погибнет, если
// здоровья в момент изготовления меньше 90%"). The original 2026-08-30 code read
// the CURRENT health, so a queue of jars got geometrically cheaper (100% -> 10% ->
// 1% of the starting HP) and could only kill at 1-4 HP through rounding.
//
// HOW DEATH HAPPENS, from the 3.4 decompile (don't "fix" this into a direct Kill
// call): Stat.Value's setter clamps to [0, ModifiedMax] (Utils.FastClamp), so HP
// bottoms out at exactly 0, never negative - and EntityAlive.OnUpdateLiving's own
// check `Health <= 0 && !IsDead() && !isEntityRemote && !IsGodMode.Value` kills the
// entity with DamageEntity(DamageSource.disease, 1) on the next update. A player
// who could not pay the full cost thus dies by vanilla's hand one frame later,
// logged as disease (god mode skips that check, leaving them merely at 0 HP).
// Survival takes strictly MORE than the cost: paying exactly it ends at 0 HP, and
// 0 HP is death in vanilla (the check is <= 0, not < 0). AddHealth stays the safe,
// non-combat HP-modification API vanilla itself uses - not DamageEntity/
// DamageResponse, since this isn't damage from a source, it's a direct self-cost.
int amount = Mathf.RoundToInt(__state.Health * NecromancerBloodPatch.HealthCostFraction);
int amount = Mathf.RoundToInt(__state.GetMaxHealth() * NecromancerBloodPatch.HealthCostFraction);
if (amount <= 0)
{
return;
@@ -213,9 +227,9 @@ namespace NecromancerTome
__state.AddHealth(-amount);
// The grunt goes AFTER the HP is actually gone, so a craft that somehow bailed out
// above never makes a sound the player cannot account for. At the 90% cost this is the
// big pain clip in every normal case (amount > 15 unless the player is already down to
// about 17 HP), and drops to the small one exactly where vanilla would drop it too.
// above never makes a sound the player cannot account for. With the cost now a fixed
// 0.9 * MaxHealth this is the big pain clip in every normal case (amount > 15 whenever
// MaxHealth >= 18), and drops to the small one exactly where vanilla would drop it too.
NecromancerBloodPatch.PlayPainSound(__state, amount);
Debug.Log("[NecromancerTome] NecromancerBloodPatch: crafted blood, deducted " + amount + " HP from owner=" + __state.entityId);