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 class HeroBattleObject : BattleObject
|
{
|
private GameObject _heroGo;
|
public GameObject heroGo => _heroGo;
|
|
public MotionBase motionBase;
|
|
public TeamHero teamHero { get; private set; }
|
|
// Buff 管理器(只有 Hero 有 buff 系统)
|
public BattleObjectBuffMgr buffMgr;
|
|
private RectTransform m_heroRectTrans;
|
|
public RectTransform heroRectTrans
|
{
|
get
|
{
|
if (m_heroRectTrans == null && _heroGo != null)
|
{
|
m_heroRectTrans = _heroGo.GetComponent<RectTransform>();
|
}
|
return m_heroRectTrans;
|
}
|
}
|
|
protected Action onDeathAnimationComplete;
|
|
protected Renderer[] renderers;
|
|
private List<HB405_tagMCAddExp> hB405_tagMCAddExps = new List<HB405_tagMCAddExp>();
|
|
private BattleHeroInfoBar _heroInfoBar;
|
public BattleHeroInfoBar heroInfoBar => _heroInfoBar;
|
|
private bool _isReborning = false;
|
public bool isReborning
|
{
|
get => _isReborning;
|
set => _isReborning = value;
|
}
|
|
public HeroBattleObject(BattleField _battleField) : base(_battleField)
|
{
|
}
|
|
public void Init(GameObject _heroGo, TeamHero _teamHero, BattleCamp _camp)
|
{
|
this._heroGo = _heroGo;
|
teamHero = _teamHero;
|
Camp = _camp;
|
ObjID = _teamHero.ObjID;
|
InitInternal();
|
}
|
|
|
private void InitInternal()
|
{
|
motionBase = new MotionBase();
|
motionBase.Init(_heroGo.GetComponentInChildren<SkeletonAnimation>(true));
|
buffMgr = new BattleObjectBuffMgr();
|
buffMgr.Init(this);
|
|
buffMgr.onIsControlChanged += OnControledChange;
|
|
layerMgr = new BattleObjectLayerMgr();
|
layerMgr.Init(this);
|
|
renderers = _heroGo.GetComponentsInChildren<Renderer>(true);
|
|
_heroInfoBar = _heroGo.GetComponentInChildren<BattleHeroInfoBar>(true);
|
_heroInfoBar.SetBattleObject(this);
|
|
// 根据阵营翻转血条
|
var heroInfoBarScale = _heroInfoBar.transform.localScale;
|
heroInfoBarScale.x *= Camp == BattleCamp.Red ? 1 : -1;
|
_heroInfoBar.transform.localScale = heroInfoBarScale;
|
if (battleField is StoryBattleField && (battleField as StoryBattleField).battleState == StoryBattleState.Break)
|
{
|
//主线关卡休息中的不显示血条
|
heroInfoBar.SetActive(false);
|
}
|
else
|
{
|
heroInfoBar.SetActive(true);
|
}
|
SetFront();
|
|
if (battleField.ToString() != BattleConst.StoryBattleField &&
|
battleField.ToString() != BattleConst.TianziBillboradBattleField)
|
{
|
var hitArea = heroGo.GetComponent<Image>();
|
if (hitArea == null)
|
{
|
hitArea = heroGo.AddComponent<Image>();
|
hitArea.color = new Color(0, 0, 0, 0); //让射线检测到
|
}
|
|
var btn = heroGo.GetComponent<ButtonEx>();
|
if (btn == null)
|
{
|
btn = heroGo.AddComponent<ButtonEx>();
|
btn.interval = 0.5f;// 防止频繁连续点击
|
}
|
|
btn.AddListener(() =>
|
{
|
// 判断点击的是我方阵营还是敌方阵营,目前左边都是我方阵营
|
bool isMySide = Camp == BattleCamp.Red;
|
EventBroadcast.Instance.Broadcast(EventName.BATTLE_CLICK_HERO, new BattleClickHeroData()
|
{
|
battleName = battleField.ToString(),
|
isMySide = isMySide,
|
mapID = battleField.MapID,
|
funcLineID = battleField.FuncLineID,
|
npcID = teamHero.NPCID,
|
posNum = teamHero.positionNum,
|
heroID = teamHero.heroId,
|
teams = battleField?.battleObjMgr.GetBattleObjList(isMySide ? BattleCamp.Red : BattleCamp.Blue),
|
});
|
});
|
}
|
}
|
|
public override void Run()
|
{
|
motionBase.Run();
|
heroInfoBar.Run();
|
buffMgr.Run();
|
}
|
|
public override void Pause()
|
{
|
motionBase.Pause();
|
}
|
|
public override void Resume()
|
{
|
motionBase.Resume();
|
}
|
|
public override void Destroy()
|
{
|
motionBase.Release();
|
motionBase = null;
|
buffMgr.onIsControlChanged -= OnControledChange;
|
buffMgr.Release();
|
buffMgr = null;
|
teamHero = null;
|
ObjID = 0;
|
|
if (_heroGo != null)
|
{
|
GameObject.DestroyImmediate(_heroGo);
|
_heroGo = null;
|
}
|
}
|
|
// ============ 动画相关方法实现(通过 motionBase) ============
|
|
public override void PlayAnimation(MotionName motionName, bool loop)
|
{
|
motionBase.PlayAnimation(motionName, loop);
|
}
|
|
public override void ShowIllusionShadow(bool show, Color? color = null)
|
{
|
if (color.HasValue)
|
{
|
motionBase.ShowIllusionShadow(show, color.Value);
|
}
|
else
|
{
|
motionBase.ShowIllusionShadow(show);
|
}
|
}
|
|
public override Spine.TrackEntry PlaySkillAnimation(SkillConfig skillConfig, SkillBase skillBase, bool isCounter, Action onComplete)
|
{
|
return motionBase.PlaySkillAnimation(skillConfig, skillBase, isCounter, onComplete);
|
}
|
|
public override bool CanStartDeath()
|
{
|
return motionBase.CanStartDeath();
|
}
|
|
public override bool CanCastSkillAnimation(SkillConfig skillConfig)
|
{
|
return motionBase.CanCastSkill(skillConfig);
|
}
|
|
public override SkeletonAnimation GetSkeletonAnimation()
|
{
|
return motionBase.skeletonAnim;
|
}
|
|
public override void SetSkeletonAlpha(float alpha)
|
{
|
if (motionBase.skeletonAnim != null)
|
{
|
motionBase.skeletonAnim.skeleton.A = alpha;
|
}
|
}
|
|
public override RectTransform GetRectTransform() => heroRectTrans;
|
|
public override GameObject GetGameObject() => _heroGo;
|
|
public override Transform GetTransform() => _heroGo?.transform;
|
|
public override Vector3 GetPosition() => heroRectTrans != null ? heroRectTrans.position : Vector3.zero;
|
|
public override BattleHeroInfoBar GetHeroInfoBar() => _heroInfoBar;
|
|
public override void RefreshBuff(List<HB428_tagSCBuffRefresh> buffList)
|
{
|
_heroInfoBar?.RefreshBuff(buffList);
|
}
|
|
public override void UpdateHP(float percentage)
|
{
|
_heroInfoBar?.UpdateHP(percentage);
|
}
|
public override bool IsReborning() => _isReborning;
|
|
public override void SetReborning(bool value) => _isReborning = value;
|
|
public override void SetActive(bool active)
|
{
|
if (_heroGo != null)
|
{
|
_heroGo.SetActive(active);
|
}
|
}
|
|
public override void ResetPosition()
|
{
|
if (heroRectTrans != null)
|
{
|
heroRectTrans.anchoredPosition = Vector2.zero;
|
}
|
}
|
|
public override void SetFacing(float direction)
|
{
|
if (_heroGo != null)
|
{
|
Vector3 scale = _heroGo.transform.localScale;
|
scale.x = Mathf.Abs(scale.x) * direction;
|
_heroGo.transform.localScale = scale;
|
}
|
}
|
|
public override void ResetFacing() => SetFacing(1f);
|
|
public override void StopMoveAnimation()
|
{
|
if (heroRectTrans != null)
|
{
|
DG.Tweening.DOTween.Kill(heroRectTrans);
|
}
|
}
|
|
public override void ShowTips(string message, bool useArtText = false, bool followCharacter = true, float scaleRatio = 1f)
|
{
|
_heroInfoBar?.ShowTips(message, useArtText, followCharacter, scaleRatio);
|
}
|
|
public override void ShowTips(BattleHeroInfoBar.TipsInfo tipsInfo)
|
{
|
_heroInfoBar?.ShowTips(tipsInfo);
|
}
|
|
// 有变化了才会调用这个函数
|
private void OnControledChange(int groupType, bool value)
|
{
|
// 这里是受到硬控时候 需要表现的动画
|
if (groupType == BattleConst.HardControlGroup)
|
{
|
// 从没被硬控到被硬控
|
if (value)
|
{
|
motionBase.SetControledAnimation();
|
}
|
else
|
{
|
motionBase.CancelControledAnimation();
|
}
|
}
|
}
|
|
public override void OnObjInfoRefresh(H0418_tagObjInfoRefresh _refreshInfo)
|
{
|
// 天子的挑战拦截血条,不拦截怒气
|
BattleObject boss = battleField.FindBoss();
|
if (boss != null && battleField.MapID == 30020 && boss.ObjID == _refreshInfo.ObjID && _refreshInfo.RefreshType != (ushort)PlayerDataType.XP)
|
return;
|
switch ((PlayerDataType)_refreshInfo.RefreshType)
|
{
|
case PlayerDataType.HP:
|
long toHp = GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx);
|
if (!IsTianziBoss())
|
{
|
heroInfoBar.UpdateHP(teamHero.curHp, toHp, teamHero.maxHp, false);
|
}
|
teamHero.curHp = GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx);
|
// Debug.LogError("OnObjInfoRefresh " + teamHero.curHp);
|
break;
|
case PlayerDataType.MaxHP:
|
teamHero.maxHp = GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx);
|
if (!IsTianziBoss())
|
{
|
heroInfoBar.UpdateHP(teamHero.curHp, teamHero.curHp, teamHero.maxHp, false);
|
}
|
break;
|
case PlayerDataType.XP:
|
long toXp = GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx);
|
heroInfoBar.UpdateXP(teamHero.rage, toXp, 100);
|
teamHero.rage = (int)GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx);
|
break;
|
default:
|
Debug.LogError("BattleObject.ObjInfoRefresh 出现意外类型 " + _refreshInfo.RefreshType.ToString());
|
break;
|
}
|
}
|
|
public override DeathRecordAction Hurt(BattleHurtParam battleHurtParam, SkillRecordAction _parentSkillAction = null)
|
{
|
DeathRecordAction recordAction = null;
|
bool isLastHit = battleHurtParam.hitIndex >= battleHurtParam.skillConfig.DamageDivide.Length - 1;
|
bool firstHit = battleHurtParam.hitIndex == 0;
|
|
// 添加调试日志
|
bool isHealing = BattleUtility.IsHealing(battleHurtParam.hurt);
|
|
BattleDmgInfo dmgInfo = PopDamage(battleHurtParam);
|
|
// ============ 应用目标的血量和护盾变化 ============
|
ApplyHurtToTarget(battleHurtParam, isLastHit);
|
|
|
// 这里
|
if (dmgInfo.IsType(DamageType.Dodge) || dmgInfo.IsType(DamageType.CompletelyDodge))//如果被控制了还闪避了 要看看服务器怎么处理了
|
{
|
if (isLastHit)
|
{
|
DodgeFinishAction dodgeFinish = new DodgeFinishAction(battleField, this);
|
// 【使用 BattleField.recordPlayer】
|
// 原因:闪避完成动作是目标角色的独立行为,不是技能内部产生的
|
// 虽然是在Hurt过程中触发,但是闪避动作本身是目标的反应,应该由主RecordPlayer管理
|
// 使用InsertRecord可以插到队列最前面,保证闪避表现的优先级
|
battleField.recordPlayer.InsertRecord(dodgeFinish);
|
}
|
|
if (firstHit)
|
{
|
OnDodgeBegin(dmgInfo.IsType(DamageType.Dodge) ? DamageType.Dodge : DamageType.CompletelyDodge);
|
}
|
}
|
|
bool isFatalAttack = (null != battleHurtParam.deadPack) && isLastHit;
|
|
if (isFatalAttack)
|
{
|
if (null != battleHurtParam.battleDrops)
|
{
|
PushDropItems(battleHurtParam.battleDrops);
|
}
|
recordAction = battleField.OnObjsDead(new List<BattleDeadPack>() { battleHurtParam.deadPack }, _parentSkillAction, _parentSkillAction);
|
}
|
else
|
{
|
if (dmgInfo.IsType(DamageType.Block))
|
{
|
battleField.battleEffectMgr.PlayEffect(this, BattleConst.BlockEffectID, heroRectTrans, Camp, teamHero.modelScale);
|
}
|
// else
|
// {
|
if ((dmgInfo.IsType(DamageType.Damage) || dmgInfo.IsRealdamage()))
|
{
|
if (!buffMgr.isControled[BattleConst.HardControlGroup])
|
{
|
battleField.soundManager.PlayEffectSound(teamHero.heroConfig.HitSFX, false);
|
motionBase.PlayAnimation(MotionName.hit, false);
|
}
|
}
|
// }
|
}
|
|
return recordAction;
|
}
|
|
/// <summary>
|
/// 应用目标的血量和护盾变化
|
/// </summary>
|
private void ApplyHurtToTarget(BattleHurtParam battleHurtParam, bool isLastHit)
|
{
|
BattleHurtObj hurter = battleHurtParam.hurter;
|
|
// 应用血量变化
|
teamHero.curHp = hurter.toHp;
|
|
#if UNITY_EDITOR
|
// 最后一击时验证血量是否与服务器一致
|
if (isLastHit)
|
{
|
BattleUtility.ValidateHpConsistency(battleHurtParam, "目标受伤");
|
}
|
#endif
|
}
|
|
const float pingpongTime = 0.4f;
|
// 闪避开始
|
public override void OnDodgeBegin(DamageType damageType)
|
{
|
RectTransform rectTrans = heroRectTrans;
|
var tween = rectTrans.DOAnchorPos(new Vector3(-30, 0, 0), pingpongTime)
|
.SetEase(Ease.OutCubic);
|
|
motionBase.ShowIllusionShadow(true);
|
|
int damageTypeInt = damageType == DamageType.Dodge ? (int)damageType : BattleConst.CompletelyDodge;
|
|
DamageNumConfig damageNumConfig = DamageNumConfig.Get(damageTypeInt);
|
|
string dodgeStr = ((char)damageNumConfig.prefix).ToString();
|
|
heroInfoBar.ShowTips(dodgeStr, true, false);
|
|
tween.onComplete += () =>
|
{
|
motionBase.ShowIllusionShadow(false);
|
};
|
|
battleField.soundManager.PlayEffectSound(BattleConst.DodgeSoundID);
|
|
battleField.battleTweenMgr.OnPlayTween(tween);
|
}
|
|
// 闪避结束
|
public override void OnDodgeEnd(Action _complete = null)
|
{
|
RectTransform rectTrans = heroRectTrans;
|
|
var tween = rectTrans.DOAnchorPos(Vector3.zero, pingpongTime)
|
.SetEase(Ease.OutCubic);
|
|
tween.onComplete += () =>
|
{
|
_complete?.Invoke();
|
};
|
|
battleField.battleTweenMgr.OnPlayTween(tween);
|
}
|
|
public override void OnDeath(Action _onDeathAnimationComplete, bool withoutAnime = false)
|
{
|
buffMgr.RemoveAllBuff();
|
battleField.soundManager.PlayEffectSound(teamHero.heroConfig.DeathSFX, false);
|
if (withoutAnime)
|
{
|
SetDeath();
|
_onDeathAnimationComplete?.Invoke();
|
}
|
else
|
{
|
motionBase.PlayDeadAnimation(() =>
|
{
|
SetDeath();
|
_onDeathAnimationComplete?.Invoke();
|
});
|
}
|
}
|
|
public override void SetDeath()
|
{
|
teamHero.isDead = true;
|
OnDeadAnimationComplete();
|
}
|
|
protected virtual void OnDeadAnimationComplete()
|
{
|
// 或许看看溶解特效? YYL TODO
|
heroGo.SetActive(false);
|
|
// 防止给死亡对象又上buff
|
buffMgr.RemoveAllBuff();
|
}
|
|
// 释放者就是复活者时调用
|
public override void PreReborn(bool reviveSelf = false)
|
{
|
heroGo.SetActive(true);
|
motionBase.skeletonAnim.skeleton.A = 0f;
|
motionBase.skeletonAnim.LateUpdate();
|
heroRectTrans.anchoredPosition = Vector2.zero;
|
motionBase.ResetForReborn(reviveSelf);
|
}
|
|
// 复活action
|
public override void OnReborn(HB427_tagSCUseSkill.tagSCUseSkillHurt vNetData, bool reviveSelf = false, RecordAction parentAction = null)
|
{
|
isReborning = true;
|
heroGo.SetActive(true);
|
motionBase.ResetForReborn(reviveSelf);
|
heroRectTrans.anchoredPosition = Vector2.zero;
|
motionBase.skeletonAnim.skeleton.A = 0f;
|
motionBase.skeletonAnim.LateUpdate();
|
}
|
|
public override void AfterReborn()
|
{
|
// 清空所有
|
motionBase.ResetForReborn(false);
|
isReborning = false;
|
}
|
|
// ============ 实现抽象访问方法 ============
|
|
public override BattleObjectBuffMgr GetBuffMgr() => buffMgr;
|
|
public override int GetPositionNum() => teamHero.positionNum;
|
public override float GetModelScale() => teamHero.modelScale;
|
public override string GetName() => teamHero.name;
|
|
protected override bool GetIsStunned() => teamHero.isStunned;
|
protected override bool GetIsFrozen() => teamHero.isFrozen;
|
protected override bool GetIsStoned() => teamHero.isStoned;
|
protected override bool GetIsSlient() => teamHero.isSlient;
|
protected override bool GetIsDisarmed() => teamHero.isDisarmed;
|
protected override bool GetIsInvincible() => teamHero.isInvinceble;
|
protected override bool GetIsDead() => teamHero.isDead;
|
public override int GetRage() => teamHero.rage;
|
|
protected override void ApplyCasterHpChange(long newHp)
|
{
|
if (teamHero == null) return;
|
teamHero.curHp = newHp;
|
}
|
|
public override long GetCurHp() => teamHero == null ? 0 : teamHero.curHp;
|
public override long GetMaxHp() => teamHero == null ? 0 : teamHero.maxHp;
|
public override void SetCurHp(long value) { if (teamHero == null) return; teamHero.curHp = value; }
|
public override void SetIsDead(bool value) { if (teamHero == null) return; teamHero.isDead = value; }
|
|
public override int GetNPCID() => teamHero == null ? 0 : teamHero.NPCID;
|
public override long GetFightPower() => teamHero == null ? 0 : teamHero.fightPower;
|
|
// 伤害还要看 是否闪避 暴击 and so on 需要有一个DamageType 服务器应该会给
|
protected override BattleDmgInfo PopDamage(BattleHurtParam battleHurtParam)
|
{
|
BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, battleHurtParam);
|
// 天子的挑战拦截血条逻辑
|
BattleObject boss = battleField.FindBoss();
|
// 修复:battleHurtParam.hurtObj.ObjID -> battleHurtParam.hurter.hurtObj.ObjID
|
if (boss != null && battleField.MapID == 30020 && boss.ObjID == battleHurtParam.hurter.hurtObj.ObjID)
|
{
|
EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo);
|
return battleDmgInfo;
|
}
|
else
|
{
|
heroInfoBar.UpdateDamage(battleDmgInfo);
|
|
// YYL TODO 是否需要挂在在自身的follow点上
|
EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo);
|
return battleDmgInfo;
|
}
|
}
|
|
/// <summary>
|
/// 为施法者创建伤害信息(吸血/反伤)
|
/// </summary>
|
protected override BattleDmgInfo PopDamageForCaster(BattleHurtParam battleHurtParam)
|
{
|
// 传入 isCasterView=true 表示这是施法者视角
|
BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, battleHurtParam, _isCasterView: true);
|
|
BattleObject boss = battleField.FindBoss();
|
if (boss != null && battleField.MapID == 30020 && boss.ObjID == this.ObjID)
|
{
|
EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo);
|
return battleDmgInfo;
|
}
|
else
|
{
|
heroInfoBar.UpdateDamage(battleDmgInfo);
|
EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo);
|
return battleDmgInfo;
|
}
|
}
|
|
public override void HaveRest()
|
{
|
// YYL TODO
|
// 休息状态
|
// 多一个zzz的一个特效
|
heroGo.SetActive(true);
|
motionBase.HaveRest();
|
heroRectTrans.anchoredPosition = Vector2.zero;
|
heroInfoBar.HaveRest();
|
isReborning = false;
|
|
SetFront();
|
}
|
public override void SetSpeedRatio(float ratio)
|
{
|
motionBase.SetSpeedRatio(ratio);
|
heroInfoBar.SetSpeedRatio(ratio);
|
}
|
public override void PushDropItems(BattleDrops _battleDrops)
|
{
|
m_battleDrops = _battleDrops;
|
}
|
|
public override void PerformDrop()
|
{
|
if (null == m_battleDrops)
|
return;
|
|
EventBroadcast.Instance.Broadcast<string, BattleDrops, Action>(
|
EventName.BATTLE_DROP_ITEMS, battleField.guid, m_battleDrops, OnPerformDropFinish);
|
}
|
|
protected override void OnPerformDropFinish()
|
{
|
m_battleDrops = null;
|
}
|
|
public override void OnObjPropertyRefreshView(HB418_tagSCObjPropertyRefreshView vNetData)
|
{
|
// 天子的挑战拦截血条,不拦截怒气
|
BattleObject boss = battleField.FindBoss();
|
if (boss != null && battleField.MapID == 30020 && boss.ObjID == vNetData.ObjID && vNetData.RefreshType != (ushort)PlayerDataType.XP)
|
return;
|
|
long diffValue = GeneralDefine.GetFactValue(vNetData.DiffValue, vNetData.DiffValueEx);
|
diffValue *= vNetData.DiffType == 0 ? -1 : 1;
|
|
long newValue = GeneralDefine.GetFactValue(vNetData.Value, vNetData.ValueEx);
|
|
switch ((PlayerDataType)vNetData.RefreshType)
|
{
|
case PlayerDataType.HP:
|
long toHp = GeneralDefine.GetFactValue(vNetData.Value, vNetData.ValueEx);
|
bool isMinus = teamHero.curHp > toHp;
|
if (!IsTianziBoss())
|
{
|
heroInfoBar.UpdateHP(teamHero.curHp, toHp, teamHero.maxHp, false);
|
}
|
teamHero.curHp = newValue;
|
// Debug.LogError("OnObjPropertyRefreshView " + teamHero.curHp);
|
break;
|
case PlayerDataType.MaxHP:
|
teamHero.maxHp = newValue;
|
if (!IsTianziBoss())
|
{
|
heroInfoBar.UpdateHP(teamHero.curHp, teamHero.curHp, teamHero.maxHp, false);
|
}
|
break;
|
case PlayerDataType.XP:
|
long toXp = newValue;
|
heroInfoBar.UpdateXP(teamHero.rage, toXp, 100);
|
teamHero.rage = (int)newValue;
|
|
DamageNumConfig damageNumConfig = DamageNumConfig.Get((int)DamageType.RageUp);
|
string message = BattleUtility.ConvertToArtFont(damageNumConfig, diffValue);
|
heroInfoBar.ShowTips(new BattleHeroInfoBar.TipsInfo()
|
{
|
message = message,
|
useArtText = true,
|
followCharacter = true,
|
scaleRatio = 1f,
|
isRage = true
|
});
|
break;
|
default:
|
Debug.LogError("BattleObject.ObjPropertyRefreshView 出现意外类型 " + vNetData.RefreshType.ToString());
|
break;
|
}
|
}
|
|
public override 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.skillConfig.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);
|
if (totalReflect > 0 && !buffMgr.isControled[BattleConst.HardControlGroup])
|
{
|
motionBase.PlayAnimation(MotionName.hit, false);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 应用施法者的血量和护盾变化(吸血和反伤)
|
/// </summary>
|
private void ApplyHurtToCaster(BattleHurtParam battleHurtParam, bool isLastHit)
|
{
|
BattleCastObj caster = battleHurtParam.caster;
|
|
// 应用血量变化
|
teamHero.curHp = caster.toHp;
|
|
#if UNITY_EDITOR
|
// 最后一击时验证血量是否与服务器一致
|
if (isLastHit)
|
{
|
BattleUtility.ValidateHpConsistencyForCaster(battleHurtParam, "施法者吸血/反伤");
|
}
|
#endif
|
}
|
|
#if UNITY_EDITOR_STOP_USING
|
public override void EditorRevive()
|
{
|
teamHero.curHp = 100;
|
heroGo.SetActive(true);
|
motionBase.PlayAnimation(MotionName.idle, true);
|
}
|
#endif
|
|
protected override void OnPlayHitAnimation()
|
{
|
motionBase.PlayAnimation(MotionName.hit, false);
|
}
|
}
|