diff --git a/Project.xml b/Project.xml index cc0b7b41a9f..c73f53496c3 100644 --- a/Project.xml +++ b/Project.xml @@ -26,6 +26,7 @@ + @@ -109,9 +110,9 @@ - - - + + + @@ -121,6 +122,7 @@ + diff --git a/art/flashFiles/FNF_main_menu_assets_pt-BR.fla b/art/flashFiles/FNF_main_menu_assets_pt-BR.fla new file mode 100644 index 00000000000..510407f72ff Binary files /dev/null and b/art/flashFiles/FNF_main_menu_assets_pt-BR.fla differ diff --git a/art/flashFiles/PsychGF.fla b/art/flashFiles/PsychGF.fla new file mode 100644 index 00000000000..ae0983cdf5e Binary files /dev/null and b/art/flashFiles/PsychGF.fla differ diff --git a/art/flashFiles/PsychGF2.fla b/art/flashFiles/PsychGF2.fla deleted file mode 100644 index de377c9c3a1..00000000000 Binary files a/art/flashFiles/PsychGF2.fla and /dev/null differ diff --git a/assets/base_game/shared/data/2hot/preload.json b/assets/base_game/shared/data/2hot/preload.json new file mode 100644 index 00000000000..66e2f8c5850 --- /dev/null +++ b/assets/base_game/shared/data/2hot/preload.json @@ -0,0 +1,12 @@ +{ + "images/spraycanAtlas/": 3, + "images/PicoBullet": 2, + "images/spraypaintExplosionEZ": 3, + + "sounds/Darnell_Lighter": 3, + "sounds/Kick_Can_UP": 3, + "sounds/Kick_Can_FORWARD": 3, + "sounds/Gun_Prep": 3, + "sounds/Pico_Bonk": 3, + "sounds/shots/": 3 +} \ No newline at end of file diff --git a/assets/base_game/shared/data/stress/preload.json b/assets/base_game/shared/data/stress/preload.json index 5b0ecc2b36f..e318045f208 100644 --- a/assets/base_game/shared/data/stress/preload.json +++ b/assets/base_game/shared/data/stress/preload.json @@ -1,3 +1,3 @@ { - "images": ["tankmanKilled1"] + "images/tankmanKilled1": 3 } \ No newline at end of file diff --git a/assets/base_game/shared/stages/phillyBlazin.json b/assets/base_game/shared/stages/phillyBlazin.json index f96aee9c5d2..25ddd2c8770 100644 --- a/assets/base_game/shared/stages/phillyBlazin.json +++ b/assets/base_game/shared/stages/phillyBlazin.json @@ -20,7 +20,9 @@ "images/phillyBlazin/streetBlur": 3, "images/phillyBlazin/skyBlur": 2, - "images/phillyBlazin/lightning": 2 + "images/phillyBlazin/lightning": 2, + + "sounds/lightning/": 3 }, "_editorMeta": { diff --git a/assets/base_game/shared/stages/phillyStreets.json b/assets/base_game/shared/stages/phillyStreets.json index af10c9bfe37..26ba43b454a 100644 --- a/assets/base_game/shared/stages/phillyStreets.json +++ b/assets/base_game/shared/stages/phillyStreets.json @@ -18,6 +18,7 @@ "images/abot/systemEyes/": 3, "images/abot/abotSystem/": 3, + "images/SpraycanPile": 3, "images/phillyStreets/phillyConstruction": 3, "images/phillyStreets/phillyHighwayLights": 3, "images/phillyStreets/phillyHighway": 3, diff --git a/assets/base_game/weekend1/sounds/Shoot_1.ogg b/assets/base_game/weekend1/sounds/Shoot_1.ogg deleted file mode 100644 index 93e10003ade..00000000000 Binary files a/assets/base_game/weekend1/sounds/Shoot_1.ogg and /dev/null differ diff --git a/assets/base_game/weekend1/sounds/fuse_burning.ogg b/assets/base_game/weekend1/sounds/fuse_burning.ogg deleted file mode 100644 index 9813d0785ae..00000000000 Binary files a/assets/base_game/weekend1/sounds/fuse_burning.ogg and /dev/null differ diff --git a/assets/base_game/weekend1/sounds/Lightning1.ogg b/assets/base_game/weekend1/sounds/lightning/Lightning1.ogg similarity index 100% rename from assets/base_game/weekend1/sounds/Lightning1.ogg rename to assets/base_game/weekend1/sounds/lightning/Lightning1.ogg diff --git a/assets/base_game/weekend1/sounds/Lightning2.ogg b/assets/base_game/weekend1/sounds/lightning/Lightning2.ogg similarity index 100% rename from assets/base_game/weekend1/sounds/Lightning2.ogg rename to assets/base_game/weekend1/sounds/lightning/Lightning2.ogg diff --git a/assets/base_game/weekend1/sounds/Lightning3.ogg b/assets/base_game/weekend1/sounds/lightning/Lightning3.ogg similarity index 100% rename from assets/base_game/weekend1/sounds/Lightning3.ogg rename to assets/base_game/weekend1/sounds/lightning/Lightning3.ogg diff --git a/assets/base_game/weekend1/sounds/shot1.ogg b/assets/base_game/weekend1/sounds/shots/shot1.ogg similarity index 100% rename from assets/base_game/weekend1/sounds/shot1.ogg rename to assets/base_game/weekend1/sounds/shots/shot1.ogg diff --git a/assets/base_game/weekend1/sounds/shot2.ogg b/assets/base_game/weekend1/sounds/shots/shot2.ogg similarity index 100% rename from assets/base_game/weekend1/sounds/shot2.ogg rename to assets/base_game/weekend1/sounds/shots/shot2.ogg diff --git a/assets/base_game/weekend1/sounds/shot3.ogg b/assets/base_game/weekend1/sounds/shots/shot3.ogg similarity index 100% rename from assets/base_game/weekend1/sounds/shot3.ogg rename to assets/base_game/weekend1/sounds/shots/shot3.ogg diff --git a/assets/base_game/weekend1/sounds/shot4.ogg b/assets/base_game/weekend1/sounds/shots/shot4.ogg similarity index 100% rename from assets/base_game/weekend1/sounds/shot4.ogg rename to assets/base_game/weekend1/sounds/shots/shot4.ogg diff --git a/assets/base_game/weekend1/sounds/singed_loop.ogg b/assets/base_game/weekend1/sounds/singed_loop.ogg deleted file mode 100644 index b3e597ae603..00000000000 Binary files a/assets/base_game/weekend1/sounds/singed_loop.ogg and /dev/null differ diff --git a/assets/secrets/images/PessyBump.png b/assets/secrets/images/PessyBump.png new file mode 100644 index 00000000000..107f29c38c2 Binary files /dev/null and b/assets/secrets/images/PessyBump.png differ diff --git a/assets/secrets/images/PessyBump.xml b/assets/secrets/images/PessyBump.xml new file mode 100644 index 00000000000..4cf63c83fbe --- /dev/null +++ b/assets/secrets/images/PessyBump.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/secrets/images/RiverBump.png b/assets/secrets/images/RiverBump.png deleted file mode 100644 index 44f978fd22b..00000000000 Binary files a/assets/secrets/images/RiverBump.png and /dev/null differ diff --git a/assets/secrets/images/RiverBump.xml b/assets/secrets/images/RiverBump.xml deleted file mode 100644 index 38c73e44bc5..00000000000 --- a/assets/secrets/images/RiverBump.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/secrets/images/ShadowBump.xml b/assets/secrets/images/ShadowBump.xml index b3d6293377a..16b32cba941 100644 --- a/assets/secrets/images/ShadowBump.xml +++ b/assets/secrets/images/ShadowBump.xml @@ -8,4 +8,23 @@ + + + + + + + + + + + + + + + + + + + diff --git a/assets/secrets/images/ZRiverBump.png b/assets/secrets/images/ZRiverBump.png new file mode 100644 index 00000000000..19f096b36fc Binary files /dev/null and b/assets/secrets/images/ZRiverBump.png differ diff --git a/assets/secrets/images/ZRiverBump.xml b/assets/secrets/images/ZRiverBump.xml new file mode 100644 index 00000000000..6394744e5e2 --- /dev/null +++ b/assets/secrets/images/ZRiverBump.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/assets/secrets/sounds/JinglePessy.mp3 b/assets/secrets/sounds/JinglePessy.mp3 new file mode 100644 index 00000000000..81d0b9b3419 Binary files /dev/null and b/assets/secrets/sounds/JinglePessy.mp3 differ diff --git a/assets/secrets/sounds/JinglePessy.ogg b/assets/secrets/sounds/JinglePessy.ogg new file mode 100644 index 00000000000..3e3e7bdd5dc Binary files /dev/null and b/assets/secrets/sounds/JinglePessy.ogg differ diff --git a/assets/secrets/sounds/JingleRiver.mp3 b/assets/secrets/sounds/JingleRiver.mp3 index adeffde4e3b..385ebca73d5 100644 Binary files a/assets/secrets/sounds/JingleRiver.mp3 and b/assets/secrets/sounds/JingleRiver.mp3 differ diff --git a/assets/secrets/sounds/JingleRiver.ogg b/assets/secrets/sounds/JingleRiver.ogg index d679905e2ff..52a565a3580 100644 Binary files a/assets/secrets/sounds/JingleRiver.ogg and b/assets/secrets/sounds/JingleRiver.ogg differ diff --git a/assets/shared/images/achievements/pessy_easter_egg.png b/assets/shared/images/achievements/pessy_easter_egg.png new file mode 100644 index 00000000000..02362f5e95b Binary files /dev/null and b/assets/shared/images/achievements/pessy_easter_egg.png differ diff --git a/assets/shared/images/achievements/weekend1_nomiss.png b/assets/shared/images/achievements/weekend1_nomiss.png new file mode 100644 index 00000000000..3c1a17f8de3 Binary files /dev/null and b/assets/shared/images/achievements/weekend1_nomiss.png differ diff --git a/assets/shared/images/credits/majigsaw.png b/assets/shared/images/credits/majigsaw.png new file mode 100644 index 00000000000..48a84e97f3e Binary files /dev/null and b/assets/shared/images/credits/majigsaw.png differ diff --git a/assets/shared/images/gfDanceTitle.json b/assets/shared/images/gfDanceTitle.json index b3a304adf2b..bb5fe726e9b 100644 --- a/assets/shared/images/gfDanceTitle.json +++ b/assets/shared/images/gfDanceTitle.json @@ -1,10 +1,15 @@ { - "titlex":-150, - "titley":-100, - "startx":100, - "starty":576, - "gfx":512, - "gfy":40, - "backgroundSprite":"", - "bpm":102 + "titlex": -150, + "titley": -100, + "startx": 100, + "starty": 576, + "gfx": 512, + "gfy": 40, + "backgroundSprite": "", + "bpm": 102, + + "animation": "gfDance", + "dance_left": [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], + "dance_right": [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], + "idle": false } \ No newline at end of file diff --git a/assets/shared/images/noteSplashes/noteSplashes-diamond.json b/assets/shared/images/noteSplashes/noteSplashes-diamond.json index 2517fd70121..720742a050e 100644 --- a/assets/shared/images/noteSplashes/noteSplashes-diamond.json +++ b/assets/shared/images/noteSplashes/noteSplashes-diamond.json @@ -6,9 +6,11 @@ 95, 68 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "note splash diamond purple 10", - "minFps": 22, "name": "purple", "indices": [] }, @@ -18,9 +20,11 @@ 106, 60 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "note splash diamond blue 20", - "minFps": 22, "name": "blue2", "indices": [] }, @@ -30,9 +34,11 @@ 106, 60 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "note splash diamond red 20", - "minFps": 22, "name": "red2", "indices": [] }, @@ -42,9 +48,11 @@ 95, 68 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "note splash diamond red 10", - "minFps": 22, "name": "red", "indices": [] }, @@ -54,9 +62,11 @@ 106, 60 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "note splash diamond purple 20", - "minFps": 22, "name": "purple2", "indices": [] }, @@ -66,9 +76,11 @@ 95, 68 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "note splash diamond blue 10", - "minFps": 22, "name": "blue", "indices": [] }, @@ -78,9 +90,11 @@ 106, 60 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "note splash diamond green 20", - "minFps": 22, "name": "green2", "indices": [] }, @@ -90,16 +104,16 @@ 95, 68 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "note splash diamond green 10", - "minFps": 22, "name": "green", "indices": [] } }, - "affectedByShader": true, - "scale": [ - 1, - 1 - ] + "allowRGB": true, + "allowPixel": true, + "scale": 1 } \ No newline at end of file diff --git a/assets/shared/images/noteSplashes/noteSplashes-electric.json b/assets/shared/images/noteSplashes/noteSplashes-electric.json index f18a7fe0c82..430ab3d4866 100644 --- a/assets/shared/images/noteSplashes/noteSplashes-electric.json +++ b/assets/shared/images/noteSplashes/noteSplashes-electric.json @@ -6,11 +6,13 @@ 62 ], "noteData": 0, - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "splash electro purple 10", "indices": [], - "name": "purple", - "minFps": 22 + "name": "purple" }, "blue": { "offsets": [ @@ -18,11 +20,13 @@ 62 ], "noteData": 1, - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "splash electro blue 10", "indices": [], - "name": "blue", - "minFps": 22 + "name": "blue" }, "red": { "offsets": [ @@ -30,11 +34,13 @@ 62 ], "noteData": 3, - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "splash electro red 10", "indices": [], - "name": "red", - "minFps": 22 + "name": "red" }, "green": { "offsets": [ @@ -42,14 +48,17 @@ 62 ], "noteData": 2, - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "splash electro green 10", "indices": [], - "name": "green", - "minFps": 22 + "name": "green" } }, - "affectedByShader": true, + "allowRGB": true, + "allowPixel": true, "rgb": [ { "b": 0, @@ -63,8 +72,5 @@ }, null ], - "scale": [ - 1, - 1 - ] + "scale": 1 } \ No newline at end of file diff --git a/assets/shared/images/noteSplashes/noteSplashes-sparkles.json b/assets/shared/images/noteSplashes/noteSplashes-sparkles.json index a87aeabc3cb..7b4080ce132 100644 --- a/assets/shared/images/noteSplashes/noteSplashes-sparkles.json +++ b/assets/shared/images/noteSplashes/noteSplashes-sparkles.json @@ -6,11 +6,13 @@ 68 ], "noteData": 1, - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "splash sparkles blue 10", "indices": [], - "name": "blue", - "minFps": 22 + "name": "blue" }, "purple": { "offsets": [ @@ -18,23 +20,27 @@ 68 ], "noteData": 0, - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "splash sparkles purple 10", "indices": [], - "name": "purple", - "minFps": 22 + "name": "purple" }, "green": { "prefix": "splash sparkles green 10", - "maxFps": 26, + "fps": [ + 22, + 26 + ], "offsets": [ 70, 70 ], "indices": [], "name": "green", - "noteData": 2, - "minFps": 22 + "noteData": 2 }, "red": { "offsets": [ @@ -42,16 +48,16 @@ 68 ], "noteData": 3, - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "splash sparkles red 10", "indices": [], - "name": "red", - "minFps": 22 + "name": "red" } }, - "affectedByShader": true, - "scale": [ - 1, - 1 - ] + "allowRGB": true, + "allowPixel": true, + "scale": 1 } \ No newline at end of file diff --git a/assets/shared/images/noteSplashes/noteSplashes-vanilla.json b/assets/shared/images/noteSplashes/noteSplashes-vanilla.json index 6885937ab6e..5aec3c950d3 100644 --- a/assets/shared/images/noteSplashes/noteSplashes-vanilla.json +++ b/assets/shared/images/noteSplashes/noteSplashes-vanilla.json @@ -6,9 +6,11 @@ 95, 105 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "vanilla splash purple 10", - "minFps": 22, "name": "purple", "indices": [] }, @@ -18,9 +20,11 @@ 105, 90 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "vanilla splash blue 20", - "minFps": 22, "name": "blue2", "indices": [] }, @@ -30,9 +34,11 @@ 95, 100 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "vanilla splash red 20", - "minFps": 22, "name": "red2", "indices": [] }, @@ -42,9 +48,11 @@ 80, 100 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "vanilla splash red 10", - "minFps": 22, "name": "red", "indices": [] }, @@ -54,9 +62,11 @@ 105, 90 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "vanilla splash purple 20", - "minFps": 22, "name": "purple2", "indices": [] }, @@ -66,9 +76,11 @@ 87, 103 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "vanilla splash blue 10", - "minFps": 22, "name": "blue", "indices": [] }, @@ -78,9 +90,11 @@ 94, 100 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "vanilla splash green 20", - "minFps": 22, "name": "green2", "indices": [] }, @@ -90,16 +104,16 @@ 90, 100 ], - "maxFps": 26, + "fps": [ + 22, + 26 + ], "prefix": "vanilla splash green 10", - "minFps": 22, "name": "green", "indices": [] } }, - "affectedByShader": true, - "scale": [ - 1, - 1 - ] + "allowRGB": true, + "allowPixel": true, + "scale": 1 } \ No newline at end of file diff --git a/assets/shared/images/noteSplashes/noteSplashes.json b/assets/shared/images/noteSplashes/noteSplashes.json index 1315a1fd935..a1769d603d2 100644 --- a/assets/shared/images/noteSplashes/noteSplashes.json +++ b/assets/shared/images/noteSplashes/noteSplashes.json @@ -2,104 +2,118 @@ "animations": { "blue2": { "prefix": "note splash blue 20", - "maxFps": 26, + "fps": [ + 22, + 26 + ], "offsets": [ 70, 76 ], "indices": [], "name": "blue2", - "noteData": 5, - "minFps": 22 + "noteData": 5 }, "purple": { "prefix": "note splash purple 10", - "maxFps": 26, + "fps": [ + 22, + 26 + ], "offsets": [ 60, 60 ], "indices": [], "name": "purple", - "noteData": 0, - "minFps": 22 + "noteData": 0 }, "red": { "prefix": "note splash red 10", - "maxFps": 26, + "fps": [ + 22, + 26 + ], "offsets": [ 57, 58 ], "indices": [], "name": "red", - "noteData": 3, - "minFps": 22 + "noteData": 3 }, "red2": { "prefix": "note splash red 20", - "maxFps": 26, + "fps": [ + 22, + 26 + ], "offsets": [ 66, 80 ], "indices": [], "name": "red2", - "noteData": 7, - "minFps": 22 + "noteData": 7 }, "blue": { "prefix": "note splash blue 10", - "maxFps": 26, + "fps": [ + 22, + 26 + ], "offsets": [ 55, 60 ], "indices": [], "name": "blue", - "noteData": 1, - "minFps": 22 + "noteData": 1 }, "purple2": { "prefix": "note splash purple 20", - "maxFps": 26, + "fps": [ + 22, + 26 + ], "offsets": [ 76, 80 ], "indices": [], "name": "purple2", - "noteData": 4, - "minFps": 22 + "noteData": 4 }, "green": { "prefix": "note splash green 10", - "maxFps": 26, + "fps": [ + 22, + 26 + ], "offsets": [ 57, 61 ], "indices": [], "name": "green", - "noteData": 2, - "minFps": 22 + "noteData": 2 }, "green2": { "prefix": "note splash green 20", - "maxFps": 26, + "fps": [ + 22, + 26 + ], "offsets": [ 70, 80 ], "indices": [], "name": "green2", - "noteData": 6, - "minFps": 22 + "noteData": 6 } }, - "affectedByShader": true, - "scale": [ - 1, - 1 - ] + "allowRGB": true, + "allowPixel": true, + "scale": 1 } \ No newline at end of file diff --git a/assets/translations/shared/data/pt-BR.lang b/assets/translations/shared/data/pt-BR.lang index c2d43f96200..d3df9f86005 100644 --- a/assets/translations/shared/data/pt-BR.lang +++ b/assets/translations/shared/data/pt-BR.lang @@ -36,9 +36,8 @@ charting_mode: "Modo Charter" blueballed: "Broxadas: {1}" // Main Menu -images/mainmenu/menu_story_mode: "images/mainmenu/menu_story_mode" -images/mainmenu/menu_freeplay: "images/mainmenu/menu_freeplay" -images/mainmenu/menu_credits: "images/mainmenu/menu_credits" +images/mainmenu/menu_story_mode: "images/pt-BR/mainmenu/menu_story_mode" +images/mainmenu/menu_credits: "images/pt-BR/mainmenu/menu_credits" // Story Mode images/Menu_Tracks: "images/pt-BR/Menu_Tracks" @@ -87,6 +86,8 @@ achievement_week6_nomiss: "Novo Recorde!!" description_week6_nomiss: "Complete a Week 6 no Modo Difícil e sem errar." achievement_week7_nomiss: "Filho da P..." description_week7_nomiss: "Complete a Week 7 no Modo Difícil e sem errar." +achievement_weekend1_nomiss: "Briga sem Perder Amizade" +description_weekend1_nomiss: "Complete a Weekend 1 no Modo Difícil e sem errar." achievement_ur_bad: "Pontuação Desastrosa!" description_ur_bad: "Complete uma Música com uma precisão menor que 20%." achievement_ur_good: "Perfeccionista" @@ -103,6 +104,8 @@ achievement_toastie: "PC de Torradeira" description_toastie: "Jogando num belo de um PC da Xuxa, hein?" achievement_debugger: "Modo Debug" description_debugger: "Complete a Música "Test" através do Chart Editor." +achievement_pessy_easter_egg: "Garota de Programação" +description_pessy_easter_egg: "Hihi, você me encontrou~!" // Options options_note_colors: "Coloração das Notas" diff --git a/assets/translations/shared/images/pt-BR/mainmenu/menu_credits.png b/assets/translations/shared/images/pt-BR/mainmenu/menu_credits.png new file mode 100644 index 00000000000..dad10588a69 Binary files /dev/null and b/assets/translations/shared/images/pt-BR/mainmenu/menu_credits.png differ diff --git a/assets/translations/shared/images/pt-BR/mainmenu/menu_credits.xml b/assets/translations/shared/images/pt-BR/mainmenu/menu_credits.xml new file mode 100644 index 00000000000..eba93d05b18 --- /dev/null +++ b/assets/translations/shared/images/pt-BR/mainmenu/menu_credits.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/translations/shared/images/pt-BR/mainmenu/menu_story_mode.png b/assets/translations/shared/images/pt-BR/mainmenu/menu_story_mode.png new file mode 100644 index 00000000000..217229a174f Binary files /dev/null and b/assets/translations/shared/images/pt-BR/mainmenu/menu_story_mode.png differ diff --git a/assets/translations/shared/images/pt-BR/mainmenu/menu_story_mode.xml b/assets/translations/shared/images/pt-BR/mainmenu/menu_story_mode.xml new file mode 100644 index 00000000000..da33d60d80b --- /dev/null +++ b/assets/translations/shared/images/pt-BR/mainmenu/menu_story_mode.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/setup/unix.sh b/setup/unix.sh index 678c189cd6d..c3477882abc 100755 --- a/setup/unix.sh +++ b/setup/unix.sh @@ -3,19 +3,21 @@ # REMINDER THAT YOU NEED HAXE INSTALLED PRIOR TO USING THIS # https://haxe.org/download cd .. +echo Makking the main haxelib and setuping folder in same time.. +mkdir ~/haxelib && haxelib setup ~/haxelib echo Installing dependencies... echo This might take a few moments depending on your internet speed. haxelib install lime 8.1.2 haxelib install openfl 9.3.3 haxelib install flixel 5.6.1 haxelib install flixel-addons 3.2.2 -haxelib install flixel-tools 1.5.1 -haxelib install SScript 17.1.618 +haxelib install flixel-tools 1.5.1 +haxelib install hscript-iris 1.1.0 haxelib install tjson 1.4.0 +haxelib install hxdiscord_rpc 1.2.4 +haxelib install hxvlc 1.8.2 haxelib git flxanimate https://github.com/Dot-Stuff/flxanimate 768740a56b26aa0c072720e0d1236b94afe68e3e -haxelib git linc_luajit https://github.com/superpowers04/linc_luajit 633fcc051399afed6781dd60cbf30ed8c3fe2c5a -haxelib git hxdiscord_rpc https://github.com/MAJigsaw77/hxdiscord_rpc 3538a1c2bb07b04208cd014220207f8173acdb21 -haxelib git hxvlc https://github.com/MAJigsaw77/hxvlc 70e7f5f3e76d526ac6fb8f0e6665efe7dfda589d -haxelib git funkin.vis https://github.com/FunkinCrew/funkVis d5361037efa3a02c4ab20b5bd14ca11e7d00f519 +haxelib git linc_luajit https://github.com/superpowers04/linc_luajit 1906c4a96f6bb6df66562b3f24c62f4c5bba14a7 +haxelib git funkin.vis https://github.com/FunkinCrew/funkVis 22b1ce089dd924f15cdc4632397ef3504d464e90 haxelib git grig.audio https://gitlab.com/haxe-grig/grig.audio.git cbf91e2180fd2e374924fe74844086aab7891666 -echo Finished! \ No newline at end of file +echo Finished! diff --git a/setup/windows.bat b/setup/windows.bat index 6762cd7d906..f998fe85c9a 100644 --- a/setup/windows.bat +++ b/setup/windows.bat @@ -9,13 +9,13 @@ haxelib install openfl 9.3.3 haxelib install flixel 5.6.1 haxelib install flixel-addons 3.2.2 haxelib install flixel-tools 1.5.1 -haxelib install SScript 17.1.618 +haxelib install hscript-iris 1.1.0 haxelib install tjson 1.4.0 +haxelib install hxdiscord_rpc 1.2.4 +haxelib install hxvlc 1.8.2 haxelib git flxanimate https://github.com/Dot-Stuff/flxanimate 768740a56b26aa0c072720e0d1236b94afe68e3e -haxelib git linc_luajit https://github.com/superpowers04/linc_luajit 633fcc051399afed6781dd60cbf30ed8c3fe2c5a -haxelib git hxdiscord_rpc https://github.com/MAJigsaw77/hxdiscord_rpc 3538a1c2bb07b04208cd014220207f8173acdb21 -haxelib git hxvlc https://github.com/MAJigsaw77/hxvlc 70e7f5f3e76d526ac6fb8f0e6665efe7dfda589d -haxelib git funkin.vis https://github.com/FunkinCrew/funkVis d5361037efa3a02c4ab20b5bd14ca11e7d00f519 +haxelib git linc_luajit https://github.com/superpowers04/linc_luajit 1906c4a96f6bb6df66562b3f24c62f4c5bba14a7 +haxelib git funkin.vis https://github.com/FunkinCrew/funkVis 22b1ce089dd924f15cdc4632397ef3504d464e90 haxelib git grig.audio https://gitlab.com/haxe-grig/grig.audio.git cbf91e2180fd2e374924fe74844086aab7891666 echo Finished! pause diff --git a/source/backend/Achievements.hx b/source/backend/Achievements.hx index e72d189f733..aac0c787a25 100644 --- a/source/backend/Achievements.hx +++ b/source/backend/Achievements.hx @@ -22,6 +22,13 @@ typedef Achievement = @:optional var ID:Int; } +enum abstract AchievementOp(String) +{ + var GET = 'get'; + var SET = 'set'; + var ADD = 'add'; +} + class Achievements { public static function init() { @@ -33,6 +40,7 @@ class Achievements { createAchievement('week5_nomiss', {name: "Missless Christmas", description: "Beat Week 5 on Hard with no Misses."}); createAchievement('week6_nomiss', {name: "Highscore!!", description: "Beat Week 6 on Hard with no Misses."}); createAchievement('week7_nomiss', {name: "God Effing Damn It!", description: "Beat Week 7 on Hard with no Misses."}); + createAchievement('weekend1_nomiss', {name: "Just a Friendly Sparring", description: "Beat Weekend 1 on Hard with no Misses."}); createAchievement('ur_bad', {name: "What a Funkin' Disaster!", description: "Complete a Song with a rating lower than 20%."}); createAchievement('ur_good', {name: "Perfectionist", description: "Complete a Song with a rating of 100%."}); createAchievement('roadkill_enthusiast', {name: "Roadkill Enthusiast", description: "Watch the Henchmen die 50 times.", maxScore: 50, maxDecimals: 0}); @@ -41,6 +49,7 @@ class Achievements { createAchievement('two_keys', {name: "Just the Two of Us", description: "Finish a Song pressing only two keys."}); createAchievement('toastie', {name: "Toaster Gamer", description: "Have you tried to run the game on a toaster?"}); createAchievement('debugger', {name: "Debugger", description: "Beat the \"Test\" Stage from the Chart Editor.", hidden: true}); + createAchievement('pessy_easter_egg', {name: "Engine Gal Pal", description: "Teehee, you found me~!", hidden: true}); //dont delete this thing below _originalLength = _sortID + 1; @@ -85,16 +94,15 @@ class Achievements { } public static function getScore(name:String):Float - return _scoreFunc(name, 0); + return _scoreFunc(name, GET); public static function setScore(name:String, value:Float, saveIfNotUnlocked:Bool = true):Float - return _scoreFunc(name, 1, value, saveIfNotUnlocked); + return _scoreFunc(name, SET, value, saveIfNotUnlocked); public static function addScore(name:String, value:Float = 1, saveIfNotUnlocked:Bool = true):Float - return _scoreFunc(name, 2, value, saveIfNotUnlocked); + return _scoreFunc(name, ADD, value, saveIfNotUnlocked); - //mode 0 = get, 1 = set, 2 = add - static function _scoreFunc(name:String, mode:Int = 0, addOrSet:Float = 1, saveIfNotUnlocked:Bool = true):Float + static function _scoreFunc(name:String, mode:AchievementOp, addOrSet:Float = 1, saveIfNotUnlocked:Bool = true):Float { if(!variables.exists(name)) variables.set(name, 0); @@ -109,8 +117,9 @@ class Achievements { var val = addOrSet; switch(mode) { - case 0: return variables.get(name); //get - case 2: val += variables.get(name); //add + case GET: return variables.get(name); //get + case ADD: val += variables.get(name); //add + default: } if(val >= achievement.maxScore) @@ -277,7 +286,7 @@ class Achievements { } return getScore(name); }); - Lua_helper.add_callback(lua, "setAchievementScore", function(name:String, ?value:Float = 1, ?saveIfNotUnlocked:Bool = true):Float + Lua_helper.add_callback(lua, "setAchievementScore", function(name:String, ?value:Float = 0, ?saveIfNotUnlocked:Bool = true):Float { if(!achievements.exists(name)) { diff --git a/source/backend/CoolUtil.hx b/source/backend/CoolUtil.hx index 443224e3aec..7babc16f9da 100644 --- a/source/backend/CoolUtil.hx +++ b/source/backend/CoolUtil.hx @@ -64,14 +64,16 @@ class CoolUtil inline public static function dominantColor(sprite:flixel.FlxSprite):Int { var countByColor:Map = []; - for(col in 0...sprite.frameWidth) { - for(row in 0...sprite.frameHeight) { - var colorOfThisPixel:Int = sprite.pixels.getPixel32(col, row); - if(colorOfThisPixel != 0) { - if(countByColor.exists(colorOfThisPixel)) - countByColor[colorOfThisPixel] = countByColor[colorOfThisPixel] + 1; - else if(countByColor[colorOfThisPixel] != 13520687 - (2*13520687)) - countByColor[colorOfThisPixel] = 1; + for(col in 0...sprite.frameWidth) + { + for(row in 0...sprite.frameHeight) + { + var colorOfThisPixel:FlxColor = sprite.pixels.getPixel32(col, row); + if(colorOfThisPixel.alphaFloat > 0.05) + { + colorOfThisPixel = FlxColor.fromRGB(colorOfThisPixel.red, colorOfThisPixel.green, colorOfThisPixel.blue, 255); + var count:Int = countByColor.exists(colorOfThisPixel) ? countByColor[colorOfThisPixel] : 0; + countByColor[colorOfThisPixel] = count + 1; } } } @@ -79,9 +81,11 @@ class CoolUtil var maxCount = 0; var maxKey:Int = 0; //after the loop this will store the max color countByColor[FlxColor.BLACK] = 0; - for(key in countByColor.keys()) { - if(countByColor[key] >= maxCount) { - maxCount = countByColor[key]; + for(key => count in countByColor) + { + if(count >= maxCount) + { + maxCount = count; maxKey = key; } } diff --git a/source/backend/Language.hx b/source/backend/Language.hx index f23e9906328..02f03ffd226 100644 --- a/source/backend/Language.hx +++ b/source/backend/Language.hx @@ -77,8 +77,10 @@ class Language // More optimized for file loading inline public static function getFileTranslation(key:String) { + #if TRANSLATIONS_ALLOWED var str:String = phrases.get(key.trim().toLowerCase()); if(str != null) key = str; + #end return key; } diff --git a/source/backend/Mods.hx b/source/backend/Mods.hx index 4951d305616..39eb6e1ea82 100644 --- a/source/backend/Mods.hx +++ b/source/backend/Mods.hx @@ -92,11 +92,16 @@ class Mods inline public static function directoriesWithFile(path:String, fileToFind:String, mods:Bool = true) { var foldersToCheck:Array = []; - #if sys if(FileSystem.exists(path + fileToFind)) - #end foldersToCheck.push(path + fileToFind); + if(Paths.currentLevel != null && Paths.currentLevel != path) + { + var pth:String = Paths.getFolderPath(fileToFind, Paths.currentLevel); + if(FileSystem.exists(pth)) + foldersToCheck.push(pth); + } + #if MODS_ALLOWED if(mods) { diff --git a/source/backend/MusicBeatState.hx b/source/backend/MusicBeatState.hx index 751ec0629e2..d70e332d506 100644 --- a/source/backend/MusicBeatState.hx +++ b/source/backend/MusicBeatState.hx @@ -34,7 +34,7 @@ class MusicBeatState extends FlxState super.create(); if(!skip) { - openSubState(new CustomFadeTransition(0.6, true)); + openSubState(new CustomFadeTransition(0.5, true)); } FlxTransitionableState.skipNextTransOut = false; timePassedOnState = 0; @@ -156,7 +156,7 @@ class MusicBeatState extends FlxState if(nextState == null) nextState = FlxG.state; - FlxG.state.openSubState(new CustomFadeTransition(0.6, false)); + FlxG.state.openSubState(new CustomFadeTransition(0.5, false)); if(nextState == FlxG.state) CustomFadeTransition.finishCallback = function() FlxG.resetState(); else diff --git a/source/backend/Paths.hx b/source/backend/Paths.hx index 83f926dd1be..4079a13c9a7 100644 --- a/source/backend/Paths.hx +++ b/source/backend/Paths.hx @@ -173,9 +173,7 @@ class Paths public static var currentTrackedAssets:Map = []; static public function image(key:String, ?parentFolder:String = null, ?allowGPU:Bool = true):FlxGraphic { - key = Language.getFileTranslation('images/$key'); - if(key.lastIndexOf('.') < 0) key += '.png'; - + key = Language.getFileTranslation('images/$key') + '.png'; var bitmap:BitmapData = null; if (currentTrackedAssets.exists(key)) { @@ -293,9 +291,29 @@ class Paths } return getPackerAtlas(key, parentFolder); } + + static public function getMultiAtlas(keys:Array, ?parentFolder:String = null, ?allowGPU:Bool = true):FlxAtlasFrames + { + + var parentFrames:FlxAtlasFrames = Paths.getAtlas(keys[0].trim()); + if(keys.length > 1) + { + var original:FlxAtlasFrames = parentFrames; + parentFrames = new FlxAtlasFrames(parentFrames.parent); + parentFrames.addAtlas(original, true); + for (i in 1...keys.length) + { + var extraFrames:FlxAtlasFrames = Paths.getAtlas(keys[i].trim(), parentFolder, allowGPU); + if(extraFrames != null) + parentFrames.addAtlas(extraFrames, true); + } + } + return parentFrames; + } inline static public function getSparrowAtlas(key:String, ?parentFolder:String = null, ?allowGPU:Bool = true):FlxAtlasFrames { + if(key.contains('psychic')) trace(key, parentFolder, allowGPU); var imageLoaded:FlxGraphic = image(key, parentFolder, allowGPU); #if MODS_ALLOWED var xmlExists:Bool = false; @@ -303,9 +321,9 @@ class Paths var xml:String = modsXml(key); if(FileSystem.exists(xml)) xmlExists = true; - return FlxAtlasFrames.fromSparrow(imageLoaded, (xmlExists ? File.getContent(xml) : getPath('images/$key.xml', TEXT, parentFolder))); + return FlxAtlasFrames.fromSparrow(imageLoaded, (xmlExists ? File.getContent(xml) : getPath(Language.getFileTranslation('images/$key') + '.xml', TEXT, parentFolder))); #else - return FlxAtlasFrames.fromSparrow(imageLoaded, getPath('images/$key.xml', TEXT, parentFolder)); + return FlxAtlasFrames.fromSparrow(imageLoaded, getPath(Language.getFileTranslation('images/$key') + '.xml', TEXT, parentFolder)); #end } @@ -318,9 +336,9 @@ class Paths var txt:String = modsTxt(key); if(FileSystem.exists(txt)) txtExists = true; - return FlxAtlasFrames.fromSpriteSheetPacker(imageLoaded, (txtExists ? File.getContent(txt) : getPath('images/$key.txt', TEXT, parentFolder))); + return FlxAtlasFrames.fromSpriteSheetPacker(imageLoaded, (txtExists ? File.getContent(txt) : getPath(Language.getFileTranslation('images/$key') + '.txt', TEXT, parentFolder))); #else - return FlxAtlasFrames.fromSpriteSheetPacker(imageLoaded, getPath('images/$key.txt', TEXT, parentFolder)); + return FlxAtlasFrames.fromSpriteSheetPacker(imageLoaded, getPath(Language.getFileTranslation('images/$key') + '.txt', TEXT, parentFolder)); #end } @@ -333,9 +351,9 @@ class Paths var json:String = modsImagesJson(key); if(FileSystem.exists(json)) jsonExists = true; - return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, (jsonExists ? File.getContent(json) : getPath('images/$key.json', TEXT, parentFolder))); + return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, (jsonExists ? File.getContent(json) : getPath(Language.getFileTranslation('images/$key') + '.json', TEXT, parentFolder))); #else - return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, getPath('images/$key.json', TEXT, parentFolder)); + return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, getPath(Language.getFileTranslation('images/$key') + '.json', TEXT, parentFolder)); #end } diff --git a/source/backend/SpectralAnalyzerEx.hx b/source/backend/SpectralAnalyzerEx.hx deleted file mode 100644 index 3e32a242555..00000000000 --- a/source/backend/SpectralAnalyzerEx.hx +++ /dev/null @@ -1,161 +0,0 @@ -package backend; -#if funkin.vis -import funkin.vis._internal.html5.AnalyzerNode; -import funkin.vis.audioclip.frontends.LimeAudioClip; -import funkin.vis.dsp.SpectralAnalyzer; -import funkin.vis.dsp.RecentPeakFinder; -import grig.audio.FFT; -import grig.audio.FFTVisualization; -import lime.media.AudioSource; - -using grig.audio.lime.UInt8ArrayTools; -#end - -class SpectralAnalyzerEx #if funkin.vis extends SpectralAnalyzer #end -{ - #if funkin.vis - var _levels:Array = []; - public function recycledLevels():Array - { - #if web - var amplitudes:Array = htmlAnalyzer.getFloatFrequencyData(); - - for (i in 0...bars.length) { - var bar = bars[i]; - var binLo = bar.binLo; - var binHi = bar.binHi; - - var value:Float = minDb; - for (j in (binLo + 1)...(binHi)) { - value = Math.max(value, amplitudes[Std.int(j)]); - } - - // this isn't for clamping, it's to get a value - // between 0 and 1! - value = normalizedB(value); - bar.recentValues.push(value); - var recentPeak = bar.recentValues.peak; - - if(_levels[i] != null) - { - _levels[i].value = value; - _levels[i].peak = recentPeak; - } - else _levels.push({value: value, peak: recentPeak}); - } - - return _levels; - #else - var numOctets = Std.int(audioSource.buffer.bitsPerSample / 8); - var wantedLength = fftN * numOctets * audioSource.buffer.channels; - var startFrame = audioClip.currentFrame; - startFrame -= startFrame % numOctets; - var segment = audioSource.buffer.data.subarray(startFrame, min(startFrame + wantedLength, audioSource.buffer.data.length)); - var signal = recycledInterleaved(segment, audioSource.buffer.bitsPerSample); - - if (audioSource.buffer.channels > 1) - { - var mixed = []; - mixed.resize(Std.int(signal.length / audioSource.buffer.channels)); - for (i in 0...mixed.length) - { - mixed[i] = 0.0; - for (c in 0...audioSource.buffer.channels) - mixed[i] += 0.7 * signal[i*audioSource.buffer.channels+c]; - - mixed[i] *= blackmanWindow[i]; - } - signal = mixed; - } - - var range = 16; - var freqs = fft.calcFreq(signal); - var bars = vis.makeLogGraph(freqs, barCount, Math.floor(maxDb - minDb), range); - - if (bars.length > barHistories.length) - barHistories.resize(bars.length); - - _levels.resize(bars.length); - for (i in 0...bars.length) - { - if (barHistories[i] == null) - { - barHistories[i] = new RecentPeakFinder(); - trace('created barHistories[$i]'); - } - var recentValues = barHistories[i]; - var value = bars[i] / range; - - // slew limiting - var lastValue = recentValues.lastValue; - if (maxDelta > 0.0) - { - var delta = clamp(value - lastValue, -1 * maxDelta, maxDelta); - value = lastValue + delta; - } - recentValues.push(value); - - var recentPeak = recentValues.peak; - - if(_levels[i] != null) - { - _levels[i].value = value; - _levels[i].peak = recentPeak; - } - else _levels[i] = {value: value, peak: recentPeak}; - } - return _levels; - #end - } - - var _buffer:Array = []; - function recycledInterleaved(data:lime.utils.UInt8Array, bitsPerSample:Int):Array - { - switch(bitsPerSample) - { - case 8: - _buffer.resize(data.length); - for (i in 0...data.length) - _buffer[i] = data[i] / 128.0; - - case 16: - _buffer.resize(Std.int(data.length / 2)); - for (i in 0..._buffer.length) - _buffer[i] = data.getInt16(i * 2) / 32767.0; - - case 24: - _buffer.resize(Std.int(data.length / 3)); - for (i in 0..._buffer.length) - _buffer[i] = data.getInt24(i * 3) / 8388607.0; - - case 32: - _buffer.resize(Std.int(data.length / 4)); - for (i in 0..._buffer.length) - _buffer[i] = data.getInt32(i * 4) / 2147483647.0; - - default: trace('Unknown integer audio format'); - } - return _buffer; - } - - @:generic - static inline function min(x:T, y:T):T - { - return x > y ? y : x; - } - - @:generic - static inline function clamp(val:T, min:T, max:T):T - { - return val <= min ? min : val >= max ? max : val; - } - #else - //Just to avoid errors until they review my PR - public var fftN:Int = 0; - public function new(?v1:Dynamic, ?v2:Dynamic, ?v3:Dynamic, ?v4:Dynamic) {} - public function recycledLevels():Array - { - return [{value: 0, peak: 0}]; - } - #end -} \ No newline at end of file diff --git a/source/backend/ui/PsychUIInputText.hx b/source/backend/ui/PsychUIInputText.hx index d6c70ddf13c..f50dfc7c28e 100644 --- a/source/backend/ui/PsychUIInputText.hx +++ b/source/backend/ui/PsychUIInputText.hx @@ -660,7 +660,7 @@ class PsychUIInputText extends FlxSpriteGroup var letter:String = String.fromCharCode(charCode); letter = filter(letter); - if(letter.length > 0 && (maxLength == 0 || (text.length + letter.length) < maxLength)) + if(letter.length > 0 && (maxLength == 0 || (text.length + letter.length) <= maxLength)) { var lastText = text; //trace('Drawing character: $letter'); diff --git a/source/debug/FPSCounter.hx b/source/debug/FPSCounter.hx index e774328b508..33786aee619 100644 --- a/source/debug/FPSCounter.hx +++ b/source/debug/FPSCounter.hx @@ -46,19 +46,18 @@ class FPSCounter extends TextField // Event Handlers private override function __enterFrame(deltaTime:Float):Void { - // prevents the overlay from updating every frame, why would you need to anyways - if (deltaTimeout > 1000) { - deltaTimeout = 0.0; - return; - } - final now:Float = haxe.Timer.stamp() * 1000; times.push(now); while (times[0] < now - 1000) times.shift(); + // prevents the overlay from updating every frame, why would you need to anyways @crowplexus + if (deltaTimeout < 1000) { + deltaTimeout += deltaTime; + return; + } currentFPS = times.length < FlxG.updateFramerate ? times.length : FlxG.updateFramerate; updateText(); - deltaTimeout += deltaTime; + deltaTimeout = 0.0; } public dynamic function updateText():Void { // so people can override it in hscript diff --git a/source/objects/Character.hx b/source/objects/Character.hx index f8ec03d49e4..cbe232fe227 100644 --- a/source/objects/Character.hx +++ b/source/objects/Character.hx @@ -2,8 +2,6 @@ package objects; import backend.animation.PsychAnimationController; -import flixel.graphics.frames.FlxAtlasFrames; - import flixel.util.FlxSort; import flixel.util.FlxDestroyUtil; @@ -158,21 +156,7 @@ class Character extends FlxSprite if(!isAnimateAtlas) { - var split:Array = json.image.split(','); - var charFrames:FlxAtlasFrames = Paths.getAtlas(split[0].trim()); - if(split.length > 1) - { - var original:FlxAtlasFrames = charFrames; - charFrames = new FlxAtlasFrames(charFrames.parent); - charFrames.addAtlas(original, true); - for (i in 1...split.length) - { - var extraFrames:FlxAtlasFrames = Paths.getAtlas(split[i].trim()); - if(extraFrames != null) - charFrames.addAtlas(extraFrames, true); - } - } - frames = charFrames; + frames = Paths.getMultiAtlas(json.image.split(',')); } #if flxanimate else diff --git a/source/objects/HealthIcon.hx b/source/objects/HealthIcon.hx index 18afe6788dc..317c02fb37a 100644 --- a/source/objects/HealthIcon.hx +++ b/source/objects/HealthIcon.hx @@ -30,12 +30,13 @@ class HealthIcon extends FlxSprite if(!Paths.fileExists('images/' + name + '.png', IMAGE)) name = 'icons/icon-face'; //Prevents crash from missing icon var graphic = Paths.image(name, allowGPU); - loadGraphic(graphic, true, Math.floor(graphic.width / 2), Math.floor(graphic.height)); - iconOffsets[0] = (width - 150) / 2; - iconOffsets[1] = (height - 150) / 2; + var iSize:Float = Math.round(graphic.width / graphic.height); + loadGraphic(graphic, true, Math.floor(graphic.width / iSize), Math.floor(graphic.height)); + iconOffsets[0] = (width - 150) / iSize; + iconOffsets[1] = (height - 150) / iSize; updateHitbox(); - animation.add(char, [0, 1], 0, false, isPlayer); + animation.add(char, [for(i in 0...frames.frames.length) i], 0, false, isPlayer); animation.play(char); this.char = char; diff --git a/source/objects/NoteSplash.hx b/source/objects/NoteSplash.hx index 6c74fb03545..e041b41fb79 100644 --- a/source/objects/NoteSplash.hx +++ b/source/objects/NoteSplash.hx @@ -1,13 +1,12 @@ package objects; -import states.editors.NoteSplashEditorState; -import haxe.Json; import backend.animation.PsychAnimationController; import shaders.RGBPalette; +import states.editors.NoteSplashEditorState; + import flixel.system.FlxAssets.FlxShader; -import flixel.util.FlxColor; private typedef RGB = { r:Null, @@ -17,37 +16,39 @@ private typedef RGB = { private typedef NoteSplashAnim = { name:String, - prefix:String, - maxFps:Int, - minFps:Int, noteData:Int, - offsets:Array, + prefix:String, indices:Array, + offsets:Array, + fps:Array } typedef NoteSplashConfig = { animations:Map, - scale:Array, - affectedByShader:Bool, + scale:Float, + allowRGB:Bool, + allowPixel:Bool, rgb:Array> } class NoteSplash extends FlxSprite { + public var rgbShader:PixelSplashShaderRef; public var skin:String; public var config(default, set):NoteSplashConfig; - public static var DEFAULT_SKIN:String = "noteSplashes"; + + public static var DEFAULT_SKIN:String = "noteSplashes/noteSplashes"; public static var configs:Map = new Map(); public var babyArrow:StrumNote; - var noteDataMap:Map = new Map(); - var rgbShader:PixelSplashShaderRef; public function new(?splash:String) { super(); + animation = new PsychAnimationController(this); + rgbShader = new PixelSplashShaderRef(); shader = rgbShader.shader; @@ -58,40 +59,39 @@ class NoteSplash extends FlxSprite { config = null; // Reset config to the default so when reloaded it can be set properly skin = null; - + var skin:String = splash; - if (skin == null || skin.length < 1) skin = try PlayState.SONG.splashSkin catch(e) null; if (skin == null || skin.length < 1) skin = DEFAULT_SKIN + getSplashSkinPostfix(); - + this.skin = skin; - try frames = Paths.getSparrowAtlas("noteSplashes/" + skin) catch (e) { + try frames = Paths.getSparrowAtlas(skin) catch (e) { skin = DEFAULT_SKIN; // The splash skin was not found, return to the default this.skin = skin; - try frames = Paths.getSparrowAtlas("noteSplashes/" + skin) catch (e) { + try frames = Paths.getSparrowAtlas(skin) catch (e) { active = visible = false; } } - var path:String = 'images/noteSplashes/$skin.json'; - if (configs.exists(path)) - this.config = configs.get(path); + var path:String = 'images/$skin.json'; + if (configs.exists(path)) this.config = configs.get(path); else if (Paths.fileExists(path, TEXT)) { - var config:Dynamic = Json.parse(Paths.getTextFromFile(path)); - + var config:Dynamic = haxe.Json.parse(Paths.getTextFromFile(path)); if (config != null) { var tempConfig:NoteSplashConfig = { animations: new Map(), scale: config.scale, - affectedByShader: config.affectedByShader, + allowRGB: config.allowRGB, + allowPixel: config.allowPixel, rgb: config.rgb } + for (i in Reflect.fields(config.animations)) { tempConfig.animations.set(i, Reflect.field(config.animations, i)); @@ -123,14 +123,17 @@ class NoteSplash extends FlxSprite var anims:Int = 0; var datas:Int = 0; var animArray:Array = []; + while (true) { var data:Int = noteData % 4 + (datas * 4); if (!noteDataMap.exists(data) || !animation.exists(noteDataMap[data])) break; + datas++; anims++; } + if (anims > 1) { for (i in 0...anims) @@ -154,94 +157,84 @@ class NoteSplash extends FlxSprite this.animation.play(animation); anim = animation; } - else - visible = false; + else visible = false; } playDefaultAnim(); var tempShader:RGBPalette = null; - if (note == null) - note = new Note(0, noteData); - - Note.initializeGlobalRGBShader(noteData % 4); - function useDefault() + if (config.allowRGB) { - tempShader = Note.globalRgbShaders[noteData % 4]; - } + if (note == null) + note = new Note(0, noteData); - if(((cast FlxG.state) is NoteSplashEditorState) || - ((note.noteSplashData.useRGBShader) && (PlayState.SONG == null || !PlayState.SONG.disableNoteRGB))) - { - // If Note RGB is enabled: - if((!note.noteSplashData.useGlobalShader || ((cast FlxG.state) is NoteSplashEditorState))) + Note.initializeGlobalRGBShader(noteData % 4); + function useDefault() { - var colors = config.rgb; - if (colors != null) + tempShader = Note.globalRgbShaders[noteData % 4]; + } + + if(((cast FlxG.state) is NoteSplashEditorState) || + ((note.noteSplashData.useRGBShader) && (PlayState.SONG == null || !PlayState.SONG.disableNoteRGB))) + { + // If Note RGB is enabled: + if((!note.noteSplashData.useGlobalShader || ((cast FlxG.state) is NoteSplashEditorState))) { - tempShader = new RGBPalette(); - for (i in 0...colors.length) + var colors = config.rgb; + if (colors != null) { - if (i > 2) - break; - - var rgb = colors[i]; - var arr:Array = ClientPrefs.data.arrowRGB[noteData % 4]; - if(PlayState.isPixelStage) arr = ClientPrefs.data.arrowRGBPixel[noteData % 4]; - if (rgb == null) + tempShader = new RGBPalette(); + for (i in 0...colors.length) { - if (i == 0) - tempShader.r = arr[0]; - else if (i == 1) - tempShader.g = arr[1]; - else if (i == 2) - tempShader.b = arr[2]; - continue; - } - - var r:Null = rgb.r; - var g:Null = rgb.g; - var b:Null = rgb.b; - - if (r == null || Math.isNaN(r) || r < 0) - r = arr[0]; - if (g == null || Math.isNaN(g) || g < 0) - g = arr[1]; - if (b == null || Math.isNaN(b) || b < 0) - b = arr[2]; - - var color:FlxColor = FlxColor.fromRGB(r, g, b); - if (i == 0) - tempShader.r = color; - else if (i == 1) - tempShader.g = color; - else if (i == 2) - tempShader.b = color; - } + if (i > 2) break; + + var arr:Array = ClientPrefs.data.arrowRGB[noteData % 4]; + if(PlayState.isPixelStage) arr = ClientPrefs.data.arrowRGBPixel[noteData % 4]; + + var rgb = colors[i]; + if (rgb == null) + { + if (i == 0) tempShader.r = arr[0]; + else if (i == 1) tempShader.g = arr[1]; + else if (i == 2) tempShader.b = arr[2]; + continue; + } + + var r:Null = rgb.r; + var g:Null = rgb.g; + var b:Null = rgb.b; + + if (r == null || Math.isNaN(r) || r < 0) r = arr[0]; + if (g == null || Math.isNaN(g) || g < 0) g = arr[1]; + if (b == null || Math.isNaN(b) || b < 0) b = arr[2]; + + var color:FlxColor = FlxColor.fromRGB(r, g, b); + if (i == 0) tempShader.r = color; + else if (i == 1) tempShader.g = color; + else if (i == 2) tempShader.b = color; + } + } + else useDefault(); } - else - useDefault(); - } - else - { - useDefault(); + else useDefault(); } } + rgbShader.copyValues(tempShader); - if (config.affectedByShader) - rgbShader.copyValues(tempShader); - else - rgbShader.reset(); + if(!config.allowPixel) rgbShader.pixelAmount = 1; var conf = config.animations.get(anim); - var offsets = [0, 0]; + var offsets:Array = [0, 0]; + if (conf != null) offsets = conf.offsets; + if (offsets != null) { centerOffsets(); offset.set(offsets[0], offsets[1]); } + animation.finishCallback = function(name:String) { kill(); @@ -255,12 +248,12 @@ class NoteSplash extends FlxSprite if(animation.curAnim != null && conf != null) { - var minFps = conf.minFps; - if (minFps < 0) - minFps = 0; - var maxFps = conf.maxFps; - if (maxFps < 0) - maxFps = 0; + var minFps = conf.fps[0]; + if (minFps < 0) minFps = 0; + + var maxFps = conf.fps[1]; + if (maxFps < 0) maxFps = 0; + animation.curAnim.frameRate = FlxG.random.int(minFps, maxFps); } } @@ -288,26 +281,25 @@ class NoteSplash extends FlxSprite { return { animations: new Map(), - scale: [1, 1], - affectedByShader: true, + scale: 1, + allowRGB: true, + allowPixel: true, rgb: null } } - public static function addAnimationToConfig(scale:Array, config:NoteSplashConfig, name:String, prefix:String, minFps:Int, maxFps:Int, offsets:Array, indices:Array, noteData:Int):NoteSplashConfig + public static function addAnimationToConfig(config:NoteSplashConfig, scale:Float, name:String, prefix:String, fps:Array, offsets:Array, indices:Array, noteData:Int):NoteSplashConfig { - if (config == null) - config = createConfig(); + if (config == null) config = createConfig(); - config.animations.set(name, {name: name, prefix: prefix, indices: indices, minFps: minFps, maxFps: maxFps, offsets: offsets, noteData: noteData}); + config.animations.set(name, {name: name, noteData: noteData, prefix: prefix, indices: indices, offsets: offsets, fps: fps}); config.scale = scale; return config; } function set_config(value:NoteSplashConfig):NoteSplashConfig { - if (value == null) - value = createConfig(); + if (value == null) value = createConfig(); noteDataMap.clear(); @@ -317,13 +309,15 @@ class NoteSplash extends FlxSprite if (i.prefix.length > 0 && key != null && key.length > 0) { if (i.indices != null && i.indices.length > 0 && key != null && key.length > 0) - animation.addByIndices(key, i.prefix, i.indices, "", i.maxFps, false); + animation.addByIndices(key, i.prefix, i.indices, "", i.fps[1], false); else - animation.addByPrefix(key, i.prefix, i.maxFps, false); + animation.addByPrefix(key, i.prefix, i.fps[1], false); + noteDataMap.set(i.noteData, key); } } - scale.set(value.scale[0], value.scale[1]); + + scale.set(value.scale, value.scale); return config = value; } } @@ -331,14 +325,12 @@ class NoteSplash extends FlxSprite class PixelSplashShaderRef { public var shader:PixelSplashShader = new PixelSplashShader(); + public var enabled(default, set):Bool = true; + public var pixelAmount(default, set):Float = 1; public function copyValues(tempShader:RGBPalette) { - var enabled:Bool = false; if(tempShader != null) - enabled = true; - - if(enabled) { for (i in 0...3) { @@ -348,12 +340,21 @@ class PixelSplashShaderRef } shader.mult.value[0] = tempShader.shader.mult.value[0]; } - else shader.mult.value[0] = 0.0; + else enabled = false; + } + + public function set_enabled(value:Bool) + { + enabled = value; + shader.mult.value = [value ? 1 : 0]; + return value; } - public function set(enabled:Bool = true) + public function set_pixelAmount(value:Float) { - shader.mult.value = [enabled ? 1 : 0]; + pixelAmount = value; + shader.uBlocksize.value = [value, value]; + return value; } public function reset() @@ -366,11 +367,10 @@ class PixelSplashShaderRef public function new() { reset(); - set(); + enabled = true; - var pixel:Float = 1; - if(PlayState.isPixelStage) pixel = PlayState.daPixelZoom; - shader.uBlocksize.value = [pixel, pixel]; + if(!PlayState.isPixelStage) pixelAmount = 1; + else pixelAmount = PlayState.daPixelZoom; //trace('Created shader ' + Conductor.songPosition); } } @@ -379,7 +379,7 @@ class PixelSplashShader extends FlxShader { @:glFragmentHeader(' #pragma header - + uniform vec3 r; uniform vec3 g; uniform vec3 b; @@ -400,9 +400,9 @@ class PixelSplashShader extends FlxShader vec4 newColor = color; newColor.rgb = min(color.r * r + color.g * g + color.b * b, vec3(1.0)); newColor.a = color.a; - + color = mix(color, newColor, mult); - + if(color.a > 0.0) { return vec4(color.rgb, color.a); } diff --git a/source/options/NotesSubState.hx b/source/options/NotesColorSubState.hx similarity index 99% rename from source/options/NotesSubState.hx rename to source/options/NotesColorSubState.hx index 466f9111f40..572c03bf426 100644 --- a/source/options/NotesSubState.hx +++ b/source/options/NotesColorSubState.hx @@ -13,7 +13,7 @@ import objects.Note; import shaders.RGBPalette; import shaders.RGBPalette.RGBShaderReference; -class NotesSubState extends MusicBeatSubstate +class NotesColorSubState extends MusicBeatSubstate { var onModeColumn:Bool = true; var curSelectedMode:Int = 0; @@ -54,6 +54,7 @@ class NotesSubState extends MusicBeatSubstate DiscordClient.changePresence("Note Colors Menu", null); #end + onPixel = PlayState.isPixelStage; var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuDesat')); bg.color = 0xFFEA71FD; bg.screenCenter(); diff --git a/source/options/OptionsState.hx b/source/options/OptionsState.hx index ab8f7ab3ce5..a2e4a7c4317 100644 --- a/source/options/OptionsState.hx +++ b/source/options/OptionsState.hx @@ -23,7 +23,7 @@ class OptionsState extends MusicBeatState switch(label) { case 'Note Colors': - openSubState(new options.NotesSubState()); + openSubState(new options.NotesColorSubState()); case 'Controls': openSubState(new options.ControlsSubState()); case 'Graphics': diff --git a/source/psychlua/CustomSubstate.hx b/source/psychlua/CustomSubstate.hx index b4c82a60853..69a4702c4d6 100644 --- a/source/psychlua/CustomSubstate.hx +++ b/source/psychlua/CustomSubstate.hx @@ -31,8 +31,6 @@ class CustomSubstate extends MusicBeatSubstate } } PlayState.instance.openSubState(new CustomSubstate(name)); - PlayState.instance.setOnHScript('customSubstate', instance); - PlayState.instance.setOnHScript('customSubstateName', name); } public static function closeCustomSubstate() @@ -51,7 +49,6 @@ class CustomSubstate extends MusicBeatSubstate if(instance != null) { var tagObject:FlxObject = cast (MusicBeatState.getVariables().get(tag), FlxObject); - #if LUA_ALLOWED if(tagObject == null) tagObject = cast (MusicBeatState.getVariables().get(tag), FlxObject); #end if(tagObject != null) { @@ -66,6 +63,8 @@ class CustomSubstate extends MusicBeatSubstate override function create() { instance = this; + PlayState.instance.setOnHScript('customSubstate', instance); + PlayState.instance.callOnScripts('onCustomSubstateCreate', [name]); super.create(); @@ -75,6 +74,7 @@ class CustomSubstate extends MusicBeatSubstate public function new(name:String) { CustomSubstate.name = name; + PlayState.instance.setOnHScript('customSubstateName', name); super(); cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; } diff --git a/source/psychlua/FunkinLua.hx b/source/psychlua/FunkinLua.hx index 914470c10ca..4f93e742d5d 100644 --- a/source/psychlua/FunkinLua.hx +++ b/source/psychlua/FunkinLua.hx @@ -31,7 +31,7 @@ import substates.GameOverSubstate; import psychlua.LuaUtils; import psychlua.LuaUtils.LuaTweenOptions; -#if SScript +#if HSCRIPT_ALLOWED import psychlua.HScript; #end import psychlua.DebugLuaText; @@ -84,6 +84,7 @@ class FunkinLua { set('luaDebugMode', false); set('luaDeprecatedWarnings', true); set('version', MainMenuState.psychEngineVersion.trim()); + set('modFolder', this.modFolder); // Song/Week shit set('curBpm', Conductor.bpm); @@ -111,10 +112,6 @@ class FunkinLua { set('seenCutscene', PlayState.seenCutscene); set('hasVocals', PlayState.SONG.needsVoices); - // Camera poo - set('cameraX', 0); - set('cameraY', 0); - // Screen stuff set('screenWidth', FlxG.width); set('screenHeight', FlxG.height); @@ -133,10 +130,13 @@ class FunkinLua { set('misses', 0); set('hits', 0); set('combo', 0); + set('deaths', PlayState.deathCounter); set('rating', 0); set('ratingName', ''); set('ratingFC', ''); + set('totalPlayed', 0); + set('totalNotesHit', 0.0); set('inGameOver', false); set('mustHitSection', false); @@ -257,110 +257,21 @@ class FunkinLua { args = []; } - var foundScript:String = findScript(luaFile); - if(foundScript != null) - for (luaInstance in game.luaArray) - if(luaInstance.scriptName == foundScript) - { - luaInstance.call(funcName, args); - return; - } - }); - - Lua_helper.add_callback(lua, "getGlobalFromScript", function(luaFile:String, global:String) { // returns the global from a script - var foundScript:String = findScript(luaFile); - if(foundScript != null) - for (luaInstance in game.luaArray) - if(luaInstance.scriptName == foundScript) - { - Lua.getglobal(luaInstance.lua, global); - if(Lua.isnumber(luaInstance.lua,-1)) - Lua.pushnumber(lua, Lua.tonumber(luaInstance.lua, -1)); - else if(Lua.isstring(luaInstance.lua,-1)) - Lua.pushstring(lua, Lua.tostring(luaInstance.lua, -1)); - else if(Lua.isboolean(luaInstance.lua,-1)) - Lua.pushboolean(lua, Lua.toboolean(luaInstance.lua, -1)); - else - Lua.pushnil(lua); - - // TODO: table - - Lua.pop(luaInstance.lua,1); // remove the global + for (luaInstance in game.luaArray) + if(luaInstance.scriptName == luaFile) + return luaInstance.call(funcName, args); - return; - } + return null; }); - Lua_helper.add_callback(lua, "setGlobalFromScript", function(luaFile:String, global:String, val:Dynamic) { // returns the global from a script - var foundScript:String = findScript(luaFile); - if(foundScript != null) - for (luaInstance in game.luaArray) - if(luaInstance.scriptName == foundScript) - luaInstance.set(global, val); - }); - /*Lua_helper.add_callback(lua, "getGlobals", function(luaFile:String) { // returns a copy of the specified file's globals - var foundScript:String = findScript(luaFile); - if(foundScript != null) - { - for (luaInstance in game.luaArray) - { - if(luaInstance.scriptName == foundScript) - { - Lua.newtable(lua); - var tableIdx = Lua.gettop(lua); - - Lua.pushvalue(luaInstance.lua, Lua.LUA_GLOBALSINDEX); - while(Lua.next(luaInstance.lua, -2) != 0) { - // key = -2 - // value = -1 - - var pop:Int = 0; - - // Manual conversion - // first we convert the key - if(Lua.isnumber(luaInstance.lua,-2)){ - Lua.pushnumber(lua, Lua.tonumber(luaInstance.lua, -2)); - pop++; - }else if(Lua.isstring(luaInstance.lua,-2)){ - Lua.pushstring(lua, Lua.tostring(luaInstance.lua, -2)); - pop++; - }else if(Lua.isboolean(luaInstance.lua,-2)){ - Lua.pushboolean(lua, Lua.toboolean(luaInstance.lua, -2)); - pop++; - } - // TODO: table - - - // then the value - if(Lua.isnumber(luaInstance.lua,-1)){ - Lua.pushnumber(lua, Lua.tonumber(luaInstance.lua, -1)); - pop++; - }else if(Lua.isstring(luaInstance.lua,-1)){ - Lua.pushstring(lua, Lua.tostring(luaInstance.lua, -1)); - pop++; - }else if(Lua.isboolean(luaInstance.lua,-1)){ - Lua.pushboolean(lua, Lua.toboolean(luaInstance.lua, -1)); - pop++; - } - // TODO: table - - if(pop==2)Lua.rawset(lua, tableIdx); // then set it - Lua.pop(luaInstance.lua, 1); // for the loop - } - Lua.pop(luaInstance.lua,1); // end the loop entirely - Lua.pushvalue(lua, tableIdx); // push the table onto the stack so it gets returned + Lua_helper.add_callback(lua, "isRunning", function(scriptFile:String) { + for (luaInstance in game.luaArray) + if(luaInstance.scriptName == scriptFile) + return true; - return; - } + for (hscriptInstance in game.hscriptArray) + if(hscriptInstance.origin == scriptFile) + return true; - } - } - });*/ - Lua_helper.add_callback(lua, "isRunning", function(luaFile:String) { - var foundScript:String = findScript(luaFile); - if(foundScript != null) - for (luaInstance in game.luaArray) - if(luaInstance.scriptName == foundScript) - return true; return false; }); @@ -375,37 +286,43 @@ class FunkinLua { return MusicBeatState.getVariables().remove(varName); }); - Lua_helper.add_callback(lua, "addLuaScript", function(luaFile:String, ?ignoreAlreadyRunning:Bool = false) { //would be dope asf. - var foundScript:String = findScript(luaFile); - if(foundScript != null) + Lua_helper.add_callback(lua, "addLuaScript", function(luaFile:String, ?ignoreAlreadyRunning:Bool = false) { + #if sys + if(FileSystem.exists(luaFile)) + #else + if(Assets.exists(luaFile, TEXT)) + #end { if(!ignoreAlreadyRunning) for (luaInstance in game.luaArray) - if(luaInstance.scriptName == foundScript) + if(luaInstance.scriptName == luaFile) { - luaTrace('addLuaScript: The script "' + foundScript + '" is already running!'); + luaTrace('addLuaScript: The script "' + luaFile + '" is already running!'); return; } - new FunkinLua(foundScript); + new FunkinLua(luaFile); return; } luaTrace("addLuaScript: Script doesn't exist!", false, false, FlxColor.RED); }); - Lua_helper.add_callback(lua, "addHScript", function(haxeFile:String, ?ignoreAlreadyRunning:Bool = false) { + Lua_helper.add_callback(lua, "addHScript", function(scriptFile:String, ?ignoreAlreadyRunning:Bool = false) { #if HSCRIPT_ALLOWED - var foundScript:String = findScript(haxeFile, '.hx'); - if(foundScript != null) + #if sys + if(FileSystem.exists(scriptFile)) + #else + if(Assets.exists(scriptFile, TEXT)) + #end { if(!ignoreAlreadyRunning) for (script in game.hscriptArray) - if(script.origin == foundScript) + if(script.origin == scriptFile) { - luaTrace('addHScript: The script "' + foundScript + '" is already running!'); + luaTrace('addHScript: The script "' + scriptFile + '" is already running!'); return; } - PlayState.instance.initHScript(foundScript); + PlayState.instance.initHScript(scriptFile); return; } luaTrace("addHScript: Script doesn't exist!", false, false, FlxColor.RED); @@ -413,37 +330,37 @@ class FunkinLua { luaTrace("addHScript: HScript is not supported on this platform!", false, false, FlxColor.RED); #end }); - Lua_helper.add_callback(lua, "removeLuaScript", function(luaFile:String, ?ignoreAlreadyRunning:Bool = false) { - var foundScript:String = findScript(luaFile); - if(foundScript != null) + Lua_helper.add_callback(lua, "removeLuaScript", function(luaFile:String) { + var foundAny:Bool = false; + for (luaInstance in game.luaArray) { - if(!ignoreAlreadyRunning) - for (luaInstance in game.luaArray) - if(luaInstance.scriptName == foundScript) - { - luaInstance.stop(); - trace('Closing script ' + luaInstance.scriptName); - return true; - } + if(luaInstance.scriptName == luaFile) + { + trace('Closing lua script $luaFile'); + luaInstance.stop(); + foundAny = true; + } } + if(foundAny) return true; + luaTrace('removeLuaScript: Script $luaFile isn\'t running!', false, false, FlxColor.RED); return false; }); - Lua_helper.add_callback(lua, "removeHScript", function(luaFile:String, ?ignoreAlreadyRunning:Bool = false) { + Lua_helper.add_callback(lua, "removeHScript", function(scriptFile:String) { #if HSCRIPT_ALLOWED - var foundScript:String = findScript(luaFile, '.hx'); - if(foundScript != null) + var foundAny:Bool = false; + for (script in game.hscriptArray) { - if(!ignoreAlreadyRunning) - for (script in game.hscriptArray) - if(script.origin == foundScript) - { - trace('Closing script ' + (script.origin != null ? script.origin : luaFile)); - script.destroy(); - return true; - } + if(script.origin == scriptFile) + { + trace('Closing hscript $scriptFile'); + script.destroy(); + foundAny = true; + } } - luaTrace('removeHScript: Script $luaFile isn\'t running!', false, false, FlxColor.RED); + if(foundAny) return true; + + luaTrace('removeHScript: Script $scriptFile isn\'t running!', false, false, FlxColor.RED); return false; #else luaTrace("removeHScript: HScript is not supported on this platform!", false, false, FlxColor.RED); @@ -632,7 +549,7 @@ class FunkinLua { Lua_helper.add_callback(lua, "noteTweenDirection", function(tag:String, note:Int, value:Dynamic, duration:Float, ease:String) { noteTweenFunction(tag, note, {direction: value}, duration, ease); }); - Lua_helper.add_callback(lua, "mouseClicked", function(button:String) { + Lua_helper.add_callback(lua, "mouseClicked", function(?button:String = 'left') { var click:Bool = FlxG.mouse.justPressed; switch(button.trim().toLowerCase()) { @@ -643,7 +560,7 @@ class FunkinLua { } return click; }); - Lua_helper.add_callback(lua, "mousePressed", function(button:String) { + Lua_helper.add_callback(lua, "mousePressed", function(?button:String = 'left') { var press:Bool = FlxG.mouse.pressed; switch(button.trim().toLowerCase()) { @@ -654,7 +571,7 @@ class FunkinLua { } return press; }); - Lua_helper.add_callback(lua, "mouseReleased", function(button:String) { + Lua_helper.add_callback(lua, "mouseReleased", function(?button:String = 'left') { var released:Bool = FlxG.mouse.justReleased; switch(button.trim().toLowerCase()) { @@ -851,15 +768,28 @@ class FunkinLua { game.moveCamera(isDad); return isDad; }); + + Lua_helper.add_callback(lua, "setCameraScroll", function(x:Float, y:Float) FlxG.camera.scroll.set(x - FlxG.width/2, y - FlxG.height/2)); + Lua_helper.add_callback(lua, "setCameraFollowPoint", function(x:Float, y:Float) game.camFollow.setPosition(x, y)); + Lua_helper.add_callback(lua, "addCameraScroll", function(?x:Float = 0, ?y:Float = 0) FlxG.camera.scroll.add(x, y)); + Lua_helper.add_callback(lua, "addCameraFollowPoint", function(?x:Float = 0, ?y:Float = 0) { + game.camFollow.x += x; + game.camFollow.y += y; + }); + Lua_helper.add_callback(lua, "getCameraScrollX", () -> FlxG.camera.scroll.x + FlxG.width/2); + Lua_helper.add_callback(lua, "getCameraScrollY", () -> FlxG.camera.scroll.y + FlxG.height/2); + Lua_helper.add_callback(lua, "getCameraFollowX", () -> game.camFollow.x); + Lua_helper.add_callback(lua, "getCameraFollowY", () -> game.camFollow.y); + Lua_helper.add_callback(lua, "cameraShake", function(camera:String, intensity:Float, duration:Float) { LuaUtils.cameraFromString(camera).shake(intensity, duration); }); Lua_helper.add_callback(lua, "cameraFlash", function(camera:String, color:String, duration:Float,forced:Bool) { - LuaUtils.cameraFromString(camera).flash(CoolUtil.colorFromString(color), duration, null,forced); + LuaUtils.cameraFromString(camera).flash(CoolUtil.colorFromString(color), duration, null, forced); }); - Lua_helper.add_callback(lua, "cameraFade", function(camera:String, color:String, duration:Float,forced:Bool) { - LuaUtils.cameraFromString(camera).fade(CoolUtil.colorFromString(color), duration, false,null,forced); + Lua_helper.add_callback(lua, "cameraFade", function(camera:String, color:String, duration:Float, forced:Bool, ?fadeOut:Bool = false) { + LuaUtils.cameraFromString(camera).fade(CoolUtil.colorFromString(color), duration, fadeOut, null, forced); }); Lua_helper.add_callback(lua, "setRatingPercent", function(value:Float) { return game.ratingPercent = value; @@ -870,11 +800,11 @@ class FunkinLua { Lua_helper.add_callback(lua, "setRatingFC", function(value:String) { return game.ratingFC = value; }); - Lua_helper.add_callback(lua, "getMouseX", function(camera:String = 'game') { + Lua_helper.add_callback(lua, "getMouseX", function(?camera:String = 'game') { var cam:FlxCamera = LuaUtils.cameraFromString(camera); return FlxG.mouse.getScreenPosition(cam).x; }); - Lua_helper.add_callback(lua, "getMouseY", function(camera:String = 'game') { + Lua_helper.add_callback(lua, "getMouseY", function(?camera:String = 'game') { var cam:FlxCamera = LuaUtils.cameraFromString(camera); return FlxG.mouse.getScreenPosition(cam).y; }); @@ -1371,7 +1301,10 @@ class FunkinLua { }); Lua_helper.add_callback(lua, "stopSound", function(tag:String) { if(tag == null || tag.length < 1) - if(FlxG.sound.music != null) FlxG.sound.music.stop(); + { + if(FlxG.sound.music != null) + FlxG.sound.music.stop(); + } else { tag = LuaUtils.formatVariable('sound_$tag'); @@ -1386,7 +1319,10 @@ class FunkinLua { }); Lua_helper.add_callback(lua, "pauseSound", function(tag:String) { if(tag == null || tag.length < 1) - if(FlxG.sound.music != null) FlxG.sound.music.pause(); + { + if(FlxG.sound.music != null) + FlxG.sound.music.pause(); + } else { tag = LuaUtils.formatVariable('sound_$tag'); @@ -1396,7 +1332,10 @@ class FunkinLua { }); Lua_helper.add_callback(lua, "resumeSound", function(tag:String) { if(tag == null || tag.length < 1) - if(FlxG.sound.music != null) FlxG.sound.music.play(); + { + if(FlxG.sound.music != null) + FlxG.sound.music.play(); + } else { tag = LuaUtils.formatVariable('sound_$tag'); @@ -1762,27 +1701,6 @@ class FunkinLua { return (result == 'true'); } - function findScript(scriptFile:String, ext:String = '.lua') - { - if(!scriptFile.endsWith(ext)) scriptFile += ext; - var preloadPath:String = Paths.getSharedPath(scriptFile); - #if MODS_ALLOWED - var path:String = Paths.modFolders(scriptFile); - if(FileSystem.exists(scriptFile)) - return scriptFile; - else if(FileSystem.exists(path)) - return path; - - if(FileSystem.exists(preloadPath)) - #else - if(Assets.exists(preloadPath)) - #end - { - return preloadPath; - } - return null; - } - public function getErrorMessage(status:Int):String { var v:String = Lua.tostring(lua, -1); Lua.pop(lua, 1); @@ -1869,4 +1787,4 @@ class FunkinLua { return false; } } -#end \ No newline at end of file +#end diff --git a/source/psychlua/HScript.hx b/source/psychlua/HScript.hx index a421ee71e2a..59eca54b644 100644 --- a/source/psychlua/HScript.hx +++ b/source/psychlua/HScript.hx @@ -10,9 +10,11 @@ import psychlua.FunkinLua; #end #if HSCRIPT_ALLOWED -import tea.SScript; -class HScript extends SScript +import crowplexus.iris.Iris; + +class HScript extends Iris { + public var filePath:String; public var modFolder:String; #if LUA_ALLOWED @@ -37,11 +39,14 @@ class HScript extends SScript else { hs.varsToBring = varsToBring; - hs.doString(code); - @:privateAccess - if(hs.parsingException != null) + try + { + hs.scriptCode = code; + hs.execute(); + } + catch(e:Dynamic) { - PlayState.instance.addTextToDebug('ERROR ON LOADING (${hs.origin}): ${hs.parsingException.message}', FlxColor.RED); + FunkinLua.luaTrace('ERROR (${hs.origin}) - $e', false, false, FlxColor.RED); } } } @@ -53,7 +58,7 @@ class HScript extends SScript if (file == null) file = ''; - super(file, false, false); + super(null, {name: "hscript-iris", autoRun: false, autoPreset: false}); #if LUA_ALLOWED parentLua = parent; @@ -64,20 +69,31 @@ class HScript extends SScript } #end - if (scriptFile != null && scriptFile.length > 0) + filePath = file; + if (filePath != null && filePath.length > 0) { - this.origin = scriptFile; + this.origin = filePath; #if MODS_ALLOWED - var myFolder:Array = scriptFile.split('/'); + var myFolder:Array = filePath.split('/'); if(myFolder[0] + '/' == Paths.mods() && (Mods.currentModDirectory == myFolder[1] || Mods.getGlobalMods().contains(myFolder[1]))) //is inside mods folder this.modFolder = myFolder[1]; #end } - this.varsToBring = varsToBring; + var scriptThing:String = file; + if(parent == null && file != null) + { + var f:String = file.replace('\\', '/'); + if(f.contains('/') && !f.contains('\n')) + { + scriptThing = File.getContent(f); + } + } + this.scriptCode = scriptThing; preset(); execute(); + this.varsToBring = varsToBring; } var varsToBring(default, set):Any = null; @@ -303,67 +319,56 @@ class HScript extends SScript set('addBehindGF', PlayState.instance.addBehindGF); set('addBehindDad', PlayState.instance.addBehindDad); set('addBehindBF', PlayState.instance.addBehindBF); - setSpecialObject(PlayState.instance, false, PlayState.instance.instancesExclude); } } - public function executeCode(?funcToRun:String = null, ?funcArgs:Array = null):Tea { + public function executeCode(?funcToRun:String = null, ?funcArgs:Array = null):IrisCall { if (funcToRun == null) return null; if(!exists(funcToRun)) { #if LUA_ALLOWED - FunkinLua.luaTrace(origin + ' - No HScript function named: $funcToRun', false, false, FlxColor.RED); + FunkinLua.luaTrace(origin + ' - No function named: $funcToRun', false, false, FlxColor.RED); #else - PlayState.instance.addTextToDebug(origin + ' - No HScript function named: $funcToRun', FlxColor.RED); + PlayState.instance.addTextToDebug(origin + ' - No function named: $funcToRun', FlxColor.RED); #end return null; } - final callValue = call(funcToRun, funcArgs); - if (!callValue.succeeded) + try { - final e = callValue.exceptions[0]; - if (e != null) { - var msg:String = e.toString(); - #if LUA_ALLOWED - if(parentLua != null) - { - FunkinLua.luaTrace('$origin: ${parentLua.lastCalledFunction} - $msg', false, false, FlxColor.RED); - return null; - } - #end - PlayState.instance.addTextToDebug('$origin - $msg', FlxColor.RED); - } - return null; + final callValue:IrisCall = call(funcToRun, funcArgs); + return callValue.signature; } - return callValue; + catch(e:Dynamic) + { + trace('ERROR ${funcToRun}: $e'); + } + return null; } - public function executeFunction(funcToRun:String = null, funcArgs:Array):Tea { - if (funcToRun == null) return null; + public function executeFunction(funcToRun:String = null, funcArgs:Array = null):IrisCall { + if (funcToRun == null || !exists(funcToRun)) return null; return call(funcToRun, funcArgs); } #if LUA_ALLOWED public static function implement(funk:FunkinLua) { - funk.addLocalCallback("runHaxeCode", function(codeToRun:String, ?varsToBring:Any = null, ?funcToRun:String = null, ?funcArgs:Array = null):Dynamic { - #if SScript + funk.addLocalCallback("runHaxeCode", function(codeToRun:String, ?varsToBring:Any = null, ?funcToRun:String = null, ?funcArgs:Array = null):IrisCall { + #if HSCRIPT_ALLOWED initHaxeModuleCode(funk, codeToRun, varsToBring); - final retVal:Tea = funk.hscript.executeCode(funcToRun, funcArgs); - if (retVal != null) { - if(retVal.succeeded) - return (retVal.returnValue == null || LuaUtils.isOfTypes(retVal.returnValue, [Bool, Int, Float, String, Array])) ? retVal.returnValue : null; - - final e = retVal.exceptions[0]; - final calledFunc:String = if(funk.hscript.origin == funk.lastCalledFunction) funcToRun else funk.lastCalledFunction; - if (e != null) - FunkinLua.luaTrace(funk.hscript.origin + ":" + calledFunc + " - " + e, false, false, FlxColor.RED); - return null; + try + { + final retVal:IrisCall = funk.hscript.executeCode(funcToRun, funcArgs); + if (retVal != null) + { + return (retVal.signature == null || LuaUtils.isOfTypes(retVal.signature, [Bool, Int, Float, String, Array])) ? retVal.signature : null; + } } - else if (funk.hscript.returnValue != null) + catch(e:Dynamic) { - return funk.hscript.returnValue; + FunkinLua.luaTrace('ERROR (${funk.hscript.origin}: $funcToRun) - $e', false, false, FlxColor.RED); } + #else FunkinLua.luaTrace("runHaxeCode: HScript isn't supported on this platform!", false, false, FlxColor.RED); #end @@ -371,22 +376,26 @@ class HScript extends SScript }); funk.addLocalCallback("runHaxeFunction", function(funcToRun:String, ?funcArgs:Array = null) { - #if SScript - var callValue = funk.hscript.executeFunction(funcToRun, funcArgs); - if (!callValue.succeeded) + #if HSCRIPT_ALLOWED + try + { + final retVal:IrisCall = funk.hscript.executeFunction(funcToRun, funcArgs); + if (retVal != null) + { + return (retVal.signature == null || LuaUtils.isOfTypes(retVal.signature, [Bool, Int, Float, String, Array])) ? retVal.signature : null; + } + } + catch(e:Dynamic) { - var e = callValue.exceptions[0]; - if (e != null) - FunkinLua.luaTrace('ERROR (${funk.hscript.origin}: ${callValue.calledFunction}) - ' + e.message.substr(0, e.message.indexOf('\n')), false, false, FlxColor.RED); - return null; + FunkinLua.luaTrace('ERROR (${funk.hscript.origin}: $funcToRun) - $e', false, false, FlxColor.RED); } - else - return callValue.returnValue; + return null; #else FunkinLua.luaTrace("runHaxeFunction: HScript isn't supported on this platform!", false, false, FlxColor.RED); + return null; #end }); - // This function is unnecessary because import already exists in SScript as a native feature + // This function is unnecessary because import already exists in HScript as a native feature funk.addLocalCallback("addHaxeLibrary", function(libName:String, ?libPackage:String = '') { var str:String = ''; if(libPackage.length > 0) @@ -398,12 +407,7 @@ class HScript extends SScript if (c == null) c = Type.resolveEnum(str + libName); - #if SScript - if (c != null) - SScript.globalVariables[libName] = c; - #end - - #if SScript + #if HSCRIPT_ALLOWED if (funk.hscript != null) { try { @@ -421,6 +425,17 @@ class HScript extends SScript } #end + override public function set(name:String, value:Dynamic, allowOverride:Bool = false):Void { + // should always override by default + super.set(name, value, true); + } + + /*override function irisPrint(v):Void + { + FunkinLua.luaTrace('ERROR (${this.origin}:${interp.posInfos().lineNumber}): ${v}'); + trace('[${ruleSet.name}:${interp.posInfos().lineNumber}]: ${v}\n'); + }*/ + override public function destroy() { origin = null; @@ -430,14 +445,15 @@ class HScript extends SScript } function set_varsToBring(values:Any) { - if (varsToBring != null) { - for (key in Reflect.fields(varsToBring)) { - unset(key.trim()); - } - } + if (varsToBring != null) + for (key in Reflect.fields(varsToBring)) + if(exists(key.trim())) + interp.variables.remove(key.trim()); - if (values != null) { - for (key in Reflect.fields(values)) { + if (values != null) + { + for (key in Reflect.fields(values)) + { key = key.trim(); set(key, Reflect.field(values, key)); } diff --git a/source/psychlua/LuaUtils.hx b/source/psychlua/LuaUtils.hx index 2dbd096a5f5..99e382541c6 100644 --- a/source/psychlua/LuaUtils.hx +++ b/source/psychlua/LuaUtils.hx @@ -20,11 +20,11 @@ typedef LuaTweenOptions = { class LuaUtils { - public static final Function_Stop:Dynamic = "##PSYCHLUA_FUNCTIONSTOP"; - public static final Function_Continue:Dynamic = "##PSYCHLUA_FUNCTIONCONTINUE"; - public static final Function_StopLua:Dynamic = "##PSYCHLUA_FUNCTIONSTOPLUA"; - public static final Function_StopHScript:Dynamic = "##PSYCHLUA_FUNCTIONSTOPHSCRIPT"; - public static final Function_StopAll:Dynamic = "##PSYCHLUA_FUNCTIONSTOPALL"; + public static final Function_Stop:String = "##PSYCHLUA_FUNCTIONSTOP"; + public static final Function_Continue:String = "##PSYCHLUA_FUNCTIONCONTINUE"; + public static final Function_StopLua:String = "##PSYCHLUA_FUNCTIONSTOPLUA"; + public static final Function_StopHScript:String = "##PSYCHLUA_FUNCTIONSTOPHSCRIPT"; + public static final Function_StopAll:String = "##PSYCHLUA_FUNCTIONSTOPALL"; public static function getLuaTween(options:Dynamic) { @@ -497,9 +497,12 @@ class LuaUtils public static function cameraFromString(cam:String):FlxCamera { switch(cam.toLowerCase()) { + case 'camgame' | 'game': return PlayState.instance.camGame; case 'camhud' | 'hud': return PlayState.instance.camHUD; case 'camother' | 'other': return PlayState.instance.camOther; } - return PlayState.instance.camGame; + var camera:FlxCamera = MusicBeatState.getVariables().get(cam); + if (camera == null || !Std.isOfType(camera, FlxCamera)) camera = PlayState.instance.camGame; + return camera; } } \ No newline at end of file diff --git a/source/psychlua/ReflectionFunctions.hx b/source/psychlua/ReflectionFunctions.hx index 1c32a6b27ca..b1a485e2ea0 100644 --- a/source/psychlua/ReflectionFunctions.hx +++ b/source/psychlua/ReflectionFunctions.hx @@ -26,10 +26,10 @@ class ReflectionFunctions var split:Array = variable.split('.'); if(split.length > 1) { LuaUtils.setVarInArray(LuaUtils.getPropertyLoop(split, true, allowMaps), split[split.length-1], value, allowMaps); - return true; + return value; } LuaUtils.setVarInArray(LuaUtils.getTargetInstance(), variable, value, allowMaps); - return true; + return value; }); Lua_helper.add_callback(lua, "getPropertyFromClass", function(classVar:String, variable:String, ?allowMaps:Bool = false) { var myClass:Dynamic = Type.resolveClass(classVar); diff --git a/source/psychlua/ShaderFunctions.hx b/source/psychlua/ShaderFunctions.hx index 79ae92ed637..c9f755d02c1 100644 --- a/source/psychlua/ShaderFunctions.hx +++ b/source/psychlua/ShaderFunctions.hx @@ -13,7 +13,7 @@ class ShaderFunctions funk.addLocalCallback("initLuaShader", function(name:String, ?glslVersion:Int = 120) { if(!ClientPrefs.data.shaders) return false; - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) return funk.initLuaShader(name, glslVersion); #else FunkinLua.luaTrace("initLuaShader: Platform unsupported for Runtime Shaders!", false, false, FlxColor.RED); @@ -24,7 +24,7 @@ class ShaderFunctions funk.addLocalCallback("setSpriteShader", function(obj:String, shader:String) { if(!ClientPrefs.data.shaders) return false; - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) if(!funk.runtimeShaders.exists(shader) && !funk.initLuaShader(shader)) { FunkinLua.luaTrace('setSpriteShader: Shader $shader is missing!', false, false, FlxColor.RED); @@ -63,7 +63,7 @@ class ShaderFunctions Lua_helper.add_callback(lua, "getShaderBool", function(obj:String, prop:String) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if (shader == null) { @@ -77,7 +77,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "getShaderBoolArray", function(obj:String, prop:String) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if (shader == null) { @@ -91,7 +91,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "getShaderInt", function(obj:String, prop:String) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if (shader == null) { @@ -105,7 +105,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "getShaderIntArray", function(obj:String, prop:String) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if (shader == null) { @@ -119,7 +119,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "getShaderFloat", function(obj:String, prop:String) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if (shader == null) { @@ -133,7 +133,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "getShaderFloatArray", function(obj:String, prop:String) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if (shader == null) { @@ -149,7 +149,7 @@ class ShaderFunctions Lua_helper.add_callback(lua, "setShaderBool", function(obj:String, prop:String, value:Bool) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if(shader == null) { @@ -164,7 +164,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "setShaderBoolArray", function(obj:String, prop:String, values:Dynamic) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if(shader == null) { @@ -179,7 +179,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "setShaderInt", function(obj:String, prop:String, value:Int) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if(shader == null) { @@ -194,7 +194,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "setShaderIntArray", function(obj:String, prop:String, values:Dynamic) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if(shader == null) { @@ -209,7 +209,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "setShaderFloat", function(obj:String, prop:String, value:Float) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if(shader == null) { @@ -224,7 +224,7 @@ class ShaderFunctions #end }); Lua_helper.add_callback(lua, "setShaderFloatArray", function(obj:String, prop:String, values:Dynamic) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if(shader == null) { @@ -241,7 +241,7 @@ class ShaderFunctions }); Lua_helper.add_callback(lua, "setShaderSampler2D", function(obj:String, prop:String, bitmapdataPath:String) { - #if (!flash && MODS_ALLOWED && sys) + #if (!flash && sys) var shader:FlxRuntimeShader = getShader(obj); if(shader == null) { diff --git a/source/psychlua/TextFunctions.hx b/source/psychlua/TextFunctions.hx index 9c011be1e67..4c25a2c9152 100644 --- a/source/psychlua/TextFunctions.hx +++ b/source/psychlua/TextFunctions.hx @@ -5,7 +5,7 @@ class TextFunctions public static function implement(funk:FunkinLua) { var lua = funk.lua; - Lua_helper.add_callback(lua, "makeLuaText", function(tag:String, text:String, width:Int, x:Float, y:Float) { + Lua_helper.add_callback(lua, "makeLuaText", function(tag:String, ?text:String = '', ?width:Int = 0, ?x:Float = 0, ?y:Float = 0) { tag = tag.replace('.', ''); LuaUtils.destroyObject(tag); diff --git a/source/states/CreditsState.hx b/source/states/CreditsState.hx index 4e5b51e2ca1..33ab5312fc5 100644 --- a/source/states/CreditsState.hx +++ b/source/states/CreditsState.hx @@ -39,31 +39,31 @@ class CreditsState extends MusicBeatState var defaultList:Array> = [ //Name - Icon name - Description - Link - BG Color ["Psych Engine Team"], - ["Shadow Mario", "shadowmario", "Main Programmer and Head of Psych Engine", "https://ko-fi.com/shadowmario", "444444"], - ["Riveren", "riveren", "Main Artist/Animator of Psych Engine", "https://twitter.com/riverennn", "14967B"], + ["Shadow Mario", "shadowmario", "Main Programmer and Head of Psych Engine", "https://ko-fi.com/shadowmario", "444444"], + ["Riveren", "riveren", "Main Artist/Animator of Psych Engine", "https://x.com/riverennn", "14967B"], [""], ["Former Engine Members"], - ["bb-panzu", "bb", "Ex-Programmer of Psych Engine", "https://twitter.com/bbsub3", "3E813A"], + ["bb-panzu", "bb", "Ex-Programmer of Psych Engine", "https://x.com/bbsub3", "3E813A"], [""], ["Engine Contributors"], - ["crowplexus", "crowplexus", "Input System v3, Major Help and Other PRs", "https://twitter.com/crowplexus", "A1A1A1"], - ["Kamizeta", "kamizeta", "Creator of Pessy, Psych Engine's mascot.", "https://twitter.com/LittleCewwy", "D21C11"], - ["MaxNeton", "maxneton", "Loading Screen Easter Egg Artist/Animator.", "https://twitter.com/MaxNeton", "3C2E4E"], - ["Keoiki", "keoiki", "Note Splash Animations and Latin Alphabet", "https://twitter.com/Keoiki_", "D2D2D2"], - ["SqirraRNG", "sqirra", "Crash Handler and Base code for\nChart Editor's Waveform", "https://twitter.com/gedehari", "E1843A"], - ["EliteMasterEric", "mastereric", "Runtime Shaders support and Other PRs", "https://twitter.com/EliteMasterEric", "FFBD40"], - ["MAJigsaw77", "majigsaw", ".MP4 Video Loader Library (hxvlc)", "https://twitter.com/MAJigsaw77", "A1A1A1"], - ["Tahir Toprak Karabekiroglu", "tahir", "Implementing & Maintaining SScript and Other PRs", "https://twitter.com/TahirKarabekir", "A04397"], - ["iFlicky", "flicky", "Composer of Psync and Tea Time\nMade the Dialogue Sounds", "https://twitter.com/flicky_i", "9E29CF"], - ["KadeDev", "kade", "Fixed some issues on Chart Editor and Other PRs", "https://twitter.com/kade0912", "64A250"], - ["superpowers04", "superpowers04", "LUA JIT Fork", "https://twitter.com/superpowers04", "B957ED"], - ["CheemsAndFriends", "cheems", "Creator of FlxAnimate", "https://twitter.com/CheemsnFriendos", "E1E1E1"], + ["crowplexus", "crowplexus", "HScript Iris, Input System v3, and Other PRs", "https://github.com/crowplexus", "CFCFCF"], + ["Kamizeta", "kamizeta", "Creator of Pessy, Psych Engine's mascot.", "https://www.instagram.com/cewweey/", "D21C11"], + ["MaxNeton", "maxneton", "Loading Screen Easter Egg Artist/Animator.", "https://bsky.app/profile/maxneton.bsky.social","3C2E4E"], + ["Keoiki", "keoiki", "Note Splash Animations and Latin Alphabet", "https://x.com/Keoiki_", "D2D2D2"], + ["SqirraRNG", "sqirra", "Crash Handler and Base code for\nChart Editor's Waveform", "https://x.com/gedehari", "E1843A"], + ["EliteMasterEric", "mastereric", "Runtime Shaders support and Other PRs", "https://x.com/EliteMasterEric", "FFBD40"], + ["MAJigsaw77", "majigsaw", ".MP4 Video Loader Library (hxvlc)", "https://x.com/MAJigsaw77", "5F5F5F"], + ["Tahir Toprak Karabekiroglu", "tahir", "Note Splash Editor and Other PRs", "https://x.com/TahirKarabekir", "A04397"], + ["iFlicky", "flicky", "Composer of Psync and Tea Time\nAnd some sound effects", "https://x.com/flicky_i", "9E29CF"], + ["KadeDev", "kade", "Fixed some issues on Chart Editor and Other PRs", "https://x.com/kade0912", "64A250"], + ["superpowers04", "superpowers04", "LUA JIT Fork", "https://x.com/superpowers04", "B957ED"], + ["CheemsAndFriends", "cheems", "Creator of FlxAnimate", "https://x.com/CheemsnFriendos", "E1E1E1"], [""], ["Funkin' Crew"], - ["ninjamuffin99", "ninjamuffin99", "Programmer of Friday Night Funkin'", "https://twitter.com/ninja_muffin99", "CF2D2D"], - ["PhantomArcade", "phantomarcade", "Animator of Friday Night Funkin'", "https://twitter.com/PhantomArcade3K", "FADC45"], - ["evilsk8r", "evilsk8r", "Artist of Friday Night Funkin'", "https://twitter.com/evilsk8r", "5ABD4B"], - ["kawaisprite", "kawaisprite", "Composer of Friday Night Funkin'", "https://twitter.com/kawaisprite", "378FC7"], + ["ninjamuffin99", "ninjamuffin99", "Programmer of Friday Night Funkin'", "https://x.com/ninja_muffin99", "CF2D2D"], + ["PhantomArcade", "phantomarcade", "Animator of Friday Night Funkin'", "https://x.com/PhantomArcade3K", "FADC45"], + ["evilsk8r", "evilsk8r", "Artist of Friday Night Funkin'", "https://x.com/evilsk8r", "5ABD4B"], + ["kawaisprite", "kawaisprite", "Composer of Friday Night Funkin'", "https://x.com/kawaisprite", "378FC7"], [""], ["Psych Engine Discord"], ["Join the Psych Ward!", "discord", "", "https://discord.gg/2ka77eMXDv", "5165F6"] diff --git a/source/states/FlashingState.hx b/source/states/FlashingState.hx index 917dab5dd1e..a6ee4604b10 100644 --- a/source/states/FlashingState.hx +++ b/source/states/FlashingState.hx @@ -24,7 +24,7 @@ class FlashingState extends MusicBeatState Press ESCAPE to ignore this message.\n You've been warned!", 32); - warnText.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, CENTER); + warnText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, CENTER); warnText.screenCenter(Y); add(warnText); } diff --git a/source/states/LoadingState.hx b/source/states/LoadingState.hx index 371e860d36a..21d906d0e27 100644 --- a/source/states/LoadingState.hx +++ b/source/states/LoadingState.hx @@ -6,8 +6,11 @@ import openfl.display.BitmapData; import openfl.utils.AssetType; import openfl.utils.Assets as OpenFlAssets; import flixel.graphics.FlxGraphic; +import flixel.system.FlxAssets; import flixel.FlxState; +import flash.media.Sound; + import backend.Song; import backend.StageData; import objects.Character; @@ -25,7 +28,7 @@ class LoadingState extends MusicBeatState static var originalBitmapKeys:Map = []; static var requestedBitmaps:Map = []; - static var mutex:Mutex = new Mutex(); + static var mutex:Mutex; function new(target:FlxState, stopMusic:Bool) { @@ -194,21 +197,23 @@ class LoadingState extends MusicBeatState FlxG.sound.play(Paths.sound('secret')); pessy = new FlxSprite(700, 140); + pessy.frames = Paths.getSparrowAtlas('loading_screen/pessy'); + pessy.animation.addByPrefix('run', 'run', 24, true); + pessy.animation.addByPrefix('spin', 'spin', 24, true); + pessy.antialiasing = ClientPrefs.data.antialiasing; + pessy.flipX = (logo.offset.x > 0); + pessy.x = FlxG.width + 200; + pessy.velocity.x = -1100; + new FlxTimer().start(0.01, function(tmr:FlxTimer) { - pessy.frames = Paths.getSparrowAtlas('loading_screen/pessy'); - pessy.antialiasing = ClientPrefs.data.antialiasing; - pessy.flipX = (logo.offset.x > 0); - pessy.x = FlxG.width + 200; - pessy.velocity.x = -1100; if(pessy.flipX) { pessy.x = -pessy.width - 200; - pessy.velocity.x = 1100; + pessy.velocity.x *= -1; } - pessy.animation.addByPrefix('run', 'run', 24, true); - pessy.animation.addByPrefix('spin', 'spin', 24, true); pessy.animation.play('run', true); + Achievements.unlock('pessy_easter_egg'); insert(members.indexOf(loadingText), pessy); new FlxTimer().start(5, function(tmr:FlxTimer) canChangeState = true); @@ -239,6 +244,7 @@ class LoadingState extends MusicBeatState MusicBeatState.switchState(target); transitioning = true; finishedLoading = true; + mutex = null; } public static function checkLoaded():Bool @@ -335,7 +341,7 @@ class LoadingState extends MusicBeatState var noteSplash:String = NoteSplash.DEFAULT_SKIN; if(PlayState.SONG.splashSkin != null && PlayState.SONG.splashSkin.length > 0) noteSplash = PlayState.SONG.splashSkin; else noteSplash += NoteSplash.getSplashSkinPostfix(); - imagesToPrepare.push("noteSplashes/" + noteSplash); + imagesToPrepare.push(noteSplash); try { @@ -382,24 +388,37 @@ class LoadingState extends MusicBeatState song.stage = StageData.vanillaSongStage(folder); var stageData:StageFile = StageData.getStageFile(song.stage); - if (stageData != null && stageData.preload != null) + if (stageData != null) { var imgs:Array = []; var snds:Array = []; var mscs:Array = []; - for (asset in Reflect.fields(stageData.preload)) + if(stageData.preload != null) { - var filters:Int = Reflect.field(stageData.preload, asset); - var asset:String = asset.trim(); + for (asset in Reflect.fields(stageData.preload)) + { + var filters:Int = Reflect.field(stageData.preload, asset); + var asset:String = asset.trim(); - if(filters < 0 || StageData.validateVisibility(filters)) + if(filters < 0 || StageData.validateVisibility(filters)) + { + if(asset.startsWith('images/')) + imgs.push(asset.substr('images/'.length)); + else if(asset.startsWith('sounds/')) + snds.push(asset.substr('sounds/'.length)); + else if(asset.startsWith('music/')) + mscs.push(asset.substr('music/'.length)); + } + } + } + + if (stageData.objects != null) + { + for (sprite in stageData.objects) { - if(asset.startsWith('images/')) - imgs.push(asset.substr('images/'.length)); - else if(asset.startsWith('sounds/')) - snds.push(asset.substr('sounds/'.length)); - else if(asset.startsWith('music/')) - mscs.push(asset.substr('music/'.length)); + if(sprite.type == 'sprite' || sprite.type == 'animatedSprite') + if((sprite.filters < 0 || StageData.validateVisibility(sprite.filters)) && !imgs.contains(sprite.image)) + imgs.push(sprite.image); } } prepare(imgs, snds, mscs); @@ -460,15 +479,22 @@ class LoadingState extends MusicBeatState static function clearInvalidFrom(arr:Array, prefix:String, ext:String, type:AssetType, ?parentFolder:String = null) { - for (i in 0...arr.length) + for (folder in arr.copy()) { - var folder:String = arr[i]; - if(folder.trim().endsWith('/')) + var nam:String = folder.trim(); + if(nam.endsWith('/')) { - for (subfolder in Mods.directoriesWithFile(Paths.getSharedPath(), '$prefix/$folder')) + for (subfolder in Mods.directoriesWithFile(Paths.getSharedPath(), '$prefix/$nam')) + { for (file in FileSystem.readDirectory(subfolder)) + { if(file.endsWith(ext)) - arr.push(folder + file.substr(0, file.length - ext.length)); + { + var toAdd:String = nam + haxe.io.Path.withoutExtension(file); + if(!arr.contains(toAdd)) arr.push(toAdd); + } + } + } //trace('Folder detected! ' + folder); } @@ -495,53 +521,22 @@ class LoadingState extends MusicBeatState public static function startThreads() { + mutex = new Mutex(); loadMax = imagesToPrepare.length + soundsToPrepare.length + musicToPrepare.length + songsToPrepare.length; loaded = 0; //then start threads - for (sound in soundsToPrepare) initThread(() -> Paths.sound(sound), 'sound $sound'); - for (music in musicToPrepare) initThread(() -> Paths.music(music), 'music $music'); - for (song in songsToPrepare) initThread(() -> Paths.returnSound(song, 'songs', true, false), 'song $song'); + for (sound in soundsToPrepare) initThread(() -> preloadSound('sounds/$sound'), 'sound $sound'); + for (music in musicToPrepare) initThread(() -> preloadSound('music/$music'), 'music $music'); + for (song in songsToPrepare) initThread(() -> preloadSound(song, 'songs', true, false), 'song $song'); // for images, they get to have their own thread - for (image in imagesToPrepare) - Thread.create(() -> { - mutex.acquire(); - try { - var requestKey:String = 'images/$image'; - #if TRANSLATIONS_ALLOWED requestKey = Language.getFileTranslation(requestKey); #end - if(requestKey.lastIndexOf('.') < 0) requestKey += '.png'; - - if (!Paths.currentTrackedAssets.exists(requestKey)) - { - var bitmap:BitmapData = null; - var file:String = Paths.getPath(requestKey, IMAGE); - if (#if sys FileSystem.exists(file) || #end OpenFlAssets.exists(file, IMAGE)) - { - #if sys - bitmap = BitmapData.fromFile(file); - #else - bitmap = OpenFlAssets.getBitmapData(file); - #end - requestedBitmaps.set(file, bitmap); - originalBitmapKeys.set(file, requestKey); - } - else trace('no such image $image exists'); - } - } - catch(e:haxe.Exception) - { - trace('ERROR! fail on preloading image $image'); - } - mutex.release(); - loaded++; - }); + for (image in imagesToPrepare) initThread(() -> preloadGraphic(image), 'image $image'); } static function initThread(func:Void->Dynamic, traceData:String) { Thread.create(() -> { - mutex.acquire(); try { if (func() != null) trace('finished preloading $traceData'); else trace('ERROR! fail on preloading $traceData'); @@ -549,8 +544,9 @@ class LoadingState extends MusicBeatState catch(e:Dynamic) { trace('ERROR! fail on preloading $traceData'); } - mutex.release(); + mutex.acquire(); loaded++; + mutex.release(); }); } @@ -611,4 +607,70 @@ class LoadingState extends MusicBeatState trace(e.details()); } } + + // thread safe sound loader + static function preloadSound(key:String, ?path:String, ?modsAllowed:Bool = true, ?beepOnNull:Bool = true):Null + { + var file:String = Paths.getPath(Language.getFileTranslation(key) + '.${Paths.SOUND_EXT}', SOUND, path, modsAllowed); + + //trace('precaching sound: $file'); + if(!Paths.currentTrackedSounds.exists(file)) + { + if (#if sys FileSystem.exists(file) || #end OpenFlAssets.exists(file, SOUND)) + { + var sound:Sound = OpenFlAssets.getSound(file, false); + mutex.acquire(); + Paths.currentTrackedSounds.set(file, sound); + mutex.release(); + } + else if (beepOnNull) + { + trace('SOUND NOT FOUND: $key, PATH: $path'); + FlxG.log.error('SOUND NOT FOUND: $key, PATH: $path'); + return FlxAssets.getSound('flixel/sounds/beep'); + } + } + mutex.acquire(); + Paths.localTrackedAssets.push(file); + mutex.release(); + + return Paths.currentTrackedSounds.get(file); + } + + // thread safe sound loader + static function preloadGraphic(key:String):Null + { + try { + var requestKey:String = 'images/$key'; + #if TRANSLATIONS_ALLOWED requestKey = Language.getFileTranslation(requestKey); #end + if(requestKey.lastIndexOf('.') < 0) requestKey += '.png'; + + if (!Paths.currentTrackedAssets.exists(requestKey)) + { + var file:String = Paths.getPath(requestKey, IMAGE); + if (#if sys FileSystem.exists(file) || #end OpenFlAssets.exists(file, IMAGE)) + { + #if sys + var bitmap:BitmapData = BitmapData.fromFile(file); + #else + var bitmap:BitmapData = OpenFlAssets.getBitmapData(file, false); + #end + mutex.acquire(); + requestedBitmaps.set(file, bitmap); + originalBitmapKeys.set(file, requestKey); + mutex.release(); + return bitmap; + } + else trace('no such image $key exists'); + } + + return Paths.currentTrackedAssets.get(requestKey).bitmap; + } + catch(e:haxe.Exception) + { + trace('ERROR! fail on preloading image $key'); + } + + return null; + } } \ No newline at end of file diff --git a/source/states/MainMenuState.hx b/source/states/MainMenuState.hx index 2db463e0d3a..93e53b0977e 100644 --- a/source/states/MainMenuState.hx +++ b/source/states/MainMenuState.hx @@ -14,7 +14,7 @@ enum MainMenuColumn { class MainMenuState extends MusicBeatState { - public static var psychEngineVersion:String = '1.0b'; // This is also used for Discord RPC + public static var psychEngineVersion:String = '1.0-prerelease'; // This is also used for Discord RPC public static var curSelected:Int = 0; public static var curColumn:MainMenuColumn = CENTER; var allowMouse:Bool = true; //Turn this off to block mouse movement in menus @@ -93,11 +93,11 @@ class MainMenuState extends MusicBeatState var psychVer:FlxText = new FlxText(12, FlxG.height - 44, 0, "Psych Engine v" + psychEngineVersion, 12); psychVer.scrollFactor.set(); - psychVer.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + psychVer.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); add(psychVer); var fnfVer:FlxText = new FlxText(12, FlxG.height - 24, 0, "Friday Night Funkin' v" + Application.current.meta.get('version'), 12); fnfVer.scrollFactor.set(); - fnfVer.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + fnfVer.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); add(fnfVer); changeItem(); diff --git a/source/states/ModsMenuState.hx b/source/states/ModsMenuState.hx index 47be4c0e61a..b2d2162bb30 100644 --- a/source/states/ModsMenuState.hx +++ b/source/states/ModsMenuState.hx @@ -818,11 +818,10 @@ class ModItem extends FlxSpriteGroup var path:String = Paths.mods('$folder/data/settings.json'); if(FileSystem.exists(path)) { - var data:String = File.getContent(path); try { //trace('trying to load settings: $folder'); - settings = tjson.TJSON.parse(data); + settings = tjson.TJSON.parse(File.getContent(path)); } catch(e:Dynamic) { diff --git a/source/states/OutdatedState.hx b/source/states/OutdatedState.hx index a590cd3a0f8..5d3cb319e5e 100644 --- a/source/states/OutdatedState.hx +++ b/source/states/OutdatedState.hx @@ -20,7 +20,7 @@ class OutdatedState extends MusicBeatState \n Thank you for using the Engine!", 32); - warnText.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, CENTER); + warnText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, CENTER); warnText.screenCenter(Y); add(warnText); } diff --git a/source/states/PlayState.hx b/source/states/PlayState.hx index 4fdf0945731..67c1b1d0bd0 100644 --- a/source/states/PlayState.hx +++ b/source/states/PlayState.hx @@ -48,8 +48,8 @@ import psychlua.LuaUtils; import psychlua.HScript; #end -#if SScript -import tea.SScript; +#if HSCRIPT_ALLOWED +import crowplexus.iris.Iris; #end /** @@ -95,7 +95,6 @@ class PlayState extends MusicBeatState #if HSCRIPT_ALLOWED public var hscriptArray:Array = []; - public var instancesExclude:Array = []; #end public var BF_X:Float = 770; @@ -146,10 +145,10 @@ class PlayState extends MusicBeatState public var camFollow:FlxObject; private static var prevCamFollow:FlxObject; - public var strumLineNotes:FlxTypedGroup; - public var opponentStrums:FlxTypedGroup; - public var playerStrums:FlxTypedGroup; - public var grpNoteSplashes:FlxTypedGroup; + public var strumLineNotes:FlxTypedGroup = new FlxTypedGroup(); + public var opponentStrums:FlxTypedGroup = new FlxTypedGroup(); + public var playerStrums:FlxTypedGroup = new FlxTypedGroup(); + public var grpNoteSplashes:FlxTypedGroup = new FlxTypedGroup(); public var camZooming:Bool = false; public var camZoomingMult:Float = 1; @@ -248,10 +247,17 @@ class PlayState extends MusicBeatState public var startCallback:Void->Void = null; public var endCallback:Void->Void = null; + public static var nextReloadAll:Bool = false; override public function create() { //trace('Playback Rate: ' + playbackRate); Paths.clearStoredMemory(); + if(nextReloadAll) + { + Paths.clearUnusedMemory(); + Language.reloadPhrases(); + } + nextReloadAll = false; startCallback = startCountdown; endCallback = endSong; @@ -289,7 +295,6 @@ class PlayState extends MusicBeatState FlxG.cameras.add(camHUD, false); FlxG.cameras.add(camOther, false); - grpNoteSplashes = new FlxTypedGroup(); persistentUpdate = true; persistentDraw = true; @@ -420,6 +425,7 @@ class PlayState extends MusicBeatState initHScript(folder + file); #end } + #end var camPos:FlxPoint = FlxPoint.get(girlfriendCameraOffset[0], girlfriendCameraOffset[1]); if(gf != null) @@ -434,7 +440,7 @@ class PlayState extends MusicBeatState gf.visible = false; } - + #if (LUA_ALLOWED || HSCRIPT_ALLOWED) // STAGE SCRIPTS #if LUA_ALLOWED startLuasNamed('stages/' + curStage + '.lua'); #end #if HSCRIPT_ALLOWED startHScriptsNamed('stages/' + curStage + '.hx'); #end @@ -471,7 +477,6 @@ class PlayState extends MusicBeatState uiGroup.add(timeBar); uiGroup.add(timeTxt); - strumLineNotes = new FlxTypedGroup(); noteGroup.add(strumLineNotes); if(ClientPrefs.data.timeBarType == 'Song Name') @@ -480,9 +485,6 @@ class PlayState extends MusicBeatState timeTxt.y += 3; } - opponentStrums = new FlxTypedGroup(); - playerStrums = new FlxTypedGroup(); - generateSong(); noteGroup.add(grpNoteSplashes); @@ -534,14 +536,14 @@ class PlayState extends MusicBeatState updateScore(false); uiGroup.add(scoreTxt); - botplayTxt = new FlxText(400, timeBar.y + 55, FlxG.width - 800, Language.getPhrase("Botplay").toUpperCase(), 32); + botplayTxt = new FlxText(400, healthBar.y - 90, FlxG.width - 800, Language.getPhrase("Botplay").toUpperCase(), 32); botplayTxt.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); botplayTxt.scrollFactor.set(); botplayTxt.borderSize = 1.25; botplayTxt.visible = cpuControlled; uiGroup.add(botplayTxt); if(ClientPrefs.data.downScroll) - botplayTxt.y = timeBar.y - 78; + botplayTxt.y = healthBar.y + 70; uiGroup.cameras = [camHUD]; noteGroup.cameras = [camHUD]; @@ -781,7 +783,7 @@ class PlayState extends MusicBeatState if(doPush) { - if(SScript.global.exists(scriptFile)) + if(Iris.instances.exists(scriptFile)) doPush = false; if(doPush) initHScript(scriptFile); @@ -1323,7 +1325,7 @@ class PlayState extends MusicBeatState if (i != 0) { // CLEAR ANY POSSIBLE GHOST NOTES for (evilNote in unspawnNotes) { - var matches: Bool = noteColumn == evilNote.noteData && gottaHitNote == evilNote.mustPress; + var matches: Bool = (noteColumn == evilNote.noteData && gottaHitNote == evilNote.mustPress && evilNote.noteType == noteType); if (matches && Math.abs(spawnTime - evilNote.strumTime) == 0.0) { evilNote.destroy(); unspawnNotes.remove(evilNote); @@ -1334,8 +1336,8 @@ class PlayState extends MusicBeatState } var swagNote:Note = new Note(spawnTime, noteColumn, oldNote); - var isAlt: Bool = section.altAnim && !swagNote.mustPress && !section.gfSection; - swagNote.gfNote = (section.gfSection && gottaHitNote); + var isAlt: Bool = section.altAnim && !gottaHitNote; + swagNote.gfNote = (section.gfSection && gottaHitNote == section.mustHitSection); swagNote.animSuffix = isAlt ? "-alt" : ""; swagNote.mustPress = gottaHitNote; swagNote.sustainLength = holdLength; @@ -1344,7 +1346,7 @@ class PlayState extends MusicBeatState swagNote.scrollFactor.set(); unspawnNotes.push(swagNote); - final roundSus:Int = Math.round(swagNote.sustainLength / Conductor.stepCrochet); + final roundSus:Int = Math.floor(swagNote.sustainLength / Conductor.stepCrochet); if(roundSus > 0) { for (susNote in 0...roundSus + 1) @@ -1454,8 +1456,9 @@ class PlayState extends MusicBeatState } function eventEarlyTrigger(event:EventNote):Float { - var returnedValue:Null = callOnScripts('eventEarlyTrigger', [event.event, event.value1, event.value2, event.strumTime], true, [], [0]); - if(returnedValue != null && returnedValue != 0 && returnedValue != LuaUtils.Function_Continue) { + var returnedValue:Dynamic = callOnScripts('eventEarlyTrigger', [event.event, event.value1, event.value2, event.strumTime], true, [], [0]); + returnedValue = Std.parseFloat(returnedValue); + if(!Math.isNaN(returnedValue) && returnedValue != 0) { return returnedValue; } @@ -1677,8 +1680,8 @@ class PlayState extends MusicBeatState Conductor.songPosition += elapsed * 1000 * playbackRate; if (Conductor.songPosition >= Conductor.offset) { + Conductor.songPosition = FlxMath.lerp(FlxG.sound.music.time + Conductor.offset, Conductor.songPosition, Math.exp(-elapsed * 5)); var timeDiff:Float = Math.abs((FlxG.sound.music.time + Conductor.offset) - Conductor.songPosition); - Conductor.songPosition = FlxMath.lerp(FlxG.sound.music.time + Conductor.offset, Conductor.songPosition, Math.exp(-elapsed * 2.5)); if (timeDiff > 1000 * playbackRate) Conductor.songPosition = Conductor.songPosition + 1000 * FlxMath.signOf(timeDiff); } @@ -1813,8 +1816,6 @@ class PlayState extends MusicBeatState } #end - setOnScripts('cameraX', camFollow.x); - setOnScripts('cameraY', camFollow.y); setOnScripts('botPlay', cpuControlled); callOnScripts('onUpdatePost', [elapsed]); } @@ -2247,7 +2248,6 @@ class PlayState extends MusicBeatState callOnScripts('onEvent', [eventName, value1, value2, strumTime]); } - var lastCharFocus:String; public function moveCameraSection(?sec:Null):Void { if(sec == null) sec = curSection; if(sec < 0) sec = 0; @@ -2260,22 +2260,16 @@ class PlayState extends MusicBeatState camFollow.x += gf.cameraPosition[0] + girlfriendCameraOffset[0]; camFollow.y += gf.cameraPosition[1] + girlfriendCameraOffset[1]; tweenCamIn(); - if (lastCharFocus != 'gf') { - callOnScripts('onMoveCamera', ['gf']); - lastCharFocus = 'gf'; - } + callOnScripts('onMoveCamera', ['gf']); return; } var isDad:Bool = (SONG.notes[sec].mustHitSection != true); moveCamera(isDad); - if (isDad) { - if (lastCharFocus != 'dad') callOnScripts('onMoveCamera', ['dad']); - } - else if (lastCharFocus != 'boyfriend') { + if (isDad) + callOnScripts('onMoveCamera', ['dad']); + else callOnScripts('onMoveCamera', ['boyfriend']); - } - lastCharFocus = isDad ? 'dad' : 'boyfriend'; } var cameraTwn:FlxTween; @@ -2283,6 +2277,7 @@ class PlayState extends MusicBeatState { if(isDad) { + if(dad == null) return; camFollow.setPosition(dad.getMidpoint().x + 150, dad.getMidpoint().y - 100); camFollow.x += dad.cameraPosition[0] + opponentCameraOffset[0]; camFollow.y += dad.cameraPosition[1] + opponentCameraOffset[1]; @@ -2290,6 +2285,7 @@ class PlayState extends MusicBeatState } else { + if(boyfriend == null) return; camFollow.setPosition(boyfriend.getMidpoint().x - 100, boyfriend.getMidpoint().y - 100); camFollow.x -= boyfriend.cameraPosition[0] - boyfriendCameraOffset[0]; camFollow.y += boyfriend.cameraPosition[1] + boyfriendCameraOffset[1]; @@ -2668,13 +2664,11 @@ class PlayState extends MusicBeatState // obtain notes that the player can hit var plrInputNotes:Array = notes.members.filter(function(n:Note):Bool { - var canHit:Bool = !strumsBlocked[n.noteData] && n.canBeHit && n.mustPress && !n.tooLate && !n.wasGoodHit && !n.blockHit; - return n != null && canHit && !n.isSustainNote && n.noteData == key; + var canHit:Bool = n != null && !strumsBlocked[n.noteData] && n.canBeHit && n.mustPress && !n.tooLate && !n.wasGoodHit && !n.blockHit; + return canHit && !n.isSustainNote && n.noteData == key; }); plrInputNotes.sort(sortHitNotes); - var shouldMiss:Bool = !ClientPrefs.data.ghostTapping; - if (plrInputNotes.length != 0) { // slightly faster than doing `> 0` lol var funnyNote:Note = plrInputNotes[0]; // front note @@ -2694,10 +2688,12 @@ class PlayState extends MusicBeatState } goodNoteHit(funnyNote); } - else if(shouldMiss) + else { - callOnScripts('onGhostTap', [key]); - noteMissPress(key); + if (ClientPrefs.data.ghostTapping) + callOnScripts('onGhostTap', [key]); + else + noteMissPress(key); } // Needed for the "Just the Two of Us" achievement. @@ -3107,7 +3103,7 @@ class PlayState extends MusicBeatState for (script in hscriptArray) if(script != null) { - script.call('onDestroy'); + script.executeFunction('onDestroy'); script.destroy(); } @@ -3256,7 +3252,7 @@ class PlayState extends MusicBeatState if(FileSystem.exists(scriptToLoad)) { - if (SScript.global.exists(scriptToLoad)) return false; + if (Iris.instances.exists(scriptToLoad)) return false; initHScript(scriptToLoad); return true; @@ -3266,57 +3262,26 @@ class PlayState extends MusicBeatState public function initHScript(file:String) { + var newScript:HScript = null; try { - var newScript:HScript = new HScript(null, file); - if(newScript.parsingException != null) - { - addTextToDebug('ERROR ON LOADING: ${newScript.parsingException.message}', FlxColor.RED); - newScript.destroy(); - return; - } - + newScript = new HScript(null, file); + newScript.executeFunction('onCreate'); + trace('initialized hscript interp successfully: $file'); hscriptArray.push(newScript); - if(newScript.exists('onCreate')) - { - var callValue = newScript.call('onCreate'); - if(!callValue.succeeded) - { - for (e in callValue.exceptions) - { - if (e != null) - { - var len:Int = e.message.indexOf('\n') + 1; - if(len <= 0) len = e.message.length; - addTextToDebug('ERROR ($file: onCreate) - ${e.message.substr(0, len)}', FlxColor.RED); - } - } - - newScript.destroy(); - hscriptArray.remove(newScript); - trace('failed to initialize tea interp!!! ($file)'); - } - else trace('initialized tea interp successfully: $file'); - } - } - catch(e) + catch(e:Dynamic) { - var len:Int = e.message.indexOf('\n') + 1; - if(len <= 0) len = e.message.length; - addTextToDebug('ERROR - ' + e.message.substr(0, len), FlxColor.RED); - var newScript:HScript = cast (SScript.global.get(file), HScript); + addTextToDebug('ERROR ON LOADING ($file) - $e', FlxColor.RED); + var newScript:HScript = cast (Iris.instances.get(file), HScript); if(newScript != null) - { newScript.destroy(); - hscriptArray.remove(newScript); - } } } #end public function callOnScripts(funcToCall:String, args:Array = null, ignoreStops = false, exclusions:Array = null, excludeValues:Array = null):Dynamic { - var returnVal:Dynamic = LuaUtils.Function_Continue; + var returnVal:String = LuaUtils.Function_Continue; if(args == null) args = []; if(exclusions == null) exclusions = []; if(excludeValues == null) excludeValues = [LuaUtils.Function_Continue]; @@ -3327,7 +3292,7 @@ class PlayState extends MusicBeatState } public function callOnLuas(funcToCall:String, args:Array = null, ignoreStops = false, exclusions:Array = null, excludeValues:Array = null):Dynamic { - var returnVal:Dynamic = LuaUtils.Function_Continue; + var returnVal:String = LuaUtils.Function_Continue; #if LUA_ALLOWED if(args == null) args = []; if(exclusions == null) exclusions = []; @@ -3366,7 +3331,7 @@ class PlayState extends MusicBeatState } public function callOnHScript(funcToCall:String, args:Array = null, ?ignoreStops:Bool = false, exclusions:Array = null, excludeValues:Array = null):Dynamic { - var returnVal:Dynamic = LuaUtils.Function_Continue; + var returnVal:String = LuaUtils.Function_Continue; #if HSCRIPT_ALLOWED if(exclusions == null) exclusions = new Array(); @@ -3376,42 +3341,31 @@ class PlayState extends MusicBeatState var len:Int = hscriptArray.length; if (len < 1) return returnVal; - for(i in 0...len) { - var script:HScript = hscriptArray[i]; + + for(script in hscriptArray) + { + @:privateAccess if(script == null || !script.exists(funcToCall) || exclusions.contains(script.origin)) continue; - var myValue:Dynamic = null; - try { + try + { var callValue = script.call(funcToCall, args); - if(!callValue.succeeded) + var myValue:Dynamic = callValue.signature; + + if((myValue == LuaUtils.Function_StopHScript || myValue == LuaUtils.Function_StopAll) && !excludeValues.contains(myValue) && !ignoreStops) { - var e = callValue.exceptions[0]; - if(e != null) - { - var len:Int = e.message.indexOf('\n') + 1; - if(len <= 0) len = e.message.length; - addTextToDebug('ERROR (${callValue.calledFunction}) - ' + e.message.substr(0, len), FlxColor.RED); - } + returnVal = myValue; + break; } - else - { - myValue = callValue.returnValue; - - // compiler fuckup fix - final stopHscript = myValue == LuaUtils.Function_StopHScript; - final stopAll = myValue == LuaUtils.Function_StopAll; - if((stopHscript || stopAll) && !excludeValues.contains(myValue) && !ignoreStops) - { - returnVal = myValue; - break; - } - if(myValue != null && !excludeValues.contains(myValue)) - returnVal = myValue; - } + if(myValue != null && !excludeValues.contains(myValue)) + returnVal = myValue; + } + catch(e:Dynamic) + { + addTextToDebug('ERROR (${script.origin}: $funcToCall) - $e', FlxColor.RED); } - catch (e:Dynamic) {} } #end @@ -3443,8 +3397,6 @@ class PlayState extends MusicBeatState if(exclusions.contains(script.origin)) continue; - if(!instancesExclude.contains(variable)) - instancesExclude.push(variable); script.set(variable, arg); } #end @@ -3495,10 +3447,12 @@ class PlayState extends MusicBeatState } fullComboFunction(); } - updateScore(badHit); // score will only update after rating is calculated, if it's a badHit, it shouldn't bounce setOnScripts('rating', ratingPercent); setOnScripts('ratingName', ratingName); setOnScripts('ratingFC', ratingFC); + setOnScripts('totalPlayed', totalPlayed); + setOnScripts('totalNotesHit', totalNotesHit); + updateScore(badHit); // score will only update after rating is calculated, if it's a badHit, it shouldn't bounce } #if ACHIEVEMENTS_ALLOWED diff --git a/source/states/StoryMenuState.hx b/source/states/StoryMenuState.hx index 001a684d96f..3db06eafd61 100644 --- a/source/states/StoryMenuState.hx +++ b/source/states/StoryMenuState.hx @@ -48,6 +48,7 @@ class StoryMenuState extends MusicBeatState Paths.clearStoredMemory(); Paths.clearUnusedMemory(); + persistentUpdate = persistentDraw = true; PlayState.isStoryMode = true; WeekData.reloadWeekFiles(true); @@ -67,13 +68,12 @@ class StoryMenuState extends MusicBeatState } if(curWeek >= WeekData.weeksList.length) curWeek = 0; - persistentUpdate = persistentDraw = true; scoreText = new FlxText(10, 10, 0, Language.getPhrase('week_score', 'WEEK SCORE: {1}', [lerpScore]), 36); - scoreText.setFormat("VCR OSD Mono", 32); + scoreText.setFormat(Paths.font("vcr.ttf"), 32); txtWeekTitle = new FlxText(FlxG.width * 0.7, 10, 0, "", 32); - txtWeekTitle.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, RIGHT); + txtWeekTitle.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, RIGHT); txtWeekTitle.alpha = 0.7; var ui_tex = Paths.getSparrowAtlas('campaign_menu_UI_assets'); @@ -208,7 +208,7 @@ class StoryMenuState extends MusicBeatState return; } - // scoreText.setFormat('VCR OSD Mono', 32); + // scoreText.setFormat(Paths.font("vcr.ttf"), 32); if(intendedScore != lerpScore) { lerpScore = Math.floor(FlxMath.lerp(intendedScore, lerpScore, Math.exp(-elapsed * 30))); diff --git a/source/states/TitleState.hx b/source/states/TitleState.hx index a2d7690c236..d951751327d 100644 --- a/source/states/TitleState.hx +++ b/source/states/TitleState.hx @@ -21,14 +21,19 @@ import states.MainMenuState; typedef TitleData = { - titlex:Float, - titley:Float, - startx:Float, - starty:Float, - gfx:Float, - gfy:Float, - backgroundSprite:String, - bpm:Float + var titlex:Float; + var titley:Float; + var startx:Float; + var starty:Float; + var gfx:Float; + var gfy:Float; + var backgroundSprite:String; + var bpm:Float; + + @:optional var animation:String; + @:optional var dance_left:Array; + @:optional var dance_right:Array; + @:optional var idle:Bool; } class TitleState extends MusicBeatState @@ -39,10 +44,10 @@ class TitleState extends MusicBeatState public static var initialized:Bool = false; + var credGroup:FlxGroup = new FlxGroup(); + var textGroup:FlxGroup = new FlxGroup(); var blackScreen:FlxSprite; - var credGroup:FlxGroup; var credTextShit:Alphabet; - var textGroup:FlxGroup; var ngSpr:FlxSprite; var titleTextColors:Array = [0xFF33FFFF, 0xFF3333CC]; @@ -53,27 +58,29 @@ class TitleState extends MusicBeatState var wackyImage:FlxSprite; #if TITLE_SCREEN_EASTER_EGG - var easterEggKeys:Array = [ - 'SHADOW', 'RIVEREN', 'BBPANZU' + final easterEggKeys:Array = [ + 'SHADOW', 'RIVEREN', 'BBPANZU', 'PESSY' ]; - var allowedKeys:String = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + final allowedKeys:String = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; var easterEggKeysBuffer:String = ''; #end var mustUpdate:Bool = false; - var titleJSON:TitleData; - public static var updateVersion:String = ''; override public function create():Void { Paths.clearStoredMemory(); - ClientPrefs.loadPrefs(); - Language.reloadPhrases(); - super.create(); - + Paths.clearUnusedMemory(); + + if(!initialized) + { + ClientPrefs.loadPrefs(); + Language.reloadPhrases(); + } + curWacky = FlxG.random.getObject(getIntroTextShit()); #if CHECK_FOR_UPDATES @@ -100,26 +107,6 @@ class TitleState extends MusicBeatState } #end - - // IGNORE THIS!!! - titleJSON = tjson.TJSON.parse(Paths.getTextFromFile('images/gfDanceTitle.json')); - - #if TITLE_SCREEN_EASTER_EGG - if (FlxG.save.data.psychDevsEasterEgg == null) FlxG.save.data.psychDevsEasterEgg = ''; //Crash prevention - switch(FlxG.save.data.psychDevsEasterEgg.toUpperCase()) - { - case 'SHADOW': - titleJSON.gfx += 210; - titleJSON.gfy += 40; - case 'RIVEREN': - titleJSON.gfx += 180; - titleJSON.gfy += 40; - case 'BBPANZU': - titleJSON.gfx += 45; - titleJSON.gfy += 100; - } - #end - if(!initialized) { if(FlxG.save.data != null && FlxG.save.data.fullscreen) @@ -142,20 +129,15 @@ class TitleState extends MusicBeatState #elseif CHARTING MusicBeatState.switchState(new ChartingState()); #else - if(FlxG.save.data.flashing == null && !FlashingState.leftState) { + if(FlxG.save.data.flashing == null && !FlashingState.leftState) + { FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; MusicBeatState.switchState(new FlashingState()); - } else { - if (initialized) - startIntro(); - else - { - new FlxTimer().start(1, function(tmr:FlxTimer) - { - startIntro(); - }); - } + } + else + { + startIntro(); } #end } @@ -168,142 +150,187 @@ class TitleState extends MusicBeatState function startIntro() { + persistentUpdate = true; if (!initialized && FlxG.sound.music == null) FlxG.sound.playMusic(Paths.music('freakyMenu'), 0); - Conductor.bpm = titleJSON.bpm; - persistentUpdate = true; - - var bg:FlxSprite = new FlxSprite(); - bg.antialiasing = ClientPrefs.data.antialiasing; - - if (titleJSON.backgroundSprite != null && titleJSON.backgroundSprite.length > 0 && titleJSON.backgroundSprite != "none"){ - bg.loadGraphic(Paths.image(titleJSON.backgroundSprite)); - }else{ - bg.makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); - } - - // bg.setGraphicSize(Std.int(bg.width * 0.6)); - // bg.updateHitbox(); - add(bg); + loadJsonData(); + #if TITLE_SCREEN_EASTER_EGG easterEggData(); #end + Conductor.bpm = musicBPM; - logoBl = new FlxSprite(titleJSON.titlex, titleJSON.titley); + logoBl = new FlxSprite(logoPosition.x, logoPosition.y); logoBl.frames = Paths.getSparrowAtlas('logoBumpin'); logoBl.antialiasing = ClientPrefs.data.antialiasing; logoBl.animation.addByPrefix('bump', 'logo bumpin', 24, false); logoBl.animation.play('bump'); logoBl.updateHitbox(); - // logoBl.screenCenter(); - // logoBl.color = FlxColor.BLACK; - if(ClientPrefs.data.shaders) swagShader = new ColorSwap(); - gfDance = new FlxSprite(titleJSON.gfx, titleJSON.gfy); + gfDance = new FlxSprite(gfPosition.x, gfPosition.y); gfDance.antialiasing = ClientPrefs.data.antialiasing; - - var easterEgg:String = FlxG.save.data.psychDevsEasterEgg; - if(easterEgg == null) easterEgg = ''; //html5 fix - - switch(easterEgg.toUpperCase()) - { - // IGNORE THESE, GO DOWN A BIT - #if TITLE_SCREEN_EASTER_EGG - case 'SHADOW': - gfDance.frames = Paths.getSparrowAtlas('ShadowBump'); - gfDance.animation.addByPrefix('danceLeft', 'Shadow Title Bump', 24); - gfDance.animation.addByPrefix('danceRight', 'Shadow Title Bump', 24); - case 'RIVEREN': - gfDance.frames = Paths.getSparrowAtlas('RiverBump'); - gfDance.animation.addByIndices('danceLeft', 'River Title Bump', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false); - gfDance.animation.addByIndices('danceRight', 'River Title Bump', [29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false); - case 'BBPANZU': - gfDance.frames = Paths.getSparrowAtlas('BBBump'); - gfDance.animation.addByIndices('danceLeft', 'BB Title Bump', [14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27], "", 24, false); - gfDance.animation.addByIndices('danceRight', 'BB Title Bump', [27, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], "", 24, false); - #end - - default: - //EDIT THIS ONE IF YOU'RE MAKING A SOURCE CODE MOD!!!! - //EDIT THIS ONE IF YOU'RE MAKING A SOURCE CODE MOD!!!! - //EDIT THIS ONE IF YOU'RE MAKING A SOURCE CODE MOD!!!! - gfDance.frames = Paths.getSparrowAtlas('gfDanceTitle'); - gfDance.animation.addByIndices('danceLeft', 'gfDance', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false); - gfDance.animation.addByIndices('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false); - } - - add(gfDance); - add(logoBl); - if(swagShader != null) + + if(ClientPrefs.data.shaders) { + swagShader = new ColorSwap(); gfDance.shader = swagShader.shader; logoBl.shader = swagShader.shader; } + + gfDance.frames = Paths.getSparrowAtlas(characterImage); + if(!useIdle) + { + gfDance.animation.addByIndices('danceLeft', animationName, danceLeftFrames, "", 24, false); + gfDance.animation.addByIndices('danceRight', animationName, danceRightFrames, "", 24, false); + gfDance.animation.play('danceRight'); + } + else + { + gfDance.animation.addByPrefix('idle', animationName, 24, false); + gfDance.animation.play('idle'); + } + - titleText = new FlxSprite(titleJSON.startx, titleJSON.starty); - titleText.frames = Paths.getSparrowAtlas('titleEnter'); var animFrames:Array = []; - @:privateAccess { + titleText = new FlxSprite(enterPosition.x, enterPosition.y); + titleText.frames = Paths.getSparrowAtlas('titleEnter'); + @:privateAccess + { titleText.animation.findByPrefix(animFrames, "ENTER IDLE"); titleText.animation.findByPrefix(animFrames, "ENTER FREEZE"); } - if (animFrames.length > 0) { - newTitle = true; - + if (newTitle = animFrames.length > 0) + { titleText.animation.addByPrefix('idle', "ENTER IDLE", 24); titleText.animation.addByPrefix('press', ClientPrefs.data.flashing ? "ENTER PRESSED" : "ENTER FREEZE", 24); } - else { - newTitle = false; - + else + { titleText.animation.addByPrefix('idle', "Press Enter to Begin", 24); titleText.animation.addByPrefix('press', "ENTER PRESSED", 24); } - titleText.animation.play('idle'); titleText.updateHitbox(); - // titleText.screenCenter(X); - add(titleText); var logo:FlxSprite = new FlxSprite().loadGraphic(Paths.image('logo')); logo.antialiasing = ClientPrefs.data.antialiasing; logo.screenCenter(); - // add(logo); - - // FlxTween.tween(logoBl, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG}); - // FlxTween.tween(logo, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG, startDelay: 0.1}); - - credGroup = new FlxGroup(); - add(credGroup); - textGroup = new FlxGroup(); - blackScreen = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); + blackScreen = new FlxSprite().makeGraphic(1, 1, FlxColor.BLACK); + blackScreen.scale.set(FlxG.width, FlxG.height); + blackScreen.updateHitbox(); credGroup.add(blackScreen); credTextShit = new Alphabet(0, 0, "", true); credTextShit.screenCenter(); - - // credTextShit.alignment = CENTER; - credTextShit.visible = false; ngSpr = new FlxSprite(0, FlxG.height * 0.52).loadGraphic(Paths.image('newgrounds_logo')); - add(ngSpr); ngSpr.visible = false; ngSpr.setGraphicSize(Std.int(ngSpr.width * 0.8)); ngSpr.updateHitbox(); ngSpr.screenCenter(X); ngSpr.antialiasing = ClientPrefs.data.antialiasing; + add(gfDance); + add(logoBl); //FNF Logo + add(titleText); //"Press Enter to Begin" text + add(credGroup); + add(ngSpr); + if (initialized) skipIntro(); else initialized = true; - Paths.clearUnusedMemory(); // credGroup.add(credTextShit); } + // JSON data + var characterImage:String = 'gfDanceTitle'; + var animationName:String = 'gfDance'; + + var gfPosition:FlxPoint = FlxPoint.get(512, 40); + var logoPosition:FlxPoint = FlxPoint.get(-150, -100); + var enterPosition:FlxPoint = FlxPoint.get(100, 576); + + var useIdle:Bool = false; + var musicBPM:Float = 102; + var danceLeftFrames:Array = [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]; + var danceRightFrames:Array = [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; + + function loadJsonData() + { + if(Paths.fileExists('images/gfDanceTitle.json', TEXT)) + { + var titleRaw:String = Paths.getTextFromFile('images/gfDanceTitle.json'); + if(titleRaw != null && titleRaw.length > 0) + { + try + { + var titleJSON:TitleData = tjson.TJSON.parse(titleRaw); + gfPosition.set(titleJSON.gfx, titleJSON.gfy); + logoPosition.set(titleJSON.titlex, titleJSON.titley); + enterPosition.set(titleJSON.startx, titleJSON.starty); + musicBPM = titleJSON.bpm; + + if(titleJSON.animation != null && titleJSON.animation.length > 0) animationName = titleJSON.animation; + if(titleJSON.dance_left != null && titleJSON.dance_left.length > 0) danceLeftFrames = titleJSON.dance_left; + if(titleJSON.dance_right != null && titleJSON.dance_right.length > 0) danceRightFrames = titleJSON.dance_right; + useIdle = (titleJSON.idle == true); + + if (titleJSON.backgroundSprite != null && titleJSON.backgroundSprite.trim().length > 0) + { + var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image(titleJSON.backgroundSprite)); + bg.antialiasing = ClientPrefs.data.antialiasing; + add(bg); + } + } + catch(e:haxe.Exception) + { + trace('[WARN] Title JSON might broken, ignoring issue...\n${e.details()}'); + } + } + else trace('[WARN] No Title JSON detected, using default values.'); + } + //else trace('[WARN] No Title JSON detected, using default values.'); + } + + function easterEggData() + { + if (FlxG.save.data.psychDevsEasterEgg == null) FlxG.save.data.psychDevsEasterEgg = ''; //Crash prevention + var easterEgg:String = FlxG.save.data.psychDevsEasterEgg; + switch(easterEgg.toUpperCase()) + { + case 'SHADOW': + characterImage = 'ShadowBump'; + animationName = 'Shadow Title Bump'; + gfPosition.x += 210; + gfPosition.y += 40; + useIdle = true; + case 'RIVEREN': + characterImage = 'ZRiverBump'; + animationName = 'River Title Bump'; + gfPosition.x += 180; + gfPosition.y += 40; + useIdle = true; + case 'BBPANZU': + characterImage = 'BBBump'; + animationName = 'BB Title Bump'; + danceLeftFrames = [14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]; + danceRightFrames = [27, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; + gfPosition.x += 45; + gfPosition.y += 100; + case 'PESSY': + characterImage = 'PessyBump'; + animationName = 'Pessy Title Bump'; + gfPosition.x += 165; + gfPosition.y += 60; + danceLeftFrames = [29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; + danceRightFrames = [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]; + } + } + function getIntroTextShit():Array> { #if MODS_ALLOWED @@ -395,11 +422,11 @@ class TitleState extends MusicBeatState new FlxTimer().start(1, function(tmr:FlxTimer) { - if (mustUpdate) { + if (mustUpdate) MusicBeatState.switchState(new OutdatedState()); - } else { + else MusicBeatState.switchState(new MainMenuState()); - } + closedState = true; }); // FlxG.sound.play(Paths.music('titleShoot'), 0.7); @@ -428,7 +455,9 @@ class TitleState extends MusicBeatState FlxG.sound.play(Paths.sound('secret')); - var black:FlxSprite = new FlxSprite(0, 0).makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); + var black:FlxSprite = new FlxSprite(0, 0).makeGraphic(1, 1, FlxColor.BLACK); + black.scale.set(FlxG.width, FlxG.height); + black.updateHitbox(); black.alpha = 0; add(black); @@ -477,7 +506,8 @@ class TitleState extends MusicBeatState var money:Alphabet = new Alphabet(0, 0, textArray[i], true); money.screenCenter(X); money.y += (i * 60) + 200 + offset; - if(credGroup != null && textGroup != null) { + if(credGroup != null && textGroup != null) + { credGroup.add(money); textGroup.add(money); } @@ -513,15 +543,21 @@ class TitleState extends MusicBeatState if(logoBl != null) logoBl.animation.play('bump', true); - if(gfDance != null) { + if(gfDance != null) + { danceLeft = !danceLeft; - if (danceLeft) - gfDance.animation.play('danceRight'); - else - gfDance.animation.play('danceLeft'); + if(!useIdle) + { + if (danceLeft) + gfDance.animation.play('danceRight'); + else + gfDance.animation.play('danceLeft'); + } + else if(curBeat % 2 == 0) gfDance.animation.play('idle', true); } - if(!closedState) { + if(!closedState) + { sickBeats++; switch (sickBeats) { @@ -572,6 +608,7 @@ class TitleState extends MusicBeatState #if TITLE_SCREEN_EASTER_EGG if (playJingle) //Ignore deez { + playJingle = false; var easteregg:String = FlxG.save.data.psychDevsEasterEgg; if (easteregg == null) easteregg = ''; easteregg = easteregg.toUpperCase(); @@ -585,13 +622,14 @@ class TitleState extends MusicBeatState FlxG.sound.play(Paths.sound('JingleShadow')); case 'BBPANZU': sound = FlxG.sound.play(Paths.sound('JingleBB')); + case 'PESSY': + sound = FlxG.sound.play(Paths.sound('JinglePessy')); default: //Go back to normal ugly ass boring GF remove(ngSpr); remove(credGroup); FlxG.camera.flash(FlxColor.WHITE, 2); skippedIntro = true; - playJingle = false; FlxG.sound.playMusic(Paths.music('freakyMenu'), 0); FlxG.sound.music.fadeIn(4, 0, 0.7); @@ -618,9 +656,10 @@ class TitleState extends MusicBeatState FlxG.sound.playMusic(Paths.music('freakyMenu'), 0); FlxG.sound.music.fadeIn(4, 0, 0.7); transitioning = false; + if(easteregg == 'PESSY') + Achievements.unlock('pessy_easter_egg'); }; } - playJingle = false; } else #end //Default! Edit this one!! { diff --git a/source/states/editors/CharacterEditorState.hx b/source/states/editors/CharacterEditorState.hx index febde87da42..4bba260b5f5 100644 --- a/source/states/editors/CharacterEditorState.hx +++ b/source/states/editors/CharacterEditorState.hx @@ -1,7 +1,6 @@ package states.editors; import flixel.graphics.FlxGraphic; -import flixel.graphics.frames.FlxAtlasFrames; import flixel.system.debug.interaction.tools.Pointer.GraphicCursorCross; import flixel.util.FlxDestroyUtil; @@ -68,7 +67,8 @@ class CharacterEditorState extends MusicBeatState implements PsychUIEventHandler override function create() { - if(ClientPrefs.data.cacheOnGPU) Paths.clearStoredMemory(); + Paths.clearStoredMemory(); + Paths.clearUnusedMemory(); FlxG.sound.music.stop(); camEditor = initPsychCamera(); @@ -815,22 +815,7 @@ class CharacterEditorState extends MusicBeatState implements PsychUIEventHandler } else { - var split:Array = character.imageFile.split(','); - var charFrames:FlxAtlasFrames = Paths.getAtlas(split[0].trim()); - - if(split.length > 1) - { - var original:FlxAtlasFrames = charFrames; - charFrames = new FlxAtlasFrames(charFrames.parent); - charFrames.addAtlas(original, true); - for (i in 1...split.length) - { - var extraFrames:FlxAtlasFrames = Paths.getAtlas(split[i].trim()); - if(extraFrames != null) - charFrames.addAtlas(extraFrames, true); - } - } - character.frames = charFrames; + character.frames = Paths.getMultiAtlas(character.imageFile.split(',')); } for (anim in anims) { @@ -1065,7 +1050,6 @@ class CharacterEditorState extends MusicBeatState implements PsychUIEventHandler } else if(FlxG.keys.justPressed.ESCAPE) { - FlxG.mouse.visible = false; if(!_goToPlayState) { if(!unsavedProgress) @@ -1075,7 +1059,11 @@ class CharacterEditorState extends MusicBeatState implements PsychUIEventHandler } else openSubState(new ExitConfirmationPrompt()); } - else MusicBeatState.switchState(new PlayState()); + else + { + FlxG.mouse.visible = false; + MusicBeatState.switchState(new PlayState()); + } return; } } diff --git a/source/states/editors/ChartingState.hx b/source/states/editors/ChartingState.hx index 68799f9a5a4..1646fed3356 100644 --- a/source/states/editors/ChartingState.hx +++ b/source/states/editors/ChartingState.hx @@ -1,6 +1,5 @@ package states.editors; -import flash.media.Sound; import flixel.FlxSubState; import flixel.util.FlxSave; import flixel.util.FlxSort; @@ -8,7 +7,16 @@ import flixel.util.FlxSpriteUtil; import flixel.util.FlxStringUtil; import flixel.util.FlxDestroyUtil; import flixel.input.keyboard.FlxKey; + import lime.utils.Assets; +import lime.media.AudioBuffer; + +import flash.media.Sound; +import flash.geom.Rectangle; + +import haxe.Json; +import haxe.Exception; +import haxe.io.Bytes; import states.editors.content.MetaNote; import states.editors.content.VSlice; @@ -24,8 +32,6 @@ import objects.Character; import objects.HealthIcon; import objects.Note; import objects.StrumNote; -import haxe.Json; -import haxe.Exception; using DateTools; @@ -49,6 +55,13 @@ enum abstract ChartingTheme(String) var DARK = 'dark'; } +enum abstract WaveformTarget(String) +{ + var INST = 'inst'; + var PLAYER = 'voc'; + var OPPONENT = 'opp'; +} + class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychUIEvent { public static final defaultEvents:Array> = @@ -72,7 +85,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU ['Play Sound', "Value 1: Sound file name\nValue 2: Volume (Default: 1), ranges from 0 to 1"] ]; - public static var keysArray:Array = [ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT]; //Used for Vortex Editor + public static var keysArray:Array = [ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT]; //Used for Vortex Editor public static var SHOW_EVENT_COLUMN = true; public static var GRID_COLUMNS_PER_PLAYER = 4; public static var GRID_PLAYERS = 2; @@ -131,6 +144,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var prevGridBg:ChartingGridSprite; var gridBg:ChartingGridSprite; var nextGridBg:ChartingGridSprite; + var waveformSprite:FlxSprite; var scrollY:Float = 0; var zoomList:Array = [ @@ -195,6 +209,10 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var tipBg:FlxSprite; var fullTipText:FlxText; + + var vortexEnabled:Bool = false; + var waveformEnabled:Bool = false; + var waveformTarget:WaveformTarget = INST; override function create() { @@ -231,7 +249,12 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU changeTheme(chartEditorSave.data.theme != null ? chartEditorSave.data.theme : DEFAULT, false); - recreateGrids(); + createGrids(); + + waveformSprite = new FlxSprite(gridBg.x + (SHOW_EVENT_COLUMN ? GRID_SIZE : 0), 0).makeGraphic(1, 1, 0x00FFFFFF); + waveformSprite.scrollFactor.x = 0; + waveformSprite.visible = false; + add(waveformSprite); dummyArrow = new FlxSprite().makeGraphic(1, 1, FlxColor.WHITE); dummyArrow.setGraphicSize(GRID_SIZE, GRID_SIZE); @@ -479,6 +502,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU "Shift + Click - Select/Unselect Note(s)", "Right Click - Selection Box", "", + "R - Reset Section", "Z/X - Zoom in/out", "Left/Right - Change Snap", #if FLX_PITCH @@ -571,11 +595,11 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU function prepareReload() { updateJsonData(); - updateHeads(true); loadMusic(); reloadNotes(); onChartLoaded(); - + updateHeads(true); + autoSaveTime = 0; Conductor.songPosition = 0; if(FlxG.sound.music != null) FlxG.sound.music.time = 0; @@ -645,8 +669,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var chartName:String = 'unknown'; if(Song.chartPath != null) { - chartName = Song.chartPath.replace('/', '\\'); - chartName = chartName.substring(chartName.lastIndexOf('\\')+1, chartName.lastIndexOf('.')); + chartName = Song.chartPath.replace('\\', '/'); + chartName = chartName.substring(chartName.lastIndexOf('/')+1, chartName.lastIndexOf('.')); } chartName += DateTools.format(Date.now(), '_%Y-%m-%d_%H-%M-%S'); var songCopy:SwagSong = Reflect.copy(PlayState.SONG); @@ -854,6 +878,10 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU } } } + else if(FlxG.keys.justPressed.R) + { + Conductor.songPosition = FlxG.sound.music.time = cachedSectionTimes[curSec] + (curSec > 0 ? 0.000001 : 0); + } else if(FlxG.keys.pressed.W != FlxG.keys.pressed.S || FlxG.mouse.wheel != 0) { if(FlxG.sound.music.playing) @@ -1013,7 +1041,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU selectedNotes.shift(); if(note == null) continue; - trace('Removed ${!note.isEvent ? 'note' : 'event'} at time: ${note.strumTime}'); + var kind:String = !note.isEvent ? 'note' : 'event'; + trace('Removed $kind at time: ${note.strumTime}'); if(!note.isEvent) { notes.remove(note); @@ -1244,7 +1273,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var closeNotes:Array = curRenderedNotes.members.filter(function(note:MetaNote) { var chartY:Float = FlxG.mouse.y - note.chartY; - return ((note.isEvent && noteData < 0) || note.songData[1] == noteData) && chartY >= 0 && chartY < GRID_SIZE; + return ((note.isEvent && noteData < 0) || (!note.isEvent && note.songData[1] == noteData)) && chartY >= 0 && chartY < GRID_SIZE; }); closeNotes.sort(function(a:MetaNote, b:MetaNote) return Math.abs(a.strumTime - FlxG.mouse.y) < Math.abs(b.strumTime - FlxG.mouse.y) ? 1 : -1); @@ -1262,16 +1291,15 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU else if(!holdingAlt) { resetSelectedNotes(); - selectedNotes = sel.copy(); selectedNotes.remove(closest); addUndoAction(SELECT_NOTE, {old: sel, current: selectedNotes.copy()}); } - trace('Notes selected: ' + selectedNotes.length); } else if(!FlxG.keys.pressed.CONTROL) // Remove Note/Event { - trace('Removed ${!closest.isEvent ? 'note' : 'event'} at time: ${closest.strumTime}'); + var kind:String = !closest.isEvent ? 'note' : 'event'; + trace('Removed $kind at time: ${closest.strumTime}'); if(!closest.isEvent) notes.remove(closest); else @@ -1504,11 +1532,19 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var pushedEvents:Array = []; movingNotes.forEachAlive(function(note:MetaNote) { - notes.push(note); - if(!note.isEvent) pushedNotes.push(note); - else pushedEvents.push(cast (note, EventMetaNote)); + if(!note.isEvent) + { + notes.push(note); + pushedNotes.push(note); + } + else + { + events.push(cast (note, EventMetaNote)); + pushedEvents.push(cast (note, EventMetaNote)); + } }); notes.sort(PlayState.sortByTime); + events.sort(PlayState.sortByTime); movingNotes.clear(); isMovingNotes = false; softReloadNotes(); @@ -1656,7 +1692,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU else selectedEventText.visible = false; } - function recreateGrids() + function createGrids() { var destroyed:Bool = false; var stripes:Array = null; @@ -2087,6 +2123,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU } prevGridBg.vortexLineEnabled = gridBg.vortexLineEnabled = nextGridBg.vortexLineEnabled = vortexEnabled; prevGridBg.vortexLineSpace = gridBg.vortexLineSpace = nextGridBg.vortexLineSpace = GRID_SIZE * 4 * curZoom; + updateWaveform(); } function softReloadNotes(onlyCurrent:Bool = false) @@ -2219,7 +2256,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var _lastGfSection:Null = null; function updateHeads(ignoreCheck:Bool = false):Void { - var isGfSection:Bool = (PlayState.SONG.notes[curSec].gfSection == true); + var curSecData:SwagSection = PlayState.SONG.notes[curSec]; + var isGfSection:Bool = (curSecData != null && curSecData.gfSection == true); if(_lastGfSection == isGfSection && _lastSec == curSec && !ignoreCheck) return; //optimization for (i in 0...GRID_PLAYERS) @@ -2234,7 +2272,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU { var iconP1:HealthIcon = icons[0]; var iconP2:HealthIcon = icons[1]; - var mustHitSection:Bool = (PlayState.SONG.notes[curSec].mustHitSection == true); + var mustHitSection:Bool = (curSecData != null && curSecData.mustHitSection == true); if (isGfSection) { if (mustHitSection) @@ -2626,6 +2664,11 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU note.setStrumTime(Math.max(-5000, strumTimeStepper.value + (note.strumTime - firstTime))); positionNoteYOnTime(note, curSec); + + if(note.isEvent) + { + cast (note, EventMetaNote).updateEventText(); + } } softReloadNotes(); }; @@ -2811,25 +2854,16 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU }); var clearButton:PsychUIButton = new PsychUIButton(objX + 200, objY, 'Clear', function() { - if(affectNotes.checked) + for (note in curRenderedNotes) { - for (note in curRenderedNotes) - { - if(note == null || note.isEvent) continue; + if(note == null) continue; - selectedNotes.remove(note); + if(!note.isEvent && affectNotes.checked) notes.remove(note); - } - } - if(affectEvents.checked) - { - for (event in curRenderedNotes) - { - if(event == null || !event.isEvent) continue; + if(note.isEvent && affectEvents.checked) + events.remove(cast (note, EventMetaNote)); - selectedNotes.remove(event); - events.remove(cast (event, EventMetaNote)); - } + selectedNotes.remove(note); } softReloadNotes(true); }); @@ -2991,8 +3025,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU if(Song.chartPath != null && Song.chartPath.length > 0) { - var parentFolder:String = Song.chartPath.replace('/', '\\'); - parentFolder = parentFolder.substr(0, Song.chartPath.lastIndexOf('\\')+1); + var parentFolder:String = Song.chartPath.replace('\\', '/'); + parentFolder = parentFolder.substr(0, Song.chartPath.lastIndexOf('/')+1); var notetypeFile:Array = CoolUtil.coolTextFile(parentFolder + 'notetypes.txt'); if(notetypeFile.length > 0) { @@ -3131,6 +3165,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU { PlayState.SONG.offset = audioOffsetStepper.value; Conductor.offset = audioOffsetStepper.value; + updateWaveform(); }; tab_group.add(new FlxText(songNameInputText.x, songNameInputText.y - 15, 80, 'Song Name:')); @@ -3226,8 +3261,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU { try { - var filePath:String = fileDialog.path.replace('/', '\\'); - var loadedChart:SwagSong = Song.parseJSON(fileDialog.data, filePath.substr(filePath.lastIndexOf('\\'))); + var filePath:String = fileDialog.path.replace('\\', '/'); + var loadedChart:SwagSong = Song.parseJSON(fileDialog.data, filePath.substr(filePath.lastIndexOf('/'))); if(loadedChart == null || !Reflect.hasField(loadedChart, 'song')) //Check if chart is ACTUALLY a chart and valid { showOutput('Error: File loaded is not a Psych Engine/FNF 0.2.x.x chart.', true); @@ -3298,7 +3333,6 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var btn:PsychUIButton = new PsychUIButton(0, radioGrp.y + radioGrp.height + 20, 'Load', function() { - var autosaveName:String = fileList[radioGrp.checked]; var path:String = 'backups/$autosaveName'; state.close(); @@ -3360,8 +3394,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU { try { - var filePath:String = fileDialog.path.replace('/', '\\'); - var eventsFile:SwagSong = Song.parseJSON(fileDialog.data, filePath.substr(filePath.lastIndexOf('\\'))); + var filePath:String = fileDialog.path.replace('\\', '/'); + var eventsFile:SwagSong = Song.parseJSON(fileDialog.data, filePath.substr(filePath.lastIndexOf('/'))); if(eventsFile == null || Reflect.hasField(eventsFile, 'scrollSpeed') || eventsFile.events == null) { showOutput('Error: File loaded is not a Psych Engine chart/events file.', true); @@ -3529,17 +3563,18 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU { try { - var path:String = fileDialog.path.replace('/', '\\'); + var path:String = fileDialog.path.replace('\\', '/'); var chartName:String = Paths.formatToSongPath(PlayState.SONG.song) + '.json'; - chartName = chartName.substring(chartName.lastIndexOf('\\')+1, chartName.lastIndexOf('.')); + chartName = chartName.substring(chartName.lastIndexOf('/')+1, chartName.lastIndexOf('.')); - var chartFile:String = '$path\\$chartName-chart.json'; - var metadataFile:String = '$path\\$chartName-metadata.json'; + var chartFile:String = '$path/$chartName-chart.json'; + var metadataFile:String = '$path/$chartName-metadata.json'; updateChartData(); var pack:VSlicePackage = VSlice.export(PlayState.SONG); + ClientPrefs.toggleVolumeKeys(false); openSubState(new BasePrompt('Metadata', function(state:BasePrompt) { @@ -3611,8 +3646,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU fileDialog.open('song.json', 'Open a Psych Engine Chart JSON', function() { - var filePath:String = fileDialog.path.replace('/', '\\'); - var loadedChart:SwagSong = Song.parseJSON(fileDialog.data, filePath.substr(filePath.lastIndexOf('\\'))); + var filePath:String = fileDialog.path.replace('\\', '/'); + var loadedChart:SwagSong = Song.parseJSON(fileDialog.data, filePath.substr(filePath.lastIndexOf('/'))); if(loadedChart == null || !Reflect.hasField(loadedChart, 'song')) //Check if chart is ACTUALLY a chart and valid { showOutput('Error: File loaded is not a Psych Engine 0.x.x/FNF 0.2.x.x chart.', true); @@ -3626,11 +3661,12 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU return; } + ClientPrefs.toggleVolumeKeys(false); openSubState(new BasePrompt('Metadata', function(state:BasePrompt) { var songName:String = Paths.formatToSongPath(pack.metadata.songName); - var parentFolder:String = filePath.substring(0, filePath.lastIndexOf('\\')+1); + var parentFolder:String = filePath.substring(0, filePath.lastIndexOf('/')+1); var artistInput, charterInput, difficultiesInput:PsychUIInputText = null; var btnX = 640; @@ -3689,8 +3725,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU fileDialog.openDirectory('Save V-Slice Chart/Metadata JSONs', function() { overwriteSavedSomething = false; - var path:String = fileDialog.path.replace('/', '\\'); - if(path.endsWith('\\')) path = path.substr(0, path.length-1); + var path:String = fileDialog.path.replace('\\', '/'); + if(path.endsWith('/')) path = path.substr(0, path.length-1); overwriteCheck('$path/$songName-chart.json', '$songName-chart.json', PsychJsonPrinter.print(pack.chart, ['events', 'notes', 'scrollSpeed']), function() { overwriteCheck('$path/$songName-metadata.json', '$songName-metadata.json', PsychJsonPrinter.print(pack.metadata, ['characters', 'difficulties', 'timeChanges']), function() @@ -3798,8 +3834,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU { fileDialog.openDirectory('Save Converted Psych JSONs', function() { - var path:String = fileDialog.path.replace('/', '\\'); - if(!path.endsWith('\\')) path += '\\'; + var path:String = fileDialog.path.replace('\\', '/'); + if(!path.endsWith('/')) path += '/'; var diffs:Array = metadata.playData.difficulties.copy(); var defaultDiff:String = Paths.formatToSongPath(Difficulty.getDefault()); @@ -3859,8 +3895,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var oldSong = PlayState.SONG; try { - var filePath:String = fileDialog.path.replace('/', '\\'); - filePath = filePath.substring(filePath.lastIndexOf('\\')+1, filePath.lastIndexOf('.')); + var filePath:String = fileDialog.path.replace('\\', '/'); + filePath = filePath.substring(filePath.lastIndexOf('/')+1, filePath.lastIndexOf('.')); var loadedChart:SwagSong = Song.parseJSON(fileDialog.data, filePath, ''); if(loadedChart == null || !Reflect.hasField(loadedChart, 'song')) //Check if chart is ACTUALLY a chart and valid @@ -4078,7 +4114,6 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var showNextGridButton:PsychUIButton; var noteTypeLabelsButton:PsychUIButton; var vortexEditorButton:PsychUIButton; - var vortexEnabled:Bool = false; function addViewTab() { var tab = upperBox.getTab('View'); @@ -4087,6 +4122,13 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU var btnY = 1; var btnWid = Std.int(tab.width); + if(chartEditorSave.data.waveformEnabled != null) + waveformEnabled = chartEditorSave.data.waveformEnabled; + if(chartEditorSave.data.waveformTarget != null) + waveformTarget = chartEditorSave.data.waveformTarget; + if(chartEditorSave.data.waveformColor != null) + waveformSprite.color = CoolUtil.colorFromString(chartEditorSave.data.waveformColor); + showLastGridButton = new PsychUIButton(btnX, btnY, '', function() { showPreviousSection = !showPreviousSection; @@ -4135,7 +4177,61 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU btnY++; btnY += 20; - var btn:PsychUIButton = new PsychUIButton(btnX, btnY, ' Waveform...', function() showOutput('Feature not implemented yet!', true), btnWid); //TO DO: Add functionality + var btn:PsychUIButton = new PsychUIButton(btnX, btnY, ' Waveform...', function() + { + ClientPrefs.toggleVolumeKeys(false); + openSubState(new BasePrompt(320, 200, 'Waveform Settings', + function(state:BasePrompt) { + upperBox.isMinimized = true; + upperBox.bg.visible = false; + + var btn:PsychUIButton = new PsychUIButton(state.bg.x + state.bg.width - 40, state.bg.y, 'X', state.close, 40); + btn.cameras = state.cameras; + state.add(btn); + + var check:PsychUICheckBox = new PsychUICheckBox(state.bg.x + 40, state.bg.y + 80, 'Enabled', 60); + check.onClick = function() + { + chartEditorSave.data.waveformEnabled = waveformEnabled = check.checked; + updateWaveform(); + }; + check.cameras = state.cameras; + check.checked = waveformEnabled; + state.add(check); + + var waveformC:String = '0000FF'; + if(chartEditorSave.data.waveformColor != null) + waveformC = chartEditorSave.data.waveformColor; + + var input:PsychUIInputText = new PsychUIInputText(check.x, check.y + 50, 60, waveformC, 10); + input.onChange = function(old:String, cur:String) + { + chartEditorSave.data.waveformColor = cur; + waveformSprite.color = CoolUtil.colorFromString(cur); + } + input.maxLength = 6; + input.filterMode = ONLY_HEXADECIMAL; + input.cameras = state.cameras; + input.forceCase = UPPER_CASE; + + var options:Array = [INST, PLAYER, OPPONENT]; + var radioGrp:PsychUIRadioGroup = new PsychUIRadioGroup(check.x + 120, check.y, ['Instrumental', 'Main Vocals', 'Opponent Vocals']); + radioGrp.cameras = state.cameras; + radioGrp.onClick = function() + { + waveformTarget = chartEditorSave.data.waveformTarget = options[radioGrp.checked]; + updateWaveform(); + }; + radioGrp.checked = options.indexOf(waveformTarget); + state.add(radioGrp); + + var txt1:FlxText = new FlxText(input.x, input.y - 15, 80, 'Color (Hex):'); + txt1.cameras = state.cameras; + state.add(txt1); + state.add(input); + } + )); + }, btnWid); btn.text.alignment = LEFT; tab_group.add(btn); @@ -4311,12 +4407,12 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU else { var chartName:String = Paths.formatToSongPath(PlayState.SONG.song) + '.json'; - if(Song.chartPath != null) chartName = Song.chartPath.substr(Song.chartPath.lastIndexOf('\\')).trim(); + if(Song.chartPath != null) chartName = Song.chartPath.substr(Song.chartPath.lastIndexOf('/')).trim(); fileDialog.save(chartName, chartData, function() { var newPath:String = fileDialog.path; - Song.chartPath = newPath.replace('/', '\\'); + Song.chartPath = newPath.replace('\\', '/'); reloadNotesDropdowns(); showOutput('Chart saved successfully to: $newPath'); @@ -4529,6 +4625,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU override function closeSubState() { + ClientPrefs.toggleVolumeKeys(true); super.closeSubState(); upperBox.isMinimized = true; upperBox.visible = mainBox.visible = infoBox.visible = true; @@ -4685,10 +4782,12 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU case MOVE_NOTE: actionRemoveNotes(action.data.movedNotes, action.data.movedEvents); actionPushNotes(action.data.originalNotes, action.data.originalEvents); + onSelectNote(); case SELECT_NOTE: resetSelectedNotes(); selectedNotes = action.data.old; + if(lockedEvents) selectedNotes = selectedNotes.filter((note:MetaNote) -> !note.isEvent); onSelectNote(); } showOutput('Undo #${currentUndo+1}: ${action.action}'); @@ -4716,10 +4815,12 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU case MOVE_NOTE: actionRemoveNotes(action.data.originalNotes, action.data.originalEvents); actionPushNotes(action.data.movedNotes, action.data.movedEvents); + onSelectNote(); case SELECT_NOTE: resetSelectedNotes(); selectedNotes = action.data.current; + if(lockedEvents) selectedNotes = selectedNotes.filter((note:MetaNote) -> !note.isEvent); onSelectNote(); } showOutput('Redo #${currentUndo+1}: ${action.action}'); @@ -4737,6 +4838,8 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU { notes.push(note); selectedNotes.push(note); + note.songData[0] = note.strumTime; + note.songData[1] = note.chartNoteData; } } notes.sort(PlayState.sortByTime); @@ -4749,6 +4852,7 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU { events.push(event); selectedNotes.push(event); + event.songData[0] = event.strumTime; } } events.sort(PlayState.sortByTime); @@ -4759,21 +4863,40 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU function actionRemoveNotes(dataNotes:Array, dataEvents:Array) { if(dataNotes != null && dataNotes.length > 0) + { for (note in dataNotes) + { if(note != null) { notes.remove(note); selectedNotes.remove(note); + + if(note.exists) + { + note.colorTransform.redMultiplier = note.colorTransform.greenMultiplier = note.colorTransform.blueMultiplier = 1; + if(note.animation.curAnim != null) note.animation.curAnim.curFrame = 0; + } } + } + } if(dataEvents != null && dataEvents.length > 0) + { for (event in dataEvents) + { if(event != null) { - events.remove(event); + trace(events.remove(event)); selectedNotes.remove(event); - } + if(event.exists) + { + event.colorTransform.redMultiplier = event.colorTransform.greenMultiplier = event.colorTransform.blueMultiplier = 1; + if(event.animation.curAnim != null) event.animation.curAnim.curFrame = 0; + } + } + } + } softReloadNotes(); } @@ -4791,4 +4914,189 @@ class ChartingState extends MusicBeatState implements PsychUIEventHandler.PsychU } } } -} \ No newline at end of file + + // Ported from the old chart editor + var wavData:Array>> = [[[0], [0]], [[0], [0]]]; + function updateWaveform() { + #if (lime_cffi && !macro) + if(curSec < 0 || curSec >= cachedSectionTimes.length || !waveformEnabled) + { + waveformSprite.visible = false; + return; + } + + waveformSprite.visible = true; + waveformSprite.y = gridBg.y; + var width:Int = Std.int(GRID_SIZE * GRID_COLUMNS_PER_PLAYER * GRID_PLAYERS); + var height:Int = Std.int(gridBg.height); + if(Std.int(waveformSprite.height) != height && waveformSprite.pixels != null) + { + waveformSprite.pixels.dispose(); + waveformSprite.pixels.disposeImage(); + waveformSprite.makeGraphic(width, height, 0x00FFFFFF); + } + waveformSprite.pixels.fillRect(new Rectangle(0, 0, width, height), 0x00FFFFFF); + + wavData[0][0].resize(0); + wavData[0][1].resize(0); + wavData[1][0].resize(0); + wavData[1][1].resize(0); + + var sound:FlxSound = switch(waveformTarget) + { + case INST: + FlxG.sound.music; + case PLAYER: + vocals; + case OPPONENT: + opponentVocals; + default: + null; + } + + @:privateAccess + if (sound != null && sound._sound != null && sound._sound.__buffer != null) + { + var bytes:Bytes = sound._sound.__buffer.data.toBytes(); + wavData = waveformData(sound._sound.__buffer, bytes, cachedSectionTimes[curSec] - Conductor.offset, cachedSectionTimes[curSec+1] - Conductor.offset, 1, wavData, height); + } + + // Draws + var gSize:Int = Std.int(GRID_SIZE * 8); + var hSize:Int = Std.int(gSize / 2); + var size:Float = 1; + + var leftLength:Int = (wavData[0][0].length > wavData[0][1].length ? wavData[0][0].length : wavData[0][1].length); + var rightLength:Int = (wavData[1][0].length > wavData[1][1].length ? wavData[1][0].length : wavData[1][1].length); + + var length:Int = leftLength > rightLength ? leftLength : rightLength; + + for (index in 0...length) + { + var lmin:Float = FlxMath.bound(((index < wavData[0][0].length && index >= 0) ? wavData[0][0][index] : 0) * (gSize / 1.12), -hSize, hSize) / 2; + var lmax:Float = FlxMath.bound(((index < wavData[0][1].length && index >= 0) ? wavData[0][1][index] : 0) * (gSize / 1.12), -hSize, hSize) / 2; + + var rmin:Float = FlxMath.bound(((index < wavData[1][0].length && index >= 0) ? wavData[1][0][index] : 0) * (gSize / 1.12), -hSize, hSize) / 2; + var rmax:Float = FlxMath.bound(((index < wavData[1][1].length && index >= 0) ? wavData[1][1][index] : 0) * (gSize / 1.12), -hSize, hSize) / 2; + + waveformSprite.pixels.fillRect(new Rectangle(hSize - (lmin + rmin), index * size, (lmin + rmin) + (lmax + rmax), size), FlxColor.WHITE); + } + #else + waveformSprite.visible = false; + #end + } + + function waveformData(buffer:AudioBuffer, bytes:Bytes, time:Float, endTime:Float, multiply:Float = 1, ?array:Array>>, ?steps:Float):Array>> + { + #if (lime_cffi && !macro) + if (buffer == null || buffer.data == null) return [[[0], [0]], [[0], [0]]]; + + var khz:Float = (buffer.sampleRate / 1000); + var channels:Int = buffer.channels; + + var index:Int = Std.int(time * khz); + + var samples:Float = ((endTime - time) * khz); + + if (steps == null) steps = 1280; + + var samplesPerRow:Float = samples / steps; + var samplesPerRowI:Int = Std.int(samplesPerRow); + + var gotIndex:Int = 0; + + var lmin:Float = 0; + var lmax:Float = 0; + + var rmin:Float = 0; + var rmax:Float = 0; + + var rows:Float = 0; + + var simpleSample:Bool = true;//samples > 17200; + var v1:Bool = false; + + if (array == null) array = [[[0], [0]], [[0], [0]]]; + + while (index < (bytes.length - 1)) { + if (index >= 0) { + var byte:Int = bytes.getUInt16(index * channels * 2); + + if (byte > 65535 / 2) byte -= 65535; + + var sample:Float = (byte / 65535); + + if (sample > 0) + if (sample > lmax) lmax = sample; + else if (sample < 0) + if (sample < lmin) lmin = sample; + + if (channels >= 2) { + byte = bytes.getUInt16((index * channels * 2) + 2); + + if (byte > 65535 / 2) byte -= 65535; + + sample = (byte / 65535); + + if (sample > 0) { + if (sample > rmax) rmax = sample; + } else if (sample < 0) { + if (sample < rmin) rmin = sample; + } + } + } + + v1 = samplesPerRowI > 0 ? (index % samplesPerRowI == 0) : false; + while (simpleSample ? v1 : rows >= samplesPerRow) { + v1 = false; + rows -= samplesPerRow; + + gotIndex++; + + var lRMin:Float = Math.abs(lmin) * multiply; + var lRMax:Float = lmax * multiply; + + var rRMin:Float = Math.abs(rmin) * multiply; + var rRMax:Float = rmax * multiply; + + if (gotIndex > array[0][0].length) array[0][0].push(lRMin); + else array[0][0][gotIndex - 1] = array[0][0][gotIndex - 1] + lRMin; + + if (gotIndex > array[0][1].length) array[0][1].push(lRMax); + else array[0][1][gotIndex - 1] = array[0][1][gotIndex - 1] + lRMax; + + if (channels >= 2) + { + if (gotIndex > array[1][0].length) array[1][0].push(rRMin); + else array[1][0][gotIndex - 1] = array[1][0][gotIndex - 1] + rRMin; + + if (gotIndex > array[1][1].length) array[1][1].push(rRMax); + else array[1][1][gotIndex - 1] = array[1][1][gotIndex - 1] + rRMax; + } + else + { + if (gotIndex > array[1][0].length) array[1][0].push(lRMin); + else array[1][0][gotIndex - 1] = array[1][0][gotIndex - 1] + lRMin; + + if (gotIndex > array[1][1].length) array[1][1].push(lRMax); + else array[1][1][gotIndex - 1] = array[1][1][gotIndex - 1] + lRMax; + } + + lmin = 0; + lmax = 0; + + rmin = 0; + rmax = 0; + } + + index++; + rows++; + if(gotIndex > steps) break; + } + + return array; + #else + return [[[0], [0]], [[0], [0]]]; + #end + } +} diff --git a/source/states/editors/MenuCharacterEditorState.hx b/source/states/editors/MenuCharacterEditorState.hx index 2647985fa11..0bde7698175 100644 --- a/source/states/editors/MenuCharacterEditorState.hx +++ b/source/states/editors/MenuCharacterEditorState.hx @@ -49,7 +49,7 @@ class MenuCharacterEditorState extends MusicBeatState implements PsychUIEventHan add(grpWeekCharacters); txtOffsets = new FlxText(20, 10, 0, "[0, 0]", 32); - txtOffsets.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, CENTER); + txtOffsets.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, CENTER); txtOffsets.alpha = 0.7; add(txtOffsets); @@ -378,4 +378,4 @@ class MenuCharacterEditorState extends MusicBeatState implements PsychUIEventHan _file = null; FlxG.log.error("Problem saving file"); } -} \ No newline at end of file +} diff --git a/source/states/editors/NoteSplashEditorState.hx b/source/states/editors/NoteSplashEditorState.hx index 63c8cf0c056..24b10a8960c 100644 --- a/source/states/editors/NoteSplashEditorState.hx +++ b/source/states/editors/NoteSplashEditorState.hx @@ -1,21 +1,16 @@ package states.editors; -import openfl.net.FileFilter; import objects.Note; import objects.NoteSplash; import objects.StrumNote; -import flixel.FlxSprite; + +import openfl.net.FileFilter; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import flixel.input.keyboard.FlxKey; -import flixel.text.FlxText; -import flixel.tweens.FlxTween; -import flixel.util.FlxColor; -import haxe.Json; import openfl.events.Event; import openfl.events.IOErrorEvent; import openfl.net.FileReference; - -using StringTools; +import haxe.Json; @:access(objects.NoteSplash) class NoteSplashEditorState extends MusicBeatState @@ -23,27 +18,23 @@ class NoteSplashEditorState extends MusicBeatState var strums:FlxTypedSpriteGroup = new FlxTypedSpriteGroup(); var splashes:FlxTypedSpriteGroup = new FlxTypedSpriteGroup(); var config = NoteSplash.createConfig(); + var tipText:FlxText; var errorText:FlxText; var curText:FlxText; static var imageSkin:String = null; - var splash:NoteSplash; var UI:PsychUIBox; var properUI:PsychUIBox; var shaderUI:PsychUIBox; - var noteData:Int; - - var curType:String; - var currentNoteType:PsychUIInputText; override function create() { if (imageSkin == null) imageSkin = NoteSplash.DEFAULT_SKIN + NoteSplash.getSplashSkinPostfix(); - + FlxG.mouse.visible = true; FlxG.sound.volumeUpKeys = []; @@ -92,10 +83,9 @@ class NoteSplashEditorState extends MusicBeatState babyArrow.postAddedToGroup(); babyArrow.screenCenter(Y); babyArrow.ID = i; - //babyArrow.scale.scale(1.1, 1.1); strums.add(babyArrow); } - + add(strums); add(splashes); @@ -158,11 +148,11 @@ class NoteSplashEditorState extends MusicBeatState UI.add(indices_input); UI.add(new FlxText(20, 110, 0, "Minimum FPS:")); - var minFps:PsychUINumericStepper = new PsychUINumericStepper(20, 127.5, 1, 24, 1, 120); + var minFps:PsychUINumericStepper = new PsychUINumericStepper(20, 127.5, 1, 22, 1, 120); UI.add(minFps); UI.add(new FlxText(150, 110, 0, "Maximum FPS:")); - var maxFps:PsychUINumericStepper = new PsychUINumericStepper(150, 127.5, 1, 24, 1, 120); + var maxFps:PsychUINumericStepper = new PsychUINumericStepper(150, 127.5, 1, 26, 1, 120); UI.add(maxFps); animDropDown = new PsychUIDropDownMenu(-155, 57, [""], function(id:Int, name:String) @@ -177,12 +167,11 @@ class NoteSplashEditorState extends MusicBeatState numericStepperData.min = 0; numericStepperData.value = i.noteData; curAnim = name; - minFps.value = i.minFps; - maxFps.value = i.maxFps; + minFps.value = i.fps[0]; + maxFps.value = i.fps[1]; if (i.indices != null && i.indices.length > 0) - { indices_input.text = i.indices.toString().substring(1, i.indices.toString().length - 2); - } + playStrumAnim(curAnim, i.noteData); } } @@ -192,16 +181,14 @@ class NoteSplashEditorState extends MusicBeatState { var anims:Array = []; if (config != null && config.animations != null) - { for (i in config.animations.keys()) { anims.push(i); } - } + if (anims.length < 1) - { anims.push(""); - } + if (curAnim == null && anims[0].length > 0) curAnim = anims[0]; @@ -221,8 +208,8 @@ class NoteSplashEditorState extends MusicBeatState prefix_input.text = ""; indices_input.text = ""; numericStepperData.value = 0; - minFps.value = 24; - maxFps.value = 24; + minFps.value = 22; + maxFps.value = 26; setAnimDropDown(); parseRGB(); changeShader.selectedLabel = "Red"; @@ -244,16 +231,18 @@ class NoteSplashEditorState extends MusicBeatState } } - var offsets = [0, 0]; + var offsets:Array = [0, 0]; var conf = config.animations.get(name_input.text); + if (conf != null) offsets = conf.offsets; + if (offsets == null) offsets = [0, 0]; else offsets = offsets.copy(); - config = NoteSplash.addAnimationToConfig([scaleXNumericStepper.value, scaleYNumericStepper.value], config, name_input.text, prefix_input.text, cast minFps.value, cast maxFps.value, offsets, indices, cast numericStepperData.value); + config = NoteSplash.addAnimationToConfig(config, scaleNumericStepper.value, name_input.text, prefix_input.text, [cast minFps.value, cast maxFps.value], offsets, indices, cast numericStepperData.value); curAnim = name_input.text; playStrumAnim(curAnim, cast numericStepperData.value); setAnimDropDown(); @@ -294,10 +283,11 @@ class NoteSplashEditorState extends MusicBeatState errorText.color = FlxColor.RED; FlxTween.cancelTweensOf(errorText); - var image = Paths.image("noteSplashes/" + imageSkin); + + var image = Paths.image(imageSkin); if (image == null) { - errorText.text = "ERROR! Couldn't find noteSplashes/" + imageSkin + ".png"; + errorText.text = 'ERROR! Couldn\'t find $imageSkin.png'; errorText.alpha = 1; return; } @@ -305,27 +295,28 @@ class NoteSplashEditorState extends MusicBeatState { errorText.color = FlxColor.GREEN; errorText.alpha = 1; - errorText.text = "Succesfully loaded noteSplashes/" + imageSkin + ".png"; + errorText.text = 'Succesfully loaded $imageSkin.png'; } + NoteSplash.configs.clear(); + FlxTween.tween(errorText, {alpha: 0}, 1, {startDelay: 1, onComplete: (twn) -> { errorText.color = FlxColor.RED; }}); splash.loadSplash(imageSkin); splash.alpha = 0.0001; - if (splash.config != null) - config = splash.config; - else - config = NoteSplash.createConfig(); + + if (splash.config != null) config = splash.config; + else config = NoteSplash.createConfig(); curAnim = null; name_input.text = ""; prefix_input.text = ""; indices_input.text = ""; numericStepperData.value = 0; - minFps.value = 24; - maxFps.value = 24; + minFps.value = 22; + maxFps.value = 26; setAnimDropDown(); parseRGB(); changeShader.selectedLabel = "Red"; @@ -334,8 +325,7 @@ class NoteSplashEditorState extends MusicBeatState } var imageInputText:PsychUIInputText; - var scaleXNumericStepper:PsychUINumericStepper; - var scaleYNumericStepper:PsychUINumericStepper; + var scaleNumericStepper:PsychUINumericStepper; function addProperitiesTab() { var ui = properUI.getTab("Properties").menu; @@ -350,12 +340,12 @@ class NoteSplashEditorState extends MusicBeatState }); ui.add(reloadButton); - ui.add(new FlxText(20, 40, "Scale X / Y:")); - scaleXNumericStepper = new PsychUINumericStepper(20, 57.5, 0.25, 1, 0, 4, 2, 60); - ui.add(scaleXNumericStepper); + ui.add(new FlxText(20, 40, "Scale:")); + scaleNumericStepper = new PsychUINumericStepper(20, 57.5, 0.1, 1, 0, 4, 2, 60); + ui.add(scaleNumericStepper); + + scaleNumericStepper.value = config != null ? config.scale : 1; - scaleYNumericStepper = new PsychUINumericStepper(20, 75, 0.25, 1, 0, 4, 2, 60); - ui.add(scaleYNumericStepper); ui.add(new FlxText(130, 40, "Animations:")); var saveButton:PsychUIButton = new PsychUIButton(20, 130, "Save", saveSplash); @@ -367,29 +357,37 @@ class NoteSplashEditorState extends MusicBeatState var loadButton:PsychUIButton = new PsychUIButton(180, 155, "Convert TXT", loadTxt); ui.add(loadButton); - if (config != null && config.scale != null) + var allowRGBCheck:PsychUICheckBox = new PsychUICheckBox(20, 105, "", 1); + function check() { - scaleXNumericStepper.value = config.scale[0]; - scaleYNumericStepper.value = config.scale[1]; + if (config != null) + config.allowRGB = allowRGBCheck.checked; } + allowRGBCheck.onClick = check; + allowRGBCheck.checked = config != null && cast(config.allowRGB, Null) != null ? config.allowRGB : false; + + var rgbText = new FlxText(allowRGBCheck.x + 20, 0); + rgbText.text = "Allow RGB?"; + rgbText.y = allowRGBCheck.y + 2.5; + ui.add(rgbText); + + ui.add(allowRGBCheck); - var getsAffectedByShader:PsychUICheckBox = new PsychUICheckBox(20, 105, "", 1); + var allowPixelCheck:PsychUICheckBox = new PsychUICheckBox(allowRGBCheck.x + 110, allowRGBCheck.y, "", 1); function check() { if (config != null) - { - config.affectedByShader = getsAffectedByShader.checked; - } + config.allowPixel = allowPixelCheck.checked; } - getsAffectedByShader.onClick = check; - getsAffectedByShader.checked = config != null && cast(config.affectedByShader, Null) != null ? config.affectedByShader : false; + allowPixelCheck.onClick = check; + allowPixelCheck.checked = config != null && cast(config.allowPixel, Null) != null ? config.allowPixel : false; - var text = new FlxText(getsAffectedByShader.x + 20, 0); - text.text = "Affected by Shader?"; - text.y = getsAffectedByShader.y + 2.5; - ui.add(text); + var pixelText = new FlxText(allowPixelCheck.x + 20, 0); + pixelText.text = "Allow Pixel?"; + pixelText.y = allowPixelCheck.y + 2.5; + ui.add(pixelText); - ui.add(getsAffectedByShader); + ui.add(allowPixelCheck); } var redEnabled:Bool = true; @@ -500,7 +498,9 @@ class NoteSplashEditorState extends MusicBeatState // } - var copiedOffset:Array = [0, 0]; + var holdingArrowsTime:Float = 0; + var holdingArrowsElapsed:Float = 0; + var copiedOffset:Array = [0, 0]; override function update(elapsed:Float) { super.update(elapsed); @@ -509,9 +509,10 @@ class NoteSplashEditorState extends MusicBeatState curText.text = 'Copied Offsets: ${Std.string(copiedOffset).replace(',', ', ')}\n'; curText.text += 'Current Animation: ${curAnim == null || curAnim.length < 1 ? "NONE" : curAnim}'; + if (config != null && !curText.text.contains('NONE')) { - var offsets:Array = try config.animations.get(curAnim).offsets catch (e) [0, 0]; + var offsets:Array = try config.animations.get(curAnim).offsets catch (e) [0, 0]; curText.text += ' ($offsets)'.replace(',', ', '); } @@ -519,34 +520,11 @@ class NoteSplashEditorState extends MusicBeatState { var currentAnim:String = curAnimText.text; if (config.animations.exists(currentAnim) && config.animations.get(currentAnim) != null) - { addButton.label = 'Update'; - } else - { addButton.label = 'Add'; - } - - config.scale[0] = scaleXNumericStepper.value; - config.scale[1] = scaleYNumericStepper.value; - } - if (FlxG.keys.pressed.CONTROL) - { - if (FlxG.keys.justPressed.C) - { - if (config.animations.get(curAnim) != null) - copiedOffset = config.animations.get(curAnim).offsets.copy(); - } - else if (FlxG.keys.justPressed.V) - { - if (config.animations.get(curAnim) != null) - { - var conf = config.animations.get(curAnim); - conf.offsets = copiedOffset.copy(); - config.animations.set(curAnim, conf); - } - } + config.scale = scaleNumericStepper.value; } var blockInput:Bool = PsychUIInputText.focusOn != null; @@ -562,28 +540,58 @@ class NoteSplashEditorState extends MusicBeatState } } - var multiplier:Int = FlxG.keys.pressed.SHIFT ? 10 : 1; - - if (FlxG.keys.justPressed.LEFT) - { - config.animations[curAnim].offsets[0] += multiplier; - splash(); - } - else if (FlxG.keys.justPressed.RIGHT) + var changedOffset = false; + if (FlxG.keys.pressed.CONTROL && config.animations.get(curAnim) != null) { - config.animations[curAnim].offsets[0] -= multiplier; - splash(); + if (FlxG.keys.justPressed.C) + { + copiedOffset = config.animations.get(curAnim).offsets.copy(); + } + else if (FlxG.keys.justPressed.V) + { + var conf = config.animations.get(curAnim); + conf.offsets = copiedOffset.copy(); + config.animations.set(curAnim, conf); + changedOffset = true; + } + else if(FlxG.keys.justPressed.R) + { + var conf = config.animations.get(curAnim); + conf.offsets = [0, 0]; + config.animations.set(curAnim, conf); + changedOffset = true; + } } - else if (FlxG.keys.justPressed.UP) + + var multiplier:Int = (FlxG.keys.pressed.SHIFT || FlxG.gamepads.anyPressed(LEFT_SHOULDER)) ? 10 : 1; + + var moveKeysP = [FlxG.keys.justPressed.LEFT, FlxG.keys.justPressed.RIGHT, FlxG.keys.justPressed.UP, FlxG.keys.justPressed.DOWN]; + if(moveKeysP.contains(true)) { - config.animations[curAnim].offsets[1] += multiplier; - splash(); + config.animations[curAnim].offsets[0] += ((moveKeysP[0] ? 1 : 0) - (moveKeysP[1] ? 1 : 0)) * multiplier; + config.animations[curAnim].offsets[1] += ((moveKeysP[2] ? 1 : 0) - (moveKeysP[3] ? 1 : 0)) * multiplier; + changedOffset = true; } - else if (FlxG.keys.justPressed.DOWN) + + var moveKeys = [FlxG.keys.pressed.LEFT, FlxG.keys.pressed.RIGHT, FlxG.keys.pressed.UP, FlxG.keys.pressed.DOWN]; + if(moveKeys.contains(true)) { - config.animations[curAnim].offsets[1] -= multiplier; - splash(); + holdingArrowsTime += elapsed; + if(holdingArrowsTime > 0.6) + { + holdingArrowsElapsed += elapsed; + while(holdingArrowsElapsed > (1/60)) + { + config.animations[curAnim].offsets[0] += ((moveKeys[0] ? 1 : 0) - (moveKeys[1] ? 1 : 0)) * multiplier; + config.animations[curAnim].offsets[1] += ((moveKeys[2] ? 1 : 0) - (moveKeys[3] ? 1 : 0)) * multiplier; + holdingArrowsElapsed -= (1/60); + changedOffset = true; + } + } } + else holdingArrowsTime = 0; + + if(changedOffset || FlxG.keys.justPressed.SPACE) splash(); } if (!blockInput) @@ -617,14 +625,17 @@ class NoteSplashEditorState extends MusicBeatState var anims:Int = 0; var datas:Int = 0; var animArray:Array = []; + while (true) { var data:Int = strum.ID % 4 + (datas * 4); if (!splash.noteDataMap.exists(data) || !splash.animation.exists(splash.noteDataMap[data])) break; + datas++; anims++; } + if (anims > 1) { for (i in 0...anims) @@ -649,10 +660,7 @@ class NoteSplashEditorState extends MusicBeatState splashes.add(splash); } } - else - { - strum.playAnim('static'); - } + else strum.playAnim('static'); }); } else @@ -667,8 +675,7 @@ class NoteSplashEditorState extends MusicBeatState var splash:NoteSplash = new NoteSplash(imageSkin); splash.alpha = 1; splash.config = config; - if (noteData < 0) - noteData = 0; + if (noteData < 0) noteData = 0; if (name != null && splash.animation.exists(name) && noteData > -1) { @@ -701,8 +708,7 @@ class NoteSplashEditorState extends MusicBeatState if (config.rgb != null) for (i in 0...config.rgb.length) { - if (i > 2) - break; + if (i > 2) break; var rgb = config.rgb[i]; if (rgb == null) @@ -888,12 +894,10 @@ class NoteSplashEditorState extends MusicBeatState { super.destroy(); - var FlxG = FlxG.sound; - - FlxG.music.volume = 1; - FlxG.muteKeys = [FlxKey.ZERO]; - FlxG.volumeDownKeys = [FlxKey.NUMPADMINUS, FlxKey.MINUS]; - FlxG.volumeUpKeys = [FlxKey.NUMPADPLUS, FlxKey.PLUS]; + FlxG.sound.music.volume = 1; + FlxG.sound.muteKeys = [FlxKey.ZERO]; + FlxG.sound.volumeDownKeys = [FlxKey.NUMPADMINUS, FlxKey.MINUS]; + FlxG.sound.volumeUpKeys = [FlxKey.NUMPADPLUS, FlxKey.PLUS]; } public static function parseTxt(content:String):NoteSplashConfig @@ -901,32 +905,28 @@ class NoteSplashEditorState extends MusicBeatState var config = NoteSplash.createConfig(); if (content == null) return config; + var trim:String = content.trim(); if (trim.length < 1) // empty txt return config; var configs = content.split('\n'); // checks for empty txts - if (configs.length < 2) - return config; - if (configs[0].trim() == "") + if (configs.length < 2 || configs[0].trim() == "") return config; var animation:String = configs[0].rtrim(); - var minFps:Null = 24; - var maxFps:Null = 24; + var fps:Array> = [22, 26]; if (configs[1] != null && configs[1].trim() != "") { - var fps = configs[1].trim().split(" "); - minFps = Std.parseInt(fps[0]); - maxFps = Std.parseInt(fps[1]); - if (minFps == null) - minFps = 24; - if (maxFps == null) - maxFps = 24; + var newFps = configs[1].trim().split(" "); + fps = [Std.parseInt(newFps[0]), Std.parseInt(newFps[1])]; + if (fps[0] == null) fps[0] = 22; + if (fps[1] == null) fps[1] = 26; } + var hasOneOffset = false; - var offsets = [[0, 0]]; + var offsets:Array>> = [[0, 0]]; if (configs.length == 3 || configs.length == 2) { hasOneOffset = true; @@ -936,14 +936,11 @@ class NoteSplashEditorState extends MusicBeatState var offset = configs[2].trim(); if (offset != "") { - var offset = offset.split(" "); - var x = Std.parseInt(offset[0]); - var y = Std.parseInt(offset[1]); - if (x == null) - x = 0; - if (y == null) - y = 0; - + var offset:Array = offset.split(" "); + var x:Null = Std.parseFloat(offset[0]); + var y:Null = Std.parseFloat(offset[1]); + if (x == null) x = 0; + if (y == null) y = 0; offsets.push([x, y]); } } @@ -957,17 +954,15 @@ class NoteSplashEditorState extends MusicBeatState var offset = configs[i].trim(); if (offset != "") { - var offset = offset.split(" "); - var x = Std.parseInt(offset[0]); - var y = Std.parseInt(offset[1]); - if (x == null) - x = 0; - if (y == null) - y = 0; - + var offset:Array = offset.split(" "); + var x:Null = Std.parseFloat(offset[0]); + var y:Null = Std.parseFloat(offset[1]); + if (x == null) x = 0; + if (y == null) y = 0; offsets.push([x, y]); } i++; + if (i + 1 > configs.length) break; } @@ -978,8 +973,10 @@ class NoteSplashEditorState extends MusicBeatState var offset = offsets[hasOneOffset ? 0 : i]; if (i + 1 > configs.length && !hasOneOffset) break; - config = NoteSplash.addAnimationToConfig([1, 1], config, Note.colArray[i], '$animation ${Note.colArray[i]} 10', minFps, maxFps, offset, [], i); + + config = NoteSplash.addAnimationToConfig(config, 1, Note.colArray[i], '$animation ${Note.colArray[i]} 10', fps, offset, [], i); } + if (offsets.length > 4) { for (i in 0...Note.colArray.length) @@ -987,7 +984,8 @@ class NoteSplashEditorState extends MusicBeatState var offset = offsets[i + 4]; if (i + 1 > offsets.length) break; - config = NoteSplash.addAnimationToConfig([1, 1], config, Note.colArray[i] + "2", '$animation ${Note.colArray[i]} 20', minFps, maxFps, offset, [], i + 4); + + config = NoteSplash.addAnimationToConfig(config, 1, Note.colArray[i] + "2", '$animation ${Note.colArray[i]} 20', fps, offset, [], i + 4); } } @@ -1006,21 +1004,40 @@ class NoteSplashEditorHelpSubState extends MusicBeatSubstate bg.alpha = 0.6; add(bg); - var text:FlxText = new FlxText(); - text.setFormat(null, 32, FlxColor.WHITE, CENTER, OUTLINE_FAST, FlxColor.BLACK); - text.text = "CLICK on strums to SPLASH them"; - text.text += "\n\nARROW KEYS - Move Offset"; - text.text += "\nHOLD SHIFT - Move Offset 10x faster"; - text.text += "\n\nCTRL C/V - Copy or Paste Offsets"; - text.screenCenter(); + var str:Array = ["Click on a Strum or Press Space", + "to spawn a Splash", + "", + "Arrow Keys - Move Offset", + "Hold Shift - Move Offsets 10x faster", + "", + "", + "Ctrl + C - Copy Current Offset", + "Ctrl + V - Paste Copied Offset on Current Splash", + "Ctrl + R - Reset Current Offset"]; + + var helpTexts:FlxSpriteGroup = new FlxSpriteGroup(); + for (i => txt in str) + { + if(txt.length < 1) continue; + + var helpText:FlxText = new FlxText(0, 0, 0, txt, 32); + helpText.setFormat(null, 32, FlxColor.WHITE, CENTER, OUTLINE_FAST, FlxColor.BLACK); + helpText.borderColor = FlxColor.BLACK; + helpText.scrollFactor.set(); + helpText.borderSize = 1; + helpText.screenCenter(); + add(helpText); + helpText.y += ((i - str.length/2) * 32) + 16; + helpTexts.add(helpText); + } + add(helpTexts); var noteDataText:FlxText = new FlxText(); noteDataText.setFormat(null, 32, FlxColor.WHITE, RIGHT, OUTLINE_FAST, FlxColor.BLACK); noteDataText.text = "NOTE DATAS:\nLEFT: 0 and 4\nDOWN: 1 and 5\nUP: 2 and 6\nRIGHT: 3 and 7"; noteDataText.x = FlxG.width - noteDataText.width - 5; noteDataText.y = FlxG.height - noteDataText.height - 5; - - add(text); + add(noteDataText); } diff --git a/source/states/editors/StageEditorState.hx b/source/states/editors/StageEditorState.hx index 0b69838a003..0598c20edfa 100644 --- a/source/states/editors/StageEditorState.hx +++ b/source/states/editors/StageEditorState.hx @@ -1668,42 +1668,46 @@ class StageEditorState extends MusicBeatState implements PsychUIEventHandler.Psy { fullPath = fullPath.replace('\\', '/'); var exePath = Sys.getCwd().replace('\\', '/'); - if(fullPath.startsWith(exePath + 'assets/images/') #if MODS_ALLOWED || (fullPath.startsWith(exePath + 'mods/') && fullPath.contains('/images/')) #end) + if(fullPath.startsWith(exePath)) { - - var imageToLoad:String = fullPath.substring(fullPath.indexOf('/images/') + '/images/'.length, fullPath.indexOf('.')); - if(_makeNewSprite != null) + fullPath = fullPath.substr(exePath.length); + if((fullPath.startsWith('assets/') #if MODS_ALLOWED || fullPath.startsWith('mods/') #end) && fullPath.contains('/images/')) { - if(_makeNewSprite == 'animatedSprite' && !Paths.fileExists('images/$imageToLoad.xml', TEXT) && - !Paths.fileExists('images/$imageToLoad.json', TEXT) && !Paths.fileExists('images/$imageToLoad.txt', TEXT)) + var imageToLoad:String = fullPath.substring(fullPath.indexOf('/images/') + '/images/'.length, fullPath.lastIndexOf('.')); + if(_makeNewSprite != null) { - showOutput('No Animation file found with the same name of the image!', true); - _makeNewSprite = null; - _file = null; - return; + if(_makeNewSprite == 'animatedSprite' && !Paths.fileExists('images/$imageToLoad.xml', TEXT) && + !Paths.fileExists('images/$imageToLoad.json', TEXT) && !Paths.fileExists('images/$imageToLoad.txt', TEXT)) + { + showOutput('No Animation file found with the same name of the image!', true); + _makeNewSprite = null; + _file = null; + return; + } + insertMeta(new StageEditorMetaSprite({type: _makeNewSprite, name: findUnoccupiedName()}, new ModchartSprite())); } - insertMeta(new StageEditorMetaSprite({type: _makeNewSprite, name: findUnoccupiedName()}, new ModchartSprite())); - } - var selected = getSelected(); - tryLoadImage(selected, imageToLoad); - - if(_makeNewSprite != null) - { - selected.sprite.x = Math.round(FlxG.camera.scroll.x + FlxG.width/2 - selected.sprite.width/2); - selected.sprite.y = Math.round(FlxG.camera.scroll.y + FlxG.height/2 - selected.sprite.height/2); - posTxt.visible = true; - posTxt.text = 'X: ${selected.sprite.x}\nY: ${selected.sprite.y}'; + var selected = getSelected(); + tryLoadImage(selected, imageToLoad); + + if(_makeNewSprite != null) + { + selected.sprite.x = Math.round(FlxG.camera.scroll.x + FlxG.width/2 - selected.sprite.width/2); + selected.sprite.y = Math.round(FlxG.camera.scroll.y + FlxG.height/2 - selected.sprite.height/2); + posTxt.visible = true; + posTxt.text = 'X: ${selected.sprite.x}\nY: ${selected.sprite.y}'; + } + _makeNewSprite = null; + //trace('Inside Psych Engine Folder'); } - _makeNewSprite = null; - //trace('Inside Psych Engine Folder'); + else showOutput('Can\'t load files outside of "images/" folder', true); } - else showOutput('Can\'t load files outside of "images/" folder', true); + else showOutput('Can\'t load files outside of Psych Engine\'s folder', true); //TO DO: Maybe make copy of loaded file to an usable folder automatically? That would be very practical //TO DO: Bring this to Character Editor too } _file = null; #else - trace('File couldn't be loaded! You aren't on Desktop, are you?'); + trace('File couldn\'t be loaded! You aren\'t on Desktop, are you?'); #end } @@ -2324,4 +2328,4 @@ class StageEditorAnimationSubstate extends MusicBeatSubstate { close(); } } -} \ No newline at end of file +} diff --git a/source/states/editors/WeekEditorState.hx b/source/states/editors/WeekEditorState.hx index c3312998e35..a3623350982 100644 --- a/source/states/editors/WeekEditorState.hx +++ b/source/states/editors/WeekEditorState.hx @@ -40,7 +40,7 @@ class WeekEditorState extends MusicBeatState implements PsychUIEventHandler.Psyc override function create() { txtWeekTitle = new FlxText(FlxG.width * 0.7, 10, 0, "", 32); - txtWeekTitle.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, RIGHT); + txtWeekTitle.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, RIGHT); txtWeekTitle.alpha = 0.7; var ui_tex = Paths.getSparrowAtlas('campaign_menu_UI_assets'); diff --git a/source/states/editors/content/EditorPlayState.hx b/source/states/editors/content/EditorPlayState.hx index 69b76384ae7..a69582fe7d8 100644 --- a/source/states/editors/content/EditorPlayState.hx +++ b/source/states/editors/content/EditorPlayState.hx @@ -317,7 +317,7 @@ class EditorPlayState extends MusicBeatSubstate if (idx != 0) { // CLEAR ANY POSSIBLE GHOST NOTES for (evilNote in unspawnNotes) { - var matches: Bool = note.noteData == evilNote.noteData && note.mustPress == evilNote.mustPress; + var matches: Bool = note.noteData == evilNote.noteData && note.mustPress == evilNote.mustPress && note.noteType == evilNote.noteType; if (matches && Math.abs(note.strumTime - evilNote.strumTime) == 0.0) { evilNote.destroy(); unspawnNotes.remove(evilNote); @@ -334,7 +334,7 @@ class EditorPlayState extends MusicBeatSubstate swagNote.scrollFactor.set(); unspawnNotes.push(swagNote); - var roundSus:Int = Math.floor(swagNote.sustainLength / Conductor.stepCrochet); + final roundSus:Int = Math.floor(swagNote.sustainLength / Conductor.stepCrochet); if(roundSus > 0) { for (susNote in 0...roundSus + 1) diff --git a/source/states/editors/content/MetaNote.hx b/source/states/editors/content/MetaNote.hx index 09cf3905cbf..2f3a0d467b5 100644 --- a/source/states/editors/content/MetaNote.hx +++ b/source/states/editors/content/MetaNote.hx @@ -11,18 +11,22 @@ class MetaNote extends Note public var songData:Array; public var sustainSprite:FlxSprite; public var chartY:Float = 0; + public var chartNoteData:Int = 0; public function new(time:Float, data:Int, songData:Array) { super(time, data, null, false, true); this.songData = songData; this.strumTime = time; + this.chartNoteData = data; } public function changeNoteData(v:Int) { + this.chartNoteData = v; //despite being so arbitrary its sadly needed to fix a bug on moving notes this.songData[1] = v; this.noteData = v % ChartingState.GRID_COLUMNS_PER_PLAYER; + this.mustPress = (v < ChartingState.GRID_COLUMNS_PER_PLAYER); if(!PlayState.isPixelStage) loadNoteAnims(); diff --git a/source/states/editors/content/VSlice.hx b/source/states/editors/content/VSlice.hx index 90a80b2ec20..111ab1df209 100644 --- a/source/states/editors/content/VSlice.hx +++ b/source/states/editors/content/VSlice.hx @@ -331,10 +331,10 @@ class VSlice var notes:Array = []; var generatedBy:String = 'Psych Engine v${MainMenuState.psychEngineVersion} - Chart Editor V-Slice Exporter'; var timeChanges:Array = []; - + var time:Float = 0; var bpm:Float = songData.bpm; - + timeChanges.push({t: 0, bpm: bpm}); //so there was first bpm issue (if the song has multiplier bpm) var lastMustHit:Bool = false; if(songData.notes != null) { @@ -376,9 +376,7 @@ class VSlice } events.sort(sortByTime); notes.sort(sortByTime); - - if(timeChanges.length < 1) timeChanges.push({t: 0, bpm: bpm}); //failsafe - + //try to find composer despite it not being a value on psych charts var composer:String = 'Unknown'; if(Reflect.hasField(songData, 'artist')) composer = Reflect.field(songData, 'artist'); @@ -445,7 +443,7 @@ class VSlice difficulties: diffs, characters: { player: songData.player1, - girlfriend: songData.gfVersion != null ? songData.gfVersion : 'gf', + girlfriend: songData.gfVersion != null ? songData.gfVersion : '', //there is no problem if gf don't exist with it opponent: songData.player2 }, noteStyle: !PlayState.isPixelStage ? 'funkin' : 'pixel', @@ -470,4 +468,4 @@ class VSlice static function sortByTime(Obj1:Dynamic, Obj2:Dynamic):Int return FlxSort.byValues(FlxSort.ASCENDING, Obj1.t, Obj2.t); -} \ No newline at end of file +} diff --git a/source/states/stages/PhillyBlazin.hx b/source/states/stages/PhillyBlazin.hx index 41e031ed81b..7a45d939284 100644 --- a/source/states/stages/PhillyBlazin.hx +++ b/source/states/stages/PhillyBlazin.hx @@ -167,8 +167,7 @@ class PhillyBlazin extends BaseStage { for (i in 1...4) { - //trace('Lightning$i'); - Paths.sound('Lightning$i'); + Paths.sound('lightning/Lightning$i'); } } @@ -231,7 +230,7 @@ class PhillyBlazin extends BaseStage FlxTween.color(abot, LIGHTNING_FADE_DURATION, 0xFF606060, 0xFF888888); // Sound - FlxG.sound.play(Paths.soundRandom('Lightning', 1, 3)); + FlxG.sound.play(Paths.soundRandom('lightning/Lightning', 1, 3)); } // Note functions diff --git a/source/states/stages/PhillyStreets.hx b/source/states/stages/PhillyStreets.hx index df60ab21f04..2514e300212 100644 --- a/source/states/stages/PhillyStreets.hx +++ b/source/states/stages/PhillyStreets.hx @@ -323,8 +323,9 @@ class PhillyStreets extends BaseStage cutsceneHandler.timer(cutsceneDelay + 5.1, function() //pico fires at can { boyfriend.playAnim('intro2', true); + boyfriend.specialAnim = true; - FlxG.sound.play(Paths.soundRandom('shot', 1, 4)); + FlxG.sound.play(Paths.soundRandom('shots/shot', 1, 4)); FlxTween.tween(FlxG.camera.scroll, {x: camFollow.x + 100 - FlxG.width/2}, 2.5, {ease: FlxEase.quadInOut}); @@ -491,7 +492,7 @@ class PhillyStreets extends BaseStage } for (i in 1...5) - Paths.sound('shot$i'); + Paths.sound('shots/shot$i'); } function setupRainShader() @@ -833,7 +834,7 @@ class PhillyStreets extends BaseStage boyfriend.holdTimer = 0; boyfriend.playAnim('shoot', true); boyfriend.specialAnim = true; - FlxG.sound.play(Paths.soundRandom('shot', 1, 4)); + FlxG.sound.play(Paths.soundRandom('shots/shot', 1, 4)); spraycan.playCanShot(); new FlxTimer().start(1/24, function(tmr) diff --git a/source/states/stages/objects/ABotSpeaker.hx b/source/states/stages/objects/ABotSpeaker.hx index 0b3eb1d222a..eefa6488835 100644 --- a/source/states/stages/objects/ABotSpeaker.hx +++ b/source/states/stages/objects/ABotSpeaker.hx @@ -1,6 +1,8 @@ package states.stages.objects; -import backend.SpectralAnalyzerEx; +#if funkin.vis +import funkin.vis.dsp.SpectralAnalyzer; +#end class ABotSpeaker extends FlxSpriteGroup { @@ -14,14 +16,18 @@ class ABotSpeaker extends FlxSpriteGroup public var eyes:FlxAnimate; public var speaker:FlxAnimate; - var analyzer:SpectralAnalyzerEx; + #if funkin.vis + var analyzer:SpectralAnalyzer; + #end var volumes:Array = []; public var snd(default, set):FlxSound; function set_snd(changed:FlxSound) { snd = changed; + #if funkin.vis initAnalyzer(); + #end return snd; } @@ -77,14 +83,15 @@ class ABotSpeaker extends FlxSpriteGroup add(speaker); } + #if funkin.vis + var levels:Array; var levelMax:Int = 0; override function update(elapsed:Float):Void { super.update(elapsed); if(analyzer == null) return; - //var levels = analyzer.getLevels(); //this has a memory leak, so i made my own function for it - var levels = analyzer.recycledLevels(); + levels = analyzer.getLevels(levels); var oldLevelMax = levelMax; levelMax = 0; for (i in 0...Std.int(Math.min(vizSprites.length, levels.length))) @@ -103,16 +110,18 @@ class ABotSpeaker extends FlxSpriteGroup beatHit(); } } + #end public function beatHit() { speaker.anim.play('anim', true); } + #if funkin.vis public function initAnalyzer() { @:privateAccess - analyzer = new SpectralAnalyzerEx(snd._channel.__audioSource, 7, 0.1, 40); + analyzer = new SpectralAnalyzer(snd._channel.__audioSource, 7, 0.1, 40); #if desktop // On desktop it uses FFT stuff that isn't as optimized as the direct browser stuff we use on HTML5 @@ -120,6 +129,7 @@ class ABotSpeaker extends FlxSpriteGroup analyzer.fftN = 256; #end } + #end var lookingAtRight:Bool = true; public function lookLeft() diff --git a/source/substates/GameOverSubstate.hx b/source/substates/GameOverSubstate.hx index 08544795598..b4f870815ed 100644 --- a/source/substates/GameOverSubstate.hx +++ b/source/substates/GameOverSubstate.hx @@ -84,7 +84,7 @@ class GameOverSubstate extends MusicBeatSubstate PlayState.instance.setOnScripts('inGameOver', true); PlayState.instance.callOnScripts('onGameOverStart', []); - FlxG.sound.music.loadEmbedded(Paths.music(loopSoundName)); + FlxG.sound.music.loadEmbedded(Paths.music(loopSoundName), true); if(characterName == 'pico-dead') { diff --git a/source/substates/PauseSubState.hx b/source/substates/PauseSubState.hx index e033deb4bb2..c817b37c199 100644 --- a/source/substates/PauseSubState.hx +++ b/source/substates/PauseSubState.hx @@ -171,6 +171,14 @@ class PauseSubState extends MusicBeatSubstate return; } + if(FlxG.keys.justPressed.F5) + { + FlxTransitionableState.skipNextTransIn = true; + FlxTransitionableState.skipNextTransOut = true; + PlayState.nextReloadAll = true; + MusicBeatState.resetState(); + } + updateSkipTextStuff(); if (controls.UI_UP_P) {