2022-03-11 06:30:01 +00:00
|
|
|
package funkin.modding.events;
|
|
|
|
|
2023-09-08 21:46:44 +00:00
|
|
|
import funkin.data.song.SongData.SongNoteData;
|
2024-05-02 08:11:27 +00:00
|
|
|
import funkin.data.song.SongData.SongEventData;
|
2022-03-21 04:19:05 +00:00
|
|
|
import flixel.FlxState;
|
|
|
|
import flixel.FlxSubState;
|
2023-06-22 05:41:01 +00:00
|
|
|
import funkin.play.notes.NoteSprite;
|
2023-06-16 21:37:56 +00:00
|
|
|
import funkin.play.cutscene.dialogue.Conversation;
|
2022-03-11 06:30:01 +00:00
|
|
|
import funkin.play.Countdown.CountdownStep;
|
2023-06-22 05:41:01 +00:00
|
|
|
import funkin.play.notes.NoteDirection;
|
2022-03-11 06:30:01 +00:00
|
|
|
import openfl.events.EventType;
|
|
|
|
import openfl.events.KeyboardEvent;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is a base class for all events that are issued to scripted classes.
|
|
|
|
* It can be used to identify the type of event called, store data, and cancel event propagation.
|
|
|
|
*/
|
|
|
|
class ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* If true, the behavior associated with this event can be prevented.
|
|
|
|
* For example, cancelling COUNTDOWN_START should prevent the countdown from starting,
|
|
|
|
* until another script restarts it, or cancelling NOTE_HIT should cause the note to be missed.
|
|
|
|
*/
|
|
|
|
public var cancelable(default, null):Bool;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The type associated with the event.
|
|
|
|
*/
|
|
|
|
public var type(default, null):ScriptEventType;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether the event should continue to be triggered on additional targets.
|
|
|
|
*/
|
|
|
|
public var shouldPropagate(default, null):Bool;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether the event has been canceled by one of the scripts that received it.
|
|
|
|
*/
|
|
|
|
public var eventCanceled(default, null):Bool;
|
|
|
|
|
|
|
|
public function new(type:ScriptEventType, cancelable:Bool = false):Void
|
|
|
|
{
|
|
|
|
this.type = type;
|
|
|
|
this.cancelable = cancelable;
|
|
|
|
this.eventCanceled = false;
|
|
|
|
this.shouldPropagate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call this function on a cancelable event to cancel the associated behavior.
|
|
|
|
* For example, cancelling COUNTDOWN_START will prevent the countdown from starting.
|
|
|
|
*/
|
|
|
|
public function cancelEvent():Void
|
|
|
|
{
|
|
|
|
if (cancelable)
|
|
|
|
{
|
|
|
|
eventCanceled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-02 18:35:28 +00:00
|
|
|
/**
|
|
|
|
* Cancel this event.
|
|
|
|
* This is an alias for cancelEvent() but I make this typo all the time.
|
|
|
|
*/
|
2023-01-23 00:55:30 +00:00
|
|
|
public function cancel():Void
|
|
|
|
{
|
|
|
|
cancelEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call this function to stop any other Scripteds from receiving the event.
|
|
|
|
*/
|
|
|
|
public function stopPropagation():Void
|
|
|
|
{
|
|
|
|
shouldPropagate = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function toString():String
|
|
|
|
{
|
|
|
|
return 'ScriptEvent(type=$type, cancelable=$cancelable)';
|
|
|
|
}
|
2022-03-11 06:30:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SPECIFIC EVENTS
|
|
|
|
*/
|
|
|
|
/**
|
|
|
|
* An event that is fired associated with a specific note.
|
|
|
|
*/
|
|
|
|
class NoteScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* The note associated with this event.
|
|
|
|
* You cannot replace it, but you can edit it.
|
|
|
|
*/
|
2023-06-22 05:41:01 +00:00
|
|
|
public var note(default, null):NoteSprite;
|
2023-01-23 00:55:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The combo count as it is with this event.
|
|
|
|
* Will be (combo) on miss events and (combo + 1) on hit events (the stored combo count won't update if the event is cancelled).
|
|
|
|
*/
|
|
|
|
public var comboCount(default, null):Int;
|
|
|
|
|
2023-06-02 18:35:28 +00:00
|
|
|
/**
|
|
|
|
* Whether to play the record scratch sound (if this eventn type is `NOTE_MISS`).
|
|
|
|
*/
|
|
|
|
public var playSound(default, default):Bool;
|
|
|
|
|
2024-02-15 22:25:28 +00:00
|
|
|
/**
|
2024-03-01 13:13:06 +00:00
|
|
|
* The health gained or lost from this note.
|
2024-02-15 22:25:28 +00:00
|
|
|
* This affects both hits and misses. Remember that max health is 2.00.
|
|
|
|
*/
|
2024-03-01 13:13:06 +00:00
|
|
|
public var healthChange:Float;
|
2024-02-15 22:25:28 +00:00
|
|
|
|
2024-03-01 13:13:06 +00:00
|
|
|
public function new(type:ScriptEventType, note:NoteSprite, healthChange:Float, comboCount:Int = 0, cancelable:Bool = false):Void
|
2023-01-23 00:55:30 +00:00
|
|
|
{
|
|
|
|
super(type, cancelable);
|
|
|
|
this.note = note;
|
|
|
|
this.comboCount = comboCount;
|
2023-06-02 18:35:28 +00:00
|
|
|
this.playSound = true;
|
2024-03-01 13:13:06 +00:00
|
|
|
this.healthChange = healthChange;
|
2023-01-23 00:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
return 'NoteScriptEvent(type=' + type + ', cancelable=' + cancelable + ', note=' + note + ', comboCount=' + comboCount + ')';
|
|
|
|
}
|
2022-03-11 06:30:01 +00:00
|
|
|
}
|
|
|
|
|
2024-03-01 13:13:06 +00:00
|
|
|
class HitNoteScriptEvent extends NoteScriptEvent
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* The judgement the player received for hitting the note.
|
|
|
|
*/
|
|
|
|
public var judgement:String;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The score the player received for hitting the note.
|
|
|
|
*/
|
|
|
|
public var score:Int;
|
|
|
|
|
2024-05-08 12:26:17 +00:00
|
|
|
/**
|
2024-05-15 12:46:08 +00:00
|
|
|
* If the hit causes a combo break.
|
2024-05-08 12:26:17 +00:00
|
|
|
*/
|
|
|
|
public var isComboBreak:Bool = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The time difference when the player hit the note
|
|
|
|
*/
|
|
|
|
public var hitDiff:Float = 0;
|
|
|
|
|
2024-05-15 12:46:08 +00:00
|
|
|
/**
|
|
|
|
* If the hit causes a notesplash
|
|
|
|
*/
|
|
|
|
public var doesNotesplash:Bool = false;
|
|
|
|
|
|
|
|
public function new(note:NoteSprite, healthChange:Float, score:Int, judgement:String, isComboBreak:Bool, comboCount:Int = 0, hitDiff:Float = 0,
|
|
|
|
doesNotesplash:Bool = false):Void
|
2024-03-01 13:13:06 +00:00
|
|
|
{
|
|
|
|
super(NOTE_HIT, note, healthChange, comboCount, true);
|
|
|
|
this.score = score;
|
|
|
|
this.judgement = judgement;
|
2024-05-08 12:26:17 +00:00
|
|
|
this.isComboBreak = isComboBreak;
|
2024-05-15 12:46:08 +00:00
|
|
|
this.doesNotesplash = doesNotesplash;
|
2024-05-08 12:26:17 +00:00
|
|
|
this.hitDiff = hitDiff;
|
2024-03-01 13:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
2024-05-08 12:26:17 +00:00
|
|
|
return 'HitNoteScriptEvent(note=' + note + ', comboCount=' + comboCount + ', judgement=' + judgement + ', score=' + score + ', isComboBreak='
|
2024-05-15 12:46:08 +00:00
|
|
|
+ isComboBreak + ', hitDiff=' + hitDiff + ', doesNotesplash=' + doesNotesplash + ')';
|
2024-03-01 13:13:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-21 04:19:05 +00:00
|
|
|
/**
|
|
|
|
* An event that is fired when you press a key with no note present.
|
|
|
|
*/
|
|
|
|
class GhostMissNoteScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* The direction that was mistakenly pressed.
|
|
|
|
*/
|
2023-06-22 05:41:01 +00:00
|
|
|
public var dir(default, null):NoteDirection;
|
2023-01-23 00:55:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether there was a note within judgement range when this ghost note was pressed.
|
|
|
|
*/
|
|
|
|
public var hasPossibleNotes(default, null):Bool;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* How much health should be lost when this ghost note is pressed.
|
|
|
|
* Remember that max health is 2.00.
|
|
|
|
*/
|
|
|
|
public var healthChange(default, default):Float;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* How much score should be lost when this ghost note is pressed.
|
|
|
|
*/
|
|
|
|
public var scoreChange(default, default):Int;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether to play the record scratch sound.
|
|
|
|
*/
|
|
|
|
public var playSound(default, default):Bool;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether to play the miss animation on the player.
|
|
|
|
*/
|
|
|
|
public var playAnim(default, default):Bool;
|
|
|
|
|
2023-06-22 05:41:01 +00:00
|
|
|
public function new(dir:NoteDirection, hasPossibleNotes:Bool, healthChange:Float, scoreChange:Int):Void
|
2023-01-23 00:55:30 +00:00
|
|
|
{
|
2023-10-26 09:46:22 +00:00
|
|
|
super(NOTE_GHOST_MISS, true);
|
2023-01-23 00:55:30 +00:00
|
|
|
this.dir = dir;
|
|
|
|
this.hasPossibleNotes = hasPossibleNotes;
|
|
|
|
this.healthChange = healthChange;
|
|
|
|
this.scoreChange = scoreChange;
|
|
|
|
this.playSound = true;
|
|
|
|
this.playAnim = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
return 'GhostMissNoteScriptEvent(dir=' + dir + ', hasPossibleNotes=' + hasPossibleNotes + ')';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An event that is fired when the song reaches an event.
|
|
|
|
*/
|
|
|
|
class SongEventScriptEvent extends ScriptEvent
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* The note associated with this event.
|
|
|
|
* You cannot replace it, but you can edit it.
|
|
|
|
*/
|
2024-02-18 08:02:36 +00:00
|
|
|
public var eventData(default, null):funkin.data.song.SongData.SongEventData;
|
2023-01-23 00:55:30 +00:00
|
|
|
|
2024-02-18 08:02:36 +00:00
|
|
|
public function new(eventData:funkin.data.song.SongData.SongEventData):Void
|
2023-01-23 00:55:30 +00:00
|
|
|
{
|
2023-10-26 09:46:22 +00:00
|
|
|
super(SONG_EVENT, true);
|
2024-02-18 08:02:36 +00:00
|
|
|
this.eventData = eventData;
|
2023-01-23 00:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
2024-02-18 08:02:36 +00:00
|
|
|
return 'SongEventScriptEvent(event=' + eventData + ')';
|
2023-01-23 00:55:30 +00:00
|
|
|
}
|
2022-03-21 04:19:05 +00:00
|
|
|
}
|
|
|
|
|
2022-03-11 06:30:01 +00:00
|
|
|
/**
|
|
|
|
* An event that is fired during the update loop.
|
|
|
|
*/
|
|
|
|
class UpdateScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* The note associated with this event.
|
|
|
|
* You cannot replace it, but you can edit it.
|
|
|
|
*/
|
|
|
|
public var elapsed(default, null):Float;
|
|
|
|
|
|
|
|
public function new(elapsed:Float):Void
|
|
|
|
{
|
2023-10-26 09:46:22 +00:00
|
|
|
super(UPDATE, false);
|
2023-01-23 00:55:30 +00:00
|
|
|
this.elapsed = elapsed;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
return 'UpdateScriptEvent(elapsed=$elapsed)';
|
|
|
|
}
|
2022-03-11 06:30:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An event that is fired regularly during the song.
|
|
|
|
* May be on beat or on step.
|
|
|
|
*/
|
|
|
|
class SongTimeScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* The current beat of the song.
|
|
|
|
*/
|
|
|
|
public var beat(default, null):Int;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The current step of the song.
|
|
|
|
*/
|
|
|
|
public var step(default, null):Int;
|
|
|
|
|
|
|
|
public function new(type:ScriptEventType, beat:Int, step:Int):Void
|
|
|
|
{
|
|
|
|
super(type, true);
|
|
|
|
this.beat = beat;
|
|
|
|
this.step = step;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
return 'SongTimeScriptEvent(type=' + type + ', beat=' + beat + ', step=' + step + ')';
|
|
|
|
}
|
2022-03-11 06:30:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An event that is fired regularly during the song.
|
|
|
|
* May be on beat or on step.
|
|
|
|
*/
|
|
|
|
class CountdownScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* The current step of the countdown.
|
|
|
|
*/
|
|
|
|
public var step(default, null):CountdownStep;
|
|
|
|
|
2023-06-02 18:35:28 +00:00
|
|
|
public function new(type:ScriptEventType, step:CountdownStep, cancelable:Bool = true):Void
|
2023-01-23 00:55:30 +00:00
|
|
|
{
|
|
|
|
super(type, cancelable);
|
|
|
|
this.step = step;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
return 'CountdownScriptEvent(type=' + type + ', step=' + step + ')';
|
|
|
|
}
|
2022-03-11 06:30:01 +00:00
|
|
|
}
|
|
|
|
|
2023-06-16 21:37:56 +00:00
|
|
|
/**
|
|
|
|
* An event that is fired during a dialogue.
|
|
|
|
*/
|
|
|
|
class DialogueScriptEvent extends ScriptEvent
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* The dialogue being referenced by the event.
|
|
|
|
*/
|
|
|
|
public var conversation(default, null):Conversation;
|
|
|
|
|
|
|
|
public function new(type:ScriptEventType, conversation:Conversation, cancelable:Bool = true):Void
|
|
|
|
{
|
|
|
|
super(type, cancelable);
|
|
|
|
this.conversation = conversation;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
return 'DialogueScriptEvent(type=$type, conversation=$conversation)';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-11 06:30:01 +00:00
|
|
|
/**
|
|
|
|
* An event that is fired when the player presses a key.
|
|
|
|
*/
|
|
|
|
class KeyboardInputScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* The associated keyboard event.
|
|
|
|
*/
|
|
|
|
public var event(default, null):KeyboardEvent;
|
|
|
|
|
|
|
|
public function new(type:ScriptEventType, event:KeyboardEvent):Void
|
|
|
|
{
|
|
|
|
super(type, false);
|
|
|
|
this.event = event;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
return 'KeyboardInputScriptEvent(type=' + type + ', event=' + event + ')';
|
|
|
|
}
|
2022-03-11 06:30:01 +00:00
|
|
|
}
|
2022-03-13 18:36:03 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* An event that is fired once the song's chart has been parsed.
|
|
|
|
*/
|
|
|
|
class SongLoadScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* The note associated with this event.
|
|
|
|
* You cannot replace it, but you can edit it.
|
|
|
|
*/
|
2023-06-22 05:41:01 +00:00
|
|
|
public var notes(default, set):Array<SongNoteData>;
|
2023-01-23 00:55:30 +00:00
|
|
|
|
2024-05-02 08:11:27 +00:00
|
|
|
public var events(default, set):Array<SongEventData>;
|
|
|
|
|
2023-01-23 00:55:30 +00:00
|
|
|
public var id(default, null):String;
|
|
|
|
|
|
|
|
public var difficulty(default, null):String;
|
|
|
|
|
2023-06-22 05:41:01 +00:00
|
|
|
function set_notes(notes:Array<SongNoteData>):Array<SongNoteData>
|
2023-01-23 00:55:30 +00:00
|
|
|
{
|
|
|
|
this.notes = notes;
|
|
|
|
return this.notes;
|
|
|
|
}
|
|
|
|
|
2024-05-02 08:11:27 +00:00
|
|
|
function set_events(events:Array<SongEventData>):Array<SongEventData>
|
|
|
|
{
|
|
|
|
this.events = events;
|
|
|
|
return this.events;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function new(id:String, difficulty:String, notes:Array<SongNoteData>, events:Array<SongEventData>):Void
|
2023-01-23 00:55:30 +00:00
|
|
|
{
|
2023-10-26 09:46:22 +00:00
|
|
|
super(SONG_LOADED, false);
|
2023-01-23 00:55:30 +00:00
|
|
|
this.id = id;
|
|
|
|
this.difficulty = difficulty;
|
|
|
|
this.notes = notes;
|
2024-05-02 08:11:27 +00:00
|
|
|
this.events = events;
|
2023-01-23 00:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
var noteStr = notes == null ? 'null' : 'Array(' + notes.length + ')';
|
|
|
|
return 'SongLoadScriptEvent(notes=$noteStr, id=$id, difficulty=$difficulty)';
|
|
|
|
}
|
2022-03-13 18:36:03 +00:00
|
|
|
}
|
2022-03-15 00:48:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* An event that is fired when moving out of or into an FlxState.
|
|
|
|
*/
|
|
|
|
class StateChangeScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* The state the game is moving into.
|
|
|
|
*/
|
|
|
|
public var targetState(default, null):FlxState;
|
|
|
|
|
|
|
|
public function new(type:ScriptEventType, targetState:FlxState, cancelable:Bool = false):Void
|
|
|
|
{
|
|
|
|
super(type, cancelable);
|
|
|
|
this.targetState = targetState;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
return 'StateChangeScriptEvent(type=' + type + ', targetState=' + targetState + ')';
|
|
|
|
}
|
2022-03-21 04:19:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An event that is fired when moving out of or into an FlxSubState.
|
|
|
|
*/
|
|
|
|
class SubStateScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* The state the game is moving into.
|
|
|
|
*/
|
|
|
|
public var targetState(default, null):FlxSubState;
|
|
|
|
|
|
|
|
public function new(type:ScriptEventType, targetState:FlxSubState, cancelable:Bool = false):Void
|
|
|
|
{
|
|
|
|
super(type, cancelable);
|
|
|
|
this.targetState = targetState;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override function toString():String
|
|
|
|
{
|
|
|
|
return 'SubStateScriptEvent(type=' + type + ', targetState=' + targetState + ')';
|
|
|
|
}
|
2022-03-15 00:48:45 +00:00
|
|
|
}
|
2022-03-30 01:56:04 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* An event which is called when the player attempts to pause the game.
|
|
|
|
*/
|
|
|
|
class PauseScriptEvent extends ScriptEvent
|
|
|
|
{
|
2023-01-23 00:55:30 +00:00
|
|
|
/**
|
|
|
|
* Whether to use the Gitaroo Man pause.
|
|
|
|
*/
|
|
|
|
public var gitaroo(default, default):Bool;
|
|
|
|
|
|
|
|
public function new(gitaroo:Bool):Void
|
|
|
|
{
|
2023-10-26 09:46:22 +00:00
|
|
|
super(PAUSE, true);
|
2023-01-23 00:55:30 +00:00
|
|
|
this.gitaroo = gitaroo;
|
|
|
|
}
|
2022-03-30 01:56:04 +00:00
|
|
|
}
|