116 lines
3.6 KiB
C#
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}'.");
|
|
}
|
|
}
|
|
}
|