using UnityEngine; using UnityEngine.UI; using DG.Tweening; using System.Collections.Generic; using DamageNumbersPro; public class CharacterBase : MonoBehaviour { private Animator animator; //动画片段-事件名-事件数 private Dictionary> eventCountMap = new Dictionary>(); //当前执行事件的波数 private int curEventWave = 0; //角色默认状态,默认不变 public CharacterStatus DefaultStatus { get; set; } //角色当前状态,buff什么的修改这个 public CharacterStatus CurrentStatus { get; set; } //角色buff集合 public Dictionary> buffEffectDic; //角色名 public string CharacterName { get; set; } //角色阵营 public Faction CharFaction { get; set; } //是否操作结束 public bool IsControlComplted { get; set; } //角色格子位置索引比如[0,0] public Vector2Int GridIndex { get; set; } //角色所占虚拟格子 public List VirtualGridIndexs { get; set; } //每个角色5个技能,前两个默认一样的等待和移动技能 [HideInInspector] public int[] skillIds; //所有技能数据 public SkillDataController skillDataController; //每个技能的释放时间点 [HideInInspector] public float[] skillReleaseTime = new float[5]; [HideInInspector] public Slider healthbar; //是否晕眩中 public bool IsStunning { get; set; } //晕眩剩余时间 public float StunRemainTime { get; set; } public virtual void InitCharacter(Vector2Int GridIndex, string characterName, int waitSkill, int moveSkill, int skill1Id, int skill2Id, int skill3Id) { this.GridIndex = GridIndex; CharacterName = characterName; skillIds = new int[5]; skillIds[0] = waitSkill; skillIds[1] = moveSkill; skillIds[2] = skill1Id; skillIds[3] = skill2Id; skillIds[4] = skill3Id; } private void Awake() { animator = GetComponent(); InitEventCountMap(); } private void InitEventCountMap() { foreach (var animationClip in animator.runtimeAnimatorController.animationClips) { if (!eventCountMap.ContainsKey(animationClip.name)) { eventCountMap[animationClip.name] = new Dictionary(); } foreach (var eventItem in animationClip.events) { if (!eventCountMap[animationClip.name].ContainsKey(eventItem.functionName)) { eventCountMap[animationClip.name].Add(eventItem.functionName, 0); } eventCountMap[animationClip.name][eventItem.functionName]++; } } } protected virtual void Start() { //状态 CharacterStatusContainer characterStatusContainer = BinaryDataMgr.Instance.GetTable(); // 初始化默认状态和当前状态 if (characterStatusContainer.dataDic.TryGetValue(1, out var status)) { DefaultStatus = status; CurrentStatus = CopyCharacterStatus(status); } else { Debug.LogError("初始化角色状态失败"); } //buff buffEffectDic = new Dictionary>(); VirtualGridIndexs = new List(); EventMgr.Instance.AddEventListener(EventNamesMgr.BattleUpdate, BattleUpdate); } private void BattleUpdate(float delta) { if(IsStunning) { StunRemainTime -= delta; if(StunRemainTime <= 0f) { IsStunning = false; StunRemainTime = 0f; } } } private void OnDestroy() { EventMgr.Instance.RemoveEventListener(EventNamesMgr.BattleUpdate, BattleUpdate); } public virtual Transform GetSkillBarRT() { return null; } //应用击退 public void ApplyKnockback(Vector3 targetPos) { MoveTo(targetPos); Vector2Int cacheVector2Int = GridIndex; cacheVector2Int.x++; GridIndex = cacheVector2Int; } //移动 public void MoveTo(Vector3 targetPos) { transform.DOMove(targetPos, 1f).SetEase(Ease.OutQuad); } public void MoveTo(Vector3 targetPos, Vector2Int targetIndex) { GridIndex = targetIndex; MoveTo(targetPos); } /// /// 破阵需要更新被破阵方角色的索引 /// public void ShatterUpdateGridIndex() { Vector2Int cacheVector2Int = GridIndex; cacheVector2Int.x--; GridIndex = cacheVector2Int; } //受伤 public void Damage(int damage) { if(damage != 0) { CurrentStatus.healthCur -= damage; CurrentStatus.healthCur = Mathf.Max(CurrentStatus.healthCur, 0); float value = Mathf.Clamp((float)CurrentStatus.healthCur / CurrentStatus.healthMax, 0f, 1f); //UpdateHealthbar(value); if (CurrentStatus.healthCur == 0) { Dead(); } } } //拷贝一份角色状态 private CharacterStatus CopyCharacterStatus(CharacterStatus original) { return new CharacterStatus { id = original.id, movementType = original.movementType, healthCur = original.healthCur, healthMax = original.healthMax, angerCur = original.angerCur, angerMax = original.angerMax, attack = original.attack, defence = original.defence, defenseReduction = original.defenseReduction, defenceDamageResist = original.defenceDamageResist, evade = original.evade, accuracy = original.accuracy, evadeRate = original.evadeRate, criticalChance = original.criticalChance, criticalChanceResist = original.criticalChanceResist, criticalDamage = original.criticalDamage, actionCooldown = original.actionCooldown, actionCooldownRate = original.actionCooldownRate, skillCooldownRate = original.skillCooldownRate, angerAcquisitionPassive = original.angerAcquisitionPassive, angerAcquisitionStruck = original.angerAcquisitionStruck, angerAcquisitionAttack = original.angerAcquisitionAttack, angerAcquisitionRate = original.angerAcquisitionRate, controlResist = original.controlResist, controlResistRate = original.controlResistRate, size = original.size, weight = original.weight, damageResistSlash = original.damageResistSlash, damageResistExplosive = original.damageResistExplosive, damageResistPierce = original.damageResistPierce, damageProtection = original.damageProtection, healthTemp = original.healthTemp }; } public void Dead() { Debug.LogWarning("死亡"); } //更新血条 public void UpdateHealthbar(float value) { if (healthbar == null) { ResMgr.Instance.LoadAssetAsync(ResNames.Healthbar_prefab, ResMgr.Instance.resLoadType, (result) => { if (healthbar == null) { GameObject healthbarObject = Instantiate(result); healthbarObject.name = result.name; healthbarObject.transform.SetParent(UIMgr.Instance.GetLayerFather(E_UI_Layer.Bot), false); HealthBarFollow healthBarFollow = healthbarObject.GetComponent(); healthBarFollow.target = this.transform; healthBarFollow.offset = Vector3.up; healthbar = healthbarObject.GetComponent(); healthbar.DOValue(value, 1f); } }); } else { healthbar.DOValue(value, 1f); } } //生成伤害数字 public void SpawnDamageNumber(int damage) { DamageNumber damageNumber = ResMgr.Instance.Load("DamageNumber/DamageNumber"); damageNumber.Spawn(transform.position, damage); animator.SetTrigger("BeHitTrigger"); } //播放动画 public void PlayAnim(int index) { switch (index) { case 0: { } break; case 1: break; case 2: { animator.SetTrigger("Summer02Trigger"); } break; case 3: break; case 4: break; } } //攻击事件 private void fire() { if (!CharacterMgr.Instance.attackResultMap.ContainsKey(this)) return; string animStateName = null; AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(1); if (stateInfo.IsName("summer02")) { animStateName = "summer02"; } int eventCount = eventCountMap[animStateName]["fire"]; bool isFinalWave = (curEventWave == eventCount - 1); ProcessAttackResults(isFinalWave); if (!isFinalWave) { curEventWave++; } } private void ProcessAttackResults(bool processAll) { foreach (List attackResults in CharacterMgr.Instance.attackResultMap.Values) { for (int i = attackResults.Count - 1; i >= 0; i--) { if (processAll || attackResults[i].hitWaveIndex == curEventWave) { attackResults[i].characterBase.SpawnDamageNumber((int)attackResults[i].damage); attackResults.RemoveAt(i); } } } } }