continuinggg (very cool improvements)
asynced video loadings, classes rewrites, bugfixes and a lot more
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import funkin.system.FunkinSprite;
|
||||
|
||||
var tankman:FunkinSprite;
|
||||
var tankTalk1, distorto:FlxSound;
|
||||
var tankTalk, distorto:FlxSound;
|
||||
var timers:Array<FlxTimer> = [];
|
||||
var destroyDistorto:Bool = true;
|
||||
|
||||
function create() {
|
||||
FlxTween.tween(FlxG.camera, {zoom: 1}, 0.7, {ease: FlxEase.quadInOut});
|
||||
@@ -28,29 +30,39 @@ function create() {
|
||||
tankman.playAnim('tank');
|
||||
tankTalk.play();
|
||||
|
||||
new FlxTimer().start(4.1, function(ugly:FlxTimer)
|
||||
timer(4.1, function()
|
||||
{
|
||||
FlxTween.tween(FlxG.camera, {zoom: game.defaultCamZoom * 1.4}, 0.4, {ease: FlxEase.quadOut});
|
||||
FlxTween.tween(FlxG.camera, {zoom: game.defaultCamZoom * 1.3}, 0.7, {ease: FlxEase.quadInOut, startDelay: 0.45});
|
||||
game.gf.playAnim('sad', false, "DANCE");
|
||||
});
|
||||
|
||||
new FlxTimer().start(11, function(tmr:FlxTimer)
|
||||
{
|
||||
game.remove(tankman);
|
||||
tankman.destroy();
|
||||
|
||||
game.camHUD.visible = true;
|
||||
game.dad.visible = true;
|
||||
timer(11, function() {
|
||||
destroyDistorto = false;
|
||||
distorto.fadeOut((Conductor.crochet / 1000) * 5, 0);
|
||||
FlxTween.tween(FlxG.camera, {zoom: game.defaultCamZoom}, 0.7, {ease: FlxEase.quadInOut, startDelay: 0});
|
||||
|
||||
close();
|
||||
});
|
||||
}
|
||||
|
||||
function timer(duration:Float, callBack:Void->Void) {
|
||||
timers.push(new FlxTimer().start(duration, function(timer) {
|
||||
timers.remove(timer);
|
||||
callBack();
|
||||
}));
|
||||
}
|
||||
|
||||
function focusOn(char) {
|
||||
var camPos = char.getCameraPosition();
|
||||
game.camFollow.setPosition(camPos.x, camPos.y);
|
||||
camPos.put();
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
game.remove(tankman);
|
||||
game.camHUD.visible = true;
|
||||
game.dad.visible = true;
|
||||
for(timer in timers) timer.cancel();
|
||||
for(thing in [tankman, tankTalk]) thing.destroy();
|
||||
if(destroyDistorto) distorto.destroy();
|
||||
FlxTween.tween(FlxG.camera, {zoom: game.defaultCamZoom}, 0.7, {ease: FlxEase.quadInOut, startDelay: 0});
|
||||
}
|
||||
@@ -27,11 +27,6 @@ function create() {
|
||||
|
||||
stressCutscene.play();
|
||||
stressCutscene.onComplete = function() {
|
||||
for(spr in [gf, tankman, pico]) {
|
||||
spr.destroy();
|
||||
game.remove(spr);
|
||||
}
|
||||
game.camHUD.visible = game.dad.visible = game.gf.visible = true;
|
||||
close();
|
||||
};
|
||||
|
||||
@@ -59,8 +54,6 @@ function create() {
|
||||
}
|
||||
|
||||
function update(elapsed) {
|
||||
if (FlxG.keys.justPressed.F5)
|
||||
FlxG.resetState();
|
||||
switch(step) {
|
||||
case 0:
|
||||
lipSync(tankman, 0, 16750);
|
||||
@@ -133,4 +126,14 @@ function focusOn(char, snap:Bool = false) {
|
||||
game.camFollow.setPosition(camPos.x, camPos.y);
|
||||
if(snap) FlxG.camera.snapToTarget();
|
||||
camPos.put();
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
game.boyfriend.animation.finishCallback = null;
|
||||
game.camHUD.visible = game.boyfriend.visible = game.dad.visible = game.gf.visible = true;
|
||||
for(thing in [bf, gf, tankman, pico, stressCutscene]) {
|
||||
if(thing == null) continue;
|
||||
if(thing != stressCutscene) game.remove(thing);
|
||||
thing.destroy();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ import funkin.system.FunkinSprite;
|
||||
|
||||
var tankman:FunkinSprite;
|
||||
var tankTalk1, tankTalk2, bfBeep, distorto:FlxSound;
|
||||
var timers:Array<FlxTimer> = [];
|
||||
var destroyDistorto:Bool = true;
|
||||
|
||||
function create() {
|
||||
FlxTween.tween(FlxG.camera, {zoom: 1}, 0.7, {ease: FlxEase.quadInOut});
|
||||
@@ -33,35 +35,46 @@ function create() {
|
||||
tankman.playAnim('1');
|
||||
tankTalk1.play();
|
||||
|
||||
new FlxTimer().start(3, function(tmr:FlxTimer) {
|
||||
timer(3, function() {
|
||||
focusOn(game.boyfriend);
|
||||
|
||||
new FlxTimer().start(1.5, function(t) {
|
||||
timer(1.5, function() {
|
||||
game.boyfriend.playAnim("singUP");
|
||||
bfBeep.play();
|
||||
|
||||
new FlxTimer().start(1.5, function(t) {
|
||||
timer(1.5, function() {
|
||||
focusOn(game.dad);
|
||||
tankTalk2.play();
|
||||
tankman.playAnim('2');
|
||||
|
||||
new FlxTimer().start(6.1, function(t) {
|
||||
game.remove(tankman);
|
||||
tankman.destroy();
|
||||
|
||||
game.camHUD.visible = true;
|
||||
game.dad.visible = true;
|
||||
timer(6.1, function() {
|
||||
destroyDistorto = false;
|
||||
distorto.fadeOut((Conductor.crochet / 1000) * 5, 0);
|
||||
|
||||
close();
|
||||
}, 1);
|
||||
}, 1);
|
||||
}, 1);
|
||||
}, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function timer(duration:Float, callBack:Void->Void) {
|
||||
timers.push(new FlxTimer().start(duration, function(timer) {
|
||||
timers.remove(timer);
|
||||
callBack();
|
||||
}));
|
||||
}
|
||||
|
||||
function focusOn(char) {
|
||||
var camPos = char.getCameraPosition();
|
||||
game.camFollow.setPosition(camPos.x, camPos.y);
|
||||
camPos.put();
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
game.remove(tankman);
|
||||
game.camHUD.visible = true;
|
||||
game.dad.visible = true;
|
||||
for(timer in timers) timer.cancel();
|
||||
for(thing in [tankTalk1, tankTalk2, bfBeep, tankman]) thing.destroy();
|
||||
if(destroyDistorto) distorto.destroy();
|
||||
}
|
||||
@@ -43,6 +43,8 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
||||
public var debugMode:Bool = false;
|
||||
public var animDatas:Map<String, AnimData> = [];
|
||||
|
||||
public var globalCurFrame(get, set):Int;
|
||||
|
||||
/**
|
||||
* ODD interval -> asynced; EVEN interval -> synced
|
||||
*/
|
||||
@@ -374,4 +376,11 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
||||
|
||||
return beatInterval = v;
|
||||
}
|
||||
|
||||
@:noCompletion private inline function get_globalCurFrame() {
|
||||
return animateAtlas != null ? (animateAtlas.anim.curFrame) : (animation.curAnim != null ? animation.curAnim.curFrame : 0);
|
||||
}
|
||||
@:noCompletion private inline function set_globalCurFrame(val:Int) {
|
||||
return animateAtlas != null ? (animateAtlas.anim.curFrame = val) : (animation.curAnim != null ? animation.curAnim.curFrame = val : val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ class MusicBeatState extends FlxState implements IBeatReceiver
|
||||
public override function openSubState(subState:FlxSubState) {
|
||||
var e = event("onOpenSubState", EventManager.get(StateEvent).recycle(subState));
|
||||
if (!e.cancelled)
|
||||
super.openSubState(subState);
|
||||
super.openSubState(e.substate is FlxSubState ? cast e.substate : subState);
|
||||
}
|
||||
|
||||
public override function onResize(w:Int, h:Int) {
|
||||
@@ -256,11 +256,9 @@ class MusicBeatState extends FlxState implements IBeatReceiver
|
||||
if (e.cancelled)
|
||||
return false;
|
||||
|
||||
if (skipTransOut)
|
||||
if (skipTransOut || (subState is MusicBeatTransition && cast(subState, MusicBeatTransition).newState != null))
|
||||
return true;
|
||||
if (subState is MusicBeatTransition && cast(subState, MusicBeatTransition).newState != null)
|
||||
return true;
|
||||
openSubState(new MusicBeatTransition(nextState));
|
||||
openSubState(new MusicBeatTransition(e.substate));
|
||||
persistentUpdate = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
|
||||
public override function openSubState(subState:FlxSubState) {
|
||||
var e = event("onOpenSubState", EventManager.get(StateEvent).recycle(subState));
|
||||
if (!e.cancelled)
|
||||
super.openSubState(subState);
|
||||
super.openSubState(e.substate is FlxSubState ? cast e.substate : subState);
|
||||
}
|
||||
|
||||
public override function onResize(w:Int, h:Int) {
|
||||
@@ -235,7 +235,7 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
|
||||
var e = event("onStateSwitch", EventManager.get(StateEvent).recycle(nextState));
|
||||
if (e.cancelled)
|
||||
return false;
|
||||
return super.switchTo(nextState);
|
||||
return super.switchTo(e.substate);
|
||||
}
|
||||
|
||||
public override function onFocus() {
|
||||
|
||||
@@ -4,7 +4,7 @@ import flixel.FlxState;
|
||||
|
||||
final class StateEvent extends CancellableEvent {
|
||||
/**
|
||||
* Substate that is about to be opened/closed
|
||||
* Substate or State that is about to be opened/closed
|
||||
*/
|
||||
public var substate:FlxState;
|
||||
public var substate:FlxState; // WHY is it named substate :sob: - Nex
|
||||
}
|
||||
@@ -18,8 +18,8 @@ class MainState extends FlxState {
|
||||
public override function create() {
|
||||
super.create();
|
||||
if (!initiated) {
|
||||
Main.loadGameSettings();
|
||||
Constants.init();
|
||||
Main.loadGameSettings();
|
||||
}
|
||||
|
||||
initiated = true;
|
||||
|
||||
@@ -9,10 +9,12 @@ import funkin.backend.FunkinSprite;
|
||||
import funkin.backend.scripting.DummyScript;
|
||||
import funkin.backend.scripting.Script;
|
||||
import funkin.backend.scripting.events.DanceEvent;
|
||||
import funkin.backend.scripting.events.CancellableEvent;
|
||||
import funkin.backend.scripting.events.DirectionAnimEvent;
|
||||
import funkin.backend.scripting.events.PlayAnimContext;
|
||||
import funkin.backend.scripting.events.PlayAnimEvent;
|
||||
import funkin.backend.scripting.events.PointEvent;
|
||||
import funkin.backend.scripting.events.DrawEvent;
|
||||
import funkin.backend.system.Conductor;
|
||||
import funkin.backend.system.interfaces.IBeatReceiver;
|
||||
import funkin.backend.system.interfaces.IOffsetCompatible;
|
||||
@@ -147,6 +149,11 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
||||
}
|
||||
|
||||
public function tryDance() {
|
||||
var event = new CancellableEvent();
|
||||
script.call("onTryDance", [event]);
|
||||
if (event.cancelled)
|
||||
return;
|
||||
|
||||
switch (lastAnimContext) {
|
||||
case SING | MISS:
|
||||
if (lastHit + (Conductor.stepCrochet * holdTime) < Conductor.songPosition)
|
||||
@@ -173,6 +180,9 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
||||
tryDance();
|
||||
}
|
||||
|
||||
public override function measureHit(curMeasure:Int)
|
||||
script.call("measureHit", [curMeasure]);
|
||||
|
||||
public override function stepHit(curStep:Int)
|
||||
script.call("stepHit", [curStep]);
|
||||
|
||||
@@ -196,17 +206,24 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
||||
return (isPlayer != playerOffsets) != (flipX != __baseFlipped);
|
||||
|
||||
public override function draw() {
|
||||
if (isFlippedOffsets()) {
|
||||
__reverseDrawProcedure = true;
|
||||
flipX = !flipX;
|
||||
scale.x *= -1;
|
||||
var e = EventManager.get(DrawEvent).recycle();
|
||||
script.call("draw", [e]);
|
||||
|
||||
super.draw();
|
||||
if(!e.cancelled) {
|
||||
if (isFlippedOffsets()) {
|
||||
__reverseDrawProcedure = true;
|
||||
flipX = !flipX;
|
||||
scale.x *= -1;
|
||||
|
||||
flipX = !flipX;
|
||||
scale.x *= -1;
|
||||
__reverseDrawProcedure = false;
|
||||
} else super.draw();
|
||||
super.draw();
|
||||
|
||||
flipX = !flipX;
|
||||
scale.x *= -1;
|
||||
__reverseDrawProcedure = false;
|
||||
} else super.draw();
|
||||
}
|
||||
|
||||
script.call("postDraw", [e]);
|
||||
}
|
||||
|
||||
public var singAnims = ["singLEFT", "singDOWN", "singUP", "singRIGHT"];
|
||||
|
||||
@@ -41,8 +41,8 @@ class GameOverSubstate extends MusicBeatSubstate
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.characterName = character != null ? character : Constants.DEFAULT_GAMEOVER_CHARACTER;
|
||||
this.player = player;
|
||||
this.characterName = character != null ? character : Constants.DEFAULT_GAMEOVER_CHARACTER;
|
||||
this.gameOverSong = gameOverSong != null ? gameOverSong : Constants.DEFAULT_GAMEOVER_SONG;
|
||||
this.lossSFXName = lossSFX != null ? lossSFXName : Constants.DEFAULT_GAMEOVER_LOSS_SFX;
|
||||
this.retrySFX = retrySFX != null ? retrySFX : Constants.DEFAULT_GAMEOVER_RETRY_SFX;
|
||||
|
||||
@@ -130,7 +130,7 @@ class Note extends FlxSprite
|
||||
(this.noteType != null && customTypePathExists(customType)) ? 'game/notes/${this.noteType}' : 'game/notes/default', @:privateAccess strumLine.strumScale * Constants.DEFAULT_NOTE_SCALE, animSuffix);
|
||||
|
||||
if (PlayState.instance != null)
|
||||
event = PlayState.instance.scripts.event("onNoteCreation", event);
|
||||
event = PlayState.instance.gameAndCharsEvent("onNoteCreation", event);
|
||||
|
||||
this.animSuffix = event.animSuffix;
|
||||
if (!event.cancelled) {
|
||||
@@ -184,7 +184,7 @@ class Note extends FlxSprite
|
||||
|
||||
if (PlayState.instance != null) {
|
||||
PlayState.instance.splashHandler.getSplashGroup(splash);
|
||||
PlayState.instance.scripts.event("onPostNoteCreation", event);
|
||||
PlayState.instance.gameAndCharsEvent("onPostNoteCreation", event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -511,7 +511,7 @@ class PlayState extends MusicBeatState
|
||||
if (e.percent <= acc && (rating == null || rating.percent < e.percent))
|
||||
rating = e;
|
||||
|
||||
var event = scripts.event("onRatingUpdate", EventManager.get(RatingUpdateEvent).recycle(rating, curRating));
|
||||
var event = gameAndCharsEvent("onRatingUpdate", EventManager.get(RatingUpdateEvent).recycle(rating, curRating));
|
||||
if (!event.cancelled)
|
||||
curRating = event.rating;
|
||||
}
|
||||
@@ -525,6 +525,24 @@ class PlayState extends MusicBeatState
|
||||
return this.maxHealth = v;
|
||||
}
|
||||
|
||||
public inline function callOnCharacters(func:String, ?parameters:Array<Dynamic>) {
|
||||
if(strumLines != null) strumLines.forEachAlive(function (strLine:StrumLine) {
|
||||
if (strLine.characters != null) for (character in strLine.characters)
|
||||
if (character != null) character.script.call(func, parameters);
|
||||
});
|
||||
}
|
||||
|
||||
public inline function gameAndCharsCall(func:String, ?parameters:Array<Dynamic>, ?charsFunc:String) {
|
||||
scripts.call(func, parameters);
|
||||
callOnCharacters(charsFunc != null ? charsFunc : func, parameters);
|
||||
}
|
||||
|
||||
public inline function gameAndCharsEvent<T:CancellableEvent>(func:String, ?event:T, ?charsFunc:String):T {
|
||||
scripts.event(func, event);
|
||||
callOnCharacters(charsFunc != null ? charsFunc : func, [event]);
|
||||
return event;
|
||||
}
|
||||
|
||||
@:dox(hide) override public function create()
|
||||
{
|
||||
Note.__customNoteTypeExists = [];
|
||||
@@ -685,9 +703,9 @@ class PlayState extends MusicBeatState
|
||||
// HUD INITIALIZATION & CAMERA INITIALIZATION
|
||||
#if REGION
|
||||
var event = EventManager.get(AmountEvent).recycle(Constants.DEFAULT_STRUM_AMOUNT);
|
||||
if (!scripts.event("onPreGenerateStrums", event).cancelled) {
|
||||
if (!gameAndCharsEvent("onPreGenerateStrums", event).cancelled) {
|
||||
generateStrums(event.amount);
|
||||
scripts.event("onPostGenerateStrums", event);
|
||||
gameAndCharsEvent("onPostGenerateStrums", event);
|
||||
}
|
||||
|
||||
for(str in strumLines)
|
||||
@@ -787,7 +805,7 @@ class PlayState extends MusicBeatState
|
||||
|
||||
__updateNote_event = EventManager.get(NoteUpdateEvent);
|
||||
|
||||
scripts.call("postCreate");
|
||||
gameAndCharsCall("postCreate", null, "gamePostCreate");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -851,7 +869,7 @@ class PlayState extends MusicBeatState
|
||||
_startCountdownCalled = true;
|
||||
inCutscene = false;
|
||||
|
||||
if (scripts.event("onStartCountdown", new CancellableEvent()).cancelled) return;
|
||||
if (gameAndCharsEvent("onStartCountdown", new CancellableEvent()).cancelled) return;
|
||||
}
|
||||
|
||||
startedCountdown = true;
|
||||
@@ -864,14 +882,14 @@ class PlayState extends MusicBeatState
|
||||
{
|
||||
countdown(swagCounter++);
|
||||
}, introLength);
|
||||
scripts.call("onPostStartCountdown");
|
||||
gameAndCharsCall("onPostStartCountdown");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fake countdown.
|
||||
*/
|
||||
public function countdown(swagCounter:Int) {
|
||||
var event:CountdownEvent = scripts.event("onCountdown", EventManager.get(CountdownEvent).recycle(
|
||||
var event:CountdownEvent = gameAndCharsEvent("onCountdown", EventManager.get(CountdownEvent).recycle(
|
||||
swagCounter,
|
||||
1,
|
||||
introSounds[swagCounter],
|
||||
@@ -914,12 +932,12 @@ class PlayState extends MusicBeatState
|
||||
event.spriteTween = tween;
|
||||
event.cancelled = false;
|
||||
|
||||
scripts.event("onPostCountdown", event);
|
||||
gameAndCharsEvent("onPostCountdown", event);
|
||||
}
|
||||
|
||||
@:dox(hide) function startSong():Void
|
||||
{
|
||||
scripts.call("onSongStart");
|
||||
gameAndCharsCall("onSongStart");
|
||||
startingSong = false;
|
||||
|
||||
inst.onComplete = endSong;
|
||||
@@ -946,7 +964,7 @@ class PlayState extends MusicBeatState
|
||||
|
||||
updateDiscordPresence();
|
||||
|
||||
scripts.call("onStartSong");
|
||||
gameAndCharsCall("onStartSong");
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
@@ -1024,7 +1042,7 @@ class PlayState extends MusicBeatState
|
||||
@:dox(hide)
|
||||
override function openSubState(SubState:FlxSubState)
|
||||
{
|
||||
var event = scripts.event("onSubstateOpen", EventManager.get(StateEvent).recycle(SubState));
|
||||
var event = gameAndCharsEvent("onSubstateOpen", EventManager.get(StateEvent).recycle(SubState));
|
||||
|
||||
if (!postCreated)
|
||||
MusicBeatState.skipTransIn = true;
|
||||
@@ -1044,13 +1062,13 @@ class PlayState extends MusicBeatState
|
||||
startTimer.active = false;
|
||||
}
|
||||
|
||||
super.openSubState(SubState);
|
||||
super.openSubState(event.substate is FlxSubState ? cast event.substate : SubState);
|
||||
}
|
||||
|
||||
@:dox(hide)
|
||||
override function closeSubState()
|
||||
{
|
||||
var event = scripts.event("onSubstateClose", EventManager.get(StateEvent).recycle(subState));
|
||||
var event = gameAndCharsEvent("onSubstateClose", EventManager.get(StateEvent).recycle(subState));
|
||||
if (event.cancelled) return;
|
||||
|
||||
if (paused)
|
||||
@@ -1084,7 +1102,7 @@ class PlayState extends MusicBeatState
|
||||
inst.resume();
|
||||
vocals.resume();
|
||||
}
|
||||
scripts.call("onFocus");
|
||||
gameAndCharsCall("onFocus");
|
||||
updateDiscordPresence();
|
||||
super.onFocus();
|
||||
}
|
||||
@@ -1097,7 +1115,7 @@ class PlayState extends MusicBeatState
|
||||
inst.pause();
|
||||
vocals.pause();
|
||||
}
|
||||
scripts.call("onFocusLost");
|
||||
gameAndCharsCall("onFocusLost");
|
||||
updateDiscordPresence();
|
||||
super.onFocusLost();
|
||||
}
|
||||
@@ -1116,14 +1134,14 @@ class PlayState extends MusicBeatState
|
||||
strumLine.vocals.play();
|
||||
}
|
||||
vocals.play();
|
||||
scripts.call("onVocalsResync");
|
||||
gameAndCharsCall("onVocalsResync");
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the game.
|
||||
*/
|
||||
public function pauseGame() {
|
||||
var e = scripts.event("onGamePause", new CancellableEvent());
|
||||
var e = gameAndCharsEvent("onGamePause", new CancellableEvent());
|
||||
if (e.cancelled) return;
|
||||
|
||||
persistentUpdate = false;
|
||||
@@ -1291,7 +1309,7 @@ class PlayState extends MusicBeatState
|
||||
pos.x /= r;
|
||||
pos.y /= r;
|
||||
|
||||
var event = scripts.event("onCameraMove", EventManager.get(CamMoveEvent).recycle(pos, strumLines.members[curCameraTarget], r));
|
||||
var event = gameAndCharsEvent("onCameraMove", EventManager.get(CamMoveEvent).recycle(pos, strumLines.members[curCameraTarget], r));
|
||||
if (!event.cancelled)
|
||||
camFollow.setPosition(pos.x, pos.y);
|
||||
}
|
||||
@@ -1339,7 +1357,10 @@ class PlayState extends MusicBeatState
|
||||
if (event == null) return;
|
||||
if (event.params == null) return;
|
||||
|
||||
if (scripts.event("onEvent", EventManager.get(EventGameEvent).recycle(event)).cancelled) return;
|
||||
var e = EventManager.get(EventGameEvent).recycle(event);
|
||||
gameAndCharsEvent("onEvent", e);
|
||||
if (e.cancelled) return;
|
||||
var event = e.event;
|
||||
|
||||
switch(event.name) {
|
||||
case "HScript Call":
|
||||
@@ -1399,7 +1420,7 @@ class PlayState extends MusicBeatState
|
||||
*/
|
||||
public function gameOver(?character:Character, ?deathCharID:String, ?gameOverSong:String, ?lossSFX:String, ?retrySFX:String) {
|
||||
var charToUse:Character = character.getDefault(opponentMode ? dad : boyfriend); // Imma still make it check null later just in case dad or bf are also null for some weird scripts - Nex
|
||||
var event:GameOverEvent = scripts.event("onGameOver", EventManager.get(GameOverEvent).recycle(
|
||||
var event:GameOverEvent = gameAndCharsEvent("onGameOver", EventManager.get(GameOverEvent).recycle(
|
||||
charToUse == null ? 0 : charToUse.x,
|
||||
charToUse == null ? 0 : charToUse.y,
|
||||
charToUse,
|
||||
@@ -1428,7 +1449,7 @@ class PlayState extends MusicBeatState
|
||||
|
||||
openSubState(new GameOverSubstate(event.x, event.y, event.deathCharID, event.isPlayer, event.gameOverSong, event.lossSFX, event.retrySFX));
|
||||
|
||||
scripts.event("onPostGameOver", event);
|
||||
gameAndCharsEvent("onPostGameOver", event);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1436,7 +1457,7 @@ class PlayState extends MusicBeatState
|
||||
*/
|
||||
public function endSong():Void
|
||||
{
|
||||
scripts.call("onSongEnd");
|
||||
gameAndCharsCall("onSongEnd");
|
||||
canPause = false;
|
||||
inst.volume = 0;
|
||||
vocals.volume = 0;
|
||||
@@ -1557,7 +1578,7 @@ class PlayState extends MusicBeatState
|
||||
var directionID:Null<Int> = note == null ? direction : note.strumID;
|
||||
if (playerID == null || directionID == null || playerID == -1) return;
|
||||
|
||||
var event:NoteMissEvent = scripts.event("onPlayerMiss", EventManager.get(NoteMissEvent).recycle(note, -10, 1, muteVocalsOnMiss, note != null ? -0.0475 : -0.04, Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2), note == null, combo > 5, "sad", true, true, "miss", strumLines.members[playerID].characters, playerID, note != null ? note.noteType : null, directionID, 0));
|
||||
var event:NoteMissEvent = gameAndCharsEvent("onPlayerMiss", EventManager.get(NoteMissEvent).recycle(note, -10, 1, muteVocalsOnMiss, note != null ? -0.0475 : -0.04, Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2), note == null, combo > 5, "sad", true, true, "miss", strumLines.members[playerID].characters, playerID, note != null ? note.noteType : null, directionID, 0));
|
||||
strumLine.onMiss.dispatch(event);
|
||||
if (event.cancelled) return;
|
||||
|
||||
@@ -1641,11 +1662,11 @@ class PlayState extends MusicBeatState
|
||||
|
||||
var event:NoteHitEvent;
|
||||
if (strumLine != null && !strumLine.cpu)
|
||||
event = scripts.event("onPlayerHit", EventManager.get(NoteHitEvent).recycle(false, !note.isSustainNote, !note.isSustainNote, note, strumLine.characters, true, note.noteType, note.animSuffix.getDefault(note.strumID < strumLine.members.length ? strumLine.members[note.strumID].animSuffix : strumLine.animSuffix), "game/score/", "", note.strumID, score, note.isSustainNote ? null : accuracy, 0.023, daRating, Options.splashesEnabled && !note.isSustainNote && daRating == "sick"));
|
||||
event = gameAndCharsEvent("onPlayerHit", EventManager.get(NoteHitEvent).recycle(false, !note.isSustainNote, !note.isSustainNote, note, strumLine.characters, true, note.noteType, note.animSuffix.getDefault(note.strumID < strumLine.members.length ? strumLine.members[note.strumID].animSuffix : strumLine.animSuffix), "game/score/", "", note.strumID, score, note.isSustainNote ? null : accuracy, 0.023, daRating, Options.splashesEnabled && !note.isSustainNote && daRating == "sick"));
|
||||
else
|
||||
event = scripts.event("onDadHit", EventManager.get(NoteHitEvent).recycle(false, false, false, note, strumLine.characters, false, note.noteType, note.animSuffix.getDefault(note.strumID < strumLine.members.length ? strumLine.members[note.strumID].animSuffix : strumLine.animSuffix), "game/score/", "", note.strumID, 0, null, 0, daRating, false));
|
||||
event = gameAndCharsEvent("onDadHit", EventManager.get(NoteHitEvent).recycle(false, false, false, note, strumLine.characters, false, note.noteType, note.animSuffix.getDefault(note.strumID < strumLine.members.length ? strumLine.members[note.strumID].animSuffix : strumLine.animSuffix), "game/score/", "", note.strumID, 0, null, 0, daRating, false));
|
||||
strumLine.onHit.dispatch(event);
|
||||
scripts.event("onNoteHit", event);
|
||||
gameAndCharsEvent("onNoteHit", event);
|
||||
|
||||
if (!event.cancelled) {
|
||||
if (!note.isSustainNote) {
|
||||
|
||||
@@ -41,7 +41,7 @@ class SplashHandler extends FlxTypedGroup<FunkinSprite> {
|
||||
public function showSplash(name:String, strum:Strum) {
|
||||
__grp = getSplashGroup(name);
|
||||
var event = funkin.backend.scripting.EventManager.get(funkin.backend.scripting.events.DynamicEvent).recycle(__grp.showOnStrum(strum), strum);
|
||||
event = PlayState.instance.scripts.event("onSplashShown", event);
|
||||
event = PlayState.instance.gameAndCharsEvent("onSplashShown", event);
|
||||
if (!event.cancelled)
|
||||
add(event.value1);
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ class Stage extends FlxBasic implements IBeatReceiver {
|
||||
}
|
||||
|
||||
if (PlayState.instance != null) {
|
||||
var event = PlayState.instance.scripts.event("onStageXMLParsed", EventManager.get(StageXMLEvent).recycle(this, stageXML, elems));
|
||||
var event = PlayState.instance.gameAndCharsEvent("onStageXMLParsed", EventManager.get(StageXMLEvent).recycle(this, stageXML, elems));
|
||||
elems = event.elems;
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ class Stage extends FlxBasic implements IBeatReceiver {
|
||||
}
|
||||
|
||||
if(PlayState.instance != null) {
|
||||
sprite = PlayState.instance.scripts.event("onStageNodeParsed", EventManager.get(StageNodeEvent).recycle(this, node, sprite, node.name)).sprite;
|
||||
sprite = PlayState.instance.gameAndCharsEvent("onStageNodeParsed", EventManager.get(StageNodeEvent).recycle(this, node, sprite, node.name)).sprite;
|
||||
}
|
||||
|
||||
if (sprite != null) {
|
||||
|
||||
@@ -247,7 +247,7 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
__justReleased.push(s.__getJustReleased(this));
|
||||
}
|
||||
|
||||
var event = PlayState.instance.scripts.event("onInputUpdate", EventManager.get(InputSystemEvent).recycle(__pressed, __justPressed, __justReleased, this, id));
|
||||
var event = PlayState.instance.gameAndCharsEvent("onInputUpdate", EventManager.get(InputSystemEvent).recycle(__pressed, __justPressed, __justReleased, this, id));
|
||||
if (event.cancelled) return;
|
||||
|
||||
__pressed = CoolUtil.getDefault(event.pressed, []);
|
||||
@@ -282,7 +282,7 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
forEach(function(str:Strum) {
|
||||
str.updatePlayerInput(str.__getPressed(this), str.__getJustPressed(this), str.__getJustReleased(this));
|
||||
});
|
||||
PlayState.instance.scripts.call("onPostInputUpdate");
|
||||
PlayState.instance.gameAndCharsCall("onPostInputUpdate");
|
||||
}
|
||||
|
||||
public inline function addHealth(health:Float)
|
||||
@@ -317,7 +317,7 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
|
||||
var event = EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i, animPrefix);
|
||||
event.__doAnimation = !MusicBeatState.skipTransIn;
|
||||
event = PlayState.instance.scripts.event("onStrumCreation", event);
|
||||
event = PlayState.instance.gameAndCharsEvent("onStrumCreation", event);
|
||||
|
||||
if (!event.cancelled) {
|
||||
babyArrow.frames = Paths.getFrames(event.sprite);
|
||||
@@ -348,7 +348,7 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
|
||||
insert(i, babyArrow);
|
||||
|
||||
PlayState.instance.scripts.event("onPostStrumCreation", event);
|
||||
PlayState.instance.gameAndCharsEvent("onPostStrumCreation", event);
|
||||
|
||||
return babyArrow;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,75 @@
|
||||
package funkin.game.cutscenes;
|
||||
|
||||
import funkin.backend.scripting.events.NameEvent;
|
||||
import funkin.menus.PauseSubState;
|
||||
|
||||
/**
|
||||
* Substate made for cutscenes.
|
||||
*/
|
||||
class Cutscene extends MusicBeatSubstate {
|
||||
var __callback:Void->Void;
|
||||
var __pausable:Bool;
|
||||
var game:PlayState = PlayState.instance;
|
||||
|
||||
public function new(callback:Void->Void) {
|
||||
public var paused:Bool = false;
|
||||
public var pauseItems:Array<String>;
|
||||
public var skippable(default, set):Bool;
|
||||
|
||||
public function set_skippable(val:Bool):Bool {
|
||||
if(!val) pauseItems.remove('Skip Cutscene');
|
||||
else if(!pauseItems.contains('Skip Cutscene')) pauseItems.insert(1, 'Skip Cutscene');
|
||||
return skippable = val;
|
||||
}
|
||||
|
||||
public function new(callback:Void->Void, allowPause:Bool = true, canSkip:Bool = true) {
|
||||
super();
|
||||
__callback = callback;
|
||||
__pausable = allowPause;
|
||||
|
||||
pauseItems = Constants.DEFAULT_CUTSCENE_PAUSE_ITEMS;
|
||||
skippable = canSkip;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
if (pauseCheck()) pauseCutscene();
|
||||
}
|
||||
|
||||
public function pauseCheck():Bool
|
||||
return controls.PAUSE && __pausable;
|
||||
|
||||
var _before:Array<Bool> = [false, true];
|
||||
public function pauseCutscene() {
|
||||
_before = [game.persistentUpdate, game.persistentDraw];
|
||||
game.persistentUpdate = persistentUpdate = false;
|
||||
game.persistentDraw = persistentDraw = true;
|
||||
paused = true;
|
||||
|
||||
openSubState(new PauseSubState(pauseItems, selectPauseOption));
|
||||
}
|
||||
|
||||
public override function closeSubState() {
|
||||
if (paused) {
|
||||
game.persistentUpdate = _before[0];
|
||||
game.persistentDraw = _before[1];
|
||||
paused = false;
|
||||
}
|
||||
|
||||
super.closeSubState();
|
||||
}
|
||||
|
||||
public function onSkipCutscene(event:NameEvent) close();
|
||||
public function onRestartCutscene(event:NameEvent) event.name = "Restart Song"; // Making the whole PlayState restart just for precaution - Nex
|
||||
public function onResumeCutscene(event:NameEvent) event.name = "Resume";
|
||||
|
||||
public function selectPauseOption(event:NameEvent) {
|
||||
switch(event.name) {
|
||||
case 'Skip Cutscene': onSkipCutscene(event);
|
||||
case 'Restart Cutscene': onRestartCutscene(event);
|
||||
case 'Resume Cutscene': onResumeCutscene(event);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override function close() {
|
||||
|
||||
@@ -13,7 +13,7 @@ import haxe.xml.Access;
|
||||
/**
|
||||
* Substate made for dialogue cutscenes. To use it in a scripted cutscene, call `startDialogue`.
|
||||
*/
|
||||
class DialogueCutscene extends Cutscene {
|
||||
class DialogueCutscene extends ScriptedCutscene {
|
||||
public var dialoguePath:String;
|
||||
public var dialogueData:Access;
|
||||
|
||||
@@ -28,23 +28,29 @@ class DialogueCutscene extends Cutscene {
|
||||
public var curMusic:FlxSound = null;
|
||||
|
||||
public static var cutscene:DialogueCutscene;
|
||||
public var dialogueScript:Script;
|
||||
public var dialogueScript(get, set):Script;
|
||||
|
||||
public function set_curLine(val:DialogueLine) {
|
||||
lastLine = curLine;
|
||||
return curLine = val;
|
||||
}
|
||||
|
||||
// Backwards comapt funcs - Nex
|
||||
public function set_dialogueScript(val:Script) return script = val;
|
||||
public function get_dialogueScript() return script;
|
||||
|
||||
public function new(dialoguePath:String, callback:Void->Void) {
|
||||
super(callback);
|
||||
this.dialoguePath = dialoguePath;
|
||||
super(this.dialoguePath = dialoguePath, callback);
|
||||
|
||||
camera = dialogueCamera = new FlxCamera();
|
||||
dialogueCamera.bgColor = 0;
|
||||
FlxG.cameras.add(dialogueCamera, false);
|
||||
|
||||
dialogueScript = Script.create(Paths.script(Path.withoutExtension(dialoguePath), null, dialoguePath.startsWith('assets')));
|
||||
dialogueScript.setParent(cutscene = this);
|
||||
dialogueScript.load();
|
||||
cutscene = this;
|
||||
}
|
||||
|
||||
public override function onErrorScriptLoading() {
|
||||
Logs.trace('Could not find script for dialogue cutscene at "${scriptPath}"', WARNING, YELLOW);
|
||||
}
|
||||
|
||||
var parentDisabler:FunkinParentDisabler;
|
||||
@@ -110,22 +116,21 @@ class DialogueCutscene extends Cutscene {
|
||||
|
||||
next(true);
|
||||
} catch(e) {
|
||||
Logs.trace('Error while loading dialogue at ${dialoguePath}: ${e.toString()}', ERROR);
|
||||
trace(CoolUtil.getLastExceptionStack());
|
||||
var message:String = e.toString();
|
||||
Logs.trace('Error while loading dialogue at ${dialoguePath}: $message', ERROR, RED);
|
||||
dialogueScript.call("loadingError", [message]);
|
||||
close();
|
||||
}
|
||||
|
||||
dialogueScript.call("postCreate");
|
||||
}
|
||||
|
||||
public override function beatHit(curBeat:Int) {
|
||||
super.beatHit(curBeat);
|
||||
dialogueScript.call("beatHit", [curBeat]);
|
||||
public override function pauseCheck():Bool {
|
||||
return super.pauseCheck() && !controls.ACCEPT; // Avoids next() and pause() being called at the same time - Nex
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
dialogueScript.call("update", [elapsed]);
|
||||
|
||||
if(controls.ACCEPT) {
|
||||
if(dialogueBox.dialogueEnded) next();
|
||||
else dialogueBox.text.skip();
|
||||
@@ -193,8 +198,6 @@ class DialogueCutscene extends Cutscene {
|
||||
|
||||
public override function destroy() {
|
||||
if(curMusic != null && !curMusic.persist) curMusic.destroy();
|
||||
dialogueScript.call("destroy");
|
||||
dialogueScript.destroy();
|
||||
|
||||
super.destroy();
|
||||
cutscene = null;
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
package funkin.game.cutscenes;
|
||||
|
||||
import haxe.io.Path;
|
||||
import flixel.FlxSubState;
|
||||
import funkin.backend.scripting.DummyScript;
|
||||
import funkin.backend.scripting.Script;
|
||||
import funkin.backend.scripting.events.CancellableEvent;
|
||||
import funkin.backend.scripting.events.NameEvent;
|
||||
import funkin.backend.scripting.events.StateEvent;
|
||||
|
||||
/**
|
||||
* Substate made for scripted cutscenes.
|
||||
* To add cutscenes to your songs, add a `cutscene.hx` file in your song's directory (ex: `songs/song/cutscene.hx`)
|
||||
*/
|
||||
class ScriptedCutscene extends Cutscene {
|
||||
var scriptPath:String;
|
||||
var script:Script;
|
||||
|
||||
var scriptPath:String;
|
||||
public function new(scriptPath:String, callback:Void->Void) {
|
||||
super(callback);
|
||||
|
||||
script = Script.create(this.scriptPath = scriptPath);
|
||||
script = Script.create(this.scriptPath = Paths.script(Path.withoutExtension(scriptPath), null, scriptPath.startsWith('assets')));
|
||||
script.setPublicMap(PlayState.instance.scripts.publicVariables);
|
||||
script.setParent(this);
|
||||
script.load();
|
||||
@@ -22,32 +27,91 @@ class ScriptedCutscene extends Cutscene {
|
||||
|
||||
public override function create() {
|
||||
super.create();
|
||||
trace("fuck you");
|
||||
script.call("create");
|
||||
if (Std.isOfType(script, DummyScript)) {
|
||||
Logs.trace('Could not find script for scripted cutscene at ${scriptPath}', ERROR, RED);
|
||||
close();
|
||||
}
|
||||
|
||||
if(Std.isOfType(script, DummyScript))
|
||||
onErrorScriptLoading();
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
public function onErrorScriptLoading() {
|
||||
Logs.trace('Could not find script for scripted cutscene at "${scriptPath}"', ERROR, RED);
|
||||
close();
|
||||
}
|
||||
|
||||
public override function pauseCheck():Bool
|
||||
{
|
||||
var shouldClose = super.pauseCheck();
|
||||
script.call("pauseCheck", [shouldClose]);
|
||||
return shouldClose;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float)
|
||||
{
|
||||
script.call("update", [elapsed]);
|
||||
super.update(elapsed);
|
||||
script.call("postUpdate", [elapsed]);
|
||||
}
|
||||
|
||||
public override function beatHit(curBeat:Int) {
|
||||
public override function pauseCutscene()
|
||||
{
|
||||
var event = new CancellableEvent();
|
||||
script.call("pauseCutscene", [event]);
|
||||
if(!event.cancelled) super.pauseCutscene();
|
||||
}
|
||||
|
||||
public override function onSkipCutscene(event:NameEvent)
|
||||
{
|
||||
script.call("onSkipCutscene", [event]);
|
||||
if(!event.cancelled) super.onSkipCutscene(event);
|
||||
}
|
||||
|
||||
public override function onRestartCutscene(event:NameEvent)
|
||||
{
|
||||
script.call("onRestartCutscene", [event]);
|
||||
if(!event.cancelled) super.onRestartCutscene(event);
|
||||
}
|
||||
|
||||
public override function onResumeCutscene(event:NameEvent)
|
||||
{
|
||||
script.call("onResumeCutscene", [event]);
|
||||
if(!event.cancelled) super.onResumeCutscene(event);
|
||||
}
|
||||
|
||||
public override function measureHit(curMeasure:Int)
|
||||
{
|
||||
super.measureHit(curMeasure);
|
||||
script.call("measureHit", [curMeasure]);
|
||||
}
|
||||
|
||||
public override function beatHit(curBeat:Int)
|
||||
{
|
||||
super.beatHit(curBeat);
|
||||
script.call("beatHit", [curBeat]);
|
||||
}
|
||||
|
||||
public override function stepHit(curStep:Int) {
|
||||
public override function stepHit(curStep:Int)
|
||||
{
|
||||
super.stepHit(curStep);
|
||||
script.call("stepHit", [curStep]);
|
||||
}
|
||||
|
||||
public override function openSubState(sub:FlxSubState)
|
||||
{
|
||||
var event = EventManager.get(StateEvent).recycle(sub);
|
||||
script.call("onSubstateClose", [event]);
|
||||
if(!event.cancelled) super.openSubState(event.substate is FlxSubState ? cast event.substate : sub);
|
||||
}
|
||||
|
||||
public override function closeSubState()
|
||||
{
|
||||
var event = EventManager.get(StateEvent).recycle(subState);
|
||||
script.call("onSubstateOpen", [event]);
|
||||
if(!event.cancelled) super.closeSubState();
|
||||
}
|
||||
|
||||
public override function destroy() {
|
||||
script.call("destroy");
|
||||
script.destroy();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package funkin.game.cutscenes;
|
||||
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.addons.display.FlxBackdrop;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
@@ -12,7 +13,7 @@ import haxe.xml.Access;
|
||||
import sys.io.File;
|
||||
#end
|
||||
#if VIDEO_CUTSCENES
|
||||
import hxvlc.flixel.FlxVideo;
|
||||
import hxvlc.flixel.FlxVideoSprite;
|
||||
#end
|
||||
|
||||
/**
|
||||
@@ -24,22 +25,24 @@ class VideoCutscene extends Cutscene {
|
||||
var localPath:String;
|
||||
|
||||
#if VIDEO_CUTSCENES
|
||||
var video:FlxVideo;
|
||||
public var skippable:Bool = true;
|
||||
#end
|
||||
var video:FlxVideoSprite;
|
||||
final mutex = new sys.thread.Mutex();
|
||||
|
||||
var cutsceneCamera:FlxCamera;
|
||||
|
||||
var text:FunkinText;
|
||||
var loadingBackdrop:FlxBackdrop;
|
||||
var videoReady:Bool = false;
|
||||
private var __loaded:Bool = false;
|
||||
|
||||
var bg:FlxSprite;
|
||||
var subtitle:FunkinText;
|
||||
|
||||
public var subtitles:Array<CutsceneSubtitle> = [];
|
||||
var curSubtitle:Int = 0;
|
||||
#end
|
||||
|
||||
public function new(path:String, callback:Void->Void) {
|
||||
super(callback);
|
||||
super(callback, false);
|
||||
localPath = Assets.getPath(this.path = path);
|
||||
}
|
||||
|
||||
@@ -48,21 +51,17 @@ class VideoCutscene extends Cutscene {
|
||||
|
||||
// TODO: get vlc to stop autoloading those goddamn subtitles (use different file ext??)
|
||||
|
||||
#if VIDEO_CUTSCENES
|
||||
cutsceneCamera = new FlxCamera();
|
||||
cutsceneCamera.bgColor = 0;
|
||||
FlxG.cameras.add(cutsceneCamera, false);
|
||||
|
||||
#if VIDEO_CUTSCENES
|
||||
parseSubtitles();
|
||||
|
||||
video = new FlxVideo();
|
||||
video.onEndReached.add(function()
|
||||
{
|
||||
video.dispose();
|
||||
FlxG.removeChild(video);
|
||||
});
|
||||
video.onEndReached.add(close);
|
||||
FlxG.addChildBelowMouse(video);
|
||||
add(video = new FlxVideoSprite());
|
||||
video.antialiasing = true;
|
||||
video.autoPause = false; // Imma handle it better inside this class, mainly because of the pause menu - Nex
|
||||
video.bitmap.onEndReached.add(close);
|
||||
|
||||
//cover = new FlxSprite(0, FlxG.height * 0.85).makeSolid(FlxG.width + 50, FlxG.height + 50, 0xFF000000);
|
||||
//cover.scrollFactor.set(0, 0);
|
||||
@@ -77,41 +76,44 @@ class VideoCutscene extends Cutscene {
|
||||
subtitle.alignment = CENTER;
|
||||
subtitle.visible = false;
|
||||
|
||||
if (localPath.startsWith("[ZIP]")) {
|
||||
text = new FunkinText(10, 10, Std.int(FlxG.width / 2), "Loading video...");
|
||||
text.cameras = [cutsceneCamera];
|
||||
text.visible = false;
|
||||
@:privateAccess
|
||||
text.regenGraphic();
|
||||
add(text);
|
||||
text = new FunkinText(10, 10, Std.int(FlxG.width / 2), "Loading video...");
|
||||
text.cameras = [cutsceneCamera];
|
||||
text.visible = false;
|
||||
@:privateAccess
|
||||
text.regenGraphic();
|
||||
add(text);
|
||||
|
||||
loadingBackdrop = new FlxBackdrop(text.graphic, X);
|
||||
loadingBackdrop.y = FlxG.height - 20 - loadingBackdrop.height;
|
||||
loadingBackdrop.cameras = [cutsceneCamera];
|
||||
add(loadingBackdrop);
|
||||
loadingBackdrop = new FlxBackdrop(text.graphic, X);
|
||||
loadingBackdrop.y = FlxG.height - 20 - loadingBackdrop.height;
|
||||
loadingBackdrop.velocity.x = 70;
|
||||
loadingBackdrop.cameras = [cutsceneCamera];
|
||||
add(loadingBackdrop);
|
||||
|
||||
// ZIP PATH: EXPORT
|
||||
// TODO: this but better and more ram friendly
|
||||
localPath = './.temp/video-${curVideo++}.${Path.extension(path)}';
|
||||
Main.execAsync(function() {
|
||||
loadingBackdrop.alpha = 0;
|
||||
FlxTween.tween(loadingBackdrop, {alpha: 1}, 0.5, {ease: FlxEase.sineInOut});
|
||||
|
||||
Main.execAsync(function() {
|
||||
if (localPath.startsWith("[ZIP]")) {
|
||||
// ZIP PATH: EXPORT
|
||||
// TODO: this but better and more ram friendly
|
||||
localPath = './.temp/video-${curVideo++}.mp4';
|
||||
File.saveBytes(localPath, Assets.getBytes(path));
|
||||
videoReady = true;
|
||||
});
|
||||
} else {
|
||||
if (video.load(localPath))
|
||||
new FlxTimer().start(0.001, function(tmr:FlxTimer) {
|
||||
video.play();
|
||||
});
|
||||
else
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
if(video.load(localPath)) new FlxTimer().start(0.001, function(_) {mutex.acquire(); onReady(); mutex.release();});
|
||||
else { mutex.acquire(); close(); mutex.release(); }
|
||||
});
|
||||
|
||||
add(bg);
|
||||
add(subtitle);
|
||||
#end
|
||||
|
||||
cameras = [cutsceneCamera];
|
||||
#else
|
||||
close();
|
||||
#end
|
||||
}
|
||||
|
||||
#if VIDEO_CUTSCENES
|
||||
public function parseSubtitles() {
|
||||
var subtitlesPath = '${Path.withoutExtension(path)}.srt';
|
||||
|
||||
@@ -141,22 +143,18 @@ class VideoCutscene extends Cutscene {
|
||||
}
|
||||
if (subtitleText.length <= 0) continue; // empty subtitle, skipping
|
||||
var lastSub = subtitles.last();
|
||||
if (lastSub != null && lastSub.subtitle == "" && lastSub.time > beginTime)
|
||||
if (lastSub != null && lastSub.subtitle == "" && lastSub.time >= beginTime)
|
||||
subtitles.pop(); // remove last subtitle auto reset to prevent bugs
|
||||
subtitles.push({
|
||||
subtitle: subtitleText.join("."),
|
||||
time: beginTime * 1000,
|
||||
color: 0xFFFFFFFF // todo
|
||||
subtitle: subtitleText.join(""),
|
||||
time: beginTime * 1000
|
||||
});
|
||||
subtitles.push({
|
||||
subtitle: "",
|
||||
time: endTime * 1000,
|
||||
color: 0xFFFFFFFF
|
||||
time: endTime * 1000
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
trace(subtitles);
|
||||
}
|
||||
|
||||
public static function splitTime(str:String):Float {
|
||||
@@ -173,50 +171,56 @@ class VideoCutscene extends Cutscene {
|
||||
return time;
|
||||
}
|
||||
|
||||
public inline function onReady() {
|
||||
FlxTween.cancelTweensOf(loadingBackdrop);
|
||||
FlxTween.tween(loadingBackdrop, {alpha: 0}, 0.7, {ease: FlxEase.sineInOut, onComplete: function(_) {
|
||||
loadingBackdrop.destroy();
|
||||
text.destroy();
|
||||
}});
|
||||
|
||||
__pausable = __loaded = true;
|
||||
video.play();
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
#if VIDEO_CUTSCENES
|
||||
if (videoReady) {
|
||||
videoReady = false;
|
||||
|
||||
if (video.load(localPath))
|
||||
new FlxTimer().start(0.001, function(tmr:FlxTimer) {
|
||||
video.play();
|
||||
});
|
||||
else
|
||||
{
|
||||
close();
|
||||
|
||||
if (loadingBackdrop != null)
|
||||
loadingBackdrop.visible = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (loadingBackdrop != null)
|
||||
loadingBackdrop.visible = false;
|
||||
if(loadingBackdrop == null && curSubtitle < subtitles.length && haxe.Int64.toInt(video.bitmap.time) >= subtitles[curSubtitle].time) {
|
||||
setSubtitle(subtitles[curSubtitle]);
|
||||
curSubtitle++;
|
||||
}
|
||||
@:privateAccess
|
||||
var time:Int64 = video.time;
|
||||
}
|
||||
|
||||
while (subtitles.length > 0 && subtitles[0].time < Math.round(FPHelper.i64ToDouble(time.low, time.high)))
|
||||
setSubtitle(subtitles.shift());
|
||||
@:dox(hide) override public function onFocus() {
|
||||
if(FlxG.autoPause && !paused) video.resume();
|
||||
super.onFocus();
|
||||
}
|
||||
|
||||
if (loadingBackdrop != null) {
|
||||
loadingBackdrop.x -= elapsed * FlxG.width * 0.5;
|
||||
}
|
||||
if (skippable && video.isPlaying && controls.ACCEPT) {
|
||||
video.onEndReached.dispatch();
|
||||
}
|
||||
#else
|
||||
close();
|
||||
#end
|
||||
@:dox(hide) override public function onFocusLost() {
|
||||
if(FlxG.autoPause && !paused) video.pause();
|
||||
super.onFocusLost();
|
||||
}
|
||||
|
||||
public override function pauseCutscene() {
|
||||
video.pause();
|
||||
super.pauseCutscene();
|
||||
}
|
||||
|
||||
public override function onResumeCutscene(event) {
|
||||
video.resume();
|
||||
super.onResumeCutscene(event);
|
||||
}
|
||||
|
||||
public override function onRestartCutscene(event) {
|
||||
closeSubState();
|
||||
video.bitmap.position = curSubtitle = 0;
|
||||
setSubtitle({time: -1, subtitle: ""});
|
||||
video.resume();
|
||||
}
|
||||
|
||||
public function setSubtitle(sub:CutsceneSubtitle) {
|
||||
if (bg.visible = subtitle.visible = (sub.subtitle.length > 0)) {
|
||||
subtitle.text = sub.subtitle;
|
||||
subtitle.color = sub.color;
|
||||
subtitle.screenCenter(X);
|
||||
bg.scale.set(subtitle.width + 8, subtitle.height + 8);
|
||||
bg.updateHitbox();
|
||||
@@ -228,10 +232,10 @@ class VideoCutscene extends Cutscene {
|
||||
FlxG.cameras.remove(cutsceneCamera, true);
|
||||
super.destroy();
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
typedef CutsceneSubtitle = {
|
||||
var time:Float; // time in ms
|
||||
var subtitle:String; // subtitle text
|
||||
var color:FlxColor;
|
||||
}
|
||||
|
||||
@@ -87,8 +87,11 @@ class DialogueBox extends FunkinSprite {
|
||||
}
|
||||
} catch(e) {
|
||||
active = false;
|
||||
Logs.trace('Couldn\'t load dialogue box "$name": ${e.toString()}', ERROR);
|
||||
var message:String = e.toString();
|
||||
Logs.trace('Couldn\'t load dialogue box "$name": $message', ERROR, RED);
|
||||
dialogueBoxScript.call("loadingError", [message]);
|
||||
}
|
||||
|
||||
defaultTextTypeSFX = [FlxG.sound.load(textTypeSFX)];
|
||||
FlxG.sound.cache(nextSFX);
|
||||
dialogueBoxScript.call("postCreate");
|
||||
|
||||
@@ -54,9 +54,10 @@ class DialogueCharacter extends FunkinSprite {
|
||||
x = 0; y = 0;
|
||||
} catch(e) {
|
||||
var message:String = e.toString();
|
||||
Logs.trace('Failed to load dialogue character $name: ${message}', ERROR);
|
||||
Logs.trace('Failed to load dialogue character $name: ${message}', ERROR, RED);
|
||||
dialogueCharScript.call("loadingError", [message]);
|
||||
}
|
||||
|
||||
visible = false;
|
||||
dialogueCharScript.call("postCreate");
|
||||
}
|
||||
|
||||
@@ -20,19 +20,22 @@ class PauseSubState extends MusicBeatSubstate
|
||||
|
||||
var grpMenuShit:FlxTypedGroup<Alphabet>;
|
||||
|
||||
var menuItems:Array<String> = Constants.DEFAULT_PAUSE_ITEMS;
|
||||
var menuItems:Array<String>;
|
||||
var curSelected:Int = 0;
|
||||
|
||||
var pauseMusic:FlxSound;
|
||||
|
||||
public var pauseScript:Script;
|
||||
public var selectCall:NameEvent->Void; // Mainly for extern stuff that aren't scripts - Nex
|
||||
|
||||
public var game:PlayState = PlayState.instance; // shortcut
|
||||
|
||||
private var __cancelDefault:Bool = false;
|
||||
|
||||
public function new(x:Float = 0, y:Float = 0) {
|
||||
public function new(?items:Array<String>, ?selectCall:NameEvent->Void) {
|
||||
super();
|
||||
menuItems = items != null ? items : Constants.DEFAULT_PAUSE_ITEMS;
|
||||
this.selectCall = selectCall;
|
||||
}
|
||||
|
||||
var parentDisabler:FunkinParentDisabler;
|
||||
@@ -134,13 +137,11 @@ class PauseSubState extends MusicBeatSubstate
|
||||
|
||||
public function selectOption() {
|
||||
var event = EventManager.get(NameEvent).recycle(menuItems[curSelected]);
|
||||
if (selectCall != null) selectCall(event);
|
||||
pauseScript.call("onSelectOption", [event]);
|
||||
|
||||
if (event.cancelled) return;
|
||||
|
||||
var daSelected:String = event.name;
|
||||
|
||||
switch (daSelected)
|
||||
switch (event.name)
|
||||
{
|
||||
case "Resume":
|
||||
close();
|
||||
|
||||
Reference in New Issue
Block a user