Files
ichni_Official/Assets/Scripts/Game/GameElements/Notes/NoteObjects/Hold.cs
SoulliesOfficial 7580c4d87c 大更
2026-03-14 03:13:10 -04:00

306 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using Dreamteck.Splines;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using Unity.VisualScripting;
using UnityEngine;
namespace Ichni.RhythmGame
{
public class Hold : NoteBase
{
#region [] Special Fields
public float holdEndTime;
public float holdingTime;
public bool isHolding;
public float holdingBufferTime;
public float bufferTimer;
public float preTimeDifference;
public NoteJudgeType preJudgeType;
public float postTimeDifference;
public NoteJudgeType postJudgeType;
protected List<EffectBase> startHoldEffects;
protected List<EffectBase> holdingEffects;
#endregion
#region [] Generation & Initialization
public static Hold GenerateElement(string elementName, Guid id, List<string> tags, bool isFirstGenerated,
GameElement parentElement, float exactJudgeTime, float holdEndTime)
{
Hold hold = LeanPool.Spawn(GameManager.Instance.basePrefabs.holdNote, parentElement.transform).GetComponent<Hold>();
hold.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
hold.exactJudgeTime = exactJudgeTime;
hold.holdEndTime = holdEndTime;
hold.holdingTime = 0;
hold.holdingBufferTime = 0.04f;
hold.judgeIntervals = NoteJudgeIntervals.HoldDefault;
hold.preJudgeType = NoteJudgeType.NotJudged;
hold.postJudgeType = NoteJudgeType.NotJudged;
if (parentElement.TryGetComponent(out Track track) && track.trackTimeSubmodule != null)
{
hold.track = track;
hold.trackPositioner.enabled = true;
hold.trackPositioner.spline = track.trackPathSubmodule.path;
hold.trackPositioner.updateMethod = SplineUser.UpdateMethod.LateUpdate;
hold.isOnTrack = true;
hold.UpdateNoteInTrack(CoreServices.TimeProvider.SongTime);
}
else
{
hold.track = null;
hold.isOnTrack = false;
}
return hold;
}
public override void AfterInitialize()
{
base.AfterInitialize();
startHoldEffects = GetEffectListSafe("StartHold");
holdingEffects = GetEffectListSafe("Holding");
}
public override void SetDefaultSubmodules()
{
base.SetDefaultSubmodules();
NoteAudioSubmodule = new NoteAudioSubmodule(this, "DefaultTap"); // 注意以前是你写死的 DefaultTap依据需求核对
}
#endregion
#region [] Main Update
public override bool ManualUpdate(float currentSongTime)
{
if (!base.ManualUpdate(currentSongTime)) return false;
if (!isFirstJudged && !isDuringJudging &&
currentSongTime >= exactJudgeTime + judgeIntervals.beforeMiss.intervalStart &&
!GameManager.Instance.noteJudgeManager.checkingHoldList.Contains(this))
{
isDuringJudging = true;
GameManager.Instance.noteJudgeManager.checkingHoldList.Add(this);
}
if (!GameManager.Instance.songPlayer.isUpdating || isFinalJudged) return true;
if (SettingsManager.instance.gameSettings.autoPlay && isFirstJudged) ExecuteProcessJudge();
if (isHolding)
{
holdingTime = currentSongTime - exactJudgeTime;
bufferTimer = holdingBufferTime;
}
else if (isFirstJudged)
{
bufferTimer -= Time.deltaTime;
}
if (isOnTrack) UpdateNoteInTrack(currentSongTime);
if (isDuringJudging) noteScreenPosition = GetScreenPosition();
SetJudgeArea();
if (!isFirstJudged && exactJudgeTime < currentSongTime) SlowOffsetAfterExactJudgeTime();
UpdateHoldEffects();
if (SettingsManager.instance.gameSettings.autoPlay && !isFirstJudged && currentSongTime >= exactJudgeTime)
{
ExecuteStartJudge(currentSongTime);
}
CheckHoldLifeCycle(currentSongTime);
return true;
}
private void CheckHoldLifeCycle(float currentSongTime)
{
if (isFirstJudged && currentSongTime > holdEndTime)
{
isHolding = false;
isFinalJudged = true;
ExecuteFinalJudge(currentSongTime);
RemoveFromCheckingList();
}
else if (isFirstJudged && bufferTimer < 0f)
{
isHolding = false;
isFinalJudged = true;
DisruptHoldEffects();
ExecuteFinalJudge(currentSongTime);
RemoveFromCheckingList();
}
else if (!isFirstJudged && currentSongTime > exactJudgeTime + judgeIntervals.afterMiss)
{
isFirstJudged = true;
isFinalJudged = true;
DisruptHoldEffects();
Miss(exactJudgeTime + judgeIntervals.afterMiss);
RemoveFromCheckingList();
}
}
protected override void RemoveFromCheckingList()
{
if (GameManager.Instance.noteJudgeManager.checkingHoldList.Contains(this))
GameManager.Instance.noteJudgeManager.checkingHoldList.Remove(this);
}
#endregion
#region [] Judgement Logic
public bool CheckJudgeAvailability(InputUnitTap inputUnitTap)
{
if (isFirstJudged) return false;
foreach (var judgeUnit in NoteJudgeSubmodule.judgeUnitList)
{
if (!judgeUnit.CheckJudgeAvailability(inputUnitTap)) return false;
}
return true;
}
public bool CheckJudgeAvailability(InputUnitTouch inputUnitTouch)
{
if (!isFirstJudged) return false;
foreach (var judgeUnit in NoteJudgeSubmodule.judgeUnitList)
{
if (!judgeUnit.CheckJudgeAvailability(inputUnitTouch)) return false;
}
return true;
}
public override void ExecuteStartJudge(float triggerTime)
{
preTimeDifference = triggerTime - exactJudgeTime;
preJudgeType = GetStartJudgeType(preTimeDifference);
isFirstJudged = true;
isHolding = true;
NoteAudioSubmodule.PlayHoldStartAudio();
}
public void ExecuteProcessJudge()
{
isHolding = true;
}
public void ExecuteFinalJudge(float triggerTime)
{
if (startHoldEffects != null)
{
for (int i = 0; i < startHoldEffects.Count; i++)
{
if (startHoldEffects[i].nowEffectState == EffectBase.EffectState.Middle)
startHoldEffects[i].Adjust();
}
}
if (holdingEffects != null)
{
for (int i = 0; i < holdingEffects.Count; i++) holdingEffects[i].Adjust();
}
postTimeDifference = holdEndTime - triggerTime;
if (postTimeDifference <= 0.1f) postJudgeType = NoteJudgeType.Perfect;
else if (postTimeDifference <= 0.125f) postJudgeType = NoteJudgeType.Good;
else postJudgeType = NoteJudgeType.Bad;
NoteJudgeType finalJudge = GetLowerType(preJudgeType, postJudgeType);
float finalTimeDifference = Mathf.Min(preTimeDifference, postTimeDifference);
GameManager.Instance.playingRecorder.resultData.Add(finalTimeDifference);
switch (finalJudge)
{
case NoteJudgeType.Perfect: Perfect(triggerTime); break;
case NoteJudgeType.Good: Good(triggerTime); break;
case NoteJudgeType.Bad: Bad(triggerTime); break;
case NoteJudgeType.Miss: Miss(triggerTime); break;
}
if (finalJudge != NoteJudgeType.Miss) NoteAudioSubmodule.PlayGeneralJudgeAudios();
}
protected override void SetJudgeArea()
{
if (!SettingsManager.instance.gameSettings.debugMode || NoteJudgeSubmodule == null) return;
if (isDuringJudging && !isFirstJudged)
{
foreach (NoteJudgeUnit unit in NoteJudgeSubmodule.judgeUnitList)
{
if (!unit.isShowingJudge) unit.SetShowingJudge(true);
}
}
foreach (NoteJudgeUnit unit in NoteJudgeSubmodule.judgeUnitList)
{
if (unit.isShowingJudge) unit.UpdateJudge();
}
if (!isDuringJudging && CoreServices.TimeProvider.SongTime > holdEndTime - 2 * Time.deltaTime)
{
foreach (NoteJudgeUnit unit in NoteJudgeSubmodule.judgeUnitList)
{
if (unit.isShowingJudge) unit.SetShowingJudge(false);
}
}
}
#endregion
#region [] Special Hold Logic
public override void UpdateNoteInMovableTrack(float songTime)
{
if (!isHolding && !isFinalJudged) base.UpdateNoteInMovableTrack(songTime);
if (noteVisual is INoteVisualHold noteVisualHold) noteVisualHold.UpdateHoldInMovableTrack();
}
public override void UpdateNoteInStaticTrack(float songTime)
{
base.UpdateNoteInStaticTrack(songTime);
if (noteVisual is INoteVisualHold noteVisualHold) noteVisualHold.UpdateHoldInStaticTrack();
}
public override void SetPerfectPosition()
{
if (isOnTrack && track.trackTimeSubmodule is TrackTimeSubmoduleMovable movable)
{
holdingTime = holdEndTime - exactJudgeTime;
(noteVisual as INoteVisualHold)?.UpdateHoldInMovableTrack();
}
}
protected override void SlowOffsetAfterExactJudgeTime()
{
if (isOnTrack && track.trackTimeSubmodule is TrackTimeSubmoduleMovable movable)
{
holdingTime = CoreServices.TimeProvider.SongTime - exactJudgeTime;
(noteVisual as INoteVisualHold)?.UpdateHoldInMovableTrack();
}
}
private void UpdateHoldEffects()
{
if (startHoldEffects != null)
for (int i = 0; i < startHoldEffects.Count; i++) startHoldEffects[i].UpdateEffect(exactJudgeTime);
if (holdingEffects != null)
for (int i = 0; i < holdingEffects.Count; i++) holdingEffects[i].UpdateEffect(exactJudgeTime);
}
private void DisruptHoldEffects()
{
if (startHoldEffects != null)
for (int i = 0; i < startHoldEffects.Count; i++) startHoldEffects[i].Disrupt();
}
#endregion
#region [] Beatmap Method
#endregion
}
}