using Entitas; using System; using System.Collections.Generic; using UnityEngine; using Game; /// /// 主角的技能连招系统 /// public class ComboSystem : IExecuteSystem, IInitializeSystem { private IGroup _entities; private List _tempList = new List(); public void Initialize() { _entities = Util.GetGroup(GameMatcher.Hp); EventManager.Instance.AddEvent(EEvent.PlayerInput, OnPlayerAction); EventManager.Instance.AddEvent(EEvent.EntityMoveInput, OnEntityMove); } public void Execute() { var entity = Util.GetMaster(); if (Util.IsPause(entity)) { return; } UpdateComboStance(entity); //更新技能姿态 UpdateCheckCacheTime(entity); //技能缓存时间检查 //检查技能取消 可清除buff if (UpdateCheckCancel(entity)) { RemoveControl(entity); } //硬直状态无法释放技能 if (!Util.EntityIsStagger(entity)) { UpdateComboCast(entity);//技能释放 } } public void RemoveControl(GameEntity entity) { Util.RemoveControlBuffAll(entity.ID()); entity.move.IsFlowing = false; } public void UpdateComboStance(GameEntity entity) { var combo = entity.combo; var skill = entity.skill; var move = entity.move; var isGround = entity.move.IsGroundLogic; if (combo.Stance == EComboStance.Idle || combo.Stance == EComboStance.AirIdle) { combo.Stance = isGround ? EComboStance.Idle : EComboStance.AirIdle; } var hasSkill = skill.IsRunning; if (isGround && hasSkill) { //落地取消 if (combo.IsGroundCancelable) { Util.EndSkillTimeline(entity); } } } public void UpdateCheckCacheTime(GameEntity entity) { var combo = entity.combo; var dt = Time.deltaTime; var count = combo.InputQueue.Count; if (count == 0) return; foreach (var info in combo.InputQueue) { info.TimeRecord -= dt * 2; if (info.TimeRecord < 0) { info.Active = false; } } for (int i = count - 1; i >= 0; i--) { var info = combo.InputQueue[i]; if (!info.Active) { combo.InputQueue.RemoveAt(i); } } //取消缓存的保护时间 var safeTime = combo.TriggerCancelSafeTime; if (safeTime > 0) { safeTime -= dt; if (safeTime < 0) { safeTime = 0; } combo.TriggerCancelSafeTime = safeTime; } } public bool UpdateCheckCancel(GameEntity entity) { var combo = entity.combo; var isCancel = false; foreach (var info in combo.InputQueue) { var triggerType = GetSkillTriggerType(info.InputInfo); if (Util.HasComboAny(entity, triggerType)) { isCancel = true; break; } } if (isCancel) { //删除取消指令之前的所有指令 foreach (var info in combo.InputQueue) { var triggerType = GetSkillTriggerType(info.InputInfo); if (Util.HasComboAny(entity, triggerType)) { break; } info.Active = false; } } return isCancel; } public void UpdateComboCast(GameEntity entity) { var combo = entity.combo; var skill = entity.skill; var move = entity.move; var hasSkill = skill.IsRunning; if (combo.InputQueue.Count == 0) return; if (!move.IsSkillAble) return; //成功触发一个 则删除前面的全部 var isTrigger = false; for (int i = 0; i < combo.InputQueue.Count; i++) { var input = combo.InputQueue[i]; if (!input.Active) { continue; } var stanceNow = combo.Stance; var triggerType = GetSkillTriggerType(input.InputInfo); if (triggerType == EComboTriggerType.Jump) { if (hasSkill) { //JC if (combo.IsJumpCancelable) { move.IsJumpCommand = true; isTrigger = true; Util.EndSkillTimeline(entity); } } else { //正常跳跃 if (combo.Stance == EComboStance.Idle) { entity.move.IsJumpCommand = true; isTrigger = true; } } } else { var skillCastId = ""; if (Util.HasComboAny(entity, triggerType)) { //任意姿态技能 if (!hasSkill || combo.IsSkillCancelable) { skillCastId = Util.GetComboAny(entity, triggerType); } } else { //指定姿态技能 var skillKey = new Tuple(stanceNow, triggerType); if (Util.HasCombo(entity, skillKey)) { skillCastId = Util.GetCombo(entity, skillKey); } } if (!string.IsNullOrEmpty(skillCastId)) { ComboCast(entity, skillCastId); isTrigger = true; } } if (isTrigger) { //成功触发技能,对指令队列进行更新 if (isTrigger) { for (int j = 0; j < combo.InputQueue.Count; j++) { var info = combo.InputQueue[j]; if (j < i) { //触发指令之前的指令全部失效,保护时间内不处理 if (combo.TriggerCancelSafeTime == 0) { info.Active = false; } } else if (j == i) { //触发的指令失效 info.Active = false; } else { break; } } //更新combo最后触发时间 combo.TriggerCancelSafeTime = GameConst.InputRecordTriggerCancelSafeTime; } break; } } } private void ComboCast(GameEntity entity, string skillCastId) { var combo = entity.combo; var skill = entity.skill; var skillCfg = Util.GetSkillMasterConfig(skillCastId); var skillCfgCombo = skillCfg.SkillCombo; combo.PreStance = (EComboStance)skillCfgCombo.StanceEnd; // combo.stance = skillCfg.StanceCache ? combo.stance : EComboStance.None; // TODO step系统做法待定 combo.Stance = EComboStance.None; var castDir = GetSkillCastDir(entity, skillCfgCombo.FreeLock); Util.CastSkill(entity, skillCastId, skillCfg.Skill.Timeline, castDir); } private Vector3 GetSkillCastDir(GameEntity entity, bool isFreeLock) { var combo = entity.combo; var move = entity.move; var castDir = Vector3.zero; if (!isFreeLock && combo.TargetLock > 0) { var target = Util.GetEntity(combo.TargetLock); castDir = (target.move.Position - move.Position).normalized; } else { Vector3 moveDir; if (GameConst.MoveCommand2Dir.TryGetValue(combo.MoveCommand, out moveDir)) { castDir = moveDir; } } if (castDir.x == 0 && castDir.z == 0) { castDir = move.IsRight ? Vector3.right : Vector3.left; } return castDir; } private void OnEntityMove(PEntityMoveInput param) { var master = Util.GetMaster(); master.combo.MoveCommand = param.Command; } private void OnPlayerAction(PPlayerInput info) { var master = Util.GetMaster(); var pressSet = master.combo.KeyPressSet; if (info.Action == EKeyActionType.Press) { pressSet.Add(info.Key); } else if (info.Action == EKeyActionType.Release) { if (pressSet.Contains(info.Key)) { pressSet.Remove(info.Key); } } if (!Util.IsControl()) { //处于Combo系统不接收输入的状态 return; } var weaponChangeType = GetEWeaponChangeType(info); if (weaponChangeType != EWeaponChangeType.None) { //武器更换 ChangeWeapon(weaponChangeType); return; } if (GetSkillTriggerType(info) != EComboTriggerType.None) { //技能指令输入 master.combo.InputQueue.Add(new ComboInputRecord() { InputInfo = info, TimeRecord = GameConst.InputRecordTime, Active = true, }); return; } } private void ChangeWeapon(EWeaponChangeType changeType) { var master = Util.GetMaster(); var combo = master.combo; var weaponNum = combo.WeaponList.Count; var weaponNow = combo.WeaponNow; var weaponNew = weaponNow.Value; switch (changeType) { case EWeaponChangeType.None: break; case EWeaponChangeType.SetNext: weaponNew = weaponNow.Value + 1; break; case EWeaponChangeType.SetPre: weaponNew = weaponNow.Value - 1; break; default: weaponNew = (int)changeType; break; } weaponNow.Value = (weaponNew + weaponNum) % weaponNum; //切换武器时重置姿态 // combo.stance = EComboStance.Idle; // combo.preStance = EComboStance.Idle; } private EComboTriggerType GetSkillTriggerType(PPlayerInput info) { if (info.Action == EKeyActionType.Press) { if (info.Key == EFunctionKey.LightAttack) { return EComboTriggerType.LightAttack; } if (info.Key == EFunctionKey.HeavyAttack) { return EComboTriggerType.HeavyAttack; } if (info.Key == EFunctionKey.Flash) { return EComboTriggerType.Flash; } if (info.Key == EFunctionKey.Jump) { return EComboTriggerType.Jump; } } if (info.Action == EKeyActionType.Release) { if (info.Key == EFunctionKey.LightAttack) { return EComboTriggerType.LightAttackRelease; } if (info.Key == EFunctionKey.HeavyAttack) { return EComboTriggerType.HeavyAttackRelease; } } return EComboTriggerType.None; } private EWeaponChangeType GetEWeaponChangeType(PPlayerInput info) { var ret = EWeaponChangeType.None; if (info.Action != EKeyActionType.Press) { return ret; } switch (info.Key) { case EFunctionKey.WeaponPre: ret = EWeaponChangeType.SetPre; break; case EFunctionKey.WeaponNext: ret = EWeaponChangeType.SetNext; break; case EFunctionKey.Weapon0: ret = EWeaponChangeType.Set0; break; case EFunctionKey.Weapon1: ret = EWeaponChangeType.Set1; break; case EFunctionKey.Weapon2: ret = EWeaponChangeType.Set2; break; case EFunctionKey.Weapon3: ret = EWeaponChangeType.Set3; break; } return ret; } }