diff --git a/CMakeLists.txt b/CMakeLists.txt index 2818a23..7195497 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,15 @@ set(CMAKE_CXX_VISIBILITY_PRESET hidden) project(EndscreenTweaks VERSION 1.0.0) add_library(${PROJECT_NAME} SHARED + src/PlayLayer.cpp + src/CCScheduler.cpp + src/EndLevelLayer.cpp + src/CurrencyRewardLayer.cpp src/main.cpp src/Settings.cpp src/Settings.hpp + src/Manager.cpp + src/Manager.hpp # Add your cpp files here ) diff --git a/mod.json b/mod.json index e8615b4..0cc5e68 100644 --- a/mod.json +++ b/mod.json @@ -1,11 +1,11 @@ { - "geode": "4.0.0-beta.1", + "geode": "4.0.1", "gd": { "mac": "2.2074", "android": "2.2074", "win": "2.2074" }, - "version": "v1.4.2", + "version": "v1.4.3", "id": "raydeeux.endscreentweaks", "name": "EndscreenTweaks", "developers": ["RayDeeUx", "sofabeddd", "Relative"], @@ -31,13 +31,13 @@ "default": true }, "custom": { - "name": "Include Custom Messages", + "name": "Include Custom Endscreen Texts", "description": "[REQUIRES RESTART TO APPLY]\n\nIncludes your own custom \"Level Complete\" text.\nPlease edit the \"custom.txt\" file by opening this mod's config directory (look for the golden pencil button at the bottom left of the mod's introductory screen).", "type": "bool", "default": false }, "customTextsOnly": { - "name": "Only Use Custom Messages", + "name": "Only Use Custom Endscreen Texts", "description": "REQUIRES GAME RESTART TO APPLY.\n\nOnly uses your own custom \"New Best\" texts from \"custom.txt\" file.\n\nIf no custom quotes are found, the mod will fall back to the default set of quotes.\n\nEnabling this setting will override the \"Include Technoblade\" setting if you have written your own custom quotes.", "type": "bool", "default": false @@ -49,7 +49,7 @@ "default": false }, "maxScale": { - "name": "End Text Max Scale", + "name": "Endscreen Text Max Scale", "description": "Sets the max scale of all end text messages.", "type": "float", "default": 0.5, @@ -60,7 +60,7 @@ } }, "customFont": { - "name": "Endtext Font #", + "name": "Endscreen Text Font #", "description": "Sets the font of all end text messages. Default is 0 (falls back to bigFont, as seen in vanilla Geometry Dash).\n\nNotes:\n- -1 for Golden Pusab, -2 for chatFont.\n- To use font numbers greater than 0: refer to the level editor for the font each number corresponds to, subtract that number by 1, and then put it here.", "type": "int", "default": 0, @@ -76,6 +76,40 @@ "slider-step": 1 } }, + "customLevelCompleteText" : { + "name": "Enable Custom \"Level Complete\" Text", + "description": "Original idea by Saritahh.\n\nReplaces the original \"Level Complete\" text when completing a level with *either* custom text with Oxygene One (the font used in the original \"Level Complete\" font), or an image of your choice (selected from this mod's config directory).", + "type": "bool", + "default": false + }, + "customLCTMode" : { + "name": "Custom \"Level Complete\" Text Mode", + "description": "Original idea by Saritahh.\n\nChoose your preferred type of custom \"Level Complete\" replacement.\n\n\"Oxygene One\": The text is replaced with custom quotes using the Oxygene One font.\n\"Images\": The text is replaced with images from this mod's config directory.\n\"Combined\": The text is replaced with either \"Oxygene One\" texts or a random image from this mod's config directory.\n\nIf no images are found, the mod will fall back to the original \"Level Complete!\" sprite from vanilla GD (or loaded texture packs).", + "type": "string", + "default": "Oxygene One", + "one-of": [ + "Oxygene One", + "Images", + "Combined" + ] + }, + "alsoReplacePlayLayerLCT" : { + "name": "Also Replace \"Level Complete\" in PlayLayer", + "description": "Original idea by Saritahh.\n\nChoose whether the \"Level Complete\" text in PlayLayer:\n\n- remains untouched, using the Disabled option\n- matches the \"Level Complete\" text replacement on your endscreen, using the Match EndLevelLayer option\n- is different from the \"Level Complete\" text replacement on your endscreen, using the Separate From EndLevelLayer option", + "type": "string", + "default": "Disabled", + "one-of": [ + "Disabled", + "Match EndLevelLayer", + "Separate From EndLevelLayer" + ] + }, + "customLevelCompleteTextsOnly": { + "name": "Only Use Custom \"Level Complete\" Texts", + "description": "REQUIRES GAME RESTART TO APPLY.\n\nOnly uses your own custom \"Level Complete\" texts from \"customLevelCompleteQuotes.txt\" file when using a custom \"Level Complete\" text in the \"Oxygene One\".\n\nIf no custom quotes are found, the mod will fall back to the default set of quotes.", + "type": "bool", + "default": false + }, "platAttemptsAndJumps": { "name": "Plat. Attempts + Jumps", "description": "Shows your attempt and jump count on the \"Level Complete\" screen when completing Platformer levels.", @@ -145,7 +179,9 @@ }, "resources": { "files": [ - "resources/*.txt" + "resources/*.txt", + "resources/*.fnt", + "resources/*.png" ], "sprites": [ "resources/btn.png" @@ -154,7 +190,7 @@ "dependencies": [ { "id": "geode.node-ids", - "version": ">=1.13.1", + "version": ">=1.17.0", "importance": "required" } ], diff --git a/resources/default.txt b/resources/default.txt index 74f5bb8..efa7082 100644 --- a/resources/default.txt +++ b/resources/default.txt @@ -17,4 +17,4 @@ BELIEVE As the man once said, the harder you work, the luckier you get. this endscreen only stares at beautiful people Congratulations. You've cooked, ate, left no crumbs, and popped off. -trans rights are human rights (this end text is from a geode mod) \ No newline at end of file +trans rights are human rights \ No newline at end of file diff --git a/resources/defaultLevelComplete.txt b/resources/defaultLevelComplete.txt new file mode 100644 index 0000000..10b679b --- /dev/null +++ b/resources/defaultLevelComplete.txt @@ -0,0 +1,20 @@ +GG +PRACTICE COMPLETE! +BETTER THAN SPACEUK! +THINGS ARE HAPPENING HERE. +CBF DETECTED, LOSER! +SKILL ISSUE OVERCOME...? +LEVEL COMPELTE! +MAP FINISH. +CREASHAKS ORGANZINE +SPONSORED BY YOUR LOCAL MOD MENU +GEOMTREY DASH +I THINK OBS CRASHED? +GO AT 47% IMO +OK COOL NOW GET A JOB. +FINISH YOUR HOMEWORK! +WORTH $6 OF AD REVENUE +THAT WAS JUST THE TUTORIAL +SAPPHIRE SDK CLEAR +DON'T FORGET TO UNDEAFEN +CHAPTER COMPLETE \ No newline at end of file diff --git a/resources/levelCompleteFont-hd.fnt b/resources/levelCompleteFont-hd.fnt new file mode 100644 index 0000000..7ff0b8a --- /dev/null +++ b/resources/levelCompleteFont-hd.fnt @@ -0,0 +1,71 @@ +info font="Oxygene 1" size=72 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=4,4,4,4 spacing=4,4 +common lineHeight=72 base=58 scaleW=1024 scaleH=512 pages=1 packed=0 +page id=0 file="levelCompleteFont-hd.png" +chars count=67 +char id=124 x=4 y=4 width=29 height=96 xoffset=14 yoffset=-12 xadvance=16 page=0 chnl=0 letter="|" +char id=93 x=37 y=4 width=48 height=88 xoffset=8 yoffset=-8 xadvance=30 page=0 chnl=0 letter="]" +char id=40 x=89 y=4 width=56 height=88 xoffset=8 yoffset=-8 xadvance=36 page=0 chnl=0 letter="(" +char id=41 x=149 y=4 width=56 height=88 xoffset=8 yoffset=-8 xadvance=36 page=0 chnl=0 letter=")" +char id=91 x=209 y=4 width=48 height=88 xoffset=8 yoffset=-8 xadvance=28 page=0 chnl=0 letter="[" +char id=80 x=261 y=4 width=64 height=80 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="P" +char id=75 x=329 y=4 width=64 height=80 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="K" +char id=68 x=397 y=4 width=72 height=80 xoffset=8 yoffset=-8 xadvance=53 page=0 chnl=0 letter="D" +char id=65 x=473 y=4 width=64 height=80 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="A" +char id=66 x=541 y=4 width=64 height=80 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="B" +char id=89 x=609 y=4 width=64 height=80 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="Y" +char id=36 x=677 y=4 width=64 height=80 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="$" +char id=92 x=745 y=4 width=72 height=80 xoffset=8 yoffset=-8 xadvance=50 page=0 chnl=0 letter="\" +char id=63 x=821 y=4 width=64 height=80 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="?" +char id=64 x=889 y=4 width=88 height=80 xoffset=8 yoffset=-8 xadvance=68 page=0 chnl=0 letter="@" +char id=77 x=4 y=104 width=88 height=80 xoffset=8 yoffset=-8 xadvance=69 page=0 chnl=0 letter="M" +char id=51 x=96 y=104 width=64 height=80 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="3" +char id=82 x=164 y=104 width=64 height=80 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="R" +char id=52 x=232 y=104 width=72 height=80 xoffset=8 yoffset=-8 xadvance=52 page=0 chnl=0 letter="4" +char id=35 x=308 y=104 width=80 height=80 xoffset=8 yoffset=-8 xadvance=60 page=0 chnl=0 letter="#" +char id=33 x=392 y=104 width=48 height=80 xoffset=8 yoffset=-8 xadvance=29 page=0 chnl=0 letter="!" +char id=54 x=444 y=104 width=64 height=80 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="6" +char id=71 x=512 y=104 width=64 height=80 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="G" +char id=88 x=580 y=104 width=72 height=80 xoffset=8 yoffset=-8 xadvance=52 page=0 chnl=0 letter="X" +char id=57 x=656 y=104 width=64 height=80 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="9" +char id=81 x=724 y=104 width=72 height=80 xoffset=8 yoffset=-8 xadvance=53 page=0 chnl=0 letter="Q" +char id=79 x=800 y=104 width=72 height=72 xoffset=8 yoffset=-8 xadvance=53 page=0 chnl=0 letter="O" +char id=83 x=876 y=104 width=64 height=72 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="S" +char id=85 x=944 y=104 width=64 height=72 xoffset=8 yoffset=-8 xadvance=46 page=0 chnl=0 letter="U" +char id=90 x=4 y=188 width=64 height=72 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="Z" +char id=78 x=72 y=188 width=72 height=72 xoffset=8 yoffset=-8 xadvance=52 page=0 chnl=0 letter="N" +char id=87 x=148 y=188 width=88 height=72 xoffset=8 yoffset=-8 xadvance=69 page=0 chnl=0 letter="W" +char id=86 x=240 y=188 width=64 height=72 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="V" +char id=76 x=308 y=188 width=48 height=72 xoffset=8 yoffset=-8 xadvance=28 page=0 chnl=0 letter="L" +char id=74 x=360 y=188 width=56 height=72 xoffset=8 yoffset=-8 xadvance=38 page=0 chnl=0 letter="J" +char id=73 x=420 y=188 width=40 height=72 xoffset=8 yoffset=-8 xadvance=22 page=0 chnl=0 letter="I" +char id=72 x=464 y=188 width=64 height=72 xoffset=8 yoffset=-8 xadvance=46 page=0 chnl=0 letter="H" +char id=84 x=532 y=188 width=64 height=72 xoffset=8 yoffset=-8 xadvance=43 page=0 chnl=0 letter="T" +char id=50 x=600 y=188 width=64 height=72 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="2" +char id=70 x=668 y=188 width=64 height=72 xoffset=8 yoffset=-8 xadvance=43 page=0 chnl=0 letter="F" +char id=49 x=736 y=188 width=48 height=72 xoffset=8 yoffset=-8 xadvance=30 page=0 chnl=0 letter="1" +char id=69 x=788 y=188 width=64 height=72 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="E" +char id=38 x=856 y=188 width=64 height=72 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="&" +char id=37 x=924 y=188 width=64 height=72 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="%" +char id=67 x=4 y=264 width=64 height=72 xoffset=8 yoffset=-8 xadvance=43 page=0 chnl=0 letter="C" +char id=53 x=72 y=264 width=64 height=72 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="5" +char id=48 x=140 y=264 width=64 height=72 xoffset=8 yoffset=-8 xadvance=45 page=0 chnl=0 letter="0" +char id=55 x=208 y=264 width=64 height=72 xoffset=8 yoffset=-8 xadvance=44 page=0 chnl=0 letter="7" +char id=47 x=276 y=264 width=64 height=72 xoffset=8 yoffset=-8 xadvance=43 page=0 chnl=0 letter="/" +char id=59 x=344 y=264 width=40 height=72 xoffset=8 yoffset=0 xadvance=21 page=0 chnl=0 letter=";" +char id=56 x=388 y=264 width=72 height=72 xoffset=8 yoffset=-8 xadvance=53 page=0 chnl=0 letter="8" +char id=60 x=464 y=264 width=56 height=64 xoffset=8 yoffset=0 xadvance=37 page=0 chnl=0 letter="<" +char id=62 x=524 y=264 width=56 height=64 xoffset=8 yoffset=0 xadvance=36 page=0 chnl=0 letter=">" +char id=58 x=584 y=264 width=40 height=64 xoffset=8 yoffset=0 xadvance=21 page=0 chnl=0 letter=":" +char id=94 x=628 y=264 width=61 height=57 xoffset=13 yoffset=-8 xadvance=48 page=0 chnl=0 letter="^" +char id=0 x=693 y=264 width=50 height=50 xoffset=13 yoffset=2 xadvance=36 page=0 chnl=0 letter="•" +char id=44 x=747 y=264 width=40 height=48 xoffset=8 yoffset=31 xadvance=22 page=0 chnl=0 letter="," +char id=43 x=791 y=264 width=48 height=48 xoffset=8 yoffset=7 xadvance=29 page=0 chnl=0 letter="+" +char id=61 x=843 y=264 width=48 height=48 xoffset=8 yoffset=7 xadvance=28 page=0 chnl=0 letter="=" +char id=39 x=895 y=264 width=32 height=40 xoffset=8 yoffset=-8 xadvance=14 page=0 chnl=0 letter="'" +char id=126 x=931 y=264 width=64 height=40 xoffset=8 yoffset=-8 xadvance=46 page=0 chnl=0 letter="~" +char id=46 x=4 y=340 width=40 height=40 xoffset=8 yoffset=31 xadvance=22 page=0 chnl=0 letter="." +char id=96 x=48 y=340 width=38 height=35 xoffset=11 yoffset=-9 xadvance=24 page=0 chnl=0 letter="`" +char id=45 x=90 y=340 width=48 height=32 xoffset=8 yoffset=15 xadvance=30 page=0 chnl=0 letter="-" +char id=95 x=142 y=340 width=60 height=28 xoffset=8 yoffset=46 xadvance=36 page=0 chnl=0 letter="_" +char id=32 x=206 y=340 width=24 height=24 xoffset=8 yoffset=41 xadvance=46 page=0 chnl=0 letter=" " +kernings count=0 \ No newline at end of file diff --git a/resources/levelCompleteFont-hd.png b/resources/levelCompleteFont-hd.png new file mode 100644 index 0000000..b69d56b Binary files /dev/null and b/resources/levelCompleteFont-hd.png differ diff --git a/resources/levelCompleteFont-uhd.fnt b/resources/levelCompleteFont-uhd.fnt new file mode 100644 index 0000000..955258e --- /dev/null +++ b/resources/levelCompleteFont-uhd.fnt @@ -0,0 +1,71 @@ +info font="Oxygene 1" size=144 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=4,4,4,4 spacing=4,4 +common lineHeight=145 base=116 scaleW=1024 scaleH=1024 pages=1 packed=0 +page id=0 file="levelCompleteFont-uhd.png" +chars count=67 +char id=124 x=4 y=4 width=38 height=173 xoffset=22 yoffset=-11 xadvance=32 page=0 chnl=0 letter="|" +char id=41 x=46 y=4 width=93 height=157 xoffset=10 yoffset=-3 xadvance=72 page=0 chnl=0 letter=")" +char id=91 x=143 y=4 width=77 height=157 xoffset=10 yoffset=-3 xadvance=57 page=0 chnl=0 letter="[" +char id=40 x=224 y=4 width=93 height=157 xoffset=10 yoffset=-3 xadvance=72 page=0 chnl=0 letter="(" +char id=93 x=321 y=4 width=77 height=157 xoffset=10 yoffset=-3 xadvance=59 page=0 chnl=0 letter="]" +char id=52 x=402 y=4 width=125 height=141 xoffset=10 yoffset=-3 xadvance=105 page=0 chnl=0 letter="4" +char id=82 x=531 y=4 width=109 height=141 xoffset=10 yoffset=-3 xadvance=90 page=0 chnl=0 letter="R" +char id=51 x=644 y=4 width=109 height=141 xoffset=10 yoffset=-3 xadvance=90 page=0 chnl=0 letter="3" +char id=33 x=757 y=4 width=77 height=141 xoffset=10 yoffset=-3 xadvance=57 page=0 chnl=0 letter="!" +char id=88 x=838 y=4 width=125 height=141 xoffset=10 yoffset=-3 xadvance=105 page=0 chnl=0 letter="X" +char id=81 x=4 y=181 width=125 height=141 xoffset=10 yoffset=-3 xadvance=105 page=0 chnl=0 letter="Q" +char id=54 x=133 y=181 width=109 height=141 xoffset=10 yoffset=-3 xadvance=88 page=0 chnl=0 letter="6" +char id=57 x=246 y=181 width=109 height=141 xoffset=10 yoffset=-3 xadvance=91 page=0 chnl=0 letter="9" +char id=71 x=359 y=181 width=109 height=141 xoffset=10 yoffset=-3 xadvance=89 page=0 chnl=0 letter="G" +char id=77 x=472 y=181 width=157 height=141 xoffset=10 yoffset=-3 xadvance=139 page=0 chnl=0 letter="M" +char id=35 x=633 y=181 width=141 height=141 xoffset=10 yoffset=-3 xadvance=121 page=0 chnl=0 letter="#" +char id=65 x=778 y=181 width=109 height=141 xoffset=10 yoffset=-3 xadvance=90 page=0 chnl=0 letter="A" +char id=66 x=891 y=181 width=109 height=141 xoffset=10 yoffset=-3 xadvance=90 page=0 chnl=0 letter="B" +char id=68 x=4 y=326 width=125 height=141 xoffset=10 yoffset=-3 xadvance=106 page=0 chnl=0 letter="D" +char id=80 x=133 y=326 width=109 height=141 xoffset=10 yoffset=-3 xadvance=87 page=0 chnl=0 letter="P" +char id=75 x=246 y=326 width=109 height=141 xoffset=10 yoffset=-3 xadvance=90 page=0 chnl=0 letter="K" +char id=64 x=359 y=326 width=157 height=141 xoffset=10 yoffset=-3 xadvance=136 page=0 chnl=0 letter="@" +char id=92 x=520 y=326 width=125 height=141 xoffset=10 yoffset=-3 xadvance=101 page=0 chnl=0 letter="\" +char id=63 x=649 y=326 width=109 height=141 xoffset=10 yoffset=-3 xadvance=87 page=0 chnl=0 letter="?" +char id=36 x=762 y=326 width=109 height=141 xoffset=10 yoffset=-3 xadvance=88 page=0 chnl=0 letter="$" +char id=89 x=875 y=326 width=109 height=141 xoffset=10 yoffset=-3 xadvance=90 page=0 chnl=0 letter="Y" +char id=37 x=4 y=471 width=109 height=125 xoffset=10 yoffset=-3 xadvance=90 page=0 chnl=0 letter="%" +char id=38 x=117 y=471 width=109 height=125 xoffset=10 yoffset=-3 xadvance=89 page=0 chnl=0 letter="&" +char id=49 x=230 y=471 width=77 height=125 xoffset=10 yoffset=-3 xadvance=59 page=0 chnl=0 letter="1" +char id=67 x=311 y=471 width=109 height=125 xoffset=10 yoffset=-3 xadvance=87 page=0 chnl=0 letter="C" +char id=69 x=424 y=471 width=109 height=125 xoffset=10 yoffset=-3 xadvance=87 page=0 chnl=0 letter="E" +char id=48 x=537 y=471 width=109 height=125 xoffset=10 yoffset=-3 xadvance=90 page=0 chnl=0 letter="0" +char id=56 x=650 y=471 width=125 height=125 xoffset=10 yoffset=-3 xadvance=106 page=0 chnl=0 letter="8" +char id=53 x=779 y=471 width=109 height=125 xoffset=10 yoffset=-3 xadvance=89 page=0 chnl=0 letter="5" +char id=59 x=892 y=471 width=61 height=125 xoffset=10 yoffset=12 xadvance=42 page=0 chnl=0 letter=";" +char id=55 x=4 y=600 width=109 height=125 xoffset=10 yoffset=-3 xadvance=88 page=0 chnl=0 letter="7" +char id=70 x=117 y=600 width=109 height=125 xoffset=10 yoffset=-3 xadvance=86 page=0 chnl=0 letter="F" +char id=47 x=230 y=600 width=109 height=125 xoffset=10 yoffset=-3 xadvance=86 page=0 chnl=0 letter="/" +char id=76 x=343 y=600 width=77 height=125 xoffset=10 yoffset=-3 xadvance=57 page=0 chnl=0 letter="L" +char id=78 x=424 y=600 width=125 height=125 xoffset=10 yoffset=-3 xadvance=105 page=0 chnl=0 letter="N" +char id=87 x=553 y=600 width=157 height=125 xoffset=10 yoffset=-3 xadvance=138 page=0 chnl=0 letter="W" +char id=90 x=714 y=600 width=109 height=125 xoffset=10 yoffset=-3 xadvance=87 page=0 chnl=0 letter="Z" +char id=83 x=827 y=600 width=109 height=125 xoffset=10 yoffset=-3 xadvance=89 page=0 chnl=0 letter="S" +char id=79 x=4 y=729 width=125 height=125 xoffset=10 yoffset=-3 xadvance=106 page=0 chnl=0 letter="O" +char id=85 x=133 y=729 width=109 height=125 xoffset=10 yoffset=-3 xadvance=91 page=0 chnl=0 letter="U" +char id=50 x=246 y=729 width=109 height=125 xoffset=10 yoffset=-3 xadvance=88 page=0 chnl=0 letter="2" +char id=84 x=359 y=729 width=109 height=125 xoffset=10 yoffset=-3 xadvance=86 page=0 chnl=0 letter="T" +char id=73 x=472 y=729 width=61 height=125 xoffset=10 yoffset=-3 xadvance=43 page=0 chnl=0 letter="I" +char id=72 x=537 y=729 width=109 height=125 xoffset=10 yoffset=-3 xadvance=91 page=0 chnl=0 letter="H" +char id=74 x=650 y=729 width=93 height=125 xoffset=10 yoffset=-3 xadvance=75 page=0 chnl=0 letter="J" +char id=86 x=747 y=729 width=109 height=125 xoffset=10 yoffset=-3 xadvance=89 page=0 chnl=0 letter="V" +char id=58 x=860 y=729 width=61 height=109 xoffset=10 yoffset=12 xadvance=42 page=0 chnl=0 letter=":" +char id=60 x=925 y=729 width=93 height=109 xoffset=10 yoffset=12 xadvance=73 page=0 chnl=0 letter="<" +char id=62 x=4 y=858 width=93 height=109 xoffset=10 yoffset=12 xadvance=72 page=0 chnl=0 letter=">" +char id=94 x=101 y=858 width=103 height=95 xoffset=21 yoffset=-3 xadvance=95 page=0 chnl=0 letter="^" +char id=0 x=208 y=858 width=81 height=81 xoffset=20 yoffset=18 xadvance=72 page=0 chnl=0 letter="•" +char id=61 x=293 y=858 width=77 height=77 xoffset=10 yoffset=28 xadvance=57 page=0 chnl=0 letter="=" +char id=44 x=374 y=858 width=61 height=77 xoffset=10 yoffset=76 xadvance=43 page=0 chnl=0 letter="," +char id=43 x=439 y=858 width=77 height=77 xoffset=10 yoffset=28 xadvance=57 page=0 chnl=0 letter="+" +char id=46 x=520 y=858 width=61 height=61 xoffset=10 yoffset=76 xadvance=43 page=0 chnl=0 letter="." +char id=126 x=585 y=858 width=109 height=61 xoffset=10 yoffset=-3 xadvance=91 page=0 chnl=0 letter="~" +char id=39 x=698 y=858 width=45 height=61 xoffset=10 yoffset=-3 xadvance=28 page=0 chnl=0 letter="'" +char id=96 x=747 y=858 width=57 height=50 xoffset=16 yoffset=-6 xadvance=48 page=0 chnl=0 letter="`" +char id=45 x=808 y=858 width=77 height=45 xoffset=10 yoffset=44 xadvance=59 page=0 chnl=0 letter="-" +char id=95 x=889 y=858 width=101 height=37 xoffset=10 yoffset=107 xadvance=72 page=0 chnl=0 letter="_" +char id=32 x=4 y=971 width=29 height=29 xoffset=10 yoffset=96 xadvance=91 page=0 chnl=0 letter=" " +kernings count=0 \ No newline at end of file diff --git a/resources/levelCompleteFont-uhd.png b/resources/levelCompleteFont-uhd.png new file mode 100644 index 0000000..593c43d Binary files /dev/null and b/resources/levelCompleteFont-uhd.png differ diff --git a/resources/levelCompleteFont.fnt b/resources/levelCompleteFont.fnt new file mode 100644 index 0000000..98f2ae3 --- /dev/null +++ b/resources/levelCompleteFont.fnt @@ -0,0 +1,71 @@ +info font="Oxygene 1" size=36 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=4,4,4,4 spacing=4,4 +common lineHeight=36 base=29 scaleW=512 scaleH=512 pages=1 packed=0 +page id=0 file="levelCompleteFont.png" +chars count=67 +char id=124 x=4 y=4 width=22 height=55 xoffset=9 yoffset=-11 xadvance=8 page=0 chnl=0 letter="|" +char id=91 x=30 y=4 width=31 height=51 xoffset=6 yoffset=-9 xadvance=14 page=0 chnl=0 letter="[" +char id=41 x=65 y=4 width=35 height=51 xoffset=6 yoffset=-9 xadvance=18 page=0 chnl=0 letter=")" +char id=93 x=104 y=4 width=31 height=51 xoffset=6 yoffset=-9 xadvance=15 page=0 chnl=0 letter="]" +char id=40 x=139 y=4 width=35 height=51 xoffset=6 yoffset=-9 xadvance=18 page=0 chnl=0 letter="(" +char id=35 x=178 y=4 width=47 height=47 xoffset=6 yoffset=-9 xadvance=30 page=0 chnl=0 letter="#" +char id=33 x=229 y=4 width=31 height=47 xoffset=6 yoffset=-9 xadvance=14 page=0 chnl=0 letter="!" +char id=52 x=264 y=4 width=43 height=47 xoffset=6 yoffset=-9 xadvance=26 page=0 chnl=0 letter="4" +char id=51 x=311 y=4 width=39 height=47 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="3" +char id=82 x=354 y=4 width=39 height=47 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="R" +char id=81 x=397 y=4 width=43 height=47 xoffset=6 yoffset=-9 xadvance=26 page=0 chnl=0 letter="Q" +char id=57 x=444 y=4 width=39 height=47 xoffset=6 yoffset=-9 xadvance=23 page=0 chnl=0 letter="9" +char id=71 x=4 y=63 width=39 height=47 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="G" +char id=88 x=47 y=63 width=43 height=47 xoffset=6 yoffset=-9 xadvance=26 page=0 chnl=0 letter="X" +char id=54 x=94 y=63 width=39 height=47 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="6" +char id=64 x=137 y=63 width=51 height=47 xoffset=6 yoffset=-9 xadvance=34 page=0 chnl=0 letter="@" +char id=68 x=192 y=63 width=43 height=47 xoffset=6 yoffset=-9 xadvance=26 page=0 chnl=0 letter="D" +char id=75 x=239 y=63 width=39 height=47 xoffset=6 yoffset=-9 xadvance=23 page=0 chnl=0 letter="K" +char id=80 x=282 y=63 width=39 height=47 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="P" +char id=77 x=325 y=63 width=51 height=47 xoffset=6 yoffset=-9 xadvance=35 page=0 chnl=0 letter="M" +char id=65 x=380 y=63 width=39 height=47 xoffset=6 yoffset=-9 xadvance=23 page=0 chnl=0 letter="A" +char id=36 x=423 y=63 width=39 height=47 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="$" +char id=63 x=466 y=63 width=39 height=47 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="?" +char id=66 x=4 y=114 width=39 height=47 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="B" +char id=92 x=47 y=114 width=43 height=47 xoffset=6 yoffset=-9 xadvance=25 page=0 chnl=0 letter="\" +char id=89 x=94 y=114 width=39 height=47 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="Y" +char id=37 x=137 y=114 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="%" +char id=38 x=180 y=114 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="&" +char id=67 x=223 y=114 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="C" +char id=69 x=266 y=114 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="E" +char id=70 x=309 y=114 width=39 height=43 xoffset=6 yoffset=-9 xadvance=21 page=0 chnl=0 letter="F" +char id=49 x=352 y=114 width=31 height=43 xoffset=6 yoffset=-9 xadvance=15 page=0 chnl=0 letter="1" +char id=56 x=387 y=114 width=43 height=43 xoffset=6 yoffset=-9 xadvance=27 page=0 chnl=0 letter="8" +char id=50 x=434 y=114 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="2" +char id=59 x=477 y=114 width=27 height=43 xoffset=6 yoffset=-5 xadvance=11 page=0 chnl=0 letter=";" +char id=55 x=4 y=165 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="7" +char id=47 x=47 y=165 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="/" +char id=48 x=90 y=165 width=39 height=43 xoffset=6 yoffset=-9 xadvance=23 page=0 chnl=0 letter="0" +char id=53 x=133 y=165 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="5" +char id=72 x=176 y=165 width=39 height=43 xoffset=6 yoffset=-9 xadvance=23 page=0 chnl=0 letter="H" +char id=85 x=219 y=165 width=39 height=43 xoffset=6 yoffset=-9 xadvance=23 page=0 chnl=0 letter="U" +char id=78 x=262 y=165 width=43 height=43 xoffset=6 yoffset=-9 xadvance=26 page=0 chnl=0 letter="N" +char id=83 x=309 y=165 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="S" +char id=79 x=352 y=165 width=43 height=43 xoffset=6 yoffset=-9 xadvance=27 page=0 chnl=0 letter="O" +char id=90 x=399 y=165 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="Z" +char id=76 x=442 y=165 width=31 height=43 xoffset=6 yoffset=-9 xadvance=14 page=0 chnl=0 letter="L" +char id=87 x=4 y=212 width=51 height=43 xoffset=6 yoffset=-9 xadvance=35 page=0 chnl=0 letter="W" +char id=73 x=59 y=212 width=27 height=43 xoffset=6 yoffset=-9 xadvance=11 page=0 chnl=0 letter="I" +char id=84 x=90 y=212 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="T" +char id=74 x=133 y=212 width=35 height=43 xoffset=6 yoffset=-9 xadvance=19 page=0 chnl=0 letter="J" +char id=86 x=172 y=212 width=39 height=43 xoffset=6 yoffset=-9 xadvance=22 page=0 chnl=0 letter="V" +char id=62 x=215 y=212 width=35 height=39 xoffset=6 yoffset=-5 xadvance=18 page=0 chnl=0 letter=">" +char id=58 x=254 y=212 width=27 height=39 xoffset=6 yoffset=-5 xadvance=11 page=0 chnl=0 letter=":" +char id=60 x=285 y=212 width=35 height=39 xoffset=6 yoffset=-5 xadvance=18 page=0 chnl=0 letter="<" +char id=94 x=324 y=212 width=38 height=36 xoffset=9 yoffset=-9 xadvance=24 page=0 chnl=0 letter="^" +char id=0 x=366 y=212 width=32 height=32 xoffset=9 yoffset=-3 xadvance=18 page=0 chnl=0 letter="•" +char id=43 x=402 y=212 width=31 height=31 xoffset=6 yoffset=-1 xadvance=14 page=0 chnl=0 letter="+" +char id=61 x=437 y=212 width=31 height=31 xoffset=6 yoffset=-1 xadvance=14 page=0 chnl=0 letter="=" +char id=44 x=472 y=212 width=27 height=31 xoffset=6 yoffset=10 xadvance=11 page=0 chnl=0 letter="," +char id=46 x=4 y=259 width=27 height=27 xoffset=6 yoffset=10 xadvance=11 page=0 chnl=0 letter="." +char id=126 x=35 y=259 width=39 height=27 xoffset=6 yoffset=-9 xadvance=23 page=0 chnl=0 letter="~" +char id=39 x=78 y=259 width=23 height=27 xoffset=6 yoffset=-9 xadvance=7 page=0 chnl=0 letter="'" +char id=96 x=105 y=259 width=26 height=25 xoffset=8 yoffset=-10 xadvance=12 page=0 chnl=0 letter="`" +char id=45 x=135 y=259 width=31 height=23 xoffset=6 yoffset=2 xadvance=15 page=0 chnl=0 letter="-" +char id=95 x=170 y=259 width=37 height=21 xoffset=6 yoffset=18 xadvance=18 page=0 chnl=0 letter="_" +char id=32 x=211 y=259 width=19 height=19 xoffset=6 yoffset=15 xadvance=23 page=0 chnl=0 letter=" " +kernings count=0 \ No newline at end of file diff --git a/resources/levelCompleteFont.png b/resources/levelCompleteFont.png new file mode 100644 index 0000000..3aaa44f Binary files /dev/null and b/resources/levelCompleteFont.png differ diff --git a/src/CCScheduler.cpp b/src/CCScheduler.cpp new file mode 100644 index 0000000..7ad4d4a --- /dev/null +++ b/src/CCScheduler.cpp @@ -0,0 +1,11 @@ +#include +#include "Manager.hpp" + +using namespace geode::prelude; + +class $modify(MyCCScheduler, CCScheduler) { + void update(float dt) { + Manager::getSharedInstance()->fps = static_cast(getTimeScale() / dt) + 1; + CCScheduler::update(dt); + } +}; \ No newline at end of file diff --git a/src/CurrencyRewardLayer.cpp b/src/CurrencyRewardLayer.cpp new file mode 100644 index 0000000..49dc6e0 --- /dev/null +++ b/src/CurrencyRewardLayer.cpp @@ -0,0 +1,17 @@ +#include + +using namespace geode::prelude; + +class $modify(MyCurrencyRewardLayer, CurrencyRewardLayer) { + /* + THIS is apparently what i need to hook + for hiding the CurrencyRewardLayer consistently. + what the hell, robtop? + */ + void update(float p0) { + bool isHideEndLevelLayer = Mod::get()->getSettingValue("hideEndLevelLayer"); + bool isChildOfEndLevelLayer = typeinfo_cast(this->getParent()); + if (isHideEndLevelLayer && isChildOfEndLevelLayer) this->setVisible(false); + CurrencyRewardLayer::update(p0); + } +}; \ No newline at end of file diff --git a/src/EndLevelLayer.cpp b/src/EndLevelLayer.cpp new file mode 100644 index 0000000..aeabb61 --- /dev/null +++ b/src/EndLevelLayer.cpp @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include "Manager.hpp" + +#define managerMacro Manager::getSharedInstance() +#define getModBool Mod::get()->getSettingValue +#define getModDouble Mod::get()->getSettingValue +#define getModString Mod::get()->getSettingValue + +using namespace geode::prelude; + +class $modify(MyEndLevelLayer, EndLevelLayer) { + static const char* grabRandomQuote(std::vector vector = Manager::getSharedInstance()->quotes) { + std::mt19937 randomSeed(std::random_device{}()); + std::shuffle(vector.begin(), vector.end(), randomSeed); + return vector.front().c_str(); + } + CCSprite* getHideButtonSprite() { + return typeinfo_cast(getChildByIDRecursive("hide-button")->getChildren()->objectAtIndex(0)); + } + void toggleMainLayerVisibility(cocos2d::CCObject* sender) { + if (!getModBool("hideEndLevelLayer")) return; + if (m_mainLayer) { + m_mainLayer->setVisible(!m_mainLayer->isVisible()); + if (m_mainLayer->isVisible()) this->setOpacity(managerMacro->originalOpacity); + else this->setOpacity(0); + } + if (const auto hideButtonSprite = MyEndLevelLayer::getHideButtonSprite()) { + if (getModBool("hideHideEndscreen")) { + hideButtonSprite->setVisible(!hideButtonSprite->isVisible()); + } + } + if (const auto hideELLSprite = getChildByIDRecursive("hide-endlevellayer-sprite"_spr)) { + if (getModBool("hideHideEndscreen")) { + hideELLSprite->setVisible(!hideELLSprite->isVisible()); + } + } + /* + auto endLevelLayerChildren = CCArrayExt(this->getChildren()); + for (CCNode* node : endLevelLayerChildren) { + if (auto currencyLayer = typeinfo_cast(node)) { + currencyLayer->setVisible(!currencyLayer->isVisible()); + } + } + */ + } + void applySpaceUK() { + if (!getModBool("spaceUK")) return; + Manager* manager = managerMacro; + auto levelCompleteText = getChildByIDRecursive("level-complete-text"); + if (!levelCompleteText) levelCompleteText = getChildByIDRecursive("practice-complete-text"); // grab practice mode complete text as fallback node + if (!levelCompleteText) return; + if (manager->isCompactEndscreen) { + levelCompleteText->setVisible(true); + levelCompleteText->setPositionX(manager->compactEndscreenFallbackPosition); + } + levelCompleteText->setScale(0.8f * (940.f / 1004.f)); // original scale of this node is 0.8 according to logs. hardcoding it here in case other mods decide to scale it to whatever else + } + void applyHideEndLevelLayerHideBtn() { + const auto hideLayerMenu = typeinfo_cast(getChildByIDRecursive("hide-layer-menu")); + const auto hideButtonSprite = MyEndLevelLayer::getHideButtonSprite(); + const auto hideButtonButton = hideButtonSprite->getParent(); + if (!hideLayerMenu || !m_mainLayer || !hideButtonSprite || !hideButtonButton) return; + if (getModBool("hideHideEndscreen") || getModBool("hideEndLevelLayer")) hideButtonSprite->setVisible(false); + // float desiredSpriteYPosition = hideButtonButton->getPositionY() - hideButtonButton->getContentHeight(); + if (getModBool("hideEndLevelLayer")) { + Manager::getSharedInstance()->originalOpacity = this->getOpacity(); + this->setOpacity(0); + m_mainLayer->setVisible(false); + auto hideELLSprite = CCSprite::create("btn.png"_spr); + hideELLSprite->setScaleX(hideButtonSprite->getScaleX()); + hideELLSprite->setScaleY(hideButtonSprite->getScaleY()); + hideELLSprite->setID("hide-endlevellayer-sprite"_spr); + hideELLSprite->setVisible(MyEndLevelLayer::getHideButtonSprite()->isVisible()); + auto hideELLBtn = CCMenuItemSpriteExtra::create(hideELLSprite, this, menu_selector(MyEndLevelLayer::toggleMainLayerVisibility)); + hideELLBtn->setScale(hideButtonButton->getScale()); + hideELLBtn->setPositionY(hideButtonButton->getPositionY() - hideButtonButton->getContentHeight()); + hideELLBtn->setID("hide-endlevellayer-button"_spr); + hideLayerMenu->addChild(hideELLBtn); + hideLayerMenu->updateLayout(); // in case there is a layout in future node IDs updates + } + } + void applyHideChainsBackground() { + if (getModBool("hideChains")) { + if (const auto left = getChildByIDRecursive("chain-left")) left->setVisible(false); + if (auto right = getChildByIDRecursive("chain-right")) right->setVisible(false); + } + if (getModBool("hideBackground")) { + if (const auto bg = getChildByIDRecursive("background")) bg->setVisible(false); + } + } + void applyPlatAttemptsAndJumpsOrFlukedFromPercent(GJGameLevel* theLevel) { + Manager* manager = managerMacro; + manager->isCompactEndscreen = Loader::get()->isModLoaded("suntle.compactendscreen"); + const auto playLayer = PlayLayer::get(); + if (!m_mainLayer|| !playLayer) return; + const bool isPlat = theLevel->isPlatformer(); + if (getModBool("platAttemptsAndJumps") && isPlat) { + const auto timeLabel = getChildByIDRecursive("time-label"); + if (!timeLabel) return; + const auto pointsLabel = getChildByIDRecursive("points-label"); + if (!manager->isCompactEndscreen) timeLabel->setPositionY(timeLabel->getPositionY() - 20); + if (pointsLabel) pointsLabel->setPositionY(timeLabel->getPositionY() - 18); + const auto attemptsLabel = cocos2d::CCLabelBMFont::create(("Attempts: " + std::to_string(playLayer->m_attempts)).c_str(), "goldFont.fnt"); + attemptsLabel->setScale(0.8f); + attemptsLabel->setPosition(timeLabel->getPositionX(), timeLabel->getPositionY() + 40); + attemptsLabel->setID("attempts-label"_spr); + m_mainLayer->addChild(attemptsLabel); + m_mainLayer->updateLayout(); + const auto jumpsLabel = cocos2d::CCLabelBMFont::create(("Jumps: " + std::to_string(playLayer->m_jumps)).c_str(), "goldFont.fnt"); + jumpsLabel->setScale(0.8f); + jumpsLabel->setPosition({timeLabel->getPositionX(), timeLabel->getPositionY() + 20}); + jumpsLabel->setID("jumps-label"_spr); + m_mainLayer->addChild(jumpsLabel); + m_mainLayer->updateLayout(); + } else if (getModString("classicFlukedFrom") != "[Disabled]" && !isPlat && !playLayer->m_isTestMode && !playLayer->m_isPracticeMode && manager->lastFlukedPercent < 100) { + const auto timeLabel = getChildByIDRecursive("time-label"); + const auto jumpsLabel = getChildByIDRecursive("jumps-label"); + if (!timeLabel || !jumpsLabel) return; + jumpsLabel->setPositionY(jumpsLabel->getPositionY() + 7.0f); + timeLabel->setPositionY(timeLabel->getPositionY() + 14.0f); + auto flukedFromLabel = cocos2d::CCLabelBMFont::create(fmt::format("{}: {}%", getModString("classicFlukedFrom"), manager->lastFlukedPercent).c_str(), "goldFont.fnt"); + flukedFromLabel->setPosition(jumpsLabel->getPositionX(), timeLabel->getPositionY() - 16.0f); + flukedFromLabel->setScale(timeLabel->getScale()); + flukedFromLabel->setID("fluked-from-label"_spr); + m_mainLayer->addChild(flukedFromLabel); + m_mainLayer->updateLayout(); + } + } + /* + void applyGDMOCompatShowLayer(GJGameLevel* theLevel) { + isGDMO = Loader::get()->isModLoaded("maxnu.gd_mega_overlay"); + if (isGDMO && theLevel->m_coins == 0 && Loader::get()->getLoadedMod("maxnu.gd_mega_overlay")->getSavedValue("level/endlevellayerinfo/enabled")) { + // + gdmo does this silly thing where they add children without giving them node IDs and i need to release this mod ASAP so please forgive me for using getobjectatindex but getchildoftype doesnt work for this use case because everything in endscreen layer is a child of some other cclayer smh + if (!m_mainLayer) return; + auto mainLayerChildren = m_mainLayer->getChildren(); + auto attemptsLabel = getChildByIDRecursive("attempts-label"); + auto jumpsLabel = getChildByIDRecursive("jumps-label"); + if (attemptsLabel == nullptr || jumpsLabel == nullptr) { + log::info("uhoh! couldnt find labels"); + attemptsLabel = getChildByIDRecursive("attempts-label"_spr); + jumpsLabel = getChildByIDRecursive("jumps-label"_spr); + } + auto iHopeThisIsGDMONoclipAccuracyLabel = typeinfo_cast(mainLayerChildren->objectAtIndex(3)); + auto iHopeThisIsGDMONoclipDeathLabel = typeinfo_cast(mainLayerChildren->objectAtIndex(4)); + if (iHopeThisIsGDMONoclipAccuracyLabel == nullptr || iHopeThisIsGDMONoclipDeathLabel == nullptr) { + return; + } + if (strcmp(iHopeThisIsGDMONoclipAccuracyLabel->getID().c_str(), "") != 0 || strcmp(iHopeThisIsGDMONoclipDeathLabel->getID().c_str(), "") != 0) { + return; + } + iHopeThisIsGDMONoclipAccuracyLabel->setPositionY(attemptsLabel->getPositionY()); + iHopeThisIsGDMONoclipDeathLabel->setPositionY(jumpsLabel->getPositionY()); + // + // backup plan starts below + float windowWidth = getChildByIDRecursive("background")->getContentSize().width; + float windowHeight = CCDirector::get()->getWinSize().height; + float offset = getChildByIDRecursive("background")->getPositionX(); + auto starContainer = getChildByIDRecursive("star-container"); + if (starContainer == nullptr) { starContainer = getChildByIDRecursive("moon-container"); } + float gdmoHeight = windowHeight * (285.f / 320.f); + float gdmoTwentyFivePercentX = (windowWidth * .25f) + offset; + float gdmoFiftyPercentX = (windowWidth * .5f) + offset; + float gdmoSeventyFivePercentX = (windowWidth * .75f) + offset; + if (starContainer) { + if (theLevel->m_stars.value() == 1) { starContainer->setPositionX(gdmoFiftyPercentX); } + else { starContainer->setPositionX(gdmoTwentyFivePercentX); } + starContainer->setPositionY(gdmoHeight); + } + if (auto orbContainer = getChildByIDRecursive("orb-container")) { + orbContainer->setPositionY(gdmoHeight); + if (auto diamondContainer = getChildByIDRecursive("diamond-container")) { + diamondContainer->setPositionX(gdmoSeventyFivePercentX); + diamondContainer->setPositionY(gdmoHeight); + orbContainer->setPositionX(gdmoFiftyPercentX); + } else { + orbContainer->setPositionX(gdmoSeventyFivePercentX); + } + } + } + } + */ + void applyRandomQuoteAndFont(PlayLayer* playLayer, GJGameLevel* theLevel) { + auto endTextLabel = typeinfo_cast(getChildByIDRecursive("end-text")); + if (!endTextLabel) return; + Manager* manager = managerMacro; + std::string randomString = MyEndLevelLayer::grabRandomQuote(); + if (!manager->customQuotes.empty() && getModBool("customTextsOnly")) randomString = MyEndLevelLayer::grabRandomQuote(manager->customQuotes); + if ("Make sure to screenshot this win!" == randomString) { + #ifdef GEODE_IS_MACOS + randomString = "Press Command + Shift + 3 to screenshot this win!"; + #endif + #ifdef GEODE_IS_ANDROID + randomString = "Press the \"Volume Down\'\' and \"Power\'\' buttons to screenshot this win!"; + #endif + #ifdef GEODE_IS_WINDOWS + randomString = "Press \"Win + Shift + S\'\' or \"PrtSc\'\' to screenshot this win!"; + #endif + } else if (R"(''First try, part two!")" == randomString) { + std::string temp = fmt::format(R"(''First try, part {}!")", playLayer->m_attempts); + if (playLayer->m_attempts == 1) { temp = R"(''First try!")"; } + randomString = temp; + } else if (R"(''As you can see, my FPS is around 18 or so, which means we can definitely take this further.")" == randomString) { + randomString = fmt::format(R"(''As you can see, my FPS is around {} or so, which means we can definitely take this further.")", manager->fps); + } else if (R"(''If you wish to defeat me, train for another 100 years.")" == randomString) { + randomString = fmt::format(R"(''If you wish to defeat me, train for another {} years.")", std::max(100, (playLayer->m_jumps * 100))); + } else if ("Good luck on your statgrinding session!" == randomString && theLevel->m_stars.value() != 0) { + if (theLevel->isPlatformer()) { randomString = "Good luck on that moongrinding session!"; } + else { randomString = "Good luck on that stargrinding session!"; } + } + + float scale = 0.36f * 228.f / strlen(randomString.c_str()); + if ("BELIEVE" == randomString) scale = 1.5f; + else if ("endTextLabel->setString(randomString.c_str(), true);" == randomString) scale = 0.4f; + else if (scale > Mod::get()->getSettingValue("maxScale")) scale = getModDouble("maxScale"); + + endTextLabel->setScale(scale); + endTextLabel->setWidth(336.f); // width of end screen minus 20px + + endTextLabel->setString(randomString.c_str(), true); // set string + + int64_t fontID = Mod::get()->getSettingValue("customFont"); + if (fontID == -2) { + endTextLabel->setFntFile("chatFont.fnt"); + } else if (fontID == -1) { + endTextLabel->setFntFile("goldFont.fnt"); + } else if (fontID != 0) { + endTextLabel->setFntFile(fmt::format("gjFont{:02d}.fnt", fontID).c_str()); + } + + endTextLabel->setAlignment(CCTextAlignment::kCCTextAlignmentCenter); // center text + + if (manager->isCompactEndscreen) endTextLabel->setPositionX(manager->compactEndscreenFallbackPosition); + if (randomString.empty()) endTextLabel->setString(manager->fallbackString.c_str(), true); // fallback string + } + void showLayer(bool p0) { + if (!getModBool("enabled")) return EndLevelLayer::showLayer(p0); + EndLevelLayer::showLayer(getModBool("noTransition")); + if (auto playLayer = PlayLayer::get()) { + auto theLevel = playLayer->m_level; + MyEndLevelLayer::applyHideEndLevelLayerHideBtn(); + MyEndLevelLayer::applyHideChainsBackground(); + MyEndLevelLayer::applySpaceUK(); + MyEndLevelLayer::applyPlatAttemptsAndJumpsOrFlukedFromPercent(theLevel); + // MyEndLevelLayer::applyGDMOCompatShowLayer(theLevel); + } + } + void customSetup() { + EndLevelLayer::customSetup(); + if (!getModBool("enabled")) return; + managerMacro->isCompactEndscreen = Loader::get()->isModLoaded("suntle.compactendscreen"); + auto playLayer = PlayLayer::get(); + if (!playLayer) return; + if (getModBool("endTexts")) MyEndLevelLayer::applyRandomQuoteAndFont(playLayer, playLayer->m_level); + } +}; \ No newline at end of file diff --git a/src/Manager.cpp b/src/Manager.cpp new file mode 100644 index 0000000..d36c13e --- /dev/null +++ b/src/Manager.cpp @@ -0,0 +1,3 @@ +#include "Manager.hpp" + +Manager* Manager::instance = nullptr; \ No newline at end of file diff --git a/src/Manager.hpp b/src/Manager.hpp new file mode 100644 index 0000000..a8b1fb9 --- /dev/null +++ b/src/Manager.hpp @@ -0,0 +1,47 @@ +#pragma once + +// Manager.hpp structure by acaruso +// reused with explicit permission and strong encouragement + +using namespace geode::prelude; + +class Manager { + +protected: + static Manager* instance; +public: + + bool calledAlready = false; + + std::vector quotes; + std::vector customQuotes; + std::vector wETMigration; + std::vector levelCompleteQuotes; + std::vector customLevelCompleteQuotes; + + std::vector customLevelCompleteSprites; + std::vector knownCLCTModesBesidesCombined = {"Images", "Oxygene One"}; + + std::string fallbackString = "We've got too many players to congratulate on level completions. Beat this level again for an actual message."; + + int fps = -1; + int64_t originalOpacity = 0; + int lastFlukedPercent = 0; + + bool isCompactEndscreen; + bool isGDMO; + bool isLevelComplete = false; + + float compactEndscreenFallbackPosition = CCDirector::get()->getWinSize().width * 0.6f; + + CCLabelBMFont* sharedReplacementLabel = nullptr; + CCSprite* sharedReplacementSprite = nullptr; + + static Manager* getSharedInstance() { + if (!instance) { + instance = new Manager(); + } + return instance; + } + +}; \ No newline at end of file diff --git a/src/PlayLayer.cpp b/src/PlayLayer.cpp new file mode 100644 index 0000000..9dc118e --- /dev/null +++ b/src/PlayLayer.cpp @@ -0,0 +1,81 @@ +#include +#include +#include "Manager.hpp" + +#define getModBool Mod::get()->getSettingValue +#define getModString Mod::get()->getSettingValue +#define managerMacro Manager::getSharedInstance() + +using namespace geode::prelude; + +class $modify(MyPlayLayer, PlayLayer) { + static std::string grabRandomString(std::vector vector = managerMacro->quotes) { + std::mt19937 randomSeed(std::random_device{}()); + std::shuffle(vector.begin(), vector.end(), randomSeed); + return vector.front(); + } + static bool isSupportedExtension(const std::string& fileName) { + return !fileName.empty() && (geode::utils::string::endsWith(fileName, ".png") || geode::utils::string::endsWith(fileName, ".jpg")); + } + void levelComplete() { + if (!m_level) return PlayLayer::levelComplete(); + Manager* manager = managerMacro; + manager->lastFlukedPercent = this->m_level->m_normalPercent.value(); + if (getModBool("dontShowFlukeIfZero") && manager->lastFlukedPercent == 0) { manager->lastFlukedPercent = 200; } + // set it to an impossibly high value because i am too lazy to write yet another compound boolean statement + PlayLayer::levelComplete(); + } + void onQuit() { + Manager::getSharedInstance()->lastFlukedPercent = 0; + PlayLayer::onQuit(); + } + void showCompleteText() { + PlayLayer::showCompleteText(); + if (!m_level || !getModBool("enabled") || !getModBool("customLevelCompleteText") || getModString("alsoReplacePlayLayerLCT") == "Disabled") return; + Manager* manager = managerMacro; + CCSprite* toModify = nullptr; + for (const auto node : CCArrayExt(this->getChildren())) { + if (cocos::isSpriteFrameName(node, "GJ_levelComplete_001.png")) { + toModify = static_cast(node); + break; + } + } + if (!toModify) return; + std::string customLCTMode = getModString("customLCTMode"); + auto originalOpacity = toModify->getOpacity(); + bool lctReplaced = false; + toModify->setOpacity(0); + if (customLCTMode == "Combined" || customLCTMode == "Images") { + if (!manager->customLevelCompleteSprites.empty()) manager->customLevelCompleteSprites.clear(); + for (const auto& file : std::filesystem::directory_iterator((Mod::get()->getConfigDir() / R"(levelCompleteImages)").string())) { + if (isSupportedExtension(file.path().extension().string())) { + manager->customLevelCompleteSprites.push_back(file.path().string()); + } + } + std::string chosenSprite; // init sprite + if (!manager->customLevelCompleteSprites.empty()) chosenSprite = grabRandomString(manager->customLevelCompleteSprites); + else if (customLCTMode == "Images" && chosenSprite.empty()) return toModify->setOpacity(originalOpacity); // return early if no file name was selected even though user selected "Images" mode + manager->sharedReplacementSprite = CCSprite::create(chosenSprite.c_str()); + } + if (customLCTMode == "Combined" || customLCTMode == "Oxygene One") { + std::string customQuote = getModBool("customLevelCompleteTextsOnly") ? grabRandomString(manager->customLevelCompleteQuotes) : grabRandomString(manager->levelCompleteQuotes); + CCLabelBMFont* replacementLabel = CCLabelBMFont::create(customQuote.c_str(), "levelCompleteFont.fnt"_spr); + replacementLabel->setExtraKerning(5); + manager->sharedReplacementLabel = replacementLabel; + } + if (customLCTMode == "Combined") customLCTMode = grabRandomString(manager->knownCLCTModesBesidesCombined); + if (customLCTMode == "Oxygene One" && manager->sharedReplacementLabel && !lctReplaced) { + toModify->addChild(manager->sharedReplacementLabel); + manager->sharedReplacementLabel->setPosition(toModify->getContentSize() / 2.f); + manager->sharedReplacementLabel->limitLabelWidth(370.f, 1.0f, 0.25f); + manager->sharedReplacementLabel->setID("custom-level-complete-label-playlayer"_spr); + lctReplaced = true; + } else if (customLCTMode == "Images" && manager->sharedReplacementSprite && !lctReplaced) { + toModify->addChild(manager->sharedReplacementSprite); + manager->sharedReplacementSprite->setPosition(toModify->getContentSize() / 2.f); + manager->sharedReplacementSprite->setID("custom-level-complete-sprite-playlayer"_spr); + lctReplaced = true; + } + if (!lctReplaced) return toModify->setOpacity(originalOpacity); + } +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 4ce5664..7671150 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,46 +1,32 @@ -#include -#include -#include -#include -#include -#include #include -#include -#include -#include +#include "Manager.hpp" #include "Settings.hpp" -using namespace geode::prelude; - -std::vector quotes; -std::vector customQuotes; -std::vector wETMigration; - -std::string fallbackString = "We've got too many players to congratulate on level completions. Beat this level again for an actual message."; - -int fps = -1; -int64_t originalOpacity = 0; -int lastFlukedPercent = 0; - -bool isCompactEndscreen; -bool isGDMO; -bool isLevelComplete = false; +#define getModBool Mod::get()->getSettingValue +#define managerMacro Manager::getSharedInstance() +#define configDir Mod::get()->getConfigDir() -float compactEndscreenFallbackPosition = CCDirector::get()->getWinSize().width * 0.6f; +using namespace geode::prelude; $on_mod(Loaded) { - Mod::get()->registerCustomSettingType("configdir", &MyButtonSettingV3::parse); + Manager* manager = managerMacro; + (void) Mod::get()->registerCustomSettingType("configdir", &MyButtonSettingV3::parse); + if (!std::filesystem::exists((configDir / R"(levelCompleteImages)"))) { + std::filesystem::create_directory(configDir / R"(levelCompleteImages)"); + } auto pathDefault = (Mod::get()->getResourcesDir() / "default.txt"); std::ifstream file(pathDefault); std::string placeHolder; - while (std::getline(file, placeHolder)) { quotes.push_back(placeHolder); } + while (std::getline(file, placeHolder)) { + manager->quotes.push_back(placeHolder); + } - if (Mod::get()->getSettingValue("technoblade")) { + if (getModBool("technoblade")) { auto pathTechnoblade = (Mod::get()->getResourcesDir() / "technoblade.txt"); - std::ifstream file(pathTechnoblade); + std::ifstream fileTechnoblade(pathTechnoblade); std::string technoblade; - while (std::getline(file, technoblade)) { - quotes.push_back(technoblade); + while (std::getline(fileTechnoblade, technoblade)) { + manager->quotes.push_back(technoblade); } // technically i can write two one-time use boolean variables to allow people to toggle these things on and off as they please without the quotes adding themselves multiple times into the vector, but i'd rather add the "restart required" barrier just to be extra safe } @@ -51,7 +37,7 @@ float compactEndscreenFallbackPosition = CCDirector::get()->getWinSize().width * std::ifstream wETFile(oldWETMessages); std::string wETStr; while (std::getline(wETFile, wETStr)) { - wETMigration.push_back(wETStr); + manager->wETMigration.push_back(wETStr); log::info("{}", wETStr); } log::info("Finished storing oldWETMessages."); @@ -59,19 +45,19 @@ float compactEndscreenFallbackPosition = CCDirector::get()->getWinSize().width * // code adapted with permission from dialouge handler original author thesillydoggo: https://discord.com/channels/911701438269386882/911702535373475870/1212633554345918514 --erymanthus | raydeeux - auto pathCustom = (Mod::get()->getConfigDir() / "custom.txt"); + auto pathCustom = (configDir / "custom.txt"); if (!std::filesystem::exists(pathCustom)) { - log::info("customtxt does not exist. wETMigration.empty(): {} | std::filesystem::exists(oldWETMessages): {}", wETMigration.empty(), std::filesystem::exists(oldWETMessages)); - if (wETMigration.empty()) { + log::info("customtxt does not exist. wETMigration.empty(): {} | std::filesystem::exists(oldWETMessages): {}", manager->wETMigration.empty(), std::filesystem::exists(oldWETMessages)); + if (manager->wETMigration.empty()) { log::info("wETMigration was empty. Confirm \"std::filesystem::exists(oldWETMessages)\" didn't appear earlier in the logs."); std::string content = R"(lorem ipsum abc def u beat the level gg gaming [this text file was brought to you by endscreentweaks. if you're seeing this in the config directory for wholesomeendtexts, something has gone terribly TERRIBLY wrong-simply ping @erymanthus in the geode sdk discord server and do not panic!])"; - utils::file::writeString(pathCustom, content); + (void) utils::file::writeString(pathCustom, content); } else if (std::filesystem::exists(oldWETMessages)) { - if (!wETMigration.empty()) { + if (!manager->wETMigration.empty()) { log::info("Migrating custom messages from WholesomeEndTexts. Buckle up!"); /* for (std::string wETCustomMessage : wETMigration) { @@ -88,16 +74,16 @@ gg gaming migration failed, womp womp migration failed, womp womp migration failed, womp womp)"; - utils::file::writeString(pathCustom, content); + (void) utils::file::writeString(pathCustom, content); } } } - - if (Mod::get()->getSettingValue("custom")) { - auto pathCustom = (Mod::get()->getConfigDir() / "custom.txt"); - std::ifstream file(pathCustom); + + if (getModBool("custom")) { + auto pathCustomConfigDir = (configDir / "custom.txt"); + std::ifstream fileConfigDir(pathCustomConfigDir); std::string str; - while (std::getline(file, str)) { + while (std::getline(fileConfigDir, str)) { if (str.starts_with("\"") && str.ends_with("\"")) { str = str.replace(0, 1, "\'\'"); } else if (str.starts_with("\'") && str.ends_with("\'")) { @@ -106,331 +92,31 @@ migration failed, womp womp)"; if (!Mod::get()->getSavedValue("noHyphens")) { str = fmt::format("- {} -", str); } - quotes.push_back(str); - customQuotes.push_back(str); + manager->quotes.push_back(str); + manager->customQuotes.push_back(str); } // technically i can write two one-time use boolean variables to allow people to toggle these things on and off as they please without the quotes adding themselves multiple times into the vector, but i'd rather add the "restart required" barrier just to be extra safe } -} - -const char* grabRandomQuote(std::vector vector = quotes) { - std::mt19937 randomSeed(std::random_device{}()); - std::shuffle(vector.begin(), vector.end(), randomSeed); - return vector.front().c_str(); -} - -class $modify(CCScheduler) { - void update(float dt) { - fps = static_cast(getTimeScale() / dt) + 1; - CCScheduler::update(dt); - } -}; - -class $modify(MyPlayLayer, PlayLayer) { - void levelComplete() { - if (!m_level) { return PlayLayer::levelComplete(); } - lastFlukedPercent = this->m_level->m_normalPercent.value(); - if (Mod::get()->getSettingValue("dontShowFlukeIfZero") && lastFlukedPercent == 0) { lastFlukedPercent = 200; } - // set it to an impossibly high value because i am too lazy to write yet another compound boolean statement - PlayLayer::levelComplete(); - } - void onQuit() { - lastFlukedPercent = 0; - PlayLayer::onQuit(); - } -}; - -class $modify(MyCurrencyRewardLayer, CurrencyRewardLayer) { - /* - THIS is apparently what i need to hook - for hiding the CurrencyRewardLayer consistently. - what the hell, robtop? - */ - void update(float p0) { - bool isHideEndLevelLayer = Mod::get()->getSettingValue("hideEndLevelLayer"); - bool isChildOfEndLevelLayer = typeinfo_cast(this->getParent()); - if (isHideEndLevelLayer && isChildOfEndLevelLayer) { this->setVisible(false); } - CurrencyRewardLayer::update(p0); - } -}; - -class $modify(MyEndLevelLayer, EndLevelLayer) { - bool getModBool(std::string setting) { - return Mod::get()->getSettingValue(setting); - } - std::string getModString(std::string setting) { - return Mod::get()->getSettingValue(setting); - } - CCSprite* getHideButtonSprite() { - if (auto hideButtonSprite = typeinfo_cast(getChildByIDRecursive("hide-button")->getChildren()->objectAtIndex(0))) { - return hideButtonSprite; - } - return nullptr; - } - void toggleMainLayerVisibility(cocos2d::CCObject* sender) { - if (!MyEndLevelLayer::getModBool("hideEndLevelLayer")) { - return; - } - if (auto mainLayer = MyEndLevelLayer::getMainLayer()) { - mainLayer->setVisible(!mainLayer->isVisible()); - if (mainLayer->isVisible()) { this->setOpacity(originalOpacity); } - else { this->setOpacity(0); } - } - if (auto hideButtonSprite = MyEndLevelLayer::getHideButtonSprite()) { - if (!MyEndLevelLayer::getModBool("hideHideEndscreen")) { - hideButtonSprite->setVisible(!hideButtonSprite->isVisible()); - } - } - if (auto hideELLSprite = getChildByIDRecursive("hide-endlevellayer-sprite"_spr)) { - if (!MyEndLevelLayer::getModBool("hideHideEndscreen")) { - hideELLSprite->setVisible(!hideELLSprite->isVisible()); - } - } - /* - auto endLevelLayerChildren = CCArrayExt(this->getChildren()); - for (CCNode* node : endLevelLayerChildren) { - if (auto currencyLayer = typeinfo_cast(node)) { - currencyLayer->setVisible(!currencyLayer->isVisible()); - } - } - */ - } - void applySpaceUK() { - if (MyEndLevelLayer::getModBool("spaceUK")) { - auto levelCompleteText = getChildByIDRecursive("level-complete-text"); - if (levelCompleteText == nullptr) { levelCompleteText = getChildByIDRecursive("practice-complete-text"); } // grab practice mode complete text as fallback node - if (levelCompleteText) { - if (isCompactEndscreen) { - levelCompleteText->setVisible(true); - levelCompleteText->setPositionX(compactEndscreenFallbackPosition); - } - levelCompleteText->setScale(0.8f * (940.f / 1004.f)); // original scale of this node is 0.8 according to logs. hardcoding it here in case other mods decide to scale it to whatever else - } - } - } - void applyHideEndLevelLayerHideBtn() { - auto mainLayer = MyEndLevelLayer::getMainLayer(); - auto hideLayerMenu = typeinfo_cast(getChildByIDRecursive("hide-layer-menu")); - auto hideButtonSprite = MyEndLevelLayer::getHideButtonSprite(); - auto hideButtonButton = hideButtonSprite->getParent(); - if (!hideLayerMenu || !mainLayer || !hideButtonSprite || !hideButtonButton) { return; } - if (MyEndLevelLayer::getModBool("hideHideEndscreen") || MyEndLevelLayer::getModBool("hideEndLevelLayer")) { - hideButtonSprite->setVisible(false); - } - float desiredSpriteYPosition = hideButtonButton->getPositionY() - hideButtonButton->getContentHeight(); - if (MyEndLevelLayer::getModBool("hideEndLevelLayer")) { - originalOpacity = this->getOpacity(); - this->setOpacity(0); - mainLayer->setVisible(false); - auto hideELLSprite = CCSprite::create("btn.png"_spr); - hideELLSprite->setScaleX(hideButtonSprite->getScaleX()); - hideELLSprite->setScaleY(hideButtonSprite->getScaleY()); - hideELLSprite->setID("hide-endlevellayer-sprite"_spr); - hideELLSprite->setVisible(MyEndLevelLayer::getHideButtonSprite()->isVisible()); - auto hideELLBtn = CCMenuItemSpriteExtra::create(hideELLSprite, this, menu_selector(MyEndLevelLayer::toggleMainLayerVisibility)); - hideELLBtn->setScale(hideButtonButton->getScale()); - hideELLBtn->setPositionY(hideButtonButton->getPositionY() - hideButtonButton->getContentHeight()); - hideELLBtn->setID("hide-endlevellayer-button"_spr); - hideLayerMenu->addChild(hideELLBtn); - hideLayerMenu->updateLayout(); // in case there is a layout in future node IDs updates - } - } - void applyHideChainsBackground() { - if (MyEndLevelLayer::getModBool("hideChains")) { - if (auto left = getChildByIDRecursive("chain-left")) { left->setVisible(false); } - if (auto right = getChildByIDRecursive("chain-right")) { right->setVisible(false); } - } - if (MyEndLevelLayer::getModBool("hideBackground")) { - if (auto bg = getChildByIDRecursive("background")) { bg->setVisible(false); } - } - } - void applyPlatAttemptsAndJumpsOrFlukedFromPercent(GJGameLevel* theLevel) { - isCompactEndscreen = Loader::get()->isModLoaded("suntle.compactendscreen"); - auto mainLayer = MyEndLevelLayer::getMainLayer(); - if (mainLayer == nullptr) { return; } - auto playLayer = PlayLayer::get(); - if (playLayer == nullptr) { return; } - bool isPlat = theLevel->isPlatformer(); - if (MyEndLevelLayer::getModBool("platAttemptsAndJumps") && isPlat) { - auto timeLabel = getChildByIDRecursive("time-label"); - if (timeLabel == nullptr) { return; } - auto pointsLabel = getChildByIDRecursive("points-label"); - if (!isCompactEndscreen) { timeLabel->setPositionY(timeLabel->getPositionY() - 20); } - if (pointsLabel) { pointsLabel->setPositionY(timeLabel->getPositionY() - 18); } - auto attemptsLabel = cocos2d::CCLabelBMFont::create(("Attempts: " + std::to_string(playLayer->m_attempts)).c_str(), "goldFont.fnt"); - attemptsLabel->setScale(0.8f); - attemptsLabel->setPositionX(timeLabel->getPositionX()); - attemptsLabel->setPositionY(timeLabel->getPositionY() + 40); - attemptsLabel->setID("attempts-label"_spr); - mainLayer->addChild(attemptsLabel); - mainLayer->updateLayout(); - auto jumpsLabel = cocos2d::CCLabelBMFont::create(("Jumps: " + std::to_string(playLayer->m_jumps)).c_str(), "goldFont.fnt"); - jumpsLabel->setScale(0.8f); - jumpsLabel->setPositionX(timeLabel->getPositionX()); - jumpsLabel->setPositionY(timeLabel->getPositionY() + 20); - jumpsLabel->setID("jumps-label"_spr); - mainLayer->addChild(jumpsLabel); - mainLayer->updateLayout(); - } else if (MyEndLevelLayer::getModString("classicFlukedFrom") != "[Disabled]" && !isPlat && !playLayer->m_isTestMode && !playLayer->m_isPracticeMode && lastFlukedPercent < 100) { - auto timeLabel = getChildByIDRecursive("time-label"); - if (timeLabel == nullptr) { return; } - auto jumpsLabel = getChildByIDRecursive("jumps-label"); - if (jumpsLabel == nullptr) { return; } - jumpsLabel->setPositionY(jumpsLabel->getPositionY() + 7.0f); - timeLabel->setPositionY(timeLabel->getPositionY() + 14.0f); - auto flukedFromLabel = cocos2d::CCLabelBMFont::create(fmt::format("{}: {}%", getModString("classicFlukedFrom"), lastFlukedPercent).c_str(), "goldFont.fnt"); - flukedFromLabel->setPosition(jumpsLabel->getPositionX(), timeLabel->getPositionY() - 16.0f); - flukedFromLabel->setScale(timeLabel->getScale()); - flukedFromLabel->setID("fluked-from-label"_spr); - mainLayer->addChild(flukedFromLabel); - mainLayer->updateLayout(); - } - } - void applyGDMOCompatShowLayer(GJGameLevel* theLevel) { - isGDMO = Loader::get()->isModLoaded("maxnu.gd_mega_overlay"); - if (isGDMO && theLevel->m_coins == 0 && Loader::get()->getLoadedMod("maxnu.gd_mega_overlay")->getSavedValue("level/endlevellayerinfo/enabled")) { - /* - gdmo does this silly thing where they add children without giving them node IDs and i need to release this mod ASAP so please forgive me for using getobjectatindex but getchildoftype doesnt work for this use case because everything in endscreen layer is a child of some other cclayer smh - auto mainLayer = MyEndLevelLayer::getMainLayer(); - if (mainLayer == nullptr) return; - auto mainLayerChildren = mainLayer->getChildren(); - auto attemptsLabel = getChildByIDRecursive("attempts-label"); - auto jumpsLabel = getChildByIDRecursive("jumps-label"); - if (attemptsLabel == nullptr || jumpsLabel == nullptr) { - log::info("uhoh! couldnt find labels"); - attemptsLabel = getChildByIDRecursive("attempts-label"_spr); - jumpsLabel = getChildByIDRecursive("jumps-label"_spr); - } - auto iHopeThisIsGDMONoclipAccuracyLabel = typeinfo_cast(mainLayerChildren->objectAtIndex(3)); - auto iHopeThisIsGDMONoclipDeathLabel = typeinfo_cast(mainLayerChildren->objectAtIndex(4)); - if (iHopeThisIsGDMONoclipAccuracyLabel == nullptr || iHopeThisIsGDMONoclipDeathLabel == nullptr) { - return; - } - if (strcmp(iHopeThisIsGDMONoclipAccuracyLabel->getID().c_str(), "") != 0 || strcmp(iHopeThisIsGDMONoclipDeathLabel->getID().c_str(), "") != 0) { - return; - } - iHopeThisIsGDMONoclipAccuracyLabel->setPositionY(attemptsLabel->getPositionY()); - iHopeThisIsGDMONoclipDeathLabel->setPositionY(jumpsLabel->getPositionY()); - */ - // backup plan starts below - float windowWidth = getChildByIDRecursive("background")->getContentSize().width; - float windowHeight = CCDirector::get()->getWinSize().height; - float offset = getChildByIDRecursive("background")->getPositionX(); - auto starContainer = getChildByIDRecursive("star-container"); - if (starContainer == nullptr) { starContainer = getChildByIDRecursive("moon-container"); } - float gdmoHeight = windowHeight * (285.f / 320.f); - float gdmoTwentyFivePercentX = (windowWidth * .25f) + offset; - float gdmoFiftyPercentX = (windowWidth * .5f) + offset; - float gdmoSeventyFivePercentX = (windowWidth * .75f) + offset; - if (starContainer) { - if (theLevel->m_stars.value() == 1) { starContainer->setPositionX(gdmoFiftyPercentX); } - else { starContainer->setPositionX(gdmoTwentyFivePercentX); } - starContainer->setPositionY(gdmoHeight); - } - if (auto orbContainer = getChildByIDRecursive("orb-container")) { - orbContainer->setPositionY(gdmoHeight); - if (auto diamondContainer = getChildByIDRecursive("diamond-container")) { - diamondContainer->setPositionX(gdmoSeventyFivePercentX); - diamondContainer->setPositionY(gdmoHeight); - orbContainer->setPositionX(gdmoFiftyPercentX); - } else { - orbContainer->setPositionX(gdmoSeventyFivePercentX); - } - } - } - } - void applyRandomQuoteAndFont(PlayLayer* playLayer, GJGameLevel* theLevel) { - if (auto endTextLabel = typeinfo_cast(getChildByIDRecursive("end-text"))) { - std::string randomString = grabRandomQuote(); - if (!customQuotes.empty() && getModBool("customTextsOnly")) randomString = grabRandomQuote(customQuotes); - if ("Make sure to screenshot this win!" == randomString) { - #ifdef GEODE_IS_MACOS - randomString = "Press Command + Shift + 3 to screenshot this win!"; - #endif - #ifdef GEODE_IS_ANDROID - randomString = "Press the \"Volume Down\'\' and \"Power\'\' buttons to screenshot this win!"; - #endif - #ifdef GEODE_IS_WINDOWS - randomString = "Press \"Win + Shift + S\'\' or \"PrtSc\'\' to screenshot this win!"; - #endif - } else if (R"(''First try, part two!")" == randomString) { - std::string temp = fmt::format(R"(''First try, part {}!")", playLayer->m_attempts); - if (playLayer->m_attempts == 1) { temp = R"(''First try!")"; } - randomString = temp; - } else if (R"(''As you can see, my FPS is around 18 or so, which means we can definitely take this further.")" == randomString) { - randomString = fmt::format(R"(''As you can see, my FPS is around {} or so, which means we can definitely take this further.")", fps); - } else if (R"(''If you wish to defeat me, train for another 100 years.")" == randomString) { - randomString = fmt::format(R"(''If you wish to defeat me, train for another {} years.")", std::max(100, (playLayer->m_jumps * 100))); - } else if ("Good luck on that statgrinding session!" == randomString && theLevel->m_stars.value() != 0) { - if (theLevel->isPlatformer()) { randomString = "Good luck on that moongrinding session!"; } - else { randomString = "Good luck on that stargrinding session!"; } - } - - float scale = 0.36f * 228.f / strlen(randomString.c_str()); - if ("BELIEVE" == randomString) { scale = 1.5f; } - else if ("endTextLabel->setString(randomString.c_str(), true);" == randomString) { scale = 0.4f; } - else if (scale > Mod::get()->getSettingValue("maxScale")) { scale = Mod::get()->getSettingValue("maxScale"); } - - endTextLabel->setScale(scale); - endTextLabel->setWidth(336.f); // width of end screen minus 20px - - endTextLabel->setString(randomString.c_str(), true); // set string - - int64_t fontID = Mod::get()->getSettingValue("customFont"); - if (fontID == -2) { - endTextLabel->setFntFile("chatFont.fnt"); - } else if (fontID == -1) { - endTextLabel->setFntFile("goldFont.fnt"); - } else if (fontID != 0) { - endTextLabel->setFntFile(fmt::format("gjFont{:02d}.fnt", fontID).c_str()); - } - - endTextLabel->setAlignment(CCTextAlignment::kCCTextAlignmentCenter); // center text - if (isCompactEndscreen) endTextLabel->setPositionX(compactEndscreenFallbackPosition); - if (randomString.empty()) { endTextLabel->setString(fallbackString.c_str(), true); } // fallback string - } - } - CCNode* getMainLayer() { - if (auto mainLayer = getChildByIDRecursive("main-layer")) { return mainLayer; } - return nullptr; - } - void showLayer(bool p0) { - if (!MyEndLevelLayer::getModBool("enabled")) { - return EndLevelLayer::showLayer(p0); - } - EndLevelLayer::showLayer(MyEndLevelLayer::getModBool("noTransition")); - if (auto playLayer = PlayLayer::get()) { - auto theLevel = playLayer->m_level; - MyEndLevelLayer::applyHideEndLevelLayerHideBtn(); - MyEndLevelLayer::applyHideChainsBackground(); - MyEndLevelLayer::applySpaceUK(); - MyEndLevelLayer::applyPlatAttemptsAndJumpsOrFlukedFromPercent(theLevel); - MyEndLevelLayer::applyGDMOCompatShowLayer(theLevel); - } - } - void customSetup() { - EndLevelLayer::customSetup(); - if (!MyEndLevelLayer::getModBool("enabled")) { return; } - isCompactEndscreen = Loader::get()->isModLoaded("suntle.compactendscreen"); - auto playLayer = PlayLayer::get(); - if (playLayer == nullptr) { return; } - auto theLevel = playLayer->m_level; - /* - if (auto completeMessage = typeinfo_cast(getChildByIDRecursive("complete-message"))) { - // ensure that no one's up to any funny business by hardcoding the scale and contents of vanilla complete messages - completeMessage->setScale(0.55f); - if (getChildByIDRecursive("level-complete-text")) { - if (theLevel->m_isVerifiedRaw) { completeMessage->setString("Level Verified!"); } - else { completeMessage->setString("You cannot verify a level if it\nhas a start pos."); } - } else { - if (theLevel->m_levelID.value() == 0) { completeMessage->setString("Complete the level in normal mode\nto verify it!"); } - else { completeMessage->setString("Well done... Now try to complete\nit without any checkpoints!"); } - } - if (isCompactEndscreen) completeMessage->setPositionX(compactEndscreenFallbackPosition); - return; - } - */ - if (!MyEndLevelLayer::getModBool("endTexts")) { return; } - MyEndLevelLayer::applyRandomQuoteAndFont(playLayer, theLevel); - } -}; + auto pathDefaultLevelComplete = (Mod::get()->getResourcesDir() / "defaultLevelComplete.txt"); + std::ifstream defaultLCQuoteFile(pathDefaultLevelComplete); + std::string defaultLCQuote; + while (std::getline(defaultLCQuoteFile, defaultLCQuote)) { + manager->levelCompleteQuotes.push_back(defaultLCQuote); + log::info("added default levelcomplete quote: `{}`", defaultLCQuote); + } + auto pathCustomLvlCompleteQuotes = (configDir / "customLevelCompleteQuotes.txt"); + if (std::filesystem::exists(pathCustomLvlCompleteQuotes)) { + std::ifstream customLCQuoteFile(pathCustomLvlCompleteQuotes); + std::string customLCQuote; + while (std::getline(customLCQuoteFile, customLCQuote)) { + const std::string toAdd = geode::utils::string::toUpper(geode::utils::string::replace(customLCQuote, "\"", "\'\'")); + manager->levelCompleteQuotes.push_back(toAdd); + manager->customLevelCompleteQuotes.push_back(toAdd); + log::info("added custom levelcomplete quote: `{}`", toAdd); + } + } else { + std::string content = R"(insert funny text here +(yes, you can delete both lines in this text file))"; + (void) utils::file::writeString(pathCustomLvlCompleteQuotes, content); + } +} \ No newline at end of file