yyl
4 天以前 9e02ad77aaa40cd0d8be76f7fb7846d682b3746d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using Spine.Unity;
using UnityEngine.UI;
using System.Linq;
 
public enum BattleCamp
{
    Red,
    Blue
}
 
public enum BattleState
{
    None = 0,
    Stunned = 1 << 0,
    Poisoned = 1 << 1,
    Bleeding = 1 << 2,
    Silenced = 1 << 3,
    Frozen = 1 << 4,
    Burned = 1 << 5
}
 
public abstract class BattleObject
{
    public BattleField battleField;
 
    public BattleObjectLayerMgr layerMgr;
 
    public int ObjID { get; set; }
 
    public BattleCamp Camp { get; protected set; }
 
    public BattleObject(BattleField _battleField)
    {
        battleField = _battleField;
    }
 
    // ============ 抽象访问方法(子类返回各自的Team类型信息) ============
    
    public abstract int GetPositionNum();
    public abstract float GetModelScale();
    public abstract string GetName();
    
    // Buff 管理器访问方法(Hero 有 buff,Mingge 返回 null)
    public abstract BattleObjectBuffMgr GetBuffMgr();
    
    // 状态查询抽象方法
    protected abstract bool GetIsStunned();
    protected abstract bool GetIsFrozen();
    protected abstract bool GetIsStoned();
    protected abstract bool GetIsSlient();
    protected abstract bool GetIsDisarmed();
    protected abstract bool GetIsInvincible();
    protected abstract bool GetIsDead();
    public abstract int GetRage();
    
    // 血量相关抽象方法(Hero 特有,Mingge 返回默认值)
    public abstract long GetCurHp();
    public abstract long GetMaxHp();
    public abstract void SetCurHp(long value);
    public abstract void SetIsDead(bool value);
    
    // 其他属性访问方法
    public abstract int GetNPCID();
    public abstract long GetFightPower();
 
    public abstract void Run();
 
    public abstract void Pause();
 
    public abstract void Resume();
 
    public abstract void Destroy();
 
    // ============ 动画相关抽象方法(替代 motionBase 直接调用) ============
    
    /// <summary>
    /// 播放动画
    /// </summary>
    public abstract void PlayAnimation(MotionName motionName, bool loop);
    
    /// <summary>
    /// 显示幻影残影
    /// </summary>
    public abstract void ShowIllusionShadow(bool show, Color? color = null);
    
    /// <summary>
    /// 播放技能动画
    /// </summary>
    public abstract Spine.TrackEntry PlaySkillAnimation(SkillConfig skillConfig, SkillSkinConfig skillSkinConfig, SkillBase skillBase, bool isCounter, Action onComplete);
    
    /// <summary>
    /// 检查是否可以开始死亡
    /// </summary>
    public abstract bool CanStartDeath();
    
    /// <summary>
    /// 检查是否可以释放技能
    /// </summary>
    public abstract bool CanCastSkillAnimation(SkillSkinConfig skillSkinConfig);
    
    /// <summary>
    /// 获取骨骼动画组件(用于特效挂载等)
    /// </summary>
    public abstract SkeletonAnimation GetSkeletonAnimation();
    
    /// <summary>
    /// 设置骨骼动画透明度
    /// </summary>
    public abstract void SetSkeletonAlpha(float alpha);
    
    /// <summary>
    /// 获取 RectTransform(用于移动等操作)
    /// </summary>
    public virtual RectTransform GetRectTransform() => null;
    
    /// <summary>
    /// 获取 GameObject
    /// </summary>
    public virtual GameObject GetGameObject() => null;
    
    /// <summary>
    /// 获取 Transform(用于特效挂载等)
    /// </summary>
    public virtual Transform GetTransform() => null;
    
    /// <summary>
    /// 获取世界坐标位置
    /// </summary>
    public virtual Vector3 GetPosition() => Vector3.zero;
    
    /// <summary>
    /// 获取血条信息栏
    /// </summary>
    public virtual BattleHeroInfoBar GetHeroInfoBar() => null;
    
    /// <summary>
    /// 刷新Buff显示
    /// </summary>
    public virtual void RefreshBuff(List<HB428_tagSCBuffRefresh> buffList) { }
    
    /// <summary>
    /// 更新血量显示
    /// </summary>
    public virtual void UpdateHP(float percentage) { }
    
    /// <summary>
    /// 是否正在复活中
    /// </summary>
    public virtual bool IsReborning() => false;
    
    /// <summary>
    /// 设置复活状态
    /// </summary>
    public virtual void SetReborning(bool value) { }
    
    /// <summary>
    /// 设置 GameObject 激活状态
    /// </summary>
    public virtual void SetActive(bool active) { }
    
    /// <summary>
    /// 重置位置到原点
    /// </summary>
    public virtual void ResetPosition() { }
    
    /// <summary>
    /// 设置朝向(通过缩放)
    /// </summary>
    public virtual void SetFacing(float direction) { }
    
    /// <summary>
    /// 重置朝向(朝向右边)
    /// </summary>
    public virtual void ResetFacing() { }
    
    /// <summary>
    /// 停止所有移动动画
    /// </summary>
    public virtual void StopMoveAnimation() { }
    
    /// <summary>
    /// 显示提示信息(简单版本)
    /// </summary>
    public virtual void ShowTips(string message, bool useArtText = false, bool followCharacter = true, float scaleRatio = 1f) { }
    
    /// <summary>
    /// 显示提示信息(完整版本)
    /// </summary>
    public virtual void ShowTips(BattleHeroInfoBar.TipsInfo tipsInfo) { }
    
    /// <summary>
    /// 设置死亡状态(Hero 特定)
    /// </summary>
    public virtual void SetDeath() { }
    
    /// <summary>
    /// 复活后处理(Hero 特定)
    /// </summary>
    public virtual void AfterReborn() { }
    
    /// <summary>
    /// 复活前准备(Hero 特定)
    /// </summary>
    public virtual void PreReborn(bool reviveSelf = false) { }
    
    /// <summary>
    /// 复活动作(Hero 特定)
    /// </summary>
    public virtual void OnReborn(HB427_tagSCUseSkill.tagSCUseSkillHurt vNetData, bool reviveSelf = false, RecordAction parentAction = null) { }
 
    public virtual void OnObjInfoRefresh(H0418_tagObjInfoRefresh _refreshInfo)
    {
        // 子类实现
    }
 
    //  眩晕
    public bool IsStunned()
    {
        return GetIsStunned();
    }
 
    //  冰冻
    public bool IsFrozen()
    {
        return GetIsFrozen();
    }
 
    //  石化
    public bool IsStoned()
    {
        return GetIsStoned();
    }
 
    //  被沉默
    public bool IsSlient()
    {
        return GetIsSlient();
    }
 
    //  被缴械
    public bool IsDisarmed()
    {
        return GetIsDisarmed();
    }
 
    //  是否无敌
    public bool IsInvincable()
    {
        return GetIsInvincible();
    }
 
    //  是否死亡
    public bool IsDead()
    {
        return GetIsDead();
    }
 
    //  是否被控住了
    public bool IsCrowdControlled()
    {
        return IsStunned() || IsStoned() || IsFrozen();
    }
 
    public virtual bool IsCanCastSkill()
    {
        //  被控住
        if (IsCrowdControlled())
        {
            return false;
        }
 
        //  被沉默
        if (IsSlient())
        {
            return false;
        }
 
        //  看看怒气是否达到释放要求
        return GetRage() >= 100;
    }
 
    public virtual bool IsCanNormalAttack()
    {
        //  被控住
        if (IsCrowdControlled())
        {
            return false;
        }
 
        //  缴械
        if (IsDisarmed())
        {
            return false;
        }
 
        return true;
    }
 
    public abstract DeathRecordAction Hurt(BattleHurtParam battleHurtParam, SkillRecordAction _parentSkillAction = null);
 
    public abstract void OnDodgeBegin(DamageType damageType);
 
    public abstract void OnDodgeEnd(Action _complete = null);
 
    public abstract void OnDeath(Action _onDeathAnimationComplete, bool withoutAnime = false);
 
    protected abstract BattleDmgInfo PopDamage(BattleHurtParam battleHurtParam);
 
    protected abstract BattleDmgInfo PopDamageForCaster(BattleHurtParam battleHurtParam);
 
    public RectTransform GetAliasTeamNode()
    {
        return battleField.GetTeamNode(Camp);
    }
 
    public RectTransform GetEnemyTeamNode()
    {
        return battleField.GetTeamNode(Camp == BattleCamp.Red ? BattleCamp.Blue : BattleCamp.Red);
    }
 
    public BattleCamp GetEnemyCamp()
    {
        return Camp == BattleCamp.Red ? BattleCamp.Blue : BattleCamp.Red;
    }
 
    public abstract void HaveRest();
 
    protected BattleDrops m_battleDrops;
 
    public virtual void PushDropItems(BattleDrops _battleDrops)
    {
        m_battleDrops = _battleDrops;
    }
 
    public virtual void PerformDrop()
    {
        if (null == m_battleDrops)
            return;
 
        EventBroadcast.Instance.Broadcast<string, BattleDrops, Action>(
            EventName.BATTLE_DROP_ITEMS, battleField.guid, m_battleDrops, OnPerformDropFinish);
    }
 
    protected virtual void OnPerformDropFinish()
    {
        m_battleDrops = null;
    }
 
    public void SetBack()
    {
        layerMgr.SetBack();
    }
 
    public void SetFront()
    {
        layerMgr.SetFront();
    }
 
    public abstract void SetSpeedRatio(float ratio);
 
    public abstract void OnObjPropertyRefreshView(HB418_tagSCObjPropertyRefreshView vNetData);
 
 
#if UNITY_EDITOR_STOP_USING
    public abstract void EditorRevive();
 
    public List<int> TryAttack(BattleObject obj, SkillConfig skillConfig)
    {
        List<int> damageList = new List<int>();
 
        int totalDamage = 100;
 
        int damage1 = (int)((float)totalDamage * 0.3f);
 
        int damage2 = (int)((float)totalDamage * 0.25f);
 
        int damage3 = totalDamage - damage1 - damage2;
 
        damageList.Add(damage1);
        damageList.Add(damage2);
        damageList.Add(damage3);
 
        return damageList;
    }
#endif
 
    // BattleObject.cs
 
    public virtual void OnHurtTarget(BattleHurtParam battleHurtParam)
    {
        // 检查是否有吸血或反伤
        bool hasSuckHp = battleHurtParam.caster.suckHpList != null && battleHurtParam.caster.suckHpList.Count > 0;
        bool hasReflectHp = battleHurtParam.caster.reflectHpList != null && battleHurtParam.caster.reflectHpList.Count > 0;
        
        if (!hasSuckHp && !hasReflectHp)
        {
            return;
        }
 
        // ============ 应用施法者的血量和护盾变化 ============
        bool isLastHit = battleHurtParam.hitIndex >= battleHurtParam.skillSkinConfig.DamageDivide.Length - 1;
        ApplyHurtToCaster(battleHurtParam, isLastHit);
 
        // 和Hurt一样,调用PopDamage处理吸血/反伤的显示
        BattleDmgInfo casterDmgInfo = PopDamageForCaster(battleHurtParam);
        
        // 如果有反伤,施法者播放受击动画
        if (hasReflectHp && casterDmgInfo.casterDamageList != null && casterDmgInfo.casterDamageList.Count > 0)
        {
            long totalReflect = casterDmgInfo.casterDamageList.Sum(d => d.damage);
            var buffMgr = GetBuffMgr();
            if (totalReflect > 0 && buffMgr != null && !buffMgr.isControled[BattleConst.HardControlGroup])
            {
                OnPlayHitAnimation();
            }
        }
    }
 
    /// <summary>
    /// 应用施法者的血量和护盾变化(吸血和反伤)
    /// </summary>
    private void ApplyHurtToCaster(BattleHurtParam battleHurtParam, bool isLastHit)
    {
        BattleCastObj caster = battleHurtParam.caster;
        
        // 应用血量变化(由子类实现)
        ApplyCasterHpChange(caster.toHp);
 
        //  打印所有角色的名字和当前血量跟总血量
        // foreach (var obj in battleField.battleObjMgr.allBattleObjDict.Values)
        // {
        //     Debug.LogError($"[ApplyHurtToCaster] ObjID: {obj.ObjID}, Name: {obj.teamHero.heroConfig.Name}, CurHp: {obj.teamHero.curHp}, MaxHp: {obj.teamHero.maxHp} Skill {battleHurtParam.hB427_TagSCUseSkill.packUID} " );
        // }
        
        // 护盾值由buff系统自动管理,不需要手动设置
        
#if UNITY_EDITOR
        // 最后一击时验证血量是否与服务器一致
        if (isLastHit)
        {
            BattleUtility.ValidateHpConsistencyForCaster(battleHurtParam, "施法者吸血/反伤");
        }
#endif
    }
 
    public bool IsTianziBoss()
    {
        return battleField.MapID == 30020 && battleField.FindBoss() == this;
    }
 
    /// <summary>
    /// 播放受击动画(只有 Hero 有实现,Mingge 留空)
    /// </summary>
    protected abstract void OnPlayHitAnimation();
    
    /// <summary>
    /// 应用施法者血量变化(吸血/反伤)
    /// </summary>
    protected abstract void ApplyCasterHpChange(long newHp);
}