diff --git a/assets/preload/sounds/nothing.ogg b/assets/preload/sounds/nothing.ogg
deleted file mode 100644
index 9c92313..0000000
Binary files a/assets/preload/sounds/nothing.ogg and /dev/null differ
diff --git a/mods/skins/characterSelect.json b/mods/global characters/characterSelect.json
similarity index 100%
rename from mods/skins/characterSelect.json
rename to mods/global characters/characterSelect.json
diff --git a/mods/skins/readme.txt b/mods/global characters/readme.txt
similarity index 100%
rename from mods/skins/readme.txt
rename to mods/global characters/readme.txt
diff --git a/mods/test/Icon.png b/mods/test/Icon.png
index 47604f8..870f8c0 100644
Binary files a/mods/test/Icon.png and b/mods/test/Icon.png differ
diff --git a/mods/test/data/characterSelect.json b/mods/test/data/characterSelect.json
index 8124509..48cc447 100644
--- a/mods/test/data/characterSelect.json
+++ b/mods/test/data/characterSelect.json
@@ -3,10 +3,10 @@
{
"newCharacter": [
{
- "playername": "bf-pixel",
- "thecharactername": "Test",
+ "playername": "Example",
+ "thecharactername": "Example",
"thenotems": [1, 1, 1, 1],
- "notestyle": ""
+ "notestyle": "3D"
}
],
"mainName": "testtwo",
diff --git a/mods/test/data/characters/Example.json b/mods/test/data/characters/Example.json
new file mode 100644
index 0000000..aa2e21c
--- /dev/null
+++ b/mods/test/data/characters/Example.json
@@ -0,0 +1,49 @@
+{
+ "animations": [
+ {
+ "animName": "idle",
+ "anim": "idle",
+ "fps": 24,
+ "loop": true
+ },
+ {
+ "animName": "singUP",
+ "anim": "up",
+ "fps": 24,
+ "loop": false
+
+ },
+ {
+ "animName": "singLEFT",
+ "anim": "left",
+ "fps": 24,
+ "loop": false
+
+ },
+ {
+ "animName": "singRIGHT",
+ "anim": "right",
+ "fps": 24,
+ "loop": false
+ },
+ {
+ "animName": "singDOWN",
+ "anim": "down",
+ "fps": 24,
+ "loop": false
+ }
+ ],
+ "globalOffset": [-480, -700],
+ "isPlayable": false,
+ "skins": [],
+ "barcolor": {
+ "red": 0,
+ "green": 215,
+ "blue": 0
+ },
+ "antialiasing": true,
+ "nativelyPlayable": true,
+ "flipX": true,
+ "updateHitbox": true,
+ "setGraphicSize": ""
+}
diff --git a/mods/test/images/characters/Example.png b/mods/test/images/characters/Example.png
new file mode 100644
index 0000000..fe60809
Binary files /dev/null and b/mods/test/images/characters/Example.png differ
diff --git a/mods/test/images/characters/Example.xml b/mods/test/images/characters/Example.xml
new file mode 100644
index 0000000..b1b24b4
--- /dev/null
+++ b/mods/test/images/characters/Example.xml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mods/test/images/icons/Example.png b/mods/test/images/icons/Example.png
new file mode 100644
index 0000000..dfc4fc7
Binary files /dev/null and b/mods/test/images/icons/Example.png differ
diff --git a/mods/test/offsets/Example.txt b/mods/test/offsets/Example.txt
new file mode 100644
index 0000000..c95ca27
--- /dev/null
+++ b/mods/test/offsets/Example.txt
@@ -0,0 +1,5 @@
+idle 0 0
+singUP 0 0
+singRIGHT 0 0
+singLEFT 0 0
+singDOWN 0 0
\ No newline at end of file
diff --git a/source/Character.hx b/source/Character.hx
index b3cd89e..943503c 100644
--- a/source/Character.hx
+++ b/source/Character.hx
@@ -1,6 +1,7 @@
package;
import sys.FileSystem;
+import sys.io.File;
import flixel.math.FlxPoint;
import flixel.util.FlxColor;
import flixel.addons.effects.chainable.FlxEffectSprite;
@@ -9,9 +10,45 @@ import flixel.FlxSprite;
import flixel.animation.FlxBaseAnimation;
import flixel.graphics.frames.FlxAtlasFrames;
import haxe.Json;
+import haxe.format.JsonParser;
using StringTools;
+typedef CharacterFile =
+{
+ var animations:Array;
+ var globalOffset:Array;
+ var isPlayable:Bool;
+ var skins:Array;
+ var barcolor:RGB;
+ var antialiasing:Bool;
+ var nativelyPlayable:Bool;
+ var flipX:Bool;
+ var updateHitbox:Bool;
+ var setGraphicSize:String;
+}
+
+typedef Anim =
+{
+ var animName:String;
+ var anim:String;
+ var fps:Int;
+ var loop:Bool;
+}
+
+typedef SkinSet =
+{
+ var type:String;
+ var replacement:String;
+}
+
+typedef RGB =
+{
+ var red:Int;
+ var green:Int;
+ var blue:Int;
+}
+
class Character extends FlxSprite
{
public var animOffsets:Map>;
@@ -33,6 +70,8 @@ class Character extends FlxSprite
public var canSing:Bool = true;
public var skins:Map = new Map();
+ public var rawJsonCustom:String;
+ public var jsonCustom:CharacterFile;
public function new(x:Float, y:Float, ?character:String = "bf", ?isPlayer:Bool = false)
{
@@ -1144,6 +1183,135 @@ class Character extends FlxSprite
loadOffsetFile(curCharacter);
playAnim('firstDeath');
+
+ default:
+ if (FileSystem.exists(TitleState.modFolder + '/data/characters/${curCharacter}.json')) {
+
+ rawJsonCustom = File.getContent((TitleState.modFolder + '/data/characters/${curCharacter}.json'));
+ jsonCustom = cast Json.parse(rawJsonCustom);
+
+ frames = Paths.getCustomSparrowAtlas(TitleState.modFolder + '/images/characters/' + curCharacter);
+
+ for (i in jsonCustom.animations) {
+ animation.addByPrefix(i.animName, i.anim, i.fps, i.loop);
+ }
+
+ if (!jsonCustom.isPlayable) {
+ loadCustomOffsetFile(curCharacter);
+ } else {
+ loadCustomOffsetFile(curCharacter + (isPlayer ? '-playable' : ''));
+ }
+
+ globalOffset = jsonCustom.globalOffset;
+
+ for (i in jsonCustom.skins) {
+ skins.set(i.type, i.replacement);
+ }
+
+ barColor = FlxColor.fromRGB(jsonCustom.barcolor.red, jsonCustom.barcolor.green, jsonCustom.barcolor.blue);
+
+ if (jsonCustom.setGraphicSize != '')
+ {
+ var thing = jsonCustom.setGraphicSize;
+ setGraphicSize(Std.int(width * Reflect.field(PlayState, thing)));
+ }
+
+ if (jsonCustom.updateHitbox)
+ {
+ updateHitbox();
+ }
+
+ nativelyPlayable = jsonCustom.nativelyPlayable;
+
+ antialiasing = jsonCustom.antialiasing;
+
+
+
+ flipX = jsonCustom.flipX;
+
+ playAnim('idle');
+ } else if (FileSystem.exists('mods/global characters/characters/${curCharacter}.json')) {
+
+ rawJsonCustom = File.getContent(('mods/global characters/characters/${curCharacter}.json'));
+ jsonCustom = cast Json.parse(rawJsonCustom);
+
+ frames = Paths.getCustomSparrowAtlas('mods/global characters/images/' + curCharacter);
+
+ for (i in jsonCustom.animations) {
+ animation.addByPrefix(i.animName, i.anim, i.fps, i.loop);
+ }
+
+ if (!jsonCustom.isPlayable) {
+ loadCustomOffsetFile(curCharacter);
+ } else {
+ loadCustomOffsetFile(curCharacter + (isPlayer ? '-playable' : ''));
+ }
+
+ globalOffset = jsonCustom.globalOffset;
+
+ for (i in jsonCustom.skins) {
+ skins.set(i.type, i.replacement);
+ }
+
+ barColor = FlxColor.fromRGB(jsonCustom.barcolor.red, jsonCustom.barcolor.green, jsonCustom.barcolor.blue);
+
+ if (jsonCustom.setGraphicSize != '')
+ {
+ var thing = jsonCustom.setGraphicSize;
+ setGraphicSize(Std.int(width * Reflect.field(PlayState, thing)));
+ }
+
+ if (jsonCustom.updateHitbox)
+ {
+ updateHitbox();
+ }
+
+ nativelyPlayable = jsonCustom.nativelyPlayable;
+
+ antialiasing = jsonCustom.antialiasing;
+
+
+
+ flipX = jsonCustom.flipX;
+
+ playAnim('idle');
+
+ } else {
+
+ frames = Paths.getSparrowAtlas('characters/BOYFRIEND', 'shared');
+
+ animation.addByPrefix('idle', 'BF idle dance', 24, false);
+ animation.addByPrefix('singUP', 'BF NOTE UP0', 24, false);
+ animation.addByPrefix('singLEFT', 'BF NOTE LEFT0', 24, false);
+ animation.addByPrefix('singRIGHT', 'BF NOTE RIGHT0', 24, false);
+ animation.addByPrefix('singDOWN', 'BF NOTE DOWN0', 24, false);
+ animation.addByPrefix('singUPmiss', 'BF NOTE UP MISS', 24, false);
+ animation.addByPrefix('singLEFTmiss', 'BF NOTE LEFT MISS', 24, false);
+ animation.addByPrefix('singRIGHTmiss', 'BF NOTE RIGHT MISS', 24, false);
+ animation.addByPrefix('singDOWNmiss', 'BF NOTE DOWN MISS', 24, false);
+ animation.addByPrefix('hey', 'BF HEY', 24, false);
+
+ animation.addByPrefix('firstDeath', "BF dies", 24, false);
+ animation.addByPrefix('deathLoop', "BF Dead Loop", 24, true);
+ animation.addByPrefix('deathConfirm', "BF Dead confirm", 24, false);
+ animation.addByPrefix('dodge', "boyfriend dodge", 24, false);
+ animation.addByPrefix('scared', 'BF idle shaking', 24);
+ animation.addByPrefix('hit', 'BF hit', 24, false);
+
+ loadOffsetFile('bf');
+
+ skins.set('gfSkin', 'gf');
+ skins.set('3d', 'bf-3d');
+
+ barColor = FlxColor.fromRGB(49, 176, 209);
+
+
+ playAnim('idle');
+
+ nativelyPlayable = true;
+
+ flipX = true;
+ }
}
dance();
@@ -1165,6 +1333,17 @@ class Character extends FlxSprite
}
}
+ function loadCustomOffsetFile(character:String)
+ {
+ var offsetStuffs:Array = CoolUtil.coolTextFile(TitleState.modFolder + '/offsets/' + character + '.txt');
+
+ for (offsetText in offsetStuffs)
+ {
+ var offsetInfo:Array = offsetText.split(' ');
+
+ addOffset(offsetInfo[0], Std.parseFloat(offsetInfo[1]), Std.parseFloat(offsetInfo[2]));
+ }
+ }
override function update(elapsed:Float)
{
if (animation == null)
diff --git a/source/CharacterSelectState.hx b/source/CharacterSelectState.hx
index 0509c57..224c96d 100644
--- a/source/CharacterSelectState.hx
+++ b/source/CharacterSelectState.hx
@@ -174,7 +174,7 @@ class CharacterSelectState extends MusicBeatState
}
rawJson = File.getContent(Paths.json('characterSelect'));
json = cast Json.parse(rawJson);
- rawJsonCustom = File.getContent(('mods/skins/characterSelect.json'));
+ rawJsonCustom = File.getContent(('mods/global characters/characterSelect.json'));
jsonCustom = cast Json.parse(rawJsonCustom);
if (FileSystem.exists(TitleState.modFolder + '/data/characterSelect.json')) {
rawJsonCustom2 = File.getContent((TitleState.modFolder + '/data/characterSelect.json'));
@@ -194,7 +194,7 @@ class CharacterSelectState extends MusicBeatState
characters.push(new CharacterInSelect(mainName, thehotemsithink, newCharacterForms));
}
- if (FileSystem.exists('mods/skins/characterSelect.json')) {
+ if (FileSystem.exists('mods/global characters/characterSelect.json')) {
for (character in jsonCustom.characters) { // For Globle Characters
var mainName:String = character.mainName;
var thehotemsithink:Array = character.mainnotems;
diff --git a/source/CreditsPopUp.hx b/source/CreditsPopUp.hx
index c16aa89..bfdbfea 100644
--- a/source/CreditsPopUp.hx
+++ b/source/CreditsPopUp.hx
@@ -162,7 +162,7 @@ class CreditsPopUp extends FlxSpriteGroup
bg.loadGraphic(Paths.image(headingPath.path));
} else {
trace('nae');
- bg.loadGraphic(Paths.customImage('images/' + headingPath.path));
+ bg.loadGraphic(Paths.customImage(TitleState.modFolder + '/images/' + headingPath.path));
}
}
else
@@ -181,7 +181,7 @@ class CreditsPopUp extends FlxSpriteGroup
rescaleIcon();
add(funnyIcon);
} else {
- funnyIcon = new FlxSprite(0, 0, Paths.customImage('images/songCreators/' + songCreator));
+ funnyIcon = new FlxSprite(0, 0, Paths.customImage(TitleState.modFolder + '/images/songCreators/' + songCreator));
rescaleIcon();
add(funnyIcon);
}
diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx
index a344ce4..73255fc 100644
--- a/source/FreeplayState.hx
+++ b/source/FreeplayState.hx
@@ -230,7 +230,7 @@ class FreeplayState extends MusicBeatState
titles.push(NameAlpha);
} else {
trace('nae');
- var CurrentSongIcon:FlxSprite = new FlxSprite(0,0).loadGraphic(Paths.customImage('Icon'));
+ var CurrentSongIcon:FlxSprite = new FlxSprite(0,0).loadGraphic(Paths.customImage(TitleState.modFolder + '/Icon'));
CurrentSongIcon.centerOffsets(false);
CurrentSongIcon.x = (1000 * i + 1) + (512 - CurrentSongIcon.width);
CurrentSongIcon.y = (FlxG.height / 2) - 256;
diff --git a/source/HealthIcon.hx b/source/HealthIcon.hx
index bb61e2e..7a60589 100644
--- a/source/HealthIcon.hx
+++ b/source/HealthIcon.hx
@@ -1,5 +1,6 @@
package;
+import sys.FileSystem;
import flixel.FlxSprite;
import flixel.math.FlxMath;
import flixel.graphics.FlxGraphic;
@@ -37,7 +38,15 @@ class HealthIcon extends FlxSprite
if (this.char != char)
{
if (char != "none")
+ if (FileSystem.exists('assets/images/ui/iconGrid/' + char + '.png')) {
loadGraphic(FlxGraphic.fromBitmapData(BitmapData.fromFile(Paths.image('ui/iconGrid/' + char, 'preload'))), true, 150, 150);
+ } else if (FileSystem.exists('mods/global characters/icons/' + char + '.png')) {
+ loadGraphic(Paths.customImage('mods/global characters/images/icons/' + char), true, 150, 150);
+ } else if (FileSystem.exists(TitleState.modFolder + '/images/icons/' + char + '.png')) {
+ loadGraphic(Paths.customImage(TitleState.modFolder + '/images/icons/' + char), true, 150, 150);
+ } else {
+ loadGraphic(Paths.image('blank', 'shared'));
+ }
else
loadGraphic(Paths.image('blank', 'shared'));
diff --git a/source/Paths.hx b/source/Paths.hx
index 943e413..339b7e1 100644
--- a/source/Paths.hx
+++ b/source/Paths.hx
@@ -8,6 +8,7 @@ import openfl.utils.AssetType;
import openfl.utils.Assets as OpenFlAssets;
#if sys import sys.FileSystem; #end
import flash.media.Sound;
+import sys.io.File;
class Paths
{
@@ -88,6 +89,13 @@ class Paths
}
}
+ inline static public function customFile(file:String)
+ {
+ var defaultReturnPath = File.getContent(file);
+
+ return defaultReturnPath;
+ }
+
inline static public function txt(key:String, ?library:String)
{
var defaultReturnPath = getPath('data/$key.txt', TEXT, library);
@@ -158,7 +166,7 @@ class Paths
inline static public function customImage(key:String)
{
- return (FlxGraphic.fromBitmapData(BitmapData.fromFile(TitleState.modFolder + '/${key}.png')));
+ return (FlxGraphic.fromBitmapData(BitmapData.fromFile('${key}.png')));
}
inline static public function music(key:String, ?library:String)
{
@@ -287,14 +295,24 @@ class Paths
inline static public function getSparrowAtlas(key:String, ?library:String)
{
- return FlxAtlasFrames.fromSparrow(image(key, library), file('images/$key.xml', library));
+ return FlxAtlasFrames.fromSparrow(image(key, library), file('images/$key.xml', library));
}
+ inline static public function getCustomSparrowAtlas(key:String)
+ {
+ return FlxAtlasFrames.fromSparrow(customImage(key), customFile('$key.xml'));
+ }
+
inline static public function getPackerAtlas(key:String, ?library:String)
{
return FlxAtlasFrames.fromSpriteSheetPacker(image(key, library), file('images/$key.txt', library));
}
+ inline static public function getCustomPackerAtlas(key:String)
+ {
+ return FlxAtlasFrames.fromSpriteSheetPacker(customImage(key), customFile('$key.txt'));
+ }
+
inline static public function video(key:String, ?library:String)
{
return getPath('videos/$key.mp4', BINARY, library);
diff --git a/source/TitleState.hx b/source/TitleState.hx
index 3a53ea5..b5bb453 100644
--- a/source/TitleState.hx
+++ b/source/TitleState.hx
@@ -127,7 +127,7 @@ class TitleState extends MusicBeatState
if(FileSystem.exists('mods')) {
for (folder in FileSystem.readDirectory('mods')){
- if (FileSystem.isDirectory('mods/' + folder) && !mods.contains(folder) && folder != 'skins')
+ if (FileSystem.isDirectory('mods/' + folder) && !mods.contains(folder) && folder != 'global characters')
mods.push(folder);
}
}