Correct minion sacrifice and passive talent semantics (refs #19)

Coordinator Root /root, session 01a12399-cfab-7c72-8455-e0e4cb7e156c.
Independently reviewed by /root/combat_source_finish_luna (GPT-6 Luna xhigh).
31 focused DK tests, required release check and complete source type check pass.
This commit is contained in:
warren committed 2026-10-15 09:09:45 -04:00
1 parent a9322a3897
commit 3687c423e2
11 files changed
+284 -10

No files matched your search

+16 -2
View File
@@ -1,3 +1,4 @@
import { eligibleSacrificeMinion } from "./sacrificeMinion";
import { healerManaRecoveryAmount } from "./healerManaRecovery";
import { nativeDisarmedMainHandAutoAttackProfile, nativeTrainingAutoAttackProfile } from "./romNativeCombatAmount";
import { romNativePlayerHitProfile } from "./romNativeCombatResolution";
@@ -2666,6 +2667,8 @@ export function partyAbilityTargetIsValid(
|| (metamorphosisActive && !warlockMetamorphosisCanCastAbilityWhileActive(ability))) return false;
}
const origin = getPartyRuntimePosition(member.id) ?? combat.playerPosition;
if (ability.effects.some((effect) => effect.kind === "sacrifice-minion"
&& !eligibleSacrificeMinion(combat.summons, member.id, effect, origin, now))) return false;
const meditationAllowsMovement = romMageWarriorMeditationPathAllowsMovement(
member.classId,
member.secondaryClassId,
@@ -3190,7 +3193,7 @@ function choosePartySupportIntent(
lowestHealthFraction: target.health / Math.max(1, target.maxHealth),
friendlyTargets,
maintainedAbilityIds,
canUseAbility: ability => ability.effects.some(effect => ["heal", "hot", "shield"].includes(effect.kind)
canUseAbility: ability => ability.effects.some(effect => ["heal", "hot", "shield", "sacrifice-minion"].includes(effect.kind)
|| (effect.kind === "apply-aura" && Boolean(effect.aura.absorbs?.length)))
&& (healingAbilityCanAidOthers(ability) || target.id === member.id)
&& !(healingAbilityHasPendingHot(ability, member.id, target.id, combat.effects)
@@ -4587,6 +4590,17 @@ function executePartyAbility(
ability.id,
now,
);
} else if (effect.kind === "sacrifice-minion") {
if (!useCombatStore.getState().sacrificeActorMinion(member.id, ability.id, effect, origin, now)) continue;
const result = useCombatStore.getState().healActor(member.id,
Math.round(member.maxHealth * effect.percentMaxHealth), {
sourceActorId: member.id, abilityId: ability.id, school: spellSchool,
criticalChance: 0, now,
});
effectiveAmount += result.effectiveAmount;
directHealingRawAmount += result.rawAmount;
combat = useCombatStore.getState();
runtimeMember = memberFromCompanionActor(runtimeMember, combat.actors[member.id]);
} else if (effect.kind === "execute") {
for (const hostileTargetId of hostileTargets) {
const target = useCombatStore.getState().mobs[hostileTargetId];
@@ -5147,7 +5161,7 @@ function executePartyAbility(
}
emitPartyAbility(member, ability, targetId, "release", now, !castStartAlreadyEmitted);
emitPartyAbility(member, ability, targetId, "impact", now, !castStartAlreadyEmitted);
if (effectiveAmount > 0 && ability.effects.some((effect) => ["heal", "hot", "shield", "resurrection"].includes(effect.kind))) {
if (effectiveAmount > 0 && ability.effects.some((effect) => ["heal", "hot", "shield", "resurrection", "sacrifice-minion"].includes(effect.kind))) {
useCombatStore.getState().addHealingThreat({ actorId: member.id, role: member.role, abilityId: ability.id }, effectiveAmount);
}
if (suddenDoomTrigger && depth === 0) {