Files
Cielonos/Assets/Scripts/MainGame/Characters/Base/Subcontrollers/Reaction/DodgeSubmodule.cs
SoulliesOfficial 8ad26129b2 Feel滚
2026-04-29 06:16:07 -04:00

174 lines
6.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Cielonos.MainGame.Characters.Inventory;
using Sirenix.OdinInspector;
using SLSUtilities.General;
using UnityEngine;
namespace Cielonos.MainGame.Characters
{
public class DodgeSubmodule : SubmoduleBase<ReactionSubcontroller>
{
public List<DodgeSource> dodgeSources;
public bool canDodge;
[ShowInInspector]
public bool isDodging => dodgeSources.Count > 0;
[ShowInInspector]
public bool isPerfectDodging => dodgeSources.Any(source => source.hasPerfectDodge && source.isDuringPerfectDodge);
public DodgeSubmodule(ReactionSubcontroller owner) : base(owner)
{
dodgeSources = new List<DodgeSource>();
canDodge = true;
}
public void ApplyDodge(DodgeSource source, bool refreshPerfect = false)
{
if (canDodge)
{
DodgeSource existingSource = dodgeSources.Find(x => x.dodgeName == source.dodgeName);
if (existingSource != null)
{
if (source.dodgeTime > existingSource.dodgeTime)
{
existingSource.dodgeTime = source.dodgeTime;
}
if (refreshPerfect && existingSource.hasPerfectDodge)
{
existingSource.isDuringPerfectDodge = true;
existingSource.perfectTime = source.perfectTime;
}
return;
}
dodgeSources.AddByPriority(source);
}
}
public void ApplyDodge(CharacterBase sourceCharacter, ItemBase sourceItem, string dodgeName,
int priority = 0, float dodgeTime = Mathf.Infinity, float perfectTime = 0.2f, bool refreshPerfect = false,
string normalEffectName = "NormalDodge", string perfectEffectName = "PerfectDodge")
{
DodgeSource newSource = new DodgeSource(sourceCharacter, sourceItem, dodgeName, priority,
normalEffectName, perfectEffectName, dodgeTime, perfectTime);
ApplyDodge(newSource, refreshPerfect);
}
public void RemoveDodge(string dodgeName)
{
dodgeSources.RemoveAll(source => source.dodgeName == dodgeName);
}
public DodgeSource GetCurrentDodgeSource()
{
return dodgeSources.Count == 0 ? null : dodgeSources[0];
}
public void Update()
{
if (isDodging)
{
dodgeSources.ForEach(source =>
{
source.dodgeTime -= owner.owner.selfTimeSm.DeltaTime;
if (source.hasPerfectDodge)
{
source.perfectTime -= owner.owner.selfTimeSm.DeltaTime;
if (source.perfectTime <= 0)
{
source.isDuringPerfectDodge = false;
}
}
});
dodgeSources.RemoveAll(source => source.dodgeTime <= 0);
}
}
}
public class DodgeSource : IPrioritized
{
public int Priority { get; private set; }
public CharacterBase sourceCharacter;
public ItemBase sourceItem;
public string dodgeName;
public bool hasPerfectDodge;
public bool isDuringPerfectDodge;
public float perfectTime;
public float dodgeTime;
public string perfectEffectName;
public Action onPerfectDodge;
public string normalEffectName;
public Action onNormalDodge;
public DodgeSource(CharacterBase sourceCharacter, ItemBase sourceItem, string dodgeName,
int priority, string dodgeEffectName, float dodgeTime)
{
this.sourceCharacter = sourceCharacter;
this.sourceItem = sourceItem;
this.dodgeName = dodgeName;
this.normalEffectName = dodgeEffectName;
this.Priority = priority;
this.dodgeTime = dodgeTime;
this.hasPerfectDodge = false;
this.isDuringPerfectDodge = false;
}
public DodgeSource(CharacterBase sourceCharacter, ItemBase sourceItem, string dodgeName,
int priority, string normalEffectName, string perfectEffectName, float dodgeTime, float perfectTime)
{
this.sourceCharacter = sourceCharacter;
this.sourceItem = sourceItem;
this.dodgeName = dodgeName;
this.normalEffectName = normalEffectName;
this.perfectEffectName = perfectEffectName;
this.Priority = priority;
this.dodgeTime = dodgeTime;
this.perfectTime = perfectTime;
this.hasPerfectDodge = true;
this.isDuringPerfectDodge = true;
}
public static DodgeSource Default(CharacterBase sourceCharacter, float duration = Mathf.Infinity)
{
DodgeSource defaultDodge = new DodgeSource(sourceCharacter, null, "DefaultDodge", 0, "NormalDodge", "PerfectDodge", duration, 0.2f);
if (sourceCharacter is Player player)
{
defaultDodge.onPerfectDodge = () =>
{
// Perfect Dodge 反馈将在 PlayerFeedbackSubcontroller 中统一处理
// 这里可以添加任何 Perfect Dodge 特有的回调逻辑
// 例如:记录完美闪避次数、触发成就等
};
}
return defaultDodge;
}
public void PerfectDodge()
{
onPerfectDodge?.Invoke();
if (sourceItem == null)
{
sourceCharacter?.feedbackSc.PlayFeedback("PerfectDodge");
Debug.Log("Perfect Dodge!");
}
}
public void NormalDodge()
{
onNormalDodge?.Invoke();
if (sourceItem == null)
{
sourceCharacter?.feedbackSc.PlayFeedback("NormalDodge");
}
}
}
}