diff --git a/Project.xml b/Project.xml
index 643401439..029d6c890 100644
--- a/Project.xml
+++ b/Project.xml
@@ -96,7 +96,10 @@
-
+
+
+
+
diff --git a/example_mods/introMod/assets/preload/data/introText.txt b/example_mods/introMod/assets/preload/data/introText.txt
new file mode 100644
index 000000000..f0dd8224a
--- /dev/null
+++ b/example_mods/introMod/assets/preload/data/introText.txt
@@ -0,0 +1 @@
+awesomes tream--really awesome
\ No newline at end of file
diff --git a/example_mods/introMod/assets/preload/images/gfDanceTitle.png b/example_mods/introMod/assets/preload/images/gfDanceTitle.png
new file mode 100644
index 000000000..989f2a68a
Binary files /dev/null and b/example_mods/introMod/assets/preload/images/gfDanceTitle.png differ
diff --git a/source/Character.hx b/source/Character.hx
index 6fd919e2b..86a630d49 100644
--- a/source/Character.hx
+++ b/source/Character.hx
@@ -4,6 +4,7 @@ import flixel.FlxG;
import flixel.FlxSprite;
import flixel.animation.FlxBaseAnimation;
import flixel.graphics.frames.FlxAtlasFrames;
+import haxe.io.Path;
using StringTools;
@@ -32,7 +33,7 @@ class Character extends FlxSprite
{
case 'gf':
// GIRLFRIEND CODE
- tex = Paths.getSparrowAtlas('GF_assets');
+ tex = Paths.getSparrowAtlas('characters/GF_assets');
frames = tex;
animation.addByPrefix('cheer', 'GF Cheer', 24, false);
animation.addByPrefix('singLEFT', 'GF left note', 24, false);
@@ -46,19 +47,7 @@ class Character extends FlxSprite
animation.addByIndices('hairFall', "GF Dancing Beat Hair Landing", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], "", 24, false);
animation.addByPrefix('scared', 'GF FEAR', 24);
- addOffset('cheer');
- addOffset('sad', -2, -21);
- addOffset('danceLeft', 0, -9);
- addOffset('danceRight', 0, -9);
-
- addOffset("singUP", 0, 4);
- addOffset("singRIGHT", 0, -20);
- addOffset("singLEFT", 0, -19);
- addOffset("singDOWN", 0, -20);
- addOffset('hairBlow', 45, -8);
- addOffset('hairFall', 0, -9);
-
- addOffset('scared', -2, -17);
+ loadOffsetFile(curCharacter);
playAnim('danceRight');
@@ -93,6 +82,24 @@ class Character extends FlxSprite
playAnim('danceRight');
+ case 'bf-holding-gf':
+ frames = Paths.getSparrowAtlas('characters/bfAndGF');
+ quickAnimAdd('idle', 'BF idle dance');
+ quickAnimAdd('singDOWN', 'BF NOTE DOWN0');
+ quickAnimAdd('singLEFT', 'BF NOTE LEFT0');
+ quickAnimAdd('singRIGHT', 'BF NOTE RIGHT0');
+ quickAnimAdd('singUP', 'BF NOTE UP0');
+
+ quickAnimAdd('singDOWNmiss', 'BF NOTE DOWN MISS');
+ quickAnimAdd('singLEFTmiss', 'BF NOTE LEFT MISS');
+ quickAnimAdd('singRIGHTmiss', 'BF NOTE RIGHT MISS');
+ quickAnimAdd('singUPmiss', 'BF NOTE UP MISS');
+ quickAnimAdd('bfCatch', 'BF catches GF');
+
+ loadOffsetFile(curCharacter);
+
+ playAnim('idle');
+
case 'gf-car':
tex = Paths.getSparrowAtlas('gfCar');
frames = tex;
@@ -266,8 +273,20 @@ class Character extends FlxSprite
flipX = true;
+ case 'pico-speaker':
+ frames = Paths.getSparrowAtlas('characters/picoSpeaker');
+
+ quickAnimAdd('shoot1', "Pico shoot 1");
+ quickAnimAdd('shoot2', "Pico shoot 2");
+ quickAnimAdd('shoot3', "Pico shoot 3");
+ quickAnimAdd('shoot4', "Pico shoot 4");
+
+ // here for now, will be replaced later for less copypaste
+ loadOffsetFile(curCharacter);
+ playAnim('shoot1');
+
case 'bf':
- var tex = Paths.getSparrowAtlas('BOYFRIEND');
+ var tex = Paths.getSparrowAtlas('characters/BOYFRIEND');
frames = tex;
animation.addByPrefix('idle', 'BF idle dance', 24, false);
animation.addByPrefix('singUP', 'BF NOTE UP0', 24, false);
@@ -286,25 +305,14 @@ class Character extends FlxSprite
animation.addByPrefix('scared', 'BF idle shaking', 24);
- addOffset('idle', -5);
- addOffset("singUP", -29, 27);
- addOffset("singRIGHT", -38, -7);
- addOffset("singLEFT", 12, -6);
- addOffset("singDOWN", -10, -50);
- addOffset("singUPmiss", -29, 27);
- addOffset("singRIGHTmiss", -30, 21);
- addOffset("singLEFTmiss", 12, 24);
- addOffset("singDOWNmiss", -11, -19);
- addOffset("hey", 7, 4);
- addOffset('firstDeath', 37, 11);
- addOffset('deathLoop', 37, 5);
- addOffset('deathConfirm', 37, 69);
- addOffset('scared', -4);
+ loadOffsetFile(curCharacter);
playAnim('idle');
flipX = true;
+ loadOffsetFile(curCharacter);
+
case 'bf-christmas':
var tex = Paths.getSparrowAtlas('christmas/bfChristmas');
frames = tex;
@@ -521,15 +529,7 @@ class Character extends FlxSprite
animation.addByPrefix('singUPmiss', 'Tankman UP note MISS', 24, false);
animation.addByPrefix('singDOWNmiss', 'Tankman DOWN note MISS', 24, false);
- addOffset('idle');
- addOffset("singUP", 24, 56);
- addOffset("singRIGHT", -1, -7);
- addOffset("singLEFT", 100, -14);
- addOffset("singDOWN", 98, -90);
- addOffset("singUPmiss", 24, 56);
- addOffset("singRIGHTmiss", -1, -7);
- addOffset("singLEFTmiss", 100, -14);
- addOffset("singDOWNmiss", 98, -90);
+ loadOffsetFile(curCharacter);
playAnim('idle');
@@ -561,9 +561,20 @@ class Character extends FlxSprite
}
}
+ function quickAnimAdd(name:String, prefix:String)
+ {
+ animation.addByPrefix(name, prefix, 24, false);
+ }
+
private function loadOffsetFile(offsetCharacter:String)
{
- var daFile:String = Paths.file("characters/" + offsetCharacter + "Offsets.txt");
+ var daFile:Array = CoolUtil.coolTextFile(Paths.file("images/characters/" + offsetCharacter + "Offsets.txt"));
+
+ for (i in daFile)
+ {
+ var splitWords:Array = i.split(" ");
+ addOffset(splitWords[0], Std.parseInt(splitWords[1]), Std.parseInt(splitWords[2]));
+ }
}
override function update(elapsed:Float)
@@ -649,6 +660,8 @@ class Character extends FlxSprite
else
playAnim('danceLeft');
}
+ case 'pico-speaker':
+ playAnim('shoot' + FlxG.random.int(1, 4), true);
case 'spooky':
danced = !danced;
diff --git a/source/HealthIcon.hx b/source/HealthIcon.hx
index ff967e990..9224904f1 100644
--- a/source/HealthIcon.hx
+++ b/source/HealthIcon.hx
@@ -16,11 +16,13 @@ class HealthIcon extends FlxSprite
antialiasing = true;
animation.add('bf', [0, 1], 0, false, isPlayer);
+ animation.add('bf-holding-gf', [0, 1], 0, false, isPlayer);
animation.add('bf-car', [0, 1], 0, false, isPlayer);
animation.add('bf-christmas', [0, 1], 0, false, isPlayer);
animation.add('bf-pixel', [21, 21], 0, false, isPlayer);
animation.add('spooky', [2, 3], 0, false, isPlayer);
animation.add('pico', [4, 5], 0, false, isPlayer);
+ animation.add('pico-speaker', [4, 5], 0, false, isPlayer);
animation.add('mom', [6, 7], 0, false, isPlayer);
animation.add('mom-car', [6, 7], 0, false, isPlayer);
animation.add('tankman', [8, 9], 0, false, isPlayer);
diff --git a/source/Main.hx b/source/Main.hx
index ee782ca64..95b4e792f 100644
--- a/source/Main.hx
+++ b/source/Main.hx
@@ -20,7 +20,12 @@ class Main extends Sprite
var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom).
var initialState:Class = TitleState; // The FlxState the game starts with.
var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions.
+ #if web
var framerate:Int = 60; // How many frames per second the game should run at.
+ #else
+ var framerate:Int = 144; // How many frames per second the game should run at.
+
+ #end
var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode.
var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets
diff --git a/source/ModdingSubstate.hx b/source/ModdingSubstate.hx
index a46cba1c5..8afffac82 100644
--- a/source/ModdingSubstate.hx
+++ b/source/ModdingSubstate.hx
@@ -1,37 +1,149 @@
package;
+import Controls.Control;
+import flixel.FlxG;
+import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.text.FlxText;
+import flixel.util.FlxColor;
+import polymod.Polymod;
#if desktop
import sys.FileSystem;
#end
class ModdingSubstate extends MusicBeatSubstate
{
+ var grpMods:FlxTypedGroup;
+ var enabledMods:Array = [];
+ var modFolders:Array = [];
+
+ var curSelected:Int = 0;
+
public function new():Void
{
super();
- // var pathShit
+ grpMods = new FlxTypedGroup();
+ add(grpMods);
+
+ refreshModList();
+ }
+
+ override function update(elapsed:Float)
+ {
+ if (FlxG.keys.justPressed.R)
+ refreshModList();
+
+ selections();
+
+ if (controls.UP_P)
+ selections(-1);
+ if (controls.DOWN_P)
+ selections(1);
+
+ if (FlxG.keys.justPressed.SPACE)
+ grpMods.members[curSelected].modEnabled = !grpMods.members[curSelected].modEnabled;
+
+ if (FlxG.keys.justPressed.I && curSelected != 0)
+ {
+ var oldOne = grpMods.members[curSelected - 1];
+ grpMods.members[curSelected - 1] = grpMods.members[curSelected];
+ grpMods.members[curSelected] = oldOne;
+ selections(-1);
+ }
+
+ if (FlxG.keys.justPressed.K && curSelected < grpMods.members.length - 1)
+ {
+ var oldOne = grpMods.members[curSelected + 1];
+ grpMods.members[curSelected + 1] = grpMods.members[curSelected];
+ grpMods.members[curSelected] = oldOne;
+ selections(1);
+ }
+
+ super.update(elapsed);
+ }
+
+ private function selections(change:Int = 0):Void
+ {
+ curSelected += change;
+
+ if (curSelected >= modFolders.length)
+ curSelected = 0;
+ if (curSelected < 0)
+ curSelected = modFolders.length - 1;
+
+ for (txt in 0...grpMods.length)
+ {
+ if (txt == curSelected)
+ {
+ grpMods.members[txt].color = FlxColor.YELLOW;
+ }
+ else
+ grpMods.members[txt].color = FlxColor.WHITE;
+ }
+
+ organizeByY();
+ }
+
+ private function refreshModList():Void
+ {
+ while (grpMods.members.length > 0)
+ {
+ grpMods.remove(grpMods.members[0], true);
+ }
#if desktop
var modList = [];
+ modFolders = [];
+ #if desktop
for (file in FileSystem.readDirectory('./mods'))
{
- if (FileSystem.isDirectory("./mods/" + file))
- modList.push(file);
+ if (FileSystem.isDirectory('./mods/' + file))
+ modFolders.push(file);
}
+ enabledMods = [];
+
+ modList = Polymod.scan('./mods');
+
trace(modList);
var loopNum:Int = 0;
- for (i in modList)
+ for (i in modFolders)
{
- var txt:FlxText = new FlxText(0, 10 + (40 * loopNum), 0, i, 32);
- add(txt);
+ var txt:ModMenuItem = new ModMenuItem(0, 10 + (40 * loopNum), 0, i, 32);
+ txt.text = i;
+ grpMods.add(txt);
loopNum++;
}
#end
- }
-}
+ } private function organizeByY():Void
+
+ {
+ for (i in 0...grpMods.length)
+ {
+ grpMods.members[i].y = 10 + (40 * i);
+ }
+ }
+ } class ModMenuItem extends FlxText
+
+ {
+ public var modEnabled:Bool = false;
+ public var daMod:String;
+
+ public function new(x:Float, y:Float, w:Float, str:String, size:Int)
+ {
+ super(x, y, w, str, size);
+ }
+
+ override function update(elapsed:Float)
+ {
+ if (modEnabled)
+ alpha = 1;
+ else
+ alpha = 0.5;
+
+ super.update(elapsed);
+ }
+ }
diff --git a/source/OptionsSubState.hx b/source/OptionsSubState.hx
index 67b129c67..00ca548f1 100644
--- a/source/OptionsSubState.hx
+++ b/source/OptionsSubState.hx
@@ -15,6 +15,8 @@ class OptionsSubState extends MusicBeatSubstate
var grpOptionsTexts:FlxTypedGroup;
+ // public static var isDownscroll:Bool = false;
+
public function new()
{
super();
diff --git a/source/PlayState.hx b/source/PlayState.hx
index c864df782..c3e16d19e 100644
--- a/source/PlayState.hx
+++ b/source/PlayState.hx
@@ -113,6 +113,8 @@ class PlayState extends MusicBeatState
var bgGirls:BackgroundGirls;
var wiggleShit:WiggleEffect = new WiggleEffect();
+ var tankmanRun:FlxTypedGroup;
+
var talking:Bool = true;
var songScore:Int = 0;
var scoreTxt:FlxText;
@@ -499,6 +501,9 @@ class PlayState extends MusicBeatState
var tankGround:BGSprite = new BGSprite('tankGround', -200, -20);
add(tankGround);
+ tankmanRun = new FlxTypedGroup();
+ add(tankmanRun);
+
var fgTank0:BGSprite = new BGSprite('tank0', -290, 400, 1.7, 1.5, ['fg']);
foregroundSprites.add(fgTank0);
@@ -560,9 +565,19 @@ class PlayState extends MusicBeatState
if (curStage == 'limo')
gfVersion = 'gf-car';
+ if (SONG.song.toLowerCase() == 'stress')
+ gfVersion = 'pico-speaker';
+
gf = new Character(400, 130, gfVersion);
gf.scrollFactor.set(0.95, 0.95);
+ switch (gfVersion)
+ {
+ case 'pico-speaker':
+ gf.x -= 50;
+ gf.y -= 200;
+ }
+
dad = new Character(100, 100, SONG.player2);
var camPos:FlxPoint = new FlxPoint(dad.getGraphicMidpoint().x, dad.getGraphicMidpoint().y);
@@ -2383,6 +2398,17 @@ class PlayState extends MusicBeatState
}
}
+ switch (curSong.toLowerCase())
+ {
+ case 'stress':
+ if (FlxG.random.bool())
+ {
+ var tank:TankmenBG = new TankmenBG(500, 200);
+ tank.strumTime = Conductor.songPosition + (Conductor.crochet * 4);
+ tankmanRun.add(tank);
+ }
+ }
+
if (isHalloween && FlxG.random.bool(10) && curBeat > lightningStrikeBeat + lightningOffset)
{
lightningStrikeShit();
diff --git a/source/TankmenBG.hx b/source/TankmenBG.hx
new file mode 100644
index 000000000..bdd56e8a3
--- /dev/null
+++ b/source/TankmenBG.hx
@@ -0,0 +1,76 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import haxe.display.Display.Package;
+
+class TankmenBG extends FlxSprite
+{
+ public var strumTime:Float = 0;
+ public var goingRight:Bool = false;
+ public var tankSpeed:Float = 0.7;
+
+ public var endingOffset:Float;
+
+ public function new(x:Float, y:Float)
+ {
+ super(x, y);
+
+ // makeGraphic(200, 200);
+
+ frames = Paths.getSparrowAtlas('tankmanKilled1');
+ antialiasing = true;
+ animation.addByPrefix('run', 'tankman running', 24, true);
+ animation.addByPrefix('shot', 'John', 24, false);
+
+ animation.play('run');
+
+ y += FlxG.random.int(-40, 100);
+
+ goingRight = FlxG.random.bool();
+ endingOffset = FlxG.random.float(0, 120);
+
+ tankSpeed = FlxG.random.float(0.65, 0.8);
+
+ if (goingRight)
+ flipX = true;
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (animation.curAnim.name == 'run')
+ {
+ var endDirection:Float = (FlxG.width * 0.74) + endingOffset;
+
+ if (goingRight)
+ {
+ endDirection = (FlxG.width * 0.02) - endingOffset;
+
+ x = (endDirection + (Conductor.songPosition - strumTime) * tankSpeed);
+ }
+ else
+ {
+ x = (endDirection - (Conductor.songPosition - strumTime) * tankSpeed);
+ }
+ }
+
+ if (Conductor.songPosition > strumTime)
+ {
+ // kill();
+ animation.play('shot');
+
+ if (goingRight)
+ {
+ offset.y = 200;
+ offset.x = 300;
+ }
+ }
+
+ if (animation.curAnim.name == 'shot' && animation.curAnim.curFrame >= animation.curAnim.frames.length - 1)
+ {
+ kill();
+ }
+ }
+}
diff --git a/source/TitleState.hx b/source/TitleState.hx
index 572a97825..eb46ace47 100644
--- a/source/TitleState.hx
+++ b/source/TitleState.hx
@@ -37,9 +37,11 @@ class TitleState extends MusicBeatState
override public function create():Void
{
#if polymod
- polymod.Polymod.init({modRoot: "mods", dirs: ['introMod']});
+ polymod.Polymod.init({modRoot: "mods", dirs: ['introMod'], framework: OPENFL});
#end
+ FlxG.sound.muteKeys = [ZERO];
+
PlayerSettings.init();
curWacky = FlxG.random.getObject(getIntroTextShit());
@@ -216,6 +218,17 @@ class TitleState extends MusicBeatState
override function update(elapsed:Float)
{
+ /*
+ if (FlxG.keys.justPressed.R)
+ {
+ #if polymod
+ polymod.Polymod.init({modRoot: "mods", dirs: ['introMod']});
+ trace('reinitialized');
+ #end
+ }
+
+ */
+
if (FlxG.sound.music != null)
Conductor.songPosition = FlxG.sound.music.time;
// FlxG.watch.addQuick('amp', FlxG.sound.music.amplitude);