diff --git a/assets/data/weeks.xml b/assets/data/weeks.xml
index bbae5b33..bf90f983 100644
--- a/assets/data/weeks.xml
+++ b/assets/data/weeks.xml
@@ -2,19 +2,19 @@
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -61,5 +61,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/menus/storymenu/characters/spooky.png b/assets/images/menus/storymenu/characters/spooky.png
index 7bd966dd..e4eb1b65 100644
Binary files a/assets/images/menus/storymenu/characters/spooky.png and b/assets/images/menus/storymenu/characters/spooky.png differ
diff --git a/buildnumber.txt b/buildnumber.txt
index 318d1517..0a678c62 100644
--- a/buildnumber.txt
+++ b/buildnumber.txt
@@ -1 +1 @@
-1055
\ No newline at end of file
+1081
\ No newline at end of file
diff --git a/source/funkin/menus/StoryMenuState.hx b/source/funkin/menus/StoryMenuState.hx
index 5b80d362..3bd13ccf 100644
--- a/source/funkin/menus/StoryMenuState.hx
+++ b/source/funkin/menus/StoryMenuState.hx
@@ -1,5 +1,6 @@
package funkin.menus;
+import flixel.math.FlxPoint;
import funkin.system.XMLUtil;
import flixel.graphics.frames.FlxFramesCollection;
import flixel.group.FlxGroup.FlxTypedGroup;
@@ -93,6 +94,11 @@ class StoryMenuState extends MusicBeatState {
e.scrollFactor.set();
add(e);
}
+
+ characterSprites = new FlxTypedGroup();
+ for(i in 0...3) {
+ characterSprites.add(new MenuCharacterSprite(i));
+ }
add(characterSprites);
for(i=>week in weeks) {
@@ -143,11 +149,27 @@ class StoryMenuState extends MusicBeatState {
}
}
+ public function changeWeek(change:Int, force:Bool = false) {
+ if (change == 0 && !force) return;
+
+ curWeek = FlxMath.wrap(curWeek + change, 0, weeks.length-1);
+
+ if (!force) CoolUtil.playMenuSFX();
+ for(k=>e in weekSprites.members) {
+ e.targetY = k - curWeek;
+ }
+ tracklist.text = 'TRACKS\n\n${[for(e in weeks[curWeek].songs) if (!e.hide) e.name.toUpperCase()].join('\n')}';
+
+ for(i in 0...3)
+ characterSprites.members[i].changeCharacter(characters[weeks[curWeek].chars[i]]);
+
+ changeDifficulty(0, true);
+ }
+
var __oldDiffName = null;
public function changeDifficulty(change:Int, force:Bool = false) {
if (change == 0 && !force) return;
- CoolUtil.playMenuSFX(0, 0.7);
curDifficulty = FlxMath.wrap(curDifficulty + change, 0, weeks[curWeek].difficulties.length-1);
if (__oldDiffName != (__oldDiffName = weeks[curWeek].difficulties[curDifficulty].toLowerCase())) {
@@ -169,23 +191,17 @@ class StoryMenuState extends MusicBeatState {
}
}
- public function changeWeek(change:Int, force:Bool = false) {
- if (change == 0 && !force) return;
-
- curWeek = FlxMath.wrap(curWeek + change, 0, weeks.length-1);
-
- CoolUtil.playMenuSFX();
- for(k=>e in weekSprites.members) {
- e.targetY = k - curWeek;
- }
- tracklist.text = 'TRACKS\n\n${[for(e in weeks[curWeek].songs) if (!e.hide) e.name.toUpperCase()].join('\n')}';
- changeDifficulty(0, true);
- }
-
public function loadXMLs() {
loadXML(Paths.xml('weeks'));
}
+ public override function destroy() {
+ super.destroy();
+ for(e in characters)
+ if (e != null && e.offset != null)
+ e.offset.put();
+ }
+
public function loadXML(xmlPath:String) {
try {
var xml = new Access(Xml.parse(Assets.getText(xmlPath)).firstElement());
@@ -202,7 +218,11 @@ class StoryMenuState extends MusicBeatState {
var charObj:MenuCharacter = {
spritePath: Paths.image(char.getAtt('sprite').getDefault('menus/storymenu/characters/${char.att.name}')),
scale: Std.parseFloat(char.getAtt('scale')).getDefault(1),
- xml: char
+ xml: char,
+ offset: FlxPoint.get(
+ Std.parseFloat(char.getAtt('x')).getDefault(0),
+ Std.parseFloat(char.getAtt('y')).getDefault(0)
+ )
};
characters[char.att.name] = charObj;
}
@@ -279,6 +299,7 @@ typedef MenuCharacter = {
var spritePath:String;
var xml:Access;
var scale:Float;
+ var offset:FlxPoint;
// var frames:FlxFramesCollection;
}
@@ -286,14 +307,38 @@ class MenuCharacterSprite extends FlxSprite
{
public var character:String;
- public function new(pos:Int, path:String) {
- super(FlxG.width * (0.25 * pos), 80);
+ var pos:Int;
+
+ public function new(pos:Int) {
+ super(0, 70);
+ this.pos = pos;
+ visible = false;
+ antialiasing = true;
}
+ public var oldChar:MenuCharacter = null;
+
public function changeCharacter(data:MenuCharacter) {
- CoolUtil.loadAnimatedGraphic(this, Paths.image(data.spritePath));
- for(e in data.xml.nodes.anim)
- XMLUtil.addXMLAnimation(this, e);
+ visible = (data != null);
+ if (!visible)
+ return;
+
+ if (oldChar != (oldChar = data)) {
+ CoolUtil.loadAnimatedGraphic(this, data.spritePath);
+ for(e in data.xml.nodes.anim) {
+ if (e.getAtt("name") == "idle")
+ animation.remove("idle");
+
+ XMLUtil.addXMLAnimation(this, e);
+ }
+ animation.play("idle");
+ scale.set(data.scale, data.scale);
+ updateHitbox();
+ offset.x += data.offset.x;
+ offset.y += data.offset.y;
+
+ x = (FlxG.width * 0.25) * (1 + pos) - 150;
+ }
}
}
class MenuItem extends FlxSprite
diff --git a/source/funkin/system/CoolUtil.hx b/source/funkin/system/CoolUtil.hx
index c639ba84..72f2f801 100644
--- a/source/funkin/system/CoolUtil.hx
+++ b/source/funkin/system/CoolUtil.hx
@@ -31,7 +31,13 @@ class CoolUtil
* @return The return value
*/
public static function getDefault(v:T, defaultValue:T):T {
- return v == null ? defaultValue : v;
+ return (v == null || isNaN(v)) ? defaultValue : v;
+ }
+
+ public static function isNaN(v:Dynamic) {
+ if (v is Float || v is Int)
+ return Math.isNaN(cast(v, Float));
+ return false;
}
public static function setFieldDefault(v:Dynamic, name:String, defaultValue:T):T {
@@ -254,7 +260,9 @@ class CoolUtil
public static function loadAnimatedGraphic(spr:FlxSprite, path:String) {
spr.frames = loadFrames(path);
- spr.animation.add("idle", [for(i in 0...spr.frames.frames.length) i], 24, true);
- spr.animation.play("idle");
+ if (spr.frames != null && spr.frames.frames != null) {
+ spr.animation.add("idle", [for(i in 0...spr.frames.frames.length) i], 24, true);
+ spr.animation.play("idle");
+ }
}
}
\ No newline at end of file
diff --git a/source/funkin/system/XMLUtil.hx b/source/funkin/system/XMLUtil.hx
index 24ea0f16..672fa46b 100644
--- a/source/funkin/system/XMLUtil.hx
+++ b/source/funkin/system/XMLUtil.hx
@@ -44,12 +44,12 @@ class XMLUtil {
* @param sprite Destination sprite
* @param anim Animation (Must be a `anim` XML node)
*/
- public static function addXMLAnimation(sprite:FlxSprite, anim:Access):ErrorCode {
+ public static function addXMLAnimation(sprite:FlxSprite, anim:Access, loop:Bool = false):ErrorCode {
var animData:AnimData = {
name: null,
anim: null,
fps: 24,
- loop: false,
+ loop: loop,
x: 0,
y: 0,
indices: []
@@ -60,6 +60,7 @@ class XMLUtil {
if (anim.has.fps) animData.fps = Std.parseInt(anim.att.fps);
if (anim.has.x) animData.x = Std.parseFloat(anim.att.x);
if (anim.has.y) animData.y = Std.parseFloat(anim.att.y);
+ if (anim.has.loop) animData.loop = anim.att.loop == "true";
if (anim.has.indices) {
var indicesSplit = anim.att.indices.split(",");
for(indice in indicesSplit) {