From ae6ac72e9b22eb627401199de3b0ee39c8c954a5 Mon Sep 17 00:00:00 2001 From: Abnormal <86753001+AbnormalPoof@users.noreply.github.com> Date: Wed, 29 Jan 2025 08:20:59 -0600 Subject: [PATCH] reformat all of the scripts --- preload/scripts/characters/bf-christmas.hxc | 49 +- preload/scripts/characters/bf-dark.hxc | 60 +- preload/scripts/characters/bf-pixel.hxc | 23 +- preload/scripts/characters/bf.hxc | 47 +- preload/scripts/characters/darnell-blazin.hxc | 763 +++++----- preload/scripts/characters/darnell.hxc | 229 +-- preload/scripts/characters/gf-dark.hxc | 60 +- preload/scripts/characters/gf.hxc | 47 +- preload/scripts/characters/nene-christmas.hxc | 709 +++++----- preload/scripts/characters/nene-dark.hxc | 822 +++++------ preload/scripts/characters/nene.hxc | 768 +++++----- .../scripts/characters/parents-christmas.hxc | 38 +- preload/scripts/characters/pico-blazin.hxc | 911 ++++++------ preload/scripts/characters/pico-christmas.hxc | 233 +-- preload/scripts/characters/pico-dark.hxc | 185 +-- preload/scripts/characters/pico-playable.hxc | 676 ++++----- preload/scripts/characters/pico-speaker.hxc | 163 ++- preload/scripts/characters/spirit.hxc | 47 +- preload/scripts/characters/spooky-dark.hxc | 60 +- preload/scripts/characters/tankman-atlas.hxc | 46 +- preload/scripts/characters/tankman.hxc | 46 +- preload/scripts/dialogue/boxes/roses.hxc | 44 +- preload/scripts/dialogue/boxes/thorns.hxc | 44 +- preload/scripts/levels/weekend1.hxc | 21 +- preload/scripts/players/pico.hxc | 11 +- preload/scripts/shaders/AddColorShader.hxc | 32 +- .../scripts/shaders/BuildingEffectShader.hxc | 42 +- preload/scripts/shaders/DarkenColorShader.hxc | 32 +- preload/scripts/shaders/InvertColorShader.hxc | 10 +- .../scripts/shaders/MultiplyColorShader.hxc | 32 +- .../scripts/shaders/SubtractColorShader.hxc | 32 +- preload/scripts/songs/2hot.hxc | 717 +++++----- preload/scripts/songs/blammed.hxc | 24 +- preload/scripts/songs/blazin.hxc | 196 +-- preload/scripts/songs/bopeebo.hxc | 29 +- preload/scripts/songs/cocoa.hxc | 47 +- preload/scripts/songs/dadbattle.hxc | 28 +- preload/scripts/songs/darnell.hxc | 399 +++--- preload/scripts/songs/eggnog.hxc | 210 ++- preload/scripts/songs/fresh.hxc | 27 +- preload/scripts/songs/guns.hxc | 41 +- preload/scripts/songs/lit-up.hxc | 27 +- preload/scripts/songs/philly-nice.hxc | 28 +- preload/scripts/songs/pico.hxc | 28 +- preload/scripts/songs/roses.hxc | 38 +- preload/scripts/songs/satin-panties.hxc | 9 +- preload/scripts/songs/senpai.hxc | 48 +- preload/scripts/songs/south.hxc | 28 +- preload/scripts/songs/spookeez.hxc | 28 +- preload/scripts/songs/stress.hxc | 56 +- preload/scripts/songs/thorns.hxc | 55 +- preload/scripts/songs/ugh.hxc | 45 +- preload/scripts/stages/limoRide.hxc | 206 +-- preload/scripts/stages/limoRideErect.hxc | 439 +++--- preload/scripts/stages/mainStageErect.hxc | 60 +- preload/scripts/stages/mallXmasErect.hxc | 38 +- preload/scripts/stages/phillyBlazin.hxc | 383 ++--- preload/scripts/stages/phillyStreets.hxc | 1001 ++++++------- preload/scripts/stages/phillyStreetsErect.hxc | 1246 +++++++++-------- preload/scripts/stages/phillyTrain.hxc | 329 ++--- preload/scripts/stages/phillyTrainErect.hxc | 818 +++++------ .../scripts/stages/props/ABotAtlasSprite.hxc | 17 +- preload/scripts/stages/props/CasingSprite.hxc | 91 +- .../scripts/stages/props/DadShootsSprite.hxc | 27 +- .../scripts/stages/props/PicoBloodPool.hxc | 36 +- .../stages/props/PicoDopplegangerSprite.hxc | 68 +- .../scripts/stages/props/SantaDiesSprite.hxc | 27 +- .../stages/props/SpraycanAtlasSprite.hxc | 49 +- .../scripts/stages/props/TankmanSprite.hxc | 190 +-- .../stages/props/TankmanSpriteGroup.hxc | 227 +-- preload/scripts/stages/school.hxc | 30 +- preload/scripts/stages/schoolEvil.hxc | 72 +- preload/scripts/stages/spookyMansion.hxc | 117 +- preload/scripts/stages/spookyMansionErect.hxc | 196 +-- preload/scripts/stages/tankmanBattlefield.hxc | 104 +- 75 files changed, 7387 insertions(+), 6774 deletions(-) diff --git a/preload/scripts/characters/bf-christmas.hxc b/preload/scripts/characters/bf-christmas.hxc index 7ff1de84c..460f3ceb0 100644 --- a/preload/scripts/characters/bf-christmas.hxc +++ b/preload/scripts/characters/bf-christmas.hxc @@ -5,28 +5,33 @@ import funkin.play.character.MultiSparrowCharacter; import funkin.play.character.CharacterType; import funkin.play.GameOverSubState; -class BoyfriendChristmasCharacter extends MultiSparrowCharacter { - function new() { - super('bf-christmas'); - } +class BoyfriendChristmasCharacter extends MultiSparrowCharacter +{ + function new() + { + super('bf-christmas'); + } -function onNoteHit(event:HitNoteScriptEvent) - { - if (event.eventCanceled) { - // onNoteHit event was cancelled by the gameplay module. - return; - } + function onNoteHit(event:HitNoteScriptEvent) + { + if (event.eventCanceled) + { + // onNoteHit event was cancelled by the gameplay module. + return; + } - if (event.note.noteData.getMustHitNote() && characterType == CharacterType.BF) { - // Override the hit note animation. - switch(event.note.kind) { - case "censor": - holdTimer = 0; - this.playSingAnimation(event.note.noteData.getDirection(), false, 'censor'); - return; - default: - super.onNoteHit(event); - } - } - } + if (event.note.noteData.getMustHitNote() && characterType == CharacterType.BF) + { + // Override the hit note animation. + switch (event.note.kind) + { + case "censor": + holdTimer = 0; + this.playSingAnimation(event.note.noteData.getDirection(), false, 'censor'); + return; + default: + super.onNoteHit(event); + } + } + } } diff --git a/preload/scripts/characters/bf-dark.hxc b/preload/scripts/characters/bf-dark.hxc index fde0200e9..c994917f2 100644 --- a/preload/scripts/characters/bf-dark.hxc +++ b/preload/scripts/characters/bf-dark.hxc @@ -9,40 +9,44 @@ import funkin.play.character.CharacterType; import funkin.play.PlayState; import funkin.play.character.MultiSparrowCharacter; -class BoyfriendDarkCharacter extends MultiSparrowCharacter { - function new() { - super('bf-dark'); - } +class BoyfriendDarkCharacter extends MultiSparrowCharacter +{ + function new() + { + super('bf-dark'); + } var normalChar:BaseCharacter; - override function set_alpha(val:Float):Float{ - super.set_alpha(val); - if(val != 1) - normalChar.alpha = 1; - else - normalChar.alpha = 0; + override function set_alpha(val:Float):Float + { + super.set_alpha(val); + if (val != 1) normalChar.alpha = 1; + else + normalChar.alpha = 0; return val; - } - - override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) { - super.playAnimation(name, restart, ignoreOther); - if(normalChar != null){ - normalChar.playAnimation(name, restart, ignoreOther); - normalChar.setPosition(this.x, this.y); - } - } - - function onCreate(event:ScriptEvent) { - super.onCreate(event); - normalChar = CharacterDataParser.fetchCharacter('bf'); + } + + override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) + { + super.playAnimation(name, restart, ignoreOther); + if (normalChar != null) + { + normalChar.playAnimation(name, restart, ignoreOther); + normalChar.setPosition(this.x, this.y); + } + } + + function onCreate(event:ScriptEvent) + { + super.onCreate(event); + normalChar = CharacterDataParser.fetchCharacter('bf'); normalChar.zIndex = 199; - normalChar.alpha = 0; + normalChar.alpha = 0; normalChar.flipX = false; - PlayState.instance.currentStage.add(normalChar); - PlayState.instance.currentStage.refresh(); // Apply z-index. - } - + PlayState.instance.currentStage.add(normalChar); + PlayState.instance.currentStage.refresh(); // Apply z-index. + } } diff --git a/preload/scripts/characters/bf-pixel.hxc b/preload/scripts/characters/bf-pixel.hxc index 761edab3c..f73676052 100644 --- a/preload/scripts/characters/bf-pixel.hxc +++ b/preload/scripts/characters/bf-pixel.hxc @@ -5,17 +5,20 @@ import funkin.play.PauseSubState; import flixel.FlxSprite; import flixel.FlxG; -class BFPixelCharacter extends MultiSparrowCharacter { - function new() { - super('bf-pixel'); - } +class BFPixelCharacter extends MultiSparrowCharacter +{ + function new() + { + super('bf-pixel'); + } - function onCreate(event:ScriptEvent) { - super.onCreate(event); + function onCreate(event:ScriptEvent) + { + super.onCreate(event); - GameOverSubState.musicSuffix = '-pixel'; - GameOverSubState.blueBallSuffix = '-pixel'; + GameOverSubState.musicSuffix = '-pixel'; + GameOverSubState.blueBallSuffix = '-pixel'; - PauseSubState.musicSuffix = '-pixel'; - } + PauseSubState.musicSuffix = '-pixel'; + } } diff --git a/preload/scripts/characters/bf.hxc b/preload/scripts/characters/bf.hxc index a0396bb7b..b49bf32bc 100644 --- a/preload/scripts/characters/bf.hxc +++ b/preload/scripts/characters/bf.hxc @@ -4,37 +4,44 @@ import funkin.audio.FunkinSound; import funkin.play.character.MultiSparrowCharacter; import funkin.play.GameOverSubState; -class BoyfriendCharacter extends MultiSparrowCharacter { - function new() { - super('bf'); - } +class BoyfriendCharacter extends MultiSparrowCharacter +{ + function new() + { + super('bf'); + } - override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) { - if (name == "fakeoutDeath" && !this.debug) { - doFakeoutDeath(); - } else { - super.playAnimation(name, restart, ignoreOther); - } - } + override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) + { + if (name == "fakeoutDeath" && !this.debug) + { + doFakeoutDeath(); + } + else + { + super.playAnimation(name, restart, ignoreOther); + } + } - function doFakeoutDeath():Void { - FunkinSound.playOnce(Paths.sound("gameplay/gameover/fakeout_death"), 1.0); + function doFakeoutDeath():Void + { + FunkinSound.playOnce(Paths.sound("gameplay/gameover/fakeout_death"), 1.0); - var bfFakeout:FlxAtlasSprite = new FlxAtlasSprite(this.x - 440, this.y - 240, Paths.animateAtlas("characters/bfFakeOut", "shared")); + var bfFakeout:FlxAtlasSprite = new FlxAtlasSprite(this.x - 440, this.y - 240, Paths.animateAtlas("characters/bfFakeOut", "shared")); FlxG.state.subState.add(bfFakeout); - bfFakeout.zIndex = 1000; + bfFakeout.zIndex = 1000; bfFakeout.playAnimation(''); - // We don't want people to miss this. - FlxG.state.subState.mustNotExit = true; + // We don't want people to miss this. + FlxG.state.subState.mustNotExit = true; bfFakeout.onAnimationComplete.add(() -> { bfFakeout.visible = false; this.visible = true; - FlxG.state.subState.mustNotExit = false; + FlxG.state.subState.mustNotExit = false; this.playAnimation('firstDeath', true, true); // Play the "blue balled" sound. May play a variant if one has been assigned. GameOverSubState.playBlueBalledSFX(); }); bfFakeout.visible = true; - this.visible = false; - } + this.visible = false; + } } diff --git a/preload/scripts/characters/darnell-blazin.hxc b/preload/scripts/characters/darnell-blazin.hxc index 6207d4135..4f2358e2c 100644 --- a/preload/scripts/characters/darnell-blazin.hxc +++ b/preload/scripts/characters/darnell-blazin.hxc @@ -5,376 +5,395 @@ import StringTools; class DarnellBlazinCharacter extends AnimateAtlasCharacter { - function new() - { - super('darnell-blazin'); - } - - function onCreate(event:ScriptEvent) { - super.onCreate(event); - - this.danceEvery = 0; - this.playAnimation('idle', true, false); - } - - var cantUppercut = false; - - function onNoteHit(event:HitNoteScriptEvent) - { - holdTimer = 0; - - if (!StringTools.startsWith(event.note.kind, 'weekend-1-')) return; - - // SPECIAL CASE: If Pico hits a poor note at low health (at 30% chance), - // Darnell may duck below Pico's punch to attempt an uppercut. - // TODO: Maybe add a cooldown to this? - var shouldDoUppercutPrep = wasNoteHitPoorly(event) && isPlayerLowHealth() && FlxG.random.bool(30); - - if (shouldDoUppercutPrep) { - playUppercutPrepAnim(); - return; - } - - if (cantUppercut) { - playPunchHighAnim(); - return; - } - - // Override the hit note animation. - switch (event.note.kind) - { - case "weekend-1-punchlow": - playHitLowAnim(); - case "weekend-1-punchlowblocked": - playBlockAnim(); - case "weekend-1-punchlowdodged": - playDodgeAnim(); - case "weekend-1-punchlowspin": - playSpinAnim(); - - case "weekend-1-punchhigh": - playHitHighAnim(); - case "weekend-1-punchhighblocked": - playBlockAnim(); - case "weekend-1-punchhighdodged": - playDodgeAnim(); - case "weekend-1-punchhighspin": - playSpinAnim(); - - // Attempt to punch, Pico dodges or gets hit. - case "weekend-1-blockhigh": - playPunchHighAnim(); - case "weekend-1-blocklow": - playPunchLowAnim(); - case "weekend-1-blockspin": - playPunchHighAnim(); - - // Attempt to punch, Pico dodges or gets hit. - case "weekend-1-dodgehigh": - playPunchHighAnim(); - case "weekend-1-dodgelow": - playPunchLowAnim(); - case "weekend-1-dodgespin": - playPunchHighAnim(); - - // Attempt to punch, Pico ALWAYS gets hit. - case "weekend-1-hithigh": - playPunchHighAnim(); - case "weekend-1-hitlow": - playPunchLowAnim(); - case "weekend-1-hitspin": - playPunchHighAnim(); - - // Fail to dodge the uppercut. - case "weekend-1-picouppercutprep": - // Continue whatever animation was playing before - // playIdleAnim(); - case "weekend-1-picouppercut": - playUppercutHitAnim(); - - // Attempt to punch, Pico dodges or gets hit. - case "weekend-1-darnelluppercutprep": - playUppercutPrepAnim(); - case "weekend-1-darnelluppercut": - playUppercutAnim(); - - case "weekend-1-idle": - playIdleAnim(); - case "weekend-1-fakeout": - playCringeAnim(); - case "weekend-1-taunt": - playPissedConditionalAnim(); - case "weekend-1-tauntforce": - playPissedAnim(); - case "weekend-1-reversefakeout": - playFakeoutAnim(); - - default: - trace('Unknown note kind: ' + event.note.kind); - } - - cantUppercut = false; - } - - function onNoteMiss(event:NoteScriptEvent) - { - holdTimer = 0; - - if (!StringTools.startsWith(event.note.kind, 'weekend-1-')) { - return; - } - - // SPECIAL CASE: Darnell prepared to uppercut last time and Pico missed! FINISH HIM! - if (getCurrentAnimation() == 'uppercutPrep') { - playUppercutAnim(); - return; - } - - if (willMissBeLethal(event)) { - playPunchLowAnim(); - return; - } - - if (cantUppercut) { - playPunchHighAnim(); - return; - } - - // Override the hit note animation. - switch (event.note.kind) - { - // Pico tried and failed to punch, punch back! - case "weekend-1-punchlow": - playPunchLowAnim(); - case "weekend-1-punchlowblocked": - playPunchLowAnim(); - case "weekend-1-punchlowdodged": - playPunchLowAnim(); - case "weekend-1-punchlowspin": - playPunchLowAnim(); - - // Pico tried and failed to punch, punch back! - case "weekend-1-punchhigh": - playPunchHighAnim(); - case "weekend-1-punchhighblocked": - playPunchHighAnim(); - case "weekend-1-punchhighdodged": - playPunchHighAnim(); - case "weekend-1-punchhighspin": - playPunchHighAnim(); - - // Attempt to punch, Pico dodges or gets hit. - case "weekend-1-blockhigh": - playPunchHighAnim(); - case "weekend-1-blocklow": - playPunchLowAnim(); - case "weekend-1-blockspin": - playPunchHighAnim(); - - // Attempt to punch, Pico dodges or gets hit. - case "weekend-1-dodgehigh": - playPunchHighAnim(); - case "weekend-1-dodgelow": - playPunchLowAnim(); - case "weekend-1-dodgespin": - playPunchHighAnim(); - - // Attempt to punch, Pico ALWAYS gets hit. - case "weekend-1-hithigh": - playPunchHighAnim(); - case "weekend-1-hitlow": - playPunchLowAnim(); - case "weekend-1-hitspin": - playPunchHighAnim(); - - // Successfully dodge the uppercut. - case "weekend-1-picouppercutprep": - playHitHighAnim(); - cantUppercut = true; - case "weekend-1-picouppercut": - playDodgeAnim(); - - // Attempt to punch, Pico dodges or gets hit. - case "weekend-1-darnelluppercutprep": - playUppercutPrepAnim(); - case "weekend-1-darnelluppercut": - playUppercutAnim(); - - case "weekend-1-idle": - playIdleAnim(); - case "weekend-1-fakeout": - playCringeAnim(); // TODO: Which anim? - case "weekend-1-taunt": - playPissedConditionalAnim(); - case "weekend-1-tauntforce": - playPissed(); - case "weekend-1-reversefakeout": - playFakeoutAnim(); // TODO: Which anim? - - default: - trace('Unknown note kind: ' + event.note.kind); - } - - cantUppercut = false; - } - - override function onSongRetry() - { - super.onSongRetry(); - cantUppercut = false; - playIdleAnim(); - } - - function willMissBeLethal(event:NoteScriptEvent):Bool { - return (PlayState.instance.health + event.healthChange) <= 0.0; - } - - function onNoteGhostMiss(event:GhostMissNoteScriptEvent) - { - if (willMissBeLethal(event)) { - // Darnell alternates a punch so that Pico dies. - playPunchLowAnim(); - } else { - // Pico wildly throws punches but Darnell alternates between dodges and blocks. - var shouldDodge = FlxG.random.bool(50); // 50/50. - if (shouldDodge) { - playDodgeAnim(); - } else { - playBlockAnim(); - } - } - } - - override function onAnimationFinished(name:String) - { - super.onAnimationFinished(name); - } - - function moveToBack() - { - if (this.debug) return; - this.zIndex = 2000; - PlayState.instance.currentStage.refresh(); - } - - function moveToFront() - { - if (this.debug) return; - this.zIndex = 3000; - PlayState.instance.currentStage.refresh(); - } - - function wasNoteHitPoorly(event:HitNoteScriptEvent):Bool { - return (event.judgement == "bad" || event.judgement == "shit"); - } - - function isPlayerLowHealth(event:HitNoteScriptEvent):Bool { - return PlayState.instance.health <= 0.30 * 2.0; - } - - // ANIMATIONS - - var alternate:Bool = false; - - function doAlternate():String { - alternate = !alternate; - return alternate ? '1' : '2'; - } - - function playBlockAnim() - { - this.playAnimation('block', true, false); - PlayState.instance.camGame.shake(0.002, 0.1); - moveToBack(); - } - - function playCringeAnim() - { - this.playAnimation('cringe', true, false); - moveToBack(); - } - - function playDodgeAnim() - { - this.playAnimation('dodge', true, false); - moveToBack(); - } - - function playIdleAnim() - { - this.playAnimation('idle', false, false); - moveToBack(); - } - - function playFakeoutAnim() - { - this.playAnimation('fakeout', true, false); - moveToBack(); - } - - function playPissedConditionalAnim() - { - if (getCurrentAnimation() == "cringe") { - playPissedAnim(); - } else { - playIdleAnim(); - } - } - - function playPissedAnim() - { - this.playAnimation('pissed', true, false); - moveToBack(); - } - - function playUppercutPrepAnim() - { - this.playAnimation('uppercutPrep', true, false); - moveToFront(); - } - - function playUppercutAnim() - { - this.playAnimation('uppercut', true, false); - moveToFront(); - } - - function playUppercutHitAnim() - { - this.playAnimation('uppercutHit', true, false); - moveToBack(); - } - - function playHitHighAnim() - { - this.playAnimation('hitHigh', true, false); - PlayState.instance.camGame.shake(0.0025, 0.15); - moveToBack(); - } - - function playHitLowAnim() - { - this.playAnimation('hitLow', true, false); - PlayState.instance.camGame.shake(0.0025, 0.15); - moveToBack(); - } - - function playPunchHighAnim() - { - this.playAnimation('punchHigh' + doAlternate(), true, false); - moveToFront(); - } - - function playPunchLowAnim() - { - this.playAnimation('punchLow' + doAlternate(), true, false); - moveToFront(); - } - - function playSpinAnim() - { - this.playAnimation('hitSpin', true, false); - PlayState.instance.camGame.shake(0.0025, 0.15); - moveToBack(); - } + function new() + { + super('darnell-blazin'); + } + + function onCreate(event:ScriptEvent) + { + super.onCreate(event); + + this.danceEvery = 0; + this.playAnimation('idle', true, false); + } + + var cantUppercut = false; + + function onNoteHit(event:HitNoteScriptEvent) + { + holdTimer = 0; + + if (!StringTools.startsWith(event.note.kind, 'weekend-1-')) return; + + // SPECIAL CASE: If Pico hits a poor note at low health (at 30% chance), + // Darnell may duck below Pico's punch to attempt an uppercut. + // TODO: Maybe add a cooldown to this? + var shouldDoUppercutPrep = wasNoteHitPoorly(event) && isPlayerLowHealth() && FlxG.random.bool(30); + + if (shouldDoUppercutPrep) + { + playUppercutPrepAnim(); + return; + } + + if (cantUppercut) + { + playPunchHighAnim(); + return; + } + + // Override the hit note animation. + switch (event.note.kind) + { + case "weekend-1-punchlow": + playHitLowAnim(); + case "weekend-1-punchlowblocked": + playBlockAnim(); + case "weekend-1-punchlowdodged": + playDodgeAnim(); + case "weekend-1-punchlowspin": + playSpinAnim(); + + case "weekend-1-punchhigh": + playHitHighAnim(); + case "weekend-1-punchhighblocked": + playBlockAnim(); + case "weekend-1-punchhighdodged": + playDodgeAnim(); + case "weekend-1-punchhighspin": + playSpinAnim(); + + // Attempt to punch, Pico dodges or gets hit. + case "weekend-1-blockhigh": + playPunchHighAnim(); + case "weekend-1-blocklow": + playPunchLowAnim(); + case "weekend-1-blockspin": + playPunchHighAnim(); + + // Attempt to punch, Pico dodges or gets hit. + case "weekend-1-dodgehigh": + playPunchHighAnim(); + case "weekend-1-dodgelow": + playPunchLowAnim(); + case "weekend-1-dodgespin": + playPunchHighAnim(); + + // Attempt to punch, Pico ALWAYS gets hit. + case "weekend-1-hithigh": + playPunchHighAnim(); + case "weekend-1-hitlow": + playPunchLowAnim(); + case "weekend-1-hitspin": + playPunchHighAnim(); + + // Fail to dodge the uppercut. + case "weekend-1-picouppercutprep": + // Continue whatever animation was playing before + // playIdleAnim(); + case "weekend-1-picouppercut": + playUppercutHitAnim(); + + // Attempt to punch, Pico dodges or gets hit. + case "weekend-1-darnelluppercutprep": + playUppercutPrepAnim(); + case "weekend-1-darnelluppercut": + playUppercutAnim(); + + case "weekend-1-idle": + playIdleAnim(); + case "weekend-1-fakeout": + playCringeAnim(); + case "weekend-1-taunt": + playPissedConditionalAnim(); + case "weekend-1-tauntforce": + playPissedAnim(); + case "weekend-1-reversefakeout": + playFakeoutAnim(); + + default: + trace('Unknown note kind: ' + event.note.kind); + } + + cantUppercut = false; + } + + function onNoteMiss(event:NoteScriptEvent) + { + holdTimer = 0; + + if (!StringTools.startsWith(event.note.kind, 'weekend-1-')) + { + return; + } + + // SPECIAL CASE: Darnell prepared to uppercut last time and Pico missed! FINISH HIM! + if (getCurrentAnimation() == 'uppercutPrep') + { + playUppercutAnim(); + return; + } + + if (willMissBeLethal(event)) + { + playPunchLowAnim(); + return; + } + + if (cantUppercut) + { + playPunchHighAnim(); + return; + } + + // Override the hit note animation. + switch (event.note.kind) + { + // Pico tried and failed to punch, punch back! + case "weekend-1-punchlow": + playPunchLowAnim(); + case "weekend-1-punchlowblocked": + playPunchLowAnim(); + case "weekend-1-punchlowdodged": + playPunchLowAnim(); + case "weekend-1-punchlowspin": + playPunchLowAnim(); + + // Pico tried and failed to punch, punch back! + case "weekend-1-punchhigh": + playPunchHighAnim(); + case "weekend-1-punchhighblocked": + playPunchHighAnim(); + case "weekend-1-punchhighdodged": + playPunchHighAnim(); + case "weekend-1-punchhighspin": + playPunchHighAnim(); + + // Attempt to punch, Pico dodges or gets hit. + case "weekend-1-blockhigh": + playPunchHighAnim(); + case "weekend-1-blocklow": + playPunchLowAnim(); + case "weekend-1-blockspin": + playPunchHighAnim(); + + // Attempt to punch, Pico dodges or gets hit. + case "weekend-1-dodgehigh": + playPunchHighAnim(); + case "weekend-1-dodgelow": + playPunchLowAnim(); + case "weekend-1-dodgespin": + playPunchHighAnim(); + + // Attempt to punch, Pico ALWAYS gets hit. + case "weekend-1-hithigh": + playPunchHighAnim(); + case "weekend-1-hitlow": + playPunchLowAnim(); + case "weekend-1-hitspin": + playPunchHighAnim(); + + // Successfully dodge the uppercut. + case "weekend-1-picouppercutprep": + playHitHighAnim(); + cantUppercut = true; + case "weekend-1-picouppercut": + playDodgeAnim(); + + // Attempt to punch, Pico dodges or gets hit. + case "weekend-1-darnelluppercutprep": + playUppercutPrepAnim(); + case "weekend-1-darnelluppercut": + playUppercutAnim(); + + case "weekend-1-idle": + playIdleAnim(); + case "weekend-1-fakeout": + playCringeAnim(); // TODO: Which anim? + case "weekend-1-taunt": + playPissedConditionalAnim(); + case "weekend-1-tauntforce": + playPissed(); + case "weekend-1-reversefakeout": + playFakeoutAnim(); // TODO: Which anim? + + default: + trace('Unknown note kind: ' + event.note.kind); + } + + cantUppercut = false; + } + + override function onSongRetry() + { + super.onSongRetry(); + cantUppercut = false; + playIdleAnim(); + } + + function willMissBeLethal(event:NoteScriptEvent):Bool + { + return (PlayState.instance.health + event.healthChange) <= 0.0; + } + + function onNoteGhostMiss(event:GhostMissNoteScriptEvent) + { + if (willMissBeLethal(event)) + { + // Darnell alternates a punch so that Pico dies. + playPunchLowAnim(); + } + else + { + // Pico wildly throws punches but Darnell alternates between dodges and blocks. + var shouldDodge = FlxG.random.bool(50); // 50/50. + if (shouldDodge) + { + playDodgeAnim(); + } + else + { + playBlockAnim(); + } + } + } + + override function onAnimationFinished(name:String) + { + super.onAnimationFinished(name); + } + + function moveToBack() + { + if (this.debug) return; + this.zIndex = 2000; + PlayState.instance.currentStage.refresh(); + } + + function moveToFront() + { + if (this.debug) return; + this.zIndex = 3000; + PlayState.instance.currentStage.refresh(); + } + + function wasNoteHitPoorly(event:HitNoteScriptEvent):Bool + { + return (event.judgement == "bad" || event.judgement == "shit"); + } + + function isPlayerLowHealth(event:HitNoteScriptEvent):Bool + { + return PlayState.instance.health <= 0.30 * 2.0; + } + + // ANIMATIONS + var alternate:Bool = false; + + function doAlternate():String + { + alternate = !alternate; + return alternate ? '1' : '2'; + } + + function playBlockAnim() + { + this.playAnimation('block', true, false); + PlayState.instance.camGame.shake(0.002, 0.1); + moveToBack(); + } + + function playCringeAnim() + { + this.playAnimation('cringe', true, false); + moveToBack(); + } + + function playDodgeAnim() + { + this.playAnimation('dodge', true, false); + moveToBack(); + } + + function playIdleAnim() + { + this.playAnimation('idle', false, false); + moveToBack(); + } + + function playFakeoutAnim() + { + this.playAnimation('fakeout', true, false); + moveToBack(); + } + + function playPissedConditionalAnim() + { + if (getCurrentAnimation() == "cringe") + { + playPissedAnim(); + } + else + { + playIdleAnim(); + } + } + + function playPissedAnim() + { + this.playAnimation('pissed', true, false); + moveToBack(); + } + + function playUppercutPrepAnim() + { + this.playAnimation('uppercutPrep', true, false); + moveToFront(); + } + + function playUppercutAnim() + { + this.playAnimation('uppercut', true, false); + moveToFront(); + } + + function playUppercutHitAnim() + { + this.playAnimation('uppercutHit', true, false); + moveToBack(); + } + + function playHitHighAnim() + { + this.playAnimation('hitHigh', true, false); + PlayState.instance.camGame.shake(0.0025, 0.15); + moveToBack(); + } + + function playHitLowAnim() + { + this.playAnimation('hitLow', true, false); + PlayState.instance.camGame.shake(0.0025, 0.15); + moveToBack(); + } + + function playPunchHighAnim() + { + this.playAnimation('punchHigh' + doAlternate(), true, false); + moveToFront(); + } + + function playPunchLowAnim() + { + this.playAnimation('punchLow' + doAlternate(), true, false); + moveToFront(); + } + + function playSpinAnim() + { + this.playAnimation('hitSpin', true, false); + PlayState.instance.camGame.shake(0.0025, 0.15); + moveToBack(); + } } diff --git a/preload/scripts/characters/darnell.hxc b/preload/scripts/characters/darnell.hxc index fcac71fe3..c243689ac 100644 --- a/preload/scripts/characters/darnell.hxc +++ b/preload/scripts/characters/darnell.hxc @@ -5,109 +5,128 @@ import funkin.audio.FunkinSound; import funkin.Conductor; import flixel.FlxG; -class DarnellCharacter extends SparrowCharacter { - function new() { - super('darnell'); - } - - function onNoteHit(event:HitNoteScriptEvent) - { - if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) { - // Override the hit note animation. - switch(event.note.kind) { - case "weekend-1-lightcan": - holdTimer = 0; - playLightCanAnim(); - case "weekend-1-kickcan": - holdTimer = 0; - playKickCanAnim(); - case "weekend-1-kneecan": - holdTimer = 0; - playKneeCanAnim(); - default: - super.onNoteHit(event); - } - } - } - - function onNoteIncoming(event:NoteScriptEvent) { - if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) { - // Get how long until it's time to strum the note. - var msTilStrum = event.note.strumTime - Conductor.instance.songPosition; - - switch(event.note.kind) { - case "weekend-1-lightcan": - scheduleLightCanSound(msTilStrum - 65); - case "weekend-1-kickcan": - scheduleKickCanSound(msTilStrum - 50); - case "weekend-1-kneecan": - scheduleKneeCanSound(msTilStrum - 22); - default: - super.onNoteIncoming(event); - } - } - } - - /** - * Play the animation where Darnell kneels down to light the can. - */ - function playLightCanAnim() { - this.playAnimation('lightCan', true, true); - } - - var lightCanSound:FunkinSound; - var loadedLightCanSound:Bool = false; - /** - * Schedule the can-lighting sound to play in X ms - */ - function scheduleLightCanSound(timeToPlay:Float) { - if (!loadedLightCanSound) { - lightCanSound = FunkinSound.load(Paths.sound('Darnell_Lighter'), 1.0); - loadedLightCanSound = true; - } - - lightCanSound.play(true, -timeToPlay); - } - - /** - * Play the animation where Darnell kicks the can into the air. - */ - function playKickCanAnim() { - this.playAnimation('kickCan', true, true); - } - - var kickCanSound:FunkinSound; - var loadedKickCanSound:Bool = false; - /** - * Schedule the can-kicking sound to play in X ms - */ - function scheduleKickCanSound(timeToPlay:Float) { - if (!loadedKickCanSound) { - kickCanSound = FunkinSound.load(Paths.sound('Kick_Can_UP'), 1.0); - loadedKickCanSound = true; - } - - kickCanSound.play(true, -timeToPlay); - } - - /** - * Play the animation where Darnell knees the can in Pico's direction. - */ - function playKneeCanAnim() { - this.playAnimation('kneeCan', true, true); - } - - var kneeCanSound:FunkinSound; - var loadedKneeCanSound:Bool = false; - /** - * Schedule the can-kneeing sound to play in X ms - */ - function scheduleKneeCanSound(timeToPlay:Float) { - if (!loadedKneeCanSound) { - kneeCanSound = FunkinSound.load(Paths.sound('Kick_Can_FORWARD'), 1.0); - loadedKneeCanSound = true; - } - - kneeCanSound.play(true, -timeToPlay); - } +class DarnellCharacter extends SparrowCharacter +{ + function new() + { + super('darnell'); + } + + function onNoteHit(event:HitNoteScriptEvent) + { + if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) + { + // Override the hit note animation. + switch (event.note.kind) + { + case "weekend-1-lightcan": + holdTimer = 0; + playLightCanAnim(); + case "weekend-1-kickcan": + holdTimer = 0; + playKickCanAnim(); + case "weekend-1-kneecan": + holdTimer = 0; + playKneeCanAnim(); + default: + super.onNoteHit(event); + } + } + } + + function onNoteIncoming(event:NoteScriptEvent) + { + if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) + { + // Get how long until it's time to strum the note. + var msTilStrum = event.note.strumTime - Conductor.instance.songPosition; + + switch (event.note.kind) + { + case "weekend-1-lightcan": + scheduleLightCanSound(msTilStrum - 65); + case "weekend-1-kickcan": + scheduleKickCanSound(msTilStrum - 50); + case "weekend-1-kneecan": + scheduleKneeCanSound(msTilStrum - 22); + default: + super.onNoteIncoming(event); + } + } + } + + /** + * Play the animation where Darnell kneels down to light the can. + */ + function playLightCanAnim() + { + this.playAnimation('lightCan', true, true); + } + + var lightCanSound:FunkinSound; + var loadedLightCanSound:Bool = false; + + /** + * Schedule the can-lighting sound to play in X ms + */ + function scheduleLightCanSound(timeToPlay:Float) + { + if (!loadedLightCanSound) + { + lightCanSound = FunkinSound.load(Paths.sound('Darnell_Lighter'), 1.0); + loadedLightCanSound = true; + } + + lightCanSound.play(true, -timeToPlay); + } + + /** + * Play the animation where Darnell kicks the can into the air. + */ + function playKickCanAnim() + { + this.playAnimation('kickCan', true, true); + } + + var kickCanSound:FunkinSound; + var loadedKickCanSound:Bool = false; + + /** + * Schedule the can-kicking sound to play in X ms + */ + function scheduleKickCanSound(timeToPlay:Float) + { + if (!loadedKickCanSound) + { + kickCanSound = FunkinSound.load(Paths.sound('Kick_Can_UP'), 1.0); + loadedKickCanSound = true; + } + + kickCanSound.play(true, -timeToPlay); + } + + /** + * Play the animation where Darnell knees the can in Pico's direction. + */ + function playKneeCanAnim() + { + this.playAnimation('kneeCan', true, true); + } + + var kneeCanSound:FunkinSound; + var loadedKneeCanSound:Bool = false; + + /** + * Schedule the can-kneeing sound to play in X ms + */ + function scheduleKneeCanSound(timeToPlay:Float) + { + if (!loadedKneeCanSound) + { + kneeCanSound = FunkinSound.load(Paths.sound('Kick_Can_FORWARD'), 1.0); + loadedKneeCanSound = true; + } + + kneeCanSound.play(true, -timeToPlay); + } } diff --git a/preload/scripts/characters/gf-dark.hxc b/preload/scripts/characters/gf-dark.hxc index 4e49616fb..a7e30991c 100644 --- a/preload/scripts/characters/gf-dark.hxc +++ b/preload/scripts/characters/gf-dark.hxc @@ -8,40 +8,44 @@ import funkin.play.character.CharacterDataParser; import funkin.play.character.CharacterType; import funkin.play.PlayState; -class GirlfriendDarkCharacter extends SparrowCharacter { - function new() { - super('gf-dark'); - } +class GirlfriendDarkCharacter extends SparrowCharacter +{ + function new() + { + super('gf-dark'); + } var normalChar:BaseCharacter; - override function set_alpha(val:Float):Float{ - super.set_alpha(val); - if(val != 1) - normalChar.alpha = 1; - else - normalChar.alpha = 0; + override function set_alpha(val:Float):Float + { + super.set_alpha(val); + if (val != 1) normalChar.alpha = 1; + else + normalChar.alpha = 0; return val; - } - - override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) { - super.playAnimation(name, restart, ignoreOther); - if(normalChar != null){ - normalChar.playAnimation(name, restart, ignoreOther); - normalChar.setPosition(this.x, this.y); - } - } - - function onCreate(event:ScriptEvent) { - super.onCreate(event); - normalChar = CharacterDataParser.fetchCharacter('gf'); + } + + override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) + { + super.playAnimation(name, restart, ignoreOther); + if (normalChar != null) + { + normalChar.playAnimation(name, restart, ignoreOther); + normalChar.setPosition(this.x, this.y); + } + } + + function onCreate(event:ScriptEvent) + { + super.onCreate(event); + normalChar = CharacterDataParser.fetchCharacter('gf'); normalChar.zIndex = 99; - normalChar.alpha = 0; + normalChar.alpha = 0; normalChar.flipX = false; - PlayState.instance.currentStage.add(normalChar); - PlayState.instance.currentStage.refresh(); // Apply z-index. - } - + PlayState.instance.currentStage.add(normalChar); + PlayState.instance.currentStage.refresh(); // Apply z-index. + } } diff --git a/preload/scripts/characters/gf.hxc b/preload/scripts/characters/gf.hxc index 311bf6ba8..36b501bc2 100644 --- a/preload/scripts/characters/gf.hxc +++ b/preload/scripts/characters/gf.hxc @@ -3,33 +3,38 @@ import funkin.play.character.CharacterType; import funkin.play.PlayState; import flixel.addons.effects.FlxTrail; -class GirlfriendCharacter extends SparrowCharacter { - function new() { - super('gf'); - } +class GirlfriendCharacter extends SparrowCharacter +{ + function new() + { + super('gf'); + } - override function onAdd() { - if (!debug && this.characterType == CharacterType.DAD) { + override function onAdd() + { + if (!debug && this.characterType == CharacterType.DAD) + { // If Girlfriend is the opponent, set her position to the stage's assigned Girlfriend position, // while maintaining her status as an opponent. This allows the Girlfriend character to use a shared // character file without weird offsets. - var pos:FlxPoint = PlayState.instance.currentStage.getGirlfriendPosition(); + var pos:FlxPoint = PlayState.instance.currentStage.getGirlfriendPosition(); - this.originalPosition.x = pos.x - this.characterOrigin.x; - this.originalPosition.y = pos.y - this.characterOrigin.y; + this.originalPosition.x = pos.x - this.characterOrigin.x; + this.originalPosition.y = pos.y - this.characterOrigin.y; - this.resetPosition(); - } - } + this.resetPosition(); + } + } - override function dance(force:Bool) { - // Fix animation glitches with Week 3. - // Wait for 'hairBlow' to play, preventing dancing from interrupting it. - if (!force && ['hairBlow'].contains(getCurrentAnimation())) return; - // Wait for 'hairFall' to finish, preventing dancing from interrupting it. - if (!force && ['hairFall'].contains(getCurrentAnimation()) && !isAnimationFinished()) return; + override function dance(force:Bool) + { + // Fix animation glitches with Week 3. + // Wait for 'hairBlow' to play, preventing dancing from interrupting it. + if (!force && ['hairBlow'].contains(getCurrentAnimation())) return; + // Wait for 'hairFall' to finish, preventing dancing from interrupting it. + if (!force && ['hairFall'].contains(getCurrentAnimation()) && !isAnimationFinished()) return; - super.dance(force); - } -} \ No newline at end of file + super.dance(force); + } +} diff --git a/preload/scripts/characters/nene-christmas.hxc b/preload/scripts/characters/nene-christmas.hxc index 99f0d9cd8..b49e831ee 100644 --- a/preload/scripts/characters/nene-christmas.hxc +++ b/preload/scripts/characters/nene-christmas.hxc @@ -10,343 +10,374 @@ import funkin.modding.base.ScriptedFlxSpriteGroup; import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.audio.visualize.ABotVis; -class NeneChristmasCharacter extends SparrowCharacter { - function new() { - super('nene-christmas'); - } - - var pupilState:Int = 0; - - var PUPIL_STATE_NORMAL = 0; - var PUPIL_STATE_LEFT = 1; - - var abot:FlxAtlasSprite; - var abotViz:ABotVis; - var stereoBG:FlxSprite; - var eyeWhites:FlxSprite; - var pupil:FlxAtlasSprite; - - function onCreate(event:ScriptEvent) { - super.onCreate(event); - - stereoBG = new FlxSprite(0, 0, Paths.image('characters/abot/stereoBG')); - - eyeWhites = new FunkinSprite().makeSolidColor(160, 60); - - pupil = new FlxAtlasSprite(0, 0, Paths.animateAtlas("characters/abot/systemEyes", "shared")); - pupil.x = this.x; - pupil.y = this.y; - pupil.zIndex = this.zIndex - 5; - - abot = ScriptedFlxAtlasSprite.init('ABotAtlasSprite', 0, 0); - abot.x = this.x; - abot.y = this.y; - abot.zIndex = this.zIndex - 1; - - abotViz = new ABotVis(FlxG.sound.music); - abotViz.x = this.x; - abotViz.y = this.y; - abotViz.zIndex = abot.zIndex + 1; - FlxG.debugger.track(abotViz); - } - - /** - * At this amount of life, Nene will raise her knife. - */ - var VULTURE_THRESHOLD = 0.25 * 2; - - /** - * Nene is in her default state. 'danceLeft' or 'danceRight' may be playing right now, - * or maybe her 'combo' or 'drop' animations are active. - * - * Transitions: - * If player health <= VULTURE_THRESHOLD, transition to STATE_PRE_RAISE. - */ - var STATE_DEFAULT = 0; - - /** - * Nene has recognized the player is at low health, - * but has to wait for the appropriate point in the animation to move on. - * - * Transitions: - * If player health > VULTURE_THRESHOLD, transition back to STATE_DEFAULT without changing animation. - * If current animation is combo or drop, transition when animation completes. - * If current animation is danceLeft, wait until frame 14 to transition to STATE_RAISE. - * If current animation is danceRight, wait until danceLeft starts. - */ - var STATE_PRE_RAISE = 1; - - /** - * Nene is raising her knife. - * When moving to this state, immediately play the 'raiseKnife' animation. - * - * Transitions: - * Once 'raiseKnife' animation completes, transition to STATE_READY. - */ - var STATE_RAISE = 2; - - /** - * Nene is holding her knife ready to strike. - * During this state, hold the animation on the first frame, and play it at random intervals. - * This makes the blink look less periodic. - * - * Transitions: - * If the player runs out of health, move to the GameOverSubState. No transition needed. - * If player health > VULTURE_THRESHOLD, transition to STATE_LOWER. - */ - var STATE_READY = 3; - - /** - * Nene is raising her knife. - * When moving to this state, immediately play the 'lowerKnife' animation. - * - * Transitions: - * Once 'lowerKnife' animation completes, transition to STATE_DEFAULT. - */ - var STATE_LOWER = 4; - - /** - * Nene's animations are tracked in a simple state machine. - * Given the current state and an incoming event, the state changes. - */ - var currentState:Int = STATE_DEFAULT; - - /** - * Nene blinks every X beats, with X being randomly generated each time. - * This keeps the animation from looking too periodic. - */ - var MIN_BLINK_DELAY:Int = 3; - var MAX_BLINK_DELAY:Int = 7; - var blinkCountdown:Int = MIN_BLINK_DELAY; - - function dance(forceRestart:Bool) { - - - if (abot != null) - { - abot.playAnimation(""); - abot.anim.curFrame = 1; // we start on this frame, since from Flash the symbol has a non-bumpin frame on frame 0 - } - - - // Then, perform the appropriate animation for the current state. - switch(currentState) { - case STATE_DEFAULT: - if (hasDanced) { - playAnimation('danceRight', forceRestart); - } else { - playAnimation('danceLeft', forceRestart); - } - hasDanced = !hasDanced; - case STATE_PRE_RAISE: - playAnimation('danceLeft', false); - hasDanced = false; - case STATE_READY: - if (blinkCountdown == 0) { - playAnimation('idleKnife', false); - blinkCountdown = FlxG.random.int(MIN_BLINK_DELAY, MAX_BLINK_DELAY); - } else { - blinkCountdown--; - } - default: - // In other states, don't interrupt the existing animation. - } - } - - var refershedLol:Bool = false; - - /** - * Called when the chart hits a song event. - */ - public override function onSongEvent(scriptEvent:SongEventScriptEvent) - { - super.onSongEvent(scriptEvent); - if (scriptEvent.eventData.eventKind == "FocusCamera") - { - var eventProps = scriptEvent.eventData.value; - switch (Std.parseInt(eventProps.char)) { - case 0: - movePupilsRight(); - case 1: - movePupilsLeft(); - default: - } - } - - } - - function movePupilsLeft():Void { - if (pupilState == PUPIL_STATE_LEFT) return; - pupil.playAnimation(''); - pupil.anim.curFrame = 0; - // pupilState = PUPIL_STATE_LEFT; - } - - function movePupilsRight():Void { - if (pupilState == PUPIL_STATE_NORMAL) return; - pupil.playAnimation(''); - pupil.anim.curFrame = 17; - // pupilState = PUPIL_STATE_NORMAL; - } - - function onUpdate(event:UpdateScriptEvent) { - super.onUpdate(event); - - // Set the visibility of ABot to match Nene's. - abot.visible = this.visible; - pupil.visible = this.visible; - eyeWhites.visible = this.visible; - stereoBG.visible = this.visible; - - if (pupil.anim.isPlaying) - { - switch (pupilState) - { - case PUPIL_STATE_NORMAL: - if (pupil.anim.curFrame >= 17) - { - pupilState = PUPIL_STATE_LEFT; - pupil.anim.pause(); - } - - case PUPIL_STATE_LEFT: - if (pupil.anim.curFrame >= 31) - { - pupilState = PUPIL_STATE_NORMAL; - pupil.anim.pause(); - } - - } - } - - // refreshes just for the zIndex shit! - if (!refershedLol) - { - abot.x = this.x - 100; - abot.y = this.y + 216; // 764 - 740 - abot.zIndex = this.zIndex - 10; - - PlayState.instance.currentStage.add(abot); - - abotViz.x = abot.x + 200; - abotViz.y = abot.y + 84; - abotViz.zIndex = abot.zIndex - 1; - PlayState.instance.currentStage.add(abotViz); - - - eyeWhites.x = abot.x + 40; - eyeWhites.y = abot.y + 250; - eyeWhites.zIndex = abot.zIndex - 10; - PlayState.instance.currentStage.add(eyeWhites); - - pupil.x = abot.x - 507; - pupil.y = abot.y - 492; - pupil.zIndex = eyeWhites.zIndex + 5; - PlayState.instance.currentStage.add(pupil); - - stereoBG.x = abot.x + 150; - stereoBG.y = abot.y + 30; - stereoBG.zIndex = abot.zIndex - 8; - PlayState.instance.currentStage.add(stereoBG); - - PlayState.instance.currentStage.refresh(); - refershedLol = true; - } - - if (shouldTransitionState()) { - transitionState(); - } - } - - public function onScriptEvent(event:ScriptEvent):Void { - if (event.type == "SONG_START") - { - abotViz.snd = FlxG.sound.music; - abotViz.initAnalyzer(); - } - } - - var animationFinished:Bool = false; - - function onAnimationFinished(name:String) { - super.onAnimationFinished(name); - - switch(currentState) { - case STATE_RAISE: - if (name == "raiseKnife") { - animationFinished = true; - transitionState(); - } - case STATE_LOWER: - if (name == "lowerKnife") { - animationFinished = true; - transitionState(); - } - default: - // Ignore. - } - } - - function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) { - super.onAnimationFrame(name, frameNumber, frameIndex); - // trace("NENE: onAnimationFrame(" + name + ", " + frameNumber + ", " + frameIndex + ")"); - - switch(currentState) { - case STATE_PRE_RAISE: - if (name == "danceLeft" && frameNumber == 13) { - // trace("NENE: Animation finished, transitioning to STATE_RAISE"); - animationFinished = true; - transitionState(); - } - default: - // Ignore. - } - } - - function shouldTransitionState():Bool { - return PlayState.instance.currentStage.getBoyfriend().characterId != "pico-blazin"; - } - - function transitionState() { - switch (currentState) { - case STATE_DEFAULT: - if (PlayState.instance.health <= VULTURE_THRESHOLD) { - // trace('NENE: Health is low, transitioning to STATE_PRE_RAISE'); - currentState = STATE_PRE_RAISE; - } else { - currentState = STATE_DEFAULT; - } - case STATE_PRE_RAISE: - if (PlayState.instance.health > VULTURE_THRESHOLD) { - // trace('NENE: Health went back up, transitioning to STATE_DEFAULT'); - currentState = STATE_DEFAULT; - } else if (animationFinished) { - // trace('NENE: Animation finished, transitioning to STATE_RAISE'); - currentState = STATE_RAISE; - playAnimation('raiseKnife'); - animationFinished = false; - } - case STATE_RAISE: - if (animationFinished) { - // trace('NENE: Animation finished, transitioning to STATE_READY'); - currentState = STATE_READY; - animationFinished = false; - } - case STATE_READY: - if (PlayState.instance.health > VULTURE_THRESHOLD) { - // trace('NENE: Health went back up, transitioning to STATE_LOWER'); - currentState = STATE_LOWER; - playAnimation('lowerKnife'); - } - case STATE_LOWER: - if (animationFinished) { - // trace('NENE: Animation finished, transitioning to STATE_DEFAULT'); - currentState = STATE_DEFAULT; - animationFinished = false; - } - default: - // trace('UKNOWN STATE ' + currentState); - currentState = STATE_DEFAULT; - } - } +class NeneChristmasCharacter extends SparrowCharacter +{ + function new() + { + super('nene-christmas'); + } + + var pupilState:Int = 0; + + var PUPIL_STATE_NORMAL = 0; + var PUPIL_STATE_LEFT = 1; + + var abot:FlxAtlasSprite; + var abotViz:ABotVis; + var stereoBG:FlxSprite; + var eyeWhites:FlxSprite; + var pupil:FlxAtlasSprite; + + function onCreate(event:ScriptEvent) + { + super.onCreate(event); + + stereoBG = new FlxSprite(0, 0, Paths.image('characters/abot/stereoBG')); + + eyeWhites = new FunkinSprite().makeSolidColor(160, 60); + + pupil = new FlxAtlasSprite(0, 0, Paths.animateAtlas("characters/abot/systemEyes", "shared")); + pupil.x = this.x; + pupil.y = this.y; + pupil.zIndex = this.zIndex - 5; + + abot = ScriptedFlxAtlasSprite.init('ABotAtlasSprite', 0, 0); + abot.x = this.x; + abot.y = this.y; + abot.zIndex = this.zIndex - 1; + + abotViz = new ABotVis(FlxG.sound.music); + abotViz.x = this.x; + abotViz.y = this.y; + abotViz.zIndex = abot.zIndex + 1; + FlxG.debugger.track(abotViz); + } + + /** + * At this amount of life, Nene will raise her knife. + */ + var VULTURE_THRESHOLD = 0.25 * 2; + + /** + * Nene is in her default state. 'danceLeft' or 'danceRight' may be playing right now, + * or maybe her 'combo' or 'drop' animations are active. + * + * Transitions: + * If player health <= VULTURE_THRESHOLD, transition to STATE_PRE_RAISE. + */ + var STATE_DEFAULT = 0; + + /** + * Nene has recognized the player is at low health, + * but has to wait for the appropriate point in the animation to move on. + * + * Transitions: + * If player health > VULTURE_THRESHOLD, transition back to STATE_DEFAULT without changing animation. + * If current animation is combo or drop, transition when animation completes. + * If current animation is danceLeft, wait until frame 14 to transition to STATE_RAISE. + * If current animation is danceRight, wait until danceLeft starts. + */ + var STATE_PRE_RAISE = 1; + + /** + * Nene is raising her knife. + * When moving to this state, immediately play the 'raiseKnife' animation. + * + * Transitions: + * Once 'raiseKnife' animation completes, transition to STATE_READY. + */ + var STATE_RAISE = 2; + + /** + * Nene is holding her knife ready to strike. + * During this state, hold the animation on the first frame, and play it at random intervals. + * This makes the blink look less periodic. + * + * Transitions: + * If the player runs out of health, move to the GameOverSubState. No transition needed. + * If player health > VULTURE_THRESHOLD, transition to STATE_LOWER. + */ + var STATE_READY = 3; + + /** + * Nene is raising her knife. + * When moving to this state, immediately play the 'lowerKnife' animation. + * + * Transitions: + * Once 'lowerKnife' animation completes, transition to STATE_DEFAULT. + */ + var STATE_LOWER = 4; + + /** + * Nene's animations are tracked in a simple state machine. + * Given the current state and an incoming event, the state changes. + */ + var currentState:Int = STATE_DEFAULT; + + /** + * Nene blinks every X beats, with X being randomly generated each time. + * This keeps the animation from looking too periodic. + */ + var MIN_BLINK_DELAY:Int = 3; + + var MAX_BLINK_DELAY:Int = 7; + var blinkCountdown:Int = MIN_BLINK_DELAY; + + function dance(forceRestart:Bool) + { + if (abot != null) + { + abot.playAnimation(""); + abot.anim.curFrame = 1; // we start on this frame, since from Flash the symbol has a non-bumpin frame on frame 0 + } + + // Then, perform the appropriate animation for the current state. + switch (currentState) + { + case STATE_DEFAULT: + if (hasDanced) + { + playAnimation('danceRight', forceRestart); + } + else + { + playAnimation('danceLeft', forceRestart); + } + hasDanced = !hasDanced; + case STATE_PRE_RAISE: + playAnimation('danceLeft', false); + hasDanced = false; + case STATE_READY: + if (blinkCountdown == 0) + { + playAnimation('idleKnife', false); + blinkCountdown = FlxG.random.int(MIN_BLINK_DELAY, MAX_BLINK_DELAY); + } + else + { + blinkCountdown--; + } + default: + // In other states, don't interrupt the existing animation. + } + } + + var refershedLol:Bool = false; + + /** + * Called when the chart hits a song event. + */ + public override function onSongEvent(scriptEvent:SongEventScriptEvent) + { + super.onSongEvent(scriptEvent); + if (scriptEvent.eventData.eventKind == "FocusCamera") + { + var eventProps = scriptEvent.eventData.value; + switch (Std.parseInt(eventProps.char)) + { + case 0: + movePupilsRight(); + case 1: + movePupilsLeft(); + default: + } + } + } + + function movePupilsLeft():Void + { + if (pupilState == PUPIL_STATE_LEFT) return; + pupil.playAnimation(''); + pupil.anim.curFrame = 0; + // pupilState = PUPIL_STATE_LEFT; + } + + function movePupilsRight():Void + { + if (pupilState == PUPIL_STATE_NORMAL) return; + pupil.playAnimation(''); + pupil.anim.curFrame = 17; + // pupilState = PUPIL_STATE_NORMAL; + } + + function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); + + // Set the visibility of ABot to match Nene's. + abot.visible = this.visible; + pupil.visible = this.visible; + eyeWhites.visible = this.visible; + stereoBG.visible = this.visible; + + if (pupil.anim.isPlaying) + { + switch (pupilState) + { + case PUPIL_STATE_NORMAL: + if (pupil.anim.curFrame >= 17) + { + pupilState = PUPIL_STATE_LEFT; + pupil.anim.pause(); + } + + case PUPIL_STATE_LEFT: + if (pupil.anim.curFrame >= 31) + { + pupilState = PUPIL_STATE_NORMAL; + pupil.anim.pause(); + } + } + } + + // refreshes just for the zIndex shit! + if (!refershedLol) + { + abot.x = this.x - 100; + abot.y = this.y + 216; // 764 - 740 + abot.zIndex = this.zIndex - 10; + + PlayState.instance.currentStage.add(abot); + + abotViz.x = abot.x + 200; + abotViz.y = abot.y + 84; + abotViz.zIndex = abot.zIndex - 1; + PlayState.instance.currentStage.add(abotViz); + + eyeWhites.x = abot.x + 40; + eyeWhites.y = abot.y + 250; + eyeWhites.zIndex = abot.zIndex - 10; + PlayState.instance.currentStage.add(eyeWhites); + + pupil.x = abot.x - 507; + pupil.y = abot.y - 492; + pupil.zIndex = eyeWhites.zIndex + 5; + PlayState.instance.currentStage.add(pupil); + + stereoBG.x = abot.x + 150; + stereoBG.y = abot.y + 30; + stereoBG.zIndex = abot.zIndex - 8; + PlayState.instance.currentStage.add(stereoBG); + + PlayState.instance.currentStage.refresh(); + refershedLol = true; + } + + if (shouldTransitionState()) + { + transitionState(); + } + } + + public function onScriptEvent(event:ScriptEvent):Void + { + if (event.type == "SONG_START") + { + abotViz.snd = FlxG.sound.music; + abotViz.initAnalyzer(); + } + } + + var animationFinished:Bool = false; + + function onAnimationFinished(name:String) + { + super.onAnimationFinished(name); + + switch (currentState) + { + case STATE_RAISE: + if (name == "raiseKnife") + { + animationFinished = true; + transitionState(); + } + case STATE_LOWER: + if (name == "lowerKnife") + { + animationFinished = true; + transitionState(); + } + default: + // Ignore. + } + } + + function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) + { + super.onAnimationFrame(name, frameNumber, frameIndex); + // trace("NENE: onAnimationFrame(" + name + ", " + frameNumber + ", " + frameIndex + ")"); + + switch (currentState) + { + case STATE_PRE_RAISE: + if (name == "danceLeft" && frameNumber == 13) + { + // trace("NENE: Animation finished, transitioning to STATE_RAISE"); + animationFinished = true; + transitionState(); + } + default: + // Ignore. + } + } + + function shouldTransitionState():Bool + { + return PlayState.instance.currentStage.getBoyfriend().characterId != "pico-blazin"; + } + + function transitionState() + { + switch (currentState) + { + case STATE_DEFAULT: + if (PlayState.instance.health <= VULTURE_THRESHOLD) + { + // trace('NENE: Health is low, transitioning to STATE_PRE_RAISE'); + currentState = STATE_PRE_RAISE; + } + else + { + currentState = STATE_DEFAULT; + } + case STATE_PRE_RAISE: + if (PlayState.instance.health > VULTURE_THRESHOLD) + { + // trace('NENE: Health went back up, transitioning to STATE_DEFAULT'); + currentState = STATE_DEFAULT; + } + else if (animationFinished) + { + // trace('NENE: Animation finished, transitioning to STATE_RAISE'); + currentState = STATE_RAISE; + playAnimation('raiseKnife'); + animationFinished = false; + } + case STATE_RAISE: + if (animationFinished) + { + // trace('NENE: Animation finished, transitioning to STATE_READY'); + currentState = STATE_READY; + animationFinished = false; + } + case STATE_READY: + if (PlayState.instance.health > VULTURE_THRESHOLD) + { + // trace('NENE: Health went back up, transitioning to STATE_LOWER'); + currentState = STATE_LOWER; + playAnimation('lowerKnife'); + } + case STATE_LOWER: + if (animationFinished) + { + // trace('NENE: Animation finished, transitioning to STATE_DEFAULT'); + currentState = STATE_DEFAULT; + animationFinished = false; + } + default: + // trace('UKNOWN STATE ' + currentState); + currentState = STATE_DEFAULT; + } + } } diff --git a/preload/scripts/characters/nene-dark.hxc b/preload/scripts/characters/nene-dark.hxc index 8ca68c9a3..709e2d522 100644 --- a/preload/scripts/characters/nene-dark.hxc +++ b/preload/scripts/characters/nene-dark.hxc @@ -17,422 +17,462 @@ import openfl.display.BitmapData; import funkin.util.FlxColorUtil; import funkin.graphics.shaders.AdjustColorShader; -class NeneDarkCharacter extends SparrowCharacter { - function new() { - super('nene-dark'); - } +class NeneDarkCharacter extends SparrowCharacter +{ + function new() + { + super('nene-dark'); + } - var pupilState:Int = 0; + var pupilState:Int = 0; - var PUPIL_STATE_NORMAL = 0; - var PUPIL_STATE_LEFT = 1; + var PUPIL_STATE_NORMAL = 0; + var PUPIL_STATE_LEFT = 1; - var abot:FlxAtlasSprite; - var abotViz:ABotVis; - var stereoBG:FlxSprite; - var eyeWhites:FlxSprite; - var pupil:FlxAtlasSprite; + var abot:FlxAtlasSprite; + var abotViz:ABotVis; + var stereoBG:FlxSprite; + var eyeWhites:FlxSprite; + var pupil:FlxAtlasSprite; - var testShader:TextureSwap; - - var normalChar:BaseCharacter; + var testShader:TextureSwap; + var normalChar:BaseCharacter; var vizAdjustColor:AdjustColorShader; - override function set_alpha(val:Float):Float{ - super.set_alpha(val); - testShader.amount = val; - if(val != 1) - normalChar.alpha = 1; - else - normalChar.alpha = 0; + override function set_alpha(val:Float):Float + { + super.set_alpha(val); + testShader.amount = val; + if (val != 1) normalChar.alpha = 1; + else + normalChar.alpha = 0; - eyeWhites.color = FlxColorUtil.interpolate(0xFFFFFFFF, 0xFF6F96CE, val); + eyeWhites.color = FlxColorUtil.interpolate(0xFFFFFFFF, 0xFF6F96CE, val); return val; - } + } - function onCreate(event:ScriptEvent) { - super.onCreate(event); + function onCreate(event:ScriptEvent) + { + super.onCreate(event); - stereoBG = new FlxSprite(0, 0, Paths.image('characters/abot/stereoBG')); - stereoBG.color = 0xFF616785; + stereoBG = new FlxSprite(0, 0, Paths.image('characters/abot/stereoBG')); + stereoBG.color = 0xFF616785; - eyeWhites = new FunkinSprite().makeSolidColor(160, 60); + eyeWhites = new FunkinSprite().makeSolidColor(160, 60); - pupil = new FlxAtlasSprite(0, 0, Paths.animateAtlas("characters/abot/systemEyes", "shared")); - pupil.x = this.x; - pupil.y = this.y; - pupil.zIndex = this.zIndex - 5; + pupil = new FlxAtlasSprite(0, 0, Paths.animateAtlas("characters/abot/systemEyes", "shared")); + pupil.x = this.x; + pupil.y = this.y; + pupil.zIndex = this.zIndex - 5; - testShader = new TextureSwap(); - testShader.swappedImage = BitmapData.fromFile('assets/shared/images/characters/abot/dark/abotSystem/spritemap1.png'); - abot = ScriptedFlxAtlasSprite.init('ABotAtlasSprite', 0, 0); - abot.x = this.x; - abot.y = this.y; - abot.zIndex = this.zIndex - 1; - abot.shader = testShader; + testShader = new TextureSwap(); + testShader.swappedImage = BitmapData.fromFile('assets/shared/images/characters/abot/dark/abotSystem/spritemap1.png'); + abot = ScriptedFlxAtlasSprite.init('ABotAtlasSprite', 0, 0); + abot.x = this.x; + abot.y = this.y; + abot.zIndex = this.zIndex - 1; + abot.shader = testShader; - abotViz = new ABotVis(FlxG.sound.music); - abotViz.x = this.x; - abotViz.y = this.y; - abotViz.zIndex = abot.zIndex + 1; - FlxG.debugger.track(abotViz); + abotViz = new ABotVis(FlxG.sound.music); + abotViz.x = this.x; + abotViz.y = this.y; + abotViz.zIndex = abot.zIndex + 1; + FlxG.debugger.track(abotViz); - vizAdjustColor = new AdjustColorShader(); + vizAdjustColor = new AdjustColorShader(); vizAdjustColor.brightness = -12; vizAdjustColor.hue = -26; vizAdjustColor.contrast = 0; - vizAdjustColor.saturation = -45; + vizAdjustColor.saturation = -45; - for(spr in abotViz.members){ - spr.shader = vizAdjustColor; - } + for (spr in abotViz.members) + { + spr.shader = vizAdjustColor; + } - normalChar = CharacterDataParser.fetchCharacter('nene'); + normalChar = CharacterDataParser.fetchCharacter('nene'); normalChar.zIndex = this.zIndex - 1; - normalChar.alpha = 0; + normalChar.alpha = 0; normalChar.flipX = false; - } - - /** - * At this amount of life, Nene will raise her knife. - */ - var VULTURE_THRESHOLD = 0.25 * 2; - - /** - * Nene is in her default state. 'danceLeft' or 'danceRight' may be playing right now, - * or maybe her 'combo' or 'drop' animations are active. - * - * Transitions: - * If player health <= VULTURE_THRESHOLD, transition to STATE_PRE_RAISE. - */ - var STATE_DEFAULT = 0; - - /** - * Nene has recognized the player is at low health, - * but has to wait for the appropriate point in the animation to move on. - * - * Transitions: - * If player health > VULTURE_THRESHOLD, transition back to STATE_DEFAULT without changing animation. - * If current animation is combo or drop, transition when animation completes. - * If current animation is danceLeft, wait until frame 14 to transition to STATE_RAISE. - * If current animation is danceRight, wait until danceLeft starts. - */ - var STATE_PRE_RAISE = 1; - - /** - * Nene is raising her knife. - * When moving to this state, immediately play the 'raiseKnife' animation. - * - * Transitions: - * Once 'raiseKnife' animation completes, transition to STATE_READY. - */ - var STATE_RAISE = 2; - - /** - * Nene is holding her knife ready to strike. - * During this state, hold the animation on the first frame, and play it at random intervals. - * This makes the blink look less periodic. - * - * Transitions: - * If the player runs out of health, move to the GameOverSubState. No transition needed. - * If player health > VULTURE_THRESHOLD, transition to STATE_LOWER. - */ - var STATE_READY = 3; - - /** - * Nene is raising her knife. - * When moving to this state, immediately play the 'lowerKnife' animation. - * - * Transitions: - * Once 'lowerKnife' animation completes, transition to STATE_DEFAULT. - */ - var STATE_LOWER = 4; - - /** - * Nene's animations are tracked in a simple state machine. - * Given the current state and an incoming event, the state changes. - */ - var currentState:Int = STATE_DEFAULT; - - /** - * Nene blinks every X beats, with X being randomly generated each time. - * This keeps the animation from looking too periodic. - */ - var MIN_BLINK_DELAY:Int = 3; - var MAX_BLINK_DELAY:Int = 7; - var blinkCountdown:Int = MIN_BLINK_DELAY; - - override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) { - super.playAnimation(name, restart, ignoreOther); - if(normalChar != null){ - normalChar.playAnimation(name, restart, ignoreOther); - normalChar.setPosition(this.x, this.y); + } + + /** + * At this amount of life, Nene will raise her knife. + */ + var VULTURE_THRESHOLD = 0.25 * 2; + + /** + * Nene is in her default state. 'danceLeft' or 'danceRight' may be playing right now, + * or maybe her 'combo' or 'drop' animations are active. + * + * Transitions: + * If player health <= VULTURE_THRESHOLD, transition to STATE_PRE_RAISE. + */ + var STATE_DEFAULT = 0; + + /** + * Nene has recognized the player is at low health, + * but has to wait for the appropriate point in the animation to move on. + * + * Transitions: + * If player health > VULTURE_THRESHOLD, transition back to STATE_DEFAULT without changing animation. + * If current animation is combo or drop, transition when animation completes. + * If current animation is danceLeft, wait until frame 14 to transition to STATE_RAISE. + * If current animation is danceRight, wait until danceLeft starts. + */ + var STATE_PRE_RAISE = 1; + + /** + * Nene is raising her knife. + * When moving to this state, immediately play the 'raiseKnife' animation. + * + * Transitions: + * Once 'raiseKnife' animation completes, transition to STATE_READY. + */ + var STATE_RAISE = 2; + + /** + * Nene is holding her knife ready to strike. + * During this state, hold the animation on the first frame, and play it at random intervals. + * This makes the blink look less periodic. + * + * Transitions: + * If the player runs out of health, move to the GameOverSubState. No transition needed. + * If player health > VULTURE_THRESHOLD, transition to STATE_LOWER. + */ + var STATE_READY = 3; + + /** + * Nene is raising her knife. + * When moving to this state, immediately play the 'lowerKnife' animation. + * + * Transitions: + * Once 'lowerKnife' animation completes, transition to STATE_DEFAULT. + */ + var STATE_LOWER = 4; + + /** + * Nene's animations are tracked in a simple state machine. + * Given the current state and an incoming event, the state changes. + */ + var currentState:Int = STATE_DEFAULT; + + /** + * Nene blinks every X beats, with X being randomly generated each time. + * This keeps the animation from looking too periodic. + */ + var MIN_BLINK_DELAY:Int = 3; + + var MAX_BLINK_DELAY:Int = 7; + var blinkCountdown:Int = MIN_BLINK_DELAY; + + override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) + { + super.playAnimation(name, restart, ignoreOther); + if (normalChar != null) + { + normalChar.playAnimation(name, restart, ignoreOther); + normalChar.setPosition(this.x, this.y); + } + } + + function dance(forceRestart:Bool) + { + if (abot != null) + { + abot.playAnimation(""); + abot.anim.curFrame = 1; // we start on this frame, since from Flash the symbol has a non-bumpin frame on frame 0 + } + + // Then, perform the appropriate animation for the current state. + switch (currentState) + { + case STATE_DEFAULT: + if (hasDanced) + { + playAnimation('danceRight', forceRestart); + } + else + { + playAnimation('danceLeft', forceRestart); + } + hasDanced = !hasDanced; + case STATE_PRE_RAISE: + playAnimation('danceLeft', false); + hasDanced = false; + case STATE_READY: + if (blinkCountdown == 0) + { + playAnimation('idleKnife', false); + blinkCountdown = FlxG.random.int(MIN_BLINK_DELAY, MAX_BLINK_DELAY); + } + else + { + blinkCountdown--; + } + default: + // In other states, don't interrupt the existing animation. + } + } + + var refershedLol:Bool = false; + + /** + * Called when the chart hits a song event. + */ + public override function onSongEvent(scriptEvent:SongEventScriptEvent) + { + super.onSongEvent(scriptEvent); + if (scriptEvent.eventData.eventKind == "FocusCamera") + { + var eventProps = scriptEvent.eventData.value; + switch (Std.parseInt(eventProps.char)) + { + case 0: + movePupilsRight(); + case 1: + movePupilsLeft(); + default: + } + } + } + + function movePupilsLeft():Void + { + if (pupilState == PUPIL_STATE_LEFT) return; + trace('Move pupils left'); + pupil.playAnimation(''); + pupil.anim.curFrame = 0; + // pupilState = PUPIL_STATE_LEFT; + } + + function movePupilsRight():Void + { + if (pupilState == PUPIL_STATE_NORMAL) return; + trace('Move pupils right'); + pupil.playAnimation(''); + pupil.anim.curFrame = 17; + // pupilState = PUPIL_STATE_NORMAL; + } + + function moveByNoteKind(kind:String) + { + // Force ABot to look where the action is happening. + switch (event.note.kind) + { + case "weekend-1-lightcan": + movePupilsLeft(); + case "weekend-1-kickcan": + // movePupilsLeft(); + case "weekend-1-kneecan": + // movePupilsLeft(); + case "weekend-1-cockgun": + movePupilsRight(); + case "weekend-1-firegun": + // movePupilsRight(); + default: // Nothing + } + } + + function onNoteHit(event:HitNoteScriptEvent) + { + super.onNoteHit(event); + moveByNoteKind(event.note.kind); + } + + function onNoteMiss(event:NoteScriptEvent) + { + super.onNoteMiss(event); + moveByNoteKind(event.note.kind); + } + + function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); + + // Set the visibility of ABot to match Nene's. + abot.visible = this.visible; + pupil.visible = this.visible; + eyeWhites.visible = this.visible; + stereoBG.visible = this.visible; + + if (pupil?.anim?.isPlaying) + { + switch (pupilState) + { + case PUPIL_STATE_NORMAL: + if (pupil.anim.curFrame >= 17) + { + trace('Done moving pupils left'); + pupilState = PUPIL_STATE_LEFT; + pupil.anim.pause(); + } + + case PUPIL_STATE_LEFT: + if (pupil.anim.curFrame >= 30) + { + trace('Done moving pupils right'); + pupilState = PUPIL_STATE_NORMAL; + pupil.anim.pause(); + } } - } - - function dance(forceRestart:Bool) { - if (abot != null) - { - abot.playAnimation(""); - abot.anim.curFrame = 1; // we start on this frame, since from Flash the symbol has a non-bumpin frame on frame 0 - } - - // Then, perform the appropriate animation for the current state. - switch(currentState) { - case STATE_DEFAULT: - if (hasDanced) { - playAnimation('danceRight', forceRestart); - } else { - playAnimation('danceLeft', forceRestart); - } - hasDanced = !hasDanced; - case STATE_PRE_RAISE: - playAnimation('danceLeft', false); - hasDanced = false; - case STATE_READY: - if (blinkCountdown == 0) { - playAnimation('idleKnife', false); - blinkCountdown = FlxG.random.int(MIN_BLINK_DELAY, MAX_BLINK_DELAY); - } else { - blinkCountdown--; - } - default: - // In other states, don't interrupt the existing animation. - } - } - - var refershedLol:Bool = false; - - /** - * Called when the chart hits a song event. - */ - public override function onSongEvent(scriptEvent:SongEventScriptEvent) - { - super.onSongEvent(scriptEvent); - if (scriptEvent.eventData.eventKind == "FocusCamera") - { - var eventProps = scriptEvent.eventData.value; - switch (Std.parseInt(eventProps.char)) { - case 0: - movePupilsRight(); - case 1: - movePupilsLeft(); - default: - } - } - - } - - function movePupilsLeft():Void { - if (pupilState == PUPIL_STATE_LEFT) return; - trace('Move pupils left'); - pupil.playAnimation(''); - pupil.anim.curFrame = 0; - // pupilState = PUPIL_STATE_LEFT; - } - - function movePupilsRight():Void { - if (pupilState == PUPIL_STATE_NORMAL) return; - trace('Move pupils right'); - pupil.playAnimation(''); - pupil.anim.curFrame = 17; - // pupilState = PUPIL_STATE_NORMAL; - } - - function moveByNoteKind(kind:String) { - // Force ABot to look where the action is happening. - switch(event.note.kind) { - case "weekend-1-lightcan": - movePupilsLeft(); - case "weekend-1-kickcan": - // movePupilsLeft(); - case "weekend-1-kneecan": - // movePupilsLeft(); - case "weekend-1-cockgun": - movePupilsRight(); - case "weekend-1-firegun": - // movePupilsRight(); - default: // Nothing - } - } - - function onNoteHit(event:HitNoteScriptEvent) - { - super.onNoteHit(event); - moveByNoteKind(event.note.kind); - } - - function onNoteMiss(event:NoteScriptEvent) - { - super.onNoteMiss(event); - moveByNoteKind(event.note.kind); - } - - function onUpdate(event:UpdateScriptEvent) { - super.onUpdate(event); - - // Set the visibility of ABot to match Nene's. - abot.visible = this.visible; - pupil.visible = this.visible; - eyeWhites.visible = this.visible; - stereoBG.visible = this.visible; - - if (pupil?.anim?.isPlaying) - { - switch (pupilState) - { - case PUPIL_STATE_NORMAL: - if (pupil.anim.curFrame >= 17) - { - trace('Done moving pupils left'); - pupilState = PUPIL_STATE_LEFT; - pupil.anim.pause(); - } - - case PUPIL_STATE_LEFT: - if (pupil.anim.curFrame >= 30) - { - trace('Done moving pupils right'); - pupilState = PUPIL_STATE_NORMAL; - pupil.anim.pause(); - } - } - } - - // refreshes just for the zIndex shit! - if (!refershedLol) - { - abot.x = this.x - 100; - abot.y = this.y + 216; // 764 - 740 - abot.zIndex = this.zIndex - 10; - - PlayState.instance.currentStage.add(abot); - - abotViz.x = abot.x + 200; - abotViz.y = abot.y + 84; - abotViz.zIndex = abot.zIndex - 1; - PlayState.instance.currentStage.add(abotViz); - - eyeWhites.x = abot.x + 40; - eyeWhites.y = abot.y + 250; - eyeWhites.zIndex = abot.zIndex - 10; - PlayState.instance.currentStage.add(eyeWhites); - - pupil.x = abot.x - 507; - pupil.y = abot.y - 492; - pupil.zIndex = eyeWhites.zIndex + 5; - PlayState.instance.currentStage.add(pupil); - - stereoBG.x = abot.x + 150; - stereoBG.y = abot.y + 30; - stereoBG.zIndex = abot.zIndex - 8; - PlayState.instance.currentStage.add(stereoBG); - - normalChar.zIndex = this.zIndex - 3; - normalChar.flipX = false; - - PlayState.instance.currentStage.add(normalChar); - - PlayState.instance.currentStage.refresh(); - refershedLol = true; - } - - if (shouldTransitionState()) { - transitionState(); - } - } - - public function onScriptEvent(event:ScriptEvent):Void { - if (event.type == "SONG_START") - { - abotViz.snd = FlxG.sound.music; - abotViz.initAnalyzer(); - } - } - - var animationFinished:Bool = false; - - function onAnimationFinished(name:String) { - super.onAnimationFinished(name); - - switch(currentState) { - case STATE_RAISE: - if (name == "raiseKnife") { - animationFinished = true; - transitionState(); - } - case STATE_LOWER: - if (name == "lowerKnife") { - animationFinished = true; - transitionState(); - } - default: - // Ignore. - } - } - - function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) { - super.onAnimationFrame(name, frameNumber, frameIndex); - - switch(currentState) { - case STATE_PRE_RAISE: - if (name == "danceLeft" && frameNumber == 13) { - animationFinished = true; - transitionState(); - } - default: - // Ignore. - } - } - - function shouldTransitionState():Bool { - return PlayState.instance.currentStage.getBoyfriend().characterId != "pico-blazin"; - } - - function transitionState() { - switch (currentState) { - case STATE_DEFAULT: - if (PlayState.instance.health <= VULTURE_THRESHOLD) { - // trace('NENE: Health is low, transitioning to STATE_PRE_RAISE'); - currentState = STATE_PRE_RAISE; - } else { - currentState = STATE_DEFAULT; - } - case STATE_PRE_RAISE: - if (PlayState.instance.health > VULTURE_THRESHOLD) { - // trace('NENE: Health went back up, transitioning to STATE_DEFAULT'); - currentState = STATE_DEFAULT; - } else if (animationFinished) { - // trace('NENE: Animation finished, transitioning to STATE_RAISE'); - currentState = STATE_RAISE; - playAnimation('raiseKnife'); - animationFinished = false; - } - case STATE_RAISE: - if (animationFinished) { - // trace('NENE: Animation finished, transitioning to STATE_READY'); - currentState = STATE_READY; - animationFinished = false; - } - case STATE_READY: - if (PlayState.instance.health > VULTURE_THRESHOLD) { - // trace('NENE: Health went back up, transitioning to STATE_LOWER'); - currentState = STATE_LOWER; - playAnimation('lowerKnife'); - } - case STATE_LOWER: - if (animationFinished) { - // trace('NENE: Animation finished, transitioning to STATE_DEFAULT'); - currentState = STATE_DEFAULT; - animationFinished = false; - } - default: - // trace('UKNOWN STATE ' + currentState); - currentState = STATE_DEFAULT; - } - } + } + + // refreshes just for the zIndex shit! + if (!refershedLol) + { + abot.x = this.x - 100; + abot.y = this.y + 216; // 764 - 740 + abot.zIndex = this.zIndex - 10; + + PlayState.instance.currentStage.add(abot); + + abotViz.x = abot.x + 200; + abotViz.y = abot.y + 84; + abotViz.zIndex = abot.zIndex - 1; + PlayState.instance.currentStage.add(abotViz); + + eyeWhites.x = abot.x + 40; + eyeWhites.y = abot.y + 250; + eyeWhites.zIndex = abot.zIndex - 10; + PlayState.instance.currentStage.add(eyeWhites); + + pupil.x = abot.x - 507; + pupil.y = abot.y - 492; + pupil.zIndex = eyeWhites.zIndex + 5; + PlayState.instance.currentStage.add(pupil); + + stereoBG.x = abot.x + 150; + stereoBG.y = abot.y + 30; + stereoBG.zIndex = abot.zIndex - 8; + PlayState.instance.currentStage.add(stereoBG); + + normalChar.zIndex = this.zIndex - 3; + normalChar.flipX = false; + + PlayState.instance.currentStage.add(normalChar); + + PlayState.instance.currentStage.refresh(); + refershedLol = true; + } + + if (shouldTransitionState()) + { + transitionState(); + } + } + + public function onScriptEvent(event:ScriptEvent):Void + { + if (event.type == "SONG_START") + { + abotViz.snd = FlxG.sound.music; + abotViz.initAnalyzer(); + } + } + + var animationFinished:Bool = false; + + function onAnimationFinished(name:String) + { + super.onAnimationFinished(name); + + switch (currentState) + { + case STATE_RAISE: + if (name == "raiseKnife") + { + animationFinished = true; + transitionState(); + } + case STATE_LOWER: + if (name == "lowerKnife") + { + animationFinished = true; + transitionState(); + } + default: + // Ignore. + } + } + + function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) + { + super.onAnimationFrame(name, frameNumber, frameIndex); + + switch (currentState) + { + case STATE_PRE_RAISE: + if (name == "danceLeft" && frameNumber == 13) + { + animationFinished = true; + transitionState(); + } + default: + // Ignore. + } + } + + function shouldTransitionState():Bool + { + return PlayState.instance.currentStage.getBoyfriend().characterId != "pico-blazin"; + } + + function transitionState() + { + switch (currentState) + { + case STATE_DEFAULT: + if (PlayState.instance.health <= VULTURE_THRESHOLD) + { + // trace('NENE: Health is low, transitioning to STATE_PRE_RAISE'); + currentState = STATE_PRE_RAISE; + } + else + { + currentState = STATE_DEFAULT; + } + case STATE_PRE_RAISE: + if (PlayState.instance.health > VULTURE_THRESHOLD) + { + // trace('NENE: Health went back up, transitioning to STATE_DEFAULT'); + currentState = STATE_DEFAULT; + } + else if (animationFinished) + { + // trace('NENE: Animation finished, transitioning to STATE_RAISE'); + currentState = STATE_RAISE; + playAnimation('raiseKnife'); + animationFinished = false; + } + case STATE_RAISE: + if (animationFinished) + { + // trace('NENE: Animation finished, transitioning to STATE_READY'); + currentState = STATE_READY; + animationFinished = false; + } + case STATE_READY: + if (PlayState.instance.health > VULTURE_THRESHOLD) + { + // trace('NENE: Health went back up, transitioning to STATE_LOWER'); + currentState = STATE_LOWER; + playAnimation('lowerKnife'); + } + case STATE_LOWER: + if (animationFinished) + { + // trace('NENE: Animation finished, transitioning to STATE_DEFAULT'); + currentState = STATE_DEFAULT; + animationFinished = false; + } + default: + // trace('UKNOWN STATE ' + currentState); + currentState = STATE_DEFAULT; + } + } } diff --git a/preload/scripts/characters/nene.hxc b/preload/scripts/characters/nene.hxc index 8c68c0cf8..fb388467d 100644 --- a/preload/scripts/characters/nene.hxc +++ b/preload/scripts/characters/nene.hxc @@ -10,369 +10,407 @@ import funkin.modding.base.ScriptedFlxSpriteGroup; import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.audio.visualize.ABotVis; -class NeneCharacter extends SparrowCharacter { - function new() { - super('nene'); - } - - var pupilState:Int = 0; - - var PUPIL_STATE_NORMAL = 0; - var PUPIL_STATE_LEFT = 1; - - var abot:FlxAtlasSprite; - var abotViz:ABotVis; - var stereoBG:FlxSprite; - var eyeWhites:FlxSprite; - var pupil:FlxAtlasSprite; - - function onCreate(event:ScriptEvent) { - super.onCreate(event); - - stereoBG = new FlxSprite(0, 0, Paths.image('characters/abot/stereoBG')); - - eyeWhites = new FunkinSprite().makeSolidColor(160, 60); - - pupil = new FlxAtlasSprite(0, 0, Paths.animateAtlas("characters/abot/systemEyes", "shared")); - pupil.x = this.x; - pupil.y = this.y; - pupil.zIndex = this.zIndex - 5; - - abot = ScriptedFlxAtlasSprite.init('ABotAtlasSprite', 0, 0); - abot.x = this.x; - abot.y = this.y; - abot.zIndex = this.zIndex - 1; - - abotViz = new ABotVis(FlxG.sound.music); - abotViz.x = this.x; - abotViz.y = this.y; - abotViz.zIndex = abot.zIndex + 1; - FlxG.debugger.track(abotViz); - } - - /** - * At this amount of life, Nene will raise her knife. - */ - var VULTURE_THRESHOLD = 0.25 * 2; - - /** - * Nene is in her default state. 'danceLeft' or 'danceRight' may be playing right now, - * or maybe her 'combo' or 'drop' animations are active. - * - * Transitions: - * If player health <= VULTURE_THRESHOLD, transition to STATE_PRE_RAISE. - */ - var STATE_DEFAULT = 0; - - /** - * Nene has recognized the player is at low health, - * but has to wait for the appropriate point in the animation to move on. - * - * Transitions: - * If player health > VULTURE_THRESHOLD, transition back to STATE_DEFAULT without changing animation. - * If current animation is combo or drop, transition when animation completes. - * If current animation is danceLeft, wait until frame 14 to transition to STATE_RAISE. - * If current animation is danceRight, wait until danceLeft starts. - */ - var STATE_PRE_RAISE = 1; - - /** - * Nene is raising her knife. - * When moving to this state, immediately play the 'raiseKnife' animation. - * - * Transitions: - * Once 'raiseKnife' animation completes, transition to STATE_READY. - */ - var STATE_RAISE = 2; - - /** - * Nene is holding her knife ready to strike. - * During this state, hold the animation on the first frame, and play it at random intervals. - * This makes the blink look less periodic. - * - * Transitions: - * If the player runs out of health, move to the GameOverSubState. No transition needed. - * If player health > VULTURE_THRESHOLD, transition to STATE_LOWER. - */ - var STATE_READY = 3; - - /** - * Nene is raising her knife. - * When moving to this state, immediately play the 'lowerKnife' animation. - * - * Transitions: - * Once 'lowerKnife' animation completes, transition to STATE_DEFAULT. - */ - var STATE_LOWER = 4; - - /** - * Nene's animations are tracked in a simple state machine. - * Given the current state and an incoming event, the state changes. - */ - var currentState:Int = STATE_DEFAULT; - - /** - * Nene blinks every X beats, with X being randomly generated each time. - * This keeps the animation from looking too periodic. - */ - var MIN_BLINK_DELAY:Int = 3; - var MAX_BLINK_DELAY:Int = 7; - var blinkCountdown:Int = MIN_BLINK_DELAY; - - function dance(forceRestart:Bool) { - if (abot != null) - { - abot.playAnimation(""); - abot.anim.curFrame = 1; // we start on this frame, since from Flash the symbol has a non-bumpin frame on frame 0 - } - - // Then, perform the appropriate animation for the current state. - switch(currentState) { - case STATE_DEFAULT: - if (hasDanced) { - playAnimation('danceRight', forceRestart); - } else { - playAnimation('danceLeft', forceRestart); - } - hasDanced = !hasDanced; - case STATE_PRE_RAISE: - playAnimation('danceLeft', false); - hasDanced = false; - case STATE_READY: - if (blinkCountdown == 0) { - playAnimation('idleKnife', false); - blinkCountdown = FlxG.random.int(MIN_BLINK_DELAY, MAX_BLINK_DELAY); - } else { - blinkCountdown--; - } - default: - // In other states, don't interrupt the existing animation. - } - } - - var refershedLol:Bool = false; - - /** - * Called when the chart hits a song event. - */ - public override function onSongEvent(scriptEvent:SongEventScriptEvent) - { - super.onSongEvent(scriptEvent); - if (scriptEvent.eventData.eventKind == "FocusCamera") - { - var eventProps = scriptEvent.eventData.value; - switch (Std.parseInt(eventProps.char)) { - case 0: - movePupilsRight(); - case 1: - movePupilsLeft(); - default: - } - } - - } - - function movePupilsLeft():Void { - if (pupilState == PUPIL_STATE_LEFT) return; - trace('Move pupils left'); - pupil.playAnimation(''); - pupil.anim.curFrame = 0; - // pupilState = PUPIL_STATE_LEFT; - } - - function movePupilsRight():Void { - if (pupilState == PUPIL_STATE_NORMAL) return; - trace('Move pupils right'); - pupil.playAnimation(''); - pupil.anim.curFrame = 17; - // pupilState = PUPIL_STATE_NORMAL; - } - - function moveByNoteKind(kind:String) { - // Force ABot to look where the action is happening. - switch(event.note.kind) { - case "weekend-1-lightcan": - movePupilsLeft(); - case "weekend-1-kickcan": - // movePupilsLeft(); - case "weekend-1-kneecan": - // movePupilsLeft(); - case "weekend-1-cockgun": - movePupilsRight(); - case "weekend-1-firegun": - // movePupilsRight(); - default: // Nothing - } - } - - function onNoteHit(event:HitNoteScriptEvent) - { - super.onNoteHit(event); - moveByNoteKind(event.note.kind); - } - - function onNoteMiss(event:NoteScriptEvent) - { - super.onNoteMiss(event); - moveByNoteKind(event.note.kind); - } - - function onUpdate(event:UpdateScriptEvent) { - super.onUpdate(event); - - // Set the visibility of ABot to match Nene's. - abot.visible = this.visible; - pupil.visible = this.visible; - eyeWhites.visible = this.visible; - stereoBG.visible = this.visible; - - if (pupil?.anim?.isPlaying) - { - switch (pupilState) - { - case PUPIL_STATE_NORMAL: - if (pupil.anim.curFrame >= 17) - { - trace('Done moving pupils left'); - pupilState = PUPIL_STATE_LEFT; - pupil.anim.pause(); - } - - case PUPIL_STATE_LEFT: - if (pupil.anim.curFrame >= 30) - { - trace('Done moving pupils right'); - pupilState = PUPIL_STATE_NORMAL; - pupil.anim.pause(); - } - } - } - - // refreshes just for the zIndex shit! - if (!refershedLol) - { - abot.x = this.x - 100; - abot.y = this.y + 216; // 764 - 740 - abot.zIndex = this.zIndex - 10; - - PlayState.instance.currentStage.add(abot); - - abotViz.x = abot.x + 200; - abotViz.y = abot.y + 84; - abotViz.zIndex = abot.zIndex - 1; - PlayState.instance.currentStage.add(abotViz); - - eyeWhites.x = abot.x + 40; - eyeWhites.y = abot.y + 250; - eyeWhites.zIndex = abot.zIndex - 10; - PlayState.instance.currentStage.add(eyeWhites); - - pupil.x = abot.x - 507; - pupil.y = abot.y - 492; - pupil.zIndex = eyeWhites.zIndex + 5; - PlayState.instance.currentStage.add(pupil); - - stereoBG.x = abot.x + 150; - stereoBG.y = abot.y + 30; - stereoBG.zIndex = abot.zIndex - 8; - PlayState.instance.currentStage.add(stereoBG); - - PlayState.instance.currentStage.refresh(); - refershedLol = true; - } - - if (shouldTransitionState()) { - transitionState(); - } - } - - public function onScriptEvent(event:ScriptEvent):Void { - if (event.type == "SONG_START") - { - abotViz.snd = FlxG.sound.music; - abotViz.initAnalyzer(); - } - } - - var animationFinished:Bool = false; - - function onAnimationFinished(name:String) { - super.onAnimationFinished(name); - - switch(currentState) { - case STATE_RAISE: - if (name == "raiseKnife") { - animationFinished = true; - transitionState(); - } - case STATE_LOWER: - if (name == "lowerKnife") { - animationFinished = true; - transitionState(); - } - default: - // Ignore. - } - } - - function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) { - super.onAnimationFrame(name, frameNumber, frameIndex); - - switch(currentState) { - case STATE_PRE_RAISE: - if (name == "danceLeft" && frameNumber == 13) { - animationFinished = true; - transitionState(); - } - default: - // Ignore. - } - } - - function shouldTransitionState():Bool { - return PlayState.instance.currentStage.getBoyfriend().characterId != "pico-blazin"; - } - - function transitionState() { - switch (currentState) { - case STATE_DEFAULT: - if (PlayState.instance.health <= VULTURE_THRESHOLD) { - // trace('NENE: Health is low, transitioning to STATE_PRE_RAISE'); - currentState = STATE_PRE_RAISE; - } else { - currentState = STATE_DEFAULT; - } - case STATE_PRE_RAISE: - if (PlayState.instance.health > VULTURE_THRESHOLD) { - // trace('NENE: Health went back up, transitioning to STATE_DEFAULT'); - currentState = STATE_DEFAULT; - } else if (animationFinished) { - // trace('NENE: Animation finished, transitioning to STATE_RAISE'); - currentState = STATE_RAISE; - playAnimation('raiseKnife'); - animationFinished = false; - } - case STATE_RAISE: - if (animationFinished) { - // trace('NENE: Animation finished, transitioning to STATE_READY'); - currentState = STATE_READY; - animationFinished = false; - } - case STATE_READY: - if (PlayState.instance.health > VULTURE_THRESHOLD) { - // trace('NENE: Health went back up, transitioning to STATE_LOWER'); - currentState = STATE_LOWER; - playAnimation('lowerKnife'); - } - case STATE_LOWER: - if (animationFinished) { - // trace('NENE: Animation finished, transitioning to STATE_DEFAULT'); - currentState = STATE_DEFAULT; - animationFinished = false; - } - default: - // trace('UKNOWN STATE ' + currentState); - currentState = STATE_DEFAULT; - } - } +class NeneCharacter extends SparrowCharacter +{ + function new() + { + super('nene'); + } + + var pupilState:Int = 0; + + var PUPIL_STATE_NORMAL = 0; + var PUPIL_STATE_LEFT = 1; + + var abot:FlxAtlasSprite; + var abotViz:ABotVis; + var stereoBG:FlxSprite; + var eyeWhites:FlxSprite; + var pupil:FlxAtlasSprite; + + function onCreate(event:ScriptEvent) + { + super.onCreate(event); + + stereoBG = new FlxSprite(0, 0, Paths.image('characters/abot/stereoBG')); + + eyeWhites = new FunkinSprite().makeSolidColor(160, 60); + + pupil = new FlxAtlasSprite(0, 0, Paths.animateAtlas("characters/abot/systemEyes", "shared")); + pupil.x = this.x; + pupil.y = this.y; + pupil.zIndex = this.zIndex - 5; + + abot = ScriptedFlxAtlasSprite.init('ABotAtlasSprite', 0, 0); + abot.x = this.x; + abot.y = this.y; + abot.zIndex = this.zIndex - 1; + + abotViz = new ABotVis(FlxG.sound.music); + abotViz.x = this.x; + abotViz.y = this.y; + abotViz.zIndex = abot.zIndex + 1; + FlxG.debugger.track(abotViz); + } + + /** + * At this amount of life, Nene will raise her knife. + */ + var VULTURE_THRESHOLD = 0.25 * 2; + + /** + * Nene is in her default state. 'danceLeft' or 'danceRight' may be playing right now, + * or maybe her 'combo' or 'drop' animations are active. + * + * Transitions: + * If player health <= VULTURE_THRESHOLD, transition to STATE_PRE_RAISE. + */ + var STATE_DEFAULT = 0; + + /** + * Nene has recognized the player is at low health, + * but has to wait for the appropriate point in the animation to move on. + * + * Transitions: + * If player health > VULTURE_THRESHOLD, transition back to STATE_DEFAULT without changing animation. + * If current animation is combo or drop, transition when animation completes. + * If current animation is danceLeft, wait until frame 14 to transition to STATE_RAISE. + * If current animation is danceRight, wait until danceLeft starts. + */ + var STATE_PRE_RAISE = 1; + + /** + * Nene is raising her knife. + * When moving to this state, immediately play the 'raiseKnife' animation. + * + * Transitions: + * Once 'raiseKnife' animation completes, transition to STATE_READY. + */ + var STATE_RAISE = 2; + + /** + * Nene is holding her knife ready to strike. + * During this state, hold the animation on the first frame, and play it at random intervals. + * This makes the blink look less periodic. + * + * Transitions: + * If the player runs out of health, move to the GameOverSubState. No transition needed. + * If player health > VULTURE_THRESHOLD, transition to STATE_LOWER. + */ + var STATE_READY = 3; + + /** + * Nene is raising her knife. + * When moving to this state, immediately play the 'lowerKnife' animation. + * + * Transitions: + * Once 'lowerKnife' animation completes, transition to STATE_DEFAULT. + */ + var STATE_LOWER = 4; + + /** + * Nene's animations are tracked in a simple state machine. + * Given the current state and an incoming event, the state changes. + */ + var currentState:Int = STATE_DEFAULT; + + /** + * Nene blinks every X beats, with X being randomly generated each time. + * This keeps the animation from looking too periodic. + */ + var MIN_BLINK_DELAY:Int = 3; + + var MAX_BLINK_DELAY:Int = 7; + var blinkCountdown:Int = MIN_BLINK_DELAY; + + function dance(forceRestart:Bool) + { + if (abot != null) + { + abot.playAnimation(""); + abot.anim.curFrame = 1; // we start on this frame, since from Flash the symbol has a non-bumpin frame on frame 0 + } + + // Then, perform the appropriate animation for the current state. + switch (currentState) + { + case STATE_DEFAULT: + if (hasDanced) + { + playAnimation('danceRight', forceRestart); + } + else + { + playAnimation('danceLeft', forceRestart); + } + hasDanced = !hasDanced; + case STATE_PRE_RAISE: + playAnimation('danceLeft', false); + hasDanced = false; + case STATE_READY: + if (blinkCountdown == 0) + { + playAnimation('idleKnife', false); + blinkCountdown = FlxG.random.int(MIN_BLINK_DELAY, MAX_BLINK_DELAY); + } + else + { + blinkCountdown--; + } + default: + // In other states, don't interrupt the existing animation. + } + } + + var refershedLol:Bool = false; + + /** + * Called when the chart hits a song event. + */ + public override function onSongEvent(scriptEvent:SongEventScriptEvent) + { + super.onSongEvent(scriptEvent); + if (scriptEvent.eventData.eventKind == "FocusCamera") + { + var eventProps = scriptEvent.eventData.value; + switch (Std.parseInt(eventProps.char)) + { + case 0: + movePupilsRight(); + case 1: + movePupilsLeft(); + default: + } + } + } + + function movePupilsLeft():Void + { + if (pupilState == PUPIL_STATE_LEFT) return; + trace('Move pupils left'); + pupil.playAnimation(''); + pupil.anim.curFrame = 0; + // pupilState = PUPIL_STATE_LEFT; + } + + function movePupilsRight():Void + { + if (pupilState == PUPIL_STATE_NORMAL) return; + trace('Move pupils right'); + pupil.playAnimation(''); + pupil.anim.curFrame = 17; + // pupilState = PUPIL_STATE_NORMAL; + } + + function moveByNoteKind(kind:String) + { + // Force ABot to look where the action is happening. + switch (event.note.kind) + { + case "weekend-1-lightcan": + movePupilsLeft(); + case "weekend-1-kickcan": + // movePupilsLeft(); + case "weekend-1-kneecan": + // movePupilsLeft(); + case "weekend-1-cockgun": + movePupilsRight(); + case "weekend-1-firegun": + // movePupilsRight(); + default: // Nothing + } + } + + function onNoteHit(event:HitNoteScriptEvent) + { + super.onNoteHit(event); + moveByNoteKind(event.note.kind); + } + + function onNoteMiss(event:NoteScriptEvent) + { + super.onNoteMiss(event); + moveByNoteKind(event.note.kind); + } + + function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); + + // Set the visibility of ABot to match Nene's. + abot.visible = this.visible; + pupil.visible = this.visible; + eyeWhites.visible = this.visible; + stereoBG.visible = this.visible; + + if (pupil?.anim?.isPlaying) + { + switch (pupilState) + { + case PUPIL_STATE_NORMAL: + if (pupil.anim.curFrame >= 17) + { + trace('Done moving pupils left'); + pupilState = PUPIL_STATE_LEFT; + pupil.anim.pause(); + } + + case PUPIL_STATE_LEFT: + if (pupil.anim.curFrame >= 30) + { + trace('Done moving pupils right'); + pupilState = PUPIL_STATE_NORMAL; + pupil.anim.pause(); + } + } + } + + // refreshes just for the zIndex shit! + if (!refershedLol) + { + abot.x = this.x - 100; + abot.y = this.y + 216; // 764 - 740 + abot.zIndex = this.zIndex - 10; + + PlayState.instance.currentStage.add(abot); + + abotViz.x = abot.x + 200; + abotViz.y = abot.y + 84; + abotViz.zIndex = abot.zIndex - 1; + PlayState.instance.currentStage.add(abotViz); + + eyeWhites.x = abot.x + 40; + eyeWhites.y = abot.y + 250; + eyeWhites.zIndex = abot.zIndex - 10; + PlayState.instance.currentStage.add(eyeWhites); + + pupil.x = abot.x - 507; + pupil.y = abot.y - 492; + pupil.zIndex = eyeWhites.zIndex + 5; + PlayState.instance.currentStage.add(pupil); + + stereoBG.x = abot.x + 150; + stereoBG.y = abot.y + 30; + stereoBG.zIndex = abot.zIndex - 8; + PlayState.instance.currentStage.add(stereoBG); + + PlayState.instance.currentStage.refresh(); + refershedLol = true; + } + + if (shouldTransitionState()) + { + transitionState(); + } + } + + public function onScriptEvent(event:ScriptEvent):Void + { + if (event.type == "SONG_START") + { + abotViz.snd = FlxG.sound.music; + abotViz.initAnalyzer(); + } + } + + var animationFinished:Bool = false; + + function onAnimationFinished(name:String) + { + super.onAnimationFinished(name); + + switch (currentState) + { + case STATE_RAISE: + if (name == "raiseKnife") + { + animationFinished = true; + transitionState(); + } + case STATE_LOWER: + if (name == "lowerKnife") + { + animationFinished = true; + transitionState(); + } + default: + // Ignore. + } + } + + function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) + { + super.onAnimationFrame(name, frameNumber, frameIndex); + + switch (currentState) + { + case STATE_PRE_RAISE: + if (name == "danceLeft" && frameNumber == 13) + { + animationFinished = true; + transitionState(); + } + default: + // Ignore. + } + } + + function shouldTransitionState():Bool + { + return PlayState.instance.currentStage.getBoyfriend().characterId != "pico-blazin"; + } + + function transitionState() + { + switch (currentState) + { + case STATE_DEFAULT: + if (PlayState.instance.health <= VULTURE_THRESHOLD) + { + // trace('NENE: Health is low, transitioning to STATE_PRE_RAISE'); + currentState = STATE_PRE_RAISE; + } + else + { + currentState = STATE_DEFAULT; + } + case STATE_PRE_RAISE: + if (PlayState.instance.health > VULTURE_THRESHOLD) + { + // trace('NENE: Health went back up, transitioning to STATE_DEFAULT'); + currentState = STATE_DEFAULT; + } + else if (animationFinished) + { + // trace('NENE: Animation finished, transitioning to STATE_RAISE'); + currentState = STATE_RAISE; + playAnimation('raiseKnife'); + animationFinished = false; + } + case STATE_RAISE: + if (animationFinished) + { + // trace('NENE: Animation finished, transitioning to STATE_READY'); + currentState = STATE_READY; + animationFinished = false; + } + case STATE_READY: + if (PlayState.instance.health > VULTURE_THRESHOLD) + { + // trace('NENE: Health went back up, transitioning to STATE_LOWER'); + currentState = STATE_LOWER; + playAnimation('lowerKnife'); + } + case STATE_LOWER: + if (animationFinished) + { + // trace('NENE: Animation finished, transitioning to STATE_DEFAULT'); + currentState = STATE_DEFAULT; + animationFinished = false; + } + default: + // trace('UKNOWN STATE ' + currentState); + currentState = STATE_DEFAULT; + } + } } diff --git a/preload/scripts/characters/parents-christmas.hxc b/preload/scripts/characters/parents-christmas.hxc index e02f61dd9..ca070b149 100644 --- a/preload/scripts/characters/parents-christmas.hxc +++ b/preload/scripts/characters/parents-christmas.hxc @@ -2,23 +2,27 @@ import funkin.play.character.SparrowCharacter; import funkin.play.character.CharacterType; import funkin.play.PlayState; -class ParentsChristmasCharacter extends SparrowCharacter { - function new() { - super('parents-christmas'); - } +class ParentsChristmasCharacter extends SparrowCharacter +{ + function new() + { + super('parents-christmas'); + } - function onNoteHit(event:HitNoteScriptEvent) - { - if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) { - // Override the hit note animation. - switch(event.note.kind) { - case "mom": - holdTimer = 0; - this.playSingAnimation(event.note.noteData.getDirection(), false, 'alt'); - return; - } - } + function onNoteHit(event:HitNoteScriptEvent) + { + if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) + { + // Override the hit note animation. + switch (event.note.kind) + { + case "mom": + holdTimer = 0; + this.playSingAnimation(event.note.noteData.getDirection(), false, 'alt'); + return; + } + } - super.onNoteHit(event); - } + super.onNoteHit(event); + } } diff --git a/preload/scripts/characters/pico-blazin.hxc b/preload/scripts/characters/pico-blazin.hxc index 8dbd7c7cb..967a51f77 100644 --- a/preload/scripts/characters/pico-blazin.hxc +++ b/preload/scripts/characters/pico-blazin.hxc @@ -1,4 +1,3 @@ - import flixel.FlxG; import flixel.util.FlxTimer; import funkin.play.PlayState; @@ -10,449 +9,471 @@ import StringTools; class PicoBlazinCharacter extends AnimateAtlasCharacter { - function new() - { - super('pico-blazin'); - } - - function onCreate(event:ScriptEvent) - { - super.onCreate(event); - - this.danceEvery = 0; - this.playAnimation('idle', true, false); - - // NOTE: this.x and this.y are not properly set here. - - GameOverSubState.musicSuffix = '-pico'; - GameOverSubState.blueBallSuffix = '-pico-gutpunch'; - - PauseSubState.musicSuffix = '-pico'; - } - - var cantUppercut = false; - - function onNoteHit(event:HitNoteScriptEvent) - { - holdTimer = 0; - - if (!StringTools.startsWith(event.note.kind, 'weekend-1-')) return; - - // SPECIAL CASE: If Pico hits a poor note at low health (at 30% chance), - // Pico may instead punch high (but Darnell will duck below Pico to attempt an uppercut) - // TODO: Maybe add a cooldown to this? - // NOTE: This relies on scripts dispatching to opponents first, which is true at time of writing. - var shouldDoUppercutPrep = wasNoteHitPoorly(event) && isPlayerLowHealth() && isDarnellPreppingUppercut(); - - if (shouldDoUppercutPrep) { - playPunchHighAnim(); - return; - } - - if (cantUppercut) { - playBlockAnim(); - cantUppercut = false; - return; - } - - // Override the hit note animation. - switch (event.note.kind) - { - case "weekend-1-punchlow": - playPunchLowAnim(); - case "weekend-1-punchlowblocked": - playPunchLowAnim(); - case "weekend-1-punchlowdodged": - playPunchLowAnim(); - case "weekend-1-punchlowspin": - playPunchLowAnim(); - - case "weekend-1-punchhigh": - playPunchHighAnim(); - case "weekend-1-punchhighblocked": - playPunchHighAnim(); - case "weekend-1-punchhighdodged": - playPunchHighAnim(); - case "weekend-1-punchhighspin": - playPunchHighAnim(); - - case "weekend-1-blockhigh": - playBlockAnim(event.judgement); - case "weekend-1-blocklow": - playBlockAnim(event.judgement); - case "weekend-1-blockspin": - playBlockAnim(event.judgement); - - case "weekend-1-dodgehigh": - playDodgeAnim(); - case "weekend-1-dodgelow": - playDodgeAnim(); - case "weekend-1-dodgespin": - playDodgeAnim(); - - // Pico ALWAYS gets punched. - case "weekend-1-hithigh": - playHitHighAnim(); - case "weekend-1-hitlow": - playHitLowAnim(); - case "weekend-1-hitspin": - playHitSpinAnim(); - - case "weekend-1-picouppercutprep": - playUppercutPrepAnim(); - case "weekend-1-picouppercut": - playUppercutAnim(true); - - case "weekend-1-darnelluppercutprep": - playIdleAnim(); - case "weekend-1-darnelluppercut": - playUppercutHitAnim(); - - case "weekend-1-idle": - playIdleAnim(); - case "weekend-1-fakeout": - playFakeoutAnim(); - case "weekend-1-taunt": - playTauntConditionalAnim(); - case "weekend-1-tauntforce": - playTauntAnim(); - case "weekend-1-reversefakeout": - playIdleAnim(); // TODO: Which anim? - - default: - // trace('Unknown note kind: ' + event.note.kind); - } - } - - function playAnimation(name:String, restart:Bool, ignoreOther:Bool) { - if (name == "firstDeath") { - // TODO: ACTUALLY play one of the three death animations here. - - // Make sure the death music plays with PERFECT timing. - new FlxTimer().start(1.25, afterPicoDeathGutPunchIntro); - } else if (name == "deathConfirm") { - doDeathConfirm(); - } else { - super.playAnimation(name, restart, ignoreOther); - } - - super.playAnimation(name, restart, ignoreOther); - } - - function afterPicoDeathGutPunchIntro():Void { - GameOverSubState.instance.startDeathMusic(1.0, false); - playAnimation('deathLoop', true, false); - } - - function doDeathConfirm():Void { - var picoDeathConfirm:FunkinSprite = FunkinSprite.createSparrow(this.x + 905, this.y + 1030, 'picoBlazinDeathConfirm'); - picoDeathConfirm.animation.addByPrefix('confirm', "Pico Gut Punch Death0", 24, false); - picoDeathConfirm.animation.play('confirm'); - picoDeathConfirm.scale.set(1.75, 1.75); - picoDeathConfirm.zIndex = 1000; + function new() + { + super('pico-blazin'); + } + + function onCreate(event:ScriptEvent) + { + super.onCreate(event); + + this.danceEvery = 0; + this.playAnimation('idle', true, false); + + // NOTE: this.x and this.y are not properly set here. + + GameOverSubState.musicSuffix = '-pico'; + GameOverSubState.blueBallSuffix = '-pico-gutpunch'; + + PauseSubState.musicSuffix = '-pico'; + } + + var cantUppercut = false; + + function onNoteHit(event:HitNoteScriptEvent) + { + holdTimer = 0; + + if (!StringTools.startsWith(event.note.kind, 'weekend-1-')) return; + + // SPECIAL CASE: If Pico hits a poor note at low health (at 30% chance), + // Pico may instead punch high (but Darnell will duck below Pico to attempt an uppercut) + // TODO: Maybe add a cooldown to this? + // NOTE: This relies on scripts dispatching to opponents first, which is true at time of writing. + var shouldDoUppercutPrep = wasNoteHitPoorly(event) && isPlayerLowHealth() && isDarnellPreppingUppercut(); + + if (shouldDoUppercutPrep) + { + playPunchHighAnim(); + return; + } + + if (cantUppercut) + { + playBlockAnim(); + cantUppercut = false; + return; + } + + // Override the hit note animation. + switch (event.note.kind) + { + case "weekend-1-punchlow": + playPunchLowAnim(); + case "weekend-1-punchlowblocked": + playPunchLowAnim(); + case "weekend-1-punchlowdodged": + playPunchLowAnim(); + case "weekend-1-punchlowspin": + playPunchLowAnim(); + + case "weekend-1-punchhigh": + playPunchHighAnim(); + case "weekend-1-punchhighblocked": + playPunchHighAnim(); + case "weekend-1-punchhighdodged": + playPunchHighAnim(); + case "weekend-1-punchhighspin": + playPunchHighAnim(); + + case "weekend-1-blockhigh": + playBlockAnim(event.judgement); + case "weekend-1-blocklow": + playBlockAnim(event.judgement); + case "weekend-1-blockspin": + playBlockAnim(event.judgement); + + case "weekend-1-dodgehigh": + playDodgeAnim(); + case "weekend-1-dodgelow": + playDodgeAnim(); + case "weekend-1-dodgespin": + playDodgeAnim(); + + // Pico ALWAYS gets punched. + case "weekend-1-hithigh": + playHitHighAnim(); + case "weekend-1-hitlow": + playHitLowAnim(); + case "weekend-1-hitspin": + playHitSpinAnim(); + + case "weekend-1-picouppercutprep": + playUppercutPrepAnim(); + case "weekend-1-picouppercut": + playUppercutAnim(true); + + case "weekend-1-darnelluppercutprep": + playIdleAnim(); + case "weekend-1-darnelluppercut": + playUppercutHitAnim(); + + case "weekend-1-idle": + playIdleAnim(); + case "weekend-1-fakeout": + playFakeoutAnim(); + case "weekend-1-taunt": + playTauntConditionalAnim(); + case "weekend-1-tauntforce": + playTauntAnim(); + case "weekend-1-reversefakeout": + playIdleAnim(); // TODO: Which anim? + + default: + // trace('Unknown note kind: ' + event.note.kind); + } + } + + function playAnimation(name:String, restart:Bool, ignoreOther:Bool) + { + if (name == "firstDeath") + { + // TODO: ACTUALLY play one of the three death animations here. + + // Make sure the death music plays with PERFECT timing. + new FlxTimer().start(1.25, afterPicoDeathGutPunchIntro); + } + else if (name == "deathConfirm") + { + doDeathConfirm(); + } + else + { + super.playAnimation(name, restart, ignoreOther); + } + + super.playAnimation(name, restart, ignoreOther); + } + + function afterPicoDeathGutPunchIntro():Void + { + GameOverSubState.instance.startDeathMusic(1.0, false); + playAnimation('deathLoop', true, false); + } + + function doDeathConfirm():Void + { + var picoDeathConfirm:FunkinSprite = FunkinSprite.createSparrow(this.x + 905, this.y + 1030, 'picoBlazinDeathConfirm'); + picoDeathConfirm.animation.addByPrefix('confirm', "Pico Gut Punch Death0", 24, false); + picoDeathConfirm.animation.play('confirm'); + picoDeathConfirm.scale.set(1.75, 1.75); + picoDeathConfirm.zIndex = 1000; FlxG.state.subState.add(picoDeathConfirm); - picoDeathConfirm.visible = true; - this.visible = false; - - picoDeathConfirm.animation.finishCallback = () -> { - picoDeathConfirm.visible = false; - this.visible = true; - } - } - - function onNoteMiss(event:NoteScriptEvent) - { - holdTimer = 0; - - // SPECIAL CASE: Darnell prepared to uppercut last time and Pico missed! FINISH HIM! - if (isDarnellInUppercut()) { - playUppercutHitAnim(); - return; - } - - if (willMissBeLethal(event)) { - playHitLowAnim(); - return; - } - - if (cantUppercut) { - playHitHighAnim(); - return; - } - - // Override the hit note animation. - switch (event.note.kind) - { - // Pico fails to punch, and instead gets hit! - case "weekend-1-punchlow": - playHitLowAnim(); - case "weekend-1-punchlowblocked": - playHitLowAnim(); - case "weekend-1-punchlowdodged": - playHitLowAnim(); - case "weekend-1-punchlowspin": - playHitSpinAnim(); - - // Pico fails to punch, and instead gets hit! - case "weekend-1-punchhigh": - playHitHighAnim(); - case "weekend-1-punchhighblocked": - playHitHighAnim(); - case "weekend-1-punchhighdodged": - playHitHighAnim(); - case "weekend-1-punchhighspin": - playHitSpinAnim(); - - // Pico fails to block, and instead gets hit! - case "weekend-1-blockhigh": - playHitHighAnim(); - case "weekend-1-blocklow": - playHitLowAnim(); - case "weekend-1-blockspin": - playHitSpinAnim(); - - // Pico fails to dodge, and instead gets hit! - case "weekend-1-dodgehigh": - playHitHighAnim(); - case "weekend-1-dodgelow": - playHitLowAnim(); - case "weekend-1-dodgespin": - playHitSpinAnim(); - - // Pico ALWAYS gets punched. - case "weekend-1-hithigh": - playHitHighAnim(); - case "weekend-1-hitlow": - playHitLowAnim(); - case "weekend-1-hitspin": - playHitSpinAnim(); - - // Fail to dodge the uppercut. - case "weekend-1-picouppercutprep": - playPunchHighAnim(); - cantUppercut = true; - case "weekend-1-picouppercut": - playUppercutAnim(false); - - // Darnell's attempt to uppercut, Pico dodges or gets hit. - case "weekend-1-darnelluppercutprep": - playIdleAnim(); - case "weekend-1-darnelluppercut": - playUppercutHitAnim(); - - case "weekend-1-idle": - playIdleAnim(); - case "weekend-1-fakeout": - playHitHighAnim(); - case "weekend-1-taunt": - playTauntConditionalAnim(); - case "weekend-1-tauntforce": - playTauntAnim(); - case "weekend-1-reversefakeout": - playIdleAnim(); - - default: - trace('Unknown note kind: ' + event.note.kind); - } - } - - function willMissBeLethal(event:NoteScriptEvent):Bool { - return (PlayState.instance.health + event.healthChange) <= 0.0; - } - - function onNoteGhostMiss(event:GhostMissNoteScriptEvent) - { - if (willMissBeLethal(event)) { - // Darnell throws a punch so that Pico dies. - playHitLowAnim(); - } else { - // Pico wildly throws punches but Darnell dodges. - playPunchHighAnim(); - } - } - - override function onAnimationFinished(name:String) - { - super.onAnimationFinished(name); - } - - override function onSongRetry() - { - super.onSongRetry(); - cantUppercut = false; - playIdleAnim(); - - GameOverSubState.musicSuffix = '-pico'; - GameOverSubState.blueBallSuffix = '-pico-gutpunch'; - - PauseSubState.musicSuffix = '-pico'; - } - - function getDarnell() - { - if (this.debug) return null; - return PlayState.instance.currentStage.getDad(); - } - - function moveToBack() - { - if (this.debug) return; - this.zIndex = 2000; - PlayState.instance.currentStage.refresh(); - } - - function moveToFront() - { - if (this.debug) return; - this.zIndex = 3000; - PlayState.instance.currentStage.refresh(); - } - - function isDarnellPreppingUppercut():Void { - return getDarnell().getCurrentAnimation() == 'uppercutPrep'; - } - - function isDarnellInUppercut():Void { - return - getDarnell().getCurrentAnimation() == 'uppercut' - || getDarnell().getCurrentAnimation() == 'uppercut-hold'; - } - - function wasNoteHitPoorly(event:HitNoteScriptEvent):Bool { - return (event.judgement == "bad" || event.judgement == "shit"); - } - - function isPlayerLowHealth(event:HitNoteScriptEvent):Bool { - return PlayState.instance.health <= 0.30 * 2.0; - } - - // ANIMATIONS - - var alternate:Bool = false; - - function doAlternate():String { - alternate = !alternate; - return alternate ? '1' : '2'; - } - - function playBlockAnim(?judgement:String) - { - // on sick block, do a 3rd strike esque "tech" effect - if (judgement == 'sick') - { - //var blendAnims:Array = [10, 0, 10, 0, 0, 10, 0, 0, 10, 0, 10]; -// - //for (blendMode in 0...blendAnims.length) - //{ - // new FlxTimer().start(blendMode / 60, function(_) { -// - // if (blendAnims[blendMode] != 10) - // this.color = 0xFF0000FF; - // else - // this.color = 0xFFFFFFFF; -// - // this.blend = blendAnims[blendMode]; - // }); - //} - - } - - this.playAnimation('block', true, false); - PlayState.instance.camGame.shake(0.002, 0.1); - moveToBack(); - } - - function playCringeAnim() - { - this.playAnimation('cringe', true, false); - moveToBack(); - } - - function playDodgeAnim() - { - this.playAnimation('dodge', true, false); - moveToBack(); - } - - function playIdleAnim() - { - this.playAnimation('idle', false, false); - moveToBack(); - } - - function playFakeoutAnim() - { - this.playAnimation('fakeout', true, false); - moveToBack(); - } - - function playUppercutPrepAnim() - { - this.playAnimation('uppercutPrep', true, false); - moveToFront(); - } - - function playUppercutAnim(hit:Bool) - { - this.playAnimation('uppercut', true, false); - if (hit) { - PlayState.instance.camGame.shake(0.005, 0.25); - } - moveToFront(); - } - - function playUppercutHitAnim() - { - this.playAnimation('uppercutHit', true, false); - PlayState.instance.camGame.shake(0.005, 0.25); - moveToBack(); - } - - function playHitHighAnim() - { - this.playAnimation('hitHigh', true, false); - PlayState.instance.camGame.shake(0.0025, 0.15); - moveToBack(); - } - - function playHitLowAnim() - { - this.playAnimation('hitLow', true, false); - PlayState.instance.camGame.shake(0.0025, 0.15); - moveToBack(); - } - - function playHitSpinAnim() - { - this.playAnimation('hitSpin', true, false, true); - PlayState.instance.camGame.shake(0.0025, 0.15); - moveToBack(); - } - - function playPunchHighAnim() - { - this.playAnimation('punchHigh' + doAlternate(), true, false); - moveToFront(); - } - - function playPunchLowAnim() - { - this.playAnimation('punchLow' + doAlternate(), true, false); - moveToFront(); - } - - function playTauntConditionalAnim() - { - if (getCurrentAnimation() == "fakeout") { - playTauntAnim(); - } else { - playIdleAnim(); - } - } - - function playTauntAnim() - { - this.playAnimation('taunt', true, false); - moveToBack(); - } + picoDeathConfirm.visible = true; + this.visible = false; + + picoDeathConfirm.animation.finishCallback = () -> { + picoDeathConfirm.visible = false; + this.visible = true; + } + } + + function onNoteMiss(event:NoteScriptEvent) + { + holdTimer = 0; + + // SPECIAL CASE: Darnell prepared to uppercut last time and Pico missed! FINISH HIM! + if (isDarnellInUppercut()) + { + playUppercutHitAnim(); + return; + } + + if (willMissBeLethal(event)) + { + playHitLowAnim(); + return; + } + + if (cantUppercut) + { + playHitHighAnim(); + return; + } + + // Override the hit note animation. + switch (event.note.kind) + { + // Pico fails to punch, and instead gets hit! + case "weekend-1-punchlow": + playHitLowAnim(); + case "weekend-1-punchlowblocked": + playHitLowAnim(); + case "weekend-1-punchlowdodged": + playHitLowAnim(); + case "weekend-1-punchlowspin": + playHitSpinAnim(); + + // Pico fails to punch, and instead gets hit! + case "weekend-1-punchhigh": + playHitHighAnim(); + case "weekend-1-punchhighblocked": + playHitHighAnim(); + case "weekend-1-punchhighdodged": + playHitHighAnim(); + case "weekend-1-punchhighspin": + playHitSpinAnim(); + + // Pico fails to block, and instead gets hit! + case "weekend-1-blockhigh": + playHitHighAnim(); + case "weekend-1-blocklow": + playHitLowAnim(); + case "weekend-1-blockspin": + playHitSpinAnim(); + + // Pico fails to dodge, and instead gets hit! + case "weekend-1-dodgehigh": + playHitHighAnim(); + case "weekend-1-dodgelow": + playHitLowAnim(); + case "weekend-1-dodgespin": + playHitSpinAnim(); + + // Pico ALWAYS gets punched. + case "weekend-1-hithigh": + playHitHighAnim(); + case "weekend-1-hitlow": + playHitLowAnim(); + case "weekend-1-hitspin": + playHitSpinAnim(); + + // Fail to dodge the uppercut. + case "weekend-1-picouppercutprep": + playPunchHighAnim(); + cantUppercut = true; + case "weekend-1-picouppercut": + playUppercutAnim(false); + + // Darnell's attempt to uppercut, Pico dodges or gets hit. + case "weekend-1-darnelluppercutprep": + playIdleAnim(); + case "weekend-1-darnelluppercut": + playUppercutHitAnim(); + + case "weekend-1-idle": + playIdleAnim(); + case "weekend-1-fakeout": + playHitHighAnim(); + case "weekend-1-taunt": + playTauntConditionalAnim(); + case "weekend-1-tauntforce": + playTauntAnim(); + case "weekend-1-reversefakeout": + playIdleAnim(); + + default: + trace('Unknown note kind: ' + event.note.kind); + } + } + + function willMissBeLethal(event:NoteScriptEvent):Bool + { + return (PlayState.instance.health + event.healthChange) <= 0.0; + } + + function onNoteGhostMiss(event:GhostMissNoteScriptEvent) + { + if (willMissBeLethal(event)) + { + // Darnell throws a punch so that Pico dies. + playHitLowAnim(); + } + else + { + // Pico wildly throws punches but Darnell dodges. + playPunchHighAnim(); + } + } + + override function onAnimationFinished(name:String) + { + super.onAnimationFinished(name); + } + + override function onSongRetry() + { + super.onSongRetry(); + cantUppercut = false; + playIdleAnim(); + + GameOverSubState.musicSuffix = '-pico'; + GameOverSubState.blueBallSuffix = '-pico-gutpunch'; + + PauseSubState.musicSuffix = '-pico'; + } + + function getDarnell() + { + if (this.debug) return null; + return PlayState.instance.currentStage.getDad(); + } + + function moveToBack() + { + if (this.debug) return; + this.zIndex = 2000; + PlayState.instance.currentStage.refresh(); + } + + function moveToFront() + { + if (this.debug) return; + this.zIndex = 3000; + PlayState.instance.currentStage.refresh(); + } + + function isDarnellPreppingUppercut():Void + { + return getDarnell().getCurrentAnimation() == 'uppercutPrep'; + } + + function isDarnellInUppercut():Void + { + return getDarnell().getCurrentAnimation() == 'uppercut' || getDarnell().getCurrentAnimation() == 'uppercut-hold'; + } + + function wasNoteHitPoorly(event:HitNoteScriptEvent):Bool + { + return (event.judgement == "bad" || event.judgement == "shit"); + } + + function isPlayerLowHealth(event:HitNoteScriptEvent):Bool + { + return PlayState.instance.health <= 0.30 * 2.0; + } + + // ANIMATIONS + var alternate:Bool = false; + + function doAlternate():String + { + alternate = !alternate; + return alternate ? '1' : '2'; + } + + function playBlockAnim(?judgement:String) + { + // on sick block, do a 3rd strike esque "tech" effect + if (judgement == 'sick') + { + // var blendAnims:Array = [10, 0, 10, 0, 0, 10, 0, 0, 10, 0, 10]; + // + // for (blendMode in 0...blendAnims.length) + // { + // new FlxTimer().start(blendMode / 60, function(_) { + // + // if (blendAnims[blendMode] != 10) + // this.color = 0xFF0000FF; + // else + // this.color = 0xFFFFFFFF; + // + // this.blend = blendAnims[blendMode]; + // }); + // } + } + + this.playAnimation('block', true, false); + PlayState.instance.camGame.shake(0.002, 0.1); + moveToBack(); + } + + function playCringeAnim() + { + this.playAnimation('cringe', true, false); + moveToBack(); + } + + function playDodgeAnim() + { + this.playAnimation('dodge', true, false); + moveToBack(); + } + + function playIdleAnim() + { + this.playAnimation('idle', false, false); + moveToBack(); + } + + function playFakeoutAnim() + { + this.playAnimation('fakeout', true, false); + moveToBack(); + } + + function playUppercutPrepAnim() + { + this.playAnimation('uppercutPrep', true, false); + moveToFront(); + } + + function playUppercutAnim(hit:Bool) + { + this.playAnimation('uppercut', true, false); + if (hit) + { + PlayState.instance.camGame.shake(0.005, 0.25); + } + moveToFront(); + } + + function playUppercutHitAnim() + { + this.playAnimation('uppercutHit', true, false); + PlayState.instance.camGame.shake(0.005, 0.25); + moveToBack(); + } + + function playHitHighAnim() + { + this.playAnimation('hitHigh', true, false); + PlayState.instance.camGame.shake(0.0025, 0.15); + moveToBack(); + } + + function playHitLowAnim() + { + this.playAnimation('hitLow', true, false); + PlayState.instance.camGame.shake(0.0025, 0.15); + moveToBack(); + } + + function playHitSpinAnim() + { + this.playAnimation('hitSpin', true, false, true); + PlayState.instance.camGame.shake(0.0025, 0.15); + moveToBack(); + } + + function playPunchHighAnim() + { + this.playAnimation('punchHigh' + doAlternate(), true, false); + moveToFront(); + } + + function playPunchLowAnim() + { + this.playAnimation('punchLow' + doAlternate(), true, false); + moveToFront(); + } + + function playTauntConditionalAnim() + { + if (getCurrentAnimation() == "fakeout") + { + playTauntAnim(); + } + else + { + playIdleAnim(); + } + } + + function playTauntAnim() + { + this.playAnimation('taunt', true, false); + moveToBack(); + } } diff --git a/preload/scripts/characters/pico-christmas.hxc b/preload/scripts/characters/pico-christmas.hxc index 39eaa198f..74a8c725a 100644 --- a/preload/scripts/characters/pico-christmas.hxc +++ b/preload/scripts/characters/pico-christmas.hxc @@ -15,120 +15,137 @@ import funkin.play.PauseSubState; import funkin.modding.module.ModuleHandler; import flixel.tweens.FlxTween; +class PicoChristmasCharacter extends MultiSparrowCharacter +{ + function new() + { + super('pico-christmas'); + } -class PicoChristmasCharacter extends MultiSparrowCharacter { - function new() { - super('pico-christmas'); - } + function onCreate(event:ScriptEvent) + { + super.onCreate(event); - function onCreate(event:ScriptEvent) { - super.onCreate(event); + // NOTE: this.x and this.y are not properly set here. - // NOTE: this.x and this.y are not properly set here. + GameOverSubState.musicSuffix = '-pico'; + GameOverSubState.blueBallSuffix = '-pico'; - GameOverSubState.musicSuffix = '-pico'; - GameOverSubState.blueBallSuffix = '-pico'; + PauseSubState.musicSuffix = '-pico'; + } - PauseSubState.musicSuffix = '-pico'; - } + var deathSpriteRetry:FunkinSprite; + var deathSpriteNene:FunkinSprite; - var deathSpriteRetry:FunkinSprite; - var deathSpriteNene:FunkinSprite; + var picoFade:FunkinSprite; - var picoFade:FunkinSprite; - - /** + /** * Initialize and cache sprites used for the death animation, - * for use later. - */ - function createDeathSprites() { - //trace('PICO: Creating death sprites'); - deathSpriteRetry = FunkinSprite.createSparrow(0, 0, "characters/Pico_Death_Retry"); - deathSpriteRetry.animation.addByPrefix('idle', "Retry Text Loop0", 24, true); - deathSpriteRetry.animation.addByPrefix('confirm', "Retry Text Confirm0", 24, false); - - deathSpriteRetry.zIndex = this.zIndex + 5; - - deathSpriteRetry.visible = false; - - //FlxG.debugger.track(deathSpriteRetry); - - deathSpriteNene = FunkinSprite.createSparrow(0, 0, "characters/neneChristmas/neneChristmasKnife"); - var gf = PlayState.instance.currentStage.getGirlfriend(); - deathSpriteNene.x = gf.originalPosition.x; // + 280; - deathSpriteNene.y = gf.originalPosition.y; // + 70; - deathSpriteNene.zIndex = this.zIndex - 5; - deathSpriteNene.animation.addByPrefix('throw', "knife toss xmas0", 24, false); - deathSpriteNene.visible = true; - deathSpriteNene.animation.finishCallback = function(name:String) { - deathSpriteNene.visible = false; - } - } - - function playAnimation(name:String, restart:Bool, ignoreOther:Bool) { - if (name == "firstDeath") { - // Standard death animation. - createDeathSprites(); - - trace('Adding death sprites...'); - GameOverSubState.instance.add(deathSpriteRetry); - GameOverSubState.instance.add(deathSpriteNene); - GameOverSubState.instance.refresh(); - deathSpriteNene.animation.play("throw"); - } else if (name == "deathConfirm") { - deathSpriteRetry.animation.play('confirm'); - // I think the glow makes the overall animation larger, - // but a plain FlxSprite doesn't have an animation offset option so we do it manually. - deathSpriteRetry.x -= 250; - deathSpriteRetry.y -= 200; - // Skip playing the animation. - return; - } - - super.playAnimation(name, restart, ignoreOther); - } - - override function onGameOver(event:ScriptEvent):Void { - super.onGameOver(event); - } - - override function onSongRetry(event:ScriptEvent):Void { - super.onSongRetry(event); - - // Reset to standard death animation. - GameOverSubState.musicSuffix = '-pico'; - GameOverSubState.blueBallSuffix = '-pico'; - - PauseSubState.musicSuffix = '-pico'; - - this.visible = true; - } - - function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) { - super.onAnimationFrame(name, frameNumber, frameIndex); - - if (name == "firstDeath" && frameNumber == 36 - 1) { - deathSpriteRetry.animation.play('idle'); - deathSpriteRetry.visible = true; - GameOverSubState.instance.startDeathMusic(1.0, false); - // force the deathloop to play in here, since we are starting the music early it - // doesn't check this in gameover substate ! - // also no animation suffix 🤔 - GameOverSubState.instance.boyfriend.playAnimation('deathLoop'); - - deathSpriteRetry.x = this.x + 416; - deathSpriteRetry.y = this.y + 42; - } - } - - function addToStage(sprite:FlxSprite) { - if (this.debug) { - // We are in the chart editor or something. - // TODO: Make this work properly. - } else if (PlayState.instance != null && PlayState.instance.currentStage != null) { - PlayState.instance.currentStage.add(sprite); - } else { - trace('Could not add Pico sprite to stage.'); - } - } + * for use later. + */ + function createDeathSprites() + { + // trace('PICO: Creating death sprites'); + deathSpriteRetry = FunkinSprite.createSparrow(0, 0, "characters/Pico_Death_Retry"); + deathSpriteRetry.animation.addByPrefix('idle', "Retry Text Loop0", 24, true); + deathSpriteRetry.animation.addByPrefix('confirm', "Retry Text Confirm0", 24, false); + + deathSpriteRetry.zIndex = this.zIndex + 5; + + deathSpriteRetry.visible = false; + + // FlxG.debugger.track(deathSpriteRetry); + + deathSpriteNene = FunkinSprite.createSparrow(0, 0, "characters/neneChristmas/neneChristmasKnife"); + var gf = PlayState.instance.currentStage.getGirlfriend(); + deathSpriteNene.x = gf.originalPosition.x; // + 280; + deathSpriteNene.y = gf.originalPosition.y; // + 70; + deathSpriteNene.zIndex = this.zIndex - 5; + deathSpriteNene.animation.addByPrefix('throw', "knife toss xmas0", 24, false); + deathSpriteNene.visible = true; + deathSpriteNene.animation.finishCallback = function(name:String) { + deathSpriteNene.visible = false; + } + } + + function playAnimation(name:String, restart:Bool, ignoreOther:Bool) + { + if (name == "firstDeath") + { + // Standard death animation. + createDeathSprites(); + + trace('Adding death sprites...'); + GameOverSubState.instance.add(deathSpriteRetry); + GameOverSubState.instance.add(deathSpriteNene); + GameOverSubState.instance.refresh(); + deathSpriteNene.animation.play("throw"); + } + else if (name == "deathConfirm") + { + deathSpriteRetry.animation.play('confirm'); + // I think the glow makes the overall animation larger, + // but a plain FlxSprite doesn't have an animation offset option so we do it manually. + deathSpriteRetry.x -= 250; + deathSpriteRetry.y -= 200; + // Skip playing the animation. + return; + } + + super.playAnimation(name, restart, ignoreOther); + } + + override function onGameOver(event:ScriptEvent):Void + { + super.onGameOver(event); + } + + override function onSongRetry(event:ScriptEvent):Void + { + super.onSongRetry(event); + + // Reset to standard death animation. + GameOverSubState.musicSuffix = '-pico'; + GameOverSubState.blueBallSuffix = '-pico'; + + PauseSubState.musicSuffix = '-pico'; + + this.visible = true; + } + + function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) + { + super.onAnimationFrame(name, frameNumber, frameIndex); + + if (name == "firstDeath" && frameNumber == 36 - 1) + { + deathSpriteRetry.animation.play('idle'); + deathSpriteRetry.visible = true; + GameOverSubState.instance.startDeathMusic(1.0, false); + // force the deathloop to play in here, since we are starting the music early it + // doesn't check this in gameover substate ! + // also no animation suffix 🤔 + GameOverSubState.instance.boyfriend.playAnimation('deathLoop'); + + deathSpriteRetry.x = this.x + 416; + deathSpriteRetry.y = this.y + 42; + } + } + + function addToStage(sprite:FlxSprite) + { + if (this.debug) + { + // We are in the chart editor or something. + // TODO: Make this work properly. + } + else if (PlayState.instance != null && PlayState.instance.currentStage != null) + { + PlayState.instance.currentStage.add(sprite); + } + else + { + trace('Could not add Pico sprite to stage.'); + } + } } diff --git a/preload/scripts/characters/pico-dark.hxc b/preload/scripts/characters/pico-dark.hxc index 344505e3e..873864a70 100644 --- a/preload/scripts/characters/pico-dark.hxc +++ b/preload/scripts/characters/pico-dark.hxc @@ -11,104 +11,115 @@ import funkin.graphics.FunkinSprite; import funkin.play.PauseSubState; import funkin.play.PlayState; -class PicoDarkCharacter extends MultiSparrowCharacter { - function new() { - super('pico-dark'); - } +class PicoDarkCharacter extends MultiSparrowCharacter +{ + function new() + { + super('pico-dark'); + } var normalChar:BaseCharacter; - override function set_alpha(val:Float):Float{ - super.set_alpha(val); - if(val != 1) - normalChar.alpha = 1; - else - normalChar.alpha = 0; + override function set_alpha(val:Float):Float + { + super.set_alpha(val); + if (val != 1) normalChar.alpha = 1; + else + normalChar.alpha = 0; return val; - } - - override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) { - if (name == "firstDeath") { - createDeathSprites(); - - GameOverSubState.instance.add(deathSpriteRetry); - GameOverSubState.instance.add(deathSpriteNene); - deathSpriteNene.animation.play("throw"); - } else if (name == "deathConfirm") { - deathSpriteRetry.animation.play('confirm'); - // I think the glow makes the overall animation larger, - // but a plain FlxSprite doesn't have an animation offset option so we do it manually. - deathSpriteRetry.x -= 250; - deathSpriteRetry.y -= 200; - // Skip playing the animation. - return; - } - - super.playAnimation(name, restart, ignoreOther); - if(normalChar != null){ - normalChar.playAnimation(name, restart, ignoreOther); - normalChar.setPosition(this.x, this.y); - } - } - - function onCreate(event:ScriptEvent) { - super.onCreate(event); - normalChar = CharacterDataParser.fetchCharacter('pico-playable'); + } + + override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) + { + if (name == "firstDeath") + { + createDeathSprites(); + + GameOverSubState.instance.add(deathSpriteRetry); + GameOverSubState.instance.add(deathSpriteNene); + deathSpriteNene.animation.play("throw"); + } + else if (name == "deathConfirm") + { + deathSpriteRetry.animation.play('confirm'); + // I think the glow makes the overall animation larger, + // but a plain FlxSprite doesn't have an animation offset option so we do it manually. + deathSpriteRetry.x -= 250; + deathSpriteRetry.y -= 200; + // Skip playing the animation. + return; + } + + super.playAnimation(name, restart, ignoreOther); + if (normalChar != null) + { + normalChar.playAnimation(name, restart, ignoreOther); + normalChar.setPosition(this.x, this.y); + } + } + + function onCreate(event:ScriptEvent) + { + super.onCreate(event); + normalChar = CharacterDataParser.fetchCharacter('pico-playable'); normalChar.zIndex = 199; - normalChar.alpha = 0; + normalChar.alpha = 0; normalChar.flipX = false; - GameOverSubState.musicSuffix = '-pico'; - GameOverSubState.blueBallSuffix = '-pico'; + GameOverSubState.musicSuffix = '-pico'; + GameOverSubState.blueBallSuffix = '-pico'; - PauseSubState.musicSuffix = '-pico'; + PauseSubState.musicSuffix = '-pico'; - PlayState.instance.currentStage.add(normalChar); - PlayState.instance.currentStage.refresh(); // Apply z-index. - } + PlayState.instance.currentStage.add(normalChar); + PlayState.instance.currentStage.refresh(); // Apply z-index. + } - var deathSpriteRetry:FunkinSprite; - var deathSpriteNene:FunkinSprite; + var deathSpriteRetry:FunkinSprite; + var deathSpriteNene:FunkinSprite; - /** + /** * Initialize and cache sprites used for the death animation, - * for use later. - */ - function createDeathSprites() { - deathSpriteRetry = FunkinSprite.createSparrow(0, 0, "characters/Pico_Death_Retry"); - deathSpriteRetry.animation.addByPrefix('idle', "Retry Text Loop0", 24, true); - deathSpriteRetry.animation.addByPrefix('confirm', "Retry Text Confirm0", 24, false); - - deathSpriteRetry.visible = false; - - //FlxG.debugger.track(deathSpriteRetry); - - deathSpriteNene = FunkinSprite.createSparrow(0, 0, "characters/NeneKnifeToss"); - var gf = PlayState.instance.currentStage.getGirlfriend(); - deathSpriteNene.x = gf.originalPosition.x + 120;// + 280; - deathSpriteNene.y = gf.originalPosition.y - 200;// + 70; - deathSpriteNene.animation.addByPrefix('throw', "knife toss0", 24, false); - deathSpriteNene.visible = true; - deathSpriteNene.animation.finishCallback = function(name:String) { - deathSpriteNene.visible = false; - } - } - - function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) { - super.onAnimationFrame(name, frameNumber, frameIndex); - - if (name == "firstDeath" && frameNumber == 36 - 1) { - deathSpriteRetry.animation.play('idle'); - deathSpriteRetry.visible = true; - GameOverSubState.instance.startDeathMusic(1.0, false); - // force the deathloop to play in here, since we are starting the music early it - // doesn't check this in gameover substate ! - // also no animation suffix 🤔 - GameOverSubState.instance.boyfriend.playAnimation('deathLoop'); - - deathSpriteRetry.x = this.x + 195; - deathSpriteRetry.y = this.y - 70; - } - } + * for use later. + */ + function createDeathSprites() + { + deathSpriteRetry = FunkinSprite.createSparrow(0, 0, "characters/Pico_Death_Retry"); + deathSpriteRetry.animation.addByPrefix('idle', "Retry Text Loop0", 24, true); + deathSpriteRetry.animation.addByPrefix('confirm', "Retry Text Confirm0", 24, false); + + deathSpriteRetry.visible = false; + + // FlxG.debugger.track(deathSpriteRetry); + + deathSpriteNene = FunkinSprite.createSparrow(0, 0, "characters/NeneKnifeToss"); + var gf = PlayState.instance.currentStage.getGirlfriend(); + deathSpriteNene.x = gf.originalPosition.x + 120; // + 280; + deathSpriteNene.y = gf.originalPosition.y - 200; // + 70; + deathSpriteNene.animation.addByPrefix('throw', "knife toss0", 24, false); + deathSpriteNene.visible = true; + deathSpriteNene.animation.finishCallback = function(name:String) { + deathSpriteNene.visible = false; + } + } + + function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) + { + super.onAnimationFrame(name, frameNumber, frameIndex); + + if (name == "firstDeath" && frameNumber == 36 - 1) + { + deathSpriteRetry.animation.play('idle'); + deathSpriteRetry.visible = true; + GameOverSubState.instance.startDeathMusic(1.0, false); + // force the deathloop to play in here, since we are starting the music early it + // doesn't check this in gameover substate ! + // also no animation suffix 🤔 + GameOverSubState.instance.boyfriend.playAnimation('deathLoop'); + + deathSpriteRetry.x = this.x + 195; + deathSpriteRetry.y = this.y - 70; + } + } } diff --git a/preload/scripts/characters/pico-playable.hxc b/preload/scripts/characters/pico-playable.hxc index f7f31c3ed..c7096bf1f 100644 --- a/preload/scripts/characters/pico-playable.hxc +++ b/preload/scripts/characters/pico-playable.hxc @@ -15,337 +15,387 @@ import funkin.play.PauseSubState; import funkin.modding.module.ModuleHandler; import flixel.tweens.FlxTween; - -class PicoPlayerCharacter extends MultiSparrowCharacter { - function new() { - super('pico-playable'); +class PicoPlayerCharacter extends MultiSparrowCharacter +{ + function new() + { + super('pico-playable'); ignoreExclusionPref.push("shoot"); - } + } - function onCreate(event:ScriptEvent) { - super.onCreate(event); + function onCreate(event:ScriptEvent) + { + super.onCreate(event); - // NOTE: this.x and this.y are not properly set here. + // NOTE: this.x and this.y are not properly set here. - GameOverSubState.musicSuffix = '-pico'; - GameOverSubState.blueBallSuffix = '-pico'; + GameOverSubState.musicSuffix = '-pico'; + GameOverSubState.blueBallSuffix = '-pico'; - PauseSubState.musicSuffix = '-pico'; - } + PauseSubState.musicSuffix = '-pico'; + } - var deathSpriteRetry:FunkinSprite; - var deathSpriteNene:FunkinSprite; + var deathSpriteRetry:FunkinSprite; + var deathSpriteNene:FunkinSprite; - var picoFade:FunkinSprite; + var picoFade:FunkinSprite; - /** + /** * Initialize and cache sprites used for the death animation, - * for use later. - */ - function createDeathSprites() { - deathSpriteRetry = FunkinSprite.createSparrow(0, 0, "characters/Pico_Death_Retry"); - deathSpriteRetry.animation.addByPrefix('idle', "Retry Text Loop0", 24, true); - deathSpriteRetry.animation.addByPrefix('confirm', "Retry Text Confirm0", 24, false); - - deathSpriteRetry.visible = false; - - //FlxG.debugger.track(deathSpriteRetry); - - deathSpriteNene = FunkinSprite.createSparrow(0, 0, "characters/NeneKnifeToss"); - var gf = PlayState.instance.currentStage.getGirlfriend(); - deathSpriteNene.x = gf.originalPosition.x + 120;// + 280; - deathSpriteNene.y = gf.originalPosition.y - 200;// + 70; - deathSpriteNene.animation.addByPrefix('throw', "knife toss0", 24, false); - deathSpriteNene.visible = true; - deathSpriteNene.animation.finishCallback = function(name:String) { - deathSpriteNene.visible = false; - } - } - - function onNoteHit(event:HitNoteScriptEvent) - { - if (event.eventCanceled) { - // onNoteHit event was cancelled by the gameplay module. - return; - } - - if (event.note.noteData.getMustHitNote() && characterType == CharacterType.BF) { - // Override the hit note animation. - switch(event.note.kind) { - case "censor": - holdTimer = 0; - this.playSingAnimation(event.note.noteData.getDirection(), false, 'censor'); - return; - case "weekend-1-cockgun": // HE'S PULLING HIS COCK OUT - holdTimer = 0; - playCockGunAnim(); - case "weekend-1-firegun": - holdTimer = 0; - playFireGunAnim(); - default: - super.onNoteHit(event); - } - } - } - - function onNoteMiss(event:NoteScriptEvent) - { - // Override the miss note animation. - switch(event.note.kind) { - case "weekend-1-cockgun": - //playCockMissAnim(); - case "weekend-1-firegun": - playCanExplodeAnim(); - default: - super.onNoteMiss(event); - } - } - - function playAnimation(name:String, restart:Bool, ignoreOther:Bool) { - // restore vocal volume to ensure burps always play - // not needed on the dark variant because this one always exists anyway.. - if(name == "burpSmile" || name == "burpSmileLong") PlayState.instance.vocals.playerVolume = 1; - - if (name == "firstDeath") { - if (GameOverSubState.blueBallSuffix == '-pico-explode') { - // Explosion death animation. - doExplosionDeath(); - } else { - // Standard death animation. - createDeathSprites(); - - GameOverSubState.instance.add(deathSpriteRetry); - GameOverSubState.instance.add(deathSpriteNene); - deathSpriteNene.animation.play("throw"); - } - } else if (name == "deathConfirm") { - if (picoDeathExplosion != null) { - doExplosionConfirm(); - } else { - deathSpriteRetry.animation.play('confirm'); - // I think the glow makes the overall animation larger, - // but a plain FlxSprite doesn't have an animation offset option so we do it manually. - deathSpriteRetry.x -= 250; - deathSpriteRetry.y -= 200; - - // Skip playing the animation. - return; - } - } - - super.playAnimation(name, restart, ignoreOther); - } - - var picoFlicker:FlxFlicker = null; - - override function onAnimationFinished(name:String) { - super.onAnimationFinished(name); - - if (name == 'shootMISS' && PlayState.instance.health > 0.0 && !PlayState.instance.isPlayerDying) { - // ERIC: You have to use super instead of this or it breaks. - // This is because typeof(this) is PolymodAbstractClass. + * for use later. + */ + function createDeathSprites() + { + deathSpriteRetry = FunkinSprite.createSparrow(0, 0, "characters/Pico_Death_Retry"); + deathSpriteRetry.animation.addByPrefix('idle', "Retry Text Loop0", 24, true); + deathSpriteRetry.animation.addByPrefix('confirm', "Retry Text Confirm0", 24, false); + + deathSpriteRetry.visible = false; + + // FlxG.debugger.track(deathSpriteRetry); + + deathSpriteNene = FunkinSprite.createSparrow(0, 0, "characters/NeneKnifeToss"); + var gf = PlayState.instance.currentStage.getGirlfriend(); + deathSpriteNene.x = gf.originalPosition.x + 120; // + 280; + deathSpriteNene.y = gf.originalPosition.y - 200; // + 70; + deathSpriteNene.animation.addByPrefix('throw', "knife toss0", 24, false); + deathSpriteNene.visible = true; + deathSpriteNene.animation.finishCallback = function(name:String) { + deathSpriteNene.visible = false; + } + } + + function onNoteHit(event:HitNoteScriptEvent) + { + if (event.eventCanceled) + { + // onNoteHit event was cancelled by the gameplay module. + return; + } + + if (event.note.noteData.getMustHitNote() && characterType == CharacterType.BF) + { + // Override the hit note animation. + switch (event.note.kind) + { + case "censor": + holdTimer = 0; + this.playSingAnimation(event.note.noteData.getDirection(), false, 'censor'); + return; + case "weekend-1-cockgun": // HE'S PULLING HIS COCK OUT + holdTimer = 0; + playCockGunAnim(); + case "weekend-1-firegun": + holdTimer = 0; + playFireGunAnim(); + default: + super.onNoteHit(event); + } + } + } + + function onNoteMiss(event:NoteScriptEvent) + { + // Override the miss note animation. + switch (event.note.kind) + { + case "weekend-1-cockgun": + // playCockMissAnim(); + case "weekend-1-firegun": + playCanExplodeAnim(); + default: + super.onNoteMiss(event); + } + } + + function playAnimation(name:String, restart:Bool, ignoreOther:Bool) + { + // restore vocal volume to ensure burps always play + // not needed on the dark variant because this one always exists anyway.. + if (name == "burpSmile" || name == "burpSmileLong") PlayState.instance.vocals.playerVolume = 1; + + if (name == "firstDeath") + { + if (GameOverSubState.blueBallSuffix == '-pico-explode') + { + // Explosion death animation. + doExplosionDeath(); + } + else + { + // Standard death animation. + createDeathSprites(); + + GameOverSubState.instance.add(deathSpriteRetry); + GameOverSubState.instance.add(deathSpriteNene); + deathSpriteNene.animation.play("throw"); + } + } + else if (name == "deathConfirm") + { + if (picoDeathExplosion != null) + { + doExplosionConfirm(); + } + else + { + deathSpriteRetry.animation.play('confirm'); + // I think the glow makes the overall animation larger, + // but a plain FlxSprite doesn't have an animation offset option so we do it manually. + deathSpriteRetry.x -= 250; + deathSpriteRetry.y -= 200; + + // Skip playing the animation. + return; + } + } + + super.playAnimation(name, restart, ignoreOther); + } + + var picoFlicker:FlxFlicker = null; + + override function onAnimationFinished(name:String) + { + super.onAnimationFinished(name); + + if (name == 'shootMISS' && PlayState.instance.health > 0.0 && !PlayState.instance.isPlayerDying) + { + // ERIC: You have to use super instead of this or it breaks. + // This is because typeof(this) is PolymodAbstractClass. picoFlicker = FlxFlicker.flicker(super, 1, 1 / 30, true, true, function(_) { picoFlicker = FlxFlicker.flicker(super, 0.5, 1 / 60, true, true, function(_) { - picoFlicker = null; - }); + picoFlicker = null; + }); }); - } - } - - public override function onPause(event:PauseScriptEvent) { - super.onPause(event); - - if (picoFlicker != null) { - picoFlicker.pause(); - this.visible = true; - } - } - - public override function onResume(event:ScriptEvent) { - super.onResume(event); - - if (picoFlicker != null) { - picoFlicker.resume(); - } - } - - public override function getDeathCameraOffsets():Array { - var result = super.getDeathCameraOffsets(); - - if (GameOverSubState.blueBallSuffix == '-pico-explode') { - return [result[0], result[1] + 100]; - } - - return [result[0], result[1]]; - } - - var picoDeathExplosion:FlxAtlasSprite; - - function doExplosionDeath() { - - if (picoFlicker != null) { - picoFlicker.stop(); // this sets visible to true, but we make it false a few lines down anyways - } - - // Suffixed death sound will already play. - GameOverSubState.instance.resetCameraZoom(); - - // Move the camera up. - GameOverSubState.instance.cameraFollowPoint.y -= 100; - - var picoDeathExplosionPath = Paths.animateAtlas("characters/picoExplosionDeath", "weekend1"); - picoDeathExplosion = new FlxAtlasSprite(this.x - 640, this.y - 340, picoDeathExplosionPath); + } + } + + public override function onPause(event:PauseScriptEvent) + { + super.onPause(event); + + if (picoFlicker != null) + { + picoFlicker.pause(); + this.visible = true; + } + } + + public override function onResume(event:ScriptEvent) + { + super.onResume(event); + + if (picoFlicker != null) + { + picoFlicker.resume(); + } + } + + public override function getDeathCameraOffsets():Array + { + var result = super.getDeathCameraOffsets(); + + if (GameOverSubState.blueBallSuffix == '-pico-explode') + { + return [result[0], result[1] + 100]; + } + + return [result[0], result[1]]; + } + + var picoDeathExplosion:FlxAtlasSprite; + + function doExplosionDeath() + { + if (picoFlicker != null) + { + picoFlicker.stop(); // this sets visible to true, but we make it false a few lines down anyways + } + + // Suffixed death sound will already play. + GameOverSubState.instance.resetCameraZoom(); + + // Move the camera up. + GameOverSubState.instance.cameraFollowPoint.y -= 100; + + var picoDeathExplosionPath = Paths.animateAtlas("characters/picoExplosionDeath", "weekend1"); + picoDeathExplosion = new FlxAtlasSprite(this.x - 640, this.y - 340, picoDeathExplosionPath); PlayState.instance.subState.add(picoDeathExplosion); - picoDeathExplosion.zIndex = 1000; + picoDeathExplosion.zIndex = 1000; picoDeathExplosion.onAnimationFinish.add(onExplosionFinishAnim); picoDeathExplosion.visible = true; - this.visible = false; + this.visible = false; - new FlxTimer().start(3.0, afterPicoDeathExplosionIntro); + new FlxTimer().start(3.0, afterPicoDeathExplosionIntro); picoDeathExplosion.playAnimation('intro'); - - } - - var singed:FunkinSound; - function afterPicoDeathExplosionIntro(timer:FlxTimer) { - // Start the (standard) death music, 3.5 seconds after the explosion starts, - // not when the explosion sound finishes or when the loop starts. - GameOverSubState.instance.startDeathMusic(1.0, false); - singed = FunkinSound.load(Paths.sound('singed_loop'), true, false, true); - // singed.fadeIn(0.5, 0.3, 1.0); - } - - function doExplosionConfirm() { - // Suffixed confirm music will already play. - picoDeathExplosion.playAnimation('Confirm'); - if (singed != null) { - singed.stop(); - singed = null; - } - } - - function onExplosionFinishAnim(animLabel:String) { - if (animLabel == 'intro') { + } + + var singed:FunkinSound; + + function afterPicoDeathExplosionIntro(timer:FlxTimer) + { + // Start the (standard) death music, 3.5 seconds after the explosion starts, + // not when the explosion sound finishes or when the loop starts. + GameOverSubState.instance.startDeathMusic(1.0, false); + singed = FunkinSound.load(Paths.sound('singed_loop'), true, false, true); + // singed.fadeIn(0.5, 0.3, 1.0); + } + + function doExplosionConfirm() + { + // Suffixed confirm music will already play. + picoDeathExplosion.playAnimation('Confirm'); + if (singed != null) + { + singed.stop(); + singed = null; + } + } + + function onExplosionFinishAnim(animLabel:String) + { + if (animLabel == 'intro') + { picoDeathExplosion.playAnimation('Loop Start', true, false, true); - } else if (animLabel == 'Confirm') { - // Do nothing, the animation will just play. - } - } - - override function onGameOver(event:ScriptEvent):Void { - super.onGameOver(event); - } - - override function onSongRetry(event:ScriptEvent):Void { - super.onSongRetry(event); - - // Don't let these pile up. - clearCasings(); - - // Reset to standard death animation. - GameOverSubState.musicSuffix = '-pico'; - GameOverSubState.blueBallSuffix = '-pico'; - - PauseSubState.musicSuffix = '-pico'; - - picoDeathExplosion = null; - this.visible = true; - } - - function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) { - super.onAnimationFrame(name, frameNumber, frameIndex); - - if (name == "firstDeath" && frameNumber == 36 - 1) { - deathSpriteRetry.animation.play('idle'); - deathSpriteRetry.visible = true; - GameOverSubState.instance.startDeathMusic(1.0, false); - // force the deathloop to play in here, since we are starting the music early it - // doesn't check this in gameover substate ! - // also no animation suffix 🤔 - GameOverSubState.instance.boyfriend.playAnimation('deathLoop'); - - deathSpriteRetry.x = this.x + 195; - deathSpriteRetry.y = this.y - 70; - } - - if (name == "cock" && frameNumber == 3) { - createCasing(); - } - } - - var casingGroup:FlxTypedSpriteGroup; - - function createCasing() { - if (casingGroup == null) { - casingGroup = new FlxTypedSpriteGroup(); - casingGroup.x = this.x + 250; - casingGroup.y = this.y + 100; - casingGroup.zIndex = 1000; - addToStage(casingGroup); - } - - var casing = ScriptedFunkinSprite.init('CasingSprite', 0, 0); - if (casing != null) - casingGroup.add(casing); - } - - function clearCasings() { - // Clear the casing group. - if (casingGroup != null) { - casingGroup.clear(); - casingGroup = null; - } - } - - /** - * Play the animation where Pico readies his gun to shoot the can. - */ - function playCockGunAnim() { - this.playAnimation('cock', true, true); - - picoFade = new FlxSprite(0, 0); - picoFade.frames = this.frames; - picoFade.frame = this.frame; - picoFade.updateHitbox(); - picoFade.x = this.x; - picoFade.y = this.y; - // picoFade.stamp(this, 0, 0); - picoFade.alpha = 0.3; - picoFade.zIndex = this.zIndex - 3; - addToStage(picoFade); - FlxTween.tween(picoFade.scale, {x: 1.3, y: 1.3}, 0.4); - FlxTween.tween(picoFade, {alpha: 0}, 0.4); - - - FunkinSound.playOnce(Paths.sound('Gun_Prep'), 1.0); - } - /** - * Play the animation where Pico shoots the can successfully. - */ - function playFireGunAnim(hip:Bool) { - this.playAnimation('shoot', true, true); - FunkinSound.playOnce(Paths.soundRandom('shot', 1, 4)); - } - /** - * Play the animation where Pico is hit by the exploding can. - */ - function playCanExplodeAnim() { - - this.playAnimation('shootMISS', true, true); - // Donk. - FunkinSound.playOnce(Paths.sound('Pico_Bonk'), 1.0); - } - - function addToStage(sprite:FlxSprite) { - if (this.debug) { - // We are in the chart editor or something. - // TODO: Make this work properly. - } else if (PlayState.instance != null && PlayState.instance.currentStage != null) { - PlayState.instance.currentStage.add(sprite); - } else { - trace('Could not add Pico sprite to stage.'); - } - } + } + else if (animLabel == 'Confirm') + { + // Do nothing, the animation will just play. + } + } + + override function onGameOver(event:ScriptEvent):Void + { + super.onGameOver(event); + } + + override function onSongRetry(event:ScriptEvent):Void + { + super.onSongRetry(event); + + // Don't let these pile up. + clearCasings(); + + // Reset to standard death animation. + GameOverSubState.musicSuffix = '-pico'; + GameOverSubState.blueBallSuffix = '-pico'; + + PauseSubState.musicSuffix = '-pico'; + + picoDeathExplosion = null; + this.visible = true; + } + + function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int) + { + super.onAnimationFrame(name, frameNumber, frameIndex); + + if (name == "firstDeath" && frameNumber == 36 - 1) + { + deathSpriteRetry.animation.play('idle'); + deathSpriteRetry.visible = true; + GameOverSubState.instance.startDeathMusic(1.0, false); + // force the deathloop to play in here, since we are starting the music early it + // doesn't check this in gameover substate ! + // also no animation suffix 🤔 + GameOverSubState.instance.boyfriend.playAnimation('deathLoop'); + + deathSpriteRetry.x = this.x + 195; + deathSpriteRetry.y = this.y - 70; + } + + if (name == "cock" && frameNumber == 3) + { + createCasing(); + } + } + + var casingGroup:FlxTypedSpriteGroup; + + function createCasing() + { + if (casingGroup == null) + { + casingGroup = new FlxTypedSpriteGroup(); + casingGroup.x = this.x + 250; + casingGroup.y = this.y + 100; + casingGroup.zIndex = 1000; + addToStage(casingGroup); + } + + var casing = ScriptedFunkinSprite.init('CasingSprite', 0, 0); + if (casing != null) casingGroup.add(casing); + } + + function clearCasings() + { + // Clear the casing group. + if (casingGroup != null) + { + casingGroup.clear(); + casingGroup = null; + } + } + + /** + * Play the animation where Pico readies his gun to shoot the can. + */ + function playCockGunAnim() + { + this.playAnimation('cock', true, true); + + picoFade = new FlxSprite(0, 0); + picoFade.frames = this.frames; + picoFade.frame = this.frame; + picoFade.updateHitbox(); + picoFade.x = this.x; + picoFade.y = this.y; + // picoFade.stamp(this, 0, 0); + picoFade.alpha = 0.3; + picoFade.zIndex = this.zIndex - 3; + addToStage(picoFade); + FlxTween.tween(picoFade.scale, {x: 1.3, y: 1.3}, 0.4); + FlxTween.tween(picoFade, {alpha: 0}, 0.4); + + FunkinSound.playOnce(Paths.sound('Gun_Prep'), 1.0); + } + + /** + * Play the animation where Pico shoots the can successfully. + */ + function playFireGunAnim(hip:Bool) + { + this.playAnimation('shoot', true, true); + FunkinSound.playOnce(Paths.soundRandom('shot', 1, 4)); + } + + /** + * Play the animation where Pico is hit by the exploding can. + */ + function playCanExplodeAnim() + { + this.playAnimation('shootMISS', true, true); + // Donk. + FunkinSound.playOnce(Paths.sound('Pico_Bonk'), 1.0); + } + + function addToStage(sprite:FlxSprite) + { + if (this.debug) + { + // We are in the chart editor or something. + // TODO: Make this work properly. + } + else if (PlayState.instance != null && PlayState.instance.currentStage != null) + { + PlayState.instance.currentStage.add(sprite); + } + else + { + trace('Could not add Pico sprite to stage.'); + } + } } diff --git a/preload/scripts/characters/pico-speaker.hxc b/preload/scripts/characters/pico-speaker.hxc index 36d266f33..ac6f09850 100644 --- a/preload/scripts/characters/pico-speaker.hxc +++ b/preload/scripts/characters/pico-speaker.hxc @@ -1,4 +1,3 @@ - import funkin.play.character.SparrowCharacter; import funkin.play.character.CharacterType; import funkin.play.PlayState; @@ -10,93 +9,105 @@ import funkin.Conductor; import funkin.util.SortUtil; import Lambda; -class PicoSpeakerCharacter extends SparrowCharacter { - var shootTimes:Array = []; - var shootDirs:Array = []; +class PicoSpeakerCharacter extends SparrowCharacter +{ + var shootTimes:Array = []; + var shootDirs:Array = []; - function new() { - super('pico-speaker'); + function new() + { + super('pico-speaker'); ignoreExclusionPref.push("shoot1"); - ignoreExclusionPref.push("shoot2"); - ignoreExclusionPref.push("shoot3"); - ignoreExclusionPref.push("shoot4"); - } + ignoreExclusionPref.push("shoot2"); + ignoreExclusionPref.push("shoot3"); + ignoreExclusionPref.push("shoot4"); + } - override function onCreate(event:ScriptEvent):Void + override function onCreate(event:ScriptEvent):Void { - super.onCreate(event); + super.onCreate(event); - this.playAnimation('idle', true, true); + this.playAnimation('idle', true, true); - initTimemap(); - } + initTimemap(); + } - override function dance(force:Bool):Void + override function dance(force:Bool):Void { - super.dance(force); - } - - function reset():Void - { - initTimemap(); - } - - function initTimemap():Void - { - trace('Initializing Pico timings...'); - shootTimes = []; - // The tankmen's timings and directions are determined - // by the chart, specifically the internal "picospeaker" difficulty. - var animChart:SongDifficulty = PlayState.instance.currentSong.getDifficulty('picospeaker'); - if (animChart == null) - { - trace('Initializing Pico (speaker) failed; no `picospeaker` chart found for this song.'); - return; - } else { - trace('Initializing Pico (speaker); found `picospeaker` chart, continuing...'); - } - var animNotes:Array = animChart.notes; - - // turns out sorting functions are completely useless in polymod right now and do nothing - // i had to sort the whole pico chart by hand im gonna go insane - animNotes.sort(function(a:SongNoteData, b:SongNoteData):Int - { - return FlxSort.byValues(FlxSort.ASCENDING, a.time, b.time); - }); + super.dance(force); + } - for (note in animNotes) - { - shootTimes.push(note.time); - shootDirs.push(note.data); - } - } + function reset():Void + { + initTimemap(); + } - override function onUpdate(event:UpdateScriptEvent):Void - { - super.onUpdate(event); + function initTimemap():Void + { + trace('Initializing Pico timings...'); + shootTimes = []; + // The tankmen's timings and directions are determined + // by the chart, specifically the internal "picospeaker" difficulty. + var animChart:SongDifficulty = PlayState.instance.currentSong.getDifficulty('picospeaker'); + if (animChart == null) + { + trace('Initializing Pico (speaker) failed; no `picospeaker` chart found for this song.'); + return; + } + else + { + trace('Initializing Pico (speaker); found `picospeaker` chart, continuing...'); + } + var animNotes:Array = animChart.notes; + + // turns out sorting functions are completely useless in polymod right now and do nothing + // i had to sort the whole pico chart by hand im gonna go insane + animNotes.sort(function(a:SongNoteData, b:SongNoteData):Int { + return FlxSort.byValues(FlxSort.ASCENDING, a.time, b.time); + }); + + for (note in animNotes) + { + shootTimes.push(note.time); + shootDirs.push(note.data); + } + } + + override function onUpdate(event:UpdateScriptEvent):Void + { + super.onUpdate(event); // Each Pico animation is shifted from the array when it's time to play it. - if (shootTimes.length > 0 && shootTimes[0] <= Conductor.instance.songPosition) { - var nextTime:Float = shootTimes.shift(); - var nextDir:Int = shootDirs.shift(); - - if(nextDir == 3){ - nextDir -= FlxG.random.int(0, 1); - }else{ - nextDir += FlxG.random.int(0, 1); - } - playPicoAnimation(nextDir); - } - } - - function playPicoAnimation(direction:Int):Void + if (shootTimes.length > 0 && shootTimes[0] <= Conductor.instance.songPosition) + { + var nextTime:Float = shootTimes.shift(); + var nextDir:Int = shootDirs.shift(); + + if (nextDir == 3) + { + nextDir -= FlxG.random.int(0, 1); + } + else + { + nextDir += FlxG.random.int(0, 1); + } + playPicoAnimation(nextDir); + } + } + + function playPicoAnimation(direction:Int):Void { - switch (direction) { - case 0: this.playAnimation('shoot1', true, true); - case 1: this.playAnimation('shoot2', true, true); - case 2: this.playAnimation('shoot3', true, true); - case 3: this.playAnimation('shoot4', true, true); - } - } + switch (direction) + { + case 0: + this.playAnimation('shoot1', true, true); + case 1: + this.playAnimation('shoot2', true, true); + case 2: + this.playAnimation('shoot3', true, true); + case 3: + this.playAnimation('shoot4', true, true); + } + } } diff --git a/preload/scripts/characters/spirit.hxc b/preload/scripts/characters/spirit.hxc index f24e413b6..967fef3c7 100644 --- a/preload/scripts/characters/spirit.hxc +++ b/preload/scripts/characters/spirit.hxc @@ -3,28 +3,35 @@ import funkin.play.PlayState; import flixel.addons.effects.FlxTrail; import funkin.effects.FunkTrail; -class SpiritCharacter extends PackerCharacter { - function new() { - super('spirit'); - } +class SpiritCharacter extends PackerCharacter +{ + function new() + { + super('spirit'); + } - function onCreate(event:ScriptEvent) { - super.onCreate(event); + function onCreate(event:ScriptEvent) + { + super.onCreate(event); - // Weird workaround because `this` is a PolymodScriptClass and not a ScriptedPackerCharacter. - var evilTrail = new FunkTrail(this.superClass, null, 4, 24, 0.3, 0.069); + // Weird workaround because `this` is a PolymodScriptClass and not a ScriptedPackerCharacter. + var evilTrail = new FunkTrail(this.superClass, null, 4, 24, 0.3, 0.069); - // Go behind Spirit. - evilTrail.zIndex = 190; - addToStage(evilTrail); - } + // Go behind Spirit. + evilTrail.zIndex = 190; + addToStage(evilTrail); + } - function addToStage(sprite:FlxSprite) { - if (this.debug) { - // We are in the chart editor or something. - FlxG.stage.add(sprite); - } else { - PlayState.instance.currentStage.add(sprite); - } - } + function addToStage(sprite:FlxSprite) + { + if (this.debug) + { + // We are in the chart editor or something. + FlxG.stage.add(sprite); + } + else + { + PlayState.instance.currentStage.add(sprite); + } + } } diff --git a/preload/scripts/characters/spooky-dark.hxc b/preload/scripts/characters/spooky-dark.hxc index deab7ce6b..f9af22d4b 100644 --- a/preload/scripts/characters/spooky-dark.hxc +++ b/preload/scripts/characters/spooky-dark.hxc @@ -8,40 +8,44 @@ import funkin.play.character.CharacterDataParser; import funkin.play.character.CharacterType; import funkin.play.PlayState; -class SpookyDarkCharacter extends SparrowCharacter { - function new() { - super('spooky-dark'); - } +class SpookyDarkCharacter extends SparrowCharacter +{ + function new() + { + super('spooky-dark'); + } var normalChar:BaseCharacter; - override function set_alpha(val:Float):Float{ - super.set_alpha(val); - if(val != 1) - normalChar.alpha = 1; - else - normalChar.alpha = 0; + override function set_alpha(val:Float):Float + { + super.set_alpha(val); + if (val != 1) normalChar.alpha = 1; + else + normalChar.alpha = 0; return val; - } - - override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) { - super.playAnimation(name, restart, ignoreOther); - if(normalChar != null){ - normalChar.playAnimation(name, restart, ignoreOther); - normalChar.setPosition(this.x, this.y); - } - } - - function onCreate(event:ScriptEvent) { - super.onCreate(event); - normalChar = CharacterDataParser.fetchCharacter('spooky'); + } + + override function playAnimation(name:String, restart:Bool, ignoreOther:Bool) + { + super.playAnimation(name, restart, ignoreOther); + if (normalChar != null) + { + normalChar.playAnimation(name, restart, ignoreOther); + normalChar.setPosition(this.x, this.y); + } + } + + function onCreate(event:ScriptEvent) + { + super.onCreate(event); + normalChar = CharacterDataParser.fetchCharacter('spooky'); normalChar.zIndex = 199; - normalChar.alpha = 0; + normalChar.alpha = 0; normalChar.flipX = false; - PlayState.instance.currentStage.add(normalChar); - PlayState.instance.currentStage.refresh(); // Apply z-index. - } - + PlayState.instance.currentStage.add(normalChar); + PlayState.instance.currentStage.refresh(); // Apply z-index. + } } diff --git a/preload/scripts/characters/tankman-atlas.hxc b/preload/scripts/characters/tankman-atlas.hxc index ab783fbd1..f7dc27c0c 100644 --- a/preload/scripts/characters/tankman-atlas.hxc +++ b/preload/scripts/characters/tankman-atlas.hxc @@ -5,27 +5,31 @@ import funkin.play.PlayState; /** * A prototype variant of Tankman that uses the Adobe Animate Texture Atlas animation system. */ -class TankmanAtlasCharacter extends AnimateAtlasCharacter { - function new() { - super('tankman-atlas'); - } +class TankmanAtlasCharacter extends AnimateAtlasCharacter +{ + function new() + { + super('tankman-atlas'); + } - function onNoteHit(event:HitNoteScriptEvent) - { - if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) { - // Override the hit note animation. - switch(event.note.kind) { - case "ugh": - holdTimer = 0; - this.playAnimFbfation('ugh'); - return; - case "hehPrettyGood": - holdTimer = 0; - this.playAnimation('hehPrettyGood'); - return; - } - } + function onNoteHit(event:HitNoteScriptEvent) + { + if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) + { + // Override the hit note animation. + switch (event.note.kind) + { + case "ugh": + holdTimer = 0; + this.playAnimFbfation('ugh'); + return; + case "hehPrettyGood": + holdTimer = 0; + this.playAnimation('hehPrettyGood'); + return; + } + } - super.onNoteHit(event); - } + super.onNoteHit(event); + } } diff --git a/preload/scripts/characters/tankman.hxc b/preload/scripts/characters/tankman.hxc index 2a992b6f8..a7a001e6b 100644 --- a/preload/scripts/characters/tankman.hxc +++ b/preload/scripts/characters/tankman.hxc @@ -2,27 +2,31 @@ import funkin.play.character.MultiSparrowCharacter; import funkin.play.character.CharacterType; import funkin.play.PlayState; -class TankmanCharacter extends MultiSparrowCharacter { - function new() { - super('tankman'); - } +class TankmanCharacter extends MultiSparrowCharacter +{ + function new() + { + super('tankman'); + } - function onNoteHit(event:HitNoteScriptEvent) - { - super.onNoteHit(event); + function onNoteHit(event:HitNoteScriptEvent) + { + super.onNoteHit(event); - if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) { - // Override the hit note animation. - switch(event.note.kind) { - case "ugh": - holdTimer = 0; - this.playAnimation('ugh', true, true); - return; - case "hehPrettyGood": - holdTimer = 0; - this.playAnimation('hehPrettyGood', true, true); - return; - } - } - } + if (!event.note.noteData.getMustHitNote() && characterType == CharacterType.DAD) + { + // Override the hit note animation. + switch (event.note.kind) + { + case "ugh": + holdTimer = 0; + this.playAnimation('ugh', true, true); + return; + case "hehPrettyGood": + holdTimer = 0; + this.playAnimation('hehPrettyGood', true, true); + return; + } + } + } } diff --git a/preload/scripts/dialogue/boxes/roses.hxc b/preload/scripts/dialogue/boxes/roses.hxc index 15c44de85..015cecae7 100644 --- a/preload/scripts/dialogue/boxes/roses.hxc +++ b/preload/scripts/dialogue/boxes/roses.hxc @@ -3,43 +3,55 @@ import flixel.tweens.FlxTween; import funkin.play.cutscene.dialogue.ConversationState; import funkin.play.cutscene.dialogue.DialogueBox; -class RosesDialogueBox extends DialogueBox { - function new() { - super('roses'); - } +class RosesDialogueBox extends DialogueBox +{ + function new() + { + super('roses'); + } - public function onDialogueLine(event:DialogueScriptEvent):Void { + public function onDialogueLine(event:DialogueScriptEvent):Void + { super.onDialogueLine(event); - if (getCurrentAnimation() == 'idle') { + if (getCurrentAnimation() == 'idle') + { // click, then speaking playAnimation('click'); - } else if (getCurrentAnimation() == 'click') { + } + else if (getCurrentAnimation() == 'click') + { playAnimation('speaking'); } } - function onAnimationFinished(name:String):Void { + function onAnimationFinished(name:String):Void + { super.onAnimationFinished(name); - if (name == 'sentenceEnd') { + if (name == 'sentenceEnd') + { playAnimation('idle'); } - if (name == 'click') { + if (name == 'click') + { playAnimation('speaking'); } } - function onTypingComplete():Void { + function onTypingComplete():Void + { playAnimation('sentenceEnd'); super.onTypingComplete(); } - public function onDialogueStart(event:DialogueScriptEvent):Void { + public function onDialogueStart(event:DialogueScriptEvent):Void + { super.onDialogueStart(event); } - public function onDialogueLine(event:DialogueScriptEvent):Void { + public function onDialogueLine(event:DialogueScriptEvent):Void + { // Override the default box animation behavior by switching the state event.conversation.state = ConversationState.Opening; @@ -47,7 +59,8 @@ class RosesDialogueBox extends DialogueBox { super.onDialogueEnd(event); } - public function onDialogueEnd(event:DialogueScriptEvent):Void { + public function onDialogueEnd(event:DialogueScriptEvent):Void + { super.onDialogueEnd(event); // Play 'enter' in reverse this.textDisplay.visible = false; @@ -55,7 +68,8 @@ class RosesDialogueBox extends DialogueBox { playAnimation('exit', false); } - override function onDestroy(event:ScriptEvent) { + override function onDestroy(event:ScriptEvent) + { super.onDestroy(event); } } diff --git a/preload/scripts/dialogue/boxes/thorns.hxc b/preload/scripts/dialogue/boxes/thorns.hxc index a79fa460e..b2279d321 100644 --- a/preload/scripts/dialogue/boxes/thorns.hxc +++ b/preload/scripts/dialogue/boxes/thorns.hxc @@ -3,43 +3,55 @@ import flixel.tweens.FlxTween; import funkin.play.cutscene.dialogue.ConversationState; import funkin.play.cutscene.dialogue.DialogueBox; -class ThornsDialogueBox extends DialogueBox { - function new() { - super('thorns'); - } +class ThornsDialogueBox extends DialogueBox +{ + function new() + { + super('thorns'); + } - public function onDialogueLine(event:DialogueScriptEvent):Void { + public function onDialogueLine(event:DialogueScriptEvent):Void + { super.onDialogueLine(event); - if (getCurrentAnimation() == 'idle') { + if (getCurrentAnimation() == 'idle') + { // click, then speaking playAnimation('click'); - } else if (getCurrentAnimation() == 'click') { + } + else if (getCurrentAnimation() == 'click') + { playAnimation('speaking'); } } - function onAnimationFinished(name:String):Void { + function onAnimationFinished(name:String):Void + { super.onAnimationFinished(name); - if (name == 'sentenceEnd') { + if (name == 'sentenceEnd') + { playAnimation('idle'); } - if (name == 'click') { + if (name == 'click') + { playAnimation('speaking'); } } - function onTypingComplete():Void { + function onTypingComplete():Void + { playAnimation('sentenceEnd'); super.onTypingComplete(); } - public function onDialogueStart(event:DialogueScriptEvent):Void { + public function onDialogueStart(event:DialogueScriptEvent):Void + { super.onDialogueStart(event); } - public function onDialogueLine(event:DialogueScriptEvent):Void { + public function onDialogueLine(event:DialogueScriptEvent):Void + { // Override the default box animation behavior by switching the state event.conversation.state = ConversationState.Opening; @@ -47,7 +59,8 @@ class ThornsDialogueBox extends DialogueBox { super.onDialogueLine(event); } - public function onDialogueEnd(event:DialogueScriptEvent):Void { + public function onDialogueEnd(event:DialogueScriptEvent):Void + { super.onDialogueEnd(event); // Play 'enter' in reverse this.textDisplay.visible = false; @@ -55,7 +68,8 @@ class ThornsDialogueBox extends DialogueBox { playAnimation('exit', false); } - override function onDestroy(event:ScriptEvent) { + override function onDestroy(event:ScriptEvent) + { super.onDestroy(event); } } diff --git a/preload/scripts/levels/weekend1.hxc b/preload/scripts/levels/weekend1.hxc index be15574eb..a2acc2a69 100644 --- a/preload/scripts/levels/weekend1.hxc +++ b/preload/scripts/levels/weekend1.hxc @@ -3,20 +3,25 @@ import funkin.save.Save; class Weekend1Level extends Level { - function new() - { - super('weekend1'); - } + function new() + { + super('weekend1'); + } - override function isUnlocked():Bool { + override function isUnlocked():Bool + { return true; } - override function getSongDisplayNames(difficultyId:String):Array { - if (Save.instance.hasBeatenLevel('weekend1')) { + override function getSongDisplayNames(difficultyId:String):Array + { + if (Save.instance.hasBeatenLevel('weekend1')) + { // Blazin' is a secret song ;) return ["Darnell", "Lit Up", "2hot", "Blazin'"]; - } else { + } + else + { return ["Darnell", "Lit Up", "2hot"]; } } diff --git a/preload/scripts/players/pico.hxc b/preload/scripts/players/pico.hxc index 259324bd4..48aeb611d 100644 --- a/preload/scripts/players/pico.hxc +++ b/preload/scripts/players/pico.hxc @@ -3,12 +3,13 @@ import funkin.save.Save; class PicoPlayableCharacter extends PlayableCharacter { - function new() - { - super('pico'); - } + function new() + { + super('pico'); + } - override function isUnlocked():Bool { + override function isUnlocked():Bool + { return Save.instance.hasBeatenLevel('weekend1'); } } diff --git a/preload/scripts/shaders/AddColorShader.hxc b/preload/scripts/shaders/AddColorShader.hxc index 6d339fb2e..1c89e7dc9 100644 --- a/preload/scripts/shaders/AddColorShader.hxc +++ b/preload/scripts/shaders/AddColorShader.hxc @@ -2,23 +2,23 @@ import flixel.addons.display.FlxRuntimeShader; class AddColorShader extends FlxRuntimeShader { - // ARGB = FlxColor - public var color:Int = 0xFFFFFFFF; + // ARGB = FlxColor + public var color:Int = 0xFFFFFFFF; - function new(color:Int = 0xFFFFFFFF) - { - var fragText:String = Assets.getText(Paths.frag('addColor')); - super(fragText); - setColor(color); - } + function new(color:Int = 0xFFFFFFFF) + { + var fragText:String = Assets.getText(Paths.frag('addColor')); + super(fragText); + setColor(color); + } - function setColor(value:Int):Void - { - this.color = value; + function setColor(value:Int):Void + { + this.color = value; - this.setFloat('colorAlpha', ((this.color >> 24) & 0xff) / 255.0); - this.setFloat('colorRed', ((this.color >> 16) & 0xff) / 255.0); - this.setFloat('colorGreen', ((this.color >> 8) & 0xff) / 255.0); - this.setFloat('colorBlue', ((this.color) & 0xff) / 255.0); - } + this.setFloat('colorAlpha', ((this.color >> 24) & 0xff) / 255.0); + this.setFloat('colorRed', ((this.color >> 16) & 0xff) / 255.0); + this.setFloat('colorGreen', ((this.color >> 8) & 0xff) / 255.0); + this.setFloat('colorBlue', ((this.color) & 0xff) / 255.0); + } } diff --git a/preload/scripts/shaders/BuildingEffectShader.hxc b/preload/scripts/shaders/BuildingEffectShader.hxc index e4a42724c..4fdf656a9 100644 --- a/preload/scripts/shaders/BuildingEffectShader.hxc +++ b/preload/scripts/shaders/BuildingEffectShader.hxc @@ -2,30 +2,30 @@ import flixel.addons.display.FlxRuntimeShader; class BuildingEffectShader extends FlxRuntimeShader { - var alphaShit:Float = 1.0; + var alphaShit:Float = 1.0; - public var effectSpeed:Float = 1.0; + public var effectSpeed:Float = 1.0; - function new(speed:Float = 1.0) - { - var fragText:String = Assets.getText(Paths.frag('building')); - super(fragText); - this.effectSpeed = speed; - } + function new(speed:Float = 1.0) + { + var fragText:String = Assets.getText(Paths.frag('building')); + super(fragText); + this.effectSpeed = speed; + } - function setAlpha(value:Float):Void - { - this.alphaShit = value; - this.setFloat('alphaShit', this.alphaShit); - } + function setAlpha(value:Float):Void + { + this.alphaShit = value; + this.setFloat('alphaShit', this.alphaShit); + } - function update(elapsed:Float):Void - { - setAlpha(alphaShit + effectSpeed * elapsed); - } + function update(elapsed:Float):Void + { + setAlpha(alphaShit + effectSpeed * elapsed); + } - function reset() - { - setAlpha(0); - } + function reset() + { + setAlpha(0); + } } diff --git a/preload/scripts/shaders/DarkenColorShader.hxc b/preload/scripts/shaders/DarkenColorShader.hxc index 5e18f41f0..b108acd6b 100644 --- a/preload/scripts/shaders/DarkenColorShader.hxc +++ b/preload/scripts/shaders/DarkenColorShader.hxc @@ -2,23 +2,23 @@ import flixel.addons.display.FlxRuntimeShader; class DarkenColorShader extends FlxRuntimeShader { - // ARGB = FlxColor - public var color:Int = 0xFFFFFFFF; + // ARGB = FlxColor + public var color:Int = 0xFFFFFFFF; - function new(color:Int = 0xFFFFFFFF) - { - var fragText:String = Assets.getText(Paths.frag('darkenColor')); - super(fragText); - setColor(color); - } + function new(color:Int = 0xFFFFFFFF) + { + var fragText:String = Assets.getText(Paths.frag('darkenColor')); + super(fragText); + setColor(color); + } - function setColor(value:Int):Void - { - this.color = value; + function setColor(value:Int):Void + { + this.color = value; - this.setFloat('colorAlpha', ((this.color >> 24) & 0xff) / 255.0); - this.setFloat('colorRed', ((this.color >> 16) & 0xff) / 255.0); - this.setFloat('colorGreen', ((this.color >> 8) & 0xff) / 255.0); - this.setFloat('colorBlue', ((this.color) & 0xff) / 255.0); - } + this.setFloat('colorAlpha', ((this.color >> 24) & 0xff) / 255.0); + this.setFloat('colorRed', ((this.color >> 16) & 0xff) / 255.0); + this.setFloat('colorGreen', ((this.color >> 8) & 0xff) / 255.0); + this.setFloat('colorBlue', ((this.color) & 0xff) / 255.0); + } } diff --git a/preload/scripts/shaders/InvertColorShader.hxc b/preload/scripts/shaders/InvertColorShader.hxc index f37936eb9..a7307b680 100644 --- a/preload/scripts/shaders/InvertColorShader.hxc +++ b/preload/scripts/shaders/InvertColorShader.hxc @@ -2,9 +2,9 @@ import flixel.addons.display.FlxRuntimeShader; class InvertColorShader extends FlxRuntimeShader { - function new() - { - var fragText:String = Assets.getText(Paths.frag('invertColor')); - super(fragText); - } + function new() + { + var fragText:String = Assets.getText(Paths.frag('invertColor')); + super(fragText); + } } diff --git a/preload/scripts/shaders/MultiplyColorShader.hxc b/preload/scripts/shaders/MultiplyColorShader.hxc index 4acf7c650..19d3dbfbf 100644 --- a/preload/scripts/shaders/MultiplyColorShader.hxc +++ b/preload/scripts/shaders/MultiplyColorShader.hxc @@ -2,23 +2,23 @@ import flixel.addons.display.FlxRuntimeShader; class MultiplyColorShader extends FlxRuntimeShader { - // ARGB = FlxColor - public var color:Int = 0xFFFFFFFF; + // ARGB = FlxColor + public var color:Int = 0xFFFFFFFF; - function new(color:Int = 0xFFFFFFFF) - { - var fragText:String = Assets.getText(Paths.frag('multiplyColor')); - super(fragText); - setColor(color); - } + function new(color:Int = 0xFFFFFFFF) + { + var fragText:String = Assets.getText(Paths.frag('multiplyColor')); + super(fragText); + setColor(color); + } - function setColor(value:Int):Void - { - this.color = value; + function setColor(value:Int):Void + { + this.color = value; - this.setFloat('colorAlpha', ((this.color >> 24) & 0xff) / 255.0); - this.setFloat('colorRed', ((this.color >> 16) & 0xff) / 255.0); - this.setFloat('colorGreen', ((this.color >> 8) & 0xff) / 255.0); - this.setFloat('colorBlue', ((this.color) & 0xff) / 255.0); - } + this.setFloat('colorAlpha', ((this.color >> 24) & 0xff) / 255.0); + this.setFloat('colorRed', ((this.color >> 16) & 0xff) / 255.0); + this.setFloat('colorGreen', ((this.color >> 8) & 0xff) / 255.0); + this.setFloat('colorBlue', ((this.color) & 0xff) / 255.0); + } } diff --git a/preload/scripts/shaders/SubtractColorShader.hxc b/preload/scripts/shaders/SubtractColorShader.hxc index 1997bd521..cce521cfd 100644 --- a/preload/scripts/shaders/SubtractColorShader.hxc +++ b/preload/scripts/shaders/SubtractColorShader.hxc @@ -2,23 +2,23 @@ import flixel.addons.display.FlxRuntimeShader; class SubtractColorShader extends FlxRuntimeShader { - // ARGB = FlxColor - public var color:Int = 0xFFFFFFFF; + // ARGB = FlxColor + public var color:Int = 0xFFFFFFFF; - function new(color:Int = 0xFFFFFFFF) - { - var fragText:String = Assets.getText(Paths.frag('subtractColor')); - super(fragText); - setColor(color); - } + function new(color:Int = 0xFFFFFFFF) + { + var fragText:String = Assets.getText(Paths.frag('subtractColor')); + super(fragText); + setColor(color); + } - function setColor(value:Int):Void - { - this.color = value; + function setColor(value:Int):Void + { + this.color = value; - this.setFloat('colorAlpha', ((this.color >> 24) & 0xff) / 255.0); - this.setFloat('colorRed', ((this.color >> 16) & 0xff) / 255.0); - this.setFloat('colorGreen', ((this.color >> 8) & 0xff) / 255.0); - this.setFloat('colorBlue', ((this.color) & 0xff) / 255.0); - } + this.setFloat('colorAlpha', ((this.color >> 24) & 0xff) / 255.0); + this.setFloat('colorRed', ((this.color >> 16) & 0xff) / 255.0); + this.setFloat('colorGreen', ((this.color >> 8) & 0xff) / 255.0); + this.setFloat('colorBlue', ((this.color) & 0xff) / 255.0); + } } diff --git a/preload/scripts/songs/2hot.hxc b/preload/scripts/songs/2hot.hxc index 517d2ad45..a08ae5df5 100644 --- a/preload/scripts/songs/2hot.hxc +++ b/preload/scripts/songs/2hot.hxc @@ -19,384 +19,389 @@ import funkin.play.stage.StageProp; import funkin.save.Save; // We have to use FlxBasePoint in scripts because FlxPoint is inlined and not available in scripts - class TwoHOTSong extends Song { - var hasPlayedCutscene:Bool = false; - //var tempConductor:Conductor; - var cutsceneMusic:FunkinSound; + var hasPlayedCutscene:Bool = false; + // var tempConductor:Conductor; + var cutsceneMusic:FunkinSound; - function new() - { - super('2hot'); + function new() + { + super('2hot'); - hasPlayedCutscene = false; - } + hasPlayedCutscene = false; + } - /** - * Health lost when hit by can. - */ - var HEALTH_LOSS = 0.25 * 2; + /** + * Health lost when hit by can. + */ + var HEALTH_LOSS = 0.25 * 2; - public function listDifficulties(variationId:String, variationIds:Array, showLocked:Bool):Array { - if (showLocked || Save.instance.hasBeatenLevel('weekend1')) { - return super.listDifficulties(variationId, variationIds); - } + public function listDifficulties(variationId:String, variationIds:Array, showLocked:Bool):Array + { + if (showLocked || Save.instance.hasBeatenLevel('weekend1')) + { + return super.listDifficulties(variationId, variationIds); + } - // Hide all difficulties if the player has not beaten the week. - return []; - } + // Hide all difficulties if the player has not beaten the week. + return []; + } - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); - } + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); + } - function onSongRetry(event:ScriptEvent) - { - super.onSongRetry(event); + function onSongRetry(event:ScriptEvent) + { + super.onSongRetry(event); - removeCans(); - gunCocked = false; - } + removeCans(); + gunCocked = false; + } - public override function onSongEnd(event:CountdownScriptEvent):Void { - super.onSongEnd(event); + public override function onSongEnd(event:CountdownScriptEvent):Void + { + super.onSongEnd(event); if (!PlayStatePlaylist.isStoryMode) hasPlayedCutscene = true; - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { hasPlayedCutscene = true; event.cancel(); - // start the video cutscene and hide it so the other stuff can happen after + // start the video cutscene and hide it so the other stuff can happen after startCutscene(); - } else { - // Make sure the cutscene can play again next time! - hasPlayedCutscene = false; - // DO NOT CANCEL THE EVENT! - } - } - - // the Other stuff - function endCutscene(){ - VideoCutscene.onVideoStarted.removeAll(); - VideoCutscene.hideVideo(); - - new FlxTimer().start(1, function(tmr) - { - PlayState.instance.tweenCameraToPosition(1539, 833.5, 2, FlxEase.quadInOut); - PlayState.instance.tweenCameraZoom(0.69, 2, true, FlxEase.quadInOut); - }); - - // Since no music plays at this part I'm too lazy to hook Nene up to a conductor, - // so we just dance on a timer here. - new FlxTimer().start(0.5, function(tmr) - { - PlayState.instance.currentStage.getGirlfriend().dance(true); - }, 10); - - new FlxTimer().start(2, function(tmr) - { - PlayState.instance.currentStage.getBoyfriend().playAnimation('intro1', true, true); - }); - new FlxTimer().start(2.5, function(tmr) - { - PlayState.instance.currentStage.getDad().playAnimation('pissed', true, true); - }); - - new FlxTimer().start(6, function(tmr) - { - // video would play around here - //PlayState.instance.endSong(true); - - trace('Pausing ending to play a video cutscene (`2hot`)'); - - // Add a black background behind the cutscene to fix a transition bug! - trace('Adding black background behind cutscene over UI'); - var bgSprite = new FunkinSprite(-100, -100); - bgSprite.makeSolidColor(2000, 2500, 0xFF000000); - bgSprite.cameras = [PlayState.instance.camHUD]; // Show over the HUD. - bgSprite.zIndex = 1000000; - PlayState.instance.add(bgSprite); - PlayState.instance.refresh(); - - VideoCutscene.showVideo(); - }); - - } - - function startCutscene(){ - VideoCutscene.onVideoStarted.add(endCutscene); - PlayState.instance.camHUD.visible = false; - - PlayState.instance.isInCutscene = true; - hasPlayedCutscene = true; - - PlayState.instance.currentStage.getBoyfriend().danceEvery = 0; - PlayState.instance.currentStage.getDad().danceEvery = 0; - - startVideo(); - } - - function startVideo() { - VideoCutscene.play(Paths.videos('2hotCutscene'), CutsceneType.ENDING); + } + else + { + // Make sure the cutscene can play again next time! + hasPlayedCutscene = false; + // DO NOT CANCEL THE EVENT! + } + } + + // the Other stuff + function endCutscene() + { + VideoCutscene.onVideoStarted.removeAll(); + VideoCutscene.hideVideo(); + + new FlxTimer().start(1, function(tmr) { + PlayState.instance.tweenCameraToPosition(1539, 833.5, 2, FlxEase.quadInOut); + PlayState.instance.tweenCameraZoom(0.69, 2, true, FlxEase.quadInOut); + }); + + // Since no music plays at this part I'm too lazy to hook Nene up to a conductor, + // so we just dance on a timer here. + new FlxTimer().start(0.5, function(tmr) { + PlayState.instance.currentStage.getGirlfriend().dance(true); + }, 10); + + new FlxTimer().start(2, function(tmr) { + PlayState.instance.currentStage.getBoyfriend().playAnimation('intro1', true, true); + }); + new FlxTimer().start(2.5, function(tmr) { + PlayState.instance.currentStage.getDad().playAnimation('pissed', true, true); + }); + + new FlxTimer().start(6, function(tmr) { + // video would play around here + // PlayState.instance.endSong(true); + + trace('Pausing ending to play a video cutscene (`2hot`)'); + + // Add a black background behind the cutscene to fix a transition bug! + trace('Adding black background behind cutscene over UI'); + var bgSprite = new FunkinSprite(-100, -100); + bgSprite.makeSolidColor(2000, 2500, 0xFF000000); + bgSprite.cameras = [PlayState.instance.camHUD]; // Show over the HUD. + bgSprite.zIndex = 1000000; + PlayState.instance.add(bgSprite); + PlayState.instance.refresh(); + + VideoCutscene.showVideo(); + }); + } + + function startCutscene() + { + VideoCutscene.onVideoStarted.add(endCutscene); + PlayState.instance.camHUD.visible = false; + + PlayState.instance.isInCutscene = true; + hasPlayedCutscene = true; + + PlayState.instance.currentStage.getBoyfriend().danceEvery = 0; + PlayState.instance.currentStage.getDad().danceEvery = 0; + + startVideo(); + } + + function startVideo() + { + VideoCutscene.play(Paths.videos('2hotCutscene'), CutsceneType.ENDING); + } + + function removeCans() + { + for (can in spawnedCans) + { + can.kill(); + } + spawnedCans = []; } - function removeCans() - { - for (can in spawnedCans) - { - can.kill(); - } - spawnedCans = []; - } - - function onStateChangeEnd(event:StateChangeScriptEvent) - { - super.onStateChangeEnd(event); - - if ((Std.isOfType(event.targetState, PlayState))) - { - return; - } - hardClear(); - } - - function hardClear() - { - removeCans(); - gunCocked = false; - } - - var gunCocked:Bool = false; - var spawnedCans:Array = []; - - function onNoteHit(event:HitNoteScriptEvent) - { - super.onNoteHit(event); + function onStateChangeEnd(event:StateChangeScriptEvent) + { + super.onStateChangeEnd(event); + + if ((Std.isOfType(event.targetState, PlayState))) + { + return; + } + hardClear(); + } + + function hardClear() + { + removeCans(); + gunCocked = false; + } + + var gunCocked:Bool = false; + var spawnedCans:Array = []; + + function onNoteHit(event:HitNoteScriptEvent) + { + super.onNoteHit(event); if (PlayState.instance.currentStage == null) return; - switch (event.note.kind) - { - case "weekend-1-lightcan": - // Do nothing, but place this such that the animation plays at the right time. - case "weekend-1-kickcan": - // This creates the can and starts the animation. - // We define the behavior of the can in a separate scripted class, - // which allows the can to track and manage its own properties. - var newCan:ScriptedFlxAtlasSprite = ScriptedFlxAtlasSprite.init('SpraycanAtlasSprite', 0, 0); - - var spraycanPile = PlayState.instance.currentStage.getNamedProp('spraycanPile'); - - newCan.x = spraycanPile.x - 430; - newCan.y = spraycanPile.y - 840; - newCan.zIndex = spraycanPile.zIndex - 1; - - newCan.scriptCall('playCanStart'); - - PlayState.instance.currentStage.add(newCan); - PlayState.instance.currentStage.refresh(); // Apply z-index. - spawnedCans.push(newCan); - case "weekend-1-kneecan": - // Do nothing, but place this such that the animation plays at the right time. - case "weekend-1-cockgun": // lol - gunCocked = true; - new FlxTimer().start(1.0, function() - { - gunCocked = false; - }); - case "weekend-1-firegun": - if (gunCocked) - { - trace('Firing gun!'); - shootNextCan(); - } - else - { - trace('Cannot fire gun!'); - // The player cannot hit this note. - event.cancelEvent(); - } - } - } - - public var STATE_ARCING:Int = 2; // In the air. - public var STATE_SHOT:Int = 3; // Hit by the player. - public var STATE_IMPACTED:Int = 4; // Impacted the player. - - function getNextCanWithState(desiredState:Int) - { - for (index in 0...spawnedCans.length) - { - var can = spawnedCans[index]; - var canState = can.scriptGet('currentState'); - - if (canState == desiredState) - { - // Return the can we found. - return can; - } - } - return null; - } - - function onUpdate(event:UpdateScriptEvent) { - super.onUpdate(event); - } - - function darkenStageProps() - { - // Darken the background, then fade it back. - for (stageProp in PlayState.instance.currentStage.members) - { - // Determine if the stage prop is something that should be excluded from darkening. - if (Std.isOfType(stageProp, StageProp)) { - if (stageProp.name == "bf" || stageProp.name == "dad" || stageProp.name == "gf") // This refers to the player. - { - // Exclude. - continue; - } - } - - // Select cans. - if (spawnedCans.contains(stageProp)) { - // Exclude. - continue; - } - - // Hacky way of selecting PicoPlayable.picoFade. - if (stageProp.zIndex == (PlayState.instance.currentStage.getBoyfriend().zIndex - 3)) { - // Exclude. - continue; - } - - // If not excluded, darken. - stageProp.color = 0xFF111111; - new FlxTimer().start(1/24, (tmr) -> - { - stageProp.color = 0xFF222222; - FlxTween.color(stageProp, 1.4, 0xFF222222, 0xFFFFFFFF); - }); - } - } - - function blackenStageProps() - { - // Blacken the background (also Darnell and Nene) entirely, then restore it once the gameOverSubState is up. - for (stageProp in PlayState.instance.currentStage.members) - { - // Determine if the stage prop is something that should be excluded from blackening. - if (Std.isOfType(stageProp, StageProp)) { - if (stageProp.name == "bf") // This refers to the player. - { - // Exclude. - continue; - } - } - - // Select cans. - if (spawnedCans.contains(stageProp)) { - // Exclude. - continue; - } - - // If not excluded, blacken. - stageProp.color = 0xFF000000; - new FlxTimer().start(1.0, (tmr) -> - { - stageProp.color = 0xFFFFFFFF; - }); - } - } - - function shootNextCan() - { - var can = getNextCanWithState(STATE_ARCING); - - if (can != null) - { - can.scriptSet('currentState', STATE_SHOT); - can.scriptCall('playCanShot'); - - new FlxTimer().start(1/24, function(tmr) - { - darkenStageProps(); - }); - - } - } - - function missNextCan() - { - var can = getNextCanWithState(STATE_ARCING); - - if (can != null) - { - can.scriptSet('currentState', STATE_IMPACTED); - } - } - - function spawnImpactParticle() - { - var impactParticle = FunkinSprite.createSparrow(0, 0, 'CanImpactParticle'); - impactParticle.animation.addByPrefix('idle', 'CanImpactParticle0', 24, false); - impactParticle.animation.play('idle'); - impactParticle.x = PlayState.instance.currentStage.getBoyfriend().x + 400; - impactParticle.y = PlayState.instance.currentStage.getBoyfriend().y - 200; - PlayState.instance.currentStage.add(impactParticle); - - impactParticle.animation.finishCallback = function() - { - impactParticle.kill(); - }; - } - - function onNoteMiss(event:NoteScriptEvent) - { - super.onNoteMiss(event.note); - - trace('Missed note on 2hot stage...' + event.note.noteData); - - switch (event.note.kind) - { - case "weekend-1-cockgun": - event.healthChange = 0.0; // We cause health loss later. - case "weekend-1-firegun": - gunCocked = false; - event.healthChange = 0.0; // We cause health loss elsewhere. - missNextCan(); - takeCanDamage(); - case "weekend-1-firegun-hip": - gunCocked = false; - event.healthChange = 0.0; // We cause health loss elsewhere. - missNextCan(); - takeCanDamage(); - case "weekend-1-firegun-far": - gunCocked = false; - event.healthChange = 0.0; // We cause health loss elsewhere. - missNextCan(); - takeCanDamage(); - } - } - - function takeCanDamage():Void { - trace('Taking damage from can exploding!'); - PlayState.instance.health -= HEALTH_LOSS; - // TODO: This is jank as hell! Add some better way to prevent onNoteMiss's normal health loss. - // PlayState.instance.health += 0.0775; - - if (PlayState.instance.health <= 0) { - trace('Died to the can! Use special death animation.'); - - // Reset to standard death animation. - GameOverSubState.musicSuffix = '-pico-explode'; - GameOverSubState.blueBallSuffix = '-pico-explode'; - - blackenStageProps(); - } - } - - /** + switch (event.note.kind) + { + case "weekend-1-lightcan": + // Do nothing, but place this such that the animation plays at the right time. + case "weekend-1-kickcan": + // This creates the can and starts the animation. + // We define the behavior of the can in a separate scripted class, + // which allows the can to track and manage its own properties. + var newCan:ScriptedFlxAtlasSprite = ScriptedFlxAtlasSprite.init('SpraycanAtlasSprite', 0, 0); + + var spraycanPile = PlayState.instance.currentStage.getNamedProp('spraycanPile'); + + newCan.x = spraycanPile.x - 430; + newCan.y = spraycanPile.y - 840; + newCan.zIndex = spraycanPile.zIndex - 1; + + newCan.scriptCall('playCanStart'); + + PlayState.instance.currentStage.add(newCan); + PlayState.instance.currentStage.refresh(); // Apply z-index. + spawnedCans.push(newCan); + case "weekend-1-kneecan": + // Do nothing, but place this such that the animation plays at the right time. + case "weekend-1-cockgun": // lol + gunCocked = true; + new FlxTimer().start(1.0, function() { + gunCocked = false; + }); + case "weekend-1-firegun": + if (gunCocked) + { + trace('Firing gun!'); + shootNextCan(); + } + else + { + trace('Cannot fire gun!'); + // The player cannot hit this note. + event.cancelEvent(); + } + } + } + + public var STATE_ARCING:Int = 2; // In the air. + public var STATE_SHOT:Int = 3; // Hit by the player. + public var STATE_IMPACTED:Int = 4; // Impacted the player. + + function getNextCanWithState(desiredState:Int) + { + for (index in 0...spawnedCans.length) + { + var can = spawnedCans[index]; + var canState = can.scriptGet('currentState'); + + if (canState == desiredState) + { + // Return the can we found. + return can; + } + } + return null; + } + + function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); + } + + function darkenStageProps() + { + // Darken the background, then fade it back. + for (stageProp in PlayState.instance.currentStage.members) + { + // Determine if the stage prop is something that should be excluded from darkening. + if (Std.isOfType(stageProp, StageProp)) + { + if (stageProp.name == "bf" || stageProp.name == "dad" || stageProp.name == "gf") // This refers to the player. + { + // Exclude. + continue; + } + } + + // Select cans. + if (spawnedCans.contains(stageProp)) + { + // Exclude. + continue; + } + + // Hacky way of selecting PicoPlayable.picoFade. + if (stageProp.zIndex == (PlayState.instance.currentStage.getBoyfriend().zIndex - 3)) + { + // Exclude. + continue; + } + + // If not excluded, darken. + stageProp.color = 0xFF111111; + new FlxTimer().start(1 / 24, (tmr) -> { + stageProp.color = 0xFF222222; + FlxTween.color(stageProp, 1.4, 0xFF222222, 0xFFFFFFFF); + }); + } + } + + function blackenStageProps() + { + // Blacken the background (also Darnell and Nene) entirely, then restore it once the gameOverSubState is up. + for (stageProp in PlayState.instance.currentStage.members) + { + // Determine if the stage prop is something that should be excluded from blackening. + if (Std.isOfType(stageProp, StageProp)) + { + if (stageProp.name == "bf") // This refers to the player. + { + // Exclude. + continue; + } + } + + // Select cans. + if (spawnedCans.contains(stageProp)) + { + // Exclude. + continue; + } + + // If not excluded, blacken. + stageProp.color = 0xFF000000; + new FlxTimer().start(1.0, (tmr) -> { + stageProp.color = 0xFFFFFFFF; + }); + } + } + + function shootNextCan() + { + var can = getNextCanWithState(STATE_ARCING); + + if (can != null) + { + can.scriptSet('currentState', STATE_SHOT); + can.scriptCall('playCanShot'); + + new FlxTimer().start(1 / 24, function(tmr) { + darkenStageProps(); + }); + } + } + + function missNextCan() + { + var can = getNextCanWithState(STATE_ARCING); + + if (can != null) + { + can.scriptSet('currentState', STATE_IMPACTED); + } + } + + function spawnImpactParticle() + { + var impactParticle = FunkinSprite.createSparrow(0, 0, 'CanImpactParticle'); + impactParticle.animation.addByPrefix('idle', 'CanImpactParticle0', 24, false); + impactParticle.animation.play('idle'); + impactParticle.x = PlayState.instance.currentStage.getBoyfriend().x + 400; + impactParticle.y = PlayState.instance.currentStage.getBoyfriend().y - 200; + PlayState.instance.currentStage.add(impactParticle); + + impactParticle.animation.finishCallback = function() { + impactParticle.kill(); + }; + } + + function onNoteMiss(event:NoteScriptEvent) + { + super.onNoteMiss(event.note); + + trace('Missed note on 2hot stage...' + event.note.noteData); + + switch (event.note.kind) + { + case "weekend-1-cockgun": + event.healthChange = 0.0; // We cause health loss later. + case "weekend-1-firegun": + gunCocked = false; + event.healthChange = 0.0; // We cause health loss elsewhere. + missNextCan(); + takeCanDamage(); + case "weekend-1-firegun-hip": + gunCocked = false; + event.healthChange = 0.0; // We cause health loss elsewhere. + missNextCan(); + takeCanDamage(); + case "weekend-1-firegun-far": + gunCocked = false; + event.healthChange = 0.0; // We cause health loss elsewhere. + missNextCan(); + takeCanDamage(); + } + } + + function takeCanDamage():Void + { + trace('Taking damage from can exploding!'); + PlayState.instance.health -= HEALTH_LOSS; + // TODO: This is jank as hell! Add some better way to prevent onNoteMiss's normal health loss. + // PlayState.instance.health += 0.0775; + + if (PlayState.instance.health <= 0) + { + trace('Died to the can! Use special death animation.'); + + // Reset to standard death animation. + GameOverSubState.musicSuffix = '-pico-explode'; + GameOverSubState.blueBallSuffix = '-pico-explode'; + + blackenStageProps(); + } + } + + /** * Replay the cutscene after leaving the song. */ function onCreate(event:ScriptEvent):Void diff --git a/preload/scripts/songs/blammed.hxc b/preload/scripts/songs/blammed.hxc index 83f1f5e69..aca03b346 100644 --- a/preload/scripts/songs/blammed.hxc +++ b/preload/scripts/songs/blammed.hxc @@ -9,30 +9,32 @@ import flixel.FlxG; import flixel.FlxSprite; import flixel.util.FlxTimer; import funkin.save.Save; - import funkin.effects.RetroCameraFade; -class BlammedSong extends Song { +class BlammedSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('blammed'); - } + public function new() + { + super('blammed'); + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool { - if (currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); return false; - } + } - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! diff --git a/preload/scripts/songs/blazin.hxc b/preload/scripts/songs/blazin.hxc index d03afff1a..e295465a0 100644 --- a/preload/scripts/songs/blazin.hxc +++ b/preload/scripts/songs/blazin.hxc @@ -10,111 +10,123 @@ import funkin.save.Save; /** * Apply middlescroll to the song. */ -class BlazinSong extends Song { - public function new() { - super('blazin'); - - this.hasHidden = false; - this.hasPlayedCutscene = false; - } - - function onCreate(event:ScriptEvent):Void { - super.onCreate(event); - - this.hasHidden = false; - this.hasPlayedCutscene = false; - } - - function onDestroy(event:ScriptEvent):Void { - super.onDestroy(event); - - this.hasHidden = false; - } - - function onNoteHit(event:HitNoteScriptEvent):Void { - super.onNoteHit(event); - } - - public function listDifficulties(variationId:String, variationIds:Array, showLocked:Bool):Array { - if (showLocked || Save.instance.hasBeatenLevel('weekend1')) { - return super.listDifficulties(variationId, variationIds); - } - - // Hide all difficulties if the player has not beaten the week. - return []; - } - - var hasHidden = false; - var hasPlayedCutscene:Bool = false; - - function onUpdate(event:ScriptEvent):Void - { - super.onUpdate(event); - - if (!this.hasHidden) - { - this.hasHidden = true; - hideOpponentStrumline(); - centerPlayerStrumline(); - } - } - - function hideOpponentStrumline() - { - var opponentStrumline:FlxSprite = PlayState.instance.opponentStrumline; - if (opponentStrumline != null) - { - for (arrow in opponentStrumline.members) - { - arrow.visible = false; - } - } - } - - function centerPlayerStrumline() - { +class BlazinSong extends Song +{ + public function new() + { + super('blazin'); + + this.hasHidden = false; + this.hasPlayedCutscene = false; + } + + function onCreate(event:ScriptEvent):Void + { + super.onCreate(event); + + this.hasHidden = false; + this.hasPlayedCutscene = false; + } + + function onDestroy(event:ScriptEvent):Void + { + super.onDestroy(event); + + this.hasHidden = false; + } + + function onNoteHit(event:HitNoteScriptEvent):Void + { + super.onNoteHit(event); + } + + public function listDifficulties(variationId:String, variationIds:Array, showLocked:Bool):Array + { + if (showLocked || Save.instance.hasBeatenLevel('weekend1')) + { + return super.listDifficulties(variationId, variationIds); + } + + // Hide all difficulties if the player has not beaten the week. + return []; + } + + var hasHidden = false; + var hasPlayedCutscene:Bool = false; + + function onUpdate(event:ScriptEvent):Void + { + super.onUpdate(event); + + if (!this.hasHidden) + { + this.hasHidden = true; + hideOpponentStrumline(); + centerPlayerStrumline(); + } + } + + function hideOpponentStrumline() + { + var opponentStrumline:FlxSprite = PlayState.instance.opponentStrumline; + if (opponentStrumline != null) + { + for (arrow in opponentStrumline.members) + { + arrow.visible = false; + } + } + } + + function centerPlayerStrumline() + { // This is a song gimmick we are never making middlescroll an option. - var playerStrumline:FlxSprite = PlayState.instance.playerStrumline; - if (playerStrumline != null) - { - playerStrumline.x = FlxG.width / 2 - playerStrumline.width / 2; - } - } + var playerStrumline:FlxSprite = PlayState.instance.playerStrumline; + if (playerStrumline != null) + { + playerStrumline.x = FlxG.width / 2 - playerStrumline.width / 2; + } + } - public override function onSongEnd(event:CountdownScriptEvent):Void { - super.onSongEnd(event); + public override function onSongEnd(event:CountdownScriptEvent):Void + { + super.onSongEnd(event); - // Keep the cutscene from playing outside of story mode. + // Keep the cutscene from playing outside of story mode. if (!PlayStatePlaylist.isStoryMode) hasPlayedCutscene = true; - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { trace('Pausing ending to play a video cutscene (`blazin`)'); hasPlayedCutscene = true; - // Add a black background behind the cutscene to fix a transition bug! - trace('Adding black background behind cutscene over UI'); - var bgSprite = new FunkinSprite(-100, -100); - bgSprite.makeSolidColor(2000, 2500, 0xFF000000); - bgSprite.cameras = [PlayState.instance.camHUD]; // Show over the HUD. - bgSprite.zIndex = 1000000; - PlayState.instance.add(bgSprite); - PlayState.instance.refresh(); + // Add a black background behind the cutscene to fix a transition bug! + trace('Adding black background behind cutscene over UI'); + var bgSprite = new FunkinSprite(-100, -100); + bgSprite.makeSolidColor(2000, 2500, 0xFF000000); + bgSprite.cameras = [PlayState.instance.camHUD]; // Show over the HUD. + bgSprite.zIndex = 1000000; + PlayState.instance.add(bgSprite); + PlayState.instance.refresh(); event.cancel(); // CANCEL THE COUNTDOWN! startVideo(); - } else { - // Make sure the cutscene can play again next time! - hasPlayedCutscene = false; - // DO NOT CANCEL THE EVENT! - } - } - - function startVideo() { - VideoCutscene.play(Paths.videos('blazinCutscene'), CutsceneType.ENDING); - // This will call onSongEnd() again so make sure the flag is set! - hasPlayedCutscene = true; + } + else + { + // Make sure the cutscene can play again next time! + hasPlayedCutscene = false; + // DO NOT CANCEL THE EVENT! + } + } + + function startVideo() + { + VideoCutscene.play(Paths.videos('blazinCutscene'), CutsceneType.ENDING); + // This will call onSongEnd() again so make sure the flag is set! + hasPlayedCutscene = true; } } diff --git a/preload/scripts/songs/bopeebo.hxc b/preload/scripts/songs/bopeebo.hxc index 0b2d686f4..0cfad3b7b 100644 --- a/preload/scripts/songs/bopeebo.hxc +++ b/preload/scripts/songs/bopeebo.hxc @@ -8,29 +8,32 @@ import flixel.FlxG; import flixel.FlxSprite; import flixel.util.FlxTimer; import funkin.save.Save; - import funkin.effects.RetroCameraFade; -class BopeeboSong extends Song { +class BopeeboSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('bopeebo'); - } + public function new() + { + super('bopeebo'); + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool{ - if(currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); return false; - } - - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { + } + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! diff --git a/preload/scripts/songs/cocoa.hxc b/preload/scripts/songs/cocoa.hxc index 1b3827ae3..5b3198bc5 100644 --- a/preload/scripts/songs/cocoa.hxc +++ b/preload/scripts/songs/cocoa.hxc @@ -19,38 +19,37 @@ import funkin.play.stage.StageProp; import funkin.save.Save; // We have to use FlxBasePoint in scripts because FlxPoint is inlined and not available in scripts - class CocoaSong extends Song { - function new() - { - super('cocoa'); - } - - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool - { - if (currentDifficulty == 'erect' || currentDifficulty == 'nightmare') - return !Save.instance.hasBeatenSong(this.id, ['erect', 'nightmare']); + function new() + { + super('cocoa'); + } - return false; - } + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentDifficulty == 'erect' || currentDifficulty == 'nightmare') return !Save.instance.hasBeatenSong(this.id, ['erect', 'nightmare']); - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); - trace(PlayState.instance.currentVariation); - } + return false; + } - function onSongRetry(event:ScriptEvent) - { - super.onSongRetry(event); + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); + trace(PlayState.instance.currentVariation); + } - } + function onSongRetry(event:ScriptEvent) + { + super.onSongRetry(event); + } - function onUpdate(event:UpdateScriptEvent) { - super.onUpdate(event); - } + function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); + } - /** + /** * Replay the cutscene after leaving the song. */ function onCreate(event:ScriptEvent):Void diff --git a/preload/scripts/songs/dadbattle.hxc b/preload/scripts/songs/dadbattle.hxc index d73666304..1a0705195 100644 --- a/preload/scripts/songs/dadbattle.hxc +++ b/preload/scripts/songs/dadbattle.hxc @@ -9,28 +9,32 @@ import flixel.FlxG; import flixel.FlxSprite; import flixel.util.FlxTimer; import funkin.save.Save; - import funkin.effects.RetroCameraFade; -class DadBattleSong extends Song { +class DadBattleSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('dadbattle'); - } + public function new() + { + super('dadbattle'); + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool{ - if(currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); return false; - } + } - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! diff --git a/preload/scripts/songs/darnell.hxc b/preload/scripts/songs/darnell.hxc index 5d1dd7f2f..60ea6a121 100644 --- a/preload/scripts/songs/darnell.hxc +++ b/preload/scripts/songs/darnell.hxc @@ -17,41 +17,47 @@ import funkin.save.Save; import funkin.audio.FunkinSound; import funkin.play.cutscene.VideoCutscene; import funkin.play.cutscene.CutsceneType; - import funkin.play.PlayStatePlaylist; -class DarnellSong extends Song { +class DarnellSong extends Song +{ var hasPlayedCutscene:Bool; var hasPlayedInGameCutscene:Bool; var cutsceneMusic:FunkinSound; - var cutsceneConductor:Conductor; + var cutsceneConductor:Conductor; var bgSprite:FunkinSprite; - public function new() { - super('darnell'); + public function new() + { + super('darnell'); hasPlayedCutscene = false; hasPlayedInGameCutscene = false; - } + } - public function listDifficulties(variationId:String, variationIds:Array, showLocked:Bool):Array { - if (showLocked || Save.instance.hasBeatenLevel('weekend1')) { - return super.listDifficulties(variationId, variationIds); - } + public function listDifficulties(variationId:String, variationIds:Array, showLocked:Bool):Array + { + if (showLocked || Save.instance.hasBeatenLevel('weekend1')) + { + return super.listDifficulties(variationId, variationIds); + } - // Hide all difficulties if the player has not beaten the week. - return []; - } + // Hide all difficulties if the player has not beaten the week. + return []; + } - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); - if (!PlayStatePlaylist.isStoryMode){ + if (!PlayStatePlaylist.isStoryMode) + { hasPlayedCutscene = true; hasPlayedInGameCutscene = true; } - if(hasPlayedCutscene && !hasPlayedInGameCutscene){ + if (hasPlayedCutscene && !hasPlayedInGameCutscene) + { trace('Pausing countdown to play in game cutscene'); hasPlayedInGameCutscene = true; @@ -62,7 +68,8 @@ class DarnellSong extends Song { introCutscene(); } - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { trace('Pausing countdown to play a video cutscene (`darnell`)'); hasPlayedCutscene = true; @@ -71,203 +78,211 @@ class DarnellSong extends Song { PlayState.instance.tweenCameraZoom(1.3, 0, true); - // trace('Adding black background behind cutscene over UI'); - bgSprite = new FunkinSprite(0, 0); - bgSprite.makeSolidColor(2000, 2500, 0xFF000000); - bgSprite.cameras = [PlayState.instance.camCutscene]; // Show over the HUD but below the video. - // this - bgSprite.zIndex = -10000; - PlayState.instance.add(bgSprite); - PlayState.instance.refresh(); + // trace('Adding black background behind cutscene over UI'); + bgSprite = new FunkinSprite(0, 0); + bgSprite.makeSolidColor(2000, 2500, 0xFF000000); + bgSprite.cameras = [PlayState.instance.camCutscene]; // Show over the HUD but below the video. + // this + bgSprite.zIndex = -10000; + PlayState.instance.add(bgSprite); + PlayState.instance.refresh(); startVideo(); - } - } - - function introCutscene(){ - var picoPos:Array = [PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.x, PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.y]; - var nenePos:Array = [PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint.x, PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint.y]; - var darnellPos:Array = [PlayState.instance.currentStage.getDad().cameraFocusPoint.x, PlayState.instance.currentStage.getDad().cameraFocusPoint.y]; - - var cutsceneDelay:Float = 2; - - cutsceneMusic = FunkinSound.load(Paths.music("darnellCanCutscene/darnellCanCutscene", "weekend1"), true); - cutsceneMusic.volume = 1; - - cutsceneConductor = new Conductor(); + } - var songMusicData:Null = SongRegistry.instance.parseMusicData('darnellCanCutscene'); - if (songMusicData != null) { - cutsceneConductor.mapTimeChanges(songMusicData.timeChanges); - } + function introCutscene() + { + var picoPos:Array = [ + PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.x, + PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.y + ]; + var nenePos:Array = [ + PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint.x, + PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint.y + ]; + var darnellPos:Array = [ + PlayState.instance.currentStage.getDad().cameraFocusPoint.x, + PlayState.instance.currentStage.getDad().cameraFocusPoint.y + ]; + + var cutsceneDelay:Float = 2; + + cutsceneMusic = FunkinSound.load(Paths.music("darnellCanCutscene/darnellCanCutscene", "weekend1"), true); + cutsceneMusic.volume = 1; + + cutsceneConductor = new Conductor(); + + var songMusicData:Null = SongRegistry.instance.parseMusicData('darnellCanCutscene'); + if (songMusicData != null) + { + cutsceneConductor.mapTimeChanges(songMusicData.timeChanges); + } - cutsceneConductor.onBeatHit.add(onCutsceneBeatHit); + cutsceneConductor.onBeatHit.add(onCutsceneBeatHit); - var cutsceneCan:FunkinSprite = FunkinSprite.createSparrow(darnellPos[0], darnellPos[1], 'wked1_cutscene_1_can'); - cutsceneCan.animation.addByPrefix('forward', "can kick quick0", 24, false); - cutsceneCan.animation.addByPrefix('up', "can kicked up0", 24, false); - PlayState.instance.currentStage.add(cutsceneCan); + var cutsceneCan:FunkinSprite = FunkinSprite.createSparrow(darnellPos[0], darnellPos[1], 'wked1_cutscene_1_can'); + cutsceneCan.animation.addByPrefix('forward', "can kick quick0", 24, false); + cutsceneCan.animation.addByPrefix('up', "can kicked up0", 24, false); + PlayState.instance.currentStage.add(cutsceneCan); cutsceneCan.visible = false; var spraycanPile = PlayState.instance.currentStage.getNamedProp('spraycanPile'); - cutsceneCan.x = spraycanPile.x + 30; - cutsceneCan.y = spraycanPile.y - 320; - cutsceneCan.zIndex = spraycanPile.zIndex - 1; - PlayState.instance.currentStage.refresh(); + cutsceneCan.x = spraycanPile.x + 30; + cutsceneCan.y = spraycanPile.y - 320; + cutsceneCan.zIndex = spraycanPile.zIndex - 1; + PlayState.instance.currentStage.refresh(); var newCan:ScriptedFlxAtlasSprite = ScriptedFlxAtlasSprite.init('SpraycanAtlasSprite', 0, 0); - var spraycanPile = PlayState.instance.currentStage.getNamedProp('spraycanPile'); - newCan.x = spraycanPile.x - 430; - newCan.y = spraycanPile.y - 840; - newCan.zIndex = 300; - PlayState.instance.currentStage.add(newCan); - PlayState.instance.currentStage.refresh(); + var spraycanPile = PlayState.instance.currentStage.getNamedProp('spraycanPile'); + newCan.x = spraycanPile.x - 430; + newCan.y = spraycanPile.y - 840; + newCan.zIndex = 300; + PlayState.instance.currentStage.add(newCan); + PlayState.instance.currentStage.refresh(); newCan.visible = false; PlayState.instance.currentStage.getBoyfriend().playAnimation('intro1', true); - // camera sets up, pico does his animation showing him pissed - new FlxTimer().start(0.1, function(tmr) - { - PlayState.instance.tweenCameraToPosition(picoPos[0] + 250, picoPos[1], 0); - - PlayState.instance.tweenCameraZoom(1.3, 0, true, FlxEase.quadInOut); - }); - - new FlxTimer().start(0.7, function(tmr){ - cutsceneMusic.play(false); - FlxTween.tween(bgSprite, { alpha: 0}, 2, {startDelay: 0.3}, function(){bgSprite.visible = false;}); - }); - - // move camera out to show everything - new FlxTimer().start(cutsceneDelay, function(tmr){ - PlayState.instance.tweenCameraToPosition(darnellPos[0]+100, darnellPos[1], 2.5, FlxEase.quadInOut); - PlayState.instance.tweenCameraZoom(0.66, 2.5, true, FlxEase.quadInOut); - }); - - // darnell lights up a can - new FlxTimer().start(cutsceneDelay + 3, function(tmr) - { - PlayState.instance.currentStage.getDad().playAnimation('lightCan', true); - FunkinSound.playOnce(Paths.sound('Darnell_Lighter'), 1.0); - }); - - // pico cocks his gun, camera shifts to his side to show this - new FlxTimer().start(cutsceneDelay + 4, function(tmr) - { - PlayState.instance.currentStage.getBoyfriend().playAnimation('cock', true); - PlayState.instance.tweenCameraToPosition(darnellPos[0]+180, darnellPos[1], 0.4, FlxEase.backOut); - FunkinSound.playOnce(Paths.sound('Gun_Prep'), 1.0); - }); - - // darnell kicks the can up - new FlxTimer().start(cutsceneDelay + 4.4, function(tmr) - { - PlayState.instance.currentStage.getDad().playAnimation('kickCan', true); - FunkinSound.playOnce(Paths.sound('Kick_Can_UP'), 1.0); + // camera sets up, pico does his animation showing him pissed + new FlxTimer().start(0.1, function(tmr) { + PlayState.instance.tweenCameraToPosition(picoPos[0] + 250, picoPos[1], 0); + + PlayState.instance.tweenCameraZoom(1.3, 0, true, FlxEase.quadInOut); + }); + + new FlxTimer().start(0.7, function(tmr) { + cutsceneMusic.play(false); + FlxTween.tween(bgSprite, {alpha: 0}, 2, {startDelay: 0.3}, function() { + bgSprite.visible = false; + }); + }); + + // move camera out to show everything + new FlxTimer().start(cutsceneDelay, function(tmr) { + PlayState.instance.tweenCameraToPosition(darnellPos[0] + 100, darnellPos[1], 2.5, FlxEase.quadInOut); + PlayState.instance.tweenCameraZoom(0.66, 2.5, true, FlxEase.quadInOut); + }); + + // darnell lights up a can + new FlxTimer().start(cutsceneDelay + 3, function(tmr) { + PlayState.instance.currentStage.getDad().playAnimation('lightCan', true); + FunkinSound.playOnce(Paths.sound('Darnell_Lighter'), 1.0); + }); + + // pico cocks his gun, camera shifts to his side to show this + new FlxTimer().start(cutsceneDelay + 4, function(tmr) { + PlayState.instance.currentStage.getBoyfriend().playAnimation('cock', true); + PlayState.instance.tweenCameraToPosition(darnellPos[0] + 180, darnellPos[1], 0.4, FlxEase.backOut); + FunkinSound.playOnce(Paths.sound('Gun_Prep'), 1.0); + }); + + // darnell kicks the can up + new FlxTimer().start(cutsceneDelay + 4.4, function(tmr) { + PlayState.instance.currentStage.getDad().playAnimation('kickCan', true); + FunkinSound.playOnce(Paths.sound('Kick_Can_UP'), 1.0); cutsceneCan.animation.play('up'); cutsceneCan.visible = true; - }); + }); - // darnell knees the can forward - new FlxTimer().start(cutsceneDelay + 4.9, function(tmr) - { - PlayState.instance.currentStage.getDad().playAnimation('kneeCan', true); - FunkinSound.playOnce(Paths.sound('Kick_Can_FORWARD'), 1.0); + // darnell knees the can forward + new FlxTimer().start(cutsceneDelay + 4.9, function(tmr) { + PlayState.instance.currentStage.getDad().playAnimation('kneeCan', true); + FunkinSound.playOnce(Paths.sound('Kick_Can_FORWARD'), 1.0); cutsceneCan.animation.play('forward'); - }); + }); - // pico shoots the can, it explodes - new FlxTimer().start(cutsceneDelay + 5.1, function(tmr) - { - PlayState.instance.currentStage.getBoyfriend().playAnimation('intro2', true, true); + // pico shoots the can, it explodes + new FlxTimer().start(cutsceneDelay + 5.1, function(tmr) { + PlayState.instance.currentStage.getBoyfriend().playAnimation('intro2', true, true); - FunkinSound.playOnce(Paths.soundRandom('shot', 1, 4)); + FunkinSound.playOnce(Paths.soundRandom('shot', 1, 4)); - PlayState.instance.tweenCameraToPosition(darnellPos[0]+100, darnellPos[1], 1, FlxEase.quadInOut); + PlayState.instance.tweenCameraToPosition(darnellPos[0] + 100, darnellPos[1], 1, FlxEase.quadInOut); - newCan.scriptCall('playCanShot'); + newCan.scriptCall('playCanShot'); newCan.visible = true; cutsceneCan.visible = false; - new FlxTimer().start(1/24, function(tmr) - { - darkenStageProps(); - }); - }); - - // darnell laughs - new FlxTimer().start(cutsceneDelay + 5.9, function(tmr) - { - PlayState.instance.currentStage.getDad().playAnimation('laughCutscene', true); - FunkinSound.playOnce(Paths.sound('cutscene/darnell_laugh'), 0.6); - }); - - // nene spits and laughs - new FlxTimer().start(cutsceneDelay + 6.2, function(tmr) - { - PlayState.instance.currentStage.getGirlfriend().playAnimation('laughCutscene', true); - FunkinSound.playOnce(Paths.sound('cutscene/nene_laugh'), 0.6); - }); - - // camera returns to normal, cutscene flags set and countdown starts. - new FlxTimer().start(cutsceneDelay + 8, function(tmr) - { - PlayState.instance.tweenCameraZoom(0.77, 2, true, FlxEase.sineInOut); - PlayState.instance.tweenCameraToPosition(darnellPos[0]+180, darnellPos[1], 2, FlxEase.sineInOut); - PlayState.instance.isInCutscene = false; - PlayState.instance.startCountdown(); - cutsceneMusic.stop(); // stop the music!!!!!! - }); - } - - function onCutsceneBeatHit() { - // Play idle if Darnell isn't busy. - if (PlayState.instance.currentStage.getDad().isAnimationFinished() - && PlayState.instance.currentStage.getDad().getCurrentAnimation() != 'lightCan') { - PlayState.instance.currentStage.getDad().dance(true); - } - - if (PlayState.instance.currentStage.getGirlfriend().isAnimationFinished()) { - PlayState.instance.currentStage.getGirlfriend().dance(true); - } - } + new FlxTimer().start(1 / 24, function(tmr) { + darkenStageProps(); + }); + }); + + // darnell laughs + new FlxTimer().start(cutsceneDelay + 5.9, function(tmr) { + PlayState.instance.currentStage.getDad().playAnimation('laughCutscene', true); + FunkinSound.playOnce(Paths.sound('cutscene/darnell_laugh'), 0.6); + }); + + // nene spits and laughs + new FlxTimer().start(cutsceneDelay + 6.2, function(tmr) { + PlayState.instance.currentStage.getGirlfriend().playAnimation('laughCutscene', true); + FunkinSound.playOnce(Paths.sound('cutscene/nene_laugh'), 0.6); + }); + + // camera returns to normal, cutscene flags set and countdown starts. + new FlxTimer().start(cutsceneDelay + 8, function(tmr) { + PlayState.instance.tweenCameraZoom(0.77, 2, true, FlxEase.sineInOut); + PlayState.instance.tweenCameraToPosition(darnellPos[0] + 180, darnellPos[1], 2, FlxEase.sineInOut); + PlayState.instance.isInCutscene = false; + PlayState.instance.startCountdown(); + cutsceneMusic.stop(); // stop the music!!!!!! + }); + } + + function onCutsceneBeatHit() + { + // Play idle if Darnell isn't busy. + if (PlayState.instance.currentStage.getDad().isAnimationFinished() + && PlayState.instance.currentStage.getDad().getCurrentAnimation() != 'lightCan') + { + PlayState.instance.currentStage.getDad().dance(true); + } + + if (PlayState.instance.currentStage.getGirlfriend().isAnimationFinished()) + { + PlayState.instance.currentStage.getGirlfriend().dance(true); + } + } function darkenStageProps() - { - // Darken the background, then fade it back. - for (stageProp in PlayState.instance.currentStage.members) - { - // Determine if the stage prop is something that should be excluded from darkening. - if (Std.isOfType(stageProp, StageProp)) { - if (stageProp.name == "bf" || stageProp.name == "dad" || stageProp.name == "gf") // This refers to the player. - { - // Exclude. - continue; - } - } - - // Hacky way of selecting PicoPlayable.picoFade. - if (stageProp.zIndex == (PlayState.instance.currentStage.getBoyfriend().zIndex - 3)) { - // Exclude. - continue; - } - - if(stageProp.zIndex > 299){ + { + // Darken the background, then fade it back. + for (stageProp in PlayState.instance.currentStage.members) + { + // Determine if the stage prop is something that should be excluded from darkening. + if (Std.isOfType(stageProp, StageProp)) + { + if (stageProp.name == "bf" || stageProp.name == "dad" || stageProp.name == "gf") // This refers to the player. + { + // Exclude. + continue; + } + } + + // Hacky way of selecting PicoPlayable.picoFade. + if (stageProp.zIndex == (PlayState.instance.currentStage.getBoyfriend().zIndex - 3)) + { + // Exclude. + continue; + } + + if (stageProp.zIndex > 299) + { continue; } - // If not excluded, darken. - stageProp.color = 0xFF111111; - new FlxTimer().start(1/24, (tmr) -> - { - stageProp.color = 0xFF222222; - FlxTween.color(stageProp, 1.4, 0xFF222222, 0xFFFFFFFF); - }); - } - } - - function startVideo() { + // If not excluded, darken. + stageProp.color = 0xFF111111; + new FlxTimer().start(1 / 24, (tmr) -> { + stageProp.color = 0xFF222222; + FlxTween.color(stageProp, 1.4, 0xFF222222, 0xFFFFFFFF); + }); + } + } + + function startVideo() + { VideoCutscene.play(Paths.videos('darnellCutscene')); } @@ -293,11 +308,13 @@ class DarnellSong extends Song { hasPlayedInGameCutscene = false; } - function onUpdate(event:UpdateScriptEvent) { - super.onUpdate(event); + function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); - if (cutsceneConductor != null && cutsceneMusic != null) { - cutsceneConductor.update(cutsceneMusic.time); - } - } + if (cutsceneConductor != null && cutsceneMusic != null) + { + cutsceneConductor.update(cutsceneMusic.time); + } + } } diff --git a/preload/scripts/songs/eggnog.hxc b/preload/scripts/songs/eggnog.hxc index 16cc28dce..687aa7530 100644 --- a/preload/scripts/songs/eggnog.hxc +++ b/preload/scripts/songs/eggnog.hxc @@ -19,86 +19,91 @@ import funkin.play.stage.StageProp; import funkin.save.Save; // We have to use FlxBasePoint in scripts because FlxPoint is inlined and not available in scripts - class EggnogSong extends Song { - var hasPlayedCutscene:Bool = false; - - //var santaDead:ScriptedFlxAtlasSprite; + var hasPlayedCutscene:Bool = false; - function new() - { - super('eggnog'); + // var santaDead:ScriptedFlxAtlasSprite; - hasPlayedCutscene = false; - } - - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); - trace(PlayState.instance.currentVariation); - } + function new() + { + super('eggnog'); - function onSongRetry(event:ScriptEvent) - { - super.onSongRetry(event); + hasPlayedCutscene = false; + } - } + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); + trace(PlayState.instance.currentVariation); + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool - { - if(currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + function onSongRetry(event:ScriptEvent) + { + super.onSongRetry(event); + } - return false; - } + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { - var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); + return false; + } - switch (variationId) { - case 'pico': - // return hasBeatenPicoMix ? [''] : []; - // No Pico mix on BF instrumental, sorry! - return []; - default: - return hasBeatenPicoMix ? ['pico'] : []; - } - } + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { + var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); + + switch (variationId) + { + case 'pico': + // return hasBeatenPicoMix ? [''] : []; + // No Pico mix on BF instrumental, sorry! + return []; + default: + return hasBeatenPicoMix ? ['pico'] : []; + } + } } - public override function onSongEnd(event:CountdownScriptEvent):Void { - super.onSongEnd(event); - if (PlayState.instance.currentVariation != 'erect') hasPlayedCutscene = true; - // only play this on erect.. + public override function onSongEnd(event:CountdownScriptEvent):Void + { + super.onSongEnd(event); + if (PlayState.instance.currentVariation != 'erect') hasPlayedCutscene = true; + // only play this on erect.. - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { hasPlayedCutscene = true; event.cancel(); - // start the video cutscene and hide it so the other stuff can happen after + // start the video cutscene and hide it so the other stuff can happen after startCutscene(); - } else { - // Make sure the cutscene can play again next time! - hasPlayedCutscene = false; - // DO NOT CANCEL THE EVENT! - } - } - - function startCutscene(){ + } + else + { + // Make sure the cutscene can play again next time! + hasPlayedCutscene = false; + // DO NOT CANCEL THE EVENT! + } + } + function startCutscene() + { var normalSanta = PlayState.instance.currentStage.getNamedProp('santa'); normalSanta.visible = false; var santaDead:ScriptedFlxAtlasSprite = ScriptedFlxAtlasSprite.init('SantaDiesSprite', 0, 0); santaDead.x = -458; - santaDead.y = 498; - santaDead.zIndex = normalSanta.zIndex - 1; + santaDead.y = 498; + santaDead.zIndex = normalSanta.zIndex - 1; PlayState.instance.currentStage.add(santaDead); - PlayState.instance.currentStage.refresh(); // Apply z-index. + PlayState.instance.currentStage.refresh(); // Apply z-index. santaDead.scriptCall('playCutscene'); @@ -106,70 +111,63 @@ class EggnogSong extends Song var parentsShoot:ScriptedFlxAtlasSprite = ScriptedFlxAtlasSprite.init('DadShootsSprite', 0, 0); parentsShoot.x = -516; - parentsShoot.y = 503; - parentsShoot.zIndex = santaDead.zIndex - 1; + parentsShoot.y = 503; + parentsShoot.zIndex = santaDead.zIndex - 1; PlayState.instance.currentStage.add(parentsShoot); - PlayState.instance.currentStage.refresh(); // Apply z-index. + PlayState.instance.currentStage.refresh(); // Apply z-index. parentsShoot.scriptCall('playCutscene'); - //FlxTween.tween(PlayState.instance.camHUD, {alpha: 0}, 1); + // FlxTween.tween(PlayState.instance.camHUD, {alpha: 0}, 1); - PlayState.instance.isInCutscene = true; - hasPlayedCutscene = true; + PlayState.instance.isInCutscene = true; + hasPlayedCutscene = true; - PlayState.instance.currentStage.getBoyfriend().danceEvery = 0; - PlayState.instance.currentStage.getDad().danceEvery = 0; + PlayState.instance.currentStage.getBoyfriend().danceEvery = 0; + PlayState.instance.currentStage.getDad().danceEvery = 0; PlayState.instance.tweenCameraToPosition(santaDead.x + 300, santaDead.y, 2.8, FlxEase.expoOut); - //PlayState.instance.tweenCameraToPosition(santaDead.x + 300, santaDead.y, 2.8, FlxEase.expoOut); - PlayState.instance.tweenCameraZoom(0.73, 2, true, FlxEase.quadInOut); - - FunkinSound.playOnce(Paths.sound('santa_emotion'), 1); - - new FlxTimer().start(2.8, function(tmr) - { - PlayState.instance.tweenCameraToPosition(santaDead.x + 150, santaDead.y, 9, FlxEase.quartInOut); - PlayState.instance.tweenCameraZoom(0.79, 9, true, FlxEase.quadInOut); - }); - - - new FlxTimer().start(11.3, function(tmr){ - //PlayState.instance.tweenCameraZoom(0.73, 0.8, true, FlxEase.backOut); - //PlayState.instance.tweenCameraToPosition(santaDead.x + 220, santaDead.y, 0.8, FlxEase.expoOut); - //PlayState.instance.camGame.shake(0.007, 0.4); - }); - new FlxTimer().start(11.375, function(tmr) - { - FunkinSound.playOnce(Paths.sound('santa_shot_n_falls'), 1); - }); - - new FlxTimer().start(12.83, function(tmr) - { - PlayState.instance.camGame.shake(0.005, 0.2); - PlayState.instance.tweenCameraToPosition(santaDead.x + 160, santaDead.y + 80, 5, FlxEase.expoOut); - }); - - - new FlxTimer().start(15, function(tmr) - { - PlayState.instance.camHUD.fade(0xFF000000, 1, false, null, true); - }); - - new FlxTimer().start(16, function(tmr) - { - PlayState.instance.camHUD.fade(0xFF000000, 0.5, true, null, true); - PlayState.instance.endSong(true); - }); - - } + // PlayState.instance.tweenCameraToPosition(santaDead.x + 300, santaDead.y, 2.8, FlxEase.expoOut); + PlayState.instance.tweenCameraZoom(0.73, 2, true, FlxEase.quadInOut); + + FunkinSound.playOnce(Paths.sound('santa_emotion'), 1); + + new FlxTimer().start(2.8, function(tmr) { + PlayState.instance.tweenCameraToPosition(santaDead.x + 150, santaDead.y, 9, FlxEase.quartInOut); + PlayState.instance.tweenCameraZoom(0.79, 9, true, FlxEase.quadInOut); + }); + + new FlxTimer().start(11.3, function(tmr) { + // PlayState.instance.tweenCameraZoom(0.73, 0.8, true, FlxEase.backOut); + // PlayState.instance.tweenCameraToPosition(santaDead.x + 220, santaDead.y, 0.8, FlxEase.expoOut); + // PlayState.instance.camGame.shake(0.007, 0.4); + }); + new FlxTimer().start(11.375, function(tmr) { + FunkinSound.playOnce(Paths.sound('santa_shot_n_falls'), 1); + }); + + new FlxTimer().start(12.83, function(tmr) { + PlayState.instance.camGame.shake(0.005, 0.2); + PlayState.instance.tweenCameraToPosition(santaDead.x + 160, santaDead.y + 80, 5, FlxEase.expoOut); + }); + + new FlxTimer().start(15, function(tmr) { + PlayState.instance.camHUD.fade(0xFF000000, 1, false, null, true); + }); + + new FlxTimer().start(16, function(tmr) { + PlayState.instance.camHUD.fade(0xFF000000, 0.5, true, null, true); + PlayState.instance.endSong(true); + }); + } - function onUpdate(event:UpdateScriptEvent) { - super.onUpdate(event); - } + function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); + } - /** + /** * Replay the cutscene after leaving the song. */ function onCreate(event:ScriptEvent):Void diff --git a/preload/scripts/songs/fresh.hxc b/preload/scripts/songs/fresh.hxc index 94ff59145..dab242f7c 100644 --- a/preload/scripts/songs/fresh.hxc +++ b/preload/scripts/songs/fresh.hxc @@ -9,29 +9,32 @@ import flixel.FlxG; import flixel.FlxSprite; import flixel.util.FlxTimer; import funkin.save.Save; - import funkin.effects.RetroCameraFade; -class FreshSong extends Song { +class FreshSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('fresh'); - } + public function new() + { + super('fresh'); + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool { - if(currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); return false; - } + } - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! diff --git a/preload/scripts/songs/guns.hxc b/preload/scripts/songs/guns.hxc index ab9f7277a..af61e729d 100644 --- a/preload/scripts/songs/guns.hxc +++ b/preload/scripts/songs/guns.hxc @@ -2,30 +2,34 @@ import funkin.play.song.Song; import funkin.play.PlayState; import funkin.play.cutscene.VideoCutscene; import funkin.save.Save; - import funkin.play.PlayStatePlaylist; -class GunsSong extends Song { +class GunsSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('guns'); + public function new() + { + super('guns'); hasPlayedCutscene = false; - } + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool{ - if(currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); return false; - } + } - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! @@ -36,12 +40,14 @@ class GunsSong extends Song { } } - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); if (!PlayStatePlaylist.isStoryMode) hasPlayedCutscene = true; - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { trace('Pausing countdown to play a video cutscene (`guns`)'); hasPlayedCutscene = true; @@ -50,9 +56,10 @@ class GunsSong extends Song { startVideo(); } - } + } - function startVideo() { + function startVideo() + { VideoCutscene.play(Paths.videos('gunsCutscene')); } diff --git a/preload/scripts/songs/lit-up.hxc b/preload/scripts/songs/lit-up.hxc index 9dc52560e..2e21b997a 100644 --- a/preload/scripts/songs/lit-up.hxc +++ b/preload/scripts/songs/lit-up.hxc @@ -2,20 +2,23 @@ import funkin.play.song.Song; import funkin.play.PlayState; import funkin.play.cutscene.VideoCutscene; import funkin.save.Save; - import funkin.play.PlayStatePlaylist; -class LitUpSong extends Song { - public function new() { - super('lit-up'); - } +class LitUpSong extends Song +{ + public function new() + { + super('lit-up'); + } - public function listDifficulties(variationId:String, variationIds:Array, showLocked:Bool):Array { - if (showLocked || Save.instance.hasBeatenLevel('weekend1')) { - return super.listDifficulties(variationId, variationIds); - } + public function listDifficulties(variationId:String, variationIds:Array, showLocked:Bool):Array + { + if (showLocked || Save.instance.hasBeatenLevel('weekend1')) + { + return super.listDifficulties(variationId, variationIds); + } - // Hide all difficulties if the player has not beaten the week. - return []; - } + // Hide all difficulties if the player has not beaten the week. + return []; + } } diff --git a/preload/scripts/songs/philly-nice.hxc b/preload/scripts/songs/philly-nice.hxc index e127a48f1..25a1e4ca2 100644 --- a/preload/scripts/songs/philly-nice.hxc +++ b/preload/scripts/songs/philly-nice.hxc @@ -9,28 +9,32 @@ import flixel.FlxG; import flixel.FlxSprite; import flixel.util.FlxTimer; import funkin.save.Save; - import funkin.effects.RetroCameraFade; -class PhillyNiceSong extends Song { +class PhillyNiceSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('philly-nice'); - } + public function new() + { + super('philly-nice'); + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool{ - if(currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); return false; - } + } - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! diff --git a/preload/scripts/songs/pico.hxc b/preload/scripts/songs/pico.hxc index 9e8d88383..ca3e3ec60 100644 --- a/preload/scripts/songs/pico.hxc +++ b/preload/scripts/songs/pico.hxc @@ -9,28 +9,32 @@ import flixel.FlxG; import flixel.FlxSprite; import flixel.util.FlxTimer; import funkin.save.Save; - import funkin.effects.RetroCameraFade; -class PhillyNiceSong extends Song { +class PhillyNiceSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('pico'); - } + public function new() + { + super('pico'); + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool{ - if(currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); return false; - } + } - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! diff --git a/preload/scripts/songs/roses.hxc b/preload/scripts/songs/roses.hxc index c9200b607..38f8afe6f 100644 --- a/preload/scripts/songs/roses.hxc +++ b/preload/scripts/songs/roses.hxc @@ -10,20 +10,24 @@ import flixel.tweens.FlxTween; import flixel.tweens.FlxEase; import funkin.ui.options.PreferencesMenu; -class RosesSong extends Song { +class RosesSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('roses'); - } + public function new() + { + super('roses'); + } - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); trace('Started countdown for Roses...'); if (!PlayStatePlaylist.isStoryMode) hasPlayedCutscene = true; - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { trace('Pausing countdown to play cutscene.'); hasPlayedCutscene = true; @@ -37,13 +41,17 @@ class RosesSong extends Song { startDialogue(); } - } + } - function startDialogue() { - if (Preferences.naughtyness) { + function startDialogue() + { + if (Preferences.naughtyness) + { trace('Playing uncensored dialogue...'); PlayState.instance.startConversation('roses'); - } else { + } + else + { trace('Playing censored dialogue...'); PlayState.instance.startConversation('roses-censored'); } @@ -69,13 +77,14 @@ class RosesSong extends Song { hasPlayedCutscene = false; } - function onBeatHit(event:SongTimeScriptEvent) + function onBeatHit(event:SongTimeScriptEvent) { // When overriding onBeatHit, make sure to call super.onBeatHit, // otherwise boppers will not work. super.onBeatHit(event); - if (event.beat == 180 && PlayStatePlaylist.isStoryMode) { + if (event.beat == 180 && PlayStatePlaylist.isStoryMode) + { trace('Hit end of song! Starting outro.'); PlayState.instance.camCutscene.visible = true; @@ -90,7 +99,8 @@ class RosesSong extends Song { } } - public override function onDialogueEnd() { + public override function onDialogueEnd() + { // We may need to wait for the outro to play. Countdown.performCountdown(); } diff --git a/preload/scripts/songs/satin-panties.hxc b/preload/scripts/songs/satin-panties.hxc index 380c91795..dd683951e 100644 --- a/preload/scripts/songs/satin-panties.hxc +++ b/preload/scripts/songs/satin-panties.hxc @@ -18,11 +18,10 @@ import funkin.play.song.Song; import funkin.play.stage.StageProp; import funkin.save.Save; - class SatinPantiesSong extends Song { - function new() - { - super('satin-panties'); - } + function new() + { + super('satin-panties'); + } } diff --git a/preload/scripts/songs/senpai.hxc b/preload/scripts/songs/senpai.hxc index feb272fd2..c5ffd0ca1 100644 --- a/preload/scripts/songs/senpai.hxc +++ b/preload/scripts/songs/senpai.hxc @@ -8,22 +8,25 @@ import funkin.play.song.Song; import flixel.FlxG; import flixel.FlxSprite; import flixel.util.FlxTimer; - import funkin.effects.RetroCameraFade; -class SenpaiSong extends Song { +class SenpaiSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('senpai'); - } + public function new() + { + super('senpai'); + } - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); if (!PlayStatePlaylist.isStoryMode) hasPlayedCutscene = true; - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { trace('Pausing countdown to play cutscene.'); hasPlayedCutscene = true; @@ -34,9 +37,10 @@ class SenpaiSong extends Song { transitionToDialogue(); } - } + } - function transitionToDialogue() { + function transitionToDialogue() + { trace('Transitioning to dialogue.'); PlayState.instance.camCutscene.visible = true; @@ -58,18 +62,19 @@ class SenpaiSong extends Song { RetroCameraFade.fadeBlack(PlayState.instance.camGame, 12, 2); }); - FlxTween.num(0.0, 1.0, 2.0, { - ease: FlxEase.linear, - startDelay: 0.25, - onComplete: function (input) { - - // black.visible = false; - startDialogue(); - } - }, tweenFunction); + FlxTween.num(0.0, 1.0, 2.0, + { + ease: FlxEase.linear, + startDelay: 0.25, + onComplete: function(input) { + // black.visible = false; + startDialogue(); + } + }, tweenFunction); } - function startDialogue() { + function startDialogue() + { PlayState.instance.startConversation('senpai'); } @@ -93,7 +98,8 @@ class SenpaiSong extends Song { hasPlayedCutscene = false; } - public override function onDialogueEnd() { + public override function onDialogueEnd() + { // We may need to wait for the outro to play. PlayState.instance.currentStage.resume(); Countdown.performCountdown(); diff --git a/preload/scripts/songs/south.hxc b/preload/scripts/songs/south.hxc index 567de25ac..15faab013 100644 --- a/preload/scripts/songs/south.hxc +++ b/preload/scripts/songs/south.hxc @@ -9,28 +9,32 @@ import flixel.FlxG; import flixel.FlxSprite; import flixel.util.FlxTimer; import funkin.save.Save; - import funkin.effects.RetroCameraFade; -class SouthSong extends Song { +class SouthSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('south'); - } + public function new() + { + super('south'); + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool{ - if(currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); return false; - } + } - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! diff --git a/preload/scripts/songs/spookeez.hxc b/preload/scripts/songs/spookeez.hxc index 6a4bafeb7..6f2d03809 100644 --- a/preload/scripts/songs/spookeez.hxc +++ b/preload/scripts/songs/spookeez.hxc @@ -9,28 +9,32 @@ import flixel.FlxG; import flixel.FlxSprite; import flixel.util.FlxTimer; import funkin.save.Save; - import funkin.effects.RetroCameraFade; -class SpookeezSong extends Song { +class SpookeezSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('spookeez'); - } + public function new() + { + super('spookeez'); + } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool{ - if (currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); return false; - } + } - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! diff --git a/preload/scripts/songs/stress.hxc b/preload/scripts/songs/stress.hxc index 416a4e1d7..08d9f1e0e 100644 --- a/preload/scripts/songs/stress.hxc +++ b/preload/scripts/songs/stress.hxc @@ -1,26 +1,29 @@ import funkin.play.song.Song; import funkin.play.PlayState; - import funkin.play.PlayStatePlaylist; import funkin.modding.base.ScriptedFlxSpriteGroup; import funkin.play.cutscene.VideoCutscene; -class StressSong extends Song { +class StressSong extends Song +{ var hasPlayedCutscene:Bool; - var tankmanGroup:TankmanSpriteGroup; + var tankmanGroup:TankmanSpriteGroup; - public function new() { - super('stress'); + public function new() + { + super('stress'); hasPlayedCutscene = false; - } + } - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); if (!PlayStatePlaylist.isStoryMode) hasPlayedCutscene = true; - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { trace('Pausing countdown to play a video cutscene (`stress`)'); hasPlayedCutscene = true; @@ -33,27 +36,30 @@ class StressSong extends Song { trace('Initializing tankman group...'); tankmanGroup = ScriptedFlxSpriteGroup.init('TankmanSpriteGroup'); - if (tankmanGroup != null) { + if (tankmanGroup != null) + { // resets the tankmen! tankmanGroup.scriptCall('reset'); tankmanGroup.zIndex = 30; PlayState.instance.currentStage.add(tankmanGroup); PlayState.instance.currentStage.refresh(); - } else { + } + else + { trace('Failed to initialize tankman group!'); } - } + } var tankmanGroup = null; function onSongStart(event:ScriptEvent):Void { super.onSongStart(event); - } - function startVideo() { + function startVideo() + { VideoCutscene.play(Paths.videos('stressCutscene')); } @@ -66,13 +72,15 @@ class StressSong extends Song { hasPlayedCutscene = true; - // resets the tankmen! - if (tankmanGroup != null) { - tankmanGroup.scriptCall('reset'); - } - if(PlayState.instance.currentStage.getGirlfriend() != null){ - PlayState.instance.currentStage.getGirlfriend().scriptCall('reset'); - trace('reset pico!'); + // resets the tankmen! + if (tankmanGroup != null) + { + tankmanGroup.scriptCall('reset'); + } + if (PlayState.instance.currentStage.getGirlfriend() != null) + { + PlayState.instance.currentStage.getGirlfriend().scriptCall('reset'); + trace('reset pico!'); } } @@ -86,8 +94,10 @@ class StressSong extends Song { hasPlayedCutscene = false; } - function kill():Void { - if (tankmanGroup != null) { + function kill():Void + { + if (tankmanGroup != null) + { PlayState.instance.currentStage.remove(tankmanGroup); tankmanGroup.destroy(); tankmanGroup = null; diff --git a/preload/scripts/songs/thorns.hxc b/preload/scripts/songs/thorns.hxc index 95f8dbb7c..419fd0697 100644 --- a/preload/scripts/songs/thorns.hxc +++ b/preload/scripts/songs/thorns.hxc @@ -9,31 +9,34 @@ import funkin.play.PlayStatePlaylist; import flixel.util.FlxTimer; import funkin.effects.RetroCameraFade; - -class ThornsSong extends Song { +class ThornsSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('thorns'); - } + public function new() + { + super('thorns'); + } - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); if (!PlayStatePlaylist.isStoryMode) hasPlayedCutscene = true; - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { trace('Pausing countdown to play cutscene.'); - hasPlayedCutscene = true; startCutscene(); event.cancel(); // CANCEL THE COUNTDOWN! } - } + } - function startCutscene() { + function startCutscene() + { trace('Hit start of song! Starting cutscene.'); PlayState.instance.disableKeys = true; @@ -50,15 +53,15 @@ class ThornsSong extends Song { var senpaiCrazy = FunkinSprite.createSparrow(0, 0, 'weeb/senpaiCrazy'); senpaiCrazy.cameras = [PlayState.instance.camCutscene]; senpaiCrazy.animation.addByPrefix('idle', 'Senpai Pre Explosion instance 1', 24, false); - senpaiCrazy.setGraphicSize(Std.int(senpaiCrazy.width * Constants.PIXEL_ART_SCALE)); + senpaiCrazy.setGraphicSize(Std.int(senpaiCrazy.width * Constants.PIXEL_ART_SCALE)); senpaiCrazy.antialiasing = false; senpaiCrazy.pixelPerfectRender = true; senpaiCrazy.pixelPerfectPosition = true; senpaiCrazy.scrollFactor.set(); - senpaiCrazy.updateHitbox(); - senpaiCrazy.screenCenter(); - senpaiCrazy.x += senpaiCrazy.width / 5; + senpaiCrazy.updateHitbox(); + senpaiCrazy.screenCenter(); + senpaiCrazy.x += senpaiCrazy.width / 5; senpaiCrazy.alpha = 0; @@ -68,9 +71,12 @@ class ThornsSong extends Song { new FlxTimer().start(0.3, function(timer:FlxTimer) { senpaiCrazy.alpha += 0.15; - if (senpaiCrazy.alpha < 1) { + if (senpaiCrazy.alpha < 1) + { timer.reset(); - } else { + } + else + { senpaiCrazy.alpha = 1; // Play the actual animation. @@ -78,7 +84,7 @@ class ThornsSong extends Song { // Play the SFX alongside it. trace('Playing senpai death SFX.'); - FunkinSound.playOnce(Paths.sound('Senpai_Dies'), 1.0, function () { + FunkinSound.playOnce(Paths.sound('Senpai_Dies'), 1.0, function() { trace('Senpai death SFX done.'); // Called when the sound completes. Clean up the cutscene here. // Hard cut to the cutscene. @@ -87,16 +93,13 @@ class ThornsSong extends Song { RetroCameraFade.fadeBlack(PlayState.instance.camCutscene, 6, 1.4); RetroCameraFade.fadeBlack(PlayState.instance.camGame, 6, 1.4); new FlxTimer().start(1.6, _ -> { - startDialogue(); - }); // PlayState.instance.camCutscene.fade(0xFFEEEEEE, 0.8, true); }); // Fade to white 3.2 seconds into the cutscene. - new FlxTimer().start(3.2, function(deadTime:FlxTimer) - { + new FlxTimer().start(3.2, function(deadTime:FlxTimer) { RetroCameraFade.fadeWhite(PlayState.instance.camCutscene, 8, 1.4); new FlxTimer().start(1.4, function(timer:FlxTimer) { red.color = 0xFFFFFFFF; @@ -112,7 +115,8 @@ class ThornsSong extends Song { }); } - function startDialogue() { + function startDialogue() + { PlayState.instance.disableKeys = false; PlayState.instance.startConversation('thorns'); } @@ -137,10 +141,9 @@ class ThornsSong extends Song { hasPlayedCutscene = false; } - public override function onDialogueEnd() { + public override function onDialogueEnd() + { // We may need to wait for the outro to play. Countdown.performCountdown(); - - } } diff --git a/preload/scripts/songs/ugh.hxc b/preload/scripts/songs/ugh.hxc index c60753cf7..83df4fa40 100644 --- a/preload/scripts/songs/ugh.hxc +++ b/preload/scripts/songs/ugh.hxc @@ -2,23 +2,27 @@ import funkin.play.song.Song; import funkin.play.PlayState; import funkin.play.cutscene.VideoCutscene; import funkin.save.Save; - import funkin.play.PlayStatePlaylist; -class UghSong extends Song { +class UghSong extends Song +{ var hasPlayedCutscene:Bool; - public function new() { - super('ugh'); + public function new() + { + super('ugh'); hasPlayedCutscene = false; - } + } - public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array { - if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') { + public override function listAltInstrumentalIds(difficultyId:String, variationId:String):Array + { + if (difficultyId == 'easy' || difficultyId == 'normal' || difficultyId == 'hard') + { var hasBeatenPicoMix = Save.instance.hasBeatenSong(this.id, null, 'pico'); - switch (variationId) { + switch (variationId) + { case 'pico': // return hasBeatenPicoMix ? [''] : []; // No Pico mix on BF instrumental, sorry! @@ -29,23 +33,23 @@ class UghSong extends Song { } } - public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool{ - if(currentVariation == 'pico') - return !Save.instance.hasBeatenSong(this.id, null, 'pico'); - - if (currentDifficulty == 'erect' || currentDifficulty == 'nightmare') - return !Save.instance.hasBeatenSong(this.id, ['erect', 'nightmare']); + public override function isSongNew(currentDifficulty:String, currentVariation:String):Bool + { + if (currentVariation == 'pico') return !Save.instance.hasBeatenSong(this.id, null, 'pico'); + if (currentDifficulty == 'erect' || currentDifficulty == 'nightmare') return !Save.instance.hasBeatenSong(this.id, ['erect', 'nightmare']); return false; - } + } - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); if (!PlayStatePlaylist.isStoryMode) hasPlayedCutscene = true; - if (!hasPlayedCutscene) { + if (!hasPlayedCutscene) + { trace('Pausing countdown to play a video cutscene (`ugh`)'); hasPlayedCutscene = true; @@ -54,9 +58,10 @@ class UghSong extends Song { startVideo(); } - } + } - function startVideo() { + function startVideo() + { VideoCutscene.play(Paths.videos('ughCutscene')); } diff --git a/preload/scripts/stages/limoRide.hxc b/preload/scripts/stages/limoRide.hxc index 933eba84d..513eda8f7 100644 --- a/preload/scripts/stages/limoRide.hxc +++ b/preload/scripts/stages/limoRide.hxc @@ -8,106 +8,108 @@ import funkin.graphics.shaders.OverlayBlend; class LimoRideStage extends Stage { - function new() - { - super('limoRide'); - } - - function buildStage() - { - super.buildStage(); - - // Apply sky shader. - var skyOverlay:OverlayBlend = new OverlayBlend(); - var sunOverlay:FlxSprite = new FlxSprite().loadGraphic(Paths.image('limo/limoOverlay')); - sunOverlay.setGraphicSize(Std.int(sunOverlay.width * 2)); - sunOverlay.updateHitbox(); - skyOverlay.funnyShit.input = sunOverlay.pixels; - var limoSunset:FlxSprite = getNamedProp('limoSunset'); - if (limoSunset == null) { - trace('[WARN] Could not retrieve limoSunset'); - } else { - limoSunset.shader = skyOverlay; - } - - // There's some commented-out shader BS in the original code. - // I don't know what it's for, but it's not used in the game. - // If you want to re-add it, go find it in version control. - - resetFastCar(); - } - - function onBeatHit(event:SongTimeScriptEvent) - { - // When overriding onBeatHit, make sure to call super.onBeatHit, - // otherwise boppers will not work. - super.onBeatHit(event); - - if (FlxG.random.bool(10) && fastCarCanDrive) - fastCarDrive(); - } - - var fastCarCanDrive:Bool = false; - - function resetFastCar():Void - { - var fastCar = getNamedProp('fastCar'); - - if (fastCar == null) - return; - - // Props are inactive by default. - // Set active to true so position is calculated based on velocity. - fastCar.active = true; - - fastCar.x = -12600; - fastCar.y = FlxG.random.int(140, 250); - fastCar.velocity.x = 0; - fastCarCanDrive = true; - } - - function fastCarDrive():Void - { - FunkinSound.playOnce(Paths.soundRandom('carPass', 0, 1), 0.7); - - var fastCar = getNamedProp('fastCar'); - fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3; - fastCarCanDrive = false; - new FlxTimer().start(2, function(tmr:FlxTimer) - { - resetFastCar(); - }); - } - - /** - * If your stage uses additional assets not specified in the JSON, - * make sure to specify them like this, or they won't get cached in the loading screen. - */ - function fetchAssetPaths():Array - { - var results:Array = super.fetchAssetPaths(); - - // This graphic is applied by shader to the background, so it's not included in the default stage function. - results.push(Paths.image('limo/limoOverlay')); - results.push(Paths.sound('carPass0')); - results.push(Paths.sound('carPass1')); - - return results; - } - - /** - * Make sure the fast car is reset when the song restarts. - */ - function onSongRetry(event:ScriptEvent) { - super.onSongRetry(event); - resetFastCar(); - } - - /** - * Make sure the fast car is reset when the song restarts. - */ - function onCountdownStart(event:ScriptEvent) { - super.onCountdownStart(event); - resetFastCar(); - } + function new() + { + super('limoRide'); + } + + function buildStage() + { + super.buildStage(); + + // Apply sky shader. + var skyOverlay:OverlayBlend = new OverlayBlend(); + var sunOverlay:FlxSprite = new FlxSprite().loadGraphic(Paths.image('limo/limoOverlay')); + sunOverlay.setGraphicSize(Std.int(sunOverlay.width * 2)); + sunOverlay.updateHitbox(); + skyOverlay.funnyShit.input = sunOverlay.pixels; + var limoSunset:FlxSprite = getNamedProp('limoSunset'); + if (limoSunset == null) + { + trace('[WARN] Could not retrieve limoSunset'); + } + else + { + limoSunset.shader = skyOverlay; + } + + // There's some commented-out shader BS in the original code. + // I don't know what it's for, but it's not used in the game. + // If you want to re-add it, go find it in version control. + + resetFastCar(); + } + + function onBeatHit(event:SongTimeScriptEvent) + { + // When overriding onBeatHit, make sure to call super.onBeatHit, + // otherwise boppers will not work. + super.onBeatHit(event); + + if (FlxG.random.bool(10) && fastCarCanDrive) fastCarDrive(); + } + + var fastCarCanDrive:Bool = false; + + function resetFastCar():Void + { + var fastCar = getNamedProp('fastCar'); + + if (fastCar == null) return; + + // Props are inactive by default. + // Set active to true so position is calculated based on velocity. + fastCar.active = true; + + fastCar.x = -12600; + fastCar.y = FlxG.random.int(140, 250); + fastCar.velocity.x = 0; + fastCarCanDrive = true; + } + + function fastCarDrive():Void + { + FunkinSound.playOnce(Paths.soundRandom('carPass', 0, 1), 0.7); + + var fastCar = getNamedProp('fastCar'); + fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3; + fastCarCanDrive = false; + new FlxTimer().start(2, function(tmr:FlxTimer) { + resetFastCar(); + }); + } + + /** + * If your stage uses additional assets not specified in the JSON, + * make sure to specify them like this, or they won't get cached in the loading screen. + */ + function fetchAssetPaths():Array + { + var results:Array = super.fetchAssetPaths(); + + // This graphic is applied by shader to the background, so it's not included in the default stage function. + results.push(Paths.image('limo/limoOverlay')); + results.push(Paths.sound('carPass0')); + results.push(Paths.sound('carPass1')); + + return results; + } + + /** + * Make sure the fast car is reset when the song restarts. + */ + function onSongRetry(event:ScriptEvent) + { + super.onSongRetry(event); + resetFastCar(); + } + + /** + * Make sure the fast car is reset when the song restarts. + */ + function onCountdownStart(event:ScriptEvent) + { + super.onCountdownStart(event); + resetFastCar(); + } } diff --git a/preload/scripts/stages/limoRideErect.hxc b/preload/scripts/stages/limoRideErect.hxc index bc54e08b5..4484fe20b 100644 --- a/preload/scripts/stages/limoRideErect.hxc +++ b/preload/scripts/stages/limoRideErect.hxc @@ -10,250 +10,251 @@ import flixel.addons.display.FlxBackdrop; class LimoRideErectStage extends Stage { - function new() - { - super('limoRideErect'); - } + function new() + { + super('limoRideErect'); + } var colorShader:AdjustColorShader; - var mist1:FlxBackdrop; - var mist2:FlxBackdrop; - var mist3:FlxBackdrop; - var mist4:FlxBackdrop; - var mist5:FlxBackdrop; - - var shootingStarBeat:Int = 0; - var shootingStarOffset:Int = 2; - - function buildStage() - { - super.buildStage(); - - // Apply sky shader. - var skyOverlay:OverlayBlend = new OverlayBlend(); - var sunOverlay:FlxSprite = new FlxSprite().loadGraphic(Paths.image('limo/limoOverlay')); - sunOverlay.setGraphicSize(Std.int(sunOverlay.width * 2)); - sunOverlay.updateHitbox(); - skyOverlay.funnyShit.input = sunOverlay.pixels; - var limoSunset:FlxSprite = getNamedProp('limoSunset'); - if (limoSunset == null) { - trace('[WARN] Could not retrieve limoSunset'); - } else { - //limoSunset.shader = skyOverlay; - } - - // There's some commented-out shader BS in the original code. - // I don't know what it's for, but it's not used in the game. - // If you want to re-add it, go find it in version control. + var mist1:FlxBackdrop; + var mist2:FlxBackdrop; + var mist3:FlxBackdrop; + var mist4:FlxBackdrop; + var mist5:FlxBackdrop; + + var shootingStarBeat:Int = 0; + var shootingStarOffset:Int = 2; + + function buildStage() + { + super.buildStage(); + + // Apply sky shader. + var skyOverlay:OverlayBlend = new OverlayBlend(); + var sunOverlay:FlxSprite = new FlxSprite().loadGraphic(Paths.image('limo/limoOverlay')); + sunOverlay.setGraphicSize(Std.int(sunOverlay.width * 2)); + sunOverlay.updateHitbox(); + skyOverlay.funnyShit.input = sunOverlay.pixels; + var limoSunset:FlxSprite = getNamedProp('limoSunset'); + if (limoSunset == null) + { + trace('[WARN] Could not retrieve limoSunset'); + } + else + { + // limoSunset.shader = skyOverlay; + } + + // There's some commented-out shader BS in the original code. + // I don't know what it's for, but it's not used in the game. + // If you want to re-add it, go find it in version control. colorShader = new AdjustColorShader(); mist1 = new FlxBackdrop(Paths.image('limo/erect/mistMid'), 0x01); - mist1.setPosition(-650, -100); - mist1.scrollFactor.set(1.1, 1.1); - mist1.zIndex = 400; + mist1.setPosition(-650, -100); + mist1.scrollFactor.set(1.1, 1.1); + mist1.zIndex = 400; mist1.blend = 0; - mist1.color = 0xFFc6bfde; - mist1.alpha = 0.4; - mist1.velocity.x = 1700; + mist1.color = 0xFFc6bfde; + mist1.alpha = 0.4; + mist1.velocity.x = 1700; - PlayState.instance.currentStage.add(mist1); - PlayState.instance.currentStage.refresh(); // Apply z-index. + PlayState.instance.currentStage.add(mist1); + PlayState.instance.currentStage.refresh(); // Apply z-index. - mist2 = new FlxBackdrop(Paths.image('limo/erect/mistBack'), 0x01); - mist2.setPosition(-650, -100); - mist2.scrollFactor.set(1.2, 1.2); - mist2.zIndex = 401; + mist2 = new FlxBackdrop(Paths.image('limo/erect/mistBack'), 0x01); + mist2.setPosition(-650, -100); + mist2.scrollFactor.set(1.2, 1.2); + mist2.zIndex = 401; mist2.blend = 0; - mist2.color = 0xFF6a4da1; - mist2.alpha = 1; - mist2.velocity.x = 2100; - mist1.scale.set(1.3, 1.3); - - PlayState.instance.currentStage.add(mist2); - PlayState.instance.currentStage.refresh(); // Apply z-index. - - mist3 = new FlxBackdrop(Paths.image('limo/erect/mistMid'), 0x01); - mist3.setPosition(-650, -100); - mist3.scrollFactor.set(0.8, 0.8); - mist3.zIndex = 99; - mist3.blend = 0; - mist3.color = 0xFFa7d9be; - mist3.alpha = 0.5; - mist3.velocity.x = 900; - mist3.scale.set(1.5, 1.5); - - PlayState.instance.currentStage.add(mist3); - PlayState.instance.currentStage.refresh(); // Apply z-index. - - - mist4 = new FlxBackdrop(Paths.image('limo/erect/mistBack'), 0x01); - mist4.setPosition(-650, -380); - mist4.scrollFactor.set(0.6, 0.6); - mist4.zIndex = 98; + mist2.color = 0xFF6a4da1; + mist2.alpha = 1; + mist2.velocity.x = 2100; + mist1.scale.set(1.3, 1.3); + + PlayState.instance.currentStage.add(mist2); + PlayState.instance.currentStage.refresh(); // Apply z-index. + + mist3 = new FlxBackdrop(Paths.image('limo/erect/mistMid'), 0x01); + mist3.setPosition(-650, -100); + mist3.scrollFactor.set(0.8, 0.8); + mist3.zIndex = 99; + mist3.blend = 0; + mist3.color = 0xFFa7d9be; + mist3.alpha = 0.5; + mist3.velocity.x = 900; + mist3.scale.set(1.5, 1.5); + + PlayState.instance.currentStage.add(mist3); + PlayState.instance.currentStage.refresh(); // Apply z-index. + + mist4 = new FlxBackdrop(Paths.image('limo/erect/mistBack'), 0x01); + mist4.setPosition(-650, -380); + mist4.scrollFactor.set(0.6, 0.6); + mist4.zIndex = 98; mist4.blend = 0; - mist4.color = 0xFF9c77c7; - mist4.alpha = 1; - mist4.velocity.x = 700; - mist4.scale.set(1.5, 1.5); - - PlayState.instance.currentStage.add(mist4); - PlayState.instance.currentStage.refresh(); // Apply z-index. - - mist5 = new FlxBackdrop(Paths.image('limo/erect/mistMid'), 0x01); - mist5.setPosition(-650, -400); - mist5.scrollFactor.set(0.2, 0.2); - mist5.zIndex = 15; - mist5.blend = 0; - mist5.color = 0xFFE7A480; - mist5.alpha = 1; - mist5.velocity.x = 100; - mist5.scale.set(1.5, 1.5); - - PlayState.instance.currentStage.add(mist5); - PlayState.instance.currentStage.refresh(); // Apply z-index. - - getNamedProp('shootingStar').blend = 0; - - resetFastCar(); - } + mist4.color = 0xFF9c77c7; + mist4.alpha = 1; + mist4.velocity.x = 700; + mist4.scale.set(1.5, 1.5); + + PlayState.instance.currentStage.add(mist4); + PlayState.instance.currentStage.refresh(); // Apply z-index. + + mist5 = new FlxBackdrop(Paths.image('limo/erect/mistMid'), 0x01); + mist5.setPosition(-650, -400); + mist5.scrollFactor.set(0.2, 0.2); + mist5.zIndex = 15; + mist5.blend = 0; + mist5.color = 0xFFE7A480; + mist5.alpha = 1; + mist5.velocity.x = 100; + mist5.scale.set(1.5, 1.5); + + PlayState.instance.currentStage.add(mist5); + PlayState.instance.currentStage.refresh(); // Apply z-index. + + getNamedProp('shootingStar').blend = 0; + + resetFastCar(); + } - var _timer:Float = 0; + var _timer:Float = 0; function onUpdate(event:UpdateScriptEvent):Void - { - super.onUpdate(event); - - _timer += event.elapsed; - mist1.y = 100 + (Math.sin(_timer)*200); - mist2.y = 0 + (Math.sin(_timer*0.8)*100); - mist3.y = -20 + (Math.sin(_timer*0.5)*200); - mist4.y = -180 + (Math.sin(_timer*0.4)*300); - mist5.y = -450 + (Math.sin(_timer*0.2)*150); - //trace(mist1.y); - - if(PlayState.instance.currentStage.getBoyfriend() != null && PlayState.instance.currentStage.getBoyfriend().shader == null){ + { + super.onUpdate(event); + + _timer += event.elapsed; + mist1.y = 100 + (Math.sin(_timer) * 200); + mist2.y = 0 + (Math.sin(_timer * 0.8) * 100); + mist3.y = -20 + (Math.sin(_timer * 0.5) * 200); + mist4.y = -180 + (Math.sin(_timer * 0.4) * 300); + mist5.y = -450 + (Math.sin(_timer * 0.2) * 150); + // trace(mist1.y); + + if (PlayState.instance.currentStage.getBoyfriend() != null && PlayState.instance.currentStage.getBoyfriend().shader == null) + { PlayState.instance.currentStage.getBoyfriend().shader = colorShader; - PlayState.instance.currentStage.getGirlfriend().shader = colorShader; - PlayState.instance.currentStage.getDad().shader = colorShader; - getNamedProp('limoDancer1').shader = colorShader; + PlayState.instance.currentStage.getGirlfriend().shader = colorShader; + PlayState.instance.currentStage.getDad().shader = colorShader; + getNamedProp('limoDancer1').shader = colorShader; getNamedProp('limoDancer2').shader = colorShader; - getNamedProp('limoDancer3').shader = colorShader; + getNamedProp('limoDancer3').shader = colorShader; getNamedProp('limoDancer4').shader = colorShader; getNamedProp('limoDancer5').shader = colorShader; getNamedProp('fastCar').shader = colorShader; - // PlayState.instance.currentStage.getBoyfriend().visible = false; - // PlayState.instance.currentStage.getGirlfriend().visible = false; - // PlayState.instance.currentStage.getDad().visible = false; - // getNamedProp('limo').visible = false; - // getNamedProp('limoDancer1').visible = false; + // PlayState.instance.currentStage.getBoyfriend().visible = false; + // PlayState.instance.currentStage.getGirlfriend().visible = false; + // PlayState.instance.currentStage.getDad().visible = false; + // getNamedProp('limo').visible = false; + // getNamedProp('limoDancer1').visible = false; // getNamedProp('limoDancer2').visible = false; - // getNamedProp('limoDancer3').visible = false; + // getNamedProp('limoDancer3').visible = false; // getNamedProp('limoDancer4').visible = false; // getNamedProp('limoDancer5').visible = false; // getNamedProp('fastCar').visible = false; - // getNamedProp('bgLimo').visible = false; - // getNamedProp('limoSunset').visible = false; - // getNamedProp('shootingStar').visible = false; - - colorShader.hue = -30; - colorShader.saturation = -20; - colorShader.contrast = 0; - colorShader.brightness = -30; + // getNamedProp('bgLimo').visible = false; + // getNamedProp('limoSunset').visible = false; + // getNamedProp('shootingStar').visible = false; + + colorShader.hue = -30; + colorShader.saturation = -20; + colorShader.contrast = 0; + colorShader.brightness = -30; + } + } + + function doShootingStar(beat:Int):Void + { + getNamedProp('shootingStar').x = FlxG.random.int(50, 900); + getNamedProp('shootingStar').y = FlxG.random.int(-10, 20); + getNamedProp('shootingStar').flipX = FlxG.random.bool(50); + getNamedProp('shootingStar').animation.play('shooting star'); + + shootingStarBeat = beat; + shootingStarOffset = FlxG.random.int(4, 8); + } + + function onBeatHit(event:SongTimeScriptEvent) + { + // When overriding onBeatHit, make sure to call super.onBeatHit, + // otherwise boppers will not work. + super.onBeatHit(event); + + if (FlxG.random.bool(10) && fastCarCanDrive) fastCarDrive(); + + if (FlxG.random.bool(10) && event.beat > (shootingStarBeat + shootingStarOffset)) + { + doShootingStar(event.beat); } } - function doShootingStar(beat:Int):Void - { - getNamedProp('shootingStar').x = FlxG.random.int(50,900); - getNamedProp('shootingStar').y = FlxG.random.int(-10,20); - getNamedProp('shootingStar').flipX = FlxG.random.bool(50); - getNamedProp('shootingStar').animation.play('shooting star'); - - shootingStarBeat = beat; - shootingStarOffset = FlxG.random.int(4, 8); - - } - - function onBeatHit(event:SongTimeScriptEvent) - { - // When overriding onBeatHit, make sure to call super.onBeatHit, - // otherwise boppers will not work. - super.onBeatHit(event); - - if (FlxG.random.bool(10) && fastCarCanDrive) - fastCarDrive(); - - if (FlxG.random.bool(10) && event.beat > (shootingStarBeat + shootingStarOffset)) - { - doShootingStar(event.beat); - } - } - - var fastCarCanDrive:Bool = false; - - function resetFastCar():Void - { - var fastCar = getNamedProp('fastCar'); - - if (fastCar == null) - return; - - // Props are inactive by default. - // Set active to true so position is calculated based on velocity. - fastCar.active = true; - - fastCar.x = -12600; - fastCar.y = FlxG.random.int(140, 250); - fastCar.velocity.x = 0; - fastCarCanDrive = true; - } - - function fastCarDrive():Void - { - FunkinSound.playOnce(Paths.soundRandom('carPass', 0, 1), 0.7); - - var fastCar = getNamedProp('fastCar'); - fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3; - fastCarCanDrive = false; - new FlxTimer().start(2, function(tmr:FlxTimer) - { - resetFastCar(); - }); - } - - /** - * If your stage uses additional assets not specified in the JSON, - * make sure to specify them like this, or they won't get cached in the loading screen. - */ - function fetchAssetPaths():Array - { - var results:Array = super.fetchAssetPaths(); - - // This graphic is applied by shader to the background, so it's not included in the default stage function. - results.push(Paths.image('limo/limoOverlay')); - results.push(Paths.sound('carPass0')); - results.push(Paths.sound('carPass1')); - - return results; - } - - /** - * Make sure the fast car is reset when the song restarts. - */ - function onSongRetry(event:ScriptEvent) { - super.onSongRetry(event); - resetFastCar(); - shootingStarBeat = 0; - shootingStarOffset = 2; - } - - /** - * Make sure the fast car is reset when the song restarts. - */ - function onCountdownStart(event:ScriptEvent) { - super.onCountdownStart(event); - resetFastCar(); - } + var fastCarCanDrive:Bool = false; + + function resetFastCar():Void + { + var fastCar = getNamedProp('fastCar'); + + if (fastCar == null) return; + + // Props are inactive by default. + // Set active to true so position is calculated based on velocity. + fastCar.active = true; + + fastCar.x = -12600; + fastCar.y = FlxG.random.int(140, 250); + fastCar.velocity.x = 0; + fastCarCanDrive = true; + } + + function fastCarDrive():Void + { + FunkinSound.playOnce(Paths.soundRandom('carPass', 0, 1), 0.7); + + var fastCar = getNamedProp('fastCar'); + fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3; + fastCarCanDrive = false; + new FlxTimer().start(2, function(tmr:FlxTimer) { + resetFastCar(); + }); + } + + /** + * If your stage uses additional assets not specified in the JSON, + * make sure to specify them like this, or they won't get cached in the loading screen. + */ + function fetchAssetPaths():Array + { + var results:Array = super.fetchAssetPaths(); + + // This graphic is applied by shader to the background, so it's not included in the default stage function. + results.push(Paths.image('limo/limoOverlay')); + results.push(Paths.sound('carPass0')); + results.push(Paths.sound('carPass1')); + + return results; + } + + /** + * Make sure the fast car is reset when the song restarts. + */ + function onSongRetry(event:ScriptEvent) + { + super.onSongRetry(event); + resetFastCar(); + shootingStarBeat = 0; + shootingStarOffset = 2; + } + + /** + * Make sure the fast car is reset when the song restarts. + */ + function onCountdownStart(event:ScriptEvent) + { + super.onCountdownStart(event); + resetFastCar(); + } } diff --git a/preload/scripts/stages/mainStageErect.hxc b/preload/scripts/stages/mainStageErect.hxc index 0afd9b562..c6a5657a2 100644 --- a/preload/scripts/stages/mainStageErect.hxc +++ b/preload/scripts/stages/mainStageErect.hxc @@ -12,22 +12,23 @@ import funkin.modding.base.ScriptedFlxAtlasSprite; class MainStageErectStage extends Stage { - function new() - { - super('mainStageErect'); - } + function new() + { + super('mainStageErect'); + } var colorShaderBf:AdjustColorShader; var colorShaderDad:AdjustColorShader; var colorShaderGf:AdjustColorShader; - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); - } + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); + } - function buildStage() - { - super.buildStage(); + function buildStage() + { + super.buildStage(); colorShaderBf = new AdjustColorShader(); colorShaderDad = new AdjustColorShader(); @@ -36,45 +37,44 @@ class MainStageErectStage extends Stage colorShaderBf.brightness = -23; colorShaderBf.hue = 12; colorShaderBf.contrast = 7; - colorShaderBf.saturation = 0; + colorShaderBf.saturation = 0; colorShaderGf.brightness = -30; colorShaderGf.hue = -9; colorShaderGf.contrast = -4; - colorShaderGf.saturation = 0; + colorShaderGf.saturation = 0; colorShaderDad.brightness = -33; colorShaderDad.hue = -32; colorShaderDad.contrast = -23; - colorShaderDad.saturation = 0; + colorShaderDad.saturation = 0; getNamedProp('brightLightSmall').blend = 0; getNamedProp('orangeLight').blend = 0; getNamedProp('lightgreen').blend = 0; getNamedProp('lightred').blend = 0; getNamedProp('lightAbove').blend = 0; + } - } + function onUpdate(event:UpdateScriptEvent):Void + { + super.onUpdate(event); - function onUpdate(event:UpdateScriptEvent):Void - { - super.onUpdate(event); - - if(PlayState.instance.currentStage.getBoyfriend() != null && PlayState.instance.currentStage.getBoyfriend().shader == null){ + if (PlayState.instance.currentStage.getBoyfriend() != null && PlayState.instance.currentStage.getBoyfriend().shader == null) + { PlayState.instance.currentStage.getBoyfriend().shader = colorShaderBf; - PlayState.instance.currentStage.getGirlfriend().shader = colorShaderGf; - PlayState.instance.currentStage.getDad().shader = colorShaderDad; + PlayState.instance.currentStage.getGirlfriend().shader = colorShaderGf; + PlayState.instance.currentStage.getDad().shader = colorShaderDad; } + } - } - - function onBeatHit(event:SongTimeScriptEvent):Void - { - super.onBeatHit(event); - } + function onBeatHit(event:SongTimeScriptEvent):Void + { + super.onBeatHit(event); + } function onStepHit(event:SongTimeScriptEvent):Void - { - super.onStepHit(event); - } + { + super.onStepHit(event); + } } diff --git a/preload/scripts/stages/mallXmasErect.hxc b/preload/scripts/stages/mallXmasErect.hxc index 349bca43b..155aa524d 100644 --- a/preload/scripts/stages/mallXmasErect.hxc +++ b/preload/scripts/stages/mallXmasErect.hxc @@ -13,28 +13,30 @@ import flixel.FlxG; class MallXmasErectStage extends Stage { - function new() - { - super('mallXmasErect'); - } + function new() + { + super('mallXmasErect'); + } - var colorShader:AdjustColorShader; + var colorShader:AdjustColorShader; - function onCreate(event:ScriptEvent):Void { - super.onCreate(event); + function onCreate(event:ScriptEvent):Void + { + super.onCreate(event); - // Create a single color shader and reuse it. + // Create a single color shader and reuse it. colorShader = new AdjustColorShader(); - colorShader.hue = 5; - colorShader.saturation = 20; + colorShader.hue = 5; + colorShader.saturation = 20; - getNamedProp('santa').shader = colorShader; - } + getNamedProp('santa').shader = colorShader; + } - override function addCharacter(character:BaseCharacter, charType:CharacterType):Void { - // Apply the shader automatically to each character as it gets added. - super.addCharacter(character, charType); - trace('Applied stage shader to ' + character.characterName); - character.shader = colorShader; - } + override function addCharacter(character:BaseCharacter, charType:CharacterType):Void + { + // Apply the shader automatically to each character as it gets added. + super.addCharacter(character, charType); + trace('Applied stage shader to ' + character.characterName); + character.shader = colorShader; + } } diff --git a/preload/scripts/stages/phillyBlazin.hxc b/preload/scripts/stages/phillyBlazin.hxc index fd9c518c9..8cb80791d 100644 --- a/preload/scripts/stages/phillyBlazin.hxc +++ b/preload/scripts/stages/phillyBlazin.hxc @@ -18,192 +18,207 @@ import funkin.util.MathUtil; */ class PhillyBlazinStage extends Stage { - function new() - { - super('phillyBlazin'); - } - - var rainShader:RuntimeRainShader = new RuntimeRainShader(); - var scrollingSky:FlxTiledSprite; - // var rainShaderFilter:ShaderFilter; - - override function onCreate(event:ScriptEvent) { - super.onCreate(event); - cameraInitialized = false; - cameraDarkened = false; - lightningActive = true; - - rainShader.scale = FlxG.height / 200; // adjust this value so that the rain looks nice - rainShader.intensity = 0.5; - - rainShaderFilter = new ShaderFilter(rainShader); - FlxG.camera.filters = [rainShaderFilter]; - } - - override function onGameOver(event:ScriptEvent):Void { - super.onGameOver(event); - // Make it so the rain shader doesn't show over the game over screen - FlxG.camera.filters = []; - } - - override function onSongRetry(event:ScriptEvent):Void { - super.onSongRetry(event); - // Make it so the rain shader doesn't show over the game over screen - FlxG.camera.filters = [rainShaderFilter]; - lightningActive = true; - } - - override function buildStage() - { - super.buildStage(); - - var skyAdditive = PlayState.instance.currentStage.getNamedProp('skyAdditive'); - skyAdditive.blend = 0; // ADD - skyAdditive.visible = false; - - var lightning = PlayState.instance.currentStage.getNamedProp('lightning'); - lightning.visible = false; - - var foregroundMultiply = PlayState.instance.currentStage.getNamedProp('foregroundMultiply'); - foregroundMultiply.blend = 9; // MULTIPLY - foregroundMultiply.visible = false; - - var additionalLighten = PlayState.instance.currentStage.getNamedProp('additionalLighten'); - additionalLighten.blend = 0; // ADD - additionalLighten.visible = false; - - scrollingSky = new FlxTiledSprite(Paths.image('phillyBlazin/skyBlur'), 2000, 359, true, false); - scrollingSky.setPosition(-500, -120); - scrollingSky.scrollFactor.set(0, 0); - scrollingSky.zIndex = 10; - - PlayState.instance.currentStage.add(scrollingSky); - PlayState.instance.currentStage.refresh(); // Apply z-index. - - //scrollingSky.velocity.x = -20; - } - - var cameraInitialized:Bool = false; - var cameraDarkened:Bool = false; - - var lightningTimer:Float = 3.0; - var lightningActive:Bool = true; - - var rainTimeScale:Float = 1.0; - - override function onUpdate(event:ScriptEvent) - { - super.onUpdate(event); - - rainShader.updateViewInfo(FlxG.width, FlxG.height, FlxG.camera); - rainShader.update(event.elapsed * rainTimeScale); - rainTimeScale = MathUtil.coolLerp(rainTimeScale, 0.02, 0.05); - - if(scrollingSky != null) scrollingSky.scrollX -= FlxG.elapsed * 35; - - // Manually focus the camera before the song starts. - if (!cameraInitialized && PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint != null) - { - cameraInitialized = true; - initializeCamera(); - - PlayState.instance.currentStage.getBoyfriend().color = 0xFFDEDEDE; - PlayState.instance.currentStage.getDad().color = 0xFFDEDEDE; - PlayState.instance.currentStage.getGirlfriend().color = 0xFF888888; - PlayState.instance.currentStage.getGirlfriend().scriptGet('abot').color = 0xFF888888; - } - - if (lightningActive) { - lightningTimer -= FlxG.elapsed; - } else { - lightningTimer = 1; - } - - if (lightningTimer <= 0) { - applyLightning(); - lightningTimer = FlxG.random.float(7, 15); - } - } - - public function onNoteHit(event:HitNoteScriptEvent) { - super.onNoteHit(event); - rainTimeScale += 0.7; - } - - - function applyLightning():Void { - var lightning = PlayState.instance.currentStage.getNamedProp('lightning'); - var skyAdditive = PlayState.instance.currentStage.getNamedProp('skyAdditive'); - var foregroundMultiply = PlayState.instance.currentStage.getNamedProp('foregroundMultiply'); - var additionalLighten = PlayState.instance.currentStage.getNamedProp('additionalLighten'); - - var LIGHTNING_FULL_DURATION = 1.5; - var LIGHTNING_FADE_DURATION = 0.3; - - skyAdditive.visible = true; - skyAdditive.alpha = 0.7; - FlxTween.tween(skyAdditive, {alpha: 0.0}, LIGHTNING_FULL_DURATION, { - onComplete: cleanupLightning, // Make sure to call this only once! - }); - - foregroundMultiply.visible = true; - foregroundMultiply.alpha = 0.64; - FlxTween.tween(foregroundMultiply, {alpha: 0.0}, LIGHTNING_FULL_DURATION); - - additionalLighten.visible = true; - additionalLighten.alpha = 0.3; - FlxTween.tween(additionalLighten, {alpha: 0.0}, LIGHTNING_FADE_DURATION); - - lightning.visible = true; - lightning.animation.play('strike'); - - if(FlxG.random.bool(65)){ - lightning.x = FlxG.random.int(-250, 280); - }else{ - lightning.x = FlxG.random.int(780, 900); - } - - - // Darken characters - var boyfriend = PlayState.instance.currentStage.getBoyfriend(); - FlxTween.color(boyfriend, LIGHTNING_FADE_DURATION, 0xFF606060, 0xFFDEDEDE); - var dad = PlayState.instance.currentStage.getDad(); - FlxTween.color(dad, LIGHTNING_FADE_DURATION, 0xFF606060, 0xFFDEDEDE); - var girlfriend = PlayState.instance.currentStage.getGirlfriend(); - FlxTween.color(girlfriend, LIGHTNING_FADE_DURATION, 0xFF606060, 0xFF888888); - - // Sound - FunkinSound.playOnce(Paths.soundRandom('Lightning', 1, 3), 1.0); - } - - public override function onSongEnd(event:CountdownScriptEvent):Void { - super.onSongEnd(event); - // Disable lightning during ending cutscene. - lightningActive = false; - } - - function cleanupLightning(tween:FlxTween):Void { - var skyAdditive = PlayState.instance.currentStage.getNamedProp('skyAdditive'); - var foregroundMultiply = PlayState.instance.currentStage.getNamedProp('foregroundMultiply'); - var additionalLighten = PlayState.instance.currentStage.getNamedProp('additionalLighten'); - var lightning = PlayState.instance.currentStage.getNamedProp('lightning'); - skyAdditive.visible = false; - foregroundMultiply.visible = false; - additionalLighten.visible = false; - lightning.visible = false; - } - - function initializeCamera():Void { - var xTarget:Float = PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint.x; + function new() + { + super('phillyBlazin'); + } + + var rainShader:RuntimeRainShader = new RuntimeRainShader(); + var scrollingSky:FlxTiledSprite; + + // var rainShaderFilter:ShaderFilter; + + override function onCreate(event:ScriptEvent) + { + super.onCreate(event); + cameraInitialized = false; + cameraDarkened = false; + lightningActive = true; + + rainShader.scale = FlxG.height / 200; // adjust this value so that the rain looks nice + rainShader.intensity = 0.5; + + rainShaderFilter = new ShaderFilter(rainShader); + FlxG.camera.filters = [rainShaderFilter]; + } + + override function onGameOver(event:ScriptEvent):Void + { + super.onGameOver(event); + // Make it so the rain shader doesn't show over the game over screen + FlxG.camera.filters = []; + } + + override function onSongRetry(event:ScriptEvent):Void + { + super.onSongRetry(event); + // Make it so the rain shader doesn't show over the game over screen + FlxG.camera.filters = [rainShaderFilter]; + lightningActive = true; + } + + override function buildStage() + { + super.buildStage(); + + var skyAdditive = PlayState.instance.currentStage.getNamedProp('skyAdditive'); + skyAdditive.blend = 0; // ADD + skyAdditive.visible = false; + + var lightning = PlayState.instance.currentStage.getNamedProp('lightning'); + lightning.visible = false; + + var foregroundMultiply = PlayState.instance.currentStage.getNamedProp('foregroundMultiply'); + foregroundMultiply.blend = 9; // MULTIPLY + foregroundMultiply.visible = false; + + var additionalLighten = PlayState.instance.currentStage.getNamedProp('additionalLighten'); + additionalLighten.blend = 0; // ADD + additionalLighten.visible = false; + + scrollingSky = new FlxTiledSprite(Paths.image('phillyBlazin/skyBlur'), 2000, 359, true, false); + scrollingSky.setPosition(-500, -120); + scrollingSky.scrollFactor.set(0, 0); + scrollingSky.zIndex = 10; + + PlayState.instance.currentStage.add(scrollingSky); + PlayState.instance.currentStage.refresh(); // Apply z-index. + + // scrollingSky.velocity.x = -20; + } + + var cameraInitialized:Bool = false; + var cameraDarkened:Bool = false; + + var lightningTimer:Float = 3.0; + var lightningActive:Bool = true; + + var rainTimeScale:Float = 1.0; + + override function onUpdate(event:ScriptEvent) + { + super.onUpdate(event); + + rainShader.updateViewInfo(FlxG.width, FlxG.height, FlxG.camera); + rainShader.update(event.elapsed * rainTimeScale); + rainTimeScale = MathUtil.coolLerp(rainTimeScale, 0.02, 0.05); + + if (scrollingSky != null) scrollingSky.scrollX -= FlxG.elapsed * 35; + + // Manually focus the camera before the song starts. + if (!cameraInitialized && PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint != null) + { + cameraInitialized = true; + initializeCamera(); + + PlayState.instance.currentStage.getBoyfriend().color = 0xFFDEDEDE; + PlayState.instance.currentStage.getDad().color = 0xFFDEDEDE; + PlayState.instance.currentStage.getGirlfriend().color = 0xFF888888; + PlayState.instance.currentStage.getGirlfriend().scriptGet('abot').color = 0xFF888888; + } + + if (lightningActive) + { + lightningTimer -= FlxG.elapsed; + } + else + { + lightningTimer = 1; + } + + if (lightningTimer <= 0) + { + applyLightning(); + lightningTimer = FlxG.random.float(7, 15); + } + } + + public function onNoteHit(event:HitNoteScriptEvent) + { + super.onNoteHit(event); + rainTimeScale += 0.7; + } + + function applyLightning():Void + { + var lightning = PlayState.instance.currentStage.getNamedProp('lightning'); + var skyAdditive = PlayState.instance.currentStage.getNamedProp('skyAdditive'); + var foregroundMultiply = PlayState.instance.currentStage.getNamedProp('foregroundMultiply'); + var additionalLighten = PlayState.instance.currentStage.getNamedProp('additionalLighten'); + + var LIGHTNING_FULL_DURATION = 1.5; + var LIGHTNING_FADE_DURATION = 0.3; + + skyAdditive.visible = true; + skyAdditive.alpha = 0.7; + FlxTween.tween(skyAdditive, {alpha: 0.0}, LIGHTNING_FULL_DURATION, + { + onComplete: cleanupLightning, // Make sure to call this only once! + }); + + foregroundMultiply.visible = true; + foregroundMultiply.alpha = 0.64; + FlxTween.tween(foregroundMultiply, {alpha: 0.0}, LIGHTNING_FULL_DURATION); + + additionalLighten.visible = true; + additionalLighten.alpha = 0.3; + FlxTween.tween(additionalLighten, {alpha: 0.0}, LIGHTNING_FADE_DURATION); + + lightning.visible = true; + lightning.animation.play('strike'); + + if (FlxG.random.bool(65)) + { + lightning.x = FlxG.random.int(-250, 280); + } + else + { + lightning.x = FlxG.random.int(780, 900); + } + + // Darken characters + var boyfriend = PlayState.instance.currentStage.getBoyfriend(); + FlxTween.color(boyfriend, LIGHTNING_FADE_DURATION, 0xFF606060, 0xFFDEDEDE); + var dad = PlayState.instance.currentStage.getDad(); + FlxTween.color(dad, LIGHTNING_FADE_DURATION, 0xFF606060, 0xFFDEDEDE); + var girlfriend = PlayState.instance.currentStage.getGirlfriend(); + FlxTween.color(girlfriend, LIGHTNING_FADE_DURATION, 0xFF606060, 0xFF888888); + + // Sound + FunkinSound.playOnce(Paths.soundRandom('Lightning', 1, 3), 1.0); + } + + public override function onSongEnd(event:CountdownScriptEvent):Void + { + super.onSongEnd(event); + // Disable lightning during ending cutscene. + lightningActive = false; + } + + function cleanupLightning(tween:FlxTween):Void + { + var skyAdditive = PlayState.instance.currentStage.getNamedProp('skyAdditive'); + var foregroundMultiply = PlayState.instance.currentStage.getNamedProp('foregroundMultiply'); + var additionalLighten = PlayState.instance.currentStage.getNamedProp('additionalLighten'); + var lightning = PlayState.instance.currentStage.getNamedProp('lightning'); + skyAdditive.visible = false; + foregroundMultiply.visible = false; + additionalLighten.visible = false; + lightning.visible = false; + } + + function initializeCamera():Void + { + var xTarget:Float = PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint.x; var yTarget:Float = PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint.y; - // yTarget += 200; - xTarget += 50; - yTarget -= 90; + // yTarget += 200; + xTarget += 50; + yTarget -= 90; PlayState.instance.cameraFollowPoint.setPosition(xTarget, yTarget); - PlayState.instance.resetCamera(); + PlayState.instance.resetCamera(); - PlayState.instance.comboPopUps.offsets = [480, -50]; + PlayState.instance.comboPopUps.offsets = [480, -50]; - PlayState.instance.camGame.fade(0xFF000000, 1.5, true, null, true); - } + PlayState.instance.camGame.fade(0xFF000000, 1.5, true, null, true); + } } diff --git a/preload/scripts/stages/phillyStreets.hxc b/preload/scripts/stages/phillyStreets.hxc index 7f901ac72..95af5306c 100644 --- a/preload/scripts/stages/phillyStreets.hxc +++ b/preload/scripts/stages/phillyStreets.hxc @@ -23,496 +23,533 @@ import StringTools; class PhillyStreetsStage extends Stage { - var rainShader:RuntimeRainShader = new RuntimeRainShader(); - var rainShaderFilter:ShaderFilter; - var blurFilter:BlurFilter = new BlurFilter(6, 6); - - // as song goes on, these are used to make the rain more intense throught the song - // these values are also used for the rain sound effect volume intensity! - var rainShaderStartIntensity:Float; - var rainShaderEndIntensity:Float; - - // var rainSndAmbience:FunkinSound; - // var carSndAmbience:FunkinSound; - - var lightsStop:Bool = false; // state of the traffic lights - var lastChange:Int = 0; - var changeInterval:Int = 8; // make sure it doesnt change until AT LEAST this many beats - - var carWaiting:Bool = false; // if the car is waiting at the lights and is ready to go on green - var carInterruptable:Bool = true; // if the car can be reset - var car2Interruptable:Bool = true; - - var scrollingSky:FlxTiledSprite; - - function new() - { - super('phillyStreets'); - } - - /** - * Changes the current state of the traffic lights. - * Updates the next change accordingly and will force cars to move when ready - */ - function changeLights(beat:Int):Void{ - - lastChange = beat; - lightsStop = !lightsStop; - - if(lightsStop){ - getNamedProp('phillyTraffic').animation.play('tored'); - changeInterval = 20; - } else { - getNamedProp('phillyTraffic').animation.play('togreen'); - changeInterval = 30; - - if(carWaiting == true) finishCarLights(getNamedProp('phillyCars')); - } - } - - /** - * Resets every value of a car and hides it from view. - */ - function resetCar(left:Bool, right:Bool){ - if(left){ - carWaiting = false; - carInterruptable = true; - var cars = getNamedProp('phillyCars'); - if (cars != null) { - FlxTween.cancelTweensOf(cars); - cars.x = 1200; - cars.y = 818; - cars.angle = 0; - } - } - - if(right){ - car2Interruptable = true; - var cars2 = getNamedProp('phillyCars2'); - if (cars2 != null) { - FlxTween.cancelTweensOf(cars2); - getNamedProp('phillyCars2').x = 1200; - getNamedProp('phillyCars2').y = 818; - getNamedProp('phillyCars2').angle = 0; - } - } - } - - override function onCountdownStart(event:ScriptEvent) { - super.onCountdownStart(event); - - resetCar(true, true); - resetStageValues(); - } - - override function onCountdownEnd(event:ScriptEvent) { - super.onCountdownEnd(event); - // carSndAmbience.volume = 0.1; - } - - override function onCreate(event:ScriptEvent):Void - { - super.onCreate(event); - - // rainSndAmbience = FunkinSound.load(Paths.sound("rainAmbience", "weekend1"), true, false, true); - // rainSndAmbience.volume = 0; - // rainSndAmbience.play(false, FlxG.random.float(0, rainSndAmbience.length)); - - // carSndAmbience = FunkinSound.load(Paths.sound("carAmbience", "weekend1"), true, false, true); - // carSndAmbience.volume = 0; - // carSndAmbience.play(false, FlxG.random.float(0, carSndAmbience.length)); - - // rainShader.puddleMap = Assets.getBitmapData(Paths.image("phillyStreets/puddle")); - rainShader.scale = FlxG.height / 200; // adjust this value so that the rain looks nice - - FlxG.console.registerObject("rainShader", rainShader); - switch (PlayState.instance.currentSong.id) - { - case "darnell": - rainShaderStartIntensity = 0; - rainShaderEndIntensity = 0.1; - case "lit-up": - rainShaderStartIntensity = 0.1; - rainShaderEndIntensity = 0.2; - case "2hot": - rainShaderStartIntensity = 0.2; - rainShaderEndIntensity = 0.4; - } - - rainShader.intensity = rainShaderStartIntensity; - - // set the shader input - //rainShader.mask = frameBufferMan.getFrameBuffer("mask"); - //rainShader.lightMap = frameBufferMan.getFrameBuffer("lightmap"); - - rainShaderFilter = new ShaderFilter(rainShader); - FlxG.camera.filters = [rainShaderFilter]; - //FlxG.camera.setFilters([new openfl.filters.BlurFilter(16,16)]); - - resetCar(true, true); - resetStageValues(); - } - - override function buildStage() - { - super.buildStage(); - - scrollingSky = new FlxTiledSprite(Paths.image('phillyStreets/phillySkybox'), 2922, 718, true, false); - scrollingSky.setPosition(-650, -375); - scrollingSky.scrollFactor.set(0.1, 0.1); - scrollingSky.zIndex = 10; - scrollingSky.scale.set(0.65, 0.65); - - PlayState.instance.currentStage.add(scrollingSky); - PlayState.instance.currentStage.refresh(); // Apply z-index. - } - - override function onDestroy(event:ScriptEvent) { - super.onDestroy(); - - var cars = getNamedProp('phillyCars'); - if (cars != null) FlxTween.cancelTweensOf(cars); - var cars2 = getNamedProp('phillyCars2'); - if (cars2 != null) FlxTween.cancelTweensOf(cars2); - - // Fully stop ambiance. - // if (rainSndAmbience != null) rainSndAmbience.stop(); - // if (carSndAmbience != null) carSndAmbience.stop(); - } - - /** - * Drive the car away from the lights to the end of the road. - * Used when the lights turn green and the car is waiting in position. - */ - function finishCarLights(sprite:FlxSprite):Void{ - carWaiting = false; - var duration:Float = FlxG.random.float(1.8, 3); - var rotations:Array = [-5, 18]; - var offset:Array = [306.6, 168.3]; - var startdelay:Float = FlxG.random.float(0.2, 1.2); - - var path:Array = [ - FlxPoint.get(1950 - offset[0] - 80, 980 - offset[1] + 15), - FlxPoint.get(2400 - offset[0], 980 - offset[1] - 50), - FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 40) - ]; - - FlxTween.angle(sprite, rotations[0], rotations[1], duration, {ease: FlxEase.sineIn, startDelay: startdelay} ); - FlxTween.quadPath(sprite, path, duration, true, + var rainShader:RuntimeRainShader = new RuntimeRainShader(); + var rainShaderFilter:ShaderFilter; + var blurFilter:BlurFilter = new BlurFilter(6, 6); + + // as song goes on, these are used to make the rain more intense throught the song + // these values are also used for the rain sound effect volume intensity! + var rainShaderStartIntensity:Float; + var rainShaderEndIntensity:Float; + + // var rainSndAmbience:FunkinSound; + // var carSndAmbience:FunkinSound; + var lightsStop:Bool = false; // state of the traffic lights + var lastChange:Int = 0; + var changeInterval:Int = 8; // make sure it doesnt change until AT LEAST this many beats + + var carWaiting:Bool = false; // if the car is waiting at the lights and is ready to go on green + var carInterruptable:Bool = true; // if the car can be reset + var car2Interruptable:Bool = true; + + var scrollingSky:FlxTiledSprite; + + function new() + { + super('phillyStreets'); + } + + /** + * Changes the current state of the traffic lights. + * Updates the next change accordingly and will force cars to move when ready + */ + function changeLights(beat:Int):Void + { + lastChange = beat; + lightsStop = !lightsStop; + + if (lightsStop) { - ease: FlxEase.sineIn, - startDelay: startdelay, - onComplete: function(_) { - carInterruptable = true; + getNamedProp('phillyTraffic').animation.play('tored'); + changeInterval = 20; + } + else + { + getNamedProp('phillyTraffic').animation.play('togreen'); + changeInterval = 30; + + if (carWaiting == true) finishCarLights(getNamedProp('phillyCars')); + } + } + + /** + * Resets every value of a car and hides it from view. + */ + function resetCar(left:Bool, right:Bool) + { + if (left) + { + carWaiting = false; + carInterruptable = true; + var cars = getNamedProp('phillyCars'); + if (cars != null) + { + FlxTween.cancelTweensOf(cars); + cars.x = 1200; + cars.y = 818; + cars.angle = 0; } - }); - } - - /** - * Drives a car towards the lights and stops. - * Used when a car tries to drive while the lights are red. - */ - function driveCarLights(sprite:FlxSprite):Void{ - carInterruptable = false; - FlxTween.cancelTweensOf(sprite); - var variant:Int = FlxG.random.int(1,4); - sprite.animation.play('car' + variant); - var extraOffset = [0, 0]; - var duration:Float = 2; - - switch(variant){ - case 1: - duration = FlxG.random.float(1, 1.7); - case 2: - extraOffset = [20, -15]; - duration = FlxG.random.float(0.9, 1.5); - case 3: - extraOffset = [30, 50]; - duration = FlxG.random.float(1.5, 2.5); - case 4: - extraOffset = [10, 60]; - duration = FlxG.random.float(1.5, 2.5); - } - var rotations:Array = [-7, -5]; - var offset:Array = [306.6, 168.3]; - sprite.offset.set(extraOffset[0], extraOffset[1]); - - var path:Array = [ - FlxPoint.get(1500 - offset[0] - 20, 1049 - offset[1] - 20), - FlxPoint.get(1770 - offset[0] - 80, 994 - offset[1] + 10), - FlxPoint.get(1950 - offset[0] - 80, 980 - offset[1] + 15) - ]; - // debug shit!!! keeping it here just in case - // for(point in path){ - // var debug:FlxSprite = new FlxSprite(point.x - 5, point.y - 5).makeGraphic(10, 10, 0xFFFF0000); - // add(debug); - // } - FlxTween.angle(sprite, rotations[0], rotations[1], duration, {ease: FlxEase.cubeOut} ); - FlxTween.quadPath(sprite, path, duration, true, + } + + if (right) { - ease: FlxEase.cubeOut, - onComplete: function(_) { - carWaiting = true; - if(lightsStop == false) finishCarLights(getNamedProp('phillyCars')); + car2Interruptable = true; + var cars2 = getNamedProp('phillyCars2'); + if (cars2 != null) + { + FlxTween.cancelTweensOf(cars2); + getNamedProp('phillyCars2').x = 1200; + getNamedProp('phillyCars2').y = 818; + getNamedProp('phillyCars2').angle = 0; } - }); - } - - /** - * Drives a car across the screen without stopping. - * Used when the lights are green. - */ - function driveCar(sprite:FlxSprite):Void{ - carInterruptable = false; - FlxTween.cancelTweensOf(sprite); - var variant:Int = FlxG.random.int(1,4); - sprite.animation.play('car' + variant); - // setting an offset here because the current implementation of stage prop offsets was not working at all for me - // if possible id love to not have to do this but im keeping this for now - var extraOffset = [0, 0]; - var duration:Float = 2; - // set different values of speed for the car types (and the offset) - switch(variant){ - case 1: - duration = FlxG.random.float(1, 1.7); - case 2: - extraOffset = [20, -15]; - duration = FlxG.random.float(0.6, 1.2); - case 3: - extraOffset = [30, 50]; - duration = FlxG.random.float(1.5, 2.5); - case 4: - extraOffset = [10, 60]; - duration = FlxG.random.float(1.5, 2.5); - } - // random arbitrary values for getting the cars in place - // could just add them to the points but im LAZY!!!!!! - var offset:Array = [306.6, 168.3]; - sprite.offset.set(extraOffset[0], extraOffset[1]); - // start/end rotation - var rotations:Array = [-8, 18]; - // the path to move the car on - var path:Array = [ - FlxPoint.get(1570 - offset[0], 1049 - offset[1] - 30), - FlxPoint.get(2400 - offset[0], 980 - offset[1] - 50), - FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 40) - ]; - - FlxTween.angle(sprite, rotations[0], rotations[1], duration, null ); - FlxTween.quadPath(sprite, path, duration, true, + } + } + + override function onCountdownStart(event:ScriptEvent) + { + super.onCountdownStart(event); + + resetCar(true, true); + resetStageValues(); + } + + override function onCountdownEnd(event:ScriptEvent) + { + super.onCountdownEnd(event); + // carSndAmbience.volume = 0.1; + } + + override function onCreate(event:ScriptEvent):Void + { + super.onCreate(event); + + // rainSndAmbience = FunkinSound.load(Paths.sound("rainAmbience", "weekend1"), true, false, true); + // rainSndAmbience.volume = 0; + // rainSndAmbience.play(false, FlxG.random.float(0, rainSndAmbience.length)); + + // carSndAmbience = FunkinSound.load(Paths.sound("carAmbience", "weekend1"), true, false, true); + // carSndAmbience.volume = 0; + // carSndAmbience.play(false, FlxG.random.float(0, carSndAmbience.length)); + + // rainShader.puddleMap = Assets.getBitmapData(Paths.image("phillyStreets/puddle")); + rainShader.scale = FlxG.height / 200; // adjust this value so that the rain looks nice + + FlxG.console.registerObject("rainShader", rainShader); + switch (PlayState.instance.currentSong.id) + { + case "darnell": + rainShaderStartIntensity = 0; + rainShaderEndIntensity = 0.1; + case "lit-up": + rainShaderStartIntensity = 0.1; + rainShaderEndIntensity = 0.2; + case "2hot": + rainShaderStartIntensity = 0.2; + rainShaderEndIntensity = 0.4; + } + + rainShader.intensity = rainShaderStartIntensity; + + // set the shader input + // rainShader.mask = frameBufferMan.getFrameBuffer("mask"); + // rainShader.lightMap = frameBufferMan.getFrameBuffer("lightmap"); + + rainShaderFilter = new ShaderFilter(rainShader); + FlxG.camera.filters = [rainShaderFilter]; + // FlxG.camera.setFilters([new openfl.filters.BlurFilter(16,16)]); + + resetCar(true, true); + resetStageValues(); + } + + override function buildStage() + { + super.buildStage(); + + scrollingSky = new FlxTiledSprite(Paths.image('phillyStreets/phillySkybox'), 2922, 718, true, false); + scrollingSky.setPosition(-650, -375); + scrollingSky.scrollFactor.set(0.1, 0.1); + scrollingSky.zIndex = 10; + scrollingSky.scale.set(0.65, 0.65); + + PlayState.instance.currentStage.add(scrollingSky); + PlayState.instance.currentStage.refresh(); // Apply z-index. + } + + override function onDestroy(event:ScriptEvent) + { + super.onDestroy(); + + var cars = getNamedProp('phillyCars'); + if (cars != null) FlxTween.cancelTweensOf(cars); + var cars2 = getNamedProp('phillyCars2'); + if (cars2 != null) FlxTween.cancelTweensOf(cars2); + + // Fully stop ambiance. + // if (rainSndAmbience != null) rainSndAmbience.stop(); + // if (carSndAmbience != null) carSndAmbience.stop(); + } + + /** + * Drive the car away from the lights to the end of the road. + * Used when the lights turn green and the car is waiting in position. + */ + function finishCarLights(sprite:FlxSprite):Void + { + carWaiting = false; + var duration:Float = FlxG.random.float(1.8, 3); + var rotations:Array = [-5, 18]; + var offset:Array = [306.6, 168.3]; + var startdelay:Float = FlxG.random.float(0.2, 1.2); + + var path:Array = [ + FlxPoint.get(1950 - offset[0] - 80, 980 - offset[1] + 15), + FlxPoint.get(2400 - offset[0], 980 - offset[1] - 50), + FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 40) + ]; + + FlxTween.angle(sprite, rotations[0], rotations[1], duration, {ease: FlxEase.sineIn, startDelay: startdelay}); + FlxTween.quadPath(sprite, path, duration, true, + { + ease: FlxEase.sineIn, + startDelay: startdelay, + onComplete: function(_) { + carInterruptable = true; + } + }); + } + + /** + * Drives a car towards the lights and stops. + * Used when a car tries to drive while the lights are red. + */ + function driveCarLights(sprite:FlxSprite):Void + { + carInterruptable = false; + FlxTween.cancelTweensOf(sprite); + var variant:Int = FlxG.random.int(1, 4); + sprite.animation.play('car' + variant); + var extraOffset = [0, 0]; + var duration:Float = 2; + + switch (variant) + { + case 1: + duration = FlxG.random.float(1, 1.7); + case 2: + extraOffset = [20, -15]; + duration = FlxG.random.float(0.9, 1.5); + case 3: + extraOffset = [30, 50]; + duration = FlxG.random.float(1.5, 2.5); + case 4: + extraOffset = [10, 60]; + duration = FlxG.random.float(1.5, 2.5); + } + var rotations:Array = [-7, -5]; + var offset:Array = [306.6, 168.3]; + sprite.offset.set(extraOffset[0], extraOffset[1]); + + var path:Array = [ + FlxPoint.get(1500 - offset[0] - 20, 1049 - offset[1] - 20), + FlxPoint.get(1770 - offset[0] - 80, 994 - offset[1] + 10), + FlxPoint.get(1950 - offset[0] - 80, 980 - offset[1] + 15) + ]; + // debug shit!!! keeping it here just in case + // for(point in path){ + // var debug:FlxSprite = new FlxSprite(point.x - 5, point.y - 5).makeGraphic(10, 10, 0xFFFF0000); + // add(debug); + // } + FlxTween.angle(sprite, rotations[0], rotations[1], duration, {ease: FlxEase.cubeOut}); + FlxTween.quadPath(sprite, path, duration, true, + { + ease: FlxEase.cubeOut, + onComplete: function(_) { + carWaiting = true; + if (lightsStop == false) finishCarLights(getNamedProp('phillyCars')); + } + }); + } + + /** + * Drives a car across the screen without stopping. + * Used when the lights are green. + */ + function driveCar(sprite:FlxSprite):Void + { + carInterruptable = false; + FlxTween.cancelTweensOf(sprite); + var variant:Int = FlxG.random.int(1, 4); + sprite.animation.play('car' + variant); + // setting an offset here because the current implementation of stage prop offsets was not working at all for me + // if possible id love to not have to do this but im keeping this for now + var extraOffset = [0, 0]; + var duration:Float = 2; + // set different values of speed for the car types (and the offset) + switch (variant) + { + case 1: + duration = FlxG.random.float(1, 1.7); + case 2: + extraOffset = [20, -15]; + duration = FlxG.random.float(0.6, 1.2); + case 3: + extraOffset = [30, 50]; + duration = FlxG.random.float(1.5, 2.5); + case 4: + extraOffset = [10, 60]; + duration = FlxG.random.float(1.5, 2.5); + } + // random arbitrary values for getting the cars in place + // could just add them to the points but im LAZY!!!!!! + var offset:Array = [306.6, 168.3]; + sprite.offset.set(extraOffset[0], extraOffset[1]); + // start/end rotation + var rotations:Array = [-8, 18]; + // the path to move the car on + var path:Array = [ + FlxPoint.get(1570 - offset[0], 1049 - offset[1] - 30), + FlxPoint.get(2400 - offset[0], 980 - offset[1] - 50), + FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 40) + ]; + + FlxTween.angle(sprite, rotations[0], rotations[1], duration, null); + FlxTween.quadPath(sprite, path, duration, true, { ease: null, - onComplete: function(_) { - carInterruptable = true; - } - }); - } - - function driveCarBack(sprite:FlxSprite):Void{ - car2Interruptable = false; - FlxTween.cancelTweensOf(sprite); - var variant:Int = FlxG.random.int(1,4); - sprite.animation.play('car' + variant); - // setting an offset here because the current implementation of stage prop offsets was not working at all for me - // if possible id love to not have to do this but im keeping this for now - var extraOffset = [0, 0]; - var duration:Float = 2; - // set different values of speed for the car types (and the offset) - switch(variant){ - case 1: - duration = FlxG.random.float(1, 1.7); - case 2: - extraOffset = [20, -15]; - duration = FlxG.random.float(0.6, 1.2); - case 3: - extraOffset = [30, 50]; - duration = FlxG.random.float(1.5, 2.5); - case 4: - extraOffset = [10, 60]; - duration = FlxG.random.float(1.5, 2.5); - } - // random arbitrary values for getting the cars in place - // could just add them to the points but im LAZY!!!!!! - var offset:Array = [306.6, 168.3]; - sprite.offset.set(extraOffset[0], extraOffset[1]); - // start/end rotation - var rotations:Array = [18, -8]; - // the path to move the car on - var path:Array = [ - FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 60), - FlxPoint.get(2400 - offset[0], 980 - offset[1] - 30), - FlxPoint.get(1570 - offset[0], 1049 - offset[1] - 10) - - ]; - - FlxTween.angle(sprite, rotations[0], rotations[1], duration, null ); - FlxTween.quadPath(sprite, path, duration, true, + onComplete: function(_) { + carInterruptable = true; + } + }); + } + + function driveCarBack(sprite:FlxSprite):Void + { + car2Interruptable = false; + FlxTween.cancelTweensOf(sprite); + var variant:Int = FlxG.random.int(1, 4); + sprite.animation.play('car' + variant); + // setting an offset here because the current implementation of stage prop offsets was not working at all for me + // if possible id love to not have to do this but im keeping this for now + var extraOffset = [0, 0]; + var duration:Float = 2; + // set different values of speed for the car types (and the offset) + switch (variant) + { + case 1: + duration = FlxG.random.float(1, 1.7); + case 2: + extraOffset = [20, -15]; + duration = FlxG.random.float(0.6, 1.2); + case 3: + extraOffset = [30, 50]; + duration = FlxG.random.float(1.5, 2.5); + case 4: + extraOffset = [10, 60]; + duration = FlxG.random.float(1.5, 2.5); + } + // random arbitrary values for getting the cars in place + // could just add them to the points but im LAZY!!!!!! + var offset:Array = [306.6, 168.3]; + sprite.offset.set(extraOffset[0], extraOffset[1]); + // start/end rotation + var rotations:Array = [18, -8]; + // the path to move the car on + var path:Array = [ + FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 60), + FlxPoint.get(2400 - offset[0], 980 - offset[1] - 30), + FlxPoint.get(1570 - offset[0], 1049 - offset[1] - 10) + + ]; + + FlxTween.angle(sprite, rotations[0], rotations[1], duration, null); + FlxTween.quadPath(sprite, path, duration, true, { ease: null, - onComplete: function(_) { - car2Interruptable = true; - } - }); - } - - /** - * Resets the values tied to the lights that need to be accounted for on a restart. - */ - function resetStageValues():Void{ - lastChange = 0; - changeInterval = 8; - var traffic = getNamedProp('phillyTraffic'); - if (traffic != null) { - traffic.animation.play('togreen'); - } - lightsStop = false; - } - - var rainDropTimer:Float = 0; - var rainDropWait:Float = 6; - - override function onUpdate(event:UpdateScriptEvent) - { - super.onUpdate(event); - - var remappedIntensityValue:Float = FlxMath.remapToRange(Conductor.instance.songPosition, 0, FlxG.sound.music != null ? FlxG.sound.music.length : 0.0, rainShaderStartIntensity, rainShaderEndIntensity); - rainShader.intensity = remappedIntensityValue; - rainShader.updateViewInfo(FlxG.width, FlxG.height, FlxG.camera); - rainShader.update(event.elapsed); - - if(scrollingSky != null) scrollingSky.scrollX -= FlxG.elapsed * 22; - - // if (rainSndAmbience != null) { - // rainSndAmbience.volume = Math.min(0.3, remappedIntensityValue * 2); - // } - } - - function onBeatHit(event:SongTimeScriptEvent) - { - super.onBeatHit(event); - - // Try driving a car when its possible - if (FlxG.random.bool(10) && event.beat != (lastChange + changeInterval) && carInterruptable == true) - { - if(lightsStop == false){ - driveCar(getNamedProp('phillyCars')); - }else{ - driveCarLights(getNamedProp('phillyCars')); - } - } - - // try driving one on the right too. in this case theres no red light logic, it just can only spawn on green lights - if(FlxG.random.bool(10) && event.beat != (lastChange + changeInterval) && car2Interruptable == true && lightsStop == false) driveCarBack(getNamedProp('phillyCars2')); - - // After the interval has been hit, change the light state. - if (event.beat == (lastChange + changeInterval)) changeLights(event.beat); - } - - override function setupFrameBuffers() - { - //frameBufferMan.createFrameBuffer("mask", 0xFF000000); - //frameBufferMan.createFrameBuffer("lightmap", 0xFF000000); - } - - var screen:FixedBitmapData; - override function draw() - { - super.draw(); - - //screen = grabScreen(false); - //BitmapDataUtil.applyFilter(screen, blurFilter); - //rainShader.blurredScreen = screen; - } - - public override function onPause(event:PauseScriptEvent) { - super.onPause(event); - - pauseCars(); - - // Temporarily stop ambiance. - // if (rainSndAmbience != null) { - // rainSndAmbience.pause(); - // } - // if (carSndAmbience != null) { - // carSndAmbience.pause(); - // } - } - - public override function onResume(event:ScriptEvent) { - super.onResume(event); - - resumeCars(); - - // Temporarily stop ambiance. - // if (rainSndAmbience != null) rainSndAmbience.resume(); - // if (carSndAmbience != null) carSndAmbience.resume(); - } - - function pauseCars():Void { - var cars = getNamedProp('phillyCars'); - if (cars != null) { - FlxTweenUtil.pauseTweensOf(cars); - } - - var cars2 = getNamedProp('phillyCars2'); - if (cars2 != null) { - FlxTweenUtil.pauseTweensOf(cars2); - } - } - - function resumeCars():Void { - var cars = getNamedProp('phillyCars'); - if (cars != null) { - FlxTweenUtil.resumeTweensOf(cars); - } - - var cars2 = getNamedProp('phillyCars2'); - if (cars2 != null) { - FlxTweenUtil.resumeTweensOf(cars2); - } - } - - override function onGameOver(event:ScriptEvent):Void { - super.onGameOver(event); - // Make it so the rain shader doesn't show over the game over screen - FlxG.camera.filters = []; - } - - override function onSongRetry(event:ScriptEvent):Void { - super.onSongRetry(event); - // Make it so the rain shader doesn't show over the game over screen - // FlxG.camera.setFilters([rainShaderFilter]); - - resetCar(true, true); - resetStageValues(); - FlxG.camera.filters = [rainShaderFilter]; - } - - override function addProp(prop:StageProp, ?name:String = null) - { - super.addProp(prop, name); - if (StringTools.endsWith(name, "_lightmap")) - { - prop.blend = 0; // 0 means ADD (see openfl.display.BlendMode) - prop.alpha = 0.6; - //frameBufferMan.moveSpriteTo("lightmap", prop); - } - else if (name == "puddle") - { - rainShader.puddleY = prop.y + 80; - rainShader.puddleScaleY = 0.3; - //frameBufferMan.copySpriteTo("mask", prop, 0xFFFFFF); - } - else - { - //frameBufferMan.copySpriteTo("mask", prop, 0x000000); - } - } + onComplete: function(_) { + car2Interruptable = true; + } + }); + } + + /** + * Resets the values tied to the lights that need to be accounted for on a restart. + */ + function resetStageValues():Void + { + lastChange = 0; + changeInterval = 8; + var traffic = getNamedProp('phillyTraffic'); + if (traffic != null) + { + traffic.animation.play('togreen'); + } + lightsStop = false; + } + + var rainDropTimer:Float = 0; + var rainDropWait:Float = 6; + + override function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); + + var remappedIntensityValue:Float = FlxMath.remapToRange(Conductor.instance.songPosition, 0, FlxG.sound.music != null ? FlxG.sound.music.length : 0.0, + rainShaderStartIntensity, rainShaderEndIntensity); + rainShader.intensity = remappedIntensityValue; + rainShader.updateViewInfo(FlxG.width, FlxG.height, FlxG.camera); + rainShader.update(event.elapsed); + + if (scrollingSky != null) scrollingSky.scrollX -= FlxG.elapsed * 22; + + // if (rainSndAmbience != null) { + // rainSndAmbience.volume = Math.min(0.3, remappedIntensityValue * 2); + // } + } + + function onBeatHit(event:SongTimeScriptEvent) + { + super.onBeatHit(event); + + // Try driving a car when its possible + if (FlxG.random.bool(10) && event.beat != (lastChange + changeInterval) && carInterruptable == true) + { + if (lightsStop == false) + { + driveCar(getNamedProp('phillyCars')); + } + else + { + driveCarLights(getNamedProp('phillyCars')); + } + } + + // try driving one on the right too. in this case theres no red light logic, it just can only spawn on green lights + if (FlxG.random.bool(10) + && event.beat != (lastChange + changeInterval) + && car2Interruptable == true + && lightsStop == false) driveCarBack(getNamedProp('phillyCars2')); + + // After the interval has been hit, change the light state. + if (event.beat == (lastChange + changeInterval)) changeLights(event.beat); + } + + override function setupFrameBuffers() + { + // frameBufferMan.createFrameBuffer("mask", 0xFF000000); + // frameBufferMan.createFrameBuffer("lightmap", 0xFF000000); + } + + var screen:FixedBitmapData; + + override function draw() + { + super.draw(); + + // screen = grabScreen(false); + // BitmapDataUtil.applyFilter(screen, blurFilter); + // rainShader.blurredScreen = screen; + } + + public override function onPause(event:PauseScriptEvent) + { + super.onPause(event); + + pauseCars(); + + // Temporarily stop ambiance. + // if (rainSndAmbience != null) { + // rainSndAmbience.pause(); + // } + // if (carSndAmbience != null) { + // carSndAmbience.pause(); + // } + } + + public override function onResume(event:ScriptEvent) + { + super.onResume(event); + + resumeCars(); + + // Temporarily stop ambiance. + // if (rainSndAmbience != null) rainSndAmbience.resume(); + // if (carSndAmbience != null) carSndAmbience.resume(); + } + + function pauseCars():Void + { + var cars = getNamedProp('phillyCars'); + if (cars != null) + { + FlxTweenUtil.pauseTweensOf(cars); + } + + var cars2 = getNamedProp('phillyCars2'); + if (cars2 != null) + { + FlxTweenUtil.pauseTweensOf(cars2); + } + } + + function resumeCars():Void + { + var cars = getNamedProp('phillyCars'); + if (cars != null) + { + FlxTweenUtil.resumeTweensOf(cars); + } + + var cars2 = getNamedProp('phillyCars2'); + if (cars2 != null) + { + FlxTweenUtil.resumeTweensOf(cars2); + } + } + + override function onGameOver(event:ScriptEvent):Void + { + super.onGameOver(event); + // Make it so the rain shader doesn't show over the game over screen + FlxG.camera.filters = []; + } + + override function onSongRetry(event:ScriptEvent):Void + { + super.onSongRetry(event); + // Make it so the rain shader doesn't show over the game over screen + // FlxG.camera.setFilters([rainShaderFilter]); + + resetCar(true, true); + resetStageValues(); + FlxG.camera.filters = [rainShaderFilter]; + } + + override function addProp(prop:StageProp, ?name:String = null) + { + super.addProp(prop, name); + if (StringTools.endsWith(name, "_lightmap")) + { + prop.blend = 0; // 0 means ADD (see openfl.display.BlendMode) + prop.alpha = 0.6; + // frameBufferMan.moveSpriteTo("lightmap", prop); + } + else if (name == "puddle") + { + rainShader.puddleY = prop.y + 80; + rainShader.puddleScaleY = 0.3; + // frameBufferMan.copySpriteTo("mask", prop, 0xFFFFFF); + } + else + { + // frameBufferMan.copySpriteTo("mask", prop, 0x000000); + } + } override function addCharacter(character:BaseCharacter, charType:CharacterType) - { - super.addCharacter(character, charType); - // add to the mask so that characters hide puddles - // frameBufferMan.copySpriteTo("mask", character, 0x000000); - } + { + super.addCharacter(character, charType); + // add to the mask so that characters hide puddles + // frameBufferMan.copySpriteTo("mask", character, 0x000000); + } } diff --git a/preload/scripts/stages/phillyStreetsErect.hxc b/preload/scripts/stages/phillyStreetsErect.hxc index ff8b322c2..2e5492990 100644 --- a/preload/scripts/stages/phillyStreetsErect.hxc +++ b/preload/scripts/stages/phillyStreetsErect.hxc @@ -25,628 +25,666 @@ import StringTools; class PhillyStreetsErectStage extends Stage { - var rainShader:RuntimeRainShader = new RuntimeRainShader(); - var rainShaderFilter:ShaderFilter; - var blurFilter:BlurFilter = new BlurFilter(6, 6); - - // as song goes on, these are used to make the rain more intense throught the song - // these values are also used for the rain sound effect volume intensity! - var rainShaderStartIntensity:Float; - var rainShaderEndIntensity:Float; - - // var rainSndAmbience:FunkinSound; - // var carSndAmbience:FunkinSound; - - var lightsStop:Bool = false; // state of the traffic lights - var lastChange:Int = 0; - var changeInterval:Int = 8; // make sure it doesnt change until AT LEAST this many beats - - var carWaiting:Bool = false; // if the car is waiting at the lights and is ready to go on green - var carInterruptable:Bool = true; // if the car can be reset - var car2Interruptable:Bool = true; - - var paperInterruptable:Bool = true; - - var scrollingSky:FlxTiledSprite; - - var colorShader:AdjustColorShader; - - function new() - { - super('phillyStreetsErect'); - } - - /** - * Changes the current state of the traffic lights. - * Updates the next change accordingly and will force cars to move when ready - */ - function changeLights(beat:Int):Void{ - - lastChange = beat; - lightsStop = !lightsStop; - - if(lightsStop){ - getNamedProp('phillyTraffic').animation.play('tored'); - changeInterval = 20; - } else { - getNamedProp('phillyTraffic').animation.play('togreen'); - changeInterval = 30; - - if(carWaiting == true) finishCarLights(getNamedProp('phillyCars')); - } - } - - /** - * Resets every value of a car and hides it from view. - */ - function resetCar(left:Bool, right:Bool){ - if(left){ - carWaiting = false; - carInterruptable = true; - var cars = getNamedProp('phillyCars'); - if (cars != null) { - FlxTween.cancelTweensOf(cars); - cars.x = 1200; - cars.y = 818; - cars.angle = 0; - } - } - - if(right){ - car2Interruptable = true; - var cars2 = getNamedProp('phillyCars2'); - if (cars2 != null) { - FlxTween.cancelTweensOf(cars2); - getNamedProp('phillyCars2').x = 1200; - getNamedProp('phillyCars2').y = 818; - getNamedProp('phillyCars2').angle = 0; - } - } - } - - override function onCountdownStart(event:ScriptEvent) { - super.onCountdownStart(event); - - resetCar(true, true); - resetStageValues(); - } - - override function onCountdownEnd(event:ScriptEvent) { - super.onCountdownEnd(event); - // carSndAmbience.volume = 0.1; - } - - override function onCreate(event:ScriptEvent):Void - { - super.onCreate(event); - - // rainSndAmbience = FunkinSound.load(Paths.sound("rainAmbience", "weekend1"), true, false, true); - // rainSndAmbience.volume = 0; - // rainSndAmbience.play(false, FlxG.random.float(0, rainSndAmbience.length)); - - // carSndAmbience = FunkinSound.load(Paths.sound("carAmbience", "weekend1"), true, false, true); - // carSndAmbience.volume = 0; - // carSndAmbience.play(false, FlxG.random.float(0, carSndAmbience.length)); - - // rainShader.puddleMap = Assets.getBitmapData(Paths.image("phillyStreets/puddle")); - rainShader.scale = FlxG.height / 200; // adjust this value so that the rain looks nice - - FlxG.console.registerObject("rainShader", rainShader); - switch (PlayState.instance.currentSong.id) - { - case "darnell": - rainShaderStartIntensity = 0; - rainShaderEndIntensity = 0.01; - case "lit-up": - rainShaderStartIntensity = 0.01; - rainShaderEndIntensity = 0.02; - case "2hot": - rainShaderStartIntensity = 0.02; - rainShaderEndIntensity = 0.04; - } - - rainShader.intensity = rainShaderStartIntensity; - rainShader.rainColor = 0xFFa8adb5; - - // set the shader input - //rainShader.mask = frameBufferMan.getFrameBuffer("mask"); - //rainShader.lightMap = frameBufferMan.getFrameBuffer("lightmap"); - - rainShaderFilter = new ShaderFilter(rainShader); - FlxG.camera.filters = [rainShaderFilter]; - //FlxG.camera.setFilters([new openfl.filters.BlurFilter(16,16)]); - - resetCar(true, true); - resetStageValues(); - } - - var mist0:FlxBackdrop; - var mist1:FlxBackdrop; - var mist2:FlxBackdrop; - var mist3:FlxBackdrop; - var mist4:FlxBackdrop; - var mist5:FlxBackdrop; - - override function buildStage() - { - super.buildStage(); - - scrollingSky = new FlxTiledSprite(Paths.image('phillyStreets/erect/phillySkybox'), 2922, 718, true, false); - scrollingSky.setPosition(-650, -375); - scrollingSky.scrollFactor.set(0.1, 0.1); - scrollingSky.zIndex = 10; - scrollingSky.scale.set(0.65, 0.65); - - PlayState.instance.currentStage.add(scrollingSky); - PlayState.instance.currentStage.refresh(); // Apply z-index. - - colorShader = new AdjustColorShader(); - - mist0 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistMid'), 0x01); - mist0.setPosition(-650, -100); - mist0.scrollFactor.set(1.2, 1.2); - mist0.zIndex = 1000; + var rainShader:RuntimeRainShader = new RuntimeRainShader(); + var rainShaderFilter:ShaderFilter; + var blurFilter:BlurFilter = new BlurFilter(6, 6); + + // as song goes on, these are used to make the rain more intense throught the song + // these values are also used for the rain sound effect volume intensity! + var rainShaderStartIntensity:Float; + var rainShaderEndIntensity:Float; + + // var rainSndAmbience:FunkinSound; + // var carSndAmbience:FunkinSound; + var lightsStop:Bool = false; // state of the traffic lights + var lastChange:Int = 0; + var changeInterval:Int = 8; // make sure it doesnt change until AT LEAST this many beats + + var carWaiting:Bool = false; // if the car is waiting at the lights and is ready to go on green + var carInterruptable:Bool = true; // if the car can be reset + var car2Interruptable:Bool = true; + + var paperInterruptable:Bool = true; + + var scrollingSky:FlxTiledSprite; + + var colorShader:AdjustColorShader; + + function new() + { + super('phillyStreetsErect'); + } + + /** + * Changes the current state of the traffic lights. + * Updates the next change accordingly and will force cars to move when ready + */ + function changeLights(beat:Int):Void + { + lastChange = beat; + lightsStop = !lightsStop; + + if (lightsStop) + { + getNamedProp('phillyTraffic').animation.play('tored'); + changeInterval = 20; + } + else + { + getNamedProp('phillyTraffic').animation.play('togreen'); + changeInterval = 30; + + if (carWaiting == true) finishCarLights(getNamedProp('phillyCars')); + } + } + + /** + * Resets every value of a car and hides it from view. + */ + function resetCar(left:Bool, right:Bool) + { + if (left) + { + carWaiting = false; + carInterruptable = true; + var cars = getNamedProp('phillyCars'); + if (cars != null) + { + FlxTween.cancelTweensOf(cars); + cars.x = 1200; + cars.y = 818; + cars.angle = 0; + } + } + + if (right) + { + car2Interruptable = true; + var cars2 = getNamedProp('phillyCars2'); + if (cars2 != null) + { + FlxTween.cancelTweensOf(cars2); + getNamedProp('phillyCars2').x = 1200; + getNamedProp('phillyCars2').y = 818; + getNamedProp('phillyCars2').angle = 0; + } + } + } + + override function onCountdownStart(event:ScriptEvent) + { + super.onCountdownStart(event); + + resetCar(true, true); + resetStageValues(); + } + + override function onCountdownEnd(event:ScriptEvent) + { + super.onCountdownEnd(event); + // carSndAmbience.volume = 0.1; + } + + override function onCreate(event:ScriptEvent):Void + { + super.onCreate(event); + + // rainSndAmbience = FunkinSound.load(Paths.sound("rainAmbience", "weekend1"), true, false, true); + // rainSndAmbience.volume = 0; + // rainSndAmbience.play(false, FlxG.random.float(0, rainSndAmbience.length)); + + // carSndAmbience = FunkinSound.load(Paths.sound("carAmbience", "weekend1"), true, false, true); + // carSndAmbience.volume = 0; + // carSndAmbience.play(false, FlxG.random.float(0, carSndAmbience.length)); + + // rainShader.puddleMap = Assets.getBitmapData(Paths.image("phillyStreets/puddle")); + rainShader.scale = FlxG.height / 200; // adjust this value so that the rain looks nice + + FlxG.console.registerObject("rainShader", rainShader); + switch (PlayState.instance.currentSong.id) + { + case "darnell": + rainShaderStartIntensity = 0; + rainShaderEndIntensity = 0.01; + case "lit-up": + rainShaderStartIntensity = 0.01; + rainShaderEndIntensity = 0.02; + case "2hot": + rainShaderStartIntensity = 0.02; + rainShaderEndIntensity = 0.04; + } + + rainShader.intensity = rainShaderStartIntensity; + rainShader.rainColor = 0xFFa8adb5; + + // set the shader input + // rainShader.mask = frameBufferMan.getFrameBuffer("mask"); + // rainShader.lightMap = frameBufferMan.getFrameBuffer("lightmap"); + + rainShaderFilter = new ShaderFilter(rainShader); + FlxG.camera.filters = [rainShaderFilter]; + // FlxG.camera.setFilters([new openfl.filters.BlurFilter(16,16)]); + + resetCar(true, true); + resetStageValues(); + } + + var mist0:FlxBackdrop; + var mist1:FlxBackdrop; + var mist2:FlxBackdrop; + var mist3:FlxBackdrop; + var mist4:FlxBackdrop; + var mist5:FlxBackdrop; + + override function buildStage() + { + super.buildStage(); + + scrollingSky = new FlxTiledSprite(Paths.image('phillyStreets/erect/phillySkybox'), 2922, 718, true, false); + scrollingSky.setPosition(-650, -375); + scrollingSky.scrollFactor.set(0.1, 0.1); + scrollingSky.zIndex = 10; + scrollingSky.scale.set(0.65, 0.65); + + PlayState.instance.currentStage.add(scrollingSky); + PlayState.instance.currentStage.refresh(); // Apply z-index. + + colorShader = new AdjustColorShader(); + + mist0 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistMid'), 0x01); + mist0.setPosition(-650, -100); + mist0.scrollFactor.set(1.2, 1.2); + mist0.zIndex = 1000; mist0.blend = 0; - mist0.color = 0xFF5c5c5c; - mist0.alpha = 0.6; - mist0.velocity.x = 172; + mist0.color = 0xFF5c5c5c; + mist0.alpha = 0.6; + mist0.velocity.x = 172; - PlayState.instance.currentStage.add(mist0); - PlayState.instance.currentStage.refresh(); // Apply z-index. + PlayState.instance.currentStage.add(mist0); + PlayState.instance.currentStage.refresh(); // Apply z-index. - mist1 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistMid'), 0x01); - mist1.setPosition(-650, -100); - mist1.scrollFactor.set(1.1, 1.1); - mist1.zIndex = 1000; + mist1 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistMid'), 0x01); + mist1.setPosition(-650, -100); + mist1.scrollFactor.set(1.1, 1.1); + mist1.zIndex = 1000; mist1.blend = 0; - mist1.color = 0xFF5c5c5c; - mist1.alpha = 0.6; - mist1.velocity.x = 150; + mist1.color = 0xFF5c5c5c; + mist1.alpha = 0.6; + mist1.velocity.x = 150; - PlayState.instance.currentStage.add(mist1); - PlayState.instance.currentStage.refresh(); // Apply z-index. + PlayState.instance.currentStage.add(mist1); + PlayState.instance.currentStage.refresh(); // Apply z-index. - mist2 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistBack'), 0x01); - mist2.setPosition(-650, -100); - mist2.scrollFactor.set(1.2, 1.2); - mist2.zIndex = 1001; + mist2 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistBack'), 0x01); + mist2.setPosition(-650, -100); + mist2.scrollFactor.set(1.2, 1.2); + mist2.zIndex = 1001; mist2.blend = 0; - mist2.color = 0xFF5c5c5c; - mist2.alpha = 0.8; - mist2.velocity.x = -80; - - PlayState.instance.currentStage.add(mist2); - PlayState.instance.currentStage.refresh(); // Apply z-index. - - mist3 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistMid'), 0x01); - mist3.setPosition(-650, -100); - mist3.scrollFactor.set(0.95, 0.95); - mist3.zIndex = 99; - mist3.blend = 0; - mist3.color = 0xFF5c5c5c; - mist3.alpha = 0.5; - mist3.velocity.x = -50; - mist3.scale.set(0.8, 0.8); - - PlayState.instance.currentStage.add(mist3); - PlayState.instance.currentStage.refresh(); // Apply z-index. - - mist4 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistBack'), 0x01); - mist4.setPosition(-650, -100); - mist4.scrollFactor.set(0.8, 0.8); - mist4.zIndex = 88; - mist4.blend = 0; - mist4.color = 0xFF5c5c5c; - mist4.alpha = 1; - mist4.velocity.x = 40; - mist4.scale.set(0.7, 0.7); - - PlayState.instance.currentStage.add(mist4); - PlayState.instance.currentStage.refresh(); // Apply z-index. - - mist5 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistMid'), 0x01); - mist5.setPosition(-650, -100); - mist5.scrollFactor.set(0.5, 0.5); - mist5.zIndex = 39; - mist5.blend = 0; - mist5.color = 0xFF5c5c5c; - mist5.alpha = 1; - mist5.velocity.x = 20; - mist5.scale.set(1.1, 1.1); - - PlayState.instance.currentStage.add(mist5); - PlayState.instance.currentStage.refresh(); // Apply z-index. - } - - override function onDestroy(event:ScriptEvent) { - super.onDestroy(); - - var cars = getNamedProp('phillyCars'); - if (cars != null) FlxTween.cancelTweensOf(cars); - var cars2 = getNamedProp('phillyCars2'); - if (cars2 != null) FlxTween.cancelTweensOf(cars2); - - // Fully stop ambiance. - // if (rainSndAmbience != null) rainSndAmbience.stop(); - // if (carSndAmbience != null) carSndAmbience.stop(); - } - - /** - * Drive the car away from the lights to the end of the road. - * Used when the lights turn green and the car is waiting in position. - */ - function finishCarLights(sprite:FlxSprite):Void{ - carWaiting = false; - var duration:Float = FlxG.random.float(1.8, 3); - var rotations:Array = [-5, 18]; - var offset:Array = [306.6, 168.3]; - var startdelay:Float = FlxG.random.float(0.2, 1.2); - - var path:Array = [ - FlxPoint.get(1950 - offset[0] - 80, 980 - offset[1] + 15), - FlxPoint.get(2400 - offset[0], 980 - offset[1] - 50), - FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 40) - ]; - - FlxTween.angle(sprite, rotations[0], rotations[1], duration, {ease: FlxEase.sineIn, startDelay: startdelay} ); - FlxTween.quadPath(sprite, path, duration, true, + mist2.color = 0xFF5c5c5c; + mist2.alpha = 0.8; + mist2.velocity.x = -80; + + PlayState.instance.currentStage.add(mist2); + PlayState.instance.currentStage.refresh(); // Apply z-index. + + mist3 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistMid'), 0x01); + mist3.setPosition(-650, -100); + mist3.scrollFactor.set(0.95, 0.95); + mist3.zIndex = 99; + mist3.blend = 0; + mist3.color = 0xFF5c5c5c; + mist3.alpha = 0.5; + mist3.velocity.x = -50; + mist3.scale.set(0.8, 0.8); + + PlayState.instance.currentStage.add(mist3); + PlayState.instance.currentStage.refresh(); // Apply z-index. + + mist4 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistBack'), 0x01); + mist4.setPosition(-650, -100); + mist4.scrollFactor.set(0.8, 0.8); + mist4.zIndex = 88; + mist4.blend = 0; + mist4.color = 0xFF5c5c5c; + mist4.alpha = 1; + mist4.velocity.x = 40; + mist4.scale.set(0.7, 0.7); + + PlayState.instance.currentStage.add(mist4); + PlayState.instance.currentStage.refresh(); // Apply z-index. + + mist5 = new FlxBackdrop(Paths.image('phillyStreets/erect/mistMid'), 0x01); + mist5.setPosition(-650, -100); + mist5.scrollFactor.set(0.5, 0.5); + mist5.zIndex = 39; + mist5.blend = 0; + mist5.color = 0xFF5c5c5c; + mist5.alpha = 1; + mist5.velocity.x = 20; + mist5.scale.set(1.1, 1.1); + + PlayState.instance.currentStage.add(mist5); + PlayState.instance.currentStage.refresh(); // Apply z-index. + } + + override function onDestroy(event:ScriptEvent) + { + super.onDestroy(); + + var cars = getNamedProp('phillyCars'); + if (cars != null) FlxTween.cancelTweensOf(cars); + var cars2 = getNamedProp('phillyCars2'); + if (cars2 != null) FlxTween.cancelTweensOf(cars2); + + // Fully stop ambiance. + // if (rainSndAmbience != null) rainSndAmbience.stop(); + // if (carSndAmbience != null) carSndAmbience.stop(); + } + + /** + * Drive the car away from the lights to the end of the road. + * Used when the lights turn green and the car is waiting in position. + */ + function finishCarLights(sprite:FlxSprite):Void + { + carWaiting = false; + var duration:Float = FlxG.random.float(1.8, 3); + var rotations:Array = [-5, 18]; + var offset:Array = [306.6, 168.3]; + var startdelay:Float = FlxG.random.float(0.2, 1.2); + + var path:Array = [ + FlxPoint.get(1950 - offset[0] - 80, 980 - offset[1] + 15), + FlxPoint.get(2400 - offset[0], 980 - offset[1] - 50), + FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 40) + ]; + + FlxTween.angle(sprite, rotations[0], rotations[1], duration, {ease: FlxEase.sineIn, startDelay: startdelay}); + FlxTween.quadPath(sprite, path, duration, true, + { + ease: FlxEase.sineIn, + startDelay: startdelay, + onComplete: function(_) { + carInterruptable = true; + } + }); + } + + /** + * Drives a car towards the lights and stops. + * Used when a car tries to drive while the lights are red. + */ + function driveCarLights(sprite:FlxSprite):Void + { + carInterruptable = false; + FlxTween.cancelTweensOf(sprite); + var variant:Int = FlxG.random.int(1, 4); + sprite.animation.play('car' + variant); + var extraOffset = [0, 0]; + var duration:Float = 2; + + switch (variant) { - ease: FlxEase.sineIn, - startDelay: startdelay, - onComplete: function(_) { - carInterruptable = true; - } - }); - } - - /** - * Drives a car towards the lights and stops. - * Used when a car tries to drive while the lights are red. - */ - function driveCarLights(sprite:FlxSprite):Void{ - carInterruptable = false; - FlxTween.cancelTweensOf(sprite); - var variant:Int = FlxG.random.int(1,4); - sprite.animation.play('car' + variant); - var extraOffset = [0, 0]; - var duration:Float = 2; - - switch(variant){ - case 1: - duration = FlxG.random.float(1, 1.7); - case 2: - extraOffset = [20, -15]; - duration = FlxG.random.float(0.9, 1.5); - case 3: - extraOffset = [30, 50]; - duration = FlxG.random.float(1.5, 2.5); - case 4: - extraOffset = [10, 60]; - duration = FlxG.random.float(1.5, 2.5); - } - var rotations:Array = [-7, -5]; - var offset:Array = [306.6, 168.3]; - sprite.offset.set(extraOffset[0], extraOffset[1]); - - var path:Array = [ - FlxPoint.get(1500 - offset[0] - 20, 1049 - offset[1] - 20), - FlxPoint.get(1770 - offset[0] - 80, 994 - offset[1] + 10), - FlxPoint.get(1950 - offset[0] - 80, 980 - offset[1] + 15) - ]; - // debug shit!!! keeping it here just in case - // for(point in path){ - // var debug:FlxSprite = new FlxSprite(point.x - 5, point.y - 5).makeGraphic(10, 10, 0xFFFF0000); + case 1: + duration = FlxG.random.float(1, 1.7); + case 2: + extraOffset = [20, -15]; + duration = FlxG.random.float(0.9, 1.5); + case 3: + extraOffset = [30, 50]; + duration = FlxG.random.float(1.5, 2.5); + case 4: + extraOffset = [10, 60]; + duration = FlxG.random.float(1.5, 2.5); + } + var rotations:Array = [-7, -5]; + var offset:Array = [306.6, 168.3]; + sprite.offset.set(extraOffset[0], extraOffset[1]); + + var path:Array = [ + FlxPoint.get(1500 - offset[0] - 20, 1049 - offset[1] - 20), + FlxPoint.get(1770 - offset[0] - 80, 994 - offset[1] + 10), + FlxPoint.get(1950 - offset[0] - 80, 980 - offset[1] + 15) + ]; + // debug shit!!! keeping it here just in case + // for(point in path){ + // var debug:FlxSprite = new FlxSprite(point.x - 5, point.y - 5).makeGraphic(10, 10, 0xFFFF0000); // add(debug); - // } - FlxTween.angle(sprite, rotations[0], rotations[1], duration, {ease: FlxEase.cubeOut} ); - FlxTween.quadPath(sprite, path, duration, true, + // } + FlxTween.angle(sprite, rotations[0], rotations[1], duration, {ease: FlxEase.cubeOut}); + FlxTween.quadPath(sprite, path, duration, true, + { + ease: FlxEase.cubeOut, + onComplete: function(_) { + carWaiting = true; + if (lightsStop == false) finishCarLights(getNamedProp('phillyCars')); + } + }); + } + + /** + * Drives a car across the screen without stopping. + * Used when the lights are green. + */ + function driveCar(sprite:FlxSprite):Void + { + carInterruptable = false; + FlxTween.cancelTweensOf(sprite); + var variant:Int = FlxG.random.int(1, 4); + sprite.animation.play('car' + variant); + // setting an offset here because the current implementation of stage prop offsets was not working at all for me + // if possible id love to not have to do this but im keeping this for now + var extraOffset = [0, 0]; + var duration:Float = 2; + // set different values of speed for the car types (and the offset) + switch (variant) { - ease: FlxEase.cubeOut, - onComplete: function(_) { - carWaiting = true; - if(lightsStop == false) finishCarLights(getNamedProp('phillyCars')); - } - }); - } - - /** - * Drives a car across the screen without stopping. - * Used when the lights are green. - */ - function driveCar(sprite:FlxSprite):Void{ - carInterruptable = false; - FlxTween.cancelTweensOf(sprite); - var variant:Int = FlxG.random.int(1,4); - sprite.animation.play('car' + variant); - // setting an offset here because the current implementation of stage prop offsets was not working at all for me - // if possible id love to not have to do this but im keeping this for now - var extraOffset = [0, 0]; - var duration:Float = 2; - // set different values of speed for the car types (and the offset) - switch(variant){ - case 1: - duration = FlxG.random.float(1, 1.7); - case 2: - extraOffset = [20, -15]; - duration = FlxG.random.float(0.6, 1.2); - case 3: - extraOffset = [30, 50]; - duration = FlxG.random.float(1.5, 2.5); - case 4: - extraOffset = [10, 60]; - duration = FlxG.random.float(1.5, 2.5); - } - // random arbitrary values for getting the cars in place - // could just add them to the points but im LAZY!!!!!! - var offset:Array = [306.6, 168.3]; - sprite.offset.set(extraOffset[0], extraOffset[1]); - // start/end rotation - var rotations:Array = [-8, 18]; - // the path to move the car on - var path:Array = [ - FlxPoint.get(1570 - offset[0], 1049 - offset[1] - 30), - FlxPoint.get(2400 - offset[0], 980 - offset[1] - 50), - FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 40) - ]; - - FlxTween.angle(sprite, rotations[0], rotations[1], duration, null ); - FlxTween.quadPath(sprite, path, duration, true, + case 1: + duration = FlxG.random.float(1, 1.7); + case 2: + extraOffset = [20, -15]; + duration = FlxG.random.float(0.6, 1.2); + case 3: + extraOffset = [30, 50]; + duration = FlxG.random.float(1.5, 2.5); + case 4: + extraOffset = [10, 60]; + duration = FlxG.random.float(1.5, 2.5); + } + // random arbitrary values for getting the cars in place + // could just add them to the points but im LAZY!!!!!! + var offset:Array = [306.6, 168.3]; + sprite.offset.set(extraOffset[0], extraOffset[1]); + // start/end rotation + var rotations:Array = [-8, 18]; + // the path to move the car on + var path:Array = [ + FlxPoint.get(1570 - offset[0], 1049 - offset[1] - 30), + FlxPoint.get(2400 - offset[0], 980 - offset[1] - 50), + FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 40) + ]; + + FlxTween.angle(sprite, rotations[0], rotations[1], duration, null); + FlxTween.quadPath(sprite, path, duration, true, { ease: null, - onComplete: function(_) { - carInterruptable = true; - } - }); - } - - function driveCarBack(sprite:FlxSprite):Void{ - car2Interruptable = false; - FlxTween.cancelTweensOf(sprite); - var variant:Int = FlxG.random.int(1,4); - sprite.animation.play('car' + variant); - // setting an offset here because the current implementation of stage prop offsets was not working at all for me - // if possible id love to not have to do this but im keeping this for now - var extraOffset = [0, 0]; - var duration:Float = 2; - // set different values of speed for the car types (and the offset) - switch(variant){ - case 1: - duration = FlxG.random.float(1, 1.7); - case 2: - extraOffset = [20, -15]; - duration = FlxG.random.float(0.6, 1.2); - case 3: - extraOffset = [30, 50]; - duration = FlxG.random.float(1.5, 2.5); - case 4: - extraOffset = [10, 60]; - duration = FlxG.random.float(1.5, 2.5); - } - // random arbitrary values for getting the cars in place - // could just add them to the points but im LAZY!!!!!! - var offset:Array = [306.6, 168.3]; - sprite.offset.set(extraOffset[0], extraOffset[1]); - // start/end rotation - var rotations:Array = [18, -8]; - // the path to move the car on - var path:Array = [ - FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 60), - FlxPoint.get(2400 - offset[0], 980 - offset[1] - 30), - FlxPoint.get(1570 - offset[0], 1049 - offset[1] - 10) - - ]; - - FlxTween.angle(sprite, rotations[0], rotations[1], duration, null ); - FlxTween.quadPath(sprite, path, duration, true, + onComplete: function(_) { + carInterruptable = true; + } + }); + } + + function driveCarBack(sprite:FlxSprite):Void + { + car2Interruptable = false; + FlxTween.cancelTweensOf(sprite); + var variant:Int = FlxG.random.int(1, 4); + sprite.animation.play('car' + variant); + // setting an offset here because the current implementation of stage prop offsets was not working at all for me + // if possible id love to not have to do this but im keeping this for now + var extraOffset = [0, 0]; + var duration:Float = 2; + // set different values of speed for the car types (and the offset) + switch (variant) + { + case 1: + duration = FlxG.random.float(1, 1.7); + case 2: + extraOffset = [20, -15]; + duration = FlxG.random.float(0.6, 1.2); + case 3: + extraOffset = [30, 50]; + duration = FlxG.random.float(1.5, 2.5); + case 4: + extraOffset = [10, 60]; + duration = FlxG.random.float(1.5, 2.5); + } + // random arbitrary values for getting the cars in place + // could just add them to the points but im LAZY!!!!!! + var offset:Array = [306.6, 168.3]; + sprite.offset.set(extraOffset[0], extraOffset[1]); + // start/end rotation + var rotations:Array = [18, -8]; + // the path to move the car on + var path:Array = [ + FlxPoint.get(3102 - offset[0], 1127 - offset[1] + 60), + FlxPoint.get(2400 - offset[0], 980 - offset[1] - 30), + FlxPoint.get(1570 - offset[0], 1049 - offset[1] - 10) + + ]; + + FlxTween.angle(sprite, rotations[0], rotations[1], duration, null); + FlxTween.quadPath(sprite, path, duration, true, { ease: null, - onComplete: function(_) { - car2Interruptable = true; - } - }); - } - - /** - * Resets the values tied to the lights that need to be accounted for on a restart. - */ - function resetStageValues():Void{ - lastChange = 0; - changeInterval = 8; - var traffic = getNamedProp('phillyTraffic'); - if (traffic != null) { - traffic.animation.play('togreen'); - } - lightsStop = false; - } - - var rainDropTimer:Float = 0; - var rainDropWait:Float = 6; - - var _timer:Float = 0; - - override function onUpdate(event:UpdateScriptEvent) - { - super.onUpdate(event); - - _timer += event.elapsed; - mist0.y = 660 + (Math.sin(_timer*0.35)*70); - mist1.y = 500 + (Math.sin(_timer*0.3)*80); - mist2.y = 540 + (Math.sin(_timer*0.4)*60); - mist3.y = 230 + (Math.sin(_timer*0.3)*70); - mist4.y = 170 + (Math.sin(_timer*0.35)*50); - mist5.y = -80 + (Math.sin(_timer*0.08)*100); - // mist3.y = -20 + (Math.sin(_timer*0.5)*200); - // mist4.y = -180 + (Math.sin(_timer*0.4)*300); - // mist5.y = -450 + (Math.sin(_timer*0.2)*1xxx50); - //trace(mist1.y); - - var remappedIntensityValue:Float = FlxMath.remapToRange(Conductor.instance.songPosition, 0, FlxG.sound.music != null ? FlxG.sound.music.length : 0.0, rainShaderStartIntensity, rainShaderEndIntensity); - rainShader.intensity = remappedIntensityValue; - rainShader.updateViewInfo(FlxG.width, FlxG.height, FlxG.camera); - rainShader.update(event.elapsed); - - if(scrollingSky != null) scrollingSky.scrollX -= FlxG.elapsed * 22; - - if(PlayState.instance.currentStage.getBoyfriend() != null && PlayState.instance.currentStage.getBoyfriend().shader == null){ + onComplete: function(_) { + car2Interruptable = true; + } + }); + } + + /** + * Resets the values tied to the lights that need to be accounted for on a restart. + */ + function resetStageValues():Void + { + lastChange = 0; + changeInterval = 8; + var traffic = getNamedProp('phillyTraffic'); + if (traffic != null) + { + traffic.animation.play('togreen'); + } + lightsStop = false; + } + + var rainDropTimer:Float = 0; + var rainDropWait:Float = 6; + + var _timer:Float = 0; + + override function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); + + _timer += event.elapsed; + mist0.y = 660 + (Math.sin(_timer * 0.35) * 70); + mist1.y = 500 + (Math.sin(_timer * 0.3) * 80); + mist2.y = 540 + (Math.sin(_timer * 0.4) * 60); + mist3.y = 230 + (Math.sin(_timer * 0.3) * 70); + mist4.y = 170 + (Math.sin(_timer * 0.35) * 50); + mist5.y = -80 + (Math.sin(_timer * 0.08) * 100); + // mist3.y = -20 + (Math.sin(_timer*0.5)*200); + // mist4.y = -180 + (Math.sin(_timer*0.4)*300); + // mist5.y = -450 + (Math.sin(_timer*0.2)*1xxx50); + // trace(mist1.y); + + var remappedIntensityValue:Float = FlxMath.remapToRange(Conductor.instance.songPosition, 0, FlxG.sound.music != null ? FlxG.sound.music.length : 0.0, + rainShaderStartIntensity, rainShaderEndIntensity); + rainShader.intensity = remappedIntensityValue; + rainShader.updateViewInfo(FlxG.width, FlxG.height, FlxG.camera); + rainShader.update(event.elapsed); + + if (scrollingSky != null) scrollingSky.scrollX -= FlxG.elapsed * 22; + + if (PlayState.instance.currentStage.getBoyfriend() != null && PlayState.instance.currentStage.getBoyfriend().shader == null) + { PlayState.instance.currentStage.getBoyfriend().shader = colorShader; - PlayState.instance.currentStage.getGirlfriend().shader = colorShader; - PlayState.instance.currentStage.getDad().shader = colorShader; + PlayState.instance.currentStage.getGirlfriend().shader = colorShader; + PlayState.instance.currentStage.getDad().shader = colorShader; + + colorShader.hue = -5; + colorShader.saturation = -40; + colorShader.contrast = -25; + colorShader.brightness = -20; + } + + // if (rainSndAmbience != null) { + // rainSndAmbience.volume = Math.min(0.3, remappedIntensityValue * 2); + // } + } + + function onBeatHit(event:SongTimeScriptEvent) + { + super.onBeatHit(event); + + // Try driving a car when its possible + if (FlxG.random.bool(10) && event.beat != (lastChange + changeInterval) && carInterruptable == true) + { + if (lightsStop == false) + { + driveCar(getNamedProp('phillyCars')); + } + else + { + driveCarLights(getNamedProp('phillyCars')); + } + } - colorShader.hue = -5; - colorShader.saturation = -40; - colorShader.contrast = -25; - colorShader.brightness = -20; + // var paper = getNamedProp('paper'); + // if (FlxG.random.bool(0.6) && paperInterruptable == true) + // { + // paper.alpha = 1; + // paper.animation.play('paperBlow'); + // paper.y = 608 + FlxG.random.float(-150,150); + // paperInterruptable = false; + // new FlxTimer().start(2, function(tmr:FlxTimer) + // { + // paperInterruptable = true; + // paper.alpha = 0; + // }); + // } + + // try driving one on the right too. in this case theres no red light logic, it just can only spawn on green lights + if (FlxG.random.bool(10) + && event.beat != (lastChange + changeInterval) + && car2Interruptable == true + && lightsStop == false) driveCarBack(getNamedProp('phillyCars2')); + + // After the interval has been hit, change the light state. + if (event.beat == (lastChange + changeInterval)) changeLights(event.beat); + } + + override function setupFrameBuffers() + { + // frameBufferMan.createFrameBuffer("mask", 0xFF000000); + // frameBufferMan.createFrameBuffer("lightmap", 0xFF000000); + } + + var screen:FixedBitmapData; + + override function draw() + { + super.draw(); + + // screen = grabScreen(false); + // BitmapDataUtil.applyFilter(screen, blurFilter); + // rainShader.blurredScreen = screen; + } + + public override function onPause(event:PauseScriptEvent) + { + super.onPause(event); + + pauseCars(); + + // Temporarily stop ambiance. + // if (rainSndAmbience != null) { + // rainSndAmbience.pause(); + // } + // if (carSndAmbience != null) { + // carSndAmbience.pause(); + // } + } + + public override function onResume(event:ScriptEvent) + { + super.onResume(event); + + resumeCars(); + + // Temporarily stop ambiance. + // if (rainSndAmbience != null) rainSndAmbience.resume(); + // if (carSndAmbience != null) carSndAmbience.resume(); + } + + function pauseCars():Void + { + var cars = getNamedProp('phillyCars'); + if (cars != null) + { + FlxTweenUtil.pauseTweensOf(cars); + } + + var cars2 = getNamedProp('phillyCars2'); + if (cars2 != null) + { + FlxTweenUtil.pauseTweensOf(cars2); } + } - // if (rainSndAmbience != null) { - // rainSndAmbience.volume = Math.min(0.3, remappedIntensityValue * 2); - // } - } - - function onBeatHit(event:SongTimeScriptEvent) - { - super.onBeatHit(event); - - // Try driving a car when its possible - if (FlxG.random.bool(10) && event.beat != (lastChange + changeInterval) && carInterruptable == true) - { - if(lightsStop == false){ - driveCar(getNamedProp('phillyCars')); - }else{ - driveCarLights(getNamedProp('phillyCars')); - } - } - - // var paper = getNamedProp('paper'); - // if (FlxG.random.bool(0.6) && paperInterruptable == true) - // { - // paper.alpha = 1; - // paper.animation.play('paperBlow'); - // paper.y = 608 + FlxG.random.float(-150,150); - // paperInterruptable = false; - // new FlxTimer().start(2, function(tmr:FlxTimer) - // { - // paperInterruptable = true; - // paper.alpha = 0; - // }); - // } - - // try driving one on the right too. in this case theres no red light logic, it just can only spawn on green lights - if(FlxG.random.bool(10) && event.beat != (lastChange + changeInterval) && car2Interruptable == true && lightsStop == false) driveCarBack(getNamedProp('phillyCars2')); - - // After the interval has been hit, change the light state. - if (event.beat == (lastChange + changeInterval)) changeLights(event.beat); - } - - override function setupFrameBuffers() - { - //frameBufferMan.createFrameBuffer("mask", 0xFF000000); - //frameBufferMan.createFrameBuffer("lightmap", 0xFF000000); - } - - var screen:FixedBitmapData; - override function draw() - { - super.draw(); - - //screen = grabScreen(false); - //BitmapDataUtil.applyFilter(screen, blurFilter); - //rainShader.blurredScreen = screen; - } - - public override function onPause(event:PauseScriptEvent) { - super.onPause(event); - - pauseCars(); - - // Temporarily stop ambiance. - // if (rainSndAmbience != null) { - // rainSndAmbience.pause(); - // } - // if (carSndAmbience != null) { - // carSndAmbience.pause(); - // } - } - - public override function onResume(event:ScriptEvent) { - super.onResume(event); - - resumeCars(); - - // Temporarily stop ambiance. - // if (rainSndAmbience != null) rainSndAmbience.resume(); - // if (carSndAmbience != null) carSndAmbience.resume(); - } - - function pauseCars():Void { - var cars = getNamedProp('phillyCars'); - if (cars != null) { - FlxTweenUtil.pauseTweensOf(cars); - } - - var cars2 = getNamedProp('phillyCars2'); - if (cars2 != null) { - FlxTweenUtil.pauseTweensOf(cars2); - } - } - - function resumeCars():Void { - var cars = getNamedProp('phillyCars'); - if (cars != null) { - FlxTweenUtil.resumeTweensOf(cars); - } - - var cars2 = getNamedProp('phillyCars2'); - if (cars2 != null) { - FlxTweenUtil.resumeTweensOf(cars2); - } - } - - override function onGameOver(event:ScriptEvent):Void { - super.onGameOver(event); - // Make it so the rain shader doesn't show over the game over screen - FlxG.camera.filters = []; - } - - override function onSongRetry(event:ScriptEvent):Void { - super.onSongRetry(event); - // Make it so the rain shader doesn't show over the game over screen - // FlxG.camera.setFilters([rainShaderFilter]); - - resetCar(true, true); - resetStageValues(); - FlxG.camera.filters = [rainShaderFilter]; - } - - override function addProp(prop:StageProp, ?name:String = null) - { - super.addProp(prop, name); - if (StringTools.endsWith(name, "_lightmap")) - { - prop.blend = 0; // 0 means ADD (see openfl.display.BlendMode) - prop.alpha = 0.6; - //frameBufferMan.moveSpriteTo("lightmap", prop); - } - else if (name == "grey1") - { - prop.blend = 0; - //frameBufferMan.copySpriteTo("mask", prop, 0xFFFFFF); - } - else if (name == "grey2") - { - prop.blend = 9; - //frameBufferMan.copySpriteTo("mask", prop, 0xFFFFFF); - } - else - { - //frameBufferMan.copySpriteTo("mask", prop, 0x000000); - } - } + function resumeCars():Void + { + var cars = getNamedProp('phillyCars'); + if (cars != null) + { + FlxTweenUtil.resumeTweensOf(cars); + } + + var cars2 = getNamedProp('phillyCars2'); + if (cars2 != null) + { + FlxTweenUtil.resumeTweensOf(cars2); + } + } + + override function onGameOver(event:ScriptEvent):Void + { + super.onGameOver(event); + // Make it so the rain shader doesn't show over the game over screen + FlxG.camera.filters = []; + } + + override function onSongRetry(event:ScriptEvent):Void + { + super.onSongRetry(event); + // Make it so the rain shader doesn't show over the game over screen + // FlxG.camera.setFilters([rainShaderFilter]); + + resetCar(true, true); + resetStageValues(); + FlxG.camera.filters = [rainShaderFilter]; + } + + override function addProp(prop:StageProp, ?name:String = null) + { + super.addProp(prop, name); + if (StringTools.endsWith(name, "_lightmap")) + { + prop.blend = 0; // 0 means ADD (see openfl.display.BlendMode) + prop.alpha = 0.6; + // frameBufferMan.moveSpriteTo("lightmap", prop); + } + else if (name == "grey1") + { + prop.blend = 0; + // frameBufferMan.copySpriteTo("mask", prop, 0xFFFFFF); + } + else if (name == "grey2") + { + prop.blend = 9; + // frameBufferMan.copySpriteTo("mask", prop, 0xFFFFFF); + } + else + { + // frameBufferMan.copySpriteTo("mask", prop, 0x000000); + } + } override function addCharacter(character:BaseCharacter, charType:CharacterType) - { - super.addCharacter(character, charType); - // add to the mask so that characters hide puddles - // frameBufferMan.copySpriteTo("mask", character, 0x000000); - } + { + super.addCharacter(character, charType); + // add to the mask so that characters hide puddles + // frameBufferMan.copySpriteTo("mask", character, 0x000000); + } } diff --git a/preload/scripts/stages/phillyTrain.hxc b/preload/scripts/stages/phillyTrain.hxc index f554a7095..8d3d2fc76 100644 --- a/preload/scripts/stages/phillyTrain.hxc +++ b/preload/scripts/stages/phillyTrain.hxc @@ -10,168 +10,169 @@ import funkin.play.stage.Stage; class PhillyTrainStage extends Stage { - function new() - { - super('phillyTrain'); - } - - var LIGHT_COUNT:Int = 5; - - var lightShader:FlxRuntimeShader; - var trainSound:FunkinSound; - - function buildStage() - { - super.buildStage(); - - // NOTE: You pass the constructor variables directly, not as an array. - lightShader = ScriptedFlxRuntimeShader.init('BuildingEffectShader', 1.0); - trainSound = FunkinSound.load(Paths.sound('train_passes'), 1.0, false, false, false); - PlayState.instance.add(trainSound); // Sounds need to be added to the scene for update() to work - - for (i in 0...LIGHT_COUNT) - { - var light:FlxSprite = getNamedProp('lights' + i); - light.shader = lightShader; - light.visible = false; - } - } - - function fetchAssetPaths():Array - { - var results:Array = super.fetchAssetPaths(); - results.push(Paths.sound('train_passes')); - return results; - } - - var trainMoving:Bool = false; - var trainFrameTiming:Float = 0; - var trainCars:Int = 8; - var trainFinishing:Bool = false; - var trainCooldown:Int = 0; - - function onUpdate(event:UpdateScriptEvent):Void - { - super.onUpdate(event); - // Update beat lights - var shaderInput:Float = (Conductor.instance.beatLengthMs / 1000) * event.elapsed * 1.5; - lightShader.scriptCall('update', [shaderInput]); - - // Update train - if (trainMoving) - { - trainFrameTiming += event.elapsed; - - if (trainFrameTiming >= 1 / 24) - { - updateTrainPos(); - trainFrameTiming = 0; - } - } - } - - function onBeatHit(event:SongTimeScriptEvent):Void - { - super.onBeatHit(event); - // Update train cooldown - if (!trainMoving) - trainCooldown += 1; - - // Start train - if (event.beat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8) - { - trainCooldown = FlxG.random.int(-4, 0); - trainStart(); - } - - // Update lights - if (event.beat % 4 == 0) - { - // Reset opacity - lightShader.scriptCall('reset'); - - // Switch to a different light - curLight = FlxG.random.int(0, LIGHT_COUNT - 1); - for (i in 0...LIGHT_COUNT) - { - getNamedProp('lights' + i).visible = (i == curLight); - } - } - } - - public override function onSongEnd(event:CountdownScriptEvent):Void { - super.onSongEnd(event); - // Disable lightning during ending cutscene. - trainMoving = false; - if (trainSound != null) { - trainSound.stop(); - trainSound = null; - } - } - - public override function onPause(event:PauseScriptEvent) { - super.onPause(event); - - // Temporarily stop ambiance. - if (trainSound != null) trainSound.pause(); - } - - public override function onResume(event:ScriptEvent) { - super.onResume(event); - - // Temporarily stop ambiance. - if (trainSound != null) trainSound.resume(); - } - - function trainStart():Void - { - trainMoving = true; - trainSound.play(); - } - - var startedMoving:Bool = false; - - function updateTrainPos():Void - { - if (trainSound.time >= 4700) - { - startedMoving = true; - getGirlfriend().playAnimation('hairBlow'); - } - - if (startedMoving) - { - var train:FlxSprite = getNamedProp('train'); - train.x -= 400; - - if (train.x < -2000 && !trainFinishing) - { - train.x = -1150; - trainCars -= 1; - - if (trainCars <= 0) - trainFinishing = true; - } - - if (train.x < -4000 && trainFinishing) - trainReset(); - } - } - - function trainReset():Void - { - getGirlfriend().playAnimation('hairFall'); - getNamedProp('train').x = FlxG.width + 200; - - trainMoving = false; - trainCars = 8; - trainFinishing = false; - startedMoving = false; - } - - function kill() - { - super.kill(); - lightShader = null; - } + function new() + { + super('phillyTrain'); + } + + var LIGHT_COUNT:Int = 5; + + var lightShader:FlxRuntimeShader; + var trainSound:FunkinSound; + + function buildStage() + { + super.buildStage(); + + // NOTE: You pass the constructor variables directly, not as an array. + lightShader = ScriptedFlxRuntimeShader.init('BuildingEffectShader', 1.0); + trainSound = FunkinSound.load(Paths.sound('train_passes'), 1.0, false, false, false); + PlayState.instance.add(trainSound); // Sounds need to be added to the scene for update() to work + + for (i in 0...LIGHT_COUNT) + { + var light:FlxSprite = getNamedProp('lights' + i); + light.shader = lightShader; + light.visible = false; + } + } + + function fetchAssetPaths():Array + { + var results:Array = super.fetchAssetPaths(); + results.push(Paths.sound('train_passes')); + return results; + } + + var trainMoving:Bool = false; + var trainFrameTiming:Float = 0; + var trainCars:Int = 8; + var trainFinishing:Bool = false; + var trainCooldown:Int = 0; + + function onUpdate(event:UpdateScriptEvent):Void + { + super.onUpdate(event); + // Update beat lights + var shaderInput:Float = (Conductor.instance.beatLengthMs / 1000) * event.elapsed * 1.5; + lightShader.scriptCall('update', [shaderInput]); + + // Update train + if (trainMoving) + { + trainFrameTiming += event.elapsed; + + if (trainFrameTiming >= 1 / 24) + { + updateTrainPos(); + trainFrameTiming = 0; + } + } + } + + function onBeatHit(event:SongTimeScriptEvent):Void + { + super.onBeatHit(event); + // Update train cooldown + if (!trainMoving) trainCooldown += 1; + + // Start train + if (event.beat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8) + { + trainCooldown = FlxG.random.int(-4, 0); + trainStart(); + } + + // Update lights + if (event.beat % 4 == 0) + { + // Reset opacity + lightShader.scriptCall('reset'); + + // Switch to a different light + curLight = FlxG.random.int(0, LIGHT_COUNT - 1); + for (i in 0...LIGHT_COUNT) + { + getNamedProp('lights' + i).visible = (i == curLight); + } + } + } + + public override function onSongEnd(event:CountdownScriptEvent):Void + { + super.onSongEnd(event); + // Disable lightning during ending cutscene. + trainMoving = false; + if (trainSound != null) + { + trainSound.stop(); + trainSound = null; + } + } + + public override function onPause(event:PauseScriptEvent) + { + super.onPause(event); + + // Temporarily stop ambiance. + if (trainSound != null) trainSound.pause(); + } + + public override function onResume(event:ScriptEvent) + { + super.onResume(event); + + // Temporarily stop ambiance. + if (trainSound != null) trainSound.resume(); + } + + function trainStart():Void + { + trainMoving = true; + trainSound.play(); + } + + var startedMoving:Bool = false; + + function updateTrainPos():Void + { + if (trainSound.time >= 4700) + { + startedMoving = true; + getGirlfriend().playAnimation('hairBlow'); + } + + if (startedMoving) + { + var train:FlxSprite = getNamedProp('train'); + train.x -= 400; + + if (train.x < -2000 && !trainFinishing) + { + train.x = -1150; + trainCars -= 1; + + if (trainCars <= 0) trainFinishing = true; + } + + if (train.x < -4000 && trainFinishing) trainReset(); + } + } + + function trainReset():Void + { + getGirlfriend().playAnimation('hairFall'); + getNamedProp('train').x = FlxG.width + 200; + + trainMoving = false; + trainCars = 8; + trainFinishing = false; + startedMoving = false; + } + + function kill() + { + super.kill(); + lightShader = null; + } } diff --git a/preload/scripts/stages/phillyTrainErect.hxc b/preload/scripts/stages/phillyTrainErect.hxc index 7b2ace93c..12b18b769 100644 --- a/preload/scripts/stages/phillyTrainErect.hxc +++ b/preload/scripts/stages/phillyTrainErect.hxc @@ -21,24 +21,24 @@ import flixel.tweens.FlxTween; class PhillyTrainErectStage extends Stage { - function new() - { - super('phillyTrainErect'); - hasPlayedInGameCutscene = false; - } + function new() + { + super('phillyTrainErect'); + hasPlayedInGameCutscene = false; + } - var LIGHT_COUNT:Int = 5; + var LIGHT_COUNT:Int = 5; - var lightShader:FlxRuntimeShader; - var trainSound:FlxSound; + var lightShader:FlxRuntimeShader; + var trainSound:FlxSound; var colorShader:AdjustColorShader; - var cutsceneMusic:FunkinSound; + var cutsceneMusic:FunkinSound; - var hasPlayedInGameCutscene:Bool = false; - var cutsceneSkipped:Bool = false; - var canSkipCutscene:Bool = false; + var hasPlayedInGameCutscene:Bool = false; + var cutsceneSkipped:Bool = false; + var canSkipCutscene:Bool = false; - /** + /** * Replay the cutscene after leaving the song. */ function onCreate(event:ScriptEvent):Void @@ -46,16 +46,18 @@ class PhillyTrainErectStage extends Stage super.onCreate(event); hasPlayedInGameCutscene = false; - cutsceneSkipped = false; - canSkipCutscene = false; - playerShoots = false; - explode = true; + cutsceneSkipped = false; + canSkipCutscene = false; + playerShoots = false; + explode = true; } - public override function onCountdownStart(event:CountdownScriptEvent):Void { - super.onCountdownStart(event); + public override function onCountdownStart(event:CountdownScriptEvent):Void + { + super.onCountdownStart(event); - if(!hasPlayedInGameCutscene && PlayState.instance.currentStage.getBoyfriend().characterId == 'pico-playable'){ + if (!hasPlayedInGameCutscene && PlayState.instance.currentStage.getBoyfriend().characterId == 'pico-playable') + { trace('Pausing countdown to play in game cutscene'); hasPlayedInGameCutscene = true; @@ -64,410 +66,442 @@ class PhillyTrainErectStage extends Stage PlayState.instance.camHUD.visible = false; doppleGangerCutscene(); - }else{ - hasPlayedInGameCutscene = true; - cutsceneSkipped = true; - canSkipCutscene = true; - } - } - - var picoPlayer:ScriptedFlxAtlasSprite; - var picoOpponent:ScriptedFlxAtlasSprite; - var bloodPool:ScriptedFlxAtlasSprite; - var cigarette:FlxSprite; - var skipText:FlxText; + } + else + { + hasPlayedInGameCutscene = true; + cutsceneSkipped = true; + canSkipCutscene = true; + } + } - var playerShoots:Bool; - var explode:Bool; + var picoPlayer:ScriptedFlxAtlasSprite; + var picoOpponent:ScriptedFlxAtlasSprite; + var bloodPool:ScriptedFlxAtlasSprite; + var cigarette:FlxSprite; + var skipText:FlxText; - var cutsceneConductor:Conductor; + var playerShoots:Bool; + var explode:Bool; - var cutsceneTimerManager:FlxTimerManager; + var cutsceneConductor:Conductor; - function doppleGangerCutscene(){ + var cutsceneTimerManager:FlxTimerManager; - skipText = new FlxText(936, 618, 0, 'Skip [ ' + PlayState.instance.controls.getDialogueNameFromToken("CUTSCENE_ADVANCE", true) + ' ]', 20); + function doppleGangerCutscene() + { + skipText = new FlxText(936, 618, 0, 'Skip [ ' + PlayState.instance.controls.getDialogueNameFromToken("CUTSCENE_ADVANCE", true) + ' ]', 20); skipText.setFormat(Paths.font('vcr.ttf'), 40, 0xFFFFFFFF, "right", FlxTextBorderStyle.OUTLINE, 0xFF000000); skipText.scrollFactor.set(); - skipText.borderSize = 2; - skipText.alpha = 0; + skipText.borderSize = 2; + skipText.alpha = 0; add(skipText); skipText.cameras = [PlayState.instance.camCutscene]; - cutsceneTimerManager = new FlxTimerManager(); - - cutsceneConductor = new Conductor(); - var songMusicData:Null = SongRegistry.instance.parseMusicData('cutscene'); - if (songMusicData != null) { - cutsceneConductor.mapTimeChanges(songMusicData.timeChanges); - } - cutsceneConductor.onBeatHit.add(onCutsceneBeatHit); - - // 50/50 chance for who shoots - if(FlxG.random.bool(50)){ - playerShoots = true; - } else { - playerShoots = false; - } - if(FlxG.random.bool(8)){ - // trace('Doppelganger will explode!'); - explode = true; - } else { - // trace('Doppelganger will smoke!'); - explode = false; - } - - var cigarettePos:Array = []; - var shooterPos:Array = []; - - bloodPool = ScriptedFlxAtlasSprite.init('PicoBloodPool', 0, 0); - picoPlayer = ScriptedFlxAtlasSprite.init('PicoDopplegangerSprite', 0, 0); - picoOpponent = ScriptedFlxAtlasSprite.init('PicoDopplegangerSprite', 0, 0); - cigarette = new FlxSprite(0, 0); - - picoPlayer.setPosition(PlayState.instance.currentStage.getBoyfriend().x + 48.5, PlayState.instance.currentStage.getBoyfriend().y + 400); - picoOpponent.setPosition(PlayState.instance.currentStage.getDad().x + 82, PlayState.instance.currentStage.getDad().y + 400); - - picoPlayer.zIndex = PlayState.instance.currentStage.getBoyfriend().zIndex + 1; - - if(playerShoots == true){ - picoOpponent.zIndex = picoPlayer.zIndex - 1; - bloodPool.zIndex = picoOpponent.zIndex - 1; - cigarette.zIndex = PlayState.instance.currentStage.getBoyfriend().zIndex - 2; - cigarette.flipX = true; - - cigarette.setPosition(PlayState.instance.currentStage.getBoyfriend().x - 143.5, PlayState.instance.currentStage.getBoyfriend().y + 210); - bloodPool.setPosition(PlayState.instance.currentStage.getDad().x - 1487, PlayState.instance.currentStage.getDad().y - 173); - - shooterPos = [PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.x, PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.y]; - cigarettePos = [PlayState.instance.currentStage.getDad().cameraFocusPoint.x, PlayState.instance.currentStage.getDad().cameraFocusPoint.y]; - }else{ - picoOpponent.zIndex = picoPlayer.zIndex + 1; - bloodPool.zIndex = picoPlayer.zIndex - 1; - cigarette.zIndex = PlayState.instance.currentStage.getDad().zIndex - 2; - - bloodPool.setPosition(PlayState.instance.currentStage.getBoyfriend().x - 788.5, PlayState.instance.currentStage.getBoyfriend().y - 173); - cigarette.setPosition(PlayState.instance.currentStage.getBoyfriend().x - 478.5, PlayState.instance.currentStage.getBoyfriend().y + 205); - - cigarettePos = [PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.x, PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.y]; - shooterPos = [PlayState.instance.currentStage.getDad().cameraFocusPoint.x, PlayState.instance.currentStage.getDad().cameraFocusPoint.y]; - } - var midPoint:Array = [(shooterPos[0] + cigarettePos[0])/2, (shooterPos[1] + cigarettePos[1])/2]; - - cigarette.frames = Paths.getSparrowAtlas('philly/erect/cigarette'); + cutsceneTimerManager = new FlxTimerManager(); + + cutsceneConductor = new Conductor(); + var songMusicData:Null = SongRegistry.instance.parseMusicData('cutscene'); + if (songMusicData != null) + { + cutsceneConductor.mapTimeChanges(songMusicData.timeChanges); + } + cutsceneConductor.onBeatHit.add(onCutsceneBeatHit); + + // 50/50 chance for who shoots + if (FlxG.random.bool(50)) + { + playerShoots = true; + } + else + { + playerShoots = false; + } + if (FlxG.random.bool(8)) + { + // trace('Doppelganger will explode!'); + explode = true; + } + else + { + // trace('Doppelganger will smoke!'); + explode = false; + } + + var cigarettePos:Array = []; + var shooterPos:Array = []; + + bloodPool = ScriptedFlxAtlasSprite.init('PicoBloodPool', 0, 0); + picoPlayer = ScriptedFlxAtlasSprite.init('PicoDopplegangerSprite', 0, 0); + picoOpponent = ScriptedFlxAtlasSprite.init('PicoDopplegangerSprite', 0, 0); + cigarette = new FlxSprite(0, 0); + + picoPlayer.setPosition(PlayState.instance.currentStage.getBoyfriend().x + 48.5, PlayState.instance.currentStage.getBoyfriend().y + 400); + picoOpponent.setPosition(PlayState.instance.currentStage.getDad().x + 82, PlayState.instance.currentStage.getDad().y + 400); + + picoPlayer.zIndex = PlayState.instance.currentStage.getBoyfriend().zIndex + 1; + + if (playerShoots == true) + { + picoOpponent.zIndex = picoPlayer.zIndex - 1; + bloodPool.zIndex = picoOpponent.zIndex - 1; + cigarette.zIndex = PlayState.instance.currentStage.getBoyfriend().zIndex - 2; + cigarette.flipX = true; + + cigarette.setPosition(PlayState.instance.currentStage.getBoyfriend().x - 143.5, PlayState.instance.currentStage.getBoyfriend().y + 210); + bloodPool.setPosition(PlayState.instance.currentStage.getDad().x - 1487, PlayState.instance.currentStage.getDad().y - 173); + + shooterPos = [ + PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.x, + PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.y + ]; + cigarettePos = [ + PlayState.instance.currentStage.getDad().cameraFocusPoint.x, + PlayState.instance.currentStage.getDad().cameraFocusPoint.y + ]; + } + else + { + picoOpponent.zIndex = picoPlayer.zIndex + 1; + bloodPool.zIndex = picoPlayer.zIndex - 1; + cigarette.zIndex = PlayState.instance.currentStage.getDad().zIndex - 2; + + bloodPool.setPosition(PlayState.instance.currentStage.getBoyfriend().x - 788.5, PlayState.instance.currentStage.getBoyfriend().y - 173); + cigarette.setPosition(PlayState.instance.currentStage.getBoyfriend().x - 478.5, PlayState.instance.currentStage.getBoyfriend().y + 205); + + cigarettePos = [ + PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.x, + PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.y + ]; + shooterPos = [ + PlayState.instance.currentStage.getDad().cameraFocusPoint.x, + PlayState.instance.currentStage.getDad().cameraFocusPoint.y + ]; + } + var midPoint:Array = [(shooterPos[0] + cigarettePos[0]) / 2, (shooterPos[1] + cigarettePos[1]) / 2]; + + cigarette.frames = Paths.getSparrowAtlas('philly/erect/cigarette'); cigarette.animation.addByPrefix('cigarette spit', 'cigarette spit', 24, false); - cigarette.visible = false; + cigarette.visible = false; - PlayState.instance.currentStage.add(cigarette); - PlayState.instance.currentStage.add(picoPlayer); + PlayState.instance.currentStage.add(cigarette); + PlayState.instance.currentStage.add(picoPlayer); PlayState.instance.currentStage.add(picoOpponent); - PlayState.instance.currentStage.add(bloodPool); - PlayState.instance.currentStage.refresh(); + PlayState.instance.currentStage.add(bloodPool); + PlayState.instance.currentStage.refresh(); - picoPlayer.shader = colorShader; - picoOpponent.shader = colorShader; - bloodPool.shader = colorShader; + picoPlayer.shader = colorShader; + picoOpponent.shader = colorShader; + bloodPool.shader = colorShader; - PlayState.instance.currentStage.getBoyfriend().visible = false; - PlayState.instance.currentStage.getDad().visible = false; + PlayState.instance.currentStage.getBoyfriend().visible = false; + PlayState.instance.currentStage.getDad().visible = false; - if(explode == false){ - cutsceneMusic = FunkinSound.load(Paths.music("cutscene/cutscene", "week3"), true); - }else{ - cutsceneMusic = FunkinSound.load(Paths.music("cutscene/cutscene2", "week3"), true); - } - cutsceneMusic.volume = 1; - cutsceneMusic.play(false); + if (explode == false) + { + cutsceneMusic = FunkinSound.load(Paths.music("cutscene/cutscene", "week3"), true); + } + else + { + cutsceneMusic = FunkinSound.load(Paths.music("cutscene/cutscene2", "week3"), true); + } + cutsceneMusic.volume = 1; + cutsceneMusic.play(false); - picoPlayer.scriptCall('doAnim', ['Player', playerShoots, explode, cutsceneTimerManager]); - picoOpponent.scriptCall('doAnim', ['Opponent', !playerShoots, explode, cutsceneTimerManager]); + picoPlayer.scriptCall('doAnim', ['Player', playerShoots, explode, cutsceneTimerManager]); + picoOpponent.scriptCall('doAnim', ['Opponent', !playerShoots, explode, cutsceneTimerManager]); - FunkinSound.playOnce(Paths.sound('cutscene/picoGasp'), 1); + FunkinSound.playOnce(Paths.sound('cutscene/picoGasp'), 1); - PlayState.instance.resetCamera(false, true); + PlayState.instance.resetCamera(false, true); PlayState.instance.cameraFollowPoint.setPosition(midPoint[0], midPoint[1]); - new FlxTimer(cutsceneTimerManager).start(4, _ -> { - - PlayState.instance.cameraFollowPoint.setPosition(cigarettePos[0], cigarettePos[1]); - }); - - new FlxTimer(cutsceneTimerManager).start(6.3, _ -> { - PlayState.instance.cameraFollowPoint.setPosition(shooterPos[0], shooterPos[1]); - }); - - new FlxTimer(cutsceneTimerManager).start(8.75, _ -> { - cutsceneSkipped = true; - canSkipCutscene = false; - FlxTween.tween(skipText, {alpha: 0}, 0.5, {ease: FlxEase.quadIn, onComplete: _ -> {skipText.visible = false;}}); - // cutting off skipping here. really dont think its needed after this point and it saves problems from happening - PlayState.instance.cameraFollowPoint.setPosition(cigarettePos[0], cigarettePos[1]); - if(explode == true) - PlayState.instance.currentStage.getGirlfriend().playAnimation('drop70', true); - }); - - new FlxTimer(cutsceneTimerManager).start(11.2, _ -> { - if(explode == true) - bloodPool.scriptCall('doAnim'); - }); - - new FlxTimer(cutsceneTimerManager).start(11.5, _ -> { - if(explode == false){ - cigarette.visible = true; - cigarette.animation.play('cigarette spit'); - } - }); - - new FlxTimer(cutsceneTimerManager).start(13, _ -> { - - if(explode == false || playerShoots == true){ - PlayState.instance.startCountdown(); - } - - if(explode == true){ - if(playerShoots == true){ - picoPlayer.visible = false; - PlayState.instance.currentStage.getBoyfriend().visible = true; - }else{ - picoOpponent.visible = false; - PlayState.instance.disableKeys = true; - PlayState.instance.currentStage.getDad().visible = true; - - new FlxTimer().start(1, function(tmr) - { - PlayState.instance.camCutscene.fade(0xFF000000, 1, false, null, true); - }); - - new FlxTimer().start(2, function(tmr) - { - PlayState.instance.camCutscene.fade(0xFF000000, 0.5, true, null, true); - PlayState.instance.endSong(true); - }); - } - }else{ - picoPlayer.visible = false; - PlayState.instance.currentStage.getBoyfriend().visible = true; - picoOpponent.visible = false; - PlayState.instance.currentStage.getDad().visible = true; - } - - hasPlayedCutscene = true; - cutsceneMusic.stop(); - }); - } - - function skipCutscene(){ - cutsceneSkipped = true; - explode = false; - hasPlayedCutscene = true; - PlayState.instance.camCutscene.fade(0xFF000000, 0.5, false, null, true); - cutsceneMusic.fadeOut(0.5, 0); - - new FlxTimer().start(0.5, _ -> { - PlayState.instance.justUnpaused = true; - PlayState.instance.camCutscene.fade(0xFF000000, 0.5, true, null, true); - - cutsceneTimerManager.clear(); - picoPlayer.scriptCall('cancelSounds'); - picoOpponent.scriptCall('cancelSounds'); - cutsceneMusic.stop(); - - PlayState.instance.startCountdown(); - - skipText.visible = false; - picoPlayer.visible = false; - picoOpponent.visible = false; - PlayState.instance.currentStage.getBoyfriend().visible = true; - PlayState.instance.currentStage.getDad().visible = true; - }); - - } - - function onCutsceneBeatHit() { - if (PlayState.instance.currentStage.getGirlfriend().isAnimationFinished()) { - PlayState.instance.currentStage.getGirlfriend().dance(true); - } - } - - function onNoteHit(event:HitNoteScriptEvent) - { - super.onNoteHit(event); - if (PlayState.instance.currentStage == null) return; - if (!event.note.noteData.getMustHitNote() && explode == true && playerShoots == true) { - event.cancelEvent(); - PlayState.instance.vocals.opponentVolume = 0; - } + new FlxTimer(cutsceneTimerManager).start(4, _ -> { + PlayState.instance.cameraFollowPoint.setPosition(cigarettePos[0], cigarettePos[1]); + }); + + new FlxTimer(cutsceneTimerManager).start(6.3, _ -> { + PlayState.instance.cameraFollowPoint.setPosition(shooterPos[0], shooterPos[1]); + }); + + new FlxTimer(cutsceneTimerManager).start(8.75, _ -> { + cutsceneSkipped = true; + canSkipCutscene = false; + FlxTween.tween(skipText, {alpha: 0}, 0.5, {ease: FlxEase.quadIn, onComplete: _ -> { + skipText.visible = false; + }}); + // cutting off skipping here. really dont think its needed after this point and it saves problems from happening + PlayState.instance.cameraFollowPoint.setPosition(cigarettePos[0], cigarettePos[1]); + if (explode == true) PlayState.instance.currentStage.getGirlfriend().playAnimation('drop70', true); + }); + + new FlxTimer(cutsceneTimerManager).start(11.2, _ -> { + if (explode == true) bloodPool.scriptCall('doAnim'); + }); + + new FlxTimer(cutsceneTimerManager).start(11.5, _ -> { + if (explode == false) + { + cigarette.visible = true; + cigarette.animation.play('cigarette spit'); + } + }); + + new FlxTimer(cutsceneTimerManager).start(13, _ -> { + if (explode == false || playerShoots == true) + { + PlayState.instance.startCountdown(); + } + + if (explode == true) + { + if (playerShoots == true) + { + picoPlayer.visible = false; + PlayState.instance.currentStage.getBoyfriend().visible = true; + } + else + { + picoOpponent.visible = false; + PlayState.instance.disableKeys = true; + PlayState.instance.currentStage.getDad().visible = true; + + new FlxTimer().start(1, function(tmr) { + PlayState.instance.camCutscene.fade(0xFF000000, 1, false, null, true); + }); + + new FlxTimer().start(2, function(tmr) { + PlayState.instance.camCutscene.fade(0xFF000000, 0.5, true, null, true); + PlayState.instance.endSong(true); + }); + } + } + else + { + picoPlayer.visible = false; + PlayState.instance.currentStage.getBoyfriend().visible = true; + picoOpponent.visible = false; + PlayState.instance.currentStage.getDad().visible = true; + } + + hasPlayedCutscene = true; + cutsceneMusic.stop(); + }); + } - } + function skipCutscene() + { + cutsceneSkipped = true; + explode = false; + hasPlayedCutscene = true; + PlayState.instance.camCutscene.fade(0xFF000000, 0.5, false, null, true); + cutsceneMusic.fadeOut(0.5, 0); + + new FlxTimer().start(0.5, _ -> { + PlayState.instance.justUnpaused = true; + PlayState.instance.camCutscene.fade(0xFF000000, 0.5, true, null, true); + + cutsceneTimerManager.clear(); + picoPlayer.scriptCall('cancelSounds'); + picoOpponent.scriptCall('cancelSounds'); + cutsceneMusic.stop(); + + PlayState.instance.startCountdown(); + + skipText.visible = false; + picoPlayer.visible = false; + picoOpponent.visible = false; + PlayState.instance.currentStage.getBoyfriend().visible = true; + PlayState.instance.currentStage.getDad().visible = true; + }); + } - function buildStage() - { - super.buildStage(); + function onCutsceneBeatHit() + { + if (PlayState.instance.currentStage.getGirlfriend().isAnimationFinished()) + { + PlayState.instance.currentStage.getGirlfriend().dance(true); + } + } - // NOTE: You pass the constructor variables directly, not as an array. - lightShader = ScriptedFlxRuntimeShader.init('BuildingEffectShader', 1.0); - trainSound = new FlxSound().loadEmbedded(Paths.sound('train_passes')); + function onNoteHit(event:HitNoteScriptEvent) + { + super.onNoteHit(event); + if (PlayState.instance.currentStage == null) return; + if (!event.note.noteData.getMustHitNote() && explode == true && playerShoots == true) + { + event.cancelEvent(); + PlayState.instance.vocals.opponentVolume = 0; + } + } + + function buildStage() + { + super.buildStage(); + + // NOTE: You pass the constructor variables directly, not as an array. + lightShader = ScriptedFlxRuntimeShader.init('BuildingEffectShader', 1.0); + trainSound = new FlxSound().loadEmbedded(Paths.sound('train_passes')); colorShader = new AdjustColorShader(); - FlxG.sound.list.add(trainSound); - - for (i in 0...LIGHT_COUNT) - { - var light:FlxSprite = getNamedProp('lights' + i); - light.shader = lightShader; - light.visible = false; - } - - } - - function fetchAssetPaths():Array - { - var results:Array = super.fetchAssetPaths(); - results.push(Paths.sound('train_passes')); - return results; - } - - var trainMoving:Bool = false; - var trainFrameTiming:Float = 0; - var trainCars:Int = 8; - var trainFinishing:Bool = false; - var trainCooldown:Int = 0; - - function onUpdate(event:UpdateScriptEvent):Void - { - super.onUpdate(event); - if(cutsceneTimerManager != null) cutsceneTimerManager.update(event.elapsed); - // Update beat lights - var shaderInput:Float = (Conductor.instance.beatLengthMs / 1000) * event.elapsed * 1.5; - lightShader.scriptCall('update', [shaderInput]); - - if(PlayState.instance.currentStage.getBoyfriend() != null && PlayState.instance.currentStage.getBoyfriend().shader == null){ + FlxG.sound.list.add(trainSound); + + for (i in 0...LIGHT_COUNT) + { + var light:FlxSprite = getNamedProp('lights' + i); + light.shader = lightShader; + light.visible = false; + } + } + + function fetchAssetPaths():Array + { + var results:Array = super.fetchAssetPaths(); + results.push(Paths.sound('train_passes')); + return results; + } + + var trainMoving:Bool = false; + var trainFrameTiming:Float = 0; + var trainCars:Int = 8; + var trainFinishing:Bool = false; + var trainCooldown:Int = 0; + + function onUpdate(event:UpdateScriptEvent):Void + { + super.onUpdate(event); + if (cutsceneTimerManager != null) cutsceneTimerManager.update(event.elapsed); + // Update beat lights + var shaderInput:Float = (Conductor.instance.beatLengthMs / 1000) * event.elapsed * 1.5; + lightShader.scriptCall('update', [shaderInput]); + + if (PlayState.instance.currentStage.getBoyfriend() != null && PlayState.instance.currentStage.getBoyfriend().shader == null) + { PlayState.instance.currentStage.getBoyfriend().shader = colorShader; - PlayState.instance.currentStage.getGirlfriend().shader = colorShader; - PlayState.instance.currentStage.getDad().shader = colorShader; - getNamedProp('train').shader = colorShader; - - colorShader.hue = -26; - colorShader.saturation = -16; - colorShader.contrast = 0; - colorShader.brightness = -5; + PlayState.instance.currentStage.getGirlfriend().shader = colorShader; + PlayState.instance.currentStage.getDad().shader = colorShader; + getNamedProp('train').shader = colorShader; + + colorShader.hue = -26; + colorShader.saturation = -16; + colorShader.contrast = 0; + colorShader.brightness = -5; + } + + var amount:Int = 1; + + // Update train + if (trainMoving) + { + trainFrameTiming += event.elapsed; + + if (trainFrameTiming >= 1 / 24) + { + updateTrainPos(); + trainFrameTiming = 0; + } + } + + if (PlayState.instance.controls.CUTSCENE_ADVANCE && cutsceneSkipped == false) + { + if (canSkipCutscene == false) + { + trace('cant skip yet!'); + FlxTween.tween(skipText, {alpha: 1}, 0.5, {ease: FlxEase.quadOut}); + new FlxTimer().start(0.5, _ -> { + canSkipCutscene = true; + trace('can skip!'); + }); + } + } + if (PlayState.instance.controls.CUTSCENE_ADVANCE && cutsceneSkipped == false && canSkipCutscene == true) + { + skipCutscene(); + trace('skipped'); + } + + if (cutsceneConductor != null && cutsceneMusic != null) + { + cutsceneConductor.update(cutsceneMusic.time); } + } - var amount:Int = 1; + function onBeatHit(event:SongTimeScriptEvent):Void + { + super.onBeatHit(event); + // Update train cooldown + if (!trainMoving) trainCooldown += 1; - // Update train - if (trainMoving) - { - trainFrameTiming += event.elapsed; + // Start train + if (event.beat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8) + { + trainCooldown = FlxG.random.int(-4, 0); + trainStart(); + } - if (trainFrameTiming >= 1 / 24) - { - updateTrainPos(); - trainFrameTiming = 0; - } - } + // Update lights + if (event.beat % 4 == 0) + { + // Reset opacity + lightShader.scriptCall('reset'); + + // Switch to a different light + curLight = FlxG.random.int(0, LIGHT_COUNT - 1); + for (i in 0...LIGHT_COUNT) + { + getNamedProp('lights' + i).visible = (i == curLight); + } + } + } + + function trainStart():Void + { + trainMoving = true; + trainSound.play(true); + } + + var startedMoving:Bool = false; + + function updateTrainPos():Void + { + if (trainSound.time >= 4700) + { + startedMoving = true; + getGirlfriend().playAnimation('hairBlow'); + } - if (PlayState.instance.controls.CUTSCENE_ADVANCE && cutsceneSkipped == false) + if (startedMoving) { - if(canSkipCutscene == false){ - trace('cant skip yet!'); - FlxTween.tween(skipText, {alpha: 1}, 0.5, {ease: FlxEase.quadOut}); - new FlxTimer().start(0.5, _ -> { - canSkipCutscene = true; - trace('can skip!'); - }); - } + var train:FlxSprite = getNamedProp('train'); + train.x -= 400; + + if (train.x < -2000 && !trainFinishing) + { + train.x = -1150; + trainCars -= 1; + + if (trainCars <= 0) trainFinishing = true; + } + + if (train.x < -4000 && trainFinishing) trainReset(); } - if(PlayState.instance.controls.CUTSCENE_ADVANCE && cutsceneSkipped == false && canSkipCutscene == true){ - skipCutscene(); - trace('skipped'); - } - - - if (cutsceneConductor != null && cutsceneMusic != null) { - cutsceneConductor.update(cutsceneMusic.time); - } - } - - function onBeatHit(event:SongTimeScriptEvent):Void - { - super.onBeatHit(event); - // Update train cooldown - if (!trainMoving) - trainCooldown += 1; - - // Start train - if (event.beat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8) - { - trainCooldown = FlxG.random.int(-4, 0); - trainStart(); - } - - // Update lights - if (event.beat % 4 == 0) - { - // Reset opacity - lightShader.scriptCall('reset'); - - // Switch to a different light - curLight = FlxG.random.int(0, LIGHT_COUNT - 1); - for (i in 0...LIGHT_COUNT) - { - getNamedProp('lights' + i).visible = (i == curLight); - } - } - } - - function trainStart():Void - { - trainMoving = true; - trainSound.play(true); - } - - var startedMoving:Bool = false; - - function updateTrainPos():Void - { - if (trainSound.time >= 4700) - { - startedMoving = true; - getGirlfriend().playAnimation('hairBlow'); - } - - if (startedMoving) - { - var train:FlxSprite = getNamedProp('train'); - train.x -= 400; - - if (train.x < -2000 && !trainFinishing) - { - train.x = -1150; - trainCars -= 1; - - if (trainCars <= 0) - trainFinishing = true; - } - - if (train.x < -4000 && trainFinishing) - trainReset(); - } - } - - function trainReset():Void - { - getGirlfriend().playAnimation('hairFall'); - getNamedProp('train').x = FlxG.width + 200; - - trainMoving = false; - trainCars = 8; - trainFinishing = false; - startedMoving = false; - } - - function kill() - { - super.kill(); - if(cutsceneTimerManager != null) cutsceneTimerManager.destroy(); - lightShader = null; - } + } + + function trainReset():Void + { + getGirlfriend().playAnimation('hairFall'); + getNamedProp('train').x = FlxG.width + 200; + + trainMoving = false; + trainCars = 8; + trainFinishing = false; + startedMoving = false; + } + + function kill() + { + super.kill(); + if (cutsceneTimerManager != null) cutsceneTimerManager.destroy(); + lightShader = null; + } } diff --git a/preload/scripts/stages/props/ABotAtlasSprite.hxc b/preload/scripts/stages/props/ABotAtlasSprite.hxc index 938a4beee..501ce8559 100644 --- a/preload/scripts/stages/props/ABotAtlasSprite.hxc +++ b/preload/scripts/stages/props/ABotAtlasSprite.hxc @@ -6,13 +6,14 @@ class ABotAtlasSprite extends FlxAtlasSprite { function new(x:Float, y:Float) { - super(x, y, Paths.animateAtlas("characters/abot/abotSystem", "shared"), { - FrameRate: 24.0, - Reversed: false, - // ?OnComplete:Void -> Void, - ShowPivot: false, - Antialiasing: true, - ScrollFactor: new FlxPoint(1, 1), - }); + super(x, y, Paths.animateAtlas("characters/abot/abotSystem", "shared"), + { + FrameRate: 24.0, + Reversed: false, + // ?OnComplete:Void -> Void, + ShowPivot: false, + Antialiasing: true, + ScrollFactor: new FlxPoint(1, 1), + }); } } diff --git a/preload/scripts/stages/props/CasingSprite.hxc b/preload/scripts/stages/props/CasingSprite.hxc index d55074fc2..c1f9e917e 100644 --- a/preload/scripts/stages/props/CasingSprite.hxc +++ b/preload/scripts/stages/props/CasingSprite.hxc @@ -2,7 +2,6 @@ import flixel.FlxG; import funkin.graphics.FunkinSprite; import funkin.Conductor; import funkin.util.BezierUtil; - // We have to use FlxBasePoint in scripts because FlxPoint is inlined and not available in scripts import flixel.math.FlxBasePoint; @@ -11,49 +10,49 @@ import flixel.math.FlxBasePoint; */ class CasingSprite extends FunkinSprite { - function new() - { - super(0, 0); - - zIndex = 1900; - - loadSparrow('PicoBullet'); - - // Active needs to be true to enable updates. - // This includes velocity/acceleration and frame animations. - active = true; - - animation.addByPrefix('pop', "Pop0", 24, false); - animation.addByPrefix('idle', "Bullet0", 24, true); - animation.play('pop'); - animation.callback = function(name:String, frameNumber:Int, frameIndex:Int) { - if (name == 'pop' && frameNumber == 40) { - startRoll(); - } - }; - } - - function startRoll() { - this.animation.callback = null; // Save performance. - - // Get the end position of the bullet dynamically. - this.x = this.x + this.frame.offset.x - 1; - this.y = this.y + this.frame.offset.y + 1; - - this.angle = 125.1; // Copied from FLA - - // Okay this is the neat part, we can set the velocity and angular acceleration to make it roll without editing update(). - var randomFactorA = FlxG.random.float(3, 10); - var randomFactorB = FlxG.random.float(1.0, 2.0); - this.velocity.x = 20 * randomFactorB; - this.drag.x = randomFactorA * randomFactorB; - - - this.angularVelocity = 100; - // Calculated to ensure angular acceleration is maintained through the whole roll. - this.angularDrag = (this.drag.x / this.velocity.x) * 100; - - animation.play('idle'); - } + function new() + { + super(0, 0); + + zIndex = 1900; + + loadSparrow('PicoBullet'); + + // Active needs to be true to enable updates. + // This includes velocity/acceleration and frame animations. + active = true; + + animation.addByPrefix('pop', "Pop0", 24, false); + animation.addByPrefix('idle', "Bullet0", 24, true); + animation.play('pop'); + animation.callback = function(name:String, frameNumber:Int, frameIndex:Int) { + if (name == 'pop' && frameNumber == 40) + { + startRoll(); + } + }; + } + + function startRoll() + { + this.animation.callback = null; // Save performance. + + // Get the end position of the bullet dynamically. + this.x = this.x + this.frame.offset.x - 1; + this.y = this.y + this.frame.offset.y + 1; + + this.angle = 125.1; // Copied from FLA + + // Okay this is the neat part, we can set the velocity and angular acceleration to make it roll without editing update(). + var randomFactorA = FlxG.random.float(3, 10); + var randomFactorB = FlxG.random.float(1.0, 2.0); + this.velocity.x = 20 * randomFactorB; + this.drag.x = randomFactorA * randomFactorB; + + this.angularVelocity = 100; + // Calculated to ensure angular acceleration is maintained through the whole roll. + this.angularDrag = (this.drag.x / this.velocity.x) * 100; + + animation.play('idle'); + } } - diff --git a/preload/scripts/stages/props/DadShootsSprite.hxc b/preload/scripts/stages/props/DadShootsSprite.hxc index d8d6bbff6..5c50b64cd 100644 --- a/preload/scripts/stages/props/DadShootsSprite.hxc +++ b/preload/scripts/stages/props/DadShootsSprite.hxc @@ -6,29 +6,28 @@ import funkin.play.PlayState; import flixel.FlxG; // a unique object for santa getting KILLED - class DadShootsSprite extends FlxAtlasSprite { - public function new(x:Float, y:Float) { - super(x, y, Paths.animateAtlas("christmas/parents_shoot_assets", "week5"), { - FrameRate: 24.0, - Reversed: false, - // ?OnComplete:Void -> Void, - ShowPivot: false, - Antialiasing: true, - ScrollFactor: new FlxPoint(1, 1), - }); + super(x, y, Paths.animateAtlas("christmas/parents_shoot_assets", "week5"), + { + FrameRate: 24.0, + Reversed: false, + // ?OnComplete:Void -> Void, + ShowPivot: false, + Antialiasing: true, + ScrollFactor: new FlxPoint(1, 1), + }); - // onAnimationFinish.add(finishCanAnimation); + // onAnimationFinish.add(finishCanAnimation); } - public function playCutscene():Void { - //this.visible = true; + public function playCutscene():Void + { + // this.visible = true; this.playAnimation("parents whole scene", false, false, false, 0); this.onAnimationComplete.add(onFinishAnim); - } function onFinishAnim():Void diff --git a/preload/scripts/stages/props/PicoBloodPool.hxc b/preload/scripts/stages/props/PicoBloodPool.hxc index 7623cd573..fa0322d4a 100644 --- a/preload/scripts/stages/props/PicoBloodPool.hxc +++ b/preload/scripts/stages/props/PicoBloodPool.hxc @@ -9,36 +9,37 @@ import funkin.audio.FunkinSound; class PicoBloodPool extends FlxAtlasSprite { - var extend:Bool = false; var el = null; + public function new(x:Float, y:Float) { - super(x, y, Paths.animateAtlas("philly/erect/bloodPool", "week3"), { - FrameRate: 24.0, - Reversed: false, - // ?OnComplete:Void -> Void, - ShowPivot: false, - Antialiasing: true, - ScrollFactor: new FlxPoint(1, 1), + super(x, y, Paths.animateAtlas("philly/erect/bloodPool", "week3"), + { + FrameRate: 24.0, + Reversed: false, + // ?OnComplete:Void -> Void, + ShowPivot: false, + Antialiasing: true, + ScrollFactor: new FlxPoint(1, 1), + }); + + // onAnimationFinish.add(finishCanAnimation); + onAnimationComplete.addOnce((_) -> { + el = anim.curSymbol.getElement(0); + extend = true; }); - - // onAnimationFinish.add(finishCanAnimation); - onAnimationComplete.addOnce((_)->{ - el = anim.curSymbol.getElement(0); - extend = true; - }); this.visible = false; } - public function doAnim(){ + public function doAnim() + { playAnimation("poolAnim", true, false, false); - //backingTextYeah.anim.play(""); + // backingTextYeah.anim.play(""); this.visible = true; } - override public function update(elapsed:Float) { super.update(elapsed); @@ -53,6 +54,5 @@ class PicoBloodPool extends FlxAtlasSprite mat.tx -= el.symbol.transformationPoint.x * val; mat.ty -= el.symbol.transformationPoint.y * val; } - } } diff --git a/preload/scripts/stages/props/PicoDopplegangerSprite.hxc b/preload/scripts/stages/props/PicoDopplegangerSprite.hxc index 4a83b3874..5a167dcc6 100644 --- a/preload/scripts/stages/props/PicoDopplegangerSprite.hxc +++ b/preload/scripts/stages/props/PicoDopplegangerSprite.hxc @@ -10,57 +10,79 @@ import funkin.audio.FunkinSound; class PicoDopplegangerSprite extends FlxAtlasSprite { - public var isPlayer:Bool = false; + var suffix:String = ''; public function new(x:Float, y:Float) { - super(x, y, Paths.animateAtlas("philly/erect/pico_doppleganger", "week3"), { - FrameRate: 24.0, - Reversed: false, - // ?OnComplete:Void -> Void, - ShowPivot: false, - Antialiasing: true, - ScrollFactor: new FlxPoint(1, 1), - }); + super(x, y, Paths.animateAtlas("philly/erect/pico_doppleganger", "week3"), + { + FrameRate: 24.0, + Reversed: false, + // ?OnComplete:Void -> Void, + ShowPivot: false, + Antialiasing: true, + ScrollFactor: new FlxPoint(1, 1), + }); } var cutsceneSounds:FunkinSound = null; - public function cancelSounds(){ - if(cutsceneSounds != null) cutsceneSounds.destroy(); + public function cancelSounds() + { + if (cutsceneSounds != null) cutsceneSounds.destroy(); } - public function doAnim(_suffix:String, shoot:Bool = false, explode:Bool = false, timerManager:FlxTimerManager){ + public function doAnim(_suffix:String, shoot:Bool = false, explode:Bool = false, timerManager:FlxTimerManager) + { suffix = _suffix; trace('Doppelganger: doAnim(' + suffix + ', ' + shoot + ', ' + explode + ')'); - new FlxTimer(timerManager).start(0.3, _ -> {cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoGasp'), 1.0, false, true, true);}); + new FlxTimer(timerManager).start(0.3, _ -> { + cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoGasp'), 1.0, false, true, true); + }); - if(shoot == true){ + if (shoot == true) + { playAnimation("shoot" + suffix, true, false, false); - new FlxTimer(timerManager).start(6.29, _ -> {cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoShoot'), 1.0, false, true, true);}); - new FlxTimer(timerManager).start(10.33, _ -> {cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoSpin'), 1.0, false, true, true);}); - }else{ - if(explode == true){ + new FlxTimer(timerManager).start(6.29, _ -> { + cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoShoot'), 1.0, false, true, true); + }); + new FlxTimer(timerManager).start(10.33, _ -> { + cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoSpin'), 1.0, false, true, true); + }); + } + else + { + if (explode == true) + { playAnimation("explode" + suffix, true, false, false); onAnimationComplete.add(startLoop); - new FlxTimer(timerManager).start(3.7, _ -> {cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoCigarette2'), 1.0, false, true, true);}); - new FlxTimer(timerManager).start(8.75, _ -> {cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoExplode'), 1.0, false, true, true);}); - }else{ + new FlxTimer(timerManager).start(3.7, _ -> { + cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoCigarette2'), 1.0, false, true, true); + }); + new FlxTimer(timerManager).start(8.75, _ -> { + cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoExplode'), 1.0, false, true, true); + }); + } + else + { playAnimation("cigarette" + suffix, true, false, false); - new FlxTimer(timerManager).start(3.7, _ -> {cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoCigarette'), 1.0, false, true, true);}); + new FlxTimer(timerManager).start(3.7, _ -> { + cutsceneSounds = FunkinSound.load(Paths.sound('cutscene/picoCigarette'), 1.0, false, true, true); + }); } } } - function startLoop(){ + function startLoop() + { playAnimation("loop" + suffix, true, false, true); } } diff --git a/preload/scripts/stages/props/SantaDiesSprite.hxc b/preload/scripts/stages/props/SantaDiesSprite.hxc index c81d82cf9..d3f838ada 100644 --- a/preload/scripts/stages/props/SantaDiesSprite.hxc +++ b/preload/scripts/stages/props/SantaDiesSprite.hxc @@ -6,29 +6,28 @@ import funkin.play.PlayState; import flixel.FlxG; // a unique object for santa getting KILLED - class SantaDiesSprite extends FlxAtlasSprite { - public function new(x:Float, y:Float) { - super(x, y, Paths.animateAtlas("christmas/santa_speaks_assets", "week5"), { - FrameRate: 24.0, - Reversed: false, - // ?OnComplete:Void -> Void, - ShowPivot: false, - Antialiasing: true, - ScrollFactor: new FlxPoint(1, 1), - }); + super(x, y, Paths.animateAtlas("christmas/santa_speaks_assets", "week5"), + { + FrameRate: 24.0, + Reversed: false, + // ?OnComplete:Void -> Void, + ShowPivot: false, + Antialiasing: true, + ScrollFactor: new FlxPoint(1, 1), + }); - // onAnimationFinish.add(finishCanAnimation); + // onAnimationFinish.add(finishCanAnimation); } - public function playCutscene():Void { - //this.visible = true; + public function playCutscene():Void + { + // this.visible = true; this.playAnimation("santa whole scene", false, false, false, 0); onAnimationComplete.add(onFinishAnim); - } function onFinishAnim():Void diff --git a/preload/scripts/stages/props/SpraycanAtlasSprite.hxc b/preload/scripts/stages/props/SpraycanAtlasSprite.hxc index 871b59e0c..7b4e85aaa 100644 --- a/preload/scripts/stages/props/SpraycanAtlasSprite.hxc +++ b/preload/scripts/stages/props/SpraycanAtlasSprite.hxc @@ -6,28 +6,31 @@ import funkin.play.PlayState; class SpraycanAtlasSprite extends FlxAtlasSprite { - public var STATE_ARCING:Int = 2; // In the air. - public var STATE_SHOT:Int = 3; // Hit by the player. - public var STATE_IMPACTED:Int = 4; // Impacted the player. + public var STATE_ARCING:Int = 2; // In the air. + public var STATE_SHOT:Int = 3; // Hit by the player. + public var STATE_IMPACTED:Int = 4; // Impacted the player. public var currentState:Int = 2; public function new(x:Float, y:Float) { - super(x, y, Paths.animateAtlas("spraycanAtlas", "weekend1"), { - FrameRate: 24.0, - Reversed: false, - // ?OnComplete:Void -> Void, - ShowPivot: false, - Antialiasing: true, - ScrollFactor: new FlxPoint(1, 1), - }); + super(x, y, Paths.animateAtlas("spraycanAtlas", "weekend1"), + { + FrameRate: 24.0, + Reversed: false, + // ?OnComplete:Void -> Void, + ShowPivot: false, + Antialiasing: true, + ScrollFactor: new FlxPoint(1, 1), + }); onAnimationComplete.add(finishCanAnimation); } - public function finishCanAnimation(name:String) { - switch(name) { + public function finishCanAnimation(name:String) + { + switch (name) + { case 'Can Start': playHitPico(); case 'Can Shot': @@ -38,26 +41,30 @@ class SpraycanAtlasSprite extends FlxAtlasSprite } } - public function playHitExplosion():Void { + public function playHitExplosion():Void + { var explodeEZ:FunkinSprite = FunkinSprite.createSparrow(this.x + 1050, this.y + 150, "spraypaintExplosionEZ"); - explodeEZ.animation.addByPrefix("idle", "explosion round 1 short0", 24, false); - explodeEZ.animation.play("idle"); + explodeEZ.animation.addByPrefix("idle", "explosion round 1 short0", 24, false); + explodeEZ.animation.play("idle"); - PlayState.instance.currentStage.add(explodeEZ); - explodeEZ.animation.finishCallback = () -> { + PlayState.instance.currentStage.add(explodeEZ); + explodeEZ.animation.finishCallback = () -> { explodeEZ.kill(); }; } - public function playCanStart():Void { + public function playCanStart():Void + { this.playAnimation('Can Start'); } - public function playCanShot():Void { + public function playCanShot():Void + { this.playAnimation('Can Shot'); } - public function playHitPico():Void { + public function playHitPico():Void + { this.playAnimation('Hit Pico'); } } diff --git a/preload/scripts/stages/props/TankmanSprite.hxc b/preload/scripts/stages/props/TankmanSprite.hxc index 31e99fcc1..794f6a906 100644 --- a/preload/scripts/stages/props/TankmanSprite.hxc +++ b/preload/scripts/stages/props/TankmanSprite.hxc @@ -9,101 +9,101 @@ import flixel.effects.FlxFlicker; */ class TankmanSprite extends FunkinSprite { - // Randomize the horizontal position of the tankman when 'shot' plays. - public var endingOffset:Float = 0; - // Randomize the speed that the tankman moves to where it will be shot. - public var runSpeed:Float = 0; - // The time in milliseconds when the 'shot' animation should play. - public var strumTime:Float = 0; - // the side the tankman is running from - public var goingRight:Bool = false; - - function new() - { - super(); - - loadSparrow('tankmanKilled1'); - animation.addByPrefix('run', 'tankman running', 24, true); - animation.addByPrefix('shot', 'John Shot ' + FlxG.random.int(1, 2), 24, false); - - initAnim(); - - setGraphicSize(Std.int(width * 0.4)); - - updateHitbox(); - } - - // shamelessly stolen from pico thank u ericc - var tankmanFlicker:FlxFlicker = null; - - function deathFlicker() { - // ERIC: You have to use super instead of this or it breaks. - // This is because typeof(this) is PolymodAbstractClass. - tankmanFlicker = FlxFlicker.flicker(super, 0.3, 1 / 10, true, true, function(_) { + // Randomize the horizontal position of the tankman when 'shot' plays. + public var endingOffset:Float = 0; + // Randomize the speed that the tankman moves to where it will be shot. + public var runSpeed:Float = 0; + // The time in milliseconds when the 'shot' animation should play. + public var strumTime:Float = 0; + // the side the tankman is running from + public var goingRight:Bool = false; + + function new() + { + super(); + + loadSparrow('tankmanKilled1'); + animation.addByPrefix('run', 'tankman running', 24, true); + animation.addByPrefix('shot', 'John Shot ' + FlxG.random.int(1, 2), 24, false); + + initAnim(); + + setGraphicSize(Std.int(width * 0.4)); + + updateHitbox(); + } + + // shamelessly stolen from pico thank u ericc + var tankmanFlicker:FlxFlicker = null; + + function deathFlicker() + { + // ERIC: You have to use super instead of this or it breaks. + // This is because typeof(this) is PolymodAbstractClass. + tankmanFlicker = FlxFlicker.flicker(super, 0.3, 1 / 10, true, true, function(_) { tankmanFlicker = FlxFlicker.flicker(super, 0.3, 1 / 20, false, true, function(_) { - tankmanFlicker = null; - kill(); - }); + tankmanFlicker = null; + kill(); + }); }); - } - - function initAnim() - { - // Called when the sprite is created as well as when it is revived. - - animation.play('run'); - animation.curAnim.curFrame = FlxG.random.int(0, animation.curAnim.numFrames - 1); - - offset.y = 0; - offset.x = 0; - } - - function revive() - { - // Sprite has been revived! This allows it to be reused without reinstantiating. - super.revive(); - visible = true; - initAnim(); - } - - function update(elapsed:Float):Void - { - super.update(elapsed); - - - if (animation.curAnim.name == 'shot' && animation.curAnim.curFrame >= 10 && tankmanFlicker == null) - { - deathFlicker(); - } - // Check if we've reached the time when the tankman should be shot. - if (Conductor.instance.songPosition >= strumTime && animation.curAnim.name == 'run') - { - animation.play('shot'); - - offset.y = 200; - offset.x = 300; - } - - // Move the sprite while it is running. - if (animation.curAnim.name == 'run') - { - // Here, the position is set to the target position where it will be shot. - // Then, we move the sprite away from that position in the direction it's coming from. - // songPosition - strumTime will get smaller over time until it reaches 0, when the 'shot' anim plays. - if (!goingRight) - { - x = (FlxG.width * 0.02 - endingOffset) + ((Conductor.instance.songPosition - strumTime) * runSpeed); - } - else - { - x = (FlxG.width * 0.74 + endingOffset) - ((Conductor.instance.songPosition - strumTime) * runSpeed); - } - } - - // Hide this sprite if it is out of view. - // if (x >= FlxG.width * 1.2 || x <= FlxG.width * -0.5) - // visible = false; - // else - // visible = true; - } + } + + function initAnim() + { + // Called when the sprite is created as well as when it is revived. + + animation.play('run'); + animation.curAnim.curFrame = FlxG.random.int(0, animation.curAnim.numFrames - 1); + + offset.y = 0; + offset.x = 0; + } + + function revive() + { + // Sprite has been revived! This allows it to be reused without reinstantiating. + super.revive(); + visible = true; + initAnim(); + } + + function update(elapsed:Float):Void + { + super.update(elapsed); + + if (animation.curAnim.name == 'shot' && animation.curAnim.curFrame >= 10 && tankmanFlicker == null) + { + deathFlicker(); + } + // Check if we've reached the time when the tankman should be shot. + if (Conductor.instance.songPosition >= strumTime && animation.curAnim.name == 'run') + { + animation.play('shot'); + + offset.y = 200; + offset.x = 300; + } + + // Move the sprite while it is running. + if (animation.curAnim.name == 'run') + { + // Here, the position is set to the target position where it will be shot. + // Then, we move the sprite away from that position in the direction it's coming from. + // songPosition - strumTime will get smaller over time until it reaches 0, when the 'shot' anim plays. + if (!goingRight) + { + x = (FlxG.width * 0.02 - endingOffset) + ((Conductor.instance.songPosition - strumTime) * runSpeed); + } + else + { + x = (FlxG.width * 0.74 + endingOffset) - ((Conductor.instance.songPosition - strumTime) * runSpeed); + } + } + + // Hide this sprite if it is out of view. + // if (x >= FlxG.width * 1.2 || x <= FlxG.width * -0.5) + // visible = false; + // else + // visible = true; + } } diff --git a/preload/scripts/stages/props/TankmanSpriteGroup.hxc b/preload/scripts/stages/props/TankmanSpriteGroup.hxc index 87d5400bc..07cc10cfb 100644 --- a/preload/scripts/stages/props/TankmanSpriteGroup.hxc +++ b/preload/scripts/stages/props/TankmanSpriteGroup.hxc @@ -9,117 +9,118 @@ import Lambda; class TankmanSpriteGroup extends FlxTypedSpriteGroup { - var tankmanTimes:Array = []; - var tankmanDirs:Array = []; - - var MAX_SIZE = 4; - - function new() - { - super(0, 0, 4); - this.zIndex = 30; - } - - function reset() - { - group.clear(); - - // Create the other tankmen. - initTimemap(); - } - - function initTimemap() - { - trace('Initializing Tankman timings...'); - tankmanTimes = []; - // The tankmen's timings and directions are determined - // by the chart, specifically the internal "picospeaker" difficulty. - var animChart:SongDifficulty = PlayState.instance.currentSong.getDifficulty('picospeaker'); - if (animChart == null) - { - trace('Skip initializing TankmanSpriteGroup: no picospeaker chart.'); - return; - } else { - trace('Found picospeaker chart for TankmanSpriteGroup.'); - } - var animNotes:Array = animChart.notes; - - // turns out sorting functions are completely useless in polymod right now and do nothing - // i had to sort the whole pico chart by hand im gonna go insane - animNotes.sort(function(a:SongNoteData, b:SongNoteData):Int - { - return FlxSort.byValues(FlxSort.ASCENDING, a.time, b.time); - }); - - for (note in animNotes) - { - // Only one out of every 16 notes, on average, is a tankman. - if (FlxG.random.bool(6.25)) - { - tankmanTimes.push(note.time); - var goingRight:Bool = note.data == 3 ? false : true; - tankmanDirs.push(goingRight); - } - } - } - - /** - * Creates a Tankman sprite and adds it to the group. - */ - function createTankman(initX:Float, initY:Float, strumTime:Float, goingRight:Bool) - { - // recycle() is neat; it looks for a sprite which has completed its animation and resets it, - // rather than calling the constructor again. It only calls the constructor if it can't find one. - - var tankman:ScriptedFunkinSprite = group.recycle(FlxSprite, _initTankmanObj, false, true); - - // We can directly set values which are defined by the script's superclass. - tankman.x = initX; - tankman.y = initY; - tankman.flipX = !goingRight; - // We need to use scriptSet for values which were defined in a script. - tankman.scriptSet('strumTime', strumTime); - tankman.scriptSet('endingOffset', FlxG.random.float(50, 200)); - tankman.scriptSet('runSpeed', FlxG.random.float(0.6, 1)); - tankman.scriptSet('goingRight', goingRight); - - this.add(tankman); - } - - function _initTankmanObj():ScriptedFunkinSprite - { - var result:ScriptedFunkinSprite = ScriptedFunkinSprite.init('TankmanSprite'); - return result; - } - - var timer:Float = 0; - - function update(elapsed:Float) - { - super.update(elapsed); - - while (true) - { - // Create tankmen 10 seconds in advance. - var cutoff:Float = Conductor.instance.songPosition + (1000 * 3); - if (tankmanTimes.length > 0 && tankmanTimes[0] <= cutoff) - { - var nextTime:Float = tankmanTimes.shift(); - var goingRight:Bool = tankmanDirs.shift(); - var xPos = 500; - var yPos:Float = 200 + FlxG.random.int(50, 100); - createTankman(xPos, yPos, nextTime, goingRight); - } - else - { - break; - } - } - } - - function kill() - { - super.kill(); - tankmanTimes = []; - } + var tankmanTimes:Array = []; + var tankmanDirs:Array = []; + + var MAX_SIZE = 4; + + function new() + { + super(0, 0, 4); + this.zIndex = 30; + } + + function reset() + { + group.clear(); + + // Create the other tankmen. + initTimemap(); + } + + function initTimemap() + { + trace('Initializing Tankman timings...'); + tankmanTimes = []; + // The tankmen's timings and directions are determined + // by the chart, specifically the internal "picospeaker" difficulty. + var animChart:SongDifficulty = PlayState.instance.currentSong.getDifficulty('picospeaker'); + if (animChart == null) + { + trace('Skip initializing TankmanSpriteGroup: no picospeaker chart.'); + return; + } + else + { + trace('Found picospeaker chart for TankmanSpriteGroup.'); + } + var animNotes:Array = animChart.notes; + + // turns out sorting functions are completely useless in polymod right now and do nothing + // i had to sort the whole pico chart by hand im gonna go insane + animNotes.sort(function(a:SongNoteData, b:SongNoteData):Int { + return FlxSort.byValues(FlxSort.ASCENDING, a.time, b.time); + }); + + for (note in animNotes) + { + // Only one out of every 16 notes, on average, is a tankman. + if (FlxG.random.bool(6.25)) + { + tankmanTimes.push(note.time); + var goingRight:Bool = note.data == 3 ? false : true; + tankmanDirs.push(goingRight); + } + } + } + + /** + * Creates a Tankman sprite and adds it to the group. + */ + function createTankman(initX:Float, initY:Float, strumTime:Float, goingRight:Bool) + { + // recycle() is neat; it looks for a sprite which has completed its animation and resets it, + // rather than calling the constructor again. It only calls the constructor if it can't find one. + + var tankman:ScriptedFunkinSprite = group.recycle(FlxSprite, _initTankmanObj, false, true); + + // We can directly set values which are defined by the script's superclass. + tankman.x = initX; + tankman.y = initY; + tankman.flipX = !goingRight; + // We need to use scriptSet for values which were defined in a script. + tankman.scriptSet('strumTime', strumTime); + tankman.scriptSet('endingOffset', FlxG.random.float(50, 200)); + tankman.scriptSet('runSpeed', FlxG.random.float(0.6, 1)); + tankman.scriptSet('goingRight', goingRight); + + this.add(tankman); + } + + function _initTankmanObj():ScriptedFunkinSprite + { + var result:ScriptedFunkinSprite = ScriptedFunkinSprite.init('TankmanSprite'); + return result; + } + + var timer:Float = 0; + + function update(elapsed:Float) + { + super.update(elapsed); + + while (true) + { + // Create tankmen 10 seconds in advance. + var cutoff:Float = Conductor.instance.songPosition + (1000 * 3); + if (tankmanTimes.length > 0 && tankmanTimes[0] <= cutoff) + { + var nextTime:Float = tankmanTimes.shift(); + var goingRight:Bool = tankmanDirs.shift(); + var xPos = 500; + var yPos:Float = 200 + FlxG.random.int(50, 100); + createTankman(xPos, yPos, nextTime, goingRight); + } + else + { + break; + } + } + } + + function kill() + { + super.kill(); + tankmanTimes = []; + } } diff --git a/preload/scripts/stages/school.hxc b/preload/scripts/stages/school.hxc index 89438ca8f..046ac6f16 100644 --- a/preload/scripts/stages/school.hxc +++ b/preload/scripts/stages/school.hxc @@ -3,20 +3,22 @@ import funkin.play.stage.Stage; class SchoolStage extends Stage { - function new() - { - super('school'); - } + function new() + { + super('school'); + } - function buildStage() - { - super.buildStage(); + function buildStage() + { + super.buildStage(); - if (PlayState.instance.currentSong.id.toLowerCase() == "roses") - { - getNamedProp('freaks').idleSuffix = '-scared'; - } else { - getNamedProp('freaks').idleSuffix = ''; - } - } + if (PlayState.instance.currentSong.id.toLowerCase() == "roses") + { + getNamedProp('freaks').idleSuffix = '-scared'; + } + else + { + getNamedProp('freaks').idleSuffix = ''; + } + } } diff --git a/preload/scripts/stages/schoolEvil.hxc b/preload/scripts/stages/schoolEvil.hxc index 10b02182d..7a3378a91 100644 --- a/preload/scripts/stages/schoolEvil.hxc +++ b/preload/scripts/stages/schoolEvil.hxc @@ -7,39 +7,41 @@ import funkin.play.Countdown; class SchoolEvilStage extends Stage { - function new() - { - super('schoolEvil'); - } - - var wiggle:FlxRuntimeShader = null; - - override function buildStage() - { - super.buildStage(); - - wiggle = new WiggleEffectRuntime(2, 4, 0.017, WiggleEffectType.DREAMY); - - getNamedProp('evilSchoolBG').shader = wiggle; - getNamedProp('evilSchoolFG').shader = wiggle; - } - - override function addCharacter(char:BaseCharacter, charType:CharacterType) - { - - super.addCharacter(char, charType); - } - - override function onUpdate(event:UpdateScriptEvent) { - super.onUpdate(event); - - if (wiggle != null) { - wiggle.update(event.elapsed); - } - } - - function kill() { - super.kill(); - wiggle = null; - } + function new() + { + super('schoolEvil'); + } + + var wiggle:FlxRuntimeShader = null; + + override function buildStage() + { + super.buildStage(); + + wiggle = new WiggleEffectRuntime(2, 4, 0.017, WiggleEffectType.DREAMY); + + getNamedProp('evilSchoolBG').shader = wiggle; + getNamedProp('evilSchoolFG').shader = wiggle; + } + + override function addCharacter(char:BaseCharacter, charType:CharacterType) + { + super.addCharacter(char, charType); + } + + override function onUpdate(event:UpdateScriptEvent) + { + super.onUpdate(event); + + if (wiggle != null) + { + wiggle.update(event.elapsed); + } + } + + function kill() + { + super.kill(); + wiggle = null; + } } diff --git a/preload/scripts/stages/spookyMansion.hxc b/preload/scripts/stages/spookyMansion.hxc index ae8b5eed9..91d080cc7 100644 --- a/preload/scripts/stages/spookyMansion.hxc +++ b/preload/scripts/stages/spookyMansion.hxc @@ -5,73 +5,76 @@ import funkin.play.stage.Stage; class SpookyMansionStage extends Stage { - function new() - { - super('spookyMansion'); - } + function new() + { + super('spookyMansion'); + } - var lightningStrikeBeat:Int = 0; - var lightningStrikeOffset:Int = 8; + var lightningStrikeBeat:Int = 0; + var lightningStrikeOffset:Int = 8; - function doLightningStrike(playSound:Bool, beat:Int):Void - { - if (playSound) - { - FunkinSound.playOnce(Paths.soundRandom('thunder_', 1, 2), 1.0); - } + function doLightningStrike(playSound:Bool, beat:Int):Void + { + if (playSound) + { + FunkinSound.playOnce(Paths.soundRandom('thunder_', 1, 2), 1.0); + } - getNamedProp('halloweenBG').animation.play('lightning'); + getNamedProp('halloweenBG').animation.play('lightning'); - lightningStrikeBeat = beat; - lightningStrikeOffset = FlxG.random.int(8, 24); + lightningStrikeBeat = beat; + lightningStrikeOffset = FlxG.random.int(8, 24); - if (getBoyfriend() != null && getBoyfriend().hasAnimation('scared')) { - getBoyfriend().playAnimation('scared', true, true); - } + if (getBoyfriend() != null && getBoyfriend().hasAnimation('scared')) + { + getBoyfriend().playAnimation('scared', true, true); + } - if (getGirlfriend() != null && getGirlfriend().hasAnimation('scared')) { - getGirlfriend().playAnimation('scared', true, true); - } - } + if (getGirlfriend() != null && getGirlfriend().hasAnimation('scared')) + { + getGirlfriend().playAnimation('scared', true, true); + } + } - /** - * If your stage uses additional assets not specified in the JSON, - * make sure to specify them like this, or they won't get cached in the loading screen. - */ - function fetchAssetPaths():Array - { - var results:Array = super.fetchAssetPaths(); - results.push(Paths.sound('thunder_1')); - results.push(Paths.sound('thunder_2')); - return results; - } + /** + * If your stage uses additional assets not specified in the JSON, + * make sure to specify them like this, or they won't get cached in the loading screen. + */ + function fetchAssetPaths():Array + { + var results:Array = super.fetchAssetPaths(); + results.push(Paths.sound('thunder_1')); + results.push(Paths.sound('thunder_2')); + return results; + } - function onBeatHit(event:SongTimeScriptEvent) - { - super.onBeatHit(event); + function onBeatHit(event:SongTimeScriptEvent) + { + super.onBeatHit(event); - // Play lightning on sync at the start of this specific song. - // TODO: Rework this after chart format redesign. - if (PlayState.instance.currentSong != null) { - if (event.beat == 4 && PlayState.instance.currentSong.id == "spookeez") - { - doLightningStrike(false, event.beat); - } - } + // Play lightning on sync at the start of this specific song. + // TODO: Rework this after chart format redesign. + if (PlayState.instance.currentSong != null) + { + if (event.beat == 4 && PlayState.instance.currentSong.id == "spookeez") + { + doLightningStrike(false, event.beat); + } + } - // Play lightning at random intervals. - if (FlxG.random.bool(10) && event.beat > (lightningStrikeBeat + lightningStrikeOffset)) - { - doLightningStrike(true, event.beat); - } - } + // Play lightning at random intervals. + if (FlxG.random.bool(10) && event.beat > (lightningStrikeBeat + lightningStrikeOffset)) + { + doLightningStrike(true, event.beat); + } + } - function onSongRetry(event:ScriptEvent) - { - super.onSongRetry(event); + function onSongRetry(event:ScriptEvent) + { + super.onSongRetry(event); - // Properly reset lightning when restarting the song. - lightningStrikeBeat = 0; - lightningStrikeOffset = 8; - } + // Properly reset lightning when restarting the song. + lightningStrikeBeat = 0; + lightningStrikeOffset = 8; + } } diff --git a/preload/scripts/stages/spookyMansionErect.hxc b/preload/scripts/stages/spookyMansionErect.hxc index 644f29374..f0b4dc1ac 100644 --- a/preload/scripts/stages/spookyMansionErect.hxc +++ b/preload/scripts/stages/spookyMansionErect.hxc @@ -14,60 +14,61 @@ import funkin.graphics.shaders.RuntimeRainShader; class SpookyMansionErectStage extends Stage { - function new() - { - super('spookyMansionErect'); - } + function new() + { + super('spookyMansionErect'); + } - var rainShaderTarget:FlxSprite; - var rainShader:RuntimeRainShader = new RuntimeRainShader(); + var rainShaderTarget:FlxSprite; + var rainShader:RuntimeRainShader = new RuntimeRainShader(); - var lightningStrikeBeat:Int = 0; - var lightningStrikeOffset:Int = 8; + var lightningStrikeBeat:Int = 0; + var lightningStrikeOffset:Int = 8; - override function onCreate(event:ScriptEvent):Void - { - super.onCreate(event); + override function onCreate(event:ScriptEvent):Void + { + super.onCreate(event); - trace('Applying rain shader...'); + trace('Applying rain shader...'); - // adjust this value so that the rain looks nice - rainShader.scale = FlxG.height / 200 * 2; - rainShader.intensity = 0.4; - rainShader.spriteMode = true; + // adjust this value so that the rain looks nice + rainShader.scale = FlxG.height / 200 * 2; + rainShader.intensity = 0.4; + rainShader.spriteMode = true; - rainShaderTarget = getNamedProp('bgTrees'); - rainShaderTarget.shader = rainShader; - rainShaderTarget.animation.callback = onBranchFrame; - } + rainShaderTarget = getNamedProp('bgTrees'); + rainShaderTarget.shader = rainShader; + rainShaderTarget.animation.callback = onBranchFrame; + } - function onBranchFrame(name, frameNum, frameIndex) { - rainShader.updateFrameInfo(rainShaderTarget.frame); - } + function onBranchFrame(name, frameNum, frameIndex) + { + rainShader.updateFrameInfo(rainShaderTarget.frame); + } override function buildStage() - { - super.buildStage(); + { + super.buildStage(); getNamedProp('bgLight').alpha = 0; getNamedProp('stairsLight').alpha = 0; - } + } override function onUpdate(event:UpdateScriptEvent) - { - super.onUpdate(event); - rainShader.update(event.elapsed); - } + { + super.onUpdate(event); + rainShader.update(event.elapsed); + } - function doLightningStrike(playSound:Bool, beat:Int):Void - { - if(getBoyfriend() == null || getGirlfriend() == null || getDad() == null) return; + function doLightningStrike(playSound:Bool, beat:Int):Void + { + if (getBoyfriend() == null || getGirlfriend() == null || getDad() == null) return; - if (playSound) - { - FunkinSound.playOnce(Paths.soundRandom('thunder_', 1, 2), 1.0); - } + if (playSound) + { + FunkinSound.playOnce(Paths.soundRandom('thunder_', 1, 2), 1.0); + } - //getNamedProp('halloweenBG').animation.play('lightning'); + // getNamedProp('halloweenBG').animation.play('lightning'); getNamedProp('bgLight').alpha = 1; getNamedProp('stairsLight').alpha = 1; PlayState.instance.currentStage.getBoyfriend().alpha = 0; @@ -77,10 +78,10 @@ class SpookyMansionErectStage extends Stage new FlxTimer().start(0.06, function(_) { getNamedProp('bgLight').alpha = 0; getNamedProp('stairsLight').alpha = 0; - PlayState.instance.currentStage.getBoyfriend().alpha = 1; - PlayState.instance.currentStage.getDad().alpha = 1; - PlayState.instance.currentStage.getGirlfriend().alpha = 1; - }); + PlayState.instance.currentStage.getBoyfriend().alpha = 1; + PlayState.instance.currentStage.getDad().alpha = 1; + PlayState.instance.currentStage.getGirlfriend().alpha = 1; + }); new FlxTimer().start(0.12, function(_) { getNamedProp('bgLight').alpha = 1; @@ -93,58 +94,61 @@ class SpookyMansionErectStage extends Stage FlxTween.tween(PlayState.instance.currentStage.getBoyfriend(), {alpha: 1}, 1.5); FlxTween.tween(PlayState.instance.currentStage.getDad(), {alpha: 1}, 1.5); FlxTween.tween(PlayState.instance.currentStage.getGirlfriend(), {alpha: 1}, 1.5); - }); - - lightningStrikeBeat = beat; - lightningStrikeOffset = FlxG.random.int(8, 24); - - if (getBoyfriend() != null) { - getBoyfriend().playAnimation('scared', true, true); - } - - if (getGirlfriend() != null) { - getGirlfriend().playAnimation('scared', true, true); - } - } - - /** - * If your stage uses additional assets not specified in the JSON, - * make sure to specify them like this, or they won't get cached in the loading screen. - */ - function fetchAssetPaths():Array - { - var results:Array = super.fetchAssetPaths(); - results.push(Paths.sound('thunder_1')); - results.push(Paths.sound('thunder_2')); - return results; - } - - function onBeatHit(event:SongTimeScriptEvent) - { - super.onBeatHit(event); - - // Play lightning on sync at the start of this specific song. - // TODO: Rework this after chart format redesign. - if (PlayState.instance.currentSong != null) { - if (event.beat == 4 && PlayState.instance.currentSong.id == "spookeez") - { - doLightningStrike(false, event.beat); - } - } - - // Play lightning at random intervals. - if (FlxG.random.bool(10) && event.beat > (lightningStrikeBeat + lightningStrikeOffset)) - { - doLightningStrike(true, event.beat); - } - } - - function onSongRetry(event:ScriptEvent) - { - super.onSongRetry(event); - - // Properly reset lightning when restarting the song. - lightningStrikeBeat = 0; - lightningStrikeOffset = 8; - } + }); + + lightningStrikeBeat = beat; + lightningStrikeOffset = FlxG.random.int(8, 24); + + if (getBoyfriend() != null) + { + getBoyfriend().playAnimation('scared', true, true); + } + + if (getGirlfriend() != null) + { + getGirlfriend().playAnimation('scared', true, true); + } + } + + /** + * If your stage uses additional assets not specified in the JSON, + * make sure to specify them like this, or they won't get cached in the loading screen. + */ + function fetchAssetPaths():Array + { + var results:Array = super.fetchAssetPaths(); + results.push(Paths.sound('thunder_1')); + results.push(Paths.sound('thunder_2')); + return results; + } + + function onBeatHit(event:SongTimeScriptEvent) + { + super.onBeatHit(event); + + // Play lightning on sync at the start of this specific song. + // TODO: Rework this after chart format redesign. + if (PlayState.instance.currentSong != null) + { + if (event.beat == 4 && PlayState.instance.currentSong.id == "spookeez") + { + doLightningStrike(false, event.beat); + } + } + + // Play lightning at random intervals. + if (FlxG.random.bool(10) && event.beat > (lightningStrikeBeat + lightningStrikeOffset)) + { + doLightningStrike(true, event.beat); + } + } + + function onSongRetry(event:ScriptEvent) + { + super.onSongRetry(event); + + // Properly reset lightning when restarting the song. + lightningStrikeBeat = 0; + lightningStrikeOffset = 8; + } } diff --git a/preload/scripts/stages/tankmanBattlefield.hxc b/preload/scripts/stages/tankmanBattlefield.hxc index 3bdc5838b..f6ee4893e 100644 --- a/preload/scripts/stages/tankmanBattlefield.hxc +++ b/preload/scripts/stages/tankmanBattlefield.hxc @@ -5,67 +5,67 @@ import funkin.play.stage.Stage; class TankmanBattlefieldStage extends Stage { - function new() - { - super('tankmanBattlefield'); - } + function new() + { + super('tankmanBattlefield'); + } - function onCreate(event:ScriptEvent):Void - { - super.onCreate(event); - } + function onCreate(event:ScriptEvent):Void + { + super.onCreate(event); + } - override function buildStage() - { - super.buildStage(); + override function buildStage() + { + super.buildStage(); - // Give the clouds a random position, and a velocity to make them move. - var clouds = getNamedProp('clouds'); - clouds.active = true; - clouds.x = FlxG.random.int(-700, -100); - clouds.y = FlxG.random.int(-20, 20); - clouds.velocity.x = FlxG.random.float(5, 15); + // Give the clouds a random position, and a velocity to make them move. + var clouds = getNamedProp('clouds'); + clouds.active = true; + clouds.x = FlxG.random.int(-700, -100); + clouds.y = FlxG.random.int(-20, 20); + clouds.velocity.x = FlxG.random.float(5, 15); - tankAngle = FlxG.random.int(-90, 45); - tankSpeed = FlxG.random.float(5, 7); - } + tankAngle = FlxG.random.int(-90, 45); + tankSpeed = FlxG.random.float(5, 7); + } - function onUpdate(event:UpdateScriptEvent):Void - { - super.onUpdate(event); - moveTank(event.elapsed); - } + function onUpdate(event:UpdateScriptEvent):Void + { + super.onUpdate(event); + moveTank(event.elapsed); + } - var tankMoving:Bool = false; - var tankAngle:Float = FlxG.random.int(-90, 45); - var tankSpeed:Float = FlxG.random.float(5, 7); - var tankX:Float = 400; + var tankMoving:Bool = false; + var tankAngle:Float = FlxG.random.int(-90, 45); + var tankSpeed:Float = FlxG.random.float(5, 7); + var tankX:Float = 400; - function onBeatHit(event:SongTimeScriptEvent):Void - { - super.onBeatHit(event); - } + function onBeatHit(event:SongTimeScriptEvent):Void + { + super.onBeatHit(event); + } - function moveTank(elapsed:Float):Void - { - var daAngleOffset:Float = 1; - tankAngle += elapsed * tankSpeed; + function moveTank(elapsed:Float):Void + { + var daAngleOffset:Float = 1; + tankAngle += elapsed * tankSpeed; - var tankRolling = getNamedProp('tankRolling'); - tankRolling.angle = tankAngle - 90 + 15; - tankRolling.x = tankX + Math.cos(FlxAngle.asRadians((tankAngle * daAngleOffset) + 180)) * 1500; - tankRolling.y = 1300 + Math.sin(FlxAngle.asRadians((tankAngle * daAngleOffset) + 180)) * 1100; - } + var tankRolling = getNamedProp('tankRolling'); + tankRolling.angle = tankAngle - 90 + 15; + tankRolling.x = tankX + Math.cos(FlxAngle.asRadians((tankAngle * daAngleOffset) + 180)) * 1500; + tankRolling.y = 1300 + Math.sin(FlxAngle.asRadians((tankAngle * daAngleOffset) + 180)) * 1100; + } - function onSongRetry(event:ScriptEvent) - { - super.onSongRetry(event); + function onSongRetry(event:ScriptEvent) + { + super.onSongRetry(event); - // resets the clouds! - var clouds = getNamedProp('clouds'); - clouds.active = true; - clouds.x = FlxG.random.int(-700, -100); - clouds.y = FlxG.random.int(-20, 20); - clouds.velocity.x = FlxG.random.float(5, 15); - } + // resets the clouds! + var clouds = getNamedProp('clouds'); + clouds.active = true; + clouds.x = FlxG.random.int(-700, -100); + clouds.y = FlxG.random.int(-20, 20); + clouds.velocity.x = FlxG.random.float(5, 15); + } }