Files
Cielonos/Assets/Scripts/MainGame/Characters/Base/Subcontrollers/Reaction/DodgeSubmodule.cs

197 lines
6.9 KiB
C#
Raw Normal View History

2025-11-25 08:19:33 -05:00
using System;
using System.Collections.Generic;
using System.Linq;
2026-05-23 08:27:50 -04:00
using Cielonos.MainGame.Inventory;
2025-11-25 08:19:33 -05:00
using Sirenix.OdinInspector;
2026-02-13 09:22:11 -05:00
using SLSUtilities.General;
2025-11-25 08:19:33 -05:00
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);
2026-05-10 11:47:55 -04:00
public float afterPerfectDodgeTimer;
public float afterNormalDodgeTimer;
2025-11-25 08:19:33 -05:00
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()
{
2026-02-13 09:22:11 -05:00
return dodgeSources.Count == 0 ? null : dodgeSources[0];
2025-11-25 08:19:33 -05:00
}
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);
}
2026-05-10 11:47:55 -04:00
afterPerfectDodgeTimer -= owner.owner.selfTimeSm.DeltaTime;
afterNormalDodgeTimer -= owner.owner.selfTimeSm.DeltaTime;
2025-11-25 08:19:33 -05:00
}
}
public class DodgeSource : IPrioritized
{
public int Priority { get; private set; }
public CharacterBase sourceCharacter;
public ItemBase sourceItem;
public string dodgeName;
2026-05-23 08:27:50 -04:00
public float dodgeBufferTime = 0.5f;
2025-11-25 08:19:33 -05:00
public bool hasPerfectDodge;
public bool isDuringPerfectDodge;
public float perfectTime;
public float dodgeTime;
public string perfectEffectName;
public Action onPerfectDodge;
public string normalEffectName;
public Action onNormalDodge;
2026-05-23 08:27:50 -04:00
private bool _isTriggered;
2025-11-25 08:19:33 -05:00
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;
2026-05-23 08:27:50 -04:00
this._isTriggered = false;
2025-11-25 08:19:33 -05:00
}
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;
2026-05-23 08:27:50 -04:00
this._isTriggered = false;
2025-11-25 08:19:33 -05:00
}
2026-02-13 09:22:11 -05:00
public static DodgeSource Default(CharacterBase sourceCharacter, float duration = Mathf.Infinity)
{
2026-05-26 10:48:49 -04:00
DodgeSource defaultDodge = new DodgeSource(sourceCharacter, null,
"DefaultDodge", 0, "NormalDodge", "PerfectDodge", duration, 0.2f);
2026-02-13 09:22:11 -05:00
if (sourceCharacter is Player player)
{
defaultDodge.onPerfectDodge = () =>
{
2026-04-18 13:57:19 -04:00
// Perfect Dodge 反馈将在 PlayerFeedbackSubcontroller 中统一处理
// 这里可以添加任何 Perfect Dodge 特有的回调逻辑
// 例如:记录完美闪避次数、触发成就等
2026-02-13 09:22:11 -05:00
};
}
return defaultDodge;
}
2025-11-25 08:19:33 -05:00
public void PerfectDodge()
{
2026-05-23 08:27:50 -04:00
if(_isTriggered) return;
_isTriggered = true;
2025-12-22 18:36:29 -05:00
onPerfectDodge?.Invoke();
2025-11-25 08:19:33 -05:00
if (sourceItem == null)
{
2026-05-10 11:47:55 -04:00
sourceCharacter.feedbackSc.PlayFeedback("PerfectDodge");
2025-11-25 08:19:33 -05:00
}
2026-05-10 11:47:55 -04:00
2026-05-23 08:27:50 -04:00
sourceCharacter.reactionSc.dodgeSm.afterPerfectDodgeTimer = dodgeBufferTime + 0.25f;
2025-11-25 08:19:33 -05:00
}
public void NormalDodge()
{
2026-05-23 08:27:50 -04:00
if(_isTriggered) return;
_isTriggered = true;
2025-12-22 18:36:29 -05:00
onNormalDodge?.Invoke();
2025-11-25 08:19:33 -05:00
if (sourceItem == null)
{
2026-05-10 11:47:55 -04:00
sourceCharacter.feedbackSc.PlayFeedback("NormalDodge");
2025-11-25 08:19:33 -05:00
}
2026-05-10 11:47:55 -04:00
2026-05-23 08:27:50 -04:00
sourceCharacter.reactionSc.dodgeSm.afterNormalDodgeTimer = dodgeBufferTime + 0.25f;
2025-11-25 08:19:33 -05:00
}
}
}