NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Character/CharacterManager.cs

435 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Framework;
using Gameplay.Buff;
using Gameplay.Character.Utils;
using Gameplay.Common;
using Gameplay.Net;
using Gameplay.Skill;
using PhxhSDK;
using UnityEngine;
using Constants = Framework.Constants;
namespace Gameplay.Character
{
public class CharacterManager : IDisposable, IUpdatable
{
private readonly Dictionary<uint, Character> _characterDict = new Dictionary<uint, Character>(32);
private readonly List<Character> _characterList = new List<Character>();
private readonly Dictionary<int, Troops> _troopDict = new Dictionary<int, Troops>();
public List<Character> characterList
{
get
{
return _characterList;
}
}
private bool _needRefreshTargets = false;
public void Init()
{
_RegistEvent();
}
public async UniTask EnterBattle()
{
for (var i = 0; i < _characterList.Count; ++i)
{
var character = _characterList[i];
await character.EnterBattle();
}
_needRefreshTargets = true;
}
public void LeaveBattle()
{
for (var i = 0; i < _characterList.Count; ++i)
{
var character = _characterList[i];
character.LeaveBattle();
}
}
private void _RegistEvent()
{
EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, (Action<GameUnit>)_OnAnyCharacterCellIndexChange);
EventManager.Instance.Register(EventManager.EventName.INFIGHT_UP_VEHICLE, (Action<GameUnit>)_OnAnyCharacterCellIndexChange);
EventManager.Instance.Register(EventManager.EventName.INFIGHT_DOWN_VEHICLE, (Action<GameUnit>)_OnAnyCharacterCellIndexChange);
EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_DEAD, (Action<GameUnit>)_OnCharacterDead);
}
private void _OnCharacterDead(GameUnit deadCharacter)
{
_needRefreshTargets = true;
}
private void _OnAnyCharacterCellIndexChange(GameUnit noUse)
{
_needRefreshTargets = true;
}
private void _UnRegistEvent()
{
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, (Action<GameUnit>)_OnAnyCharacterCellIndexChange);
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UP_VEHICLE, (Action<GameUnit>)_OnAnyCharacterCellIndexChange);
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_DOWN_VEHICLE, (Action<GameUnit>)_OnAnyCharacterCellIndexChange);
EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_DEAD, (Action<GameUnit>)_OnCharacterDead);
}
private void _UpdateTargets()
{
_needRefreshTargets = true;
for (int i = 0; i < _characterList.Count; i++)
{
var character = _characterList[i];
character.UpdateTargets();
}
}
public void Dispose()
{
_UnRegistEvent();
foreach (var charactor in _characterDict)
{
charactor.Value.Dispose();
}
_characterDict.Clear();
}
private async UniTask<Character> _Create(uint id,
CharacterConfigData configData,
int teamId, Vector3 pos, float yaw)
{
DebugUtil.Log("Create Character id: {0} troopId: {1}",id, teamId);
var character = new Character(id, configData, teamId);
character.transData.disableEvent = true;
character.transData.pos = pos;
character.transData.yaw = yaw;
character.transData.disableEvent = false;
character.Node.GameObject.transform.position = pos;
character.Node.GameObject.transform.localRotation = Quaternion.Euler(0, yaw, 0);
await character.LoadAsync();
await _AddCharacter(character);
return character;
}
private async UniTask _AddCharacter(Character character)
{
BuffManager.instance.InitCharacter(character);
await SkillManager.instance.InitCharacter(character);
_characterDict.Add(character.GetID(), character);
_characterList.Add(character);
_AddToTroop(character);
character.buffManager.TriggerEnterBattle();
}
private void _RemoveCharacter(Character c,
int index = -1)
{
c?.LeaveBattle();
if (index == -1)
{
index = _characterList.IndexOf(c);
}
_characterDict.Remove(c.GetID());
_characterList.RemoveAt(index);
_RemoveFromTroop(c);
BuffManager.instance.RemoveCharacter(c);
SkillManager.instance.RemoveCharacter(c);
c.Dispose();
}
private void _RemoveFromTroop(Character c)
{
var teamId = c.commonData.troopId;
if (_troopDict.TryGetValue(teamId, out Troops team))
{
team.characters.Remove(c);
}
}
public async UniTask<Character> CreateNPC(int npcId,
int teamId,
int level,
Vector3 pos,
float yaw)
{
var uId = GUIDManager.GenGuid();
var monsterConfig = TableManager.Instance.Tables.Monster.Get(npcId);
var monsterTConfig = TableManager.Instance.Tables.MonsterClass.Get(monsterConfig.MonsterClassID);
var monsterLevelConfig = TableManager.Instance.Tables.MonsterLevelUp.Get(level);
var configData = new CharacterConfigData();
configData.level = level;
configData.attack = Mathf.CeilToInt(monsterTConfig.Attack * monsterConfig.AttackFix * monsterLevelConfig.AttackLevelUpTemplate);
var shootCD = 1f / monsterTConfig.ShootSpeed;
configData.shootCD = shootCD;
configData.firstShootTime = monsterTConfig.FirstShootTime;
configData.maxBulletCount = monsterTConfig.ManagazinContain;
configData.reloadTime = monsterTConfig.ChangeBulletTime;
configData.defense = Mathf.CeilToInt(monsterTConfig.Defence * monsterConfig.DefenceFix * monsterLevelConfig.DefenceLevelUpTemplate);
configData.defenseScale = monsterTConfig.DefenceStatusPara;
configData.maxHp = Mathf.CeilToInt(monsterTConfig.Hp * monsterConfig.HPFix * monsterLevelConfig.HpLevelUpTemplate);
configData.maxShield = Mathf.CeilToInt(monsterTConfig.Shield * monsterConfig.ShieldFix * monsterLevelConfig.ShieldLevelUpTemplate);
configData.moveSpeed = monsterTConfig.Speed;
configData.retreatSpeed = monsterTConfig.RetreatSpeed;
configData.shootDistance = monsterTConfig.ShootRange;
configData.moraleAttack = (int)monsterTConfig.YaZhi;
configData.initMorale = monsterTConfig.MaxMorale;
configData.maxMorale = monsterTConfig.MaxMorale;
configData.suppressMorale = monsterTConfig.SuppressMorale;
configData.retreatMorale = monsterTConfig.RetreatMorale;
configData.moraleRecover = (int)monsterTConfig.CorrageRecover;
configData.damagePepoleScale = monsterTConfig.DamageToHuman;
configData.damageCarsScale = monsterTConfig.DamageToCarrier;
configData.criticalRate = monsterTConfig.CriticalRatio;
configData.criticalScale = monsterTConfig.CriticalDamage;
configData.moveShootType = monsterTConfig.MoveShootType;
configData.breakShootType = (int)monsterTConfig.ShootMode;
configData.perShootCount = monsterTConfig.PerShootCount;
configData.skillId = monsterTConfig.SkillId;
configData.turnSpeed = monsterTConfig.TurnSpeed;
configData.job = monsterTConfig.Job;
configData.faction = monsterTConfig.Fraction;
configData.rarity = 0;
configData.modelPath = monsterTConfig.PrefabPath;
configData.weaponId = monsterTConfig.WeaponId;
configData.crossLevel = monsterTConfig.MoveCrossLevel;
configData.standLevel = monsterTConfig.StandCrossLevel;
configData.findEnemyRange = monsterConfig.FindEnemyRange;
configData.eyeBrowsType = monsterTConfig.EmojiEyeBowsType;
configData.eyeBrowColor = monsterTConfig.EmojiEyeBowsColor;
configData.eyesColor = monsterTConfig.EmojiEyesColor;
configData.inFightEmojiId = monsterTConfig.DefaultEmojiImgId;
return await _Create(uId, configData, teamId, pos, yaw);
}
public async UniTask<Character> CreateCharacter(CharacterDataInfo characterInfo,
int teamId, Vector3 pos, float yaw)
{
var cId = characterInfo.Cfg.RoleID;
var characterData = TableManager.Instance.Tables.CharacterAttri.Get(cId);
var fakeLevel = (int)characterInfo.Level;
var levelIndex = fakeLevel - 1;
var attackDataList = characterData.Attack;
var defenceDataList = characterData.Defence;
var hpDataList = characterData.Hp;
var shieldDataList = characterData.Shield;
var levelAttack = attackDataList[levelIndex];
var levelDefence = defenceDataList[levelIndex];
var levelHp = hpDataList[levelIndex];
var levelShield = shieldDataList[levelIndex];
var skillId = CharacterDataHelper.GetCharacterSkillId(characterInfo);
var configData = new CharacterConfigData();
configData.level = fakeLevel;
configData.attack = levelAttack;
var shootCD = 1f / characterData.ShootSpeed;
configData.shootCD = shootCD;
configData.firstShootTime = characterData.FirstShootTime;
configData.maxBulletCount = characterData.ManagazinContain;
configData.reloadTime = characterData.ChangeBulletTime;
configData.defense = levelDefence;
configData.defenseScale = characterData.DefenceStatusPara;
configData.maxHp = levelHp;
configData.maxShield = levelShield;
configData.moveSpeed = characterData.Speed;
configData.retreatSpeed = characterData.RetreatSpeed;
configData.shootDistance = characterData.ShootRange;
configData.moraleAttack = (int)characterData.YaZhi;
configData.initMorale = characterData.MaxMorale;
configData.maxMorale = characterData.MaxMorale;
configData.suppressMorale = characterData.SuppressMorale;
configData.retreatMorale = characterData.RetreatMorale;
configData.moraleRecover = (int)characterData.CorrageRecover;
configData.damagePepoleScale = characterData.DamageToHuman;
configData.damageCarsScale = characterData.DamageToCarrier;
configData.criticalRate = characterData.CriticalRatio;
configData.criticalScale = characterData.CriticalDamage;
configData.moveShootType = characterData.MoveShootType;
configData.breakShootType = (int)characterData.ShootMode;
configData.perShootCount = characterData.PerShootCount;
configData.skillId = skillId;
configData.turnSpeed = characterData.TurnSpeed;
configData.job = characterData.Job;
configData.faction = characterData.Fraction;
configData.rarity = characterData.StartStar;
configData.modelPath = TableManager.Instance.Tables.SkinCfg.Get(Constants.DEFULT_SKINID,characterData.RoleID).PrefabPath;
configData.weaponId = characterData.WeaponId;
configData.crossLevel = characterData.MoveCrossLevel;
configData.standLevel = characterData.StandCrossLevel;
configData.boundTags = new List<int>();
configData.boundTags.Add((int)characterData.Fraction);
configData.shiledRecoverDelay = characterData.ShieldRecoverDelay;
configData.shieldRecoverFix = characterData.ShiledRecoverValueFixed;
configData.shiledRecoverPercent = characterData.ShiledRecoverValuePercent;
configData.overflowShield = characterData.OverFlowShiledMax;
configData.hpRecoverDelay = characterData.HPRecoverDelay;
configData.hpRecoverFix = characterData.HPRecoverValueFixed;
configData.hpRecoverPercent = characterData.HPRecoverValuePercent;
configData.attackShiledScale = characterData.AttackShiledScale;
configData.attackHpScale = characterData.AttackHpScale;
configData.eyeBrowsType = characterData.EmojiEyeBowsType;
configData.eyesColor = characterData.EmojiEyesColor;
configData.eyeBrowColor = characterData.EmojiEyeBowsColor;
configData.inFightEmojiId = characterData.DefaultEmojiImgId;
return await _Create(characterInfo.ID, configData, teamId, pos, yaw);
}
private void _AddToTroop(Character c)
{
var teamId = c.commonData.troopId;
if (_troopDict.TryGetValue(teamId, out Troops team))
{
team.characters.Add(c);
}
else
{
team = new Troops(teamId);
team.characters.Add(c);
_troopDict.Add(teamId, team);
}
}
public void Remove(uint id)
{
try
{
if (_characterDict.TryGetValue(id, out Character c))
{
_RemoveCharacter(c);
//c.Dispose();
}
}
catch (Exception e)
{
DebugUtil.LogError("Remove character error: {0}", e.Message);
}
}
public Character Get(uint id)
{
Character character;
_characterDict.TryGetValue(id, out character);
return character;
}
public void SearchEnemies(GameUnit self,
List<GameUnit> enemyList)
{
if (self == null) return;
if (self.controlData.followUnit != null
&& Level.Level.IsEnemy(self.controlData.followUnit.commonData.troopId, self.commonData.troopId))
{
enemyList.Add(self.controlData.followUnit);
}
foreach (var team in _troopDict)
{
if (Level.Level.IsEnemy(team.Key, self.commonData.troopId))
{
enemyList.AddRange(team.Value.characters);
}
}
}
public void SearchFriends(GameUnit self,
List<GameUnit> friendList)
{
if (self == null) return;
if (self.controlData.followUnit != null
&& !Level.Level.IsEnemy(self.controlData.followUnit.commonData.troopId, self.commonData.troopId))
{
friendList.Add(self.controlData.followUnit);
}
foreach (var team in _troopDict)
{
if (!Level.Level.IsEnemy(team.Key, self.commonData.troopId))
{
friendList.AddRange(team.Value.characters);
}
}
}
public void Update(float deltaTime)
{
for (var i = 0; i < _characterList.Count; ++i)
{
var character = _characterList[i];
character.Update(deltaTime);
if (character.runtimeData.needRemove)
{
// 触发buff
character.buffManager.TriggerExitBattle();
_RemoveCharacter(character, i);
i--;
}
}
if (_needRefreshTargets)
{
_UpdateTargets();
}
}
public void ForEach(Action<Character> action)
{
foreach (var charactor in _characterDict)
{
action(charactor.Value);
}
}
public List<Character> FindAll(Func<Character, bool> conditions)
{
List<Character> result = new List<Character>();
foreach (var charactor in _characterDict)
{
if (conditions(charactor.Value))
{
result.Add(charactor.Value);
}
}
return result;
}
public Character FindOne(Func<Character, bool> conditions)
{
foreach (var charactor in _characterDict)
{
if (conditions(charactor.Value))
{
return charactor.Value;
}
}
return null;
}
}
}