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;
|
|
}
|
|
} |