From 2738c39e9a5ecc9669d60f7964061a8916b34bb4 Mon Sep 17 00:00:00 2001 From: MaybeMaru <97055307+MaybeMaru@users.noreply.github.com> Date: Sat, 3 Feb 2024 18:59:22 +0100 Subject: [PATCH] week 3 rewrite --- assets/preload/data/stages/philly.hx | 200 +++++----- assets/preload/data/stages/philly.json | 49 ++- assets/songs/blammed/cutscene.hx | 342 ++++++++++-------- .../week3/images/{philly => }/behindTrain.png | Bin .../weeks/week3/images/{philly => }/city.png | Bin .../images/{philly => }/phillyWindow-blur.png | Bin .../images/{philly => }/phillyWindow.png | Bin .../weeks/week3/images/{philly => }/sky.png | Bin .../week3/images/{philly => }/street.png | Bin .../weeks/week3/images/{philly => }/train.png | Bin source/funkin/graphics/FlxSpriteExt.hx | 35 ++ source/funkin/objects/NotesGroup.hx | 17 +- source/funkin/states/PlayState.hx | 7 +- source/funkin/util/backend/AssetManager.hx | 12 + source/funkin/util/modding/FunkScript.hx | 20 +- source/funkin/util/modding/ScriptUtil.hx | 73 +++- source/hscript/UsingHandler.hx | 316 ++++++++++++++++ 17 files changed, 778 insertions(+), 293 deletions(-) rename assets/weeks/week3/images/{philly => }/behindTrain.png (100%) rename assets/weeks/week3/images/{philly => }/city.png (100%) rename assets/weeks/week3/images/{philly => }/phillyWindow-blur.png (100%) rename assets/weeks/week3/images/{philly => }/phillyWindow.png (100%) rename assets/weeks/week3/images/{philly => }/sky.png (100%) rename assets/weeks/week3/images/{philly => }/street.png (100%) rename assets/weeks/week3/images/{philly => }/train.png (100%) create mode 100644 source/hscript/UsingHandler.hx diff --git a/assets/preload/data/stages/philly.hx b/assets/preload/data/stages/philly.hx index 30b7da4b..b90ebfb8 100644 --- a/assets/preload/data/stages/philly.hx +++ b/assets/preload/data/stages/philly.hx @@ -1,141 +1,105 @@ -//Lights -var phillyLightsColors:Array = [0xFF31A2FD, 0xFF31FD8C, 0xFFFB33F5, 0xFFFD4531, 0xFFFBA633]; -var phillyCityLights:FunkinSprite; -var phillyCityLightsBlur:FunkinSprite; // Was gonna use a shader but takes too much memory, so fuck it -var phillyColor:Int = 0; - -//Train -var phillyTrain:FunkinSprite; -var trainSound:FlxSound; - -var startedMoving:Bool = false; -var trainMoving:Bool = false; -var trainFrameTiming:Float = 0; - -var trainCars:Int = 8; -var trainFinishing:Bool = false; -var trainCooldown:Int = 0; - -function create():Void { - var bg:FunkinSprite = new FunkinSprite('philly/sky', [-100, 0], [0.1,0.1]); - addSpr(bg, 'phillyBg'); - - var city:FunkinSprite = new FunkinSprite('philly/city', [-10, 0], [0.3,0.3]); - city.setScale(0.85); - addSpr(city, 'phillyCity'); - - phillyCityLights = new FunkinSprite('philly/phillyWindow', [city.x, 0], [0.3,0.3]); - phillyCityLights.visible = false; - phillyCityLights.setScale(0.85); - phillyCityLights.blend = getBlendMode('add'); - addSpr(phillyCityLights, 'phillyWindow'); - - phillyCityLightsBlur = new FunkinSprite('philly/phillyWindow-blur', [city.x, 0], [0.3,0.3]); - phillyCityLightsBlur.visible = false; - phillyCityLightsBlur.setScale(0.85); - phillyCityLightsBlur.blend = getBlendMode('add'); - addSpr(phillyCityLightsBlur, 'phillyWindowBlur'); - - var streetBehind:FunkinSprite = new FunkinSprite('philly/behindTrain', [-40, 50]); - addSpr(streetBehind, 'streetBehind'); - - phillyTrain = new FunkinSprite('philly/train', [2000, 360]); - addSpr(phillyTrain, 'phillyTrain'); - - var street:FunkinSprite = new FunkinSprite('philly/street', [-40, streetBehind.y]); - addSpr(street, 'phillyStreet'); - - trainSound = getSound('train_passes'); - phillyColor += FlxG.random.int(0,3); -} +var colors = [0xFF31A2FD, 0xFF31FD8C, 0xFFFB33F5, 0xFFFD4531, 0xFFFBA633]; +var color = 0; +var start; +var sound; -function beatHit(curBeat):Void { - var genTrain:Bool = (curBeat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8 && !trainSound.playing); - var inBlammed:Bool = (State.curSong == 'Blammed' && curBeat >= 100); +function createPost() { + lights.blend = getBlendMode("add"); + blur.blend = getBlendMode("add"); - if (!trainMoving) { - trainCooldown++; + lights.alpha = 0; + blur.alpha = 0; + + start = switch (State.curSong) { + case "Pico": 2; + default: 0; } - if (genTrain && !inBlammed) { - trainStart(); - } + sound = getSound('train_passes'); + color += FlxG.random.int(0, colors.length); } -function sectionHit(curSection):Void { - var stuffToColor:Array> = [phillyCityLights, phillyCityLightsBlur]; - if (existsSpr('blammedOverlay')) { // Prevent getting a null sprite error - for (i in ['blammedOverlay', 'tunnelLights', 'tunnelLightsBlur']) - stuffToColor.push(getSpr(i)); - } - - var curColor:Int = phillyLightsColors[phillyColor]; - for (obj in stuffToColor) { - if (obj != null) { // BLAMMED COLORS - obj.color = curColor; - } - } +function sectionHit(section) { + if (section < start) return; - var showLights:Bool = true; - switch(State.curSong) { - case 'Pico': showLights = (curSection > 1); // PICO CUTSCENE - } - phillyCityLights.visible = showLights; - phillyCityLightsBlur.visible = showLights; - phillyCityLights.alpha = 1; - phillyCityLightsBlur.alpha = 1; - phillyColor = FlxMath.wrap(phillyColor + 1, 0, 4); + color = FlxMath.wrap(color + 1, 0, 4); + + var lightsColor = colors[color]; + lights.color = lightsColor; + blur.color = lightsColor; + + lights.alpha = 1; + blur.alpha = 1; } -function update(elapsed):Void { - var alphaLight:Float = Conductor.crochetMills * elapsed; - phillyCityLights.alpha = Math.max(phillyCityLights.alpha - alphaLight * 2, 0.001); - phillyCityLightsBlur.alpha = Math.max(phillyCityLightsBlur.alpha - alphaLight * 2.5, 0.001); - - if (trainMoving) { - trainFrameTiming += elapsed; - if (trainFrameTiming >= 1 / 24) { - updateTrainPos(); - trainFrameTiming = 0; - } - } +function updatePost(elapsed) { + var speed = Conductor.crochetMills * elapsed * 2; + lights.alpha -= speed; + blur.alpha -= speed * 1.25; + + trainMoving = sound.playing && sound.time > 4650; + if (trainMoving && !finishedMove) + updateTrain(elapsed); } -function trainStart():Void { +/* + * TRAIN CRAP +**/ + +var trainFrame = 0; +var trainCars = 8; +var trainMoving = false; +var trainFinished = false; +var trainCooldown = 0; +var finishedMove = false; + +function beatHit(beat) { + if (!trainMoving) + trainCooldown++; + + var moveTrain = (!trainMoving && trainCooldown > 8) && (beat % 8 == 4 && FlxG.random.bool(30)); + if (moveTrain) + startTrain(); +} + +function startTrain() { trainCooldown = FlxG.random.int(-4, 0); - trainMoving = true; - if (!trainSound.playing) { - trainSound.play(true); - } + finishedMove = false; + sound.play(true); } -function updateTrainPos():Void { - if (trainSound.time >= 4700) { - startedMoving = true; - State.gf.playAnim('hairBlow'); - } +function updateTrain(elapsed) { + trainFrame += elapsed; + if (trainFrame >= 1 / 24) { + moveTrain(); + trainFrame = 0; + } +} - if (startedMoving) { - phillyTrain.x -= 400; - if (phillyTrain.x < -2000 && !trainFinishing) { - phillyTrain.x = -1150; - trainCars -= 1; - if (trainCars <= 0) { - trainFinishing = true; - } +function moveTrain() { + train.x -= 400; + if (!trainFinished) { + if (train.x < 800) + State.gf.playAnim('hairBlow'); + + if (train.x < -1900) { + train.x = -850; + trainCars--; + if (trainCars < 1) + trainFinished = true; } + } - if (phillyTrain.x < -4000 && trainFinishing) { - trainReset(); - } + if (train.x < -4000 && trainFinished) { + resetTrain(); } } -function trainReset():Void { +function resetTrain() { State.gf.playAnim('hairFall'); - phillyTrain.x = FlxG.width + 200; - trainMoving = false; + train.x = 2000; trainCars = 8; - trainFinishing = false; - startedMoving = false; + trainFinished = false; + trainMoving = false; + finishedMove = true; } \ No newline at end of file diff --git a/assets/preload/data/stages/philly.json b/assets/preload/data/stages/philly.json index 3eaa0c5c..b6cb3295 100644 --- a/assets/preload/data/stages/philly.json +++ b/assets/preload/data/stages/philly.json @@ -5,5 +5,52 @@ "bfOffsets": [-75,0], "startCamOffsets": [-800,-350], "dadCamOffsets": [-100, 0], - "bfCamOffsets": [100, 0] + "bfCamOffsets": [100, 0], + "layers": { + "bg": [ + { + "tag": "sky", + "imagePath": "sky", + "position": [-100, 0], + "scrolls": [0.1, 0.1] + }, + { + "tag": "city", + "imagePath": "city", + "position": [-10, 0], + "scrolls": [0.3,0.3], + "scale": 0.85 + }, + { + "tag": "lights", + "imagePath": "phillyWindow", + "position": [-10, 0], + "scrolls": [0.3,0.3], + "scale": 0.85 + }, + { + "tag": "blur", + "imagePath": "phillyWindow-blur", + "position": [-10, 0], + "scrolls": [0.3,0.3], + "scale": 0.85 + }, + { + "tag": "tracks", + "imagePath": "behindTrain", + "position": [-40, 50] + }, + { + "tag": "train", + "imagePath": "train", + "position": [2000, 360] + }, + { + "tag": "street", + "imagePath": "street", + "position": [-40, 50] + } + ], + "fg": [] + } } \ No newline at end of file diff --git a/assets/songs/blammed/cutscene.hx b/assets/songs/blammed/cutscene.hx index 0befaa19..da73701b 100644 --- a/assets/songs/blammed/cutscene.hx +++ b/assets/songs/blammed/cutscene.hx @@ -1,181 +1,213 @@ import flixel.addons.display.FlxBackdrop; +import flixel.util.FlxGradient; -function create() -{ - var blammedOverlay:FunkinSprite = new FunkinSprite('', [-500,-500], [0,0]).makeGraphic(FlxG.width*2, FlxG.height*2, FlxColor.WHITE); - blammedOverlay.blend = getBlendMode('multiply'); - addSpr(blammedOverlay, 'blammedOverlay', true); +var cars = []; +var gradient; var transTrain; - var tunnelBG:FlxSpriteExt = new FlxSpriteExt().makeGraphic(FlxG.width, FlxG.height, FlxColor.fromRGB(16, 13, 29)); - tunnelBG.scrollFactor.set(); - addSpr(tunnelBG,'tunnelBG'); - - var tunnelLights = new FunkinSprite('blammed/tunnelLights', [-300,300],[0.8,0.8]); - tunnelLights.blend = getBlendMode('add'); - tunnelLights.addAnim('lights', 'tunnelLights', 24, true); - tunnelLights.playAnim('lights'); - tunnelLights.setScale(0.8); - addSpr(tunnelLights,'tunnelLights'); - - var tunnelLightsBlur = new FunkinSprite('blammed/tunnelLightsBlur', [tunnelLights.x - 25, tunnelLights.y - 5],[0.8,0.8]); - tunnelLightsBlur.blend = getBlendMode('add'); - tunnelLightsBlur.addAnim('lights', 'tunnelLights', 24, true); - tunnelLightsBlur.playAnim('lights'); - tunnelLightsBlur.setScale(0.8); - addSpr(tunnelLightsBlur,'tunnelLightsBlur'); - - tunnelLights._dynamic.update = function (elapsed) { - var alphaVal = Conductor.sectionCrochetMills * elapsed; - tunnelLights.alpha -= alphaVal; - tunnelLightsBlur.alpha -= alphaVal * 2.5; - } +function createPost() { + createTunnel(); + createCity(); + createCars(); - // scale, speed - var cityData = [[0.6, 50], [0.8, 100]]; - for (i in 0...2) { - var cityLoop = new FlxBackdrop(Paths.image('blammed/cityLoop'), 0x01); - cityLoop.flipX = i == 0; - cityLoop.color = (i == 0 ? FlxColor.fromRGB(120, 105, 185) : FlxColor.WHITE); - cityLoop.alpha = (i == 0 ? 0.8 : 1); - cityLoop.scale.set(cityData[i][0], cityData[i][0]); - cityLoop.updateHitbox(); - cityLoop.y += 300 + (i * 50); - cityLoop.scrollFactor.set(0.25,0.25); - cityLoop.visible = false; - addSpr(cityLoop, 'cityLoop' + i); - cityLoop._dynamic.update = function (elapsed) { - cityLoop.x += elapsed * cityData[i][1]; - cityLoop.x %= cityLoop.width; - } - } - - // sides trains - for (i in 0...2) { - var sideTrain = new FunkinSprite('blammed/blammedTrain', [i == 0 ? -1650 : 950, 675]); - sideTrain.color = FlxColor.GRAY; - sideTrain.setScale(0.8); - sideTrain.addAnim('train', 'train', 24, true); - sideTrain.playAnim('train', true, false, FlxG.random.int(0,2)); - addSpr(sideTrain,'sideTrain' + i); - } - - var blammedTrain:FunkinSprite = new FunkinSprite('blammed/blammedTrain', [-375, 675]); - blammedTrain.setScale(0.8); - blammedTrain.addAnim('train', 'train', 24, true); - blammedTrain.playAnim('train'); - addSpr(blammedTrain, 'blammedTrain'); - - for (i in ['sideTrain0','sideTrain1','blammedTrain']) { - var spr = getSpr(i); - spr._dynamic.timeElapsed = 0; - spr._dynamic.update = function (elapsed) { - spr._dynamic.timeElapsed += elapsed; - if (spr._dynamic.timeElapsed >= 1 / 24) { - spr._dynamic.timeElapsed = 0; - spr.offset.set(FlxG.random.float(-1.5,1.5), FlxG.random.float(-1.5,1.5)); + gradient = FlxGradient.createGradientFlxSprite(FlxG.width * 2, 1, [FlxColor.TRANSPARENT, FlxColor.BLACK, FlxColor.BLACK], 1, 0); + gradient.scale.y = FlxG.height; + gradient.updateHitbox(); + gradient.setPosition(1500, 200); + add(gradient); + + transTrain = new FunkinSprite("train", [1500, 175]); + transTrain.scale.set(2, 2); + transTrain.updateHitbox(); + add(transTrain); +} + +function createCars() { + for (i in 0...3) { + var car:FunkinSprite = new FunkinSprite('blammed/blammedTrain', [switch (i) { + case 0: -1650; case 1: 950; default: -375; + }, 675]); + car.addAnim('t', 'train', 24, true); + car.playAnim('t'); + + if (i != 2) + car.color = FlxColor.GRAY; + + car.setScale(0.8); + cars.push(car); + addSpr(car, 'car' + i); + + car._dynamic.timeElapsed = 0; + car._dynamic.update = function (e) { + car._dynamic.timeElapsed += e; + if (car._dynamic.timeElapsed >= 1 / 24) { + car._dynamic.timeElapsed = 0; + car.offset.set(FlxG.random.float(-1.5,1.5), FlxG.random.float(-1.5,1.5)); - if (i == 'blammedTrain' && spr.visible) { + if (i == 2 && car.visible) { for (c in [State.boyfriend, State.dad]) { c.applyCurOffset(true); - c.offset.x += spr.offset.x; - c.offset.y += spr.offset.y; + c.offset.x += car.offset.x; + c.offset.y += car.offset.y; } } } } } - - hideBlammed(false); - cacheCharacter("bf-car"); -} - -function beatHit(curBeat) -{ - switch (curBeat) - { - case 126: startBlammedTransition(); - case 128: addBlammedTransition(); - } - for (i in ['tunnelLights', 'tunnelLightsBlur']) - getSpr(i).alpha = 1; + for (i in cars) + i.visible = false; } - -function hidePhilly(value) { - for (i in ['overlayTrain', 'overlayTrainBG', 'phillyStreet', 'phillyTrain', 'streetBehind']) { - if (existsSpr(i)) getSpr(i).destroy(); - //getSpr(i).visible = value; - } -} - -function hideBlammed(value) { - for (i in ['sideTrain0','sideTrain1','blammedTrain','tunnelBG','tunnelLights','tunnelLightsBlur','blammedOverlay']) { - getSpr(i).visible = value; + +// TUNNEL SECTION + +var tunnel; var overlay; var lights; var blur; + +function createTunnel() { + var colorLights = getGlobalVar("colorLights"); + + tunnel = new FlxSprite(-500, -500).makeRect(FlxG.width + 500, FlxG.height + 500, FlxColor.fromRGB(16, 13, 29)); + tunnel.scrollFactor.set(); + addSpr(tunnel, 'tunnel'); + + lights = new FunkinSprite('blammed/tunnelLights', [-550,300],[0.8,0.8]); + lights.setScale(0.8); + lights.alpha = 0; + addSpr(lights,'tunnelLights'); + + blur = new FunkinSprite('blammed/tunnelLightsBlur', [lights.x - 25, lights.y - 5],[0.8,0.8]); + blur.blend = getBlendMode('add'); + blur.setScale(0.8); + blur.alpha = 0; + addSpr(blur,'tunnelBlur'); + + for (i in [lights, blur]) { + i.addAnim('lights', 'tunnelLights', 24, true); + i.playAnim('lights'); } + + overlay = new FlxSprite(-500, -500).makeRect(FlxG.width + 500, FlxG.height + 500); + overlay.scrollFactor.set(); + overlay.blend = getBlendMode('multiply'); + addSpr(overlay, 'overlay', true); + + colorLights.push(overlay); + colorLights.push(lights); + colorLights.push(blur); + + visibleTunnel(false); } - -function addBlammedTransition() { - State.camGame.flash(getSpr('phillyWindow').color, Conductor.crochet/250, null, true); - State.switchChar('bf', 'bf-car'); - State.gfGroup.visible = false; - State.boyfriend.x += 75; - State.dad.x -= 50; - - hidePhilly(false); - hideBlammed(true); - - State.camZooming = getPref('camera-zoom'); - State.defaultCamZoom = 1; - State.camGame.zoom = State.defaultCamZoom; - State.cameraMovement(); +function visibleTunnel(bool) { + overlay.visible = bool; + lights.visible = bool; + blur.visible = bool; + tunnel.visible = bool; } - -function startBlammedTransition() { - var overlayTrain:FunkinSprite = new FunkinSprite('philly/train', [4200, -50], [0,0]); - overlayTrain.scale.set(2,2); - var overlayTrainBG:FunkinSprite = new FunkinSprite('', [overlayTrain.x,overlayTrain.y], [0,0]).makeGraphic(overlayTrain.width/1.35, overlayTrain.height/1.4, FlxColor.BLACK); - - overlayTrainBG.scale.set(overlayTrain.scale.x,overlayTrain.scale.y); - overlayTrainBG.scale.x *= 2; - overlayTrain.updateHitbox(); - overlayTrainBG.updateHitbox(); - overlayTrainBG.offset.x -= overlayTrain.width/15*overlayTrain.scale.x; - - addSpr(overlayTrainBG, 'overlayTrainBG', true); - addSpr(overlayTrain, 'overlayTrain', true); + +// CITY SECTION + +var cityBg; var cityFg; + +function createCity() { + var cityData = [[0.6, 50], [0.8, 100]]; + + cityBg = new FlxBackdrop(Paths.image('blammed/cityLoop'), 0x01); + cityBg.scrollFactor.set(0, 0.25); + cityBg.flipX = true; + cityBg.color = FlxColor.fromRGB(120, 105, 185); + cityBg.alpha = 0.8; + cityBg.scale.set(0.6, 0.6); + cityBg.updateHitbox(); + cityBg.y = 300; + + cityFg = new FlxBackdrop(Paths.image('blammed/cityLoop'), 0x01); + cityFg.scrollFactor.set(0, 0.25); + cityFg.scale.set(0.8, 0.8); + cityFg.updateHitbox(); + cityFg.y = 350; + + addSpr(cityBg, "cityBg"); + addSpr(cityFg, "cityFg"); + + cityBg.velocity.x = 30; + cityFg.velocity.x = 100; + cityBg.visible = false; + cityFg.visible = false; } - -function exitTunnelTransition() { - for (i in ['blammedOverlay', 'tunnelBG', 'tunnelLights','tunnelLightsBlur']) getSpr(i).visible = false; - for (i in ['cityLoop0', 'cityLoop1']) getSpr(i).visible = true; - State.camGame.flash(getPref('flashing-light') ? FlxColor.WHITE : FlxColor.fromRGB(255,255,255,120), Conductor.crochetMills * 4, null, true); - State.defaultCamZoom = 0.8; - State.camGame.zoom = 0.8; - - for (i in ['phillyWindow', 'phillyWindowBlur', 'phillyCity']) getSpr(i).y += 2000; - var sky = getSpr('phillyBg'); - sky.setScale(1.33, false); - sky.y += 50; + +function beatHit(beat) { + lights.alpha = 1; + blur.alpha = 1; + + switch (beat) + { + case 100: + setGlobalVar("trainAllowed", false); + + case 126: // Train goes over the screen + FlxTween.tween(gradient, {x: -800}, Conductor.crochetMills * 1.25); + transTrain.velocity.x = -19125; + + case 128: // Enter tunnel + visibleTunnel(true); + State.camGame.flash(switch (overlay.color) { + case 0xFF31A2FD: 0xFF31FD8C; + case 0xFF31FD8C: 0xFFFB33F5; + case 0xFFFB33F5: 0xFFFD4531; + case 0xFFFD4531: 0xFFFBA633; + case 0xFFFBA633: 0xFF31A2FD; + }, Conductor.crochet / 250); + + gradient.destroy(); + transTrain.destroy(); + + for (i in cars) + i.visible = true; + + for (i in ["city", "lights", "blur", "tracks", "street"]) + getSpr(i).visible = false; + + State.switchChar('bf', 'bf-car'); + State.gfGroup.visible = false; + State.boyfriend.x += 75; + State.dad.x -= 50; + + State.camZooming = getPref('camera-zoom'); + State.defaultCamZoom = 1; + State.camGame.zoom = State.defaultCamZoom; + State.cameraMovement(); + } } - -function sectionHit(curSection) -{ - switch (curSection) + +function sectionHit(section) { + switch (section) { - case 28: + case 28: // Zoom up to bf State.camZooming = false; FlxTween.tween(State.camGame, {zoom: 1.5}, Conductor.sectionCrochetMills * 4); - case 48: exitTunnelTransition(); - case 72: State.camHUD.fade(FlxColor.BLACK, Conductor.crochetMills * 2); + + case 48: // Exit tunnel + visibleTunnel(false); + + var flashColor = getPref('flashing-light') ? FlxColor.WHITE : FlxColor.fromRGB(255,255,255,120); + State.camGame.flash(flashColor, Conductor.crochetMills * 4, null, true); + State.defaultCamZoom = 0.8; + State.camGame.zoom = 0.8; + + var sky = getSpr('sky'); + sky.setScale(1.33, false); + sky.y += 50; + + cityBg.visible = true; + cityFg.visible = true; + + case 72: // Ending fade + State.camHUD.fade(FlxColor.BLACK, Conductor.crochetMills * 2); } } - -function update(elapsed) -{ - if (existsSpr('overlayTrain')) - { - getSpr('overlayTrain').x -= (225*75)*elapsed; - getSpr('overlayTrainBG').x = getSpr('overlayTrain').x; - } + +function updatePost(e) { + var speed = Conductor.sectionCrochetMills * e; + lights.alpha -= speed; + blur.alpha -= speed * 2.5; } \ No newline at end of file diff --git a/assets/weeks/week3/images/philly/behindTrain.png b/assets/weeks/week3/images/behindTrain.png similarity index 100% rename from assets/weeks/week3/images/philly/behindTrain.png rename to assets/weeks/week3/images/behindTrain.png diff --git a/assets/weeks/week3/images/philly/city.png b/assets/weeks/week3/images/city.png similarity index 100% rename from assets/weeks/week3/images/philly/city.png rename to assets/weeks/week3/images/city.png diff --git a/assets/weeks/week3/images/philly/phillyWindow-blur.png b/assets/weeks/week3/images/phillyWindow-blur.png similarity index 100% rename from assets/weeks/week3/images/philly/phillyWindow-blur.png rename to assets/weeks/week3/images/phillyWindow-blur.png diff --git a/assets/weeks/week3/images/philly/phillyWindow.png b/assets/weeks/week3/images/phillyWindow.png similarity index 100% rename from assets/weeks/week3/images/philly/phillyWindow.png rename to assets/weeks/week3/images/phillyWindow.png diff --git a/assets/weeks/week3/images/philly/sky.png b/assets/weeks/week3/images/sky.png similarity index 100% rename from assets/weeks/week3/images/philly/sky.png rename to assets/weeks/week3/images/sky.png diff --git a/assets/weeks/week3/images/philly/street.png b/assets/weeks/week3/images/street.png similarity index 100% rename from assets/weeks/week3/images/philly/street.png rename to assets/weeks/week3/images/street.png diff --git a/assets/weeks/week3/images/philly/train.png b/assets/weeks/week3/images/train.png similarity index 100% rename from assets/weeks/week3/images/philly/train.png rename to assets/weeks/week3/images/train.png diff --git a/source/funkin/graphics/FlxSpriteExt.hx b/source/funkin/graphics/FlxSpriteExt.hx index 5deae02b..3cb81c9d 100644 --- a/source/funkin/graphics/FlxSpriteExt.hx +++ b/source/funkin/graphics/FlxSpriteExt.hx @@ -205,6 +205,41 @@ class FlxSpriteExt extends FlxSkewedSprite { return value; } + public function makeRect(width:Int, height:Int, color:FlxColor = FlxColor.WHITE, unique:Bool = false, ?key:String):FlxSpriteExt { + makeGraphic(1, 1, color, unique, key); + antialiasing = false; + scale.set(width, height); + updateHitbox(); + return this; + } + + override function makeGraphic(width:Int, height:Int, color:FlxColor = FlxColor.WHITE, unique:Bool = false, ?key:String):FlxSprite { + if (key == null) + key = '::g::w$width::h$height::c$color::'; + + if (unique) { + var i:Int = 0; + while (AssetManager.existsAsset(key + i)) + i++; + + key = key + i; + } + else { + var asset = AssetManager.getAssetGraphic(key); + if (asset != null) { + frames = asset.imageFrame; + return this; + } + } + + var bitmap = new BitmapData(width, height, true, color); + + @:privateAccess + var graphic = AssetManager.__cacheFromBitmap(key, bitmap, false, 0, false); + frames = graphic.imageFrame; + return this; + } + private inline function prepareFrameMatrix(frame:FlxFrame, mat:FlxMatrix, flipX:Bool, flipY:Bool):Void { @:privateAccess { mat.a = frame.tileMatrix[0]; diff --git a/source/funkin/objects/NotesGroup.hx b/source/funkin/objects/NotesGroup.hx index be4a5906..d730351e 100644 --- a/source/funkin/objects/NotesGroup.hx +++ b/source/funkin/objects/NotesGroup.hx @@ -100,9 +100,13 @@ class NotesGroup extends Group game = isPlayState ? PlayState.instance : null; this.isPlayState = isPlayState; SONG = Song.checkSong(_SONG, null, false); //Double check null values - Conductor.mapBPMChanges(SONG); + curSong = SONG.song; + + Conductor.mapBPMChanges(SONG); Conductor.bpm = SONG.bpm; Conductor.songOffset = SONG.offsets; + Conductor.loadMusic(curSong); + songSpeed = getPref('use-const-speed') && isPlayState ? getPref('const-speed') : SONG.speed; inBotplay = getPref('botplay') && isPlayState; vanillaUI = getPref('vanilla-ui'); @@ -199,21 +203,14 @@ class NotesGroup extends Group } private function generateSong():Void { - final songData:SwagSong = SONG; - ModdingUtil.addCall('generateSong', [songData]); + ModdingUtil.addCall('generateSong', [SONG]); unspawnNotes = []; events = []; notes = new TypedGroup(); add(notes); - final noteData:Array = songData.notes; - curSong = songData.song; - - Conductor.loadMusic(curSong); - Conductor.bpm = songData.bpm; - - for (section in noteData) { + for (section in SONG.notes) { for (songNotes in section.sectionNotes) { final strumTime:Float = songNotes[0]; final susLength:Null = songNotes[2]; diff --git a/source/funkin/states/PlayState.hx b/source/funkin/states/PlayState.hx index 5191cb6c..dafebcde 100644 --- a/source/funkin/states/PlayState.hx +++ b/source/funkin/states/PlayState.hx @@ -100,7 +100,12 @@ class PlayState extends MusicBeatState { override public function create():Void { instance = this; - clearCache ? CoolUtil.clearCache(clearCacheData) : FlxG.bitmap.clearUnused(); + if (clearCache) CoolUtil.clearCache(clearCacheData) + else { + FlxG.bitmap.clearUnused(); + CoolUtil.gc(); + } + clearCache = true; clearCacheData = null; diff --git a/source/funkin/util/backend/AssetManager.hx b/source/funkin/util/backend/AssetManager.hx index 0091365c..c83e6711 100644 --- a/source/funkin/util/backend/AssetManager.hx +++ b/source/funkin/util/backend/AssetManager.hx @@ -25,6 +25,13 @@ class Asset isGraphicAsset = asset is LodGraphic; isSoundAsset = !isGraphicAsset; this.asset = asset; + + if (isGraphicAsset) { + var graphic = cast(asset, LodGraphic); + graphic.persist = true; + graphic.destroyOnNoUse = false; + } + return this; } @@ -183,6 +190,11 @@ class AssetManager var bitmap = __getFileBitmap(path); + return __cacheFromBitmap(key, bitmap, staticAsset, lodLevel, useTexture); + } + + @:noCompletion + private static inline function __cacheFromBitmap(key:String, bitmap:BitmapData, staticAsset:Bool, ?lodLevel:LodLevel, ?useTexture:Bool) { @:privateAccess var graphic = new LodGraphic(null, bitmap); diff --git a/source/funkin/util/modding/FunkScript.hx b/source/funkin/util/modding/FunkScript.hx index 62ae4114..f19aeef2 100644 --- a/source/funkin/util/modding/FunkScript.hx +++ b/source/funkin/util/modding/FunkScript.hx @@ -221,8 +221,24 @@ class FunkScript extends hscript.Script implements IFlxDestroyable { return manager; }); - set('addSpr', function(spr:Dynamic, key:String = 'coolswag', onTop:Bool = false):Void { - ScriptUtil.addSprite(spr,key,onTop); + set('addSpr', function(spr:Dynamic, ?key:String, onTop:Bool = false):Dynamic { + return ScriptUtil.addSprite(spr, key, onTop); + }); + + set('insertSpr', function(spr:Dynamic, ?key:String, position:Int, onTop:Bool = false):Dynamic { + return ScriptUtil.insertSprite(spr, key, position, onTop); + }); + + set('insertBehind', function(spr:Dynamic, ?key:String, behindKey:String) { + var layer = ScriptUtil.getSpriteLayer(behindKey); + var bSpr = ScriptUtil.getSprite(behindKey); + ScriptUtil.insertSprite(spr, key, layer.indexOf(bSpr) - 1, layer); + }); + + set('insertAbove', function(spr:Dynamic, ?key:String, aboveKey:String) { + var layer = ScriptUtil.getSpriteLayer(aboveKey); + var aSpr = ScriptUtil.getSprite(aboveKey); + ScriptUtil.insertSprite(spr, key, layer.indexOf(aSpr), layer); }); set('setObjMap', function(object:Dynamic, key:String) { diff --git a/source/funkin/util/modding/ScriptUtil.hx b/source/funkin/util/modding/ScriptUtil.hx index 2f1d4f31..2cb00260 100644 --- a/source/funkin/util/modding/ScriptUtil.hx +++ b/source/funkin/util/modding/ScriptUtil.hx @@ -1,5 +1,6 @@ package funkin.util.modding; +import flixel.util.typeLimit.OneOfTwo; import flixel.util.typeLimit.OneOfThree; typedef SpriteLayer = OneOfThree, String, Bool>; @@ -8,12 +9,18 @@ typedef SpriteLayer = OneOfThree, String, Bool>; class ScriptUtil { public static var objMap:Map = []; - inline public static function addSprite(sprite:Dynamic, key:String, layer:SpriteLayer = "bg") { + inline public static function addSprite(sprite:Dynamic, ?key:String, layer:SpriteLayer = "bg") { objMap.set(formatSpriteKey(key, layer), sprite); getLayer(layer).add(sprite); return sprite; } + inline public static function insertSprite(sprite:Dynamic, ?key:String, position:Int = 0, layer:SpriteLayer = "bg") { + objMap.set(formatSpriteKey(key, layer), sprite); + getLayer(layer).insert(position, sprite); + return sprite; + } + inline static function getLayerKey(layer:SpriteLayer):String { if (layer is String) return layer; else if (layer is Bool) return layer ? "fg" : "bg"; @@ -28,7 +35,7 @@ class ScriptUtil { else return cast(layer, FlxTypedGroup); } - public static function getSprite(key:String) { + public static function getSprite(key:String):Dynamic { for (i in ['fg', 'bg']) { final sprKey = getSpriteKey(i, key); if (objMap.exists(sprKey)) @@ -38,7 +45,7 @@ class ScriptUtil { return null; } - public static function existsSprite(key:String) { + public static function existsSprite(key:String):Bool { for (i in ['fg', 'bg']) { if (objMap.exists(getSpriteKey(i, key))) return true; @@ -46,8 +53,23 @@ class ScriptUtil { return false; } - inline public static function formatSpriteKey(key:String, layer:SpriteLayer) { - return getSpriteKey(getLayerKey(layer), key); + public static function getSpriteLayer(key:String):String { + for (i in ['fg', 'bg']) { + final sprKey = getSpriteKey(i, key); + if (objMap.exists(sprKey)) + return i; + } + ModdingUtil.errorPrint('Sprite not found: $key'); + return null; + } + + inline public static function formatSpriteKey(?key:String, layer:SpriteLayer) { + var layerKey = getLayerKey(layer); + + if (key == null) + key = layerKey + getLayer(layer).length; + + return getSpriteKey(layerKey, key); } inline public static function getSpriteKey(group:String, key:String) { @@ -104,4 +126,43 @@ class ScriptUtil { default: NORMAL; } } -} \ No newline at end of file +} + +/* +typedef LayerKey = OneOfTwo; +typedef Layer = FlxTypedGroup; + +class StageSystem +{ + public var layers:Map = [ + "bg" => new Layer(), + "fg" => new Layer() + ]; + + public var layersOrder:Array = ["bg", "fg"]; + + public function getLayers():Array { + var array:Array = []; + + for (layer in layersOrder) { + var layer = getLayer(layer); + if (layer != null) + array.push(layer); + } + + return array; + } + + public function getLayer(key:LayerKey):Layer { + return layers.get(__resolveLayerKey(key)); + } + + public function addLayer(layer:Layer, key:String) { + layers.set(key, layer); + layersOrder.push(key); + } + + function __resolveLayerKey(key:LayerKey):String { + return key is Bool ? (key ? "fg" : "bg") : key; + } +}*/ \ No newline at end of file diff --git a/source/hscript/UsingHandler.hx b/source/hscript/UsingHandler.hx new file mode 100644 index 00000000..c281fd9f --- /dev/null +++ b/source/hscript/UsingHandler.hx @@ -0,0 +1,316 @@ +package hscript; + +class UsingHandler { + public static function init() {} +} + +/*package hscript; + +import Type.ValueType; +import haxe.macro.ComplexTypeTools; +#if macro +import haxe.macro.Expr; +import haxe.macro.Context; +import haxe.macro.Printer; +import haxe.macro.Compiler; + +using StringTools; + +class UsingHandler { + public var usedClass:Class; + public var className:String; + + public function new(className:String, usedClass:Class) { + this.className = className; + this.usedClass = usedClass; + } + + public static function init() { + Compiler.addGlobalMetadata('flixel', '@:build(hscript.UsingHandler.build())'); + Compiler.addGlobalMetadata('openfl.display.BlendMode', '@:build(hscript.UsingHandler.build())'); + } + + public static function build():Array { + var fields = Context.getBuildFields(); + var clRef = Context.getLocalClass(); + if (clRef == null) return fields; + var cl = clRef.get(); + + // cl.name.startsWith("Flx") && + if (cl.name.endsWith("_Impl_") && cl.params.length <= 0 && !cl.meta.has(":multiType") && !cl.meta.has("_HSC")) { + var metas = cl.meta.get(); + + var shadowClass = macro class { + + }; + shadowClass.kind = TDClass(); + shadowClass.params = switch(cl.params.length) { + case 0: + null; + case 1: + [ + { + name: "T", + } + ]; + default: + [for(k=>e in cl.params) { + name: "T" + Std.int(k+1) + }]; + }; + shadowClass.name = '${cl.name.substr(0, cl.name.length - 6)}_HSC'; + + var imports = Context.getLocalImports().copy(); + setupMetas(shadowClass, imports); + + for(f in fields) + switch(f.kind) { + case FFun(fun): + if (f.access.contains(AStatic)) { + if (fun.expr != null) + shadowClass.fields.push(f); + } + case FProp(get, set, t, e): + if (get == "default" && (set == "never" || set == "null")) + shadowClass.fields.push(f); + case FVar(t, e): + if (f.access.contains(AStatic) || cl.meta.has(":enum") || f.name.toUpperCase() == f.name) { + var name:String = f.name; + var enumType:String = cl.name; + var pack = cl.module.split("."); + pack.pop(); + var complexType:ComplexType = t != null ? t : (name.contains("REGEX") ? + TPath({ + name: "EReg", + pack: [] + }) : TPath({ + name: cl.name.substr(0, cl.name.length - 6), + pack: pack})); + var field:Field = { + pos: f.pos, + name: f.name, + meta: f.meta, + kind: FVar(complexType, { + pos: Context.currentPos(), + expr: ECast(e, complexType) + }), + doc: f.doc, + access: [APublic, AStatic] + } + + shadowClass.fields.push(field); + } + default: + } + + Context.defineModule(cl.module, [shadowClass], imports); + } + + return fields; + } + + static function fixStdTypes(type:ComplexType) { + switch(type) { + case TPath({name: "StdTypes"}): + var a:TypePath = type.getParameters()[0]; + a.name = a.sub; + a.sub = null; + default: + } + return type; + } + + public static function setupMetas(shadowClass:TypeDefinition, imports) { + shadowClass.meta = [{ + name: ':dox', + pos: Context.currentPos(), + params: [ + { + expr: EConst(CIdent("hide")), + pos: Context.currentPos() + } + ] + }]; + var module = Context.getModule(Context.getLocalModule()); + for(t in module) { + switch(t) { + case TInst(t, params): + if (t != null) { + var e = t.get(); + processModule(shadowClass, e.module, e.name); + processImport(imports, e.module, e.name); + } + case TEnum(t, params): + if (t != null) { + var e = t.get(); + processModule(shadowClass, e.module, e.name); + processImport(imports, e.module, e.name); + } + case TType(t, params): + if (t != null) { + var e = t.get(); + processModule(shadowClass, e.module, e.name); + processImport(imports, e.module, e.name); + } + case TAbstract(t, params): + if (t != null) { + var e = t.get(); + processModule(shadowClass, e.module, e.name); + processImport(imports, e.module, e.name); + } + default: + // not needed? + } + } + } + + public static function processModule(shadowClass:TypeDefinition, module:String, n:String) { + if (n.endsWith("_Impl_")) + n = n.substr(0, n.length - 6); + if (module.endsWith("_Impl_")) + module = module.substr(0, module.length - 6); + + shadowClass.meta.push( + { + name: ':access', + params: [ + Context.parse(fixModuleName(module.endsWith('.${n}') ? module : '${module}.${n}'), Context.currentPos()) + ], + pos: Context.currentPos() + } + ); + } + + + //public static function getModuleName(path:Type) { + // switch(path) { + // case TPath(name, pack):// | TDClass(name, pack): + // var str = ""; + // for(p in pack) { + // str += p + "."; + // } + // str += name; + // return str; + // + // default: + // } + // return "INVALID"; + //} + + public static function fixModuleName(name:String) { + return [for(s in name.split(".")) if (s.charAt(0) == "_") s.substr(1) else s].join("."); + } + public static function processImport(imports:Array, module:String, n:String) { + if (n.endsWith("_Impl_")) + n = n.substr(0, n.length - 6); + module = fixModuleName(module); + if (module.endsWith("_Impl_")) + module = module.substr(0, module.length - 6); + + imports.push({ + path: [for(m in module.split(".")) { + name: m, + pos: Context.currentPos() + }], + mode: INormal + }); + } + + public static function cleanExpr(expr:Expr, oldFunc:String, newFunc:String) { + if (expr == null) return; + if (expr.expr == null) return; + switch(expr.expr) { + case EConst(c): + switch(c) { + case CIdent(s): + if (s == oldFunc) + expr.expr = EConst(CIdent(newFunc)); + case CString(s, b): + if (s == oldFunc) + expr.expr = EConst(CString(s, b)); + default: + // nothing + } + case EField(e, field): + if (field == oldFunc && e != null) { + switch(e.expr) { + case EConst(c): + switch(c) { + case CIdent(s): + if (s == "super") + expr.expr = EField(e, newFunc); + default: + + } + default: + + } + } + case EParenthesis(e): + cleanExpr(e, oldFunc, newFunc); + case EObjectDecl(fields): + for(f in fields) { + cleanExpr(f.expr, oldFunc, newFunc); + } + case EArrayDecl(values): + for(a in values) { + cleanExpr(a, oldFunc, newFunc); + } + case ECall(e, params): + cleanExpr(e, oldFunc, newFunc); + case EBlock(exprs): + for(e in exprs) + cleanExpr(e, oldFunc, newFunc); + case EFor(it, expr): + cleanExpr(it, oldFunc, newFunc); + cleanExpr(expr, oldFunc, newFunc); + case EIf(econd, eif, eelse): + cleanExpr(econd, oldFunc, newFunc); + cleanExpr(eif, oldFunc, newFunc); + cleanExpr(eelse, oldFunc, newFunc); + case EWhile(econd, e, normalWhile): + cleanExpr(econd, oldFunc, newFunc); + cleanExpr(e, oldFunc, newFunc); + case ECast(e, t): + cleanExpr(e, oldFunc, newFunc); + case ECheckType(e, t): + cleanExpr(e, oldFunc, newFunc); + case ETry(e, catches): + cleanExpr(e, oldFunc, newFunc); + for(c in catches) { + cleanExpr(c.expr, oldFunc, newFunc); + } + case EThrow(e): + cleanExpr(e, oldFunc, newFunc); + case ETernary(econd, eif, eelse): + cleanExpr(econd, oldFunc, newFunc); + cleanExpr(eif, oldFunc, newFunc); + cleanExpr(eelse, oldFunc, newFunc); + case ESwitch(e, cases, edef): + cleanExpr(e, oldFunc, newFunc); + for(c in cases) { + cleanExpr(c.expr, oldFunc, newFunc); + } + cleanExpr(edef, oldFunc, newFunc); + case EReturn(e): + cleanExpr(e, oldFunc, newFunc); + case EIs(e, t): + cleanExpr(e, oldFunc, newFunc); + case EVars(vars): + for(v in vars) { + cleanExpr(v.expr, oldFunc, newFunc); + } + case ENew(t, params): + for(p in params) { + cleanExpr(p, oldFunc, newFunc); + } + default: + } + } +} +#else +class UsingHandler { + public var usedClass:Class; + public var className:String; +} +#end*/ \ No newline at end of file