You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			414 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C#
		
	
		
		
			
		
	
	
			414 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C#
		
	
| 
											2 years ago
										 | using Entitas; | ||
|  | using System; | ||
|  | using System.Collections.Generic; | ||
|  | using UnityEngine; | ||
|  | using Game; | ||
|  | 
 | ||
|  | /// <summary> | ||
|  | /// 主角的技能连招系统 | ||
|  | /// </summary> | ||
|  | public class ComboSystem : IExecuteSystem, IInitializeSystem | ||
|  | { | ||
|  |     private IGroup<GameEntity> _entities; | ||
|  |     private List<int> _tempList = new List<int>(); | ||
|  |     public void Initialize() | ||
|  |     { | ||
|  |         _entities = Util.GetGroup(GameMatcher.Hp); | ||
|  |         EventManager.Instance.AddEvent<PPlayerInput>(EEvent.PlayerInput, OnPlayerAction); | ||
|  |         EventManager.Instance.AddEvent<PEntityMoveInput>(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<EComboStance, EComboTriggerType>(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; | ||
|  |     } | ||
|  | } |