using Framework;
using Gameplay.Buff;
using Gameplay.Character;
using Gameplay.Level;
using System;
using AOT.PostProcess.BlackArea;
using cfg.BuffCfg;
using Code.Scripts.Gameplay.PlaneShadow;
using Code.Scripts.Gameplay.Unit.Data;
using CodeStage.AntiCheat.ObscuredTypes;
using Cysharp.Threading.Tasks;
using Gameplay.Area;
using Gameplay.Bullet;
using Gameplay.Common;
using Gameplay.Fight.Flag;
using Gameplay.Performance;
using Gameplay.Pool;
using Gameplay.Skill;
using Gameplay.Unit.Data;
using UnityEngine;
namespace Gameplay.Unit
{
public class GameUnit : Framework.Wrapper.Unit
{
public bool isReady = false;
public readonly EGameUnitType gameunitType;
public DebugShowInfo debugShowInfo;
public Transform transform
{
get
{
return _node.transform;
}
}
public UnitViewData viewData;
///
/// 公用数据,或者其他一些不知道放哪的数据
///
public UnitCommonData commonData;
///
/// logic移动相关数据,view层主要与此进行同步
///
public UnitTransData transData;
///
/// 生存相关数据,控制角色的死亡,复活等
///
public UnitAliveData aliveData;
///
/// 战斗相关数据,主要用于公式计算相关
///
public UnitFightData fightData
{
get;
private set;
}
///
/// 战斗中使用的路径数据
/// 可用于提前计算好, 在需要用的地方直接使用, 避免重复计算
/// 也可以实时计算, 但是需要注意性能问题
///
public UnitPathData pathData
{
get;
private set;
}
///
/// 战斗内的控制数据,主要用于战斗内的逻辑控制
///
public UnitControlData controlData;
///
/// 状态数据,主要用于标识判定
///
public UnitStatusData statusData
{
get;
set;
}
///
/// 单位关卡数据
///
public UnitLevelData unitLevelData
{
get;
set;
}
///
/// 单位UI数据
///
public UnitUIData unitUIData
{
get;
set;
}
public UnitFightStoryData fightStoryData
{
get;
set;
}
public bool needRemove
{
get;
set;
}
///
/// gameunit的buff管理器
/// 因为需要通过buff来控制一些属性,所以需要在gameunit中管理buff
///
public UnitBuffManager buffManager;
public DelayMoraleDamage delayMoraleDamage;
public RoadLineView roadLineView;
public GameUnit(uint id,
int troopId,
EGameUnitType type) : base(id)
{
transData = new UnitTransData(this);
commonData = new UnitCommonData(this);
aliveData = new UnitAliveData(this);
fightData = new UnitFightData(this);
controlData = new UnitControlData(this);
statusData = new UnitStatusData(this);
unitUIData = new UnitUIData(this);
fightStoryData = new UnitFightStoryData(this);
pathData = new UnitPathData(this);
delayMoraleDamage = new DelayMoraleDamage(this);
gameunitType = type;
commonData.troopId = troopId;
// 初始化逃跑时间
fightData.baseRetreateTime = TableManager.Instance.Tables.GlobalConfig.ForceEscapeTime;
fightData.retreateTime = TableManager.Instance.Tables.GlobalConfig.ForceEscapeTime;
}
public async UniTask Prepare()
{
await _OnPrepare();
Node.GameObject.SetActive(false);
}
protected virtual async UniTask _OnPrepare()
{
}
///
/// 用于从备战席到战场的初始化
/// 添加到战场中,并进行ready,此时并没有真正进入战斗
///
public void Ready()
{
Node.GameObject.SetActive(true);
viewData = new UnitViewData(this);
_OnReady();
EventManager.Instance.Send(EventManager.EventName.LevelUnitBorn, this);
}
protected virtual void _OnReady()
{
}
///
/// 进入战斗,真正的进入战斗,如果有相关全局技能,则会触发
///
public void EnterBattle()
{
if (commonData.canControl)
{
// 可以控制的单位,进入战斗时,默认是攻击状态
statusData.isAttackActive = true;
}
_OnEnterBattle();
EventManager.Instance.Send(EventManager.EventName.INFIGHT_UNIT_READY, this);
// 尝试触发格子buff
_TriggerBlockBuff();
}
protected virtual void _OnEnterBattle()
{
}
///
/// 离开战斗,如果有相关全局技能,则会触发
///
public void ExitBattle()
{
Node.GameObject.SetActive(false);
if (LevelManager.Instance.CurrentLevel.selectUnit == this)
{
LevelManager.Instance.CurrentLevel.UnSelectUnit();
}
if (roadLineView != null)
{
roadLineView.Dispose();
roadLineView = null;
}
_OnExitBattle();
}
protected virtual void _OnExitBattle()
{
}
///
/// 回到备战席,通常需要隐藏模型一类的
///
public void BackPrepare()
{
_OnBackPrepare();
Node.GameObject.SetActive(false);
}
protected virtual void _OnBackPrepare()
{
}
public void LogicUpdate(float dt)
{
if (controlData.forceUpdateTarget)
{
_UpdateTargets();
}
_OnLogicUpdate(dt);
_UpdateBlackArea();
if (roadLineView != null)
{
roadLineView.LogicUpdate(dt);
}
}
public void MoveLogicUpdate(float dt)
{
_OnMoveLogicUpdate(dt);
}
protected virtual void _OnMoveLogicUpdate(float dt)
{
}
public void ForceUpdateBlackArea()
{
_UpdateBlackArea();
}
private void _UpdateBlackArea()
{
if (commonData.troopId == ETroopsId.Self)
{
return;
}
var isInLightArea = BlackAreaManager.instance.CheckIsInLightArea(transData.cellIndex);
viewData.SetShow(isInLightArea);
}
protected virtual void _OnLogicUpdate(float dt)
{
}
public void SetPosAndYaw(int cellIndex,
float yaw)
{
transData.disableEvent = true;
// 设置数据
transData.pos = AreaManager.instance.GetWorldPosByIndex(cellIndex);
transData.yaw = yaw;
// 设置view
_node.GameObject.transform.position = transData.pos;
_node.GameObject.transform.eulerAngles = new Vector3(0, yaw, 0);
transData.disableEvent = false;
}
public void RecoverMorale(int value)
{
var finalValue = Mathf.FloorToInt(value * fightData.moraleRecoverScale);
_OnRecoverMorale(finalValue);
}
protected virtual void _OnRecoverMorale(int value)
{
aliveData.currentMorale += value;
if (aliveData.currentMorale > aliveData.maxMorale)
{
aliveData.currentMorale = aliveData.maxMorale;
}
}
private bool _CheckIsUnbeatble()
{
var isSelf = commonData.troopId == ETroopsId.Self;
return isSelf ? CodeDefine.Fight.HP_NOCOST : CodeDefine.Fight.HP_NOCOST_ENEMY;
}
private bool _CheckMoraleUnbeatble()
{
if (commonData.troopId == ETroopsId.Self)
{
return CodeDefine.Fight.MORALE_NOCOST;
}
else
{
return CodeDefine.Fight.MORALE_NOCOST_ENEMY;
}
}
public void TakeMoraleDamage(int damage,
GameUnit sender)
{
if (!statusData.canBeAttack)
{
// 不可被攻击
return;
}
if (_CheckMoraleUnbeatble())
{
return;
}
var baseDamage = damage;
var damageScale = sender.fightData.moraleDamageScale;
var beDamageScale = fightData.moraleBeDamageScale;
var realDamage = Mathf.CeilToInt(baseDamage * damageScale * beDamageScale);
// 特殊检查
_YalishuaijianCheck(ref realDamage);
if (CodeDefine.Fight.ONE_DAMAGE_RETREAT)
{
realDamage = aliveData.maxMorale;
}
_OnTakeMoraleDamage(sender, realDamage);
}
private void _YalishuaijianCheck(ref int realDamage)
{
var yalishuaijianBuffs = buffManager.GetBuffsByType(EBuffType.SpecialYaLiShuaiJian);
if (yalishuaijianBuffs.Count != 0)
{
// 只去第一个,靠配表保证只有一个
var yalishuaijianBuff = yalishuaijianBuffs[0] as BuffSpecialYaLiShuaiJian;
if (yalishuaijianBuff == null)
{
DebugUtil.LogError("不应该出现这个错误,说明类型转换出错");
return;
}
var decreaseRate = yalishuaijianBuff.decreasePercent;
var decreseValue = Mathf.CeilToInt(decreaseRate * realDamage);
realDamage -= decreseValue;
// decrease的伤害,按秒给出去
delayMoraleDamage.AddSecondsDamage(decreseValue, yalishuaijianBuff.delayTime);
}
}
public void DamageMoraleImd(GameUnit sender,
int damage)
{
var newMorale = aliveData.currentMorale - damage;
if (newMorale < 0)
{
newMorale = 0;
}
// 死撑检查
if (statusData.isDeadRetreat && this is Character.Character c)
{
var buff = c.buffManager.GetBuffByType(EBuffType.DeadRetreat) as BuffDeadRetreat;
if (buff == null)
{
DebugUtil.LogError("角色身上有死撑状态,但是buff为空");
return;
}
var retreateValue = c.runtimeData.configData.retreatMorale;
if (newMorale < retreateValue)
{
// 不扣减士气
// 按系数转为扣血
var damageRate = buff.morale2DmgRate;
var damageValue = Mathf.CeilToInt(damage * damageRate);
_OnTakeNormalDamage(0, damageValue, sender, false, false);
return;
}
}
aliveData.currentMorale = newMorale;
}
protected virtual void _OnTakeMoraleDamage(GameUnit sender,
int damage)
{
commonData.lastInFightSeconds = LevelManager.Instance.CurrentLevel.LevelTime;
DamageMoraleImd(sender, damage);
}
public void RecoverShield(int value,
bool canOverFlow)
{
_OnRecoverShield(value, canOverFlow);
}
protected virtual void _OnRecoverShield(int value,
bool canOverFlow)
{
aliveData.currentShield += value;
var maxShield = canOverFlow ? aliveData.maxShield + fightData.overflowShiledMaxValue : (int)aliveData.maxShield;
if (aliveData.currentShield > maxShield)
{
aliveData.currentShield = maxShield;
}
}
public void RecoverHp(int value)
{
_OnRecoverHp(value);
}
protected virtual void _OnRecoverHp(int value)
{
aliveData.currentHp += value;
if (aliveData.currentHp > aliveData.maxHp)
{
aliveData.currentHp = aliveData.maxHp;
}
}
private float _GetFinalScaleForUnitType(GameUnit sender)
{
var scaleForSpecial = 1f;
switch (gameunitType)
{
case EGameUnitType.Character:
scaleForSpecial = sender.fightData.scaleForHuman;
break;
case EGameUnitType.Vehicle:
scaleForSpecial = sender.fightData.scaleForVehicle;
break;
case EGameUnitType.Building:
scaleForSpecial = sender.fightData.scaleForBuilding;
break;
}
return scaleForSpecial;
}
public void TakePureDamage(ObscuredInt damage, GameUnit sender)
{
_OnTakeNormalDamage(int.MaxValue, damage, sender, false, false);
}
public void TakeNormalDamage(ObscuredInt attackPowerLevel, ObscuredInt damage,
GameUnit sender,
bool isCritical)
{
if (!statusData.canBeAttack)
{
// 不可被攻击
return;
}
if (attackPowerLevel < fightData.defensePowerLevel && !_CheckIsOneDamageKill())
{
// 小于忽略伤害
return;
}
statusData.lastAttackUnit = sender;
commonData.lastInFightSeconds = LevelManager.Instance.CurrentLevel.LevelTime;
commonData.lastBeHitSeconds = LevelManager.Instance.CurrentLevel.LevelTime;
// 通用处理
var senderLevel = sender.commonData.level;
if (sender.gameunitType == EGameUnitType.Vehicle)
{
// 载具进行攻击时, 等级强制为受击者当前等级
senderLevel = commonData.level;
}
var defense = fightData.defense;
if (defense < 0)
{
defense = 0;
}
if (aliveData.currentShield > 0)
{
defense = 0;
}
// 减伤值
var valueN = GLConfig.Inst.data.FPN;
var valueK = GLConfig.Inst.data.FPK;
var levelOffset = commonData.level - senderLevel;
if (levelOffset < 0)
{
levelOffset = 0;
}
var preCalc = levelOffset * valueN + defense + valueK;
var reduceValue = 1f;
if (preCalc > 0)
{
reduceValue = (defense + levelOffset * valueN) / preCalc;
}
var reduceScaler = 1 - reduceValue;
var skillRate = sender.fightData.skillRate;
var finalDamageScale = sender.fightData.finalDamageScale;
var beHitScale = fightData.beDamageScale;
var hasShield = aliveData.currentShield > 0;
var ignoreRandom = UnityEngine.Random.Range(0, 1f);
var ignoreShieldRate = sender.fightData.ignoreShieldRate;
var isIgnoreShield = ignoreRandom < ignoreShieldRate;
if (isIgnoreShield)
{
hasShield = false;
}
var scaleAttack = 1f;
if (gameunitType == EGameUnitType.Character)
{
scaleAttack = hasShield ? sender.fightData.attackScaleForShiled : sender.fightData.attackScaleForHp;
}
var scaleForSpecial = _GetFinalScaleForUnitType(sender);
var realDamage = Mathf.CeilToInt(damage * skillRate * reduceScaler * scaleAttack * scaleForSpecial * finalDamageScale * beHitScale);
realDamage += fightData.extraDamageOnNormalAttack;
if (realDamage < 1)
{
realDamage = 1;
}
if (_CheckIsOneDamageKill())
{
realDamage = (aliveData.currentHp + aliveData.currentShield) * 10;
}
if (CodeDefine.ENABLE_FIGHT_NORMAL_ATTACK_LOG)
{
DebugUtil.Log($"{sender.GetDescString()} 对 {GetDescString()} 造成了 {damage} 伤害 实际伤害为 {realDamage} 是否暴击 {isCritical} 是否无视护盾 {isIgnoreShield}");
}
_OnTakeNormalDamage(attackPowerLevel, realDamage, sender, isCritical, isIgnoreShield);
}
private bool _CheckIsOneDamageKill()
{
if (commonData.troopId == ETroopsId.Self)
{
return CodeDefine.Fight.ONE_DAMAGE_KILL_SELF;
}
else
{
return CodeDefine.Fight.ONE_DAMAGE_KILL_ENEMY;
}
}
private void _TriggerOnTakeDamage()
{
if (buffManager != null)
{
buffManager.TriggerOnTakeDamage();
}
var skillManager = SkillManager.instance.GetUnitSkillManager(this);
if (skillManager != null)
{
skillManager.TriggerBeAttack();
}
}
protected virtual void _OnTakeNormalDamage(ObscuredInt attackPowerLevel, ObscuredInt realDamage,
GameUnit sender,
bool isCritical,
bool ignoreShield)
{
if (buffManager.damageRedirectBuff != null)
{
// 身上有伤害转移buff
var redirectPercent = buffManager.damageRedirectBuff.redirectPercent;
var redirectValue = Mathf.FloorToInt(realDamage * redirectPercent);
realDamage -= redirectValue;
// 对创建者造成伤害
buffManager.damageRedirectBuff.creator.TakeNormalDamage(attackPowerLevel, redirectValue, this, false);
}
var data = ObjPoolManager.instance.Get();
data.sender = sender;
data.owner = this;
data.damage = realDamage;
data.isCritical = isCritical;
if (!PerformanceManager.instance.data.disableFloatDamage)
{
EventManager.Instance.Send(EventManager.EventName.INFIGHT_GET_DAMAGED, data);
}
// 给AI发送受伤事件
EventManager.Instance.Send(EventManager.EventName.INFIGHT_GET_DAMAGED_FOR_AI, data);
ObjPoolManager.instance.Return(data);
_TriggerOnTakeDamage();
fightData.hurtAccumulate += realDamage;
if (aliveData.currentShield > 0 && !ignoreShield)
{
if (aliveData.currentShield >= realDamage)
{
if (_CheckIsUnbeatble())
{
return;
}
aliveData.currentShield -= realDamage;
if (debugShowInfo.cacheConfigId != 0)
{
EventManager.Instance.Send(EventManager.EventName.INFIGHT_AUDIO_BE_ATTACK_AND_HAS_SHEILD, debugShowInfo.cacheConfigId);
}
return;
}
else
{
if (_CheckIsUnbeatble())
{
return;
}
realDamage -= aliveData.currentShield;
aliveData.currentShield = 0;
var isDead = _DamageHP(realDamage);
if (isDead)
{
sender.buffManager.TriggerKillUnit(this);
}
else
{
if (debugShowInfo.cacheConfigId != 0)
{
EventManager.Instance.Send(EventManager.EventName.INFIGHT_AUDIO_BE_ATTACK_AND_NO_SHEILD, debugShowInfo.cacheConfigId);
}
}
}
}
else
{
var isDead = _DamageHP(realDamage);
if (isDead)
{
sender.buffManager.TriggerKillUnit(this);
}
}
}
private bool _DamageHP(int damage)
{
if (_CheckIsUnbeatble())
{
return false;
}
aliveData.currentHp -= damage;
if (aliveData.currentHp <= 0)
{
aliveData.currentHp = 0;
return true;
}
return false;
}
public void OnSelect()
{
if (CodeDefine.ENABLE_FIGHT_NORMAL_ATTACK_LOG)
DebugUtil.Log("Select: ----- GameUnit : {0}", GetID());
statusData.isSelected = true;
_OnSelect();
EventManager.Instance.Send(EventManager.EventName.LevelUnitSelect, this);
}
protected virtual void _OnSelect()
{
}
public void OnUnSelect()
{
if (CodeDefine.ENABLE_FIGHT_NORMAL_ATTACK_LOG)
DebugUtil.Log("UnSelect ---- GameUnit: {0}", GetID());
statusData.isSelected = false;
_OnUnSelect();
EventManager.Instance.Send(EventManager.EventName.LevelUnitUnSelect, this);
}
protected virtual void _OnUnSelect()
{
}
public void MoveTo(GameUnit unit)
{
if (unit == null)
{
DebugUtil.LogError("moveto的对象为空");
return;
}
controlData.followUnit = unit;
if (LevelManager.Instance.CurrentLevel.selectUnit == this)
{
EventManager.Instance.Send(EventManager.EventName.INFIGHT_OP_SET_TARGET);
}
// 这里需要判定是否是敌方
// 如果是敌方,且在攻击范围内,则直接切换攻击目标
if (unit.commonData.troopId != commonData.troopId)
{
if (unit.statusData.CheckCanBeTarget(this))
{
// 在攻击范围内,直接切换攻击目标
controlData.targetEnemy = unit;
return;
}
}
MoveTo(unit.transData.cellIndex, false);
}
public void MoveTo(int cellIndex,
bool cancelFollow)
{
if (cancelFollow)
{
controlData.followUnit = null;
}
var map = LevelManager.Instance.CurrentLevel.Map;
if (map == null) return;
controlData.targetCellIndex = cellIndex;
if (LevelManager.Instance.CurrentLevel.selectUnit == this)
{
EventManager.Instance.Send(EventManager.EventName.INFIGHT_OP_SET_MOVEPOS);
}
}
public void StopToCurrentCell()
{
controlData.targetCellIndex = transData.cellIndex;
controlData.followUnit = null;
}
///
/// 该方法仅由skillhandle进行调用
///
///
///
public void _UseSkill(int cellIndex,
SkillHandle skillHandle)
{
//test
// PlayAudio();
_OnUseSkill(cellIndex, skillHandle);
}
protected virtual void _OnUseSkill(int cellIndex,
SkillHandle skillHandle)
{
}
///
/// AI自动使用技能
///
public void AITryUseSkill()
{
}
public ViewBullet EmitSkillBullet(int bulletId,
GameUnit targetUnit,
SkillHandle skillHandle)
{
commonData.lastInFightSeconds = LevelManager.Instance.CurrentLevel.LevelTime;
var bullet = BulletManager.instance.EmitBullet(bulletId, targetUnit, skillHandle.owner);
if (bullet != null)
{
if (statusData.needSkillPaused)
{
SkillManager.instance.screenEffect.AttachObj(bullet.rootObj);
}
}
return bullet;
}
public ViewBullet EmitSkillBullet(int bulletId,
int targetCellIndex,
SkillHandle skillHandle)
{
commonData.lastInFightSeconds = LevelManager.Instance.CurrentLevel.LevelTime;
var bullet = BulletManager.instance.EmitBullet(bulletId, targetCellIndex, skillHandle.owner);
if (bullet != null)
{
if (statusData.needSkillPaused)
{
SkillManager.instance.screenEffect.AttachObj(bullet.rootObj);
}
}
return bullet;
}
public void UpdateTargets()
{
_UpdateTargets();
controlData.forceUpdateTarget = false;
}
protected virtual void _UpdateTargets()
{
}
protected void _CommonUpdateTargets()
{
// 已经死亡则不再索敌
if (statusData.isDead) return;
// 放技能时不索敌
if (statusData.isInSkilling) return;
if (statusData.isPretend)
{
// 伪装状态下不索敌, 并且清除当前目标
controlData.targetEnemy = null;
return;
}
var selfCellIndex = transData.cellIndex;
if (controlData.tauntUnit != null)
{
// 嘲讽单位
controlData.followUnit = controlData.tauntUnit;
}
// 强制索敌逻辑
var followUnit = controlData.followUnit;
if (followUnit != null && Level.Level.IsEnemy(this, followUnit))
{
if (!followUnit.statusData.CheckCanBeTarget(null))
{
controlData.followUnit = null;
}
else
{
// 判定范围
if (followUnit.statusData.CheckIsInAttackArea(this))
{
controlData.targetEnemy = followUnit;
if (LevelManager.Instance.CurrentLevel.selectUnit == this)
{
EventManager.Instance.Send(EventManager.EventName.INFIGHT_OP_SET_TARGET);
}
return;
}
// 不在攻击范围内,向目标移动
controlData.targetCellIndex = followUnit.transData.cellIndex;
}
}
// 优先索敌逻辑
var watchUnit = controlData.markEnemy;
if (followUnit != null)
{
// 跟随索敌覆盖优先索敌
watchUnit = followUnit;
}
if (watchUnit != null)
{
// 判断是否在攻击范围内
var canBeTarget = watchUnit.statusData.CheckCanBeTarget(this);
if (canBeTarget)
{
// 在攻击范围内,则不需要重新索敌
controlData.targetEnemy = watchUnit;
// 清空markEnemy
controlData.markEnemy = null;
// 停到当前格子
controlData.targetCellIndex = selfCellIndex;
return;
}
// 有watch目标时,不再继续索敌
controlData.targetEnemy = null;
return;
}
var oldTarget = controlData.targetEnemy;
if (oldTarget != null)
{
// 判断是否还在攻击范围内
var canBeTarget = oldTarget.statusData.CheckCanBeTarget(this);
if (canBeTarget)
{
// 还在范围内,则不需要重新索敌
return;
}
}
GameUnit target = null;
var minDistance = fightData.attackDistance + 1;
var allUnits = GameUnitManager.instance.infightUnits.unitList;
var allUnitsCount = allUnits.Count;
for (var i = 0; i < allUnitsCount; ++i)
{
var enemy = allUnits[i];
if (enemy == null) continue;
if (enemy == this) continue;
if (!statusData.isChaos && !Level.Level.IsEnemy(this, enemy)) continue;
var enemyCellIndex = enemy.transData.cellIndex;
var cellDistance = AreaManager.instance.GetDistance(selfCellIndex, enemyCellIndex);
if (cellDistance >= minDistance) continue;
if (!enemy.statusData.CheckCanBeTarget(this)) continue;
minDistance = cellDistance;
target = enemy;
}
controlData.targetEnemy = target;
}
public void TriggerCellIndexChange()
{
if (buffManager == null)
{
// 说明还没有初始化
return;
}
// 先触发已有buff
buffManager.TriggerCellIndexChange();
// 再判定格子是否有需要添加的buff
_TriggerBlockBuff();
_TriggerPickFlag();
}
public void TriggerExitUnitContainer()
{
if (buffManager == null)
{
return;
}
_TriggerBlockBuff();
_TriggerPickFlag();
}
private void _TriggerPickFlag()
{
if (statusData.isHoldFlag) return;
if (!statusData.CheckCanPickFlag()) return;
var pickFlag = FlagManager.instance.PickFlag(transData.cellIndex);
if (pickFlag == null)
{
return;
}
pickFlag.Dispose();
buffManager.AddBuffById(CodeDefine.HOLD_FLAG_BUFF_ID);
}
private void _TriggerBlockBuff()
{
if (buffManager == null)
{
return;
}
// 移除旧的
_TriggerRemoveBlockBuff();
// 添加新的
_TriggerAddBlockBuff();
}
private void _TriggerRemoveBlockBuff()
{
// -1 的时候 直接返回
if (transData.lastCellIndex == -1) return;
var oldBlockData = LevelManager.Instance.CurrentLevel.Map.GetBlockData(transData.lastCellIndex);
if (oldBlockData == null)
{
DebugUtil.LogError("CellIndexChange中的BlockData为空,cellIndex:{0}", transData.lastCellIndex);
return;
}
var blockProperty = oldBlockData.GetTerrainTypeProperty();
if (blockProperty == null)
{
DebugUtil.LogError("CellIndexChange中的BlockProperty为空,cellIndex:{0}", transData.lastCellIndex);
return;
}
if (!blockProperty.AddBuff)
{
return;
}
var buffIds = blockProperty.buffIds;
if (buffIds == null) return;
for (var i = 0; i < buffIds.Length; ++i)
{
var buffId = buffIds[i];
buffManager.RemoveBuffById(buffId);
}
}
private void _TriggerAddBlockBuff()
{
var blockData = LevelManager.Instance.CurrentLevel.Map.GetBlockData(transData.cellIndex);
if (blockData == null)
{
DebugUtil.LogError("CellIndexChange中的BlockData为空,cellIndex:{0}", transData.cellIndex);
return;
}
var blockProperty = blockData.GetTerrainTypeProperty();
if (blockProperty == null)
{
DebugUtil.LogError("CellIndexChange中的BlockProperty为空,cellIndex:{0}", transData.cellIndex);
return;
}
if (!blockProperty.AddBuff)
{
return;
}
var buffIds = blockProperty.buffIds;
if (buffIds == null) return;
for (var i = 0; i < buffIds.Length; ++i)
{
var buffId = buffIds[i];
buffManager.AddBuffById(buffId);
}
}
public virtual string GetDescString()
{
return "";
}
protected void _CreateRoadLine()
{
if (commonData.troopId != ETroopsId.Self)
{
return;
}
if (!commonData.canControl)
{
return;
}
roadLineView = new RoadLineView();
roadLineView.Init();
roadLineView.UpdateLine(this);
roadLineView.CreateEndNotice(unitUIData.uiIndex);
}
public void ForcePlayAnim(string animName)
{
_OnForcePlayAnim(animName);
}
public void RecordAnim()
{
_OnRecordAnim();
}
public void RestoreAnim()
{
_OnRestoreAnim();
}
protected virtual void _OnForcePlayAnim(string animName)
{
}
protected virtual void _OnRecordAnim()
{
}
protected virtual void _OnRestoreAnim()
{
}
public void EvacuateFromFight()
{
_OnEvacuateFromFight();
statusData.isEvacuate = true;
}
protected virtual void _OnEvacuateFromFight()
{
}
}
}