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.
		
		
		
		
		
			
		
			
				
	
	
		
			446 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			446 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C#
		
	
| using Entitas;
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using UnityEngine;
 | |
| using Game;
 | |
| 
 | |
| /// <summary>
 | |
| /// 主角的技能连招系统
 | |
| /// </summary>
 | |
| public class ComboSystem : IExecuteSystem, IInitializeSystem
 | |
| {
 | |
|     public void Initialize()
 | |
|     {
 | |
|         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); //技能释放
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private static void RemoveControl(GameEntity entity)
 | |
|     {
 | |
|         Util.RemoveControlBuffAll(entity.ID());
 | |
|         entity.move.IsFlowing = false;
 | |
|     }
 | |
| 
 | |
|     private static 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);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private static 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;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private static 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;
 | |
|     }
 | |
| 
 | |
|     private static 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 static 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 static 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 static void OnEntityMove(PEntityMoveInput param)
 | |
|     {
 | |
|         var master = Util.GetMaster();
 | |
|         master.combo.MoveCommand = param.Command;
 | |
|     }
 | |
| 
 | |
|     private static 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 static 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 static 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 static 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;
 | |
|     }
 | |
| } |