diff --git a/assets/data/characters/bf-car.xml b/assets/data/characters/bf-car.xml
index bb7db17e..65d5adc5 100644
--- a/assets/data/characters/bf-car.xml
+++ b/assets/data/characters/bf-car.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/assets/data/characters/gf-car.xml b/assets/data/characters/gf-car.xml
index b4de4984..0afe78ed 100644
--- a/assets/data/characters/gf-car.xml
+++ b/assets/data/characters/gf-car.xml
@@ -1,23 +1,5 @@
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/assets/data/characters/gf.xml b/assets/data/characters/gf.xml
index dcb655cf..38a24f75 100644
--- a/assets/data/characters/gf.xml
+++ b/assets/data/characters/gf.xml
@@ -12,7 +12,9 @@
-
-
+
@@ -30,13 +30,10 @@
+
+
+
-
-
-
-
-
-
\ No newline at end of file
diff --git a/assets/data/stages/mall.xml b/assets/data/stages/mall.xml
new file mode 100644
index 00000000..24601ec0
--- /dev/null
+++ b/assets/data/stages/mall.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/buildnumber.txt b/buildnumber.txt
index df689d84..06690d5e 100644
--- a/buildnumber.txt
+++ b/buildnumber.txt
@@ -1 +1 @@
-234
\ No newline at end of file
+238
\ No newline at end of file
diff --git a/source/ChartingState.hx b/source/ChartingState.hx
index 147824ee..dd9417ef 100644
--- a/source/ChartingState.hx
+++ b/source/ChartingState.hx
@@ -126,7 +126,8 @@ class ChartingState extends MusicBeatState
player2: 'dad',
speed: 1,
validScore: false,
- stage: 'stage'
+ stage: 'stage',
+ gf: 'gf'
};
}
diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx
index 3e653c86..bcac0ba4 100644
--- a/source/funkin/game/PlayState.hx
+++ b/source/funkin/game/PlayState.hx
@@ -184,9 +184,9 @@ class PlayState extends MusicBeatState
DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC);
#end
-
- // TODO: Chart GF version
- gf = new Character(400, 130, "gf");
+ var gfVersion = SONG.gf;
+ if (gfVersion == null) gfVersion = "gf";
+ gf = new Character(400, 130, gfVersion);
gf.scrollFactor.set(0.95, 0.95);
dad = new Character(100, 100, SONG.player2);
diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx
index 41338be5..6306ccf4 100644
--- a/source/funkin/game/Stage.hx
+++ b/source/funkin/game/Stage.hx
@@ -50,11 +50,14 @@ class Stage extends FlxBasic implements IBeatReceiver {
case "sprite" | "spr" | "sparrow":
var spr = new StageSprite();
spr.antialiasing = true;
+
+ var addDefAnim = true;
if (!node.has.sprite || !node.has.name || !node.has.x || !node.has.y) continue;
if (Assets.exists(Paths.file('images/$spritesParentFolder${node.att.sprite}.xml', TEXT))) {
spr.frames = Paths.getSparrowAtlas('$spritesParentFolder${node.att.sprite}');
} else {
+ addDefAnim = false;
spr.loadGraphic(Paths.image('$spritesParentFolder${node.att.sprite}'));
}
var x:Null = Std.parseFloat(node.att.x);
@@ -72,46 +75,32 @@ class Stage extends FlxBasic implements IBeatReceiver {
if (node.has.updateHitbox && node.att.updateHitbox == "true") spr.updateHitbox();
for(anim in node.nodes.anim) {
+ addDefAnim = false;
if (anim.has.name) spr.beatAnims.push(anim.att.name);
XMLUtil.addXMLAnimation(spr, anim);
}
if (node.has.beatAnim && node.att.beatAnim.trim() != "") spr.beatAnims = [for(e in node.att.beatAnim.split(",")) e.trim()];
+ if (node.has.anim) {
+ spr.animation.play(node.att.anim);
+ } else if (addDefAnim) {
+ spr.animation.addByPrefix("anim", "", 24, true);
+ spr.animation.play("anim");
+ }
stageSprites.set(node.att.name, spr);
PlayState.instance.add(spr);
spr;
case "boyfriend" | "bf":
- if (node.has.x) {
- var x:Null = Std.parseFloat(node.att.x);
- if (x != null) PlayState.instance.boyfriend.x = x;
- }
- if (node.has.y) {
- var y:Null = Std.parseFloat(node.att.y);
- if (y != null) PlayState.instance.boyfriend.y = y;
- }
+ doCharNodeShit(PlayState.instance.boyfriend, node);
PlayState.instance.add(PlayState.instance.boyfriend);
PlayState.instance.boyfriend;
case "girlfriend" | "gf":
- if (node.has.x) {
- var x:Null = Std.parseFloat(node.att.x);
- if (x != null) PlayState.instance.gf.x = x;
- }
- if (node.has.y) {
- var y:Null = Std.parseFloat(node.att.y);
- if (y != null) PlayState.instance.gf.y = y;
- }
+ doCharNodeShit(PlayState.instance.gf, node);
PlayState.instance.add(PlayState.instance.gf);
PlayState.instance.gf;
case "dad" | "opponent":
- if (node.has.x) {
- var x:Null = Std.parseFloat(node.att.x);
- if (x != null) PlayState.instance.dad.x = x;
- }
- if (node.has.y) {
- var y:Null = Std.parseFloat(node.att.y);
- if (y != null) PlayState.instance.dad.y = y;
- }
+ doCharNodeShit(PlayState.instance.dad, node);
PlayState.instance.add(PlayState.instance.dad);
PlayState.instance.dad;
default: null;
@@ -129,6 +118,26 @@ class Stage extends FlxBasic implements IBeatReceiver {
}
PlayState.instance.scripts.add(stageScript);
}
+
+
+ private static function doCharNodeShit(char:Character, node:Access) {
+ if (node.has.x) {
+ var x:Null = Std.parseFloat(node.att.x);
+ if (x != null) char.x = x;
+ }
+ if (node.has.y) {
+ var y:Null = Std.parseFloat(node.att.y);
+ if (y != null) char.y = y;
+ }
+ if (node.has.camxoffset) {
+ var x:Null = Std.parseFloat(node.att.camxoffset);
+ if (x != null) char.cameraOffset.x += x;
+ }
+ if (node.has.camyoffset) {
+ var y:Null = Std.parseFloat(node.att.camyoffset);
+ if (y != null) char.cameraOffset.y += y;
+ }
+ }
public function beatHit(curBeat:Int) {}
diff --git a/source/funkin/system/Song.hx b/source/funkin/system/Song.hx
index d72d5c25..094f7587 100644
--- a/source/funkin/system/Song.hx
+++ b/source/funkin/system/Song.hx
@@ -18,6 +18,7 @@ typedef SwagSong =
var player1:String;
var player2:String;
+ var gf:String;
var validScore:Bool;
}
diff --git a/source/funkin/system/XMLUtil.hx b/source/funkin/system/XMLUtil.hx
index 0efcf2fb..e2c212bc 100644
--- a/source/funkin/system/XMLUtil.hx
+++ b/source/funkin/system/XMLUtil.hx
@@ -23,7 +23,7 @@ class XMLUtil {
var value:Dynamic = switch(property.att.type.toLowerCase()) {
case "float" | "number": Std.parseFloat(property.att.value);
- case "int" | "integer": Std.parseInt(property.att.value);
+ case "int" | "integer" | "color": Std.parseInt(property.att.value);
case "string" | "str" | "text": property.att.value;
case "bool" | "boolean": property.att.value.toLowerCase() == "true";
default: return TYPE_INCORRECT;