port PlayerActionEvent IsHittable
rename timing margin values simplify some player action event logic
This commit is contained in:
parent
6585753545
commit
b9c5fd4581
|
@ -233,7 +233,7 @@ namespace HeavenStudio.Games.Scripts_CropStomp
|
|||
|
||||
stompedBeat = cond.songPositionInBeatsAsDouble;
|
||||
|
||||
landBeat = targetBeat + (float)cond.SecsToBeats(Minigame.EndTime()-1, cond.GetBpmAtBeat(targetBeat));
|
||||
landBeat = targetBeat + (float)cond.SecsToBeats(Minigame.NgLateTime()-1, cond.GetBpmAtBeat(targetBeat));
|
||||
|
||||
if (autoTriggered)
|
||||
{
|
||||
|
|
|
@ -201,7 +201,7 @@ namespace HeavenStudio.Games.Scripts_KarateMan
|
|||
switch (forceHand)
|
||||
{
|
||||
case 0:
|
||||
if (cond.songPositionInBeatsAsDouble - lastPunchTime < 0.25f + (Minigame.LateTime() - 1f))
|
||||
if (cond.songPositionInBeatsAsDouble - lastPunchTime < 0.25f + (Minigame.JustLateTime() - 1f))
|
||||
{
|
||||
lastPunchTime = double.MinValue;
|
||||
anim.DoScaledAnimationAsync("Straight", 0.5f);
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace HeavenStudio.Games
|
|||
{
|
||||
public class Minigame : MonoBehaviour
|
||||
{
|
||||
public static double earlyTime = 0.075f, perfectTime = 0.06f, aceEarlyTime = 0.01f, aceLateTime = 0.01f, lateTime = 0.06f, endTime = 0.075f;
|
||||
public static double ngEarlyTime = 0.075f, justEarlyTime = 0.06f, aceEarlyTime = 0.01f, aceLateTime = 0.01f, justLateTime = 0.06f, ngLateTime = 0.075f;
|
||||
public static float rankHiThreshold = 0.8f, rankOkThreshold = 0.6f;
|
||||
[SerializeField] public SoundSequence.SequenceKeyValue[] SoundSequences;
|
||||
|
||||
|
@ -45,7 +45,9 @@ namespace HeavenStudio.Games
|
|||
InputType inputType,
|
||||
PlayerActionEvent.ActionEventCallbackState OnHit,
|
||||
PlayerActionEvent.ActionEventCallback OnMiss,
|
||||
PlayerActionEvent.ActionEventCallback OnBlank)
|
||||
PlayerActionEvent.ActionEventCallback OnBlank,
|
||||
PlayerActionEvent.ActionEventHittableQuery HittableQuery = null
|
||||
)
|
||||
{
|
||||
|
||||
GameObject evtObj = new GameObject("ActionEvent" + (startBeat+timer));
|
||||
|
@ -59,6 +61,7 @@ namespace HeavenStudio.Games
|
|||
evt.OnHit = OnHit;
|
||||
evt.OnMiss = OnMiss;
|
||||
evt.OnBlank = OnBlank;
|
||||
evt.IsHittable = HittableQuery;
|
||||
|
||||
evt.OnDestroy = RemoveScheduledInput;
|
||||
|
||||
|
@ -98,8 +101,6 @@ namespace HeavenStudio.Games
|
|||
return evt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Clean up method used whenever a PlayerActionEvent has finished
|
||||
public void RemoveScheduledInput(PlayerActionEvent evt)
|
||||
{
|
||||
|
@ -151,49 +152,36 @@ namespace HeavenStudio.Games
|
|||
}
|
||||
|
||||
// now should fix the fast bpm problem
|
||||
public static double EarlyTime()
|
||||
public static double NgEarlyTime()
|
||||
{
|
||||
return 1f - earlyTime;
|
||||
return 1f - ngEarlyTime;
|
||||
}
|
||||
|
||||
public static double PerfectTime()
|
||||
public static double JustEarlyTime()
|
||||
{
|
||||
return 1f - perfectTime;
|
||||
return 1f - justEarlyTime;
|
||||
}
|
||||
|
||||
public static double LateTime()
|
||||
public static double JustLateTime()
|
||||
{
|
||||
return 1f + lateTime;
|
||||
return 1f + justLateTime;
|
||||
}
|
||||
|
||||
public static double EndTime()
|
||||
public static double NgLateTime()
|
||||
{
|
||||
return 1f + endTime;
|
||||
return 1f + ngLateTime;
|
||||
}
|
||||
|
||||
public static double AceStartTime()
|
||||
public static double AceEarlyTime()
|
||||
{
|
||||
return 1f - aceEarlyTime;
|
||||
}
|
||||
|
||||
public static double AceEndTime()
|
||||
public static double AceLateTime()
|
||||
{
|
||||
return 1f + aceLateTime;
|
||||
}
|
||||
|
||||
// DEPRECATED: scales timing windows to the BPM in an ""intelligent"" manner
|
||||
// only left for historical reasons
|
||||
static float ScaleTimingMargin(float f)
|
||||
{
|
||||
float bpm = Conductor.instance.songBpm * Conductor.instance.musicSource.pitch;
|
||||
float a = bpm / 120f;
|
||||
float b = (Mathf.Log(a) + 2f) * 0.5f;
|
||||
float r = Mathf.Lerp(a, b, 0.25f);
|
||||
return r * f;
|
||||
}
|
||||
|
||||
public int firstEnable = 0;
|
||||
|
||||
public virtual void OnGameSwitch(double beat)
|
||||
{
|
||||
//Below is a template that can be used for handling previous entities.
|
||||
|
@ -263,7 +251,7 @@ namespace HeavenStudio.Games
|
|||
|
||||
public void ScoreMiss(double weight = 1f)
|
||||
{
|
||||
GameManager.instance.ScoreInputAccuracy(0, true, EndTime(), weight, false);
|
||||
GameManager.instance.ScoreInputAccuracy(0, true, NgLateTime(), weight, false);
|
||||
if (weight > 0)
|
||||
{
|
||||
GoForAPerfect.instance.Miss();
|
||||
|
|
|
@ -18,10 +18,12 @@ namespace HeavenStudio.Games
|
|||
public static bool EnableAutoplayCheat = true;
|
||||
public delegate void ActionEventCallback(PlayerActionEvent caller);
|
||||
public delegate void ActionEventCallbackState(PlayerActionEvent caller, float state);
|
||||
public delegate bool ActionEventHittableQuery();
|
||||
|
||||
public ActionEventCallbackState OnHit; //Function to trigger when an input has been done perfectly
|
||||
public ActionEventCallback OnMiss; //Function to trigger when an input has been missed
|
||||
public ActionEventCallback OnBlank; //Function to trigger when an input has been recorded while this is pending
|
||||
public ActionEventHittableQuery IsHittable; //Checks if an input can be hit. Returning false will skip button checks.
|
||||
|
||||
public ActionEventCallback OnDestroy; //Function to trigger whenever this event gets destroyed. /!\ Shouldn't be used for a minigame! Use OnMiss instead /!\
|
||||
|
||||
|
@ -55,6 +57,11 @@ namespace HeavenStudio.Games
|
|||
this.OnMiss = OnMiss;
|
||||
}
|
||||
|
||||
public void setHittableQuery(ActionEventHittableQuery IsHittable)
|
||||
{
|
||||
this.IsHittable = IsHittable;
|
||||
}
|
||||
|
||||
public void Enable() { enabled = true; }
|
||||
public void Disable() { enabled = false; }
|
||||
public void QueueDeletion() { markForDeletion = true; }
|
||||
|
@ -105,7 +112,7 @@ namespace HeavenStudio.Games
|
|||
}
|
||||
|
||||
//BUGFIX: ActionEvents destroyed too early
|
||||
if (normalizedTime > Minigame.EndTime()) Miss();
|
||||
if (normalizedTime > Minigame.NgLateTime()) Miss();
|
||||
|
||||
if (lockedByEvent)
|
||||
{
|
||||
|
@ -116,11 +123,11 @@ namespace HeavenStudio.Games
|
|||
return;
|
||||
}
|
||||
|
||||
if (!autoplayOnly && IsCorrectInput())
|
||||
if (!autoplayOnly && (IsHittable == null || IsHittable != null && IsHittable()) && IsCorrectInput())
|
||||
{
|
||||
if (IsExpectingInputNow())
|
||||
{
|
||||
double stateProg = ((normalizedTime - Minigame.PerfectTime()) / (Minigame.LateTime() - Minigame.PerfectTime()) - 0.5f) * 2;
|
||||
double stateProg = ((normalizedTime - Minigame.JustEarlyTime()) / (Minigame.JustLateTime() - Minigame.JustEarlyTime()) - 0.5f) * 2;
|
||||
Hit(stateProg, normalizedTime);
|
||||
}
|
||||
else
|
||||
|
@ -186,8 +193,16 @@ namespace HeavenStudio.Games
|
|||
|
||||
public bool IsExpectingInputNow()
|
||||
{
|
||||
if (IsHittable != null)
|
||||
{
|
||||
if (!IsHittable()) return false;
|
||||
}
|
||||
if (!enabled) return false;
|
||||
if (!isEligible) return false;
|
||||
if (markForDeletion) return false;
|
||||
|
||||
double normalizedBeat = GetNormalizedTime();
|
||||
return normalizedBeat > Minigame.EarlyTime() && normalizedBeat < Minigame.EndTime();
|
||||
return normalizedBeat > Minigame.NgEarlyTime() && normalizedBeat < Minigame.NgLateTime();
|
||||
}
|
||||
|
||||
double GetNormalizedTime()
|
||||
|
@ -195,9 +210,9 @@ namespace HeavenStudio.Games
|
|||
var cond = Conductor.instance;
|
||||
double currTime = cond.songPositionAsDouble;
|
||||
double targetTime = cond.GetSongPosFromBeat(startBeat + timer);
|
||||
double min = targetTime - 1f;
|
||||
double max = targetTime + 1f;
|
||||
return 1f + (((currTime - min) / (max - min))-0.5f)*2;
|
||||
|
||||
// HS timing window uses 1 as the middle point instead of 0
|
||||
return 1 + (currTime - targetTime);
|
||||
}
|
||||
|
||||
//For the Autoplay
|
||||
|
@ -210,7 +225,7 @@ namespace HeavenStudio.Games
|
|||
else
|
||||
{
|
||||
double normalizedBeat = GetNormalizedTime();
|
||||
double stateProg = ((normalizedBeat - Minigame.PerfectTime()) / (Minigame.LateTime() - Minigame.PerfectTime()) - 0.5f) * 2;
|
||||
double stateProg = ((normalizedBeat - Minigame.JustEarlyTime()) / (Minigame.JustLateTime() - Minigame.JustEarlyTime()) - 0.5f) * 2;
|
||||
Hit(stateProg, normalizedBeat);
|
||||
}
|
||||
}
|
||||
|
@ -251,27 +266,27 @@ namespace HeavenStudio.Games
|
|||
|
||||
double TimeToAccuracy(double time)
|
||||
{
|
||||
if (time >= Minigame.AceStartTime() && time <= Minigame.AceEndTime())
|
||||
if (time >= Minigame.AceEarlyTime() && time <= Minigame.AceLateTime())
|
||||
{
|
||||
// Ace
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
double state = 0;
|
||||
if (time >= Minigame.PerfectTime() && time <= Minigame.LateTime())
|
||||
if (time >= Minigame.JustEarlyTime() && time <= Minigame.JustLateTime())
|
||||
{
|
||||
// Good Hit
|
||||
if (time > 1.0)
|
||||
{
|
||||
// late half of timing window
|
||||
state = 1.0 - ((time - Minigame.AceEndTime()) / (Minigame.LateTime() - Minigame.AceEndTime()));
|
||||
state = 1.0 - ((time - Minigame.AceLateTime()) / (Minigame.JustLateTime() - Minigame.AceLateTime()));
|
||||
state *= 1.0 - Minigame.rankHiThreshold;
|
||||
state += Minigame.rankHiThreshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
//early half of timing window
|
||||
state = ((time - Minigame.PerfectTime()) / (Minigame.AceStartTime() - Minigame.PerfectTime()));
|
||||
state = ((time - Minigame.JustEarlyTime()) / (Minigame.AceEarlyTime() - Minigame.JustEarlyTime()));
|
||||
state *= 1.0 - Minigame.rankHiThreshold;
|
||||
state += Minigame.rankHiThreshold;
|
||||
}
|
||||
|
@ -281,13 +296,13 @@ namespace HeavenStudio.Games
|
|||
if (time > 1.0)
|
||||
{
|
||||
// late half of timing window
|
||||
state = 1.0 - ((time - Minigame.LateTime()) / (Minigame.EndTime() - Minigame.LateTime()));
|
||||
state = 1.0 - ((time - Minigame.JustLateTime()) / (Minigame.NgLateTime() - Minigame.JustLateTime()));
|
||||
state *= Minigame.rankOkThreshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
//early half of timing window
|
||||
state = ((time - Minigame.PerfectTime()) / (Minigame.AceStartTime() - Minigame.PerfectTime()));
|
||||
state = ((time - Minigame.JustEarlyTime()) / (Minigame.AceEarlyTime() - Minigame.JustEarlyTime()));
|
||||
state *= Minigame.rankOkThreshold;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -343,7 +343,7 @@ namespace HeavenStudio.Games.Scripts_SpaceSoccer
|
|||
var cond = Conductor.instance;
|
||||
ball = null;
|
||||
// queue the miss sound
|
||||
MultiSound.Play(new MultiSound.Sound[] { new MultiSound.Sound("spaceSoccer/missNeutral", targetBeat + (float)cond.SecsToBeats(Minigame.EndTime()-1,
|
||||
MultiSound.Play(new MultiSound.Sound[] { new MultiSound.Sound("spaceSoccer/missNeutral", targetBeat + (float)cond.SecsToBeats(Minigame.NgLateTime()-1,
|
||||
cond.GetBpmAtBeat(targetBeat)), SoundByte.GetPitchFromCents(UnityEngine.Random.Range(-75, 75), false)) });
|
||||
}
|
||||
|
||||
|
|
|
@ -41,13 +41,13 @@ namespace HeavenStudio.Common
|
|||
{
|
||||
if (cond.songPositionInBeatsAsDouble > starStart && state == StarState.In)
|
||||
{
|
||||
double offset = cond.SecsToBeats(Minigame.AceStartTime()-1, cond.GetBpmAtBeat(StarTargetTime));
|
||||
double offset = cond.SecsToBeats(Minigame.AceEarlyTime()-1, cond.GetBpmAtBeat(StarTargetTime));
|
||||
if (cond.songPositionInBeatsAsDouble <= starStart + starLength + offset)
|
||||
starAnim.DoScaledAnimation("StarIn", starStart, starLength + (float)offset);
|
||||
else
|
||||
starAnim.Play("StarIn", -1, 1f);
|
||||
|
||||
offset = cond.SecsToBeats(Minigame.AceEndTime()-1, cond.GetBpmAtBeat(StarTargetTime));
|
||||
offset = cond.SecsToBeats(Minigame.AceLateTime()-1, cond.GetBpmAtBeat(StarTargetTime));
|
||||
if (cond.songPositionInBeatsAsDouble > starStart + starLength + offset)
|
||||
KillStar();
|
||||
}
|
||||
|
@ -94,8 +94,8 @@ namespace HeavenStudio.Common
|
|||
public bool DoStarJust()
|
||||
{
|
||||
if (state == StarState.In &&
|
||||
cond.songPositionInBeatsAsDouble >= StarTargetTime + cond.SecsToBeats(Minigame.AceStartTime()-1, cond.GetBpmAtBeat(StarTargetTime)) &&
|
||||
cond.songPositionInBeatsAsDouble <= StarTargetTime + cond.SecsToBeats(Minigame.AceEndTime()-1, cond.GetBpmAtBeat(StarTargetTime))
|
||||
cond.songPositionInBeatsAsDouble >= StarTargetTime + cond.SecsToBeats(Minigame.AceEarlyTime()-1, cond.GetBpmAtBeat(StarTargetTime)) &&
|
||||
cond.songPositionInBeatsAsDouble <= StarTargetTime + cond.SecsToBeats(Minigame.AceLateTime()-1, cond.GetBpmAtBeat(StarTargetTime))
|
||||
)
|
||||
{
|
||||
state = StarState.Collected;
|
||||
|
|
|
@ -87,12 +87,12 @@ namespace HeavenStudio.Common
|
|||
// SetArrowPos(time);
|
||||
|
||||
// no Clamp() because double
|
||||
time = System.Math.Max(Minigame.EarlyTime(), System.Math.Min(Minigame.EndTime(), time));
|
||||
time = System.Math.Max(Minigame.NgEarlyTime(), System.Math.Min(Minigame.NgLateTime(), time));
|
||||
|
||||
if (time >= Minigame.AceStartTime() && time <= Minigame.AceEndTime())
|
||||
if (time >= Minigame.AceEarlyTime() && time <= Minigame.AceLateTime())
|
||||
{
|
||||
type = Rating.Just;
|
||||
frac = (float)((time - Minigame.AceStartTime()) / (Minigame.AceEndTime() - Minigame.AceStartTime()));
|
||||
frac = (float)((time - Minigame.AceEarlyTime()) / (Minigame.AceLateTime() - Minigame.AceEarlyTime()));
|
||||
y = barJustTransform.localScale.y * frac - (barJustTransform.localScale.y * 0.5f);
|
||||
}
|
||||
else
|
||||
|
@ -100,32 +100,32 @@ namespace HeavenStudio.Common
|
|||
if (time > 1.0)
|
||||
{
|
||||
// goes "down"
|
||||
if (time <= Minigame.LateTime())
|
||||
if (time <= Minigame.JustLateTime())
|
||||
{
|
||||
type = Rating.OK;
|
||||
frac = (float)((time - Minigame.AceEndTime()) / (Minigame.LateTime() - Minigame.AceEndTime()));
|
||||
frac = (float)((time - Minigame.AceLateTime()) / (Minigame.JustLateTime() - Minigame.AceLateTime()));
|
||||
y = ((barOKTransform.localScale.y - barJustTransform.localScale.y) * frac) + barJustTransform.localScale.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = Rating.NG;
|
||||
frac = (float)((time - Minigame.LateTime()) / (Minigame.EndTime() - Minigame.LateTime()));
|
||||
frac = (float)((time - Minigame.JustLateTime()) / (Minigame.NgLateTime() - Minigame.JustLateTime()));
|
||||
y = ((barNGTransform.localScale.y - barOKTransform.localScale.y) * frac) + barOKTransform.localScale.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// goes "up"
|
||||
if (time >= Minigame.PerfectTime())
|
||||
if (time >= Minigame.JustEarlyTime())
|
||||
{
|
||||
type = Rating.OK;
|
||||
frac = (float)((time - Minigame.PerfectTime()) / (Minigame.AceStartTime() - Minigame.PerfectTime()));
|
||||
frac = (float)((time - Minigame.JustEarlyTime()) / (Minigame.AceEarlyTime() - Minigame.JustEarlyTime()));
|
||||
y = ((barOKTransform.localScale.y - barJustTransform.localScale.y) * -frac) - barJustTransform.localScale.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = Rating.NG;
|
||||
frac = (float)((time - Minigame.EarlyTime()) / (Minigame.PerfectTime() - Minigame.EarlyTime()));
|
||||
frac = (float)((time - Minigame.NgEarlyTime()) / (Minigame.JustEarlyTime() - Minigame.NgEarlyTime()));
|
||||
y = ((barNGTransform.localScale.y - barOKTransform.localScale.y) * -frac) - barOKTransform.localScale.y;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue