philly stage

This commit is contained in:
Yoshman29
2022-10-07 18:44:57 +02:00
parent 1e156c83ee
commit 666c7fa7e0
10 changed files with 247 additions and 32 deletions
+23 -3
View File
@@ -1,9 +1,29 @@
var lights:FlxSprite;
var curColor:Int = 0;
var colors = [
0xFF31A2FD,
0xFF31FD8C,
0xFFFB33F5,
0xFFFD4531,
0xFFFBA633
];
function create() {
lights = stage.getSprite("")
light.color = colors[curColor];
}
function beatHit(curBeat:Int) {
if (curBeat % 4 == 0) {
// switches color
var newColor = FlxG.random.int(0, colors.length-2);
if (newColor >= curColor) newColor++;
curColor = newColor;
light.color = colors[curColor];
}
}
function update(elapsed:Float) {
if (Conductor.songPosition > 0)
light.alpha = 1 - (FlxEase.cubeIn((curBeatFloat / 4) % 1) * 0.85);
else
light.alpha = 0;
}
+1 -1
View File
@@ -2,7 +2,7 @@
<stage zoom="1.05" name="spooky" folder="stages/philly/">
<sprite name="bg" x="-100" y="0" sprite="sky" scroll="0.1"/>
<sprite name="city" x="-10" y="0" sprite="city" scroll="0.3" scale="0.85" updateHitbox="true"/>
<sprite name="light" x="-10" y="0" sprite="win0" scroll="0.3" scale="0.85" updateHitbox="true"/>
<sprite name="light" x="-10" y="0" sprite="win" scroll="0.3" scale="0.85" updateHitbox="true"/>
<sprite name="streetBehind" x="-40" y="50" sprite="behindTrain" />
<sprite name="phillyTrain" x="2000" y="360" sprite="train" />
<sprite name="street" x="-40" y="50" sprite="street" />
+1 -1
View File
@@ -1 +1 @@
193
205
+47 -2
View File
@@ -1,10 +1,12 @@
package funkin.game;
import flixel.util.FlxDestroyUtil;
#if desktop
import Discord.DiscordClient;
#end
import Section.SwagSection;
import funkin.system.Song.SwagSong;
import funkin.scripting.ScriptPack;
import WiggleEffect.WiggleEffectType;
import flixel.FlxBasic;
import flixel.FlxCamera;
@@ -62,6 +64,7 @@ class PlayState extends MusicBeatState
public static var storyDifficulty:Int = 1;
public static var fromMods:Bool = false;
public var scripts:ScriptPack;
public var halloweenLevel:Bool = false;
public var stage:Stage;
@@ -134,6 +137,9 @@ class PlayState extends MusicBeatState
if (FlxG.sound.music != null)
FlxG.sound.music.stop();
scripts = new ScriptPack("PlayState");
scripts.setParent(this);
camGame = new FlxCamera();
camHUD = new FlxCamera();
camHUD.bgColor.alpha = 0;
@@ -190,11 +196,15 @@ class PlayState extends MusicBeatState
// TODO: Custom Stage Loading
add(new Stage(SONG.stage));
scripts.load();
scripts.call("create");
add(gf);
add(dad);
add(boyfriend);
strumLine = new FlxSprite(0, 50).makeGraphic(FlxG.width, 10);
strumLine.scrollFactor.set();
@@ -240,6 +250,9 @@ class PlayState extends MusicBeatState
scoreTxt = new FlxText(healthBarBG.x + healthBarBG.width - 190, healthBarBG.y + 30, 0, "", 20);
scoreTxt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT);
scoreTxt.borderStyle = OUTLINE;
scoreTxt.borderSize = 1;
scoreTxt.borderColor = 0xFF000000;
scoreTxt.scrollFactor.set();
add(scoreTxt);
@@ -263,21 +276,25 @@ class PlayState extends MusicBeatState
public override function createPost() {
super.createPost();
startCountdown();
scripts.call("createPost");
}
public var startTimer:FlxTimer;
public var perfectMode:Bool = false;
public var introLength:Int = 5;
function startCountdown():Void
{
inCutscene = false;
generateStaticArrows(0);
generateStaticArrows(1);
scripts.call("onStartCountdown");
startedCountdown = true;
Conductor.songPosition = 0;
Conductor.songPosition -= Conductor.crochet * 5;
Conductor.songPosition -= Conductor.crochet * introLength;
var swagCounter:Int = 0;
@@ -304,6 +321,9 @@ class PlayState extends MusicBeatState
}
}
// TODO: Cancelable countdown
scripts.call("onCountdown", [swagCounter]);
switch (swagCounter)
{
@@ -368,7 +388,7 @@ class PlayState extends MusicBeatState
swagCounter += 1;
// generateSong('fresh');
}, 5);
}, introLength);
}
public var previousFrameTime:Int = 0;
@@ -391,7 +411,9 @@ class PlayState extends MusicBeatState
}
public override function destroy() {
scripts.call("destroy");
super.destroy();
FlxDestroyUtil.destroy(scripts);
instance = null;
}
@@ -603,6 +625,8 @@ class PlayState extends MusicBeatState
override function openSubState(SubState:FlxSubState)
{
// TODO: Cancellable substate opening.
scripts.call("onSubstateOpen", [SubState]);
if (paused)
{
if (FlxG.sound.music != null)
@@ -620,6 +644,7 @@ class PlayState extends MusicBeatState
override function closeSubState()
{
scripts.call("onSubstateClose");
if (paused)
{
if (FlxG.sound.music != null && !startingSong)
@@ -648,6 +673,7 @@ class PlayState extends MusicBeatState
override public function onFocus():Void
{
scripts.call("onFocus");
#if desktop
if (health > 0 && !paused)
{
@@ -667,6 +693,7 @@ class PlayState extends MusicBeatState
override public function onFocusLost():Void
{
scripts.call("onFocusLost");
#if desktop
if (health > 0 && !paused)
{
@@ -685,6 +712,7 @@ class PlayState extends MusicBeatState
Conductor.songPosition = FlxG.sound.music.time;
vocals.time = Conductor.songPosition;
vocals.play();
scripts.call("onVocalsResync");
}
public var paused:Bool = false;
@@ -693,6 +721,8 @@ class PlayState extends MusicBeatState
public function pauseGame() {
// TODO: Cancellable game pause
scripts.call("onGamePause");
persistentUpdate = false;
persistentDraw = true;
paused = true;
@@ -711,6 +741,7 @@ class PlayState extends MusicBeatState
// TODO: Update Discord Status
public function updateDiscordStatus() {
// TODO: Cancellable Discord Update Presence
#if desktop
// Song duration in a float, useful for the time left feature
songLength = FlxG.sound.music.length;
@@ -718,6 +749,7 @@ class PlayState extends MusicBeatState
// Updating Discord Rich Presence (with Time Left)
DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC, true, songLength);
#end
scripts.call("onDiscordPresenceUpdate");
}
override public function update(elapsed:Float)
{
@@ -726,6 +758,7 @@ class PlayState extends MusicBeatState
#end
super.update(elapsed);
scripts.call("update", [elapsed]);
scoreTxt.text = "Score:" + songScore;
@@ -988,6 +1021,7 @@ class PlayState extends MusicBeatState
function endSong():Void
{
scripts.call("onSongEnd");
canPause = false;
FlxG.sound.music.volume = 0;
vocals.volume = 0;
@@ -1223,6 +1257,8 @@ class PlayState extends MusicBeatState
var justPressed = [controls.LEFT_P, controls.DOWN_P, controls.UP_P, controls.RIGHT_P];
var justReleased = [controls.LEFT_R, controls.DOWN_R, controls.UP_R, controls.RIGHT_R];
// TODO: Events like param:OnKeyEvent for better compatibility
scripts.call("onKeyShit", [pressed, justPressed, justReleased]);
var funcsToExec:Array<Note->Void> = [];
if (pressed.contains(true)) {
funcsToExec.push(function(note:Note) {
@@ -1254,6 +1290,7 @@ class PlayState extends MusicBeatState
playerStrums.forEach(function(str:Strum) {
str.updatePlayerInput(pressed[str.ID], justPressed[str.ID], justReleased[str.ID]);
});
scripts.call("onKeyShitPost");
}
function noteMiss(direction:Int = 1):Void
@@ -1300,6 +1337,8 @@ class PlayState extends MusicBeatState
if (!note.wasGoodHit)
{
if (note.mustPress) {
// TODO: See TODO above
scripts.call("onPlayerHit", [note]);
if (!note.isSustainNote)
{
popUpScore(note.strumTime);
@@ -1330,6 +1369,8 @@ class PlayState extends MusicBeatState
}
});
} else {
// TODO: See TODO above the todo above
scripts.call("onDadHit", [note]);
// TODO: NOTE PRESSED HANDLER FOR DAD
switch (note.noteData)
{
@@ -1358,6 +1399,8 @@ class PlayState extends MusicBeatState
}
public function deleteNote(note:Note) {
// TODO: See TODO above the TODO above the one that says TODO note pressed handler for dad
scripts.call("onNoteDelete", [note]);
note.kill();
notes.remove(note, true);
note.destroy();
@@ -1366,6 +1409,7 @@ class PlayState extends MusicBeatState
override function stepHit()
{
super.stepHit();
scripts.call("stepHit", [curStep]);
if (FlxG.sound.music.time > Conductor.songPosition + 20 || FlxG.sound.music.time < Conductor.songPosition - 20)
{
resyncVocals();
@@ -1378,6 +1422,7 @@ class PlayState extends MusicBeatState
override function beatHit()
{
super.beatHit();
scripts.call("beatHit", [curBeat]);
if (SONG.notes[Math.floor(curStep / 16)] != null)
{
+10 -1
View File
@@ -5,9 +5,12 @@ import openfl.utils.Assets;
import haxe.xml.Access;
import flixel.FlxBasic;
import funkin.interfaces.IBeatReceiver;
import funkin.scripting.Script;
import haxe.io.Path;
class Stage extends FlxBasic implements IBeatReceiver {
public var stageXML:Access;
public var stagePath:String;
public var stageSprites:Map<String, FlxSprite> = [];
public var stageScript:Script;
@@ -18,8 +21,9 @@ class Stage extends FlxBasic implements IBeatReceiver {
public function new(stage:String) {
super();
if (PlayState.instance == null) return;
stagePath = Paths.xml('stages/$stage');
try {
stageXML = new Access(Xml.parse(Assets.getText(Paths.xml('stages/$stage'))).firstElement());
stageXML = new Access(Xml.parse(Assets.getText(stagePath)).firstElement());
} catch(e) {
// TODO: handler
trace(e.details());
@@ -98,6 +102,11 @@ class Stage extends FlxBasic implements IBeatReceiver {
PlayState.instance.add(PlayState.instance.dad);
}
}
stageScript = Script.create(Paths.script('data/stages/$stage'));
for(k=>e in stageSprites) {
stageScript.set(k, e);
}
PlayState.instance.scripts.add(stageScript);
}
public function beatHit(curBeat:Int) {}
+3 -4
View File
@@ -33,14 +33,14 @@ class ModsFolder {
public static var modsPath:String = "./mods/";
/**
* [Description] Initialises `mods` folder by adding callbacks and such.
* Initialises `mods` folder by adding callbacks and such.
*/
public static function init() {
FlxG.signals.preStateCreate.add(onStateSwitch);
}
/**
* [Description] Loads a mod with the specified name.
* Loads a mod with the specified name.
* @param modName Name of the mod
* @param force Whenever the mod should be reloaded if it has already been loaded
*/
@@ -74,7 +74,7 @@ class ModsFolder {
}
/**
* [Description] Gets all assets in folders and put them in the `assets` array.
* Gets all assets in folders and put them in the `assets` array.
* @param assets Array of assets
* @param rootPath Root path
* @param path Path inside of the rootPath (ex: `root path/path/path2/`)
@@ -138,7 +138,6 @@ class ModsFolder {
}
private static function onStateSwitch(newState:FlxState) {
// TODO: assets reloading
Assets.cache.clear();
if (currentModFolder == null) return;
+6 -2
View File
@@ -6,6 +6,8 @@ import hscript.*;
class HScript extends Script {
var interp:Interp;
var expr:Expr;
public override function onCreate(path:String) {
super.onCreate(path);
@@ -14,14 +16,12 @@ class HScript extends Script {
var code:String = Assets.getText(path);
var parser = new hscript.Parser();
parser.allowJSON = parser.allowMetadata = parser.allowTypes = true;
var expr:Expr;
try {
expr = parser.parseString(code, fileName);
} catch(e) {
return;
}
interp.errorHandler = _errorHandler;
interp.execute(expr);
}
private function _errorHandler(error:Error) {
@@ -32,6 +32,10 @@ class HScript extends Script {
interp.scriptObject = parent;
}
public override function onLoad() {
interp.execute(expr);
}
private override function onCall(funcName:String, parameters:Array<Dynamic>):Dynamic {
if (interp == null) return null;
+94 -17
View File
@@ -1,31 +1,91 @@
package funkin.scripting;
import flixel.util.FlxDestroyUtil.IFlxDestroyable;
import flixel.FlxBasic;
import haxe.io.Path;
import openfl.utils.Assets;
/**
* Class used for scripting.
*/
class Script {
class Script extends FlxBasic implements IFlxDestroyable {
public static function getDefaultVariables():Map<String, Dynamic> {
return [
// Haxe related stuff
"Std" => Std,
"Math" => Math,
"StringTools" => StringTools,
"Json" => haxe.Json,
// OpenFL & Lime related stuff
"Assets" => openfl.utils.Assets,
"Application" => lime.app.Application,
"window" => lime.app.Application.current.window,
// Flixel related stuff
"FlxG" => flixel.FlxG,
"FlxSprite" => flixel.FlxSprite,
"FlxEase" => flixel.tweens.FlxEase,
"FlxTween" => flixel.tweens.FlxTween,
"FlxCamera" => flixel.FlxCamera,
"state" => flixel.FlxG.state,
"FlxSound" => flixel.system.FlxSound,
"FlxAssets" => flixel.system.FlxAssets,
"FlxMath" => flixel.math.FlxMath,
"FlxPoint" => flixel.math.FlxPoint,
"FlxGroup" => flixel.group.FlxGroup,
"FlxTypedGroup" => flixel.group.FlxGroup.FlxTypedGroup,
"FlxSpriteGroup" => flixel.group.FlxSpriteGroup,
"FlxTypeText" => flixel.addons.text.FlxTypeText,
"FlxText" => flixel.text.FlxText,
"FlxAxes" => flixel.util.FlxAxes,
"FlxTimer" => flixel.util.FlxTimer,
// Engine related stuff
"engine" => {
build: funkin.macros.BuildCounterMacro.getBuildNumber(),
name: "Codename Engine"
},
"PlayState" => funkin.game.PlayState,
"GameOverSubstate" => funkin.game.GameOverSubstate,
"Note" => funkin.game.Note,
"Strum" => funkin.game.Strum,
"Character" => funkin.game.Character,
"Boyfriend" => funkin.game.Character, // for compatibility
"FreeplayState" => funkin.menus.FreeplayState,
"MainMenuState" => funkin.menus.MainMenuState,
"PauseSubState" => funkin.menus.PauseSubState,
"StoryMenuState" => funkin.menus.StoryMenuState,
"TitleState" => funkin.menus.TitleState,
"Paths" => funkin.system.Paths,
"Conductor" => funkin.system.Conductor,
"CoolUtil" => funkin.system.CoolUtil,
];
}
/**
* [Description] All available script extensions
* All available script extensions
*/
public static var scriptExtensions:Array<String> = [
"hx", "hscript", "hsc"
];
/**
* [Description] Currently executing script.
* Currently executing script.
*/
public static var curScript:Script = null;
/**
* [Description] Script name (with extension)
* Script name (with extension)
*/
public var fileName:String;
/**
* [Description] Creates a script from the specified asset path. The language is automatically determined.
* Path to the script.
*/
public var path:String = null;
/**
* Creates a script from the specified asset path. The language is automatically determined.
* @param path Path in assets
*/
public static function create(path:String):Script {
@@ -41,26 +101,33 @@ class Script {
}
/**
* [Description] Creates a new instance of the script class.
* Creates a new instance of the script class.
* @param path
*/
public function new(path:String) {
super();
fileName = Path.withoutDirectory(path);
var oldScript = curScript;
curScript = this;
this.path = path;
onCreate(path);
curScript = oldScript;
for(k=>e in getDefaultVariables()) {
set(k, e);
}
}
/**
* [Description] Internal. Creates the script.
* @param path Path to the script.
* Loads the script
*/
public function onCreate(path:String) {}
public function load() {
var oldScript = curScript;
curScript = this;
onLoad();
curScript = oldScript;
}
/**
* [Description] Calls the function `func` defined in the script.
* Calls the function `func` defined in the script.
* @param func Name of the function
* @param parameters (Optional) Parameters of the function.
* @return Dynamic Result (if void, then null)
@@ -76,27 +143,27 @@ class Script {
}
/**
* [Description] Sets a script's parent object so that its properties can be accessed easily. Ex: Passing `PlayState.instace` will allow `boyfriend` to be typed instead of `PlayState.instance.boyfriend`.
* Sets a script's parent object so that its properties can be accessed easily. Ex: Passing `PlayState.instace` will allow `boyfriend` to be typed instead of `PlayState.instance.boyfriend`.
* @param variable Parent variable.
*/
public function setParent(variable:Dynamic) {}
/**
* [Description] Gets the variable `variable` from the script's variables.
* Gets the variable `variable` from the script's variables.
* @param variable Name of the variable.
* @return Dynamic Variable (or null if it doesn't exists)
*/
public function get(variable:String):Dynamic {return null;}
/**
* [Description] Gets the variable `variable` from the script's variables.
* Gets the variable `variable` from the script's variables.
* @param variable Name of the variable.
* @return Dynamic Variable (or null if it doesn't exists)
*/
public function set(variable:String, value:Dynamic):Void {}
/**
* [Description] Shows an error from this script.
* Shows an error from this script.
* @param text Text of the error (ex: Null Object Reference).
* @param additionalInfo Additional information you could provide.
*/
@@ -111,4 +178,14 @@ class Script {
private function onCall(func:String, parameters:Array<Dynamic>):Dynamic {
return null;
}
public function onCreate(path:String) {}
public function onLoad() {}
public function onDestroy() {};
public override function destroy() {
super.destroy();
onDestroy();
}
}
+61
View File
@@ -0,0 +1,61 @@
package funkin.scripting;
class ScriptPack extends Script {
public var scripts:Array<Script> = [];
public var additionalDefaultVariables:Map<String, Dynamic> = [];
public var parent:Dynamic = null;
public override function load() {
for(e in scripts) {
e.load();
}
}
public override function call(func:String, ?parameters:Array<Dynamic>):Dynamic {
for(e in scripts)
e.call(func, parameters);
return null;
}
public override function get(val:String):Dynamic {
for(e in scripts) {
var v = e.get(val);
if (v != null) return v;
}
return null;
}
public override function set(val:String, value:Dynamic) {
for(e in scripts) e.set(val, value);
}
public override function setParent(parent:Dynamic) {
this.parent = parent;
for(e in scripts) e.setParent(parent);
}
public override function onDestroy() {
for(e in scripts) e.destroy();
}
public override function onCreate(path:String) {}
public function add(script:Script) {
scripts.push(script);
__configureNewScript(script);
}
public function remove(script:Script) {
scripts.remove(script);
}
public function insert(pos:Int, script:Script) {
scripts.insert(pos, script);
__configureNewScript(script);
}
private function __configureNewScript(script:Script) {
if (parent != null) script.setParent(parent);
for(k=>e in additionalDefaultVariables) script.set(k, e);
}
}
+1 -1
View File
@@ -47,7 +47,7 @@ class MusicBeatState extends FlxUIState
private function updateBeat():Void
{
curBeat = Math.floor(curBeatFloat = (curStep / 4));
curBeat = Math.floor(curBeatFloat = (curStepFloat / 4));
}
private function updateCurStep():Void