import type { EntityId } from 'db://assets/mx/module/ecs'; import { createAbilityContext } from 'db://assets/mx/module/battle/combat/AbilityContext'; import { EntityTag, HealthComp, TagComp } from 'db://assets/mx/module/battle'; import type { SkillPresentationContext } from '../skill/SkillPresentationTypes'; import { SkillPresentationEnv } from '../skill/SkillPresentationEnv'; /** Boss 不可被秒杀/斩杀 */ export function isBossEntity(entityId: EntityId): boolean { const session = SkillPresentationEnv.getBattleSession(); if (!session?.world.isAlive(entityId)) return false; return !!session.world.getComponent(entityId, TagComp)?.tags.includes(EntityTag.Boss); } /** 聚合已选词条 skill_special(含普攻 up_type=1) */ export function readSkillSpecialWan(caster: EntityId, specialType: number): number { let best = 0; for (const raw of SkillPresentationEnv.getSkillSpecials(caster)) { for (const seg of String(raw).split(';')) { const part = seg.trim(); if (!part) continue; const nums = part.split(',').map(Number); if ((nums[0] ?? 0) !== specialType || nums.length < 2) continue; best = Math.max(best, Math.max(0, Number(nums[1]) || 0)); } } return best; } function dealExecuteDamage( ctx: SkillPresentationContext, targetId: EntityId, damageType: string, ): boolean { const session = SkillPresentationEnv.getBattleSession(); if (!session?.world.isAlive(targetId)) return false; const floatPos = SkillPresentationEnv.resolveKillFloaterWorldPos(targetId); const abilityCtx = createAbilityContext(session, ctx.caster, ctx.abilityId, [targetId]); abilityCtx.level = ctx.level; const amount = session.damage.dealToTarget(ctx.caster, targetId, { percentMaxHpWan: 10000, scale: 1, damageType, skillAtkBuff1: '', skillAtkBuff2: '', }, abilityCtx); if (amount > 0 && floatPos) { SkillPresentationEnv.playKillFloater(floatPos, damageType); } return amount > 0; } /** skill_special 类型 10:概率秒杀(Boss 无效) */ export function tryInstantKill( ctx: SkillPresentationContext, targetId: EntityId, killWan: number, damageType = 'instant_kill', ): boolean { if (killWan <= 0 || isBossEntity(targetId)) return false; const rng = SkillPresentationEnv.getBattleRng(); const roll = (rng?.next() ?? Math.random()) * 10000; if (roll >= killWan) return false; return dealExecuteDamage(ctx, targetId, damageType); } /** skill_special 类型 11:HP 比例斩杀(Boss 无效) */ export function tryExecuteByThreshold( ctx: SkillPresentationContext, targetId: EntityId, thresholdWan: number, damageType = 'execute', ): boolean { if (thresholdWan <= 0 || isBossEntity(targetId)) return false; const session = SkillPresentationEnv.getBattleSession(); if (!session?.world.isAlive(targetId)) return false; const hp = session.world.getComponent(targetId, HealthComp); if (!hp || hp.maxHp <= 0) return false; if (hp.hp / hp.maxHp > thresholdWan / 10000) return false; return dealExecuteDamage(ctx, targetId, damageType); }