Files
Cielonos/Assets/Opsive/BehaviorDesigner/Add-Ons/CielonosPack/Conditionals/RhythmAttackDetector.cs
SoulliesOfficial c9d9f60073 IFD敌人初步
2026-06-14 04:17:41 -04:00

116 lines
3.6 KiB
C#

using Cielonos.MainGame.Characters.AI;
using Opsive.BehaviorDesigner.Runtime.Tasks;
using Opsive.Shared.Utility;
using UnityEngine;
namespace Cielonos.MainGame.Characters.AI
{
[Category("Cielonos/Rhythm")]
[Description("Returns Success if an upcoming beat containing a tag that starts with 'EnemyAttack' is within the lead time. Otherwise returns Failure.")]
public class RhythmAttackDetector : AutomataConditionalBase
{
[Tooltip("The lead time before the beat in seconds.")]
public float leadTime = 0.1f;
[Tooltip("The prefix of the tag to match.")]
public string tagPrefix = "EnemyAttack";
private MusicBeatSystem _beatSystem;
private BeatMarker _lastTriggeredBeat;
public override void OnAwake()
{
base.OnAwake();
_beatSystem = CombatManager.GetCombatSystem<MusicBeatSystem>();
}
public override void OnStart()
{
_lastTriggeredBeat = null;
}
public override TaskStatus OnUpdate()
{
if (_beatSystem == null || !_beatSystem.IsActive || _beatSystem.CurrentBeatData == null)
{
return TaskStatus.Failure;
}
BeatMarker targetBeat = FindNextMatchingBeat();
if (targetBeat == null)
{
return TaskStatus.Failure;
}
// If we have already triggered for this specific beat, we shouldn't succeed again
if (_lastTriggeredBeat == targetBeat)
{
return TaskStatus.Failure;
}
float timeUntilBeat = targetBeat.time - _beatSystem.CurrentSongTime;
// Check if we are within the lead time window
if (timeUntilBeat <= leadTime)
{
TriggerDetection(targetBeat, timeUntilBeat);
return TaskStatus.Success;
}
return TaskStatus.Failure;
}
private BeatMarker FindNextMatchingBeat()
{
float currentTime = _beatSystem.CurrentSongTime;
var markers = _beatSystem.CurrentBeatData.beatMarkers;
if (markers == null) return null;
for (int i = 0; i < markers.Count; i++)
{
BeatMarker marker = markers[i];
// Check for upcoming beats
if (marker.time > currentTime)
{
if (marker.tags != null)
{
for (int j = 0; j < marker.tags.Count; j++)
{
if (marker.tags[j].StartsWith(tagPrefix))
{
return marker;
}
}
}
}
}
return null;
}
private void TriggerDetection(BeatMarker beat, float timeUntilBeat)
{
_lastTriggeredBeat = beat;
// Log matching tags for identification
string matchedTag = "";
if (beat.tags != null)
{
foreach (string t in beat.tags)
{
if (t.StartsWith(tagPrefix))
{
matchedTag = t;
break;
}
}
}
Debug.Log($"[RhythmAttackDetector] Conditional MET for {self.gameObject.name} at {beat.time:F3}s " +
$"(in {timeUntilBeat:F3}s) with matched tag '{matchedTag}'.");
}
}
}