package; import Section.SwagSection; import Song.SwagSong; import WiggleEffect.WiggleEffectType; import flixel.FlxBasic; import flixel.FlxCamera; import flixel.FlxG; import flixel.FlxGame; import flixel.FlxObject; import flixel.FlxSprite; import flixel.FlxState; import flixel.FlxSubState; import flixel.addons.display.FlxGridOverlay; import flixel.addons.effects.FlxTrail; import flixel.addons.effects.FlxTrailArea; import flixel.addons.effects.chainable.FlxEffectSprite; import flixel.addons.effects.chainable.FlxWaveEffect; import flixel.addons.transition.FlxTransitionableState; import flixel.graphics.atlas.FlxAtlas; import flixel.graphics.frames.FlxAtlasFrames; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.math.FlxMath; import flixel.math.FlxPoint; import flixel.math.FlxRect; import flixel.system.FlxSound; import flixel.text.FlxText; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.ui.FlxBar; import flixel.util.FlxCollision; import flixel.util.FlxColor; import flixel.util.FlxSort; import flixel.util.FlxStringUtil; import flixel.util.FlxTimer; import haxe.Json; import lime.utils.Assets; import openfl.display.BlendMode; import openfl.display.StageQuality; import openfl.filters.ShaderFilter; import shaderslmfao.ColorSwap; import ui.PreferencesMenu; using StringTools; #if discord_rpc import Discord.DiscordClient; #end class PlayState extends MusicBeatState { public static var curStage:String = ''; public static var SONG:SwagSong; public static var isStoryMode:Bool = false; public static var storyWeek:Int = 0; public static var storyPlaylist:Array = []; public static var storyDifficulty:Int = 1; public static var deathCounter:Int = 0; public static var practiceMode:Bool = false; var halloweenLevel:Bool = false; private var vocals:FlxSound; private var dad:Character; private var gf:Character; private var boyfriend:Boyfriend; private var notes:FlxTypedGroup; private var unspawnNotes:Array = []; private var strumLine:FlxSprite; private var curSection:Int = 0; private var camFollow:FlxObject; private static var prevCamFollow:FlxObject; private var strumLineNotes:FlxTypedGroup; private var playerStrums:FlxTypedGroup; private var camZooming:Bool = false; private var curSong:String = ""; private var gfSpeed:Int = 1; private var health:Float = 1; private var combo:Int = 0; private var healthBarBG:FlxSprite; private var healthBar:FlxBar; private var generatedMusic:Bool = false; private var startingSong:Bool = false; private var iconP1:HealthIcon; private var iconP2:HealthIcon; private var camHUD:FlxCamera; private var camGame:FlxCamera; var dialogue:Array = ['blah blah blah', 'coolswag']; var halloweenBG:FlxSprite; var isHalloween:Bool = false; var phillyCityLights:FlxTypedGroup; var phillyTrain:FlxSprite; var trainSound:FlxSound; var foregroundSprites:FlxTypedGroup; var limo:FlxSprite; var grpLimoDancers:FlxTypedGroup; var fastCar:FlxSprite; var upperBoppers:FlxSprite; var bottomBoppers:FlxSprite; var santa:FlxSprite; var bgGirls:BackgroundGirls; var wiggleShit:WiggleEffect = new WiggleEffect(); var tankmanRun:FlxTypedGroup; var talking:Bool = true; var songScore:Int = 0; var scoreTxt:FlxText; public static var campaignScore:Int = 0; var defaultCamZoom:Float = 1.05; // how big to stretch the pixel art assets public static var daPixelZoom:Float = 6; var inCutscene:Bool = false; #if discord_rpc // 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) FlxG.sound.music.stop(); // var gameCam:FlxCamera = FlxG.camera; camGame = new FlxCamera(); camHUD = new FlxCamera(); camHUD.bgColor.alpha = 0; FlxG.cameras.reset(camGame); FlxG.cameras.add(camHUD, false); persistentUpdate = true; persistentDraw = true; if (SONG == null) SONG = Song.loadFromJson('tutorial'); Conductor.mapBPMChanges(SONG); Conductor.changeBPM(SONG.bpm); foregroundSprites = new FlxTypedGroup(); switch (SONG.song.toLowerCase()) { case 'tutorial': dialogue = ["Hey you're pretty cute.", 'Use the arrow keys to keep up \nwith me singing.']; case 'bopeebo': dialogue = [ 'HEY!', "You think you can just sing\nwith my daughter like that?", "If you want to date her...", "You're going to have to go \nthrough ME first!" ]; case 'fresh': dialogue = ["Not too shabby boy.", ""]; case 'dadbattle': dialogue = [ "gah you think you're hot stuff?", "If you can beat me here...", "Only then I will even CONSIDER letting you\ndate my daughter!" ]; case 'senpai': dialogue = CoolUtil.coolTextFile(Paths.txt('senpai/senpaiDialogue')); case 'roses': dialogue = CoolUtil.coolTextFile(Paths.txt('roses/rosesDialogue')); case 'thorns': dialogue = CoolUtil.coolTextFile(Paths.txt('thorns/thornsDialogue')); } initDiscord(); switch (SONG.song.toLowerCase()) { case 'spookeez' | 'monster' | 'south': curStage = "spooky"; halloweenLevel = true; var hallowTex = Paths.getSparrowAtlas('halloween_bg'); halloweenBG = new FlxSprite(-200, -100); halloweenBG.frames = hallowTex; halloweenBG.animation.addByPrefix('idle', 'halloweem bg0'); halloweenBG.animation.addByPrefix('lightning', 'halloweem bg lightning strike', 24, false); halloweenBG.animation.play('idle'); halloweenBG.antialiasing = true; add(halloweenBG); isHalloween = true; case 'pico' | 'blammed' | 'philly': curStage = 'philly'; var bg:FlxSprite = new FlxSprite(-100).loadGraphic(Paths.image('philly/sky')); bg.scrollFactor.set(0.1, 0.1); add(bg); var city:FlxSprite = new FlxSprite(-10).loadGraphic(Paths.image('philly/city')); city.scrollFactor.set(0.3, 0.3); city.setGraphicSize(Std.int(city.width * 0.85)); city.updateHitbox(); add(city); phillyCityLights = new FlxTypedGroup(); add(phillyCityLights); for (i in 0...5) { var light:FlxSprite = new FlxSprite(city.x).loadGraphic(Paths.image('philly/win' + i)); light.scrollFactor.set(0.3, 0.3); light.visible = false; light.setGraphicSize(Std.int(light.width * 0.85)); light.updateHitbox(); light.antialiasing = true; phillyCityLights.add(light); } var streetBehind:FlxSprite = new FlxSprite(-40, 50).loadGraphic(Paths.image('philly/behindTrain')); add(streetBehind); phillyTrain = new FlxSprite(2000, 360).loadGraphic(Paths.image('philly/train')); add(phillyTrain); trainSound = new FlxSound().loadEmbedded(Paths.sound('train_passes')); FlxG.sound.list.add(trainSound); // var cityLights:FlxSprite = new FlxSprite().loadGraphic(AssetPaths.win0.png); var street:FlxSprite = new FlxSprite(-40, streetBehind.y).loadGraphic(Paths.image('philly/street')); add(street); case "milf" | 'satin-panties' | 'high': curStage = 'limo'; defaultCamZoom = 0.90; var skyBG:FlxSprite = new FlxSprite(-120, -50).loadGraphic(Paths.image('limo/limoSunset')); skyBG.scrollFactor.set(0.1, 0.1); add(skyBG); var bgLimo:FlxSprite = new FlxSprite(-200, 480); bgLimo.frames = Paths.getSparrowAtlas('limo/bgLimo'); bgLimo.animation.addByPrefix('drive', "background limo pink", 24); bgLimo.animation.play('drive'); bgLimo.scrollFactor.set(0.4, 0.4); add(bgLimo); grpLimoDancers = new FlxTypedGroup(); add(grpLimoDancers); for (i in 0...5) { var dancer:BackgroundDancer = new BackgroundDancer((370 * i) + 130, bgLimo.y - 400); dancer.scrollFactor.set(0.4, 0.4); grpLimoDancers.add(dancer); } var overlayShit:FlxSprite = new FlxSprite(-500, -600).loadGraphic(Paths.image('limo/limoOverlay')); overlayShit.alpha = 0.5; // add(overlayShit); // var shaderBullshit = new BlendModeEffect(new OverlayShader(), FlxColor.RED); // FlxG.camera.setFilters([new ShaderFilter(cast shaderBullshit.shader)]); // overlayShit.shader = shaderBullshit; limo = new FlxSprite(-120, 550); limo.frames = Paths.getSparrowAtlas('limo/limoDrive'); limo.animation.addByPrefix('drive', "Limo stage", 24); limo.animation.play('drive'); limo.antialiasing = true; fastCar = new FlxSprite(-300, 160).loadGraphic(Paths.image('limo/fastCarLol')); // add(limo); case "cocoa" | 'eggnog': curStage = 'mall'; defaultCamZoom = 0.80; var bg:FlxSprite = new FlxSprite(-1000, -500).loadGraphic(Paths.image('christmas/bgWalls')); bg.antialiasing = true; bg.scrollFactor.set(0.2, 0.2); bg.active = false; bg.setGraphicSize(Std.int(bg.width * 0.8)); bg.updateHitbox(); add(bg); upperBoppers = new FlxSprite(-240, -90); upperBoppers.frames = Paths.getSparrowAtlas('christmas/upperBop'); upperBoppers.animation.addByPrefix('bop', "Upper Crowd Bob", 24, false); upperBoppers.antialiasing = true; upperBoppers.scrollFactor.set(0.33, 0.33); upperBoppers.setGraphicSize(Std.int(upperBoppers.width * 0.85)); upperBoppers.updateHitbox(); add(upperBoppers); var bgEscalator:FlxSprite = new FlxSprite(-1100, -600).loadGraphic(Paths.image('christmas/bgEscalator')); bgEscalator.antialiasing = true; bgEscalator.scrollFactor.set(0.3, 0.3); bgEscalator.active = false; bgEscalator.setGraphicSize(Std.int(bgEscalator.width * 0.9)); bgEscalator.updateHitbox(); add(bgEscalator); var tree:FlxSprite = new FlxSprite(370, -250).loadGraphic(Paths.image('christmas/christmasTree')); tree.antialiasing = true; tree.scrollFactor.set(0.40, 0.40); add(tree); bottomBoppers = new FlxSprite(-300, 140); bottomBoppers.frames = Paths.getSparrowAtlas('christmas/bottomBop'); bottomBoppers.animation.addByPrefix('bop', 'Bottom Level Boppers', 24, false); bottomBoppers.antialiasing = true; bottomBoppers.scrollFactor.set(0.9, 0.9); bottomBoppers.setGraphicSize(Std.int(bottomBoppers.width * 1)); bottomBoppers.updateHitbox(); add(bottomBoppers); var fgSnow:FlxSprite = new FlxSprite(-600, 700).loadGraphic(Paths.image('christmas/fgSnow')); fgSnow.active = false; fgSnow.antialiasing = true; add(fgSnow); santa = new FlxSprite(-840, 150); santa.frames = Paths.getSparrowAtlas('christmas/santa'); santa.animation.addByPrefix('idle', 'santa idle in fear', 24, false); santa.antialiasing = true; add(santa); case 'winter-horrorland': curStage = 'mallEvil'; var bg:FlxSprite = new FlxSprite(-400, -500).loadGraphic(Paths.image('christmas/evilBG')); bg.antialiasing = true; bg.scrollFactor.set(0.2, 0.2); bg.active = false; bg.setGraphicSize(Std.int(bg.width * 0.8)); bg.updateHitbox(); add(bg); var evilTree:FlxSprite = new FlxSprite(300, -300).loadGraphic(Paths.image('christmas/evilTree')); evilTree.antialiasing = true; evilTree.scrollFactor.set(0.2, 0.2); add(evilTree); var evilSnow:FlxSprite = new FlxSprite(-200, 700).loadGraphic(Paths.image("christmas/evilSnow")); evilSnow.antialiasing = true; add(evilSnow); case 'senpai' | 'roses': curStage = 'school'; // defaultCamZoom = 0.9; var bgSky = new FlxSprite().loadGraphic(Paths.image('weeb/weebSky')); bgSky.scrollFactor.set(0.1, 0.1); add(bgSky); var repositionShit = -200; var bgSchool:FlxSprite = new FlxSprite(repositionShit, 0).loadGraphic(Paths.image('weeb/weebSchool')); bgSchool.scrollFactor.set(0.6, 0.90); add(bgSchool); var bgStreet:FlxSprite = new FlxSprite(repositionShit).loadGraphic(Paths.image('weeb/weebStreet')); bgStreet.scrollFactor.set(0.95, 0.95); add(bgStreet); var fgTrees:FlxSprite = new FlxSprite(repositionShit + 170, 130).loadGraphic(Paths.image('weeb/weebTreesBack')); fgTrees.scrollFactor.set(0.9, 0.9); add(fgTrees); var bgTrees:FlxSprite = new FlxSprite(repositionShit - 380, -800); var treetex = Paths.getPackerAtlas('weeb/weebTrees'); bgTrees.frames = treetex; bgTrees.animation.add('treeLoop', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], 12); bgTrees.animation.play('treeLoop'); bgTrees.scrollFactor.set(0.85, 0.85); add(bgTrees); var treeLeaves:FlxSprite = new FlxSprite(repositionShit, -40); treeLeaves.frames = Paths.getSparrowAtlas('weeb/petals'); treeLeaves.animation.addByPrefix('leaves', 'PETALS ALL', 24, true); treeLeaves.animation.play('leaves'); treeLeaves.scrollFactor.set(0.85, 0.85); add(treeLeaves); var widShit = Std.int(bgSky.width * 6); bgSky.setGraphicSize(widShit); bgSchool.setGraphicSize(widShit); bgStreet.setGraphicSize(widShit); bgTrees.setGraphicSize(Std.int(widShit * 1.4)); fgTrees.setGraphicSize(Std.int(widShit * 0.8)); treeLeaves.setGraphicSize(widShit); fgTrees.updateHitbox(); bgSky.updateHitbox(); bgSchool.updateHitbox(); bgStreet.updateHitbox(); bgTrees.updateHitbox(); treeLeaves.updateHitbox(); bgGirls = new BackgroundGirls(-100, 190); bgGirls.scrollFactor.set(0.9, 0.9); if (SONG.song.toLowerCase() == 'roses') { bgGirls.getScared(); } bgGirls.setGraphicSize(Std.int(bgGirls.width * daPixelZoom)); bgGirls.updateHitbox(); add(bgGirls); case 'thorns': curStage = 'schoolEvil'; var waveEffectBG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 3, 2); var waveEffectFG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 5, 2); var posX = 400; var posY = 200; var bg:FlxSprite = new FlxSprite(posX, posY); bg.frames = Paths.getSparrowAtlas('weeb/animatedEvilSchool'); bg.animation.addByPrefix('idle', 'background 2', 24); bg.animation.play('idle'); bg.scrollFactor.set(0.8, 0.9); bg.scale.set(6, 6); add(bg); /* var bg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolBG')); bg.scale.set(6, 6); // bg.setGraphicSize(Std.int(bg.width * 6)); // bg.updateHitbox(); add(bg); var fg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolFG')); fg.scale.set(6, 6); // fg.setGraphicSize(Std.int(fg.width * 6)); // fg.updateHitbox(); add(fg); wiggleShit.effectType = WiggleEffectType.DREAMY; wiggleShit.waveAmplitude = 0.01; wiggleShit.waveFrequency = 60; wiggleShit.waveSpeed = 0.8; */ // bg.shader = wiggleShit.shader; // fg.shader = wiggleShit.shader; /* var waveSprite = new FlxEffectSprite(bg, [waveEffectBG]); var waveSpriteFG = new FlxEffectSprite(fg, [waveEffectFG]); // Using scale since setGraphicSize() doesnt work??? waveSprite.scale.set(6, 6); waveSpriteFG.scale.set(6, 6); waveSprite.setPosition(posX, posY); waveSpriteFG.setPosition(posX, posY); waveSprite.scrollFactor.set(0.7, 0.8); waveSpriteFG.scrollFactor.set(0.9, 0.8); // waveSprite.setGraphicSize(Std.int(waveSprite.width * 6)); // waveSprite.updateHitbox(); // waveSpriteFG.setGraphicSize(Std.int(fg.width * 6)); // waveSpriteFG.updateHitbox(); add(waveSprite); add(waveSpriteFG); */ case 'guns' | 'stress' | 'ugh': defaultCamZoom = 0.90; curStage = 'tank'; var bg:BGSprite = new BGSprite('tankSky', 0, -200, 0, 0); add(bg); var tankSky:BGSprite = new BGSprite('tankClouds', 0, 10, 0.1, 0.1); add(tankSky); var tankMountains:BGSprite = new BGSprite('tankMountains', -100, 150, 0.2, 0.2); add(tankMountains); var tankBuildings:BGSprite = new BGSprite('tankBuildings', -200, 370, 0.25, 0.25); add(tankBuildings); var tankRuins:BGSprite = new BGSprite('tankRuins', -200, 170, 0.35, 0.35); add(tankRuins); var tankWatchtower:BGSprite = new BGSprite('tankWatchtower', 300, 50, 0.5, 0.5); add(tankWatchtower); 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); var fgTank1:BGSprite = new BGSprite('tank1', -100, 680, 2, 0.2, ['fg']); foregroundSprites.add(fgTank1); // just called 'foreground' just cuz small inconsistency no bbiggei var fgTank2:BGSprite = new BGSprite('tank2', 450, 840, 1.5, 1.5, ['foreground']); foregroundSprites.add(fgTank2); var fgTank4:BGSprite = new BGSprite('tank4', 1000, 880, 1.5, 1.5, ['fg']); foregroundSprites.add(fgTank4); var fgTank5:BGSprite = new BGSprite('tank5', 1400, 600, 1.5, 1.5, ['fg']); foregroundSprites.add(fgTank5); var fgTank3:BGSprite = new BGSprite('tank3', 1300, 1130, 3.5, 2.5, ['fg']); foregroundSprites.add(fgTank3); default: defaultCamZoom = 0.9; curStage = 'stage'; var bg:BGSprite = new BGSprite('stageback', -600, -200, 0.9, 0.9); add(bg); var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront')); stageFront.setGraphicSize(Std.int(stageFront.width * 1.1)); stageFront.updateHitbox(); stageFront.antialiasing = true; stageFront.scrollFactor.set(0.9, 0.9); stageFront.active = false; add(stageFront); var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains')); stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9)); stageCurtains.updateHitbox(); stageCurtains.antialiasing = true; stageCurtains.scrollFactor.set(1.3, 1.3); stageCurtains.active = false; add(stageCurtains); } var gfVersion:String = 'gf'; switch (curStage) { case 'limo': gfVersion = 'gf-car'; case 'mall' | 'mallEvil': gfVersion = 'gf-christmas'; case 'school': gfVersion = 'gf-pixel'; case 'schoolEvil': gfVersion = 'gf-pixel'; } 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; for (i in 0...TankmenBG.animationNotes.length) { var tankman:TankmenBG = new TankmenBG(500, 200 + FlxG.random.int(0, 150), TankmenBG.animationNotes[i][1] < 2); tankman.strumTime = TankmenBG.animationNotes[i][0]; tankmanRun.add(tankman); } } dad = new Character(100, 100, SONG.player2); var camPos:FlxPoint = new FlxPoint(dad.getGraphicMidpoint().x, dad.getGraphicMidpoint().y); switch (SONG.player2) { case 'gf': dad.setPosition(gf.x, gf.y); gf.visible = false; if (isStoryMode) { camPos.x += 600; tweenCamIn(); } case "spooky": dad.y += 200; case "monster": dad.y += 100; case 'monster-christmas': dad.y += 130; case 'dad': camPos.x += 400; case 'pico': camPos.x += 600; dad.y += 300; case 'parents-christmas': dad.x -= 500; case 'senpai': dad.x += 150; dad.y += 360; camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); case 'senpai-angry': dad.x += 150; dad.y += 360; camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); case 'spirit': dad.x -= 150; dad.y += 100; camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); case 'tankman': dad.y += 180; } boyfriend = new Boyfriend(770, 450, SONG.player1); switch (SONG.player1) { case "bf-holding-gf": boyfriend.y -= 140; } // REPOSITIONING PER STAGE switch (curStage) { case 'limo': boyfriend.y -= 220; boyfriend.x += 260; resetFastCar(); add(fastCar); case 'mall': boyfriend.x += 200; case 'mallEvil': boyfriend.x += 320; dad.y -= 80; case 'school': boyfriend.x += 200; boyfriend.y += 220; gf.x += 180; gf.y += 300; case 'schoolEvil': // trailArea.scrollFactor.set(); var evilTrail = new FlxTrail(dad, null, 4, 24, 0.3, 0.069); // evilTrail.changeValuesEnabled(false, false, false, false); // evilTrail.changeGraphic() add(evilTrail); // evilTrail.scrollFactor.set(1.1, 1.1); boyfriend.x += 200; boyfriend.y += 220; gf.x += 180; gf.y += 300; } add(gf); // Shitty layering but whatev it works LOL if (curStage == 'limo') add(limo); add(dad); add(boyfriend); add(foregroundSprites); var doof:DialogueBox = new DialogueBox(false, dialogue); // doof.x += 70; // doof.y = FlxG.height * 0.5; doof.scrollFactor.set(); doof.finishThing = startCountdown; Conductor.songPosition = -5000; strumLine = new FlxSprite(0, 50).makeGraphic(FlxG.width, 10); if (PreferencesMenu.getPref('downscroll')) { strumLine.y = FlxG.height - 150; // 150 just random ass number lol } strumLine.scrollFactor.set(); strumLineNotes = new FlxTypedGroup(); add(strumLineNotes); playerStrums = new FlxTypedGroup(); // startCountdown(); generateSong(); // add(strumLine); camFollow = new FlxObject(0, 0, 1, 1); camFollow.setPosition(camPos.x, camPos.y); if (prevCamFollow != null) { camFollow = prevCamFollow; prevCamFollow = null; } add(camFollow); FlxG.camera.follow(camFollow, LOCKON, 0.04); // FlxG.camera.setScrollBounds(0, FlxG.width, 0, FlxG.height); FlxG.camera.zoom = defaultCamZoom; FlxG.camera.focusOn(camFollow.getPosition()); FlxG.worldBounds.set(0, 0, FlxG.width, FlxG.height); FlxG.fixedTimestep = false; healthBarBG = new FlxSprite(0, FlxG.height * 0.9).loadGraphic(Paths.image('healthBar')); healthBarBG.screenCenter(X); healthBarBG.scrollFactor.set(); add(healthBarBG); if (PreferencesMenu.getPref('downscroll')) healthBarBG.y = FlxG.height * 0.1; healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this, 'health', 0, 2); healthBar.scrollFactor.set(); healthBar.createFilledBar(0xFFFF0000, 0xFF66FF33); // healthBar add(healthBar); scoreTxt = new FlxText(healthBarBG.x + healthBarBG.width - 190, healthBarBG.y + 30, 0, "", 20); scoreTxt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); scoreTxt.scrollFactor.set(); add(scoreTxt); iconP1 = new HealthIcon(SONG.player1, true); iconP1.y = healthBar.y - (iconP1.height / 2); add(iconP1); iconP2 = new HealthIcon(SONG.player2, false); iconP2.y = healthBar.y - (iconP2.height / 2); add(iconP2); strumLineNotes.cameras = [camHUD]; notes.cameras = [camHUD]; healthBar.cameras = [camHUD]; healthBarBG.cameras = [camHUD]; iconP1.cameras = [camHUD]; iconP2.cameras = [camHUD]; scoreTxt.cameras = [camHUD]; doof.cameras = [camHUD]; // if (SONG.song == 'South') // FlxG.camera.alpha = 0.7; // UI_camera.zoom = 1; // cameras = [FlxG.cameras.list[1]]; startingSong = true; if (isStoryMode) { switch (curSong.toLowerCase()) { case "winter-horrorland": var blackScreen:FlxSprite = new FlxSprite(0, 0).makeGraphic(Std.int(FlxG.width * 2), Std.int(FlxG.height * 2), FlxColor.BLACK); add(blackScreen); blackScreen.scrollFactor.set(); camHUD.visible = false; new FlxTimer().start(0.1, function(tmr:FlxTimer) { remove(blackScreen); FlxG.sound.play(Paths.sound('Lights_Turn_On')); camFollow.y = -2050; camFollow.x += 200; FlxG.camera.focusOn(camFollow.getPosition()); FlxG.camera.zoom = 1.5; new FlxTimer().start(0.8, function(tmr:FlxTimer) { camHUD.visible = true; remove(blackScreen); FlxTween.tween(FlxG.camera, {zoom: defaultCamZoom}, 2.5, { ease: FlxEase.quadInOut, onComplete: function(twn:FlxTween) { startCountdown(); } }); }); }); case 'senpai': schoolIntro(doof); case 'roses': FlxG.sound.play(Paths.sound('ANGRY')); schoolIntro(doof); case 'thorns': schoolIntro(doof); default: startCountdown(); } } else { switch (curSong.toLowerCase()) { default: startCountdown(); } } super.create(); } function initDiscord():Void { #if discord_rpc 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); black.scrollFactor.set(); add(black); var red:FlxSprite = new FlxSprite(-100, -100).makeGraphic(FlxG.width * 2, FlxG.height * 2, 0xFFff1b31); red.scrollFactor.set(); var senpaiEvil:FlxSprite = new FlxSprite(); senpaiEvil.frames = Paths.getSparrowAtlas('weeb/senpaiCrazy'); senpaiEvil.animation.addByPrefix('idle', 'Senpai Pre Explosion', 24, false); senpaiEvil.setGraphicSize(Std.int(senpaiEvil.width * 6)); senpaiEvil.scrollFactor.set(); senpaiEvil.updateHitbox(); senpaiEvil.screenCenter(); if (SONG.song.toLowerCase() == 'roses' || SONG.song.toLowerCase() == 'thorns') { remove(black); if (SONG.song.toLowerCase() == 'thorns') { add(red); } } new FlxTimer().start(0.3, function(tmr:FlxTimer) { black.alpha -= 0.15; if (black.alpha > 0) { tmr.reset(0.3); } else { if (dialogueBox != null) { inCutscene = true; if (SONG.song.toLowerCase() == 'thorns') { add(senpaiEvil); senpaiEvil.alpha = 0; new FlxTimer().start(0.3, function(swagTimer:FlxTimer) { senpaiEvil.alpha += 0.15; if (senpaiEvil.alpha < 1) { swagTimer.reset(); } else { senpaiEvil.animation.play('idle'); FlxG.sound.play(Paths.sound('Senpai_Dies'), 1, false, null, true, function() { remove(senpaiEvil); remove(red); FlxG.camera.fade(FlxColor.WHITE, 0.01, true, function() { add(dialogueBox); }, true); }); new FlxTimer().start(3.2, function(deadTime:FlxTimer) { FlxG.camera.fade(FlxColor.WHITE, 1.6, false); }); } }); } else { add(dialogueBox); } } else startCountdown(); remove(black); } }); } var startTimer:FlxTimer = new FlxTimer(); var perfectMode:Bool = false; function startCountdown():Void { inCutscene = false; generateStaticArrows(0); generateStaticArrows(1); talking = false; startedCountdown = true; Conductor.songPosition = 0; Conductor.songPosition -= Conductor.crochet * 5; var swagCounter:Int = 0; startTimer.start(Conductor.crochet / 1000, function(tmr:FlxTimer) { // 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> = new Map>(); introAssets.set('default', ['ready', "set", "go"]); introAssets.set('school', ['weeb/pixelUI/ready-pixel', 'weeb/pixelUI/set-pixel', 'weeb/pixelUI/date-pixel']); introAssets.set('schoolEvil', ['weeb/pixelUI/ready-pixel', 'weeb/pixelUI/set-pixel', 'weeb/pixelUI/date-pixel']); var introAlts:Array = introAssets.get('default'); var altSuffix:String = ""; for (value in introAssets.keys()) { if (value == curStage) { introAlts = introAssets.get(value); altSuffix = '-pixel'; } } switch (swagCounter) { case 0: FlxG.sound.play(Paths.sound('intro3' + altSuffix), 0.6); case 1: var ready:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[0])); ready.scrollFactor.set(); ready.updateHitbox(); if (curStage.startsWith('school')) ready.setGraphicSize(Std.int(ready.width * daPixelZoom)); ready.screenCenter(); add(ready); FlxTween.tween(ready, {y: ready.y += 100, alpha: 0}, Conductor.crochet / 1000, { ease: FlxEase.cubeInOut, onComplete: function(twn:FlxTween) { ready.destroy(); } }); FlxG.sound.play(Paths.sound('intro2' + altSuffix), 0.6); case 2: var set:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[1])); set.scrollFactor.set(); if (curStage.startsWith('school')) set.setGraphicSize(Std.int(set.width * daPixelZoom)); set.screenCenter(); add(set); FlxTween.tween(set, {y: set.y += 100, alpha: 0}, Conductor.crochet / 1000, { ease: FlxEase.cubeInOut, onComplete: function(twn:FlxTween) { set.destroy(); } }); FlxG.sound.play(Paths.sound('intro1' + altSuffix), 0.6); case 3: var go:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[2])); go.scrollFactor.set(); if (curStage.startsWith('school')) go.setGraphicSize(Std.int(go.width * daPixelZoom)); go.updateHitbox(); go.screenCenter(); add(go); FlxTween.tween(go, {y: go.y += 100, alpha: 0}, Conductor.crochet / 1000, { ease: FlxEase.cubeInOut, onComplete: function(twn:FlxTween) { go.destroy(); } }); FlxG.sound.play(Paths.sound('introGo' + altSuffix), 0.6); } swagCounter += 1; // generateSong('fresh'); }, 4); } var previousFrameTime:Int = 0; var lastReportedPlayheadPosition:Int = 0; var songTime:Float = 0; function startSong():Void { startingSong = false; previousFrameTime = FlxG.game.ticks; lastReportedPlayheadPosition = 0; if (!paused) FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false); FlxG.sound.music.onComplete = endSong; vocals.play(); #if discord_rpc // 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; private function generateSong():Void { // FlxG.log.add(ChartParser.parse()); var songData = SONG; Conductor.changeBPM(songData.bpm); curSong = songData.song; if (SONG.needsVoices) vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song)); else vocals = new FlxSound(); FlxG.sound.list.add(vocals); notes = new FlxTypedGroup(); add(notes); var noteData:Array; // NEW SHIT noteData = songData.notes; var playerCounter:Int = 0; var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped for (section in noteData) { var coolSection:Int = Std.int(section.lengthInSteps / 4); for (songNotes in section.sectionNotes) { var daStrumTime:Float = songNotes[0]; var daNoteData:Int = Std.int(songNotes[1] % 4); var gottaHitNote:Bool = section.mustHitSection; if (songNotes[1] > 3) { gottaHitNote = !section.mustHitSection; } var oldNote:Note; if (unspawnNotes.length > 0) oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)]; else oldNote = null; var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote); swagNote.sustainLength = songNotes[2]; swagNote.scrollFactor.set(0, 0); var susLength:Float = swagNote.sustainLength; susLength = susLength / Conductor.stepCrochet; unspawnNotes.push(swagNote); for (susNote in 0...Math.floor(susLength)) { oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)]; var sustainNote:Note = new Note(daStrumTime + (Conductor.stepCrochet * susNote) + Conductor.stepCrochet, daNoteData, oldNote, true); sustainNote.scrollFactor.set(); unspawnNotes.push(sustainNote); sustainNote.mustPress = gottaHitNote; if (sustainNote.mustPress) { sustainNote.x += FlxG.width / 2; // general offset } } swagNote.mustPress = gottaHitNote; if (swagNote.mustPress) { swagNote.x += FlxG.width / 2; // general offset } else {} } daBeats += 1; } // trace(unspawnNotes.length); // playerCounter += 1; unspawnNotes.sort(sortByShit); generatedMusic = true; } function sortByShit(Obj1:Note, Obj2:Note):Int { return FlxSort.byValues(FlxSort.ASCENDING, Obj1.strumTime, Obj2.strumTime); } private function generateStaticArrows(player:Int):Void { for (i in 0...4) { // 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) { case 'school' | 'schoolEvil': babyArrow.loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels'), true, 17, 17); babyArrow.animation.add('green', [6]); babyArrow.animation.add('red', [7]); babyArrow.animation.add('blue', [5]); babyArrow.animation.add('purplel', [4]); babyArrow.setGraphicSize(Std.int(babyArrow.width * daPixelZoom)); babyArrow.updateHitbox(); babyArrow.antialiasing = false; switch (Math.abs(i)) { case 0: babyArrow.x += Note.swagWidth * 0; babyArrow.animation.add('static', [0]); babyArrow.animation.add('pressed', [4, 8], 12, false); babyArrow.animation.add('confirm', [12, 16], 24, false); case 1: babyArrow.x += Note.swagWidth * 1; babyArrow.animation.add('static', [1]); babyArrow.animation.add('pressed', [5, 9], 12, false); babyArrow.animation.add('confirm', [13, 17], 24, false); case 2: babyArrow.x += Note.swagWidth * 2; babyArrow.animation.add('static', [2]); babyArrow.animation.add('pressed', [6, 10], 12, false); babyArrow.animation.add('confirm', [14, 18], 12, false); case 3: babyArrow.x += Note.swagWidth * 3; babyArrow.animation.add('static', [3]); babyArrow.animation.add('pressed', [7, 11], 12, false); babyArrow.animation.add('confirm', [15, 19], 24, false); } default: babyArrow.frames = Paths.getSparrowAtlas('NOTE_assets'); babyArrow.animation.addByPrefix('green', 'arrowUP'); babyArrow.animation.addByPrefix('blue', 'arrowDOWN'); babyArrow.animation.addByPrefix('purple', 'arrowLEFT'); babyArrow.animation.addByPrefix('red', 'arrowRIGHT'); babyArrow.antialiasing = true; babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7)); switch (Math.abs(i)) { case 0: babyArrow.x += Note.swagWidth * 0; 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', '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', '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', 'arrow static instance 3'); babyArrow.animation.addByPrefix('pressed', 'right press', 24, false); babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false); } } babyArrow.updateHitbox(); babyArrow.scrollFactor.set(); if (!isStoryMode) { babyArrow.y -= 10; babyArrow.alpha = 0; FlxTween.tween(babyArrow, {y: babyArrow.y + 10, alpha: 1}, 1, {ease: FlxEase.circOut, startDelay: 0.5 + (0.2 * i)}); } babyArrow.ID = i; if (player == 1) { playerStrums.add(babyArrow); } babyArrow.animation.play('static'); babyArrow.x += 50; babyArrow.x += ((FlxG.width / 2) * player); strumLineNotes.add(babyArrow); } } function tweenCamIn():Void { FlxTween.tween(FlxG.camera, {zoom: 1.3}, (Conductor.stepCrochet * 4 / 1000), {ease: FlxEase.elasticInOut}); } override function openSubState(SubState:FlxSubState) { if (paused) { if (FlxG.sound.music != null) { FlxG.sound.music.pause(); vocals.pause(); } if (!startTimer.finished) startTimer.active = false; } super.openSubState(SubState); } override function closeSubState() { if (paused) { if (FlxG.sound.music != null && !startingSong) { resyncVocals(); } if (!startTimer.finished) startTimer.active = true; paused = false; #if discord_rpc 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(); } #if discord_rpc override public function onFocus():Void { 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); } } super.onFocus(); } override public function onFocusLost():Void { if (health > 0 && !paused) { DiscordClient.changePresence(detailsPausedText, SONG.song + " (" + storyDifficultyText + ")", iconRPC); } super.onFocusLost(); } #end function resyncVocals():Void { vocals.pause(); FlxG.sound.music.play(); Conductor.songPosition = FlxG.sound.music.time; vocals.time = Conductor.songPosition; vocals.play(); } private var paused:Bool = false; var startedCountdown:Bool = false; var canPause:Bool = true; override public function update(elapsed:Float) { // makes the lerp non-dependant on the framerate FlxG.camera.followLerp = 0.04 * (elapsed / (1 / 60)); #if !debug perfectMode = false; #end if (FlxG.keys.justPressed.NINE) iconP1.swapOldIcon(); // do this BEFORE super.update() so songPosition is accurate 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; } switch (curStage) { case 'philly': if (trainMoving) { trainFrameTiming += elapsed; if (trainFrameTiming >= 1 / 24) { updateTrainPos(); trainFrameTiming = 0; } } // phillyCityLights.members[curLight].alpha -= (Conductor.crochet / 1000) * FlxG.elapsed; } super.update(elapsed); scoreTxt.text = "Score:" + songScore; if (controls.PAUSE && startedCountdown && canPause) { persistentUpdate = false; persistentDraw = true; paused = true; // 1 / 1000 chance for Gitaroo Man easter egg if (FlxG.random.bool(0.1)) { // gitaroo man easter egg FlxG.switchState(new GitarooPause()); } else { var boyfriendPos = boyfriend.getScreenPosition(); var pauseSubState = new PauseSubState(boyfriendPos.x, boyfriendPos.y); openSubState(pauseSubState); pauseSubState.camera = camHUD; boyfriendPos.put(); } #if discord_rpc DiscordClient.changePresence(detailsPausedText, SONG.song + " (" + storyDifficultyText + ")", iconRPC); #end } if (FlxG.keys.justPressed.SEVEN) { FlxG.switchState(new ChartingState()); #if discord_rpc DiscordClient.changePresence("Chart Editor", null, null, true); #end } // FlxG.watch.addQuick('VOL', vocals.amplitudeLeft); // FlxG.watch.addQuick('VOLRight', vocals.amplitudeRight); iconP1.setGraphicSize(Std.int(FlxMath.lerp(150, iconP1.width, 0.85))); iconP2.setGraphicSize(Std.int(FlxMath.lerp(150, iconP2.width, 0.85))); iconP1.updateHitbox(); iconP2.updateHitbox(); var iconOffset:Int = 26; iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01) - iconOffset); iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01)) - (iconP2.width - iconOffset); if (health > 2) health = 2; if (healthBar.percent < 20) iconP1.animation.curAnim.curFrame = 1; else iconP1.animation.curAnim.curFrame = 0; if (healthBar.percent > 80) iconP2.animation.curAnim.curFrame = 1; else iconP2.animation.curAnim.curFrame = 0; /* if (FlxG.keys.justPressed.NINE) FlxG.switchState(new Charting()); */ #if debug if (FlxG.keys.justPressed.EIGHT) FlxG.switchState(new AnimationDebug(SONG.player2)); #end if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null) { cameraRightSide = PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection; cameraMovement(); } if (camZooming) { FlxG.camera.zoom = FlxMath.lerp(defaultCamZoom, FlxG.camera.zoom, 0.95); camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95); } FlxG.watch.addQuick("beatShit", curBeat); FlxG.watch.addQuick("stepShit", curStep); if (curSong == 'Fresh') { switch (curBeat) { case 16: camZooming = true; gfSpeed = 2; case 48: gfSpeed = 1; case 80: gfSpeed = 2; case 112: gfSpeed = 1; case 163: // FlxG.sound.music.stop(); // FlxG.switchState(new TitleState()); } } if (curSong == 'Bopeebo') { switch (curBeat) { case 128, 129, 130: vocals.volume = 0; // FlxG.sound.music.stop(); // FlxG.switchState(new PlayState()); } } // better streaming of shit if (!inCutscene && !_exiting) { // RESET = Quick Game Over Screen if (controls.RESET) { health = 0; trace("RESET = True"); } #if CAN_CHEAT // brandon's a pussy if (controls.CHEAT) { health += 1; trace("User is cheating!"); } #end if (health <= 0 && !practiceMode) { boyfriend.stunned = true; persistentUpdate = false; persistentDraw = false; paused = true; vocals.stop(); FlxG.sound.music.stop(); deathCounter += 1; openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); // FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); #if discord_rpc // Game Over doesn't get his own variable because it's only used here DiscordClient.changePresence("Game Over - " + detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC); #end } } while (unspawnNotes[0] != null &&unspawnNotes[0].strumTime - Conductor.songPosition < 1500 / SONG.speed) { var dunceNote:Note = unspawnNotes[0]; notes.add(dunceNote); var index:Int = unspawnNotes.indexOf(dunceNote); unspawnNotes.splice(index, 1); } if (generatedMusic) { notes.forEachAlive(function(daNote:Note) { if (daNote.y > FlxG.height) { daNote.active = false; daNote.visible = false; } else { daNote.visible = true; daNote.active = true; } var strumLineMid = strumLine.y + Note.swagWidth / 2; if (PreferencesMenu.getPref('downscroll')) { daNote.y = (strumLine.y + (Conductor.songPosition - daNote.strumTime) * (0.45 * FlxMath.roundDecimal(SONG.speed, 2))); if (daNote.isSustainNote && (!daNote.mustPress || (daNote.wasGoodHit || (daNote.prevNote.wasGoodHit && !daNote.canBeHit))) && daNote.y - daNote.offset.y * daNote.scale.y + daNote.height >= strumLineMid) { // div by scale because cliprect is affected by scale i THINK var swagRect:FlxRect = new FlxRect(0, 0, daNote.width / daNote.scale.x, daNote.height / daNote.scale.y); swagRect.height = (strumLineMid - daNote.y) / daNote.scale.y; swagRect.y = daNote.height / daNote.scale.y - swagRect.height; daNote.clipRect = swagRect; } } else { daNote.y = (strumLine.y - (Conductor.songPosition - daNote.strumTime) * (0.45 * FlxMath.roundDecimal(SONG.speed, 2))); if (daNote.isSustainNote && (!daNote.mustPress || (daNote.wasGoodHit || (daNote.prevNote.wasGoodHit && !daNote.canBeHit))) && daNote.y + daNote.offset.y * daNote.scale.y <= strumLineMid) { var swagRect:FlxRect = new FlxRect(0, 0, daNote.width / daNote.scale.x, daNote.height / daNote.scale.y); swagRect.y = (strumLineMid - daNote.y) / daNote.scale.y; swagRect.height -= swagRect.y; daNote.clipRect = swagRect; } } if (!daNote.mustPress && daNote.wasGoodHit) { if (SONG.song != 'Tutorial') camZooming = true; var altAnim:String = ""; if (SONG.notes[Math.floor(curStep / 16)] != null) { if (SONG.notes[Math.floor(curStep / 16)].altAnim) altAnim = '-alt'; } switch (Math.abs(daNote.noteData)) { case 0: dad.playAnim('singLEFT' + altAnim, true); case 1: dad.playAnim('singDOWN' + altAnim, true); case 2: dad.playAnim('singUP' + altAnim, true); case 3: dad.playAnim('singRIGHT' + altAnim, true); } dad.holdTimer = 0; if (SONG.needsVoices) vocals.volume = 1; daNote.kill(); notes.remove(daNote, true); daNote.destroy(); } // WIP interpolation shit? Need to fix the pause issue // daNote.y = (strumLine.y - (songTime - daNote.strumTime) * (0.45 * PlayState.SONG.speed)); var noteMiss:Bool = daNote.y < -daNote.height; if (PreferencesMenu.getPref('downscroll')) noteMiss = daNote.y > FlxG.height; if (noteMiss) { if (daNote.tooLate || !daNote.wasGoodHit) { health -= 0.0475; vocals.volume = 0; } daNote.active = false; daNote.visible = false; daNote.kill(); notes.remove(daNote, true); daNote.destroy(); } }); } if (!inCutscene) keyShit(); #if debug if (FlxG.keys.justPressed.ONE) endSong(); #end } function endSong():Void { deathCounter = 0; canPause = false; FlxG.sound.music.volume = 0; vocals.volume = 0; if (SONG.validScore) { Highscore.saveScore(SONG.song, songScore, storyDifficulty); } if (isStoryMode) { campaignScore += songScore; storyPlaylist.remove(storyPlaylist[0]); if (storyPlaylist.length <= 0) { FlxG.sound.playMusic(Paths.music('freakyMenu')); transIn = FlxTransitionableState.defaultTransIn; transOut = FlxTransitionableState.defaultTransOut; FlxG.switchState(new StoryMenuState()); // if () StoryMenuState.weekUnlocked[Std.int(Math.min(storyWeek + 1, StoryMenuState.weekUnlocked.length - 1))] = true; if (SONG.validScore) { NGio.unlockMedal(60961); Highscore.saveWeekScore(storyWeek, campaignScore, storyDifficulty); } FlxG.save.data.weekUnlocked = StoryMenuState.weekUnlocked; FlxG.save.flush(); } else { var difficulty:String = ""; if (storyDifficulty == 0) difficulty = '-easy'; if (storyDifficulty == 2) difficulty = '-hard'; trace('LOADING NEXT SONG'); trace(PlayState.storyPlaylist[0].toLowerCase() + difficulty); if (SONG.song.toLowerCase() == 'eggnog') { var blackShit:FlxSprite = new FlxSprite(-FlxG.width * FlxG.camera.zoom, -FlxG.height * FlxG.camera.zoom).makeGraphic(FlxG.width * 3, FlxG.height * 3, FlxColor.BLACK); blackShit.scrollFactor.set(); add(blackShit); camHUD.visible = false; FlxG.sound.play(Paths.sound('Lights_Shut_off')); } FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; prevCamFollow = camFollow; PlayState.SONG = Song.loadFromJson(PlayState.storyPlaylist[0].toLowerCase() + difficulty, PlayState.storyPlaylist[0]); FlxG.sound.music.stop(); LoadingState.loadAndSwitchState(new PlayState()); } } else { trace('WENT BACK TO FREEPLAY??'); FlxG.switchState(new FreeplayState()); } } var endingSong:Bool = false; private function popUpScore(strumtime:Float, daNote:Note):Void { var noteDiff:Float = Math.abs(strumtime - Conductor.songPosition); // boyfriend.playAnim('hey'); vocals.volume = 1; var placement:String = Std.string(combo); var coolText:FlxText = new FlxText(0, 0, 0, placement, 32); coolText.screenCenter(); coolText.x = FlxG.width * 0.55; // var rating:FlxSprite = new FlxSprite(); var score:Int = 350; var daRating:String = "sick"; var isSick:Bool = true; if (noteDiff > Conductor.safeZoneOffset * 0.9) { daRating = 'shit'; score = 50; isSick = false; // shitty copypaste on this literally just because im lazy and tired lol! } else if (noteDiff > Conductor.safeZoneOffset * 0.75) { daRating = 'bad'; score = 100; isSick = false; } else if (noteDiff > Conductor.safeZoneOffset * 0.2) { daRating = 'good'; score = 200; isSick = false; } if (isSick) { var noteSplash:NoteSplash = new NoteSplash(daNote.x, daNote.y, daNote.noteData); add(noteSplash); noteSplash.cameras = [camHUD]; } songScore += score; /* if (combo > 60) daRating = 'sick'; else if (combo > 12) daRating = 'good' else if (combo > 4) daRating = 'bad'; */ var pixelShitPart1:String = ""; var pixelShitPart2:String = ''; if (curStage.startsWith('school')) { pixelShitPart1 = 'weeb/pixelUI/'; pixelShitPart2 = '-pixel'; } rating.loadGraphic(Paths.image(pixelShitPart1 + daRating + pixelShitPart2)); rating.screenCenter(); rating.x = coolText.x - 40; rating.y -= 60; rating.acceleration.y = 550; rating.velocity.y -= FlxG.random.int(140, 175); rating.velocity.x -= FlxG.random.int(0, 10); var comboSpr:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'combo' + pixelShitPart2)); comboSpr.screenCenter(); comboSpr.x = coolText.x; comboSpr.acceleration.y = 600; comboSpr.velocity.y -= 150; comboSpr.velocity.x += FlxG.random.int(1, 10); add(rating); if (!curStage.startsWith('school')) { rating.setGraphicSize(Std.int(rating.width * 0.7)); rating.antialiasing = true; comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7)); comboSpr.antialiasing = true; } else { rating.setGraphicSize(Std.int(rating.width * daPixelZoom * 0.7)); comboSpr.setGraphicSize(Std.int(comboSpr.width * daPixelZoom * 0.7)); } comboSpr.updateHitbox(); rating.updateHitbox(); var seperatedScore:Array = []; seperatedScore.push(Math.floor(combo / 100)); seperatedScore.push(Math.floor((combo - (seperatedScore[0] * 100)) / 10)); seperatedScore.push(combo % 10); var daLoop:Int = 0; for (i in seperatedScore) { var numScore:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'num' + Std.int(i) + pixelShitPart2)); numScore.screenCenter(); numScore.x = coolText.x + (43 * daLoop) - 90; numScore.y += 80; if (!curStage.startsWith('school')) { numScore.antialiasing = true; numScore.setGraphicSize(Std.int(numScore.width * 0.5)); } else { numScore.setGraphicSize(Std.int(numScore.width * daPixelZoom)); } numScore.updateHitbox(); numScore.acceleration.y = FlxG.random.int(200, 300); numScore.velocity.y -= FlxG.random.int(140, 160); numScore.velocity.x = FlxG.random.float(-5, 5); if (combo >= 10 || combo == 0) add(numScore); FlxTween.tween(numScore, {alpha: 0}, 0.2, { onComplete: function(tween:FlxTween) { numScore.destroy(); }, startDelay: Conductor.crochet * 0.002 }); daLoop++; } /* trace(combo); trace(seperatedScore); */ coolText.text = Std.string(seperatedScore); // add(coolText); FlxTween.tween(rating, {alpha: 0}, 0.2, { startDelay: Conductor.crochet * 0.001 }); FlxTween.tween(comboSpr, {alpha: 0}, 0.2, { onComplete: function(tween:FlxTween) { coolText.destroy(); comboSpr.destroy(); rating.destroy(); }, startDelay: Conductor.crochet * 0.001 }); curSection += 1; } var cameraRightSide:Bool = false; function cameraMovement() { if (camFollow.x != dad.getMidpoint().x + 150 && !cameraRightSide) { camFollow.setPosition(dad.getMidpoint().x + 150, dad.getMidpoint().y - 100); // camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210); switch (dad.curCharacter) { case 'mom': camFollow.y = dad.getMidpoint().y; case 'senpai': camFollow.y = dad.getMidpoint().y - 430; camFollow.x = dad.getMidpoint().x - 100; case 'senpai-angry': camFollow.y = dad.getMidpoint().y - 430; camFollow.x = dad.getMidpoint().x - 100; } if (dad.curCharacter == 'mom') vocals.volume = 1; if (SONG.song.toLowerCase() == 'tutorial') { tweenCamIn(); } } if (cameraRightSide && camFollow.x != boyfriend.getMidpoint().x - 100) { camFollow.setPosition(boyfriend.getMidpoint().x - 100, boyfriend.getMidpoint().y - 100); switch (curStage) { case 'limo': camFollow.x = boyfriend.getMidpoint().x - 300; case 'mall': camFollow.y = boyfriend.getMidpoint().y - 200; case 'school': camFollow.x = boyfriend.getMidpoint().x - 200; camFollow.y = boyfriend.getMidpoint().y - 200; case 'schoolEvil': camFollow.x = boyfriend.getMidpoint().x - 200; camFollow.y = boyfriend.getMidpoint().y - 200; } if (SONG.song.toLowerCase() == 'tutorial') { FlxTween.tween(FlxG.camera, {zoom: 1}, (Conductor.stepCrochet * 4 / 1000), {ease: FlxEase.elasticInOut}); } } } private function keyShit():Void { // control arrays, order L D R U var holdArray:Array = [controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT]; var pressArray:Array = [ controls.NOTE_LEFT_P, controls.NOTE_DOWN_P, controls.NOTE_UP_P, controls.NOTE_RIGHT_P ]; var releaseArray:Array = [ controls.NOTE_LEFT_R, controls.NOTE_DOWN_R, controls.NOTE_UP_R, controls.NOTE_RIGHT_R ]; // HOLDS, check for sustain notes if (holdArray.contains(true) && /*!boyfriend.stunned && */ generatedMusic) { notes.forEachAlive(function(daNote:Note) { if (daNote.isSustainNote && daNote.canBeHit && daNote.mustPress && holdArray[daNote.noteData]) goodNoteHit(daNote); }); } // PRESSES, check for note hits if (pressArray.contains(true) && /*!boyfriend.stunned && */ generatedMusic) { boyfriend.holdTimer = 0; var possibleNotes:Array = []; // notes that can be hit var directionList:Array = []; // directions that can be hit var dumbNotes:Array = []; // notes to kill later notes.forEachAlive(function(daNote:Note) { if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit) { if (directionList.contains(daNote.noteData)) { for (coolNote in possibleNotes) { if (coolNote.noteData == daNote.noteData && Math.abs(daNote.strumTime - coolNote.strumTime) < 10) { // if it's the same note twice at < 10ms distance, just delete it // EXCEPT u cant delete it in this loop cuz it fucks with the collection lol dumbNotes.push(daNote); break; } else if (coolNote.noteData == daNote.noteData && daNote.strumTime < coolNote.strumTime) { // if daNote is earlier than existing note (coolNote), replace possibleNotes.remove(coolNote); possibleNotes.push(daNote); break; } } } else { possibleNotes.push(daNote); directionList.push(daNote.noteData); } } }); for (note in dumbNotes) { FlxG.log.add("killing dumb ass note at " + note.strumTime); note.kill(); notes.remove(note, true); note.destroy(); } possibleNotes.sort((a, b) -> Std.int(a.strumTime - b.strumTime)); if (perfectMode) goodNoteHit(possibleNotes[0]); else if (possibleNotes.length > 0) { for (shit in 0...pressArray.length) { // if a direction is hit that shouldn't be if (pressArray[shit] && !directionList.contains(shit)) badNoteHit(); } for (coolNote in possibleNotes) { if (pressArray[coolNote.noteData]) goodNoteHit(coolNote); } } else { badNoteHit(); } } if (boyfriend.holdTimer > Conductor.stepCrochet * 4 * 0.001 && !holdArray.contains(true)) { if (boyfriend.animation.curAnim.name.startsWith('sing') && !boyfriend.animation.curAnim.name.endsWith('miss')) { boyfriend.playAnim('idle'); } } playerStrums.forEach(function(spr:FlxSprite) { if (pressArray[spr.ID] && spr.animation.curAnim.name != 'confirm') spr.animation.play('pressed'); if (!holdArray[spr.ID]) spr.animation.play('static'); if (spr.animation.curAnim.name == 'confirm' && !curStage.startsWith('school')) { spr.centerOffsets(); spr.offset.x -= 13; spr.offset.y -= 13; } else spr.centerOffsets(); }); } function noteMiss(direction:Int = 1):Void { if (!boyfriend.stunned) { health -= 0.04; if (combo > 5 && gf.animOffsets.exists('sad')) { gf.playAnim('sad'); } combo = 0; songScore -= 10; FlxG.sound.play(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2)); // FlxG.sound.play(Paths.sound('missnote1'), 1, false); // FlxG.log.add('played imss note'); boyfriend.stunned = true; // get stunned for 5 seconds new FlxTimer().start(5 / 60, function(tmr:FlxTimer) { boyfriend.stunned = false; }); switch (direction) { case 0: boyfriend.playAnim('singLEFTmiss', true); case 1: boyfriend.playAnim('singDOWNmiss', true); case 2: boyfriend.playAnim('singUPmiss', true); case 3: boyfriend.playAnim('singRIGHTmiss', true); } } } function badNoteHit() { // just double pasting this shit cuz fuk u // REDO THIS SYSTEM! var leftP = controls.NOTE_LEFT_P; var downP = controls.NOTE_DOWN_P; var upP = controls.NOTE_UP_P; var rightP = controls.NOTE_RIGHT_P; if (leftP) noteMiss(0); if (downP) noteMiss(1); if (upP) noteMiss(2); if (rightP) noteMiss(3); } function goodNoteHit(note:Note):Void { if (!note.wasGoodHit) { if (!note.isSustainNote) { popUpScore(note.strumTime, note); combo += 1; } if (note.noteData >= 0) health += 0.023; else health += 0.004; switch (note.noteData) { case 0: boyfriend.playAnim('singLEFT', true); case 1: boyfriend.playAnim('singDOWN', true); case 2: boyfriend.playAnim('singUP', true); case 3: boyfriend.playAnim('singRIGHT', true); } playerStrums.forEach(function(spr:FlxSprite) { if (Math.abs(note.noteData) == spr.ID) { spr.animation.play('confirm', true); } }); note.wasGoodHit = true; vocals.volume = 1; if (!note.isSustainNote) { note.kill(); notes.remove(note, true); note.destroy(); } } } var fastCarCanDrive:Bool = true; function resetFastCar():Void { fastCar.x = -12600; fastCar.y = FlxG.random.int(140, 250); fastCar.velocity.x = 0; fastCarCanDrive = true; } function fastCarDrive() { FlxG.sound.play(Paths.soundRandom('carPass', 0, 1), 0.7); fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3; fastCarCanDrive = false; new FlxTimer().start(2, function(tmr:FlxTimer) { resetFastCar(); }); } var trainMoving:Bool = false; var trainFrameTiming:Float = 0; var trainCars:Int = 8; var trainFinishing:Bool = false; var trainCooldown:Int = 0; function trainStart():Void { trainMoving = true; trainSound.play(true); } var startedMoving:Bool = false; function updateTrainPos():Void { if (trainSound.time >= 4700) { startedMoving = true; gf.playAnim('hairBlow'); } if (startedMoving) { phillyTrain.x -= 400; if (phillyTrain.x < -2000 && !trainFinishing) { phillyTrain.x = -1150; trainCars -= 1; if (trainCars <= 0) trainFinishing = true; } if (phillyTrain.x < -4000 && trainFinishing) trainReset(); } } function trainReset():Void { gf.playAnim('hairFall'); phillyTrain.x = FlxG.width + 200; trainMoving = false; // trainSound.stop(); // trainSound.time = 0; trainCars = 8; trainFinishing = false; startedMoving = false; } function lightningStrikeShit():Void { FlxG.sound.play(Paths.soundRandom('thunder_', 1, 2)); halloweenBG.animation.play('lightning'); lightningStrikeBeat = curBeat; lightningOffset = FlxG.random.int(8, 24); boyfriend.playAnim('scared', true); gf.playAnim('scared', true); } override function stepHit() { super.stepHit(); if (Math.abs(FlxG.sound.music.time - Conductor.songPosition) > 20 || (SONG.needsVoices && Math.abs(vocals.time - Conductor.songPosition) > 20)) { resyncVocals(); } if (dad.curCharacter == 'spooky' && curStep % 4 == 2) { // dad.dance(); } } var lightningStrikeBeat:Int = 0; var lightningOffset:Int = 8; override function beatHit() { super.beatHit(); if (generatedMusic) { notes.sort(FlxSort.byY, FlxSort.DESCENDING); } if (SONG.notes[Math.floor(curStep / 16)] != null) { if (SONG.notes[Math.floor(curStep / 16)].changeBPM) { Conductor.changeBPM(SONG.notes[Math.floor(curStep / 16)].bpm); FlxG.log.add('CHANGED BPM!'); } // else // Conductor.changeBPM(SONG.bpm); } // FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM); wiggleShit.update(Conductor.crochet); // HARDCODING FOR MILF ZOOMS! if (PreferencesMenu.getPref('camera-zoom')) { if (curSong.toLowerCase() == 'milf' && curBeat >= 168 && curBeat < 200 && camZooming && FlxG.camera.zoom < 1.35) { FlxG.camera.zoom += 0.015; camHUD.zoom += 0.03; } if (camZooming && FlxG.camera.zoom < 1.35 && curBeat % 4 == 0) { FlxG.camera.zoom += 0.015; camHUD.zoom += 0.03; } } iconP1.setGraphicSize(Std.int(iconP1.width + 30)); iconP2.setGraphicSize(Std.int(iconP2.width + 30)); iconP1.updateHitbox(); iconP2.updateHitbox(); if (curBeat % gfSpeed == 0) { gf.dance(); } if (curBeat % 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') { if (!dad.animation.curAnim.name.startsWith("sing")) dad.dance(); } if (curBeat % 8 == 7 && curSong == 'Bopeebo') { boyfriend.playAnim('hey', true); if (SONG.song == 'Tutorial' && dad.curCharacter == 'gf') { dad.playAnim('cheer', true); } } foregroundSprites.forEach(function(spr:BGSprite) { spr.dance(); }); switch (curStage) { case 'school': bgGirls.dance(); case 'mall': upperBoppers.animation.play('bop', true); bottomBoppers.animation.play('bop', true); santa.animation.play('idle', true); case 'limo': grpLimoDancers.forEach(function(dancer:BackgroundDancer) { dancer.dance(); }); if (FlxG.random.bool(10) && fastCarCanDrive) fastCarDrive(); case "philly": if (!trainMoving) trainCooldown += 1; if (curBeat % 4 == 0) { phillyCityLights.forEach(function(light:FlxSprite) { light.visible = false; }); curLight = FlxG.random.int(0, phillyCityLights.length - 1); phillyCityLights.members[curLight].visible = true; // phillyCityLights.members[curLight].alpha = 1; } if (curBeat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8) { trainCooldown = FlxG.random.int(-4, 0); trainStart(); } } if (isHalloween && FlxG.random.bool(10) && curBeat > lightningStrikeBeat + lightningOffset) { lightningStrikeShit(); } } var curLight:Int = 0; }