Files
ichni_Official/Assets/Scripts/Game/GameElements/Notes/NoteObjects/Hold.cs

385 lines
13 KiB
C#
Raw Normal View History

2025-06-03 02:42:28 -04:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Dreamteck.Splines;
using Ichni.RhythmGame.Beatmap;
2025-07-21 05:42:20 -04:00
using UniRx;
2025-06-03 02:42:28 -04:00
using Unity.VisualScripting;
using UnityEngine;
2025-08-11 14:04:06 -04:00
using UnityEngine.Serialization;
2025-06-03 02:42:28 -04:00
namespace Ichni.RhythmGame
{
public partial class Hold : NoteBase
{
public float holdEndTime;
public float holdingTime;
public bool isHolding;
2025-07-21 05:42:20 -04:00
public float holdingBufferTime;
public float bufferTimer;
2025-08-11 14:04:06 -04:00
public float preTimeDifference;
2025-07-21 05:42:20 -04:00
public NoteJudgeType preJudgeType;
2025-08-11 14:04:06 -04:00
public float postTimeDifference;
2025-07-21 05:42:20 -04:00
public NoteJudgeType postJudgeType;
2025-06-03 02:42:28 -04:00
public static Hold GenerateElement(string elementName, Guid id, List<string> tags, bool isFirstGenerated,
GameElement parentElement, float exactJudgeTime, float holdEndTime)
{
Hold hold = Instantiate(GameManager.instance.basePrefabs.holdNote, parentElement.transform).GetComponent<Hold>();
hold.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
hold.exactJudgeTime = exactJudgeTime;
hold.holdEndTime = holdEndTime;
hold.holdingTime = 0;
2025-08-27 21:45:18 -04:00
hold.holdingBufferTime = 0.04f;
2025-07-21 05:42:20 -04:00
hold.judgeIntervals = new NoteJudgeIntervals(
new TimeInterval(-0.15f, -0.15f), new TimeInterval(-0.15f, -0.125f),
new TimeInterval(-0.125f, -0.1f), new TimeInterval(-0.1f, 0.1f),
new TimeInterval(0.1f, 0.125f), new TimeInterval(0.125f, 0.15f), 0.15f);
hold.preJudgeType = NoteJudgeType.NotJudged;
hold.postJudgeType = NoteJudgeType.NotJudged;
2025-06-03 02:42:28 -04:00
if (parentElement.TryGetComponent(out Track track))
{
if (track.trackTimeSubmodule != null)
{
hold.track = track;
hold.trackPositioner = hold.AddComponent<SplinePositioner>();
hold.trackPositioner.spline = track.trackPathSubmodule.path;
hold.trackPositioner.updateMethod = SplineUser.UpdateMethod.LateUpdate;
hold.isOnTrack = true;
hold.UpdateNoteInTrack();
}
else
{
throw new Exception("如果Note要生成在Track上Track必须有TrackTimeSubmodule组件。");
}
}
else
{
hold.track = null;
hold.isOnTrack = false;
}
return hold;
}
2025-07-21 05:42:20 -04:00
public override void ExecuteStartJudge()
{
float triggerTime = GameManager.instance.songTime;
2025-08-11 14:04:06 -04:00
preTimeDifference = triggerTime - exactJudgeTime;
2025-07-21 05:42:20 -04:00
2025-08-11 14:04:06 -04:00
NoteJudgeType startJudgeType = GetStartJudgeType(preTimeDifference);
2025-07-21 05:42:20 -04:00
preJudgeType = startJudgeType;
isFirstJudged = true;
isHolding = true;
2025-08-11 14:04:06 -04:00
noteAudioSubmodule.PlayHoldStartAudio();
2025-08-22 14:54:40 -04:00
//Debug.Log($"Hold Note Start Judge: {startJudgeType} at {triggerTime}");
2025-07-21 05:42:20 -04:00
}
public void ExecuteProcessJudge()
{
isHolding = true;
}
public void ExecuteFinalJudge()
{
2025-08-22 14:54:40 -04:00
foreach (EffectBase effect in noteVisual.effectSubmodule.effectCollection["StartHold"])
{
if (effect.nowEffectState == EffectBase.EffectState.Middle)
{
effect.Adjust();
}
}
foreach (EffectBase effect in noteVisual.effectSubmodule.effectCollection["Holding"])
{
effect.Adjust();
}
2025-07-21 05:42:20 -04:00
float triggerTime = GameManager.instance.songTime;
2025-08-11 14:04:06 -04:00
postTimeDifference = holdEndTime - triggerTime;
if (postTimeDifference <= 0.1f)
2025-07-21 05:42:20 -04:00
{
postJudgeType = NoteJudgeType.Perfect;
}
2025-08-11 14:04:06 -04:00
else if (postTimeDifference <= 0.125f)
2025-07-21 05:42:20 -04:00
{
postJudgeType = NoteJudgeType.Good;
}
else
{
postJudgeType = NoteJudgeType.Bad;
}
2025-08-22 14:54:40 -04:00
//Debug.Log($"Hold Note Final Judge: {postJudgeType} at {triggerTime} of difference {postTimeDifference}");
2025-07-21 05:42:20 -04:00
2025-08-11 14:04:06 -04:00
NoteJudgeType finalJudge = GetLowerType(preJudgeType, postJudgeType);
float finalTimeDifference = Mathf.Min(preTimeDifference, postTimeDifference);
GameManager.instance.playingRecorder.resultData.Add(finalTimeDifference);
2025-07-21 05:42:20 -04:00
if (finalJudge == NoteJudgeType.Perfect)
{
Perfect(triggerTime);
}
else if (finalJudge == NoteJudgeType.Good)
{
Good(triggerTime);
}
else if (finalJudge == NoteJudgeType.Bad)
{
Bad(triggerTime);
}
else if (finalJudge == NoteJudgeType.Miss)
{
Miss(triggerTime);
}
2025-08-11 14:04:06 -04:00
2025-07-21 05:42:20 -04:00
if (finalJudge != NoteJudgeType.Miss)
{
noteAudioSubmodule.PlayGeneralJudgeAudios();
}
}
2025-06-03 02:42:28 -04:00
}
public partial class Hold
{
public override void UpdateNoteInMovableTrack()
{
if (!isHolding && !isFinalJudged)
{
base.UpdateNoteInMovableTrack();
}
2025-07-21 05:42:20 -04:00
if (noteVisual is INoteVisualHold noteVisualHold)
2025-06-03 02:42:28 -04:00
{
noteVisualHold.UpdateHoldInMovableTrack();
}
}
public override void UpdateNoteInStaticTrack()
{
base.UpdateNoteInStaticTrack();
2025-07-21 05:42:20 -04:00
if (noteVisual is INoteVisualHold noteVisualHold)
2025-06-03 02:42:28 -04:00
{
noteVisualHold.UpdateHoldInStaticTrack();
}
}
2025-07-21 05:42:20 -04:00
protected override void RemoveFromCheckingList()
{
2025-08-11 14:04:06 -04:00
if (GameManager.instance.noteJudgeManager.checkingHoldList.Contains(this))
{
GameManager.instance.noteJudgeManager.checkingHoldList.Remove(this);
}
2025-07-21 05:42:20 -04:00
}
2025-08-22 14:54:40 -04:00
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 = GameManager.instance.songTime - exactJudgeTime;
(noteVisual as INoteVisualHold)?.UpdateHoldInMovableTrack();
}
}
2025-06-03 02:42:28 -04:00
}
public partial class Hold
{
public override void SetDefaultSubmodules()
{
base.SetDefaultSubmodules();
noteAudioSubmodule = new NoteAudioSubmodule(this, "DefaultTap");
}
public override void SaveBM()
{
matchedBM = new Hold_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM, exactJudgeTime, holdEndTime);
}
}
2025-07-21 05:42:20 -04:00
public partial class Hold
{
public bool CheckJudgeAvailability(InputUnitTap inputUnitTap)
{
return !isFirstJudged && noteJudgeSubmodule.judgeUnitList.All(judgeUnit => judgeUnit.CheckJudgeAvailability(inputUnitTap));
}
public bool CheckJudgeAvailability(InputUnitTouch inputUnitTouch)
{
return isFirstJudged && noteJudgeSubmodule.judgeUnitList.All(judgeUnit => judgeUnit.CheckJudgeAvailability(inputUnitTouch));
}
2025-07-26 04:20:25 -04:00
protected override void SetJudgeArea()
{
2025-08-11 14:04:06 -04:00
if (!SettingsManager.instance.gameSettings.debugMode)
{
return;
}
2025-07-26 04:20:25 -04:00
if (noteJudgeSubmodule != null)
{
2025-08-11 14:04:06 -04:00
if (isDuringJudging && !isFirstJudged)
2025-07-26 04:20:25 -04:00
{
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => !unit.isShowingJudge))
{
unit.SetShowingJudge(true);
}
}
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
{
unit.UpdateJudge();
}
2025-08-11 14:04:06 -04:00
if (!isDuringJudging && GameManager.instance.songTime > holdEndTime - 2 * Time.deltaTime)
2025-07-26 04:20:25 -04:00
{
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
{
unit.SetShowingJudge(false);
}
}
}
}
2025-07-21 05:42:20 -04:00
}
2025-06-03 02:42:28 -04:00
public partial class Hold
{
protected override void Update()
{
2025-07-21 05:42:20 -04:00
float songTime = GameManager.instance.songTime;
if (!isFirstJudged && !isDuringJudging &&
songTime >= exactJudgeTime + judgeIntervals.beforeMiss.intervalStart &&
2025-08-11 14:04:06 -04:00
!GameManager.instance.noteJudgeManager.checkingHoldList.Contains(this))
2025-07-08 14:28:40 -04:00
{
2025-07-21 05:42:20 -04:00
isDuringJudging = true;
2025-08-11 14:04:06 -04:00
GameManager.instance.noteJudgeManager.checkingHoldList.Add(this);
2025-07-08 14:28:40 -04:00
}
2025-07-21 05:42:20 -04:00
if (!GameManager.instance.audioManager.isUpdating || isFinalJudged)
2025-06-03 02:42:28 -04:00
{
2025-07-21 05:42:20 -04:00
return;
2025-06-03 02:42:28 -04:00
}
if (isHolding)
{
holdingTime = songTime - exactJudgeTime;
2025-07-21 05:42:20 -04:00
bufferTimer = holdingBufferTime;
}
else if(isFirstJudged)
{
bufferTimer -= Time.deltaTime;
2025-06-03 02:42:28 -04:00
}
2025-07-21 05:42:20 -04:00
if (isOnTrack)
2025-06-03 02:42:28 -04:00
{
2025-07-21 05:42:20 -04:00
UpdateNoteInTrack();
2025-06-03 02:42:28 -04:00
}
2025-07-21 05:42:20 -04:00
if (isDuringJudging)
2025-06-03 02:42:28 -04:00
{
2025-08-11 14:04:06 -04:00
noteScreenPosition = GetScreenPosition();
2025-06-03 02:42:28 -04:00
}
2025-07-21 05:42:20 -04:00
2025-07-26 04:20:25 -04:00
SetJudgeArea();
2025-08-22 14:54:40 -04:00
if (!isFirstJudged && exactJudgeTime < GameManager.instance.songTime)
{
SlowOffsetAfterExactJudgeTime();
}
2025-07-21 05:42:20 -04:00
foreach (EffectBase e in noteVisual.effectSubmodule.effectCollection["Generate"])
2025-06-03 02:42:28 -04:00
{
2025-07-21 05:42:20 -04:00
e.UpdateEffect(exactJudgeTime);
2025-06-03 02:42:28 -04:00
}
2025-07-21 05:42:20 -04:00
foreach (EffectBase e in noteVisual.effectSubmodule.effectCollection["StartHold"])
{
e.UpdateEffect(exactJudgeTime);
}
2025-06-03 02:42:28 -04:00
2025-07-21 05:42:20 -04:00
foreach (EffectBase e in noteVisual.effectSubmodule.effectCollection["Holding"])
2025-06-03 02:42:28 -04:00
{
2025-07-21 05:42:20 -04:00
e.UpdateEffect(exactJudgeTime);
}
2025-08-11 14:04:06 -04:00
if (isFirstJudged && songTime > holdEndTime)
2025-07-21 05:42:20 -04:00
{
isHolding = false;
isFinalJudged = true;
ExecuteFinalJudge();
RemoveFromCheckingList();
}
2025-06-03 02:42:28 -04:00
2025-07-21 05:42:20 -04:00
if (isFirstJudged && bufferTimer < 0f)
{
isHolding = false;
isFinalJudged = true;
2025-08-22 14:54:40 -04:00
foreach (EffectBase e in noteVisual.effectSubmodule.effectCollection["StartHold"])
{
e.Disrupt();
}
2025-07-21 05:42:20 -04:00
ExecuteFinalJudge();
RemoveFromCheckingList();
}
if (!isFirstJudged && GameManager.instance.songTime > exactJudgeTime + judgeIntervals.afterMiss)
{
Miss(exactJudgeTime + judgeIntervals.afterMiss);
isFirstJudged = true;
isFinalJudged = true;
RemoveFromCheckingList();
2025-06-03 02:42:28 -04:00
}
}
private void LateUpdate()
{
2025-07-21 05:42:20 -04:00
isHolding = false;
2025-06-03 02:42:28 -04:00
}
}
namespace Beatmap
{
public class Hold_BM : NoteBase_BM
{
public float holdEndTime;
public Hold_BM()
{
}
public Hold_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement, float exactJudgeTime, float holdEndTime)
: base(elementName, elementGuid, tags, attachedElement, exactJudgeTime)
{
this.holdEndTime = holdEndTime;
}
public override void ExecuteBM()
{
matchedElement = Hold.GenerateElement(elementName, elementGuid, tags, false,
GetElement(attachedElementGuid), exactJudgeTime, holdEndTime);
}
}
}
}