| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- import { _decorator, Component } from 'cc';
- import { HitEffectConfig, HitResult } from '../BulletTypes';
- const { ccclass } = _decorator;
- /**
- * 命中效果(可移植版):纯逻辑整合,不直接与敌人系统耦合
- */
- @ccclass('BCBulletHitEffect')
- export class BulletHitEffect extends Component {
- private effects: HitEffectConfig[] = [];
- private remainingPierce = 0;
- private remainingRicochet = 0;
- public init(effects: HitEffectConfig[]) {
- this.effects = [...(effects ?? [])].sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
- // 初始化穿透与弹射计数
- const pierce = this.effects.find(e => e.type === 'pierce_damage');
- const ricochet = this.effects.find(e => e.type === 'ricochet_damage');
- this.remainingPierce = Math.max(0, pierce?.pierceCount ?? 0);
- this.remainingRicochet = Math.max(0, ricochet?.ricochetCount ?? 0);
- }
- /**
- * 计算命中后结果(纯数据),由上层去应用到敌人/场景
- */
- public applyOnHit(): HitResult {
- if (!this.effects || this.effects.length === 0) return { didHit: true, damageApplied: 0 };
- let damage = 0;
- let ricochet = false;
- let ricochetAngle: number | undefined = undefined;
- let explosion = false;
- let explosionRadius: number | undefined = undefined;
- let spawnBurn = false;
- let burnPayload: HitResult['burn'] = null;
- for (const e of this.effects) {
- switch (e.type) {
- case 'normal_damage':
- damage += Math.max(0, e.damage ?? 0);
- break;
- case 'pierce_damage':
- damage += Math.max(0, e.damage ?? 0);
- // 穿透次数在命中后交由生命周期或外层减少
- break;
- case 'ricochet_damage':
- damage += Math.max(0, e.damage ?? 0);
- if (this.remainingRicochet > 0) {
- ricochet = true;
- ricochetAngle = e.ricochetAngle ?? ricochetAngle;
- }
- break;
- case 'explosion':
- damage += Math.max(0, e.damage ?? 0);
- explosion = true;
- explosionRadius = e.radius ?? explosionRadius;
- break;
- case 'ground_burn':
- // 地面燃烧不直接叠加伤害(由区域 DOT 管理)
- spawnBurn = true;
- burnPayload = {
- damagePerTick: Math.max(0, e.damage ?? 0),
- duration: Math.max(0, e.duration ?? 0),
- tickInterval: Math.max(0.05, e.tickInterval ?? 0.5)
- };
- break;
- }
- }
- const res: HitResult = {
- didHit: true,
- damageApplied: damage,
- ricochet,
- ricochetAngle,
- pierced: this.remainingPierce > 0,
- remainingPierce: this.remainingPierce,
- explosion,
- explosionRadius,
- spawnBurn,
- burn: burnPayload
- };
- return res;
- }
- /** 在外层确认穿透后调用,减少计数 */
- public consumePierce() {
- if (this.remainingPierce > 0) this.remainingPierce -= 1;
- }
- /** 在外层确认弹射后调用,减少计数 */
- public consumeRicochet() {
- if (this.remainingRicochet > 0) this.remainingRicochet -= 1;
- }
- }
|