NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Common/GameUnit.cs

491 lines
16 KiB
C#

using Framework;
using Framework.Wrapper;
using Gameplay.Buff;
using Gameplay.Character;
using Gameplay.Level;
using System;
using System.Collections.Generic;
using cfg.BuffCfg;
using CodeStage.AntiCheat.ObscuredTypes;
using Gameplay.Bullet;
using Gameplay.Skill;
using PhxhSDK;
using UnityEngine;
namespace Gameplay.Common
{
public class GameUnit : Unit
{
public bool isReady = false;
public readonly EGameUnitType gameunitType;
public EAvatarType avatarType
{
get;
protected set;
}
/// <summary>
/// 公用数据,或者其他一些不知道放哪的数据
/// </summary>
public readonly UnitCommonData commonData;
/// <summary>
/// logic移动相关数据,view层主要与此进行同步
/// </summary>
public readonly UnitTransData transData;
/// <summary>
/// 生存相关数据,控制角色的死亡,复活等
/// </summary>
public readonly UnitAliveData aliveData;
/// <summary>
/// 战斗相关数据,主要用于公式计算相关
/// </summary>
public readonly UnitFightData fightData;
/// <summary>
/// 战斗内的控制数据,主要用于战斗内的逻辑控制
/// </summary>
public readonly UnitControlData controlData;
/// <summary>
/// 状态数据,主要用于标识判定
/// </summary>
public readonly UnitStatusData statusData;
/// <summary>
/// gameunit的buff管理器
/// 因为需要通过buff来控制一些属性,所以需要在gameunit中管理buff
/// </summary>
public UnitBuffManager buffManager;
public DelayMoraleDamage delayMoraleDamage;
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);
delayMoraleDamage = new DelayMoraleDamage(this);
avatarType = EAvatarType.Unknown;
gameunitType = type;
commonData.troopId = troopId;
EventManager.Instance.Send(EventManager.EventName.UnitCreate, this);
}
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()
{
if (SROptions.Current == null) return false;
var isSelf = commonData.troopId == ETroopsId.Self;
var isUnbeatable = isSelf ? SROptions.Current.SelfUnbeatable : SROptions.Current.EnemyUnbeatable;
return isUnbeatable;
}
public void TakeMoraleDamage(int damage,
GameUnit sender)
{
if (_CheckIsUnbeatble())
{
return;
}
var baseDamage = damage;
var damageScale = sender.fightData.moraleDamageScale;
var beDamageScale = fightData.moraleBeDamageScale;
var realDamage = Mathf.CeilToInt(baseDamage * damageScale * beDamageScale);
// 特殊检查
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);
}
_OnTakeMoraleDamage(realDamage);
}
public void DamageMoraleImd(int damage)
{
aliveData.currentMorale -= damage;
if (aliveData.currentMorale < 0)
{
aliveData.currentMorale = 0;
}
}
protected virtual void _OnTakeMoraleDamage(int damage)
{
commonData.lastInFightSeconds = LevelManager.Instance.CurrentLevel.LevelTime;
DamageMoraleImd(damage);
}
public void RecoverShield(int value,
bool canOverFlow)
{
_OnRecoverShield(value, canOverFlow);
}
protected virtual void _OnRecoverShield(int value,
bool canOverFlow)
{
if (canOverFlow)
{
aliveData.currentShield += value;
var maxShiled = aliveData.maxShield + fightData.overflowShiledMaxValue;
if (aliveData.currentShield > maxShiled)
{
aliveData.currentShield = maxShiled;
}
}
else
{
if (aliveData.currentHp < aliveData.maxShield)
{
aliveData.currentShield += value;
var maxShiled = aliveData.maxShield;
if (aliveData.currentShield > maxShiled)
{
aliveData.currentShield = maxShiled;
}
}
}
}
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;
}
}
public void TakeNormalDamage(ObscuredInt damage,
GameUnit sender,
bool isCritical)
{
if (_CheckIsUnbeatble())
{
return;
}
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;
// 减伤值
var valueN = GLConfig.Inst.data.FPN;
var valueK = GLConfig.Inst.data.FPK;
var preCalc = (senderLevel - commonData.level) * valueN + defense + valueK;
var reduceValue = 1f;
if (preCalc > 0)
{
reduceValue = defense / preCalc;
}
var reduceScaler = 1 - reduceValue;
var skillRate = sender.fightData.skillRate;
var scaleForSpecial = 1f;
switch (gameunitType)
{
case EGameUnitType.Character:
scaleForSpecial = sender.fightData.scaleForHuman;
break;
case EGameUnitType.Vehicle:
scaleForSpecial = sender.fightData.scaleForVehicle;
break;
}
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 = hasShield ? sender.fightData.attackScaleForShiled : sender.fightData.attackScaleForHp;
var realDamage = Mathf.CeilToInt(damage * skillRate * reduceScaler * scaleAttack * scaleForSpecial * finalDamageScale * beHitScale);
if (realDamage < 1)
{
realDamage = 1;
}
_OnTakeNormalDamage(realDamage, sender, isCritical, isignoreShield);
}
protected virtual void _OnTakeNormalDamage(ObscuredInt realDamage,
GameUnit sender,
bool isCritical, bool ignoreShield)
{
EventManager.Instance.Send(EventManager.EventName.INFIGHT_GET_DAMAGED, new EventDataGetDamaged()
{
sender = sender,
owner = this,
damage = realDamage,
isCritical = isCritical,
});
if (aliveData.currentShield > 0 && !ignoreShield)
{
if (aliveData.currentShield >= realDamage)
{
aliveData.currentShield -= realDamage;
return;
}
else
{
realDamage -= aliveData.currentShield;
aliveData.currentShield = 0;
_DamageHP(realDamage);
}
}
else
{
_DamageHP(realDamage);
}
}
private void _DamageHP(int damage)
{
aliveData.currentHp -= damage;
if (aliveData.currentHp < 0)
{
aliveData.currentHp = 0;
}
}
public void OnSelect()
{
if (DebugUtil.LogEnable)
DebugUtil.Log("Select: ----- GameUnit : {0}", GetID());
_OnSelect();
EventManager.Instance.Send(EventManager.EventName.LevelUnitSelect, this);
}
protected virtual void _OnSelect()
{
SelecterView.Instance.SetSelectAndTarget(Node, null);
}
public void OnUnSelect()
{
if (DebugUtil.LogEnable)
DebugUtil.Log("UnSelect ---- GameUnit: {0}", GetID());
_OnUnSelect();
EventManager.Instance.Send(EventManager.EventName.LevelUnitUnSelect, this);
}
protected virtual void _OnUnSelect()
{
SelecterView.Instance.UnSelect(Node);
}
public void MoveAway(GameUnit unit)
{
Vector2Int targetPos;
var map = LevelManager.Instance.CurrentLevel.Map;
map.WorldPosition2BlockPosition(unit.Node.GetPosition(), out targetPos);
var selfPos = map.TGSCellIndex2BlockPosition(transData.cellIndex);
selfPos.x = Math.Clamp((selfPos.x - targetPos.x) > 0 ? selfPos.x + 1 : selfPos.x - 1, 0, map.MapData.height - 1);
selfPos.y = Math.Clamp((selfPos.y - targetPos.y) > 0 ? selfPos.y + 1 : selfPos.y - 1, 0, map.MapData.width - 1);
MoveTo(map.BlockPosition2TGSCellIndex(selfPos), true);
}
public void MoveTo(GameUnit unit)
{
if (unit == null)
{
DebugUtil.LogError("moveto的对象为空");
return;
}
controlData.followUnit = unit;
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)
{
var wrapCellPos = map.TGSCellIndex2WorldPosition(cellIndex);
SelecterView.Instance.SetSelectAndTarget(Node, new SelecterView.TargetInfo()
{
pos = wrapCellPos
});
}
}
public void StopToCurrentCell()
{
controlData.targetCellIndex = transData.cellIndex;
controlData.followUnit = null;
}
public void UseSkill(int cellIndex, SkillHandle skillHandle)
{
//test
PlayAudio();
_OnUseSkill(cellIndex, skillHandle);
}
private async void PlayAudio()
{
await AudioManager.Instance.PlayAudio("DemoProj_S1");
}
protected virtual void _OnUseSkill(int cellIndex, SkillHandle skillHandle)
{
}
public void 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);
}
}
}
public void EmitSkillBullets(int bulletId,
List<int> cellIndexs,
SkillHandle skillHandle)
{
commonData.lastInFightSeconds = LevelManager.Instance.CurrentLevel.LevelTime;
var skillConfig = skillHandle.runtimeData.configData;
if (skillConfig.SelectCount < 0)
{
// 全选
for (var i = 0; i < cellIndexs.Count; ++i)
{
var cellIndex = cellIndexs[i];
var bullet = BulletManager.instance.EmitBullet(bulletId, cellIndex, skillHandle.owner);
if (bullet != null)
{
if (statusData.needSkillPaused)
{
SkillManager.instance.screenEffect.AttachObj(bullet.rootObj);
}
}
}
}
else
{
// 随机选择指定个数
var listAll = new List<GameUnit>();
for (var i = 0; i < cellIndexs.Count; ++i)
{
var cellIndex = cellIndexs[i];
BulletManager.instance.PreSelectUnits(cellIndex, bulletId, skillHandle.owner, listAll);
}
List<GameUnit> randomSelect = null;
if (listAll.Count > skillConfig.SelectCount)
{
// 随机指定个数
randomSelect = ArrayEx.RandomArrayFromArray(listAll, skillConfig.SelectCount);
}
else
{
randomSelect = listAll;
}
for (int i = 0; i < randomSelect.Count; i++)
{
var selectUnit = randomSelect[i];
var bullet = BulletManager.instance.EmitBullet(bulletId, selectUnit, skillHandle.owner);
if (bullet != null)
{
if (statusData.needSkillPaused)
{
SkillManager.instance.screenEffect.AttachObj(bullet.rootObj);
}
}
}
}
}
}
}