Merge branch 'master' into options

This commit is contained in:
George FunBook 2021-03-22 23:05:46 -05:00
commit 3476796cc6
20 changed files with 814 additions and 195 deletions

View File

@ -126,6 +126,8 @@
<haxelib name="faxe" if='switch'/>
<haxelib name="polymod"/>
<haxelib name="hxcpp-debug-server" if="desktop debug"/>
<haxelib name="discord_rpc" if="desktop"/>
<!-- <haxelib name="hxcpp-debug-server" if="desktop"/> -->
<!-- <haxelib name="markdown" /> -->
<!-- <haxelib name="HtmlParser" /> -->

View File

@ -16,6 +16,8 @@ class Boyfriend extends Character
super(x, y, char, true);
}
public var startedDeath:Bool = false;
override function update(elapsed:Float)
{
if (!debugMode)
@ -32,7 +34,7 @@ class Boyfriend extends Character
playAnim('idle', true, false, 10);
}
if (animation.curAnim.name == 'firstDeath' && animation.curAnim.finished)
if (animation.curAnim.name == 'firstDeath' && animation.curAnim.finished && startedDeath)
{
playAnim('deathLoop');
}

View File

@ -33,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);
@ -47,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');
@ -94,6 +82,26 @@ 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');
flipX = true;
case 'gf-car':
tex = Paths.getSparrowAtlas('gfCar');
frames = tex;
@ -280,7 +288,7 @@ class Character extends FlxSprite
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);
@ -299,25 +307,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;
@ -413,8 +410,8 @@ class Character extends FlxSprite
animation.play('firstDeath');
addOffset('firstDeath');
addOffset('deathLoop', -37);
addOffset('deathConfirm', -37);
addOffset('deathLoop', -30, -12);
addOffset('deathConfirm', -30, -12);
playAnim('firstDeath');
// pixel bullshit
setGraphicSize(Std.int(width * 6));

View File

@ -0,0 +1,63 @@
package;
import flixel.FlxG;
import flixel.group.FlxGroup.FlxTypedGroup;
import shaderslmfao.ColorSwap;
class ColorpickSubstate extends MusicBeatSubstate
{
var curSelected:Int = 0;
var grpNotes:FlxTypedGroup<Note>;
public function new()
{
super();
grpNotes = new FlxTypedGroup<Note>();
add(grpNotes);
for (i in 0...4)
{
var note:Note = new Note(0, i);
note.x = (100 * i) + i;
note.screenCenter(Y);
grpNotes.add(note);
}
}
override function update(elapsed:Float)
{
if (controls.BACK)
{
FlxG.state.closeSubState();
FlxG.state.openSubState(new OptionsSubState());
}
if (controls.RIGHT_P)
curSelected += 1;
if (controls.LEFT_P)
curSelected -= 1;
if (curSelected < 0)
curSelected = grpNotes.members.length - 1;
if (curSelected >= grpNotes.members.length)
curSelected = 0;
if (controls.UP)
{
grpNotes.members[curSelected].colorSwap.update(elapsed * 0.3);
Note.arrowColors[curSelected] += elapsed * 0.3;
}
if (controls.DOWN)
{
grpNotes.members[curSelected].colorSwap.update(-elapsed * 0.3);
Note.arrowColors[curSelected] += -elapsed * 0.3;
}
super.update(elapsed);
}
}

View File

@ -60,6 +60,24 @@ class DialogueBox extends FlxSpriteGroup
bgFade.alpha = 0.7;
}, 5);
portraitLeft = new FlxSprite(-20, 40);
portraitLeft.frames = Paths.getSparrowAtlas('weeb/senpaiPortrait');
portraitLeft.animation.addByPrefix('enter', 'Senpai Portrait Enter', 24, false);
portraitLeft.setGraphicSize(Std.int(portraitLeft.width * PlayState.daPixelZoom * 0.9));
portraitLeft.updateHitbox();
portraitLeft.scrollFactor.set();
add(portraitLeft);
portraitLeft.visible = false;
portraitRight = new FlxSprite(0, 40);
portraitRight.frames = Paths.getSparrowAtlas('weeb/bfPortrait');
portraitRight.animation.addByPrefix('enter', 'Boyfriend portrait enter', 24, false);
portraitRight.setGraphicSize(Std.int(portraitRight.width * PlayState.daPixelZoom * 0.9));
portraitRight.updateHitbox();
portraitRight.scrollFactor.set();
add(portraitRight);
portraitRight.visible = false;
box = new FlxSprite(-20, 45);
var hasDialog = false;
@ -94,24 +112,6 @@ class DialogueBox extends FlxSpriteGroup
if (!hasDialog)
return;
portraitLeft = new FlxSprite(-20, 40);
portraitLeft.frames = Paths.getSparrowAtlas('weeb/senpaiPortrait');
portraitLeft.animation.addByPrefix('enter', 'Senpai Portrait Enter', 24, false);
portraitLeft.setGraphicSize(Std.int(portraitLeft.width * PlayState.daPixelZoom * 0.9));
portraitLeft.updateHitbox();
portraitLeft.scrollFactor.set();
add(portraitLeft);
portraitLeft.visible = false;
portraitRight = new FlxSprite(0, 40);
portraitRight.frames = Paths.getSparrowAtlas('weeb/bfPortrait');
portraitRight.animation.addByPrefix('enter', 'Boyfriend portrait enter', 24, false);
portraitRight.setGraphicSize(Std.int(portraitRight.width * PlayState.daPixelZoom * 0.9));
portraitRight.updateHitbox();
portraitRight.scrollFactor.set();
add(portraitRight);
portraitRight.visible = false;
box.animation.play('normalOpen');
box.setGraphicSize(Std.int(box.width * PlayState.daPixelZoom * 0.9));
box.updateHitbox();
@ -120,7 +120,10 @@ class DialogueBox extends FlxSpriteGroup
box.screenCenter(X);
portraitLeft.screenCenter(X);
handSelect = new FlxSprite(FlxG.width * 0.9, FlxG.height * 0.9).loadGraphic(Paths.image('weeb/pixelUI/hand_textbox'));
handSelect = new FlxSprite(1042, 590).loadGraphic(Paths.image('weeb/pixelUI/hand_textbox'));
handSelect.setGraphicSize(Std.int(handSelect.width * PlayState.daPixelZoom * 0.9));
handSelect.updateHitbox();
handSelect.visible = false;
add(handSelect);
@ -199,6 +202,7 @@ class DialogueBox extends FlxSpriteGroup
portraitLeft.visible = false;
portraitRight.visible = false;
swagDialogue.alpha -= 1 / 5;
handSelect.alpha -= 1 / 5;
dropText.alpha = swagDialogue.alpha;
}, 5);
@ -230,7 +234,13 @@ class DialogueBox extends FlxSpriteGroup
// swagDialogue.text = ;
swagDialogue.resetText(dialogueList[0]);
swagDialogue.start(0.04, true);
swagDialogue.start(0.04);
swagDialogue.completeCallback = function()
{
trace("dialogue finish");
handSelect.visible = true;
};
handSelect.visible = false;
switch (curCharacter)
{

82
source/Discord.hx Normal file
View File

@ -0,0 +1,82 @@
package;
import Sys.sleep;
import discord_rpc.DiscordRpc;
using StringTools;
class DiscordClient
{
public function new()
{
trace("Discord Client starting...");
DiscordRpc.start({
clientID: "814588678700924999",
onReady: onReady,
onError: onError,
onDisconnected: onDisconnected
});
trace("Discord Client started.");
while (true)
{
DiscordRpc.process();
sleep(2);
//trace("Discord Client Update");
}
DiscordRpc.shutdown();
}
static function onReady()
{
DiscordRpc.presence({
details: "In the Menus",
state: null,
largeImageKey: 'icon',
largeImageText: "Friday Night Funkin'"
});
}
static function onError(_code:Int, _message:String)
{
trace('Error! $_code : $_message');
}
static function onDisconnected(_code:Int, _message:String)
{
trace('Disconnected! $_code : $_message');
}
public static function initialize()
{
var DiscordDaemon = sys.thread.Thread.create(() ->
{
new DiscordClient();
});
trace("Discord Client initialized");
}
public static function changePresence(details:String, state:Null<String>, ?smallImageKey : String, ?hasStartTimestamp : Bool, ?endTimestamp: Float)
{
var startTimestamp:Float = if(hasStartTimestamp) Date.now().getTime() else 0;
if (endTimestamp > 0)
{
endTimestamp = startTimestamp + endTimestamp;
}
DiscordRpc.presence({
details: details,
state: state,
largeImageKey: 'icon',
largeImageText: "Friday Night Funkin'",
smallImageKey : smallImageKey,
// Obtained times are in milliseconds so they are divided so Discord can use it
startTimestamp : Std.int(startTimestamp / 1000),
endTimestamp : Std.int(endTimestamp / 1000)
});
//trace('Discord RPC Updated. Arguments: $details, $state, $smallImageKey, $hasStartTimestamp, $endTimestamp');
}
}

View File

@ -1,5 +1,8 @@
package;
#if desktop
import Discord.DiscordClient;
#end
import flash.text.TextField;
import flixel.FlxG;
import flixel.FlxSprite;
@ -49,6 +52,11 @@ class FreeplayState extends MusicBeatState
FlxG.sound.playMusic(Paths.music('freakyMenu'));
}
#if desktop
// Updating Discord Rich Presence
DiscordClient.changePresence("In the Menus", null);
#end
var isDebug:Bool = false;
#if debug
@ -59,7 +67,7 @@ class FreeplayState extends MusicBeatState
addWeek(['Bopeebo', 'Fresh', 'Dadbattle'], 1, ['dad']);
if (StoryMenuState.weekUnlocked[2] || isDebug)
addWeek(['Spookeez', 'South', 'Monster'], 2, ['spooky']);
addWeek(['Spookeez', 'South', 'Monster'], 2, ['spooky', 'spooky', 'monster']);
if (StoryMenuState.weekUnlocked[3] || isDebug)
addWeek(['Pico', 'Philly', 'Blammed'], 3, ['pico']);

View File

@ -13,6 +13,7 @@ class GameOverSubstate extends MusicBeatSubstate
var camFollow:FlxObject;
var stageSuffix:String = "";
var randomGameover:Int = 1;
public function new(x:Float, y:Float)
{
@ -49,8 +50,12 @@ class GameOverSubstate extends MusicBeatSubstate
FlxG.camera.target = null;
bf.playAnim('firstDeath');
randomGameover = FlxG.random.int(1, 25);
}
var playingDeathSound:Bool = false;
override function update(elapsed:Float)
{
super.update(elapsed);
@ -75,9 +80,24 @@ class GameOverSubstate extends MusicBeatSubstate
FlxG.camera.follow(camFollow, LOCKON, 0.01);
}
if (bf.animation.curAnim.name == 'firstDeath' && bf.animation.curAnim.finished)
switch (PlayState.storyWeek)
{
FlxG.sound.playMusic(Paths.music('gameOver' + stageSuffix));
case 7:
if (bf.animation.curAnim.name == 'firstDeath' && bf.animation.curAnim.finished && !playingDeathSound)
{
playingDeathSound = true;
FlxG.sound.play(Paths.sound('jeffGameover/jeffGameover-' + randomGameover), 1, false, null, true, function()
{
bf.startedDeath = true;
coolStartDeath();
});
}
default:
if (bf.animation.curAnim.name == 'firstDeath' && bf.animation.curAnim.finished)
{
bf.startedDeath = true;
coolStartDeath();
}
}
if (FlxG.sound.music.playing)
@ -86,6 +106,11 @@ class GameOverSubstate extends MusicBeatSubstate
}
}
private function coolStartDeath():Void
{
FlxG.sound.playMusic(Paths.music('gameOver' + stageSuffix));
}
override function beatHit()
{
super.beatHit();

View File

@ -2,6 +2,8 @@ package;
import flixel.FlxSprite;
using StringTools;
class HealthIcon extends FlxSprite
{
/**
@ -9,36 +11,53 @@ class HealthIcon extends FlxSprite
*/
public var sprTracker:FlxSprite;
var char:String = 'bf';
var isPlayer:Bool = false;
public function new(char:String = 'bf', isPlayer:Bool = false)
{
super();
loadGraphic(Paths.image('iconGrid'), true, 150, 150);
this.isPlayer = isPlayer;
this.char = char;
loadIcon(char);
antialiasing = true;
animation.add('bf', [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);
animation.add('face', [10, 11], 0, false, isPlayer);
animation.add('dad', [12, 13], 0, false, isPlayer);
animation.add('senpai', [22, 22], 0, false, isPlayer);
animation.add('senpai-angry', [22, 22], 0, false, isPlayer);
animation.add('spirit', [23, 23], 0, false, isPlayer);
animation.add('bf-old', [14, 15], 0, false, isPlayer);
animation.add('gf', [16], 0, false, isPlayer);
animation.add('parents-christmas', [17], 0, false, isPlayer);
animation.add('monster', [19, 20], 0, false, isPlayer);
animation.add('monster-christmas', [19, 20], 0, false, isPlayer);
animation.play(char);
scrollFactor.set();
}
public var isOldIcon:Bool = false;
public function swapOldIcon():Void
{
isOldIcon = !isOldIcon;
if (isOldIcon)
{
loadGraphic(Paths.image('icons/icon-bf-old'), true, 150, 150);
animation.add('bf-old', [0, 1], 0, false, isPlayer);
animation.play('bf-old');
}
else
loadIcon(char);
}
function loadIcon(char:String):Void
{
var realChar:String = "";
switch (char)
{
case 'bf-pixel':
realChar = char;
default:
realChar = char.split('-')[0].trim();
}
loadGraphic(Paths.image('icons/icon-' + realChar), true, 150, 150);
animation.add(realChar, [0, 1], 0, false, isPlayer);
animation.play(realChar);
}
override function update(elapsed:Float)
{
super.update(elapsed);

View File

@ -1,6 +1,7 @@
package;
import NGio;
import flixel.ui.FlxButton;
import flixel.FlxG;
import flixel.FlxObject;
@ -17,6 +18,10 @@ import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import lime.app.Application;
#if desktop
import Discord.DiscordClient;
#end
#if newgrounds
import io.newgrounds.NG;
import ui.NgPrompt;
@ -38,6 +43,11 @@ class MainMenuState extends MusicBeatState
override function create()
{
#if desktop
// Updating Discord Rich Presence
DiscordClient.changePresence("In the Menus", null);
#end
transIn = FlxTransitionableState.defaultTransIn;
transOut = FlxTransitionableState.defaultTransOut;

View File

@ -91,10 +91,10 @@ class ModdingSubstate extends MusicBeatSubstate
grpMods.remove(grpMods.members[0], true);
}
#if desktop
var modList = [];
modFolders = [];
#if desktop
for (file in FileSystem.readDirectory('./mods'))
{
if (FileSystem.isDirectory('./mods/' + file))

View File

@ -9,9 +9,6 @@ import flixel.util.FlxTimer;
class MusicBeatState extends FlxUIState
{
private var lastBeat:Float = 0;
private var lastStep:Float = 0;
private var curStep:Int = 0;
private var curBeat:Int = 0;
private var controls(get, never):Controls;
@ -35,7 +32,7 @@ class MusicBeatState extends FlxUIState
updateCurStep();
updateBeat();
if (oldStep != curStep && curStep > 0)
if (oldStep != curStep && curStep >= 0)
stepHit();
super.update(elapsed);

View File

@ -11,9 +11,6 @@ class MusicBeatSubstate extends FlxSubState
super();
}
private var lastBeat:Float = 0;
private var lastStep:Float = 0;
private var curStep:Int = 0;
private var curBeat:Int = 0;
private var controls(get, never):Controls;
@ -29,7 +26,7 @@ class MusicBeatSubstate extends FlxSubState
updateCurStep();
curBeat = Math.floor(curStep / 4);
if (oldStep != curStep && curStep > 0)
if (oldStep != curStep && curStep >= 0)
stepHit();

View File

@ -1,15 +1,19 @@
package;
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.graphics.frames.FlxAtlasFrames;
import flixel.math.FlxMath;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import shaderslmfao.ColorSwap;
using StringTools;
#if polymod
import polymod.format.ParseRules.TargetSignatureElement;
#end
using StringTools;
class Note extends FlxSprite
{
public var strumTime:Float = 0;
@ -24,6 +28,7 @@ class Note extends FlxSprite
public var sustainLength:Float = 0;
public var isSustainNote:Bool = false;
public var colorSwap:ColorSwap;
public var noteScore:Float = 1;
public static var swagWidth:Float = 160 * 0.7;
@ -32,6 +37,8 @@ class Note extends FlxSprite
public static var BLUE_NOTE:Int = 1;
public static var RED_NOTE:Int = 3;
public static var arrowColors:Array<Float> = [1, 1, 1, 1];
public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false)
{
super();
@ -82,10 +89,10 @@ class Note extends FlxSprite
default:
frames = Paths.getSparrowAtlas('NOTE_assets');
animation.addByPrefix('greenScroll', 'green0');
animation.addByPrefix('redScroll', 'red0');
animation.addByPrefix('blueScroll', 'blue0');
animation.addByPrefix('purpleScroll', 'purple0');
animation.addByPrefix('greenScroll', 'green instance');
animation.addByPrefix('redScroll', 'red instance');
animation.addByPrefix('blueScroll', 'blue instance');
animation.addByPrefix('purpleScroll', 'purple instance');
animation.addByPrefix('purpleholdend', 'pruple end hold');
animation.addByPrefix('greenholdend', 'green hold end');
@ -100,13 +107,25 @@ class Note extends FlxSprite
setGraphicSize(Std.int(width * 0.7));
updateHitbox();
antialiasing = true;
// colorSwap.colorToReplace = 0xFFF9393F;
// colorSwap.newColor = 0xFF00FF00;
// color = FlxG.random.color();
// color.saturation *= 4;
// replaceColor(0xFFC1C1C1, FlxColor.RED);
}
colorSwap = new ColorSwap();
shader = colorSwap.shader;
updateColors();
switch (noteData)
{
case 0:
x += swagWidth * 0;
animation.play('purpleScroll');
case 1:
x += swagWidth * 1;
animation.play('blueScroll');
@ -167,6 +186,11 @@ class Note extends FlxSprite
}
}
public function updateColors():Void
{
colorSwap.update(arrowColors[noteData]);
}
override function update(elapsed:Float)
{
super.update(elapsed);

View File

@ -8,7 +8,7 @@ import flixel.util.FlxColor;
class OptionsSubState extends MusicBeatSubstate
{
var textMenuItems:Array<String> = ['Master Volume', 'Sound Volume', 'Controls'];
var textMenuItems:Array<String> = ['Master Volume', 'Sound Volume', 'Controls', 'Colors', 'Back'];
var selector:FlxSprite;
var curSelected:Int = 0;
@ -63,16 +63,24 @@ class OptionsSubState extends MusicBeatSubstate
txt.color = FlxColor.YELLOW;
});
if (controls.BACK)
FlxG.switchState(new MainMenuState());
if (controls.ACCEPT)
{
switch (textMenuItems[curSelected])
{
case "Colors":
FlxG.state.closeSubState();
FlxG.state.openSubState(new ColorpickSubstate());
case "Controls":
FlxG.state.closeSubState();
FlxG.state.openSubState(new ControlsSubState());
case "Mods":
FlxG.state.closeSubState();
FlxG.state.openSubState(new ModdingSubstate());
case "Back":
FlxG.switchState(new MainMenuState());
}
}
}

View File

@ -38,9 +38,14 @@ import lime.utils.Assets;
import openfl.display.BlendMode;
import openfl.display.StageQuality;
import openfl.filters.ShaderFilter;
import shaderslmfao.ColorSwap;
using StringTools;
#if desktop
import Discord.DiscordClient;
#end
class PlayState extends MusicBeatState
{
public static var curStage:String = '';
@ -113,6 +118,8 @@ class PlayState extends MusicBeatState
var bgGirls:BackgroundGirls;
var wiggleShit:WiggleEffect = new WiggleEffect();
var tankmanRun:FlxTypedGroup<TankmenBG>;
var talking:Bool = true;
var songScore:Int = 0;
var scoreTxt:FlxText;
@ -126,6 +133,15 @@ class PlayState extends MusicBeatState
var inCutscene:Bool = false;
#if desktop
// Discord RPC variables
var storyDifficultyText:String = "";
var iconRPC:String = "";
var songLength:Float = 0;
var detailsText:String = "";
var detailsPausedText:String = "";
#end
override public function create()
{
if (FlxG.sound.music != null)
@ -179,6 +195,8 @@ class PlayState extends MusicBeatState
dialogue = CoolUtil.coolTextFile(Paths.txt('thorns/thornsDialogue'));
}
initDiscord();
switch (SONG.song.toLowerCase())
{
case 'spookeez' | 'monster' | 'south':
@ -499,6 +517,9 @@ class PlayState extends MusicBeatState
var tankGround:BGSprite = new BGSprite('tankGround', -200, -20);
add(tankGround);
tankmanRun = new FlxTypedGroup<TankmenBG>();
add(tankmanRun);
var fgTank0:BGSprite = new BGSprite('tank0', -290, 400, 1.7, 1.5, ['fg']);
foregroundSprites.add(fgTank0);
@ -619,6 +640,12 @@ class PlayState extends MusicBeatState
boyfriend = new Boyfriend(770, 450, SONG.player1);
switch (SONG.player1)
{
case "bf-holding-gf":
boyfriend.y -= 140;
}
// REPOSITIONING PER STAGE
switch (curStage)
{
@ -805,6 +832,32 @@ class PlayState extends MusicBeatState
super.create();
}
function initDiscord():Void
{
#if desktop
storyDifficultyText = CoolUtil.difficultyString();
iconRPC = SONG.player2;
// To avoid having duplicate images in Discord assets
switch (iconRPC)
{
case 'senpai-angry':
iconRPC = 'senpai';
case 'monster-christmas':
iconRPC = 'monster';
case 'mom-car':
iconRPC = 'mom';
}
// String that contains the mode defined here so it isn't necessary to call changePresence for each mode
detailsText = isStoryMode ? "Story Mode: Week " + storyWeek : "Freeplay";
detailsPausedText = "Paused - " + detailsText;
// Updating Discord Rich Presence.
DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC);
#end
}
function schoolIntro(?dialogueBox:DialogueBox):Void
{
var black:FlxSprite = new FlxSprite(-100, -100).makeGraphic(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK);
@ -908,9 +961,18 @@ class PlayState extends MusicBeatState
startTimer = new FlxTimer().start(Conductor.crochet / 1000, function(tmr:FlxTimer)
{
dad.dance();
gf.dance();
boyfriend.playAnim('idle');
// this just based on beatHit stuff but compact
if (swagCounter % gfSpeed == 0)
gf.dance();
if (swagCounter % 2 == 0)
{
if (!boyfriend.animation.curAnim.name.startsWith("sing"))
boyfriend.playAnim('idle');
if (!dad.animation.curAnim.name.startsWith("sing"))
dad.dance();
}
else if (dad.curCharacter == 'spooky' && !dad.animation.curAnim.name.startsWith("sing"))
dad.dance();
var introAssets:Map<String, Array<String>> = new Map<String, Array<String>>();
introAssets.set('default', ['ready', "set", "go"]);
@ -1011,6 +1073,14 @@ class PlayState extends MusicBeatState
FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false);
FlxG.sound.music.onComplete = endSong;
vocals.play();
#if desktop
// Song duration in a float, useful for the time left feature
songLength = FlxG.sound.music.length;
// Updating Discord Rich Presence (with Time Left)
DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC, true, songLength);
#end
}
var debugNum:Int = 0;
@ -1121,6 +1191,9 @@ class PlayState extends MusicBeatState
{
// FlxG.log.add(i);
var babyArrow:FlxSprite = new FlxSprite(0, strumLine.y);
var colorswap:ColorSwap = new ColorSwap();
babyArrow.shader = colorswap.shader;
colorswap.update(Note.arrowColors[i]);
switch (curStage)
{
@ -1173,22 +1246,22 @@ class PlayState extends MusicBeatState
{
case 0:
babyArrow.x += Note.swagWidth * 0;
babyArrow.animation.addByPrefix('static', 'arrowLEFT');
babyArrow.animation.addByPrefix('static', 'arrow static instance 1');
babyArrow.animation.addByPrefix('pressed', 'left press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false);
case 1:
babyArrow.x += Note.swagWidth * 1;
babyArrow.animation.addByPrefix('static', 'arrowDOWN');
babyArrow.animation.addByPrefix('static', 'arrow static instance 2');
babyArrow.animation.addByPrefix('pressed', 'down press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false);
case 2:
babyArrow.x += Note.swagWidth * 2;
babyArrow.animation.addByPrefix('static', 'arrowUP');
babyArrow.animation.addByPrefix('static', 'arrow static instance 4');
babyArrow.animation.addByPrefix('pressed', 'up press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false);
case 3:
babyArrow.x += Note.swagWidth * 3;
babyArrow.animation.addByPrefix('static', 'arrowRIGHT');
babyArrow.animation.addByPrefix('static', 'arrow static instance 3');
babyArrow.animation.addByPrefix('pressed', 'right press', 24, false);
babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false);
}
@ -1253,11 +1326,53 @@ class PlayState extends MusicBeatState
if (!startTimer.finished)
startTimer.active = true;
paused = false;
#if desktop
if (startTimer.finished)
{
DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC, true, songLength - Conductor.songPosition);
}
else
{
DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC);
}
#end
}
super.closeSubState();
}
override public function onFocus():Void
{
#if desktop
if (health > 0 && !paused)
{
if (Conductor.songPosition > 0.0)
{
DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC, true, songLength - Conductor.songPosition);
}
else
{
DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC);
}
}
#end
super.onFocus();
}
override public function onFocusLost():Void
{
#if desktop
if (health > 0 && !paused)
{
DiscordClient.changePresence(detailsPausedText, SONG.song + " (" + storyDifficultyText + ")", iconRPC);
}
#end
super.onFocusLost();
}
function resyncVocals():Void
{
vocals.pause();
@ -1279,11 +1394,39 @@ class PlayState extends MusicBeatState
#end
if (FlxG.keys.justPressed.NINE)
iconP1.swapOldIcon();
// do this BEFORE super.update() so songPosition is accurate
if (startingSong)
{
if (iconP1.animation.curAnim.name == 'bf-old')
iconP1.animation.play(SONG.player1);
else
iconP1.animation.play('bf-old');
if (startedCountdown)
{
Conductor.songPosition += FlxG.elapsed * 1000;
if (Conductor.songPosition >= 0)
startSong();
}
}
else
{
// Conductor.songPosition = FlxG.sound.music.time;
Conductor.songPosition += FlxG.elapsed * 1000;
if (!paused)
{
songTime += FlxG.game.ticks - previousFrameTime;
previousFrameTime = FlxG.game.ticks;
// Interpolation type beat
if (Conductor.lastSongPos != Conductor.songPosition)
{
songTime = (songTime + Conductor.songPosition) / 2;
Conductor.lastSongPos = Conductor.songPosition;
// Conductor.songPosition += FlxG.elapsed * 1000;
// trace('MISSED FRAME');
}
}
// Conductor.lastSongPos = FlxG.sound.music.time;
}
switch (curStage)
@ -1306,7 +1449,7 @@ class PlayState extends MusicBeatState
scoreTxt.text = "Score:" + songScore;
if (FlxG.keys.justPressed.ENTER && startedCountdown && canPause)
if (controls.PAUSE && startedCountdown && canPause)
{
persistentUpdate = false;
persistentDraw = true;
@ -1326,11 +1469,19 @@ class PlayState extends MusicBeatState
pauseSubState.camera = camHUD;
boyfriendPos.put();
}
#if desktop
DiscordClient.changePresence(detailsPausedText, SONG.song + " (" + storyDifficultyText + ")", iconRPC);
#end
}
if (FlxG.keys.justPressed.SEVEN)
{
FlxG.switchState(new ChartingState());
#if desktop
DiscordClient.changePresence("Chart Editor", null, null, true);
#end
}
// FlxG.watch.addQuick('VOL', vocals.amplitudeLeft);
@ -1368,38 +1519,6 @@ class PlayState extends MusicBeatState
FlxG.switchState(new AnimationDebug(SONG.player2));
#end
if (startingSong)
{
if (startedCountdown)
{
Conductor.songPosition += FlxG.elapsed * 1000;
if (Conductor.songPosition >= 0)
startSong();
}
}
else
{
// Conductor.songPosition = FlxG.sound.music.time;
Conductor.songPosition += FlxG.elapsed * 1000;
if (!paused)
{
songTime += FlxG.game.ticks - previousFrameTime;
previousFrameTime = FlxG.game.ticks;
// Interpolation type beat
if (Conductor.lastSongPos != Conductor.songPosition)
{
songTime = (songTime + Conductor.songPosition) / 2;
Conductor.lastSongPos = Conductor.songPosition;
// Conductor.songPosition += FlxG.elapsed * 1000;
// trace('MISSED FRAME');
}
}
// Conductor.lastSongPos = FlxG.sound.music.time;
}
if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null)
{
if (curBeat % 4 == 0)
@ -1529,6 +1648,11 @@ class PlayState extends MusicBeatState
openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
// FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
#if desktop
// Game Over doesn't get his own variable because it's only used here
DiscordClient.changePresence("Game Over - " + detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC);
#end
}
if (unspawnNotes[0] != null)
@ -1893,8 +2017,11 @@ class PlayState extends MusicBeatState
var controlArray:Array<Bool> = [leftP, downP, upP, rightP];
// FlxG.watch.addQuick('asdfa', upP);
if ((upP || rightP || downP || leftP) && !boyfriend.stunned && generatedMusic)
if ((upP || rightP || downP || leftP) && generatedMusic)
{
// note to self, used to have stunned
// && !boyfriend.stunned
boyfriend.holdTimer = 0;
var possibleNotes:Array<Note> = [];
@ -2213,8 +2340,7 @@ class PlayState extends MusicBeatState
function trainStart():Void
{
trainMoving = true;
if (!trainSound.playing)
trainSound.play(true);
trainSound.play(true);
}
var startedMoving:Bool = false;
@ -2304,10 +2430,6 @@ class PlayState extends MusicBeatState
}
// else
// Conductor.changeBPM(SONG.bpm);
// Dad doesnt interupt his own notes
if (SONG.notes[Math.floor(curStep / 16)].mustHitSection)
dad.dance();
}
// FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM);
wiggleShit.update(Conductor.crochet);
@ -2336,9 +2458,17 @@ class PlayState extends MusicBeatState
gf.dance();
}
if (!boyfriend.animation.curAnim.name.startsWith("sing"))
if (curBeat % 2 == 0)
{
boyfriend.playAnim('idle');
if (!boyfriend.animation.curAnim.name.startsWith("sing"))
boyfriend.playAnim('idle');
if (!dad.animation.curAnim.name.startsWith("sing"))
dad.dance();
}
else if (dad.curCharacter == 'spooky')
{
if (!dad.animation.curAnim.name.startsWith("sing"))
dad.dance();
}
if (curBeat % 8 == 7 && curSong == 'Bopeebo')
@ -2398,6 +2528,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();

View File

@ -1,5 +1,8 @@
package;
#if desktop
import Discord.DiscordClient;
#end
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.addons.transition.FlxTransitionableState;
@ -109,6 +112,11 @@ class StoryMenuState extends MusicBeatState
add(grpLocks);
trace("Line 70");
#if desktop
// Updating Discord Rich Presence
DiscordClient.changePresence("In the Menus", null);
#end
for (i in 0...weekData.length)
{

76
source/TankmenBG.hx Normal file
View File

@ -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();
}
}
}

View File

@ -16,9 +16,15 @@ import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import lime.app.Application;
import openfl.Assets;
import shaderslmfao.ColorSwap;
using StringTools;
#if desktop
import Discord.DiscordClient;
import sys.thread.Thread;
#end
class TitleState extends MusicBeatState
{
static var initialized:Bool = false;
@ -33,12 +39,18 @@ class TitleState extends MusicBeatState
var wackyImage:FlxSprite;
var lastBeat:Int = 0;
var swagShader:ColorSwap;
override public function create():Void
{
#if polymod
polymod.Polymod.init({modRoot: "mods", dirs: ['introMod'], framework: OPENFL});
#end
swagShader = new ColorSwap();
FlxG.sound.muteKeys = [ZERO];
curWacky = FlxG.random.getObject(getIntroTextShit());
@ -79,6 +91,10 @@ class TitleState extends MusicBeatState
startIntro();
});
#end
#if desktop
DiscordClient.initialize();
#end
}
var logoBl:FlxSprite;
@ -122,6 +138,7 @@ class TitleState extends MusicBeatState
// bg.antialiasing = true;
// bg.setGraphicSize(Std.int(bg.width * 0.6));
// bg.updateHitbox();
add(bg);
logoBl = new FlxSprite(-150, -100);
@ -130,6 +147,10 @@ class TitleState extends MusicBeatState
logoBl.animation.addByPrefix('bump', 'logo bumpin', 24);
logoBl.animation.play('bump');
logoBl.updateHitbox();
logoBl.shader = swagShader.shader;
// trace();
// logoBl.screenCenter();
// logoBl.color = FlxColor.BLACK;
@ -139,6 +160,9 @@ class TitleState extends MusicBeatState
gfDance.animation.addByIndices('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
gfDance.antialiasing = true;
add(gfDance);
gfDance.shader = swagShader.shader;
add(logoBl);
titleText = new FlxSprite(100, FlxG.height * 0.8);
@ -300,11 +324,21 @@ class TitleState extends MusicBeatState
// FlxG.sound.play(Paths.music('titleShoot'), 0.7);
}
if (pressedEnter && !skippedIntro)
if (pressedEnter && !skippedIntro && initialized)
{
skipIntro();
}
if (controls.UI_LEFT)
{
swagShader.update(-elapsed * 0.1);
}
if (controls.UI_RIGHT)
{
swagShader.update(elapsed * 0.1);
}
super.update(elapsed);
}
@ -338,11 +372,14 @@ class TitleState extends MusicBeatState
}
}
var isRainbow:Bool = false;
override function beatHit()
{
super.beatHit();
logoBl.animation.play('bump');
logoBl.animation.play('bump', true);
danceLeft = !danceLeft;
if (danceLeft)
@ -351,57 +388,65 @@ class TitleState extends MusicBeatState
gfDance.animation.play('danceLeft');
FlxG.log.add(curBeat);
switch (curBeat)
// if the user is draggin the window some beats will
// be missed so this is just to compensate
if (curBeat > lastBeat)
{
case 1:
createCoolText(['ninjamuffin99', 'phantomArcade', 'kawaisprite', 'evilsk8er']);
// credTextShit.visible = true;
case 3:
addMoreText('present');
// credTextShit.text += '\npresent...';
// credTextShit.addText();
case 4:
deleteCoolText();
// credTextShit.visible = false;
// credTextShit.text = 'In association \nwith';
// credTextShit.screenCenter();
case 5:
createCoolText(['In association', 'with']);
case 7:
addMoreText('newgrounds');
ngSpr.visible = true;
// credTextShit.text += '\nNewgrounds';
case 8:
deleteCoolText();
ngSpr.visible = false;
// credTextShit.visible = false;
for (i in lastBeat...curBeat)
{
switch (i + 1)
{
case 1:
createCoolText(['ninjamuffin99', 'phantomArcade', 'kawaisprite', 'evilsk8er']);
// credTextShit.visible = true;
case 3:
addMoreText('present');
// credTextShit.text += '\npresent...';
// credTextShit.addText();
case 4:
deleteCoolText();
// credTextShit.visible = false;
// credTextShit.text = 'In association \nwith';
// credTextShit.screenCenter();
case 5:
createCoolText(['In association', 'with']);
case 7:
addMoreText('newgrounds');
ngSpr.visible = true;
// credTextShit.text += '\nNewgrounds';
case 8:
deleteCoolText();
ngSpr.visible = false;
// credTextShit.visible = false;
// credTextShit.text = 'Shoutouts Tom Fulp';
// credTextShit.screenCenter();
case 9:
createCoolText([curWacky[0]]);
// credTextShit.visible = true;
case 11:
addMoreText(curWacky[1]);
// credTextShit.text += '\nlmao';
case 12:
deleteCoolText();
// credTextShit.visible = false;
// credTextShit.text = "Friday";
// credTextShit.screenCenter();
case 13:
addMoreText('Friday');
// credTextShit.visible = true;
case 14:
addMoreText('Night');
// credTextShit.text += '\nNight';
case 15:
addMoreText('Funkin'); // credTextShit.text += '\nFunkin';
// credTextShit.text = 'Shoutouts Tom Fulp';
// credTextShit.screenCenter();
case 9:
createCoolText([curWacky[0]]);
// credTextShit.visible = true;
case 11:
addMoreText(curWacky[1]);
// credTextShit.text += '\nlmao';
case 12:
deleteCoolText();
// credTextShit.visible = false;
// credTextShit.text = "Friday";
// credTextShit.screenCenter();
case 13:
addMoreText('Friday');
// credTextShit.visible = true;
case 14:
addMoreText('Night');
// credTextShit.text += '\nNight';
case 15:
addMoreText('Funkin'); // credTextShit.text += '\nFunkin';
case 16:
skipIntro();
case 16:
skipIntro();
}
}
}
lastBeat = curBeat;
}
var skippedIntro:Bool = false;

View File

@ -0,0 +1,105 @@
package shaderslmfao;
import flixel.system.FlxAssets.FlxShader;
import flixel.util.FlxColor;
class ColorSwap
{
public var shader(default, null):ColorSwapShader;
public var colorToReplace(default, set):FlxColor;
public var newColor(default, set):FlxColor;
public var daTime(default, set):Float;
public var hueShit:Float = 0;
public function new():Void
{
shader = new ColorSwapShader();
shader.uTime.value = [0];
shader.money.value = [0];
}
public function update(elapsed:Float):Void
{
shader.uTime.value[0] += elapsed;
hueShit += elapsed;
// trace(shader.money.value[0]);
}
function set_colorToReplace(color:FlxColor):FlxColor
{
colorToReplace = color;
return color;
}
function set_daTime(daTime:Float):Float
{
return daTime;
}
function set_newColor(color:FlxColor):FlxColor
{
newColor = color;
return color;
}
}
class ColorSwapShader extends FlxShader
{
@:glFragmentSource('
#pragma header
uniform float uTime;
uniform float money;
vec3 normalizeColor(vec3 color)
{
return vec3(
color[0] / 255.0,
color[1] / 255.0,
color[2] / 255.0
);
}
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void main()
{
vec4 color = flixel_texture2D(bitmap, openfl_TextureCoordv);
vec4 swagColor = vec4(rgb2hsv(vec3(color[0], color[1], color[2])), color[3]);
// [0] is the hue???
swagColor[0] += uTime;
// swagColor[1] += uTime;
// money += swagColor[0];
color = vec4(hsv2rgb(vec3(swagColor[0], swagColor[1], swagColor[2])), swagColor[3]);
gl_FragColor = color;
}
')
public function new()
{
super();
}
}