From 8b62bb1d6541dfd5f02870dc5eef53c571b281e8 Mon Sep 17 00:00:00 2001 From: Misa Date: Tue, 27 Aug 2024 15:13:24 -0700 Subject: [PATCH 01/64] Bump version to v2.5 I consider the 2.4 development cycle over now, after the most important bugs (and regressions) were fixed in 2.4.2. [skip ci] --- desktop_version/src/ReleaseVersion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/src/ReleaseVersion.h b/desktop_version/src/ReleaseVersion.h index 325ae381..288946dd 100644 --- a/desktop_version/src/ReleaseVersion.h +++ b/desktop_version/src/ReleaseVersion.h @@ -1,6 +1,6 @@ #ifndef RELEASEVERSION_H #define RELEASEVERSION_H -#define RELEASE_VERSION "v2.4.2" +#define RELEASE_VERSION "v2.5" #endif /* RELEASEVERSION_H */ From d8b2b3542a70175f1fcd3fbca19149b88ce4bbf1 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Sun, 25 Aug 2024 20:19:07 -0300 Subject: [PATCH 02/64] Add enemy speed as a room property Currently, you can change platform speed, but not enemy speed, which is always hardcoded to be 4. This commit fixes that, by adding the "enemyv" property, which is an offset to the speed of 4. Since it defaults to 0, older levels are not broken by this change. --- desktop_version/lang/ar/strings.xml | 1 + desktop_version/lang/ca/strings.xml | 1 + desktop_version/lang/cy/strings.xml | 1 + desktop_version/lang/de/strings.xml | 1 + desktop_version/lang/en/strings.xml | 1 + desktop_version/lang/eo/strings.xml | 1 + desktop_version/lang/es/strings.xml | 1 + desktop_version/lang/es_419/strings.xml | 1 + desktop_version/lang/es_AR/strings.xml | 1 + desktop_version/lang/fr/strings.xml | 1 + desktop_version/lang/ga/strings.xml | 1 + desktop_version/lang/it/strings.xml | 1 + desktop_version/lang/ja/strings.xml | 1 + desktop_version/lang/ko/strings.xml | 1 + desktop_version/lang/nl/strings.xml | 1 + desktop_version/lang/pl/strings.xml | 1 + desktop_version/lang/pt_BR/strings.xml | 1 + desktop_version/lang/pt_PT/strings.xml | 1 + desktop_version/lang/ru/strings.xml | 1 + desktop_version/lang/szl/strings.xml | 1 + desktop_version/lang/tr/strings.xml | 1 + desktop_version/lang/uk/strings.xml | 1 + desktop_version/lang/zh/strings.xml | 1 + desktop_version/lang/zh_TW/strings.xml | 1 + desktop_version/src/CustomLevels.cpp | 4 +++ desktop_version/src/CustomLevels.h | 1 + desktop_version/src/Editor.cpp | 37 ++++++++++++++++++++++--- desktop_version/src/Map.cpp | 2 +- 28 files changed, 63 insertions(+), 5 deletions(-) diff --git a/desktop_version/lang/ar/strings.xml b/desktop_version/lang/ar/strings.xml index dc4ab172..3788d484 100644 --- a/desktop_version/lang/ar/strings.xml +++ b/desktop_version/lang/ar/strings.xml @@ -630,6 +630,7 @@ + diff --git a/desktop_version/lang/ca/strings.xml b/desktop_version/lang/ca/strings.xml index 9067a50d..9e4d58ed 100644 --- a/desktop_version/lang/ca/strings.xml +++ b/desktop_version/lang/ca/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/cy/strings.xml b/desktop_version/lang/cy/strings.xml index 75233e0a..3db5fbab 100644 --- a/desktop_version/lang/cy/strings.xml +++ b/desktop_version/lang/cy/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/de/strings.xml b/desktop_version/lang/de/strings.xml index 8bc440f8..d08033a4 100644 --- a/desktop_version/lang/de/strings.xml +++ b/desktop_version/lang/de/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/en/strings.xml b/desktop_version/lang/en/strings.xml index 86a4217f..5ce4803b 100644 --- a/desktop_version/lang/en/strings.xml +++ b/desktop_version/lang/en/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/eo/strings.xml b/desktop_version/lang/eo/strings.xml index 6c085043..4884154b 100644 --- a/desktop_version/lang/eo/strings.xml +++ b/desktop_version/lang/eo/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/es/strings.xml b/desktop_version/lang/es/strings.xml index 68c8a246..493b2b1e 100644 --- a/desktop_version/lang/es/strings.xml +++ b/desktop_version/lang/es/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/es_419/strings.xml b/desktop_version/lang/es_419/strings.xml index 827a3b97..ea50cfc3 100644 --- a/desktop_version/lang/es_419/strings.xml +++ b/desktop_version/lang/es_419/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/es_AR/strings.xml b/desktop_version/lang/es_AR/strings.xml index e2cdc457..ff360450 100644 --- a/desktop_version/lang/es_AR/strings.xml +++ b/desktop_version/lang/es_AR/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/fr/strings.xml b/desktop_version/lang/fr/strings.xml index 411cc564..f074c748 100644 --- a/desktop_version/lang/fr/strings.xml +++ b/desktop_version/lang/fr/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/ga/strings.xml b/desktop_version/lang/ga/strings.xml index cbdf9987..07168eb3 100644 --- a/desktop_version/lang/ga/strings.xml +++ b/desktop_version/lang/ga/strings.xml @@ -624,6 +624,7 @@ Déan cóip chúltaca, ar eagla na heagla." explanation="translation maintenance + diff --git a/desktop_version/lang/it/strings.xml b/desktop_version/lang/it/strings.xml index f4798b2b..ca6cf2b3 100644 --- a/desktop_version/lang/it/strings.xml +++ b/desktop_version/lang/it/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/ja/strings.xml b/desktop_version/lang/ja/strings.xml index f7fe0042..b1cdf6ac 100644 --- a/desktop_version/lang/ja/strings.xml +++ b/desktop_version/lang/ja/strings.xml @@ -658,6 +658,7 @@ Steam Deckには対応していません。" explanation="" max="38*5" max_local + diff --git a/desktop_version/lang/ko/strings.xml b/desktop_version/lang/ko/strings.xml index e7b69f1f..443fc638 100755 --- a/desktop_version/lang/ko/strings.xml +++ b/desktop_version/lang/ko/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/nl/strings.xml b/desktop_version/lang/nl/strings.xml index 6d1aeebc..10935c08 100644 --- a/desktop_version/lang/nl/strings.xml +++ b/desktop_version/lang/nl/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/pl/strings.xml b/desktop_version/lang/pl/strings.xml index 059bd1ed..5a41019d 100644 --- a/desktop_version/lang/pl/strings.xml +++ b/desktop_version/lang/pl/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/pt_BR/strings.xml b/desktop_version/lang/pt_BR/strings.xml index 0d084ab8..7d361b27 100644 --- a/desktop_version/lang/pt_BR/strings.xml +++ b/desktop_version/lang/pt_BR/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/pt_PT/strings.xml b/desktop_version/lang/pt_PT/strings.xml index 3d24a84f..76b74963 100644 --- a/desktop_version/lang/pt_PT/strings.xml +++ b/desktop_version/lang/pt_PT/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/ru/strings.xml b/desktop_version/lang/ru/strings.xml index 04c6476b..c09caf4b 100644 --- a/desktop_version/lang/ru/strings.xml +++ b/desktop_version/lang/ru/strings.xml @@ -647,6 +647,7 @@ + diff --git a/desktop_version/lang/szl/strings.xml b/desktop_version/lang/szl/strings.xml index 3eadda25..688ad9f8 100644 --- a/desktop_version/lang/szl/strings.xml +++ b/desktop_version/lang/szl/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/tr/strings.xml b/desktop_version/lang/tr/strings.xml index c7cfdf82..681feb6d 100644 --- a/desktop_version/lang/tr/strings.xml +++ b/desktop_version/lang/tr/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/uk/strings.xml b/desktop_version/lang/uk/strings.xml index dbfc81a9..fb6ae76d 100644 --- a/desktop_version/lang/uk/strings.xml +++ b/desktop_version/lang/uk/strings.xml @@ -622,6 +622,7 @@ + diff --git a/desktop_version/lang/zh/strings.xml b/desktop_version/lang/zh/strings.xml index d437c5ba..403405d7 100644 --- a/desktop_version/lang/zh/strings.xml +++ b/desktop_version/lang/zh/strings.xml @@ -632,6 +632,7 @@ + diff --git a/desktop_version/lang/zh_TW/strings.xml b/desktop_version/lang/zh_TW/strings.xml index 157c0cba..d78acc4b 100644 --- a/desktop_version/lang/zh_TW/strings.xml +++ b/desktop_version/lang/zh_TW/strings.xml @@ -632,6 +632,7 @@ + diff --git a/desktop_version/src/CustomLevels.cpp b/desktop_version/src/CustomLevels.cpp index 704bed37..347bff9a 100644 --- a/desktop_version/src/CustomLevels.cpp +++ b/desktop_version/src/CustomLevels.cpp @@ -57,6 +57,7 @@ RoomProperty::RoomProperty(void) enemyx2=320; enemyy2=240; enemytype=0; + enemyv=0; directmode=0; } @@ -389,6 +390,7 @@ void customlevelclass::reset(void) roomproperties[i+(j*maxwidth)].enemyx2=320; roomproperties[i+(j*maxwidth)].enemyy2=240; roomproperties[i+(j*maxwidth)].enemytype=0; + roomproperties[i+(j*maxwidth)].enemyv=0; roomproperties[i+(j*maxwidth)].directmode=0; } } @@ -1264,6 +1266,7 @@ bool customlevelclass::load(std::string _path) edLevelClassElement->QueryIntAttribute("enemyx2", &roomproperties[i].enemyx2); edLevelClassElement->QueryIntAttribute("enemyy2", &roomproperties[i].enemyy2); edLevelClassElement->QueryIntAttribute("enemytype", &roomproperties[i].enemytype); + edLevelClassElement->QueryIntAttribute("enemyv", &roomproperties[i].enemyv); edLevelClassElement->QueryIntAttribute("directmode", &roomproperties[i].directmode); edLevelClassElement->QueryIntAttribute("warpdir", &roomproperties[i].warpdir); @@ -1645,6 +1648,7 @@ bool customlevelclass::save(const std::string& _path) roompropertyElement->SetAttribute( "enemyx2", roomproperties[i].enemyx2); roompropertyElement->SetAttribute( "enemyy2", roomproperties[i].enemyy2); roompropertyElement->SetAttribute( "enemytype", roomproperties[i].enemytype); + roompropertyElement->SetAttribute( "enemyv", roomproperties[i].enemyv); roompropertyElement->SetAttribute( "directmode", roomproperties[i].directmode); roompropertyElement->SetAttribute( "warpdir", roomproperties[i].warpdir); diff --git a/desktop_version/src/CustomLevels.h b/desktop_version/src/CustomLevels.h index 97e3448d..b728d412 100644 --- a/desktop_version/src/CustomLevels.h +++ b/desktop_version/src/CustomLevels.h @@ -31,6 +31,7 @@ public: FOREACH_PROP(enemyx2, int) \ FOREACH_PROP(enemyy2, int) \ FOREACH_PROP(enemytype, int) \ + FOREACH_PROP(enemyv, int) \ FOREACH_PROP(directmode, int) class RoomProperty diff --git a/desktop_version/src/Editor.cpp b/desktop_version/src/Editor.cpp index 322510bf..2a04509e 100644 --- a/desktop_version/src/Editor.cpp +++ b/desktop_version/src/Editor.cpp @@ -3096,12 +3096,22 @@ static void handle_draw_input() const int room = ed.levx + ed.levy * cl.maxwidth; const int plat_speed = cl.roomproperties[room].platv; + const int enemy_speed = cl.roomproperties[room].enemyv; + const bool ctrl = key.keymap[SDLK_LCTRL] || key.keymap[SDLK_RCTRL]; + const bool shift = key.keymap[SDLK_LSHIFT] || key.keymap[SDLK_RSHIFT]; if (key.keymap[SDLK_COMMA]) { - if (key.keymap[SDLK_LCTRL] || key.keymap[SDLK_RCTRL]) + if (ctrl) { - cl.roomproperties[room].platv = plat_speed - 1; + if (shift) + { + cl.roomproperties[room].enemyv = enemy_speed - 1; + } + else + { + cl.roomproperties[room].platv = plat_speed - 1; + } } else { @@ -3111,9 +3121,16 @@ static void handle_draw_input() } else if (key.keymap[SDLK_PERIOD]) { - if (key.keymap[SDLK_LCTRL] || key.keymap[SDLK_RCTRL]) + if (ctrl) { - cl.roomproperties[room].platv = plat_speed + 1; + if (shift) + { + cl.roomproperties[room].enemyv = enemy_speed + 1; + } + else + { + cl.roomproperties[room].platv = plat_speed + 1; + } } else { @@ -3134,6 +3151,18 @@ static void handle_draw_input() ed.show_note(buffer); } + if (enemy_speed != cl.roomproperties[room].enemyv) + { + char buffer[3 * SCREEN_WIDTH_CHARS + 1]; + vformat_buf( + buffer, sizeof(buffer), + loc::gettext("Enemy speed is now {speed}"), + "speed:int", + cl.roomproperties[room].enemyv + 4 + ); + ed.show_note(buffer); + } + if (key.keymap[SDLK_SPACE]) { ed.toolbox_open = !ed.toolbox_open; diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index 747ebc38..ee7a904f 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -1850,7 +1850,7 @@ void mapclass::loadlevel(int rx, int ry) { case 1: // Enemies obj.customenemy = room->enemytype; - obj.createentity(ex, ey, 56, ent.p1, 4, bx1, by1, bx2, by2); + obj.createentity(ex, ey, 56, ent.p1, 4 + room->enemyv, bx1, by1, bx2, by2); break; case 2: // Platforms and conveyors if (ent.p1 <= 4) From 32562f03a961057b4f63cadc1536d59b1848b1db Mon Sep 17 00:00:00 2001 From: Misa Date: Fri, 30 Aug 2024 10:19:27 -0700 Subject: [PATCH 03/64] Give MotU trophy in normal mode This makes it so that it is possible to obtain the Master of the Universe trophy/achievement, usually unlocked by beating No Death Mode, outside of NDM. There are several conditions that need to be met: 1. The game needs to be started from a new game and cannot be from loading a save. 2. Accessibility modes (invincibility and slowdown) must never be enabled. If either condition is violated, then the boolean that keeps track of NDM eligibility will be set to false. --- desktop_version/src/Game.cpp | 22 ++++++++++++++++++++-- desktop_version/src/Game.h | 2 ++ desktop_version/src/Logic.cpp | 2 ++ desktop_version/src/Script.cpp | 11 +++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 1d7bad14..d7f3818d 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -225,6 +225,7 @@ void Game::init(void) ndmresulthardestroom_x = hardestroom_x; ndmresulthardestroom_y = hardestroom_y; ndmresulthardestroom_specialname = false; + nodeatheligible = false; customcol=0; @@ -3312,11 +3313,14 @@ void Game::updatestate(void) } } - - if (nodeathmode) + if (nodeathmode || nodeatheligible) { unlockAchievement("vvvvvvmaster"); //bloody hell unlocknum(UnlockTrophy_NODEATHMODE_COMPLETE); + } + + if (nodeathmode) + { setstate(3520); setstatedelay(0); } @@ -7768,6 +7772,11 @@ void Game::returntoingame(void) } } DEFER_CALLBACK(nextbgcolor); + + if (nocompetitive()) + { + invalidate_ndm_trophy(); + } } void Game::unlockAchievement(const char* name) @@ -7820,6 +7829,15 @@ void Game::copyndmresults(void) SDL_memcpy(ndmresultcrewstats, crewstats, sizeof(ndmresultcrewstats)); } +void Game::invalidate_ndm_trophy(void) +{ + if (nodeatheligible) + { + vlog_debug("NDM trophy is invalidated!"); + } + nodeatheligible = false; +} + static inline int get_framerate(const int slowdown) { switch (slowdown) diff --git a/desktop_version/src/Game.h b/desktop_version/src/Game.h index 362a956c..20c71a4d 100644 --- a/desktop_version/src/Game.h +++ b/desktop_version/src/Game.h @@ -432,6 +432,8 @@ public: int ndmresulthardestroom_y; bool ndmresulthardestroom_specialname; void copyndmresults(void); + bool nodeatheligible; + void invalidate_ndm_trophy(void); //Time Trials bool intimetrial, timetrialparlost; diff --git a/desktop_version/src/Logic.cpp b/desktop_version/src/Logic.cpp index 7046e871..67dd637a 100644 --- a/desktop_version/src/Logic.cpp +++ b/desktop_version/src/Logic.cpp @@ -461,6 +461,8 @@ void gamelogic(void) game.deathseq--; if (game.deathseq <= 0) { + game.invalidate_ndm_trophy(); + if (game.nodeathmode) { game.deathseq = 1; diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index a58b1735..d939a600 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -2651,6 +2651,16 @@ void scriptclass::startgamemode(const enum StartMode mode) graphics.showcutscenebars = true; graphics.setbars(320); load("intro"); + + if (!game.nocompetitive()) + { + game.nodeatheligible = true; + vlog_debug("NDM trophy is eligible."); + } + else + { + game.invalidate_ndm_trophy(); + } } break; @@ -3088,6 +3098,7 @@ void scriptclass::hardreset(void) game.nodeathmode = false; game.nocutscenes = false; + game.nodeatheligible = false; for (i = 0; i < (int) SDL_arraysize(game.crewstats); i++) { From c870df4e5b7eba425712e5a62f9bef20144e6434 Mon Sep 17 00:00:00 2001 From: Misa Date: Sun, 15 Sep 2024 23:53:56 -0700 Subject: [PATCH 04/64] Remove slowdown during death animation Some discussion on the Discord server resulted in this change. It's a quality-of-life improvement where, if the game is in slowdown mode, it will return to 100% speed for the duration of the death animation. The reasoning is obvious. There is nothing to do during the death animation, so making it take longer during slowdown is just an annoyance to the player, almost a penalty for them using an accessibility option. This is the same reason why slowdown no longer applies in menus, etc. --- desktop_version/src/Game.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index d7f3818d..14647d58 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -7838,8 +7838,13 @@ void Game::invalidate_ndm_trophy(void) nodeatheligible = false; } -static inline int get_framerate(const int slowdown) +static inline int get_framerate(const int slowdown, const int deathseq) { + if (deathseq != -1) + { + return 34; + } + switch (slowdown) { case 30: @@ -7868,7 +7873,7 @@ int Game::get_timestep(void) switch (gamestate) { case GAMEMODE: - return get_framerate(slowdown); + return get_framerate(slowdown, deathseq); default: return 34; } From 8aec83daec5585dbcdd1898d380a75c83eb52892 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Wed, 5 Jun 2024 09:17:04 -0300 Subject: [PATCH 05/64] Checkpoint autosaving --- desktop_version/src/Entity.cpp | 7 +++++++ desktop_version/src/Game.cpp | 12 ++++++++++++ desktop_version/src/Game.h | 1 + desktop_version/src/Script.cpp | 7 +++++++ 4 files changed, 27 insertions(+) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index f70246d7..7e477dae 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -2749,6 +2749,13 @@ bool entityclass::updateentities( int i ) game.savedir = entities[player].dir; } entities[i].state = 0; + + if (game.checkpoint_saving) + { + bool success = game.savequick(); + game.gamesaved = success; + game.gamesavefailed = !success; + } } break; case 9: //Gravity Lines diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 14647d58..f01bc034 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -377,6 +377,12 @@ void Game::init(void) screenshot_border_timer = 0; screenshot_saved_success = false; +#ifdef __ANDROID__ + checkpoint_saving = true; +#else + checkpoint_saving = false; +#endif + setdefaultcontrollerbuttons(); } @@ -4940,6 +4946,10 @@ void Game::deserializesettings(tinyxml2::XMLElement* dataNode, struct ScreenSett roomname_translator::set_enabled(help.Int(pText)); } + if (SDL_strcmp(pKey, "checkpoint_saving") == 0) + { + checkpoint_saving = help.Int(pText); + } } setdefaultcontrollerbuttons(); @@ -5198,6 +5208,8 @@ void Game::serializesettings(tinyxml2::XMLElement* dataNode, const struct Screen xml::update_tag(dataNode, "english_sprites", (int) loc::english_sprites); xml::update_tag(dataNode, "new_level_font", loc::new_level_font.c_str()); xml::update_tag(dataNode, "roomname_translator", (int) roomname_translator::enabled); + + xml::update_tag(dataNode, "checkpoint_saving", (int) checkpoint_saving); } static bool settings_loaded = false; diff --git a/desktop_version/src/Game.h b/desktop_version/src/Game.h index 20c71a4d..64fcb5a2 100644 --- a/desktop_version/src/Game.h +++ b/desktop_version/src/Game.h @@ -363,6 +363,7 @@ public: int savetrinkets; bool startscript; std::string newscript; + bool checkpoint_saving; bool menustart; diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index d939a600..3353ee2d 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -1206,6 +1206,13 @@ void scriptclass::run(void) { game.savedir = obj.entities[i].dir; } + + if (game.checkpoint_saving) + { + bool success = game.savequick(); + game.gamesaved = success; + game.gamesavefailed = !success; + } } else if (words[0] == "gamestate") { From e58fd606cff3cfe25bcdc97f31d2fb4de851eb35 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Thu, 26 Sep 2024 13:20:18 -0300 Subject: [PATCH 06/64] add menu option for checkpoint saving --- desktop_version/lang/ar/strings.xml | 5 +++++ desktop_version/lang/ca/strings.xml | 5 +++++ desktop_version/lang/cy/strings.xml | 5 +++++ desktop_version/lang/de/strings.xml | 5 +++++ desktop_version/lang/en/strings.xml | 5 +++++ desktop_version/lang/eo/strings.xml | 5 +++++ desktop_version/lang/es/strings.xml | 5 +++++ desktop_version/lang/es_419/strings.xml | 5 +++++ desktop_version/lang/es_AR/strings.xml | 5 +++++ desktop_version/lang/fr/strings.xml | 5 +++++ desktop_version/lang/ga/strings.xml | 5 +++++ desktop_version/lang/it/strings.xml | 5 +++++ desktop_version/lang/ja/strings.xml | 5 +++++ desktop_version/lang/ko/strings.xml | 5 +++++ desktop_version/lang/nl/strings.xml | 5 +++++ desktop_version/lang/pl/strings.xml | 5 +++++ desktop_version/lang/pt_BR/strings.xml | 5 +++++ desktop_version/lang/pt_PT/strings.xml | 5 +++++ desktop_version/lang/ru/strings.xml | 5 +++++ desktop_version/lang/szl/strings.xml | 5 +++++ desktop_version/lang/tr/strings.xml | 5 +++++ desktop_version/lang/uk/strings.xml | 5 +++++ desktop_version/lang/zh/strings.xml | 5 +++++ desktop_version/lang/zh_TW/strings.xml | 5 +++++ desktop_version/src/Game.cpp | 1 + desktop_version/src/Input.cpp | 6 ++++++ desktop_version/src/Render.cpp | 16 ++++++++++++++++ 27 files changed, 143 insertions(+) diff --git a/desktop_version/lang/ar/strings.xml b/desktop_version/lang/ar/strings.xml index 3788d484..7c192c43 100644 --- a/desktop_version/lang/ar/strings.xml +++ b/desktop_version/lang/ar/strings.xml @@ -236,6 +236,11 @@ + + + + + + + + + + diff --git a/desktop_version/lang/cy/strings.xml b/desktop_version/lang/cy/strings.xml index 3db5fbab..90b23913 100644 --- a/desktop_version/lang/cy/strings.xml +++ b/desktop_version/lang/cy/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/de/strings.xml b/desktop_version/lang/de/strings.xml index d08033a4..e869c9db 100644 --- a/desktop_version/lang/de/strings.xml +++ b/desktop_version/lang/de/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/en/strings.xml b/desktop_version/lang/en/strings.xml index 5ce4803b..ee3db7b6 100644 --- a/desktop_version/lang/en/strings.xml +++ b/desktop_version/lang/en/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/eo/strings.xml b/desktop_version/lang/eo/strings.xml index 4884154b..63fcd003 100644 --- a/desktop_version/lang/eo/strings.xml +++ b/desktop_version/lang/eo/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/es/strings.xml b/desktop_version/lang/es/strings.xml index 493b2b1e..c2cfae35 100644 --- a/desktop_version/lang/es/strings.xml +++ b/desktop_version/lang/es/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/es_419/strings.xml b/desktop_version/lang/es_419/strings.xml index ea50cfc3..ea6a1cf9 100644 --- a/desktop_version/lang/es_419/strings.xml +++ b/desktop_version/lang/es_419/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/es_AR/strings.xml b/desktop_version/lang/es_AR/strings.xml index ff360450..e9bf98b1 100644 --- a/desktop_version/lang/es_AR/strings.xml +++ b/desktop_version/lang/es_AR/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/fr/strings.xml b/desktop_version/lang/fr/strings.xml index f074c748..b7f69dc4 100644 --- a/desktop_version/lang/fr/strings.xml +++ b/desktop_version/lang/fr/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/ga/strings.xml b/desktop_version/lang/ga/strings.xml index 07168eb3..bb19ca2c 100644 --- a/desktop_version/lang/ga/strings.xml +++ b/desktop_version/lang/ga/strings.xml @@ -233,6 +233,11 @@ Déan cóip chúltaca, ar eagla na heagla." explanation="translation maintenance + + + + + diff --git a/desktop_version/lang/it/strings.xml b/desktop_version/lang/it/strings.xml index ca6cf2b3..4a3c32f3 100644 --- a/desktop_version/lang/it/strings.xml +++ b/desktop_version/lang/it/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/ja/strings.xml b/desktop_version/lang/ja/strings.xml index b1cdf6ac..0586db9e 100644 --- a/desktop_version/lang/ja/strings.xml +++ b/desktop_version/lang/ja/strings.xml @@ -246,6 +246,11 @@ Escキーを押すと表示を終了する。" explanation="" max="38*6" max_loc + + + + + diff --git a/desktop_version/lang/ko/strings.xml b/desktop_version/lang/ko/strings.xml index 443fc638..10ff2981 100755 --- a/desktop_version/lang/ko/strings.xml +++ b/desktop_version/lang/ko/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/nl/strings.xml b/desktop_version/lang/nl/strings.xml index 10935c08..09a551ae 100644 --- a/desktop_version/lang/nl/strings.xml +++ b/desktop_version/lang/nl/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/pl/strings.xml b/desktop_version/lang/pl/strings.xml index 5a41019d..c88a28fa 100644 --- a/desktop_version/lang/pl/strings.xml +++ b/desktop_version/lang/pl/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/pt_BR/strings.xml b/desktop_version/lang/pt_BR/strings.xml index 7d361b27..dd5d677b 100644 --- a/desktop_version/lang/pt_BR/strings.xml +++ b/desktop_version/lang/pt_BR/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/pt_PT/strings.xml b/desktop_version/lang/pt_PT/strings.xml index 76b74963..51ca859b 100644 --- a/desktop_version/lang/pt_PT/strings.xml +++ b/desktop_version/lang/pt_PT/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/ru/strings.xml b/desktop_version/lang/ru/strings.xml index c09caf4b..3b310c88 100644 --- a/desktop_version/lang/ru/strings.xml +++ b/desktop_version/lang/ru/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/szl/strings.xml b/desktop_version/lang/szl/strings.xml index 688ad9f8..38640252 100644 --- a/desktop_version/lang/szl/strings.xml +++ b/desktop_version/lang/szl/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/tr/strings.xml b/desktop_version/lang/tr/strings.xml index 681feb6d..cd98037d 100644 --- a/desktop_version/lang/tr/strings.xml +++ b/desktop_version/lang/tr/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/uk/strings.xml b/desktop_version/lang/uk/strings.xml index fb6ae76d..33c6fa97 100644 --- a/desktop_version/lang/uk/strings.xml +++ b/desktop_version/lang/uk/strings.xml @@ -232,6 +232,11 @@ + + + + + diff --git a/desktop_version/lang/zh/strings.xml b/desktop_version/lang/zh/strings.xml index 403405d7..a9b83ef0 100644 --- a/desktop_version/lang/zh/strings.xml +++ b/desktop_version/lang/zh/strings.xml @@ -238,6 +238,11 @@ + + + + + diff --git a/desktop_version/lang/zh_TW/strings.xml b/desktop_version/lang/zh_TW/strings.xml index d78acc4b..9d58c94e 100644 --- a/desktop_version/lang/zh_TW/strings.xml +++ b/desktop_version/lang/zh_TW/strings.xml @@ -238,6 +238,11 @@ + + + + + diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index f01bc034..fb80f66b 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -6868,6 +6868,7 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ ) option(loc::gettext("unfocus pause")); option(loc::gettext("unfocus audio pause")); option(loc::gettext("room name background")); + option(loc::gettext("checkpoint saving")); option(loc::gettext("return")); menuyoff = 0; maxspacing = 15; diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index 468c265a..c00f7362 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -862,6 +862,12 @@ static void menuactionpress(void) game.savestatsandsettings_menu(); music.playef(Sound_VIRIDIAN); break; + case 3: + // toggle checkpoint saving + game.checkpoint_saving = !game.checkpoint_saving; + game.savestatsandsettings_menu(); + music.playef(Sound_VIRIDIAN); + break; default: //back music.playef(Sound_VIRIDIAN); diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index 20efc8ff..9b22bd89 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -1139,6 +1139,7 @@ static void menurender(void) break; } case 2: + { font::print(PR_2X | PR_CEN, -1, 30, loc::gettext("Room Name BG"), tr, tg, tb); int next_y = font::print_wrap(PR_CEN, -1, 65, loc::gettext("Lets you see through what is behind the name at the bottom of the screen."), tr, tg, tb); if (graphics.translucentroomname) @@ -1147,6 +1148,21 @@ static void menurender(void) font::print_wrap(PR_CEN, -1, next_y, loc::gettext("Room name background is OPAQUE"), tr, tg, tb); break; } + case 3: + { + font::print(PR_2X | PR_CEN, -1, 30, loc::gettext("Checkpoint Saving"), tr, tg, tb); + int next_y = font::print_wrap(PR_CEN, -1, 65, loc::gettext("Toggle if checkpoints should save the game."), tr, tg, tb); + if (game.checkpoint_saving) + { + font::print_wrap(PR_CEN, -1, next_y, loc::gettext("Checkpoint saving is OFF"), tr / 2, tg / 2, tb / 2); + } + else + { + font::print_wrap(PR_CEN, -1, next_y, loc::gettext("Checkpoint saving is ON"), tr, tg, tb); + } + break; + } + } break; case Menu::accessibility: { From 41d5e688e940c1b59b349189779f0460978e1a11 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Thu, 26 Sep 2024 13:32:46 -0300 Subject: [PATCH 07/64] Fix menu option, show textbox when save failed In my last commit, I accidentally inverted whether the description says ON or OFF. --- desktop_version/src/Entity.cpp | 5 +++++ desktop_version/src/Game.cpp | 17 +++++++++++------ desktop_version/src/Game.h | 1 + desktop_version/src/Render.cpp | 2 +- desktop_version/src/Script.cpp | 5 +++++ 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 7e477dae..1946fd41 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -2755,6 +2755,11 @@ bool entityclass::updateentities( int i ) bool success = game.savequick(); game.gamesaved = success; game.gamesavefailed = !success; + + if (game.gamesavefailed) { + game.show_save_fail(); + graphics.textboxapplyposition(); + } } } break; diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index fb80f66b..72ea288a 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -828,7 +828,7 @@ static void savetele_textbox_success(textboxclass* THIS) THIS->pad(3, 3); } -static void savetele_textbox_fail(textboxclass* THIS) +static void save_textbox_fail(textboxclass* THIS) { THIS->lines.clear(); THIS->lines.push_back(loc::gettext("ERROR: Could not save game!")); @@ -836,6 +836,15 @@ static void savetele_textbox_fail(textboxclass* THIS) THIS->pad(1, 1); } +void Game::show_save_fail(void) +{ + graphics.createtextboxflipme("", -1, 12, TEXT_COLOUR("red")); + graphics.textboxprintflags(PR_FONT_INTERFACE); + graphics.textboxcenterx(); + graphics.textboxtimer(50); + graphics.textboxtranslate(TEXTTRANSLATE_FUNCTION, save_textbox_fail); +} + void Game::savetele_textbox(void) { if (inspecial() || map.custommode) @@ -853,11 +862,7 @@ void Game::savetele_textbox(void) } else { - graphics.createtextboxflipme("", -1, 12, TEXT_COLOUR("red")); - graphics.textboxprintflags(PR_FONT_INTERFACE); - graphics.textboxcenterx(); - graphics.textboxtimer(50); - graphics.textboxtranslate(TEXTTRANSLATE_FUNCTION, savetele_textbox_fail); + show_save_fail(); } graphics.textboxapplyposition(); } diff --git a/desktop_version/src/Game.h b/desktop_version/src/Game.h index 64fcb5a2..b416859a 100644 --- a/desktop_version/src/Game.h +++ b/desktop_version/src/Game.h @@ -225,6 +225,7 @@ public: void crewmate_textbox(const int color); void remaining_textbox(void); void actionprompt_textbox(void); + void show_save_fail(void); void savetele_textbox(void); void setstate(int gamestate); diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index 9b22bd89..252dc53d 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -1152,7 +1152,7 @@ static void menurender(void) { font::print(PR_2X | PR_CEN, -1, 30, loc::gettext("Checkpoint Saving"), tr, tg, tb); int next_y = font::print_wrap(PR_CEN, -1, 65, loc::gettext("Toggle if checkpoints should save the game."), tr, tg, tb); - if (game.checkpoint_saving) + if (!game.checkpoint_saving) { font::print_wrap(PR_CEN, -1, next_y, loc::gettext("Checkpoint saving is OFF"), tr / 2, tg / 2, tb / 2); } diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 3353ee2d..9160e7fe 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -1212,6 +1212,11 @@ void scriptclass::run(void) bool success = game.savequick(); game.gamesaved = success; game.gamesavefailed = !success; + + if (game.gamesavefailed) { + game.show_save_fail(); + graphics.textboxapplyposition(); + } } } else if (words[0] == "gamestate") From c04c6bc552042d933fd49ee89e1b1be61b8834a4 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Thu, 26 Sep 2024 15:25:13 -0300 Subject: [PATCH 08/64] Abstract checkpoint saving to its own function This also makes the save failed textbox not appear in special modes, and allows custom levels to quicksave from checkpoints as well. --- desktop_version/src/Entity.cpp | 12 +----------- desktop_version/src/Game.cpp | 16 ++++++++++++++++ desktop_version/src/Game.h | 1 + desktop_version/src/Script.cpp | 12 +----------- 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 1946fd41..5023b16b 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -2750,17 +2750,7 @@ bool entityclass::updateentities( int i ) } entities[i].state = 0; - if (game.checkpoint_saving) - { - bool success = game.savequick(); - game.gamesaved = success; - game.gamesavefailed = !success; - - if (game.gamesavefailed) { - game.show_save_fail(); - graphics.textboxapplyposition(); - } - } + game.checkpoint_save(); } break; case 9: //Gravity Lines diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 72ea288a..c8fdc0d7 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -845,6 +845,22 @@ void Game::show_save_fail(void) graphics.textboxtranslate(TEXTTRANSLATE_FUNCTION, save_textbox_fail); } +void Game::checkpoint_save(void) +{ + if (checkpoint_saving && !inspecial()) + { + bool success = map.custommode ? customsavequick(cl.ListOfMetaData[playcustomlevel].filename) : savequick(); + gamesaved = success; + gamesavefailed = !success; + + if (gamesavefailed) + { + show_save_fail(); + graphics.textboxapplyposition(); + } + } +} + void Game::savetele_textbox(void) { if (inspecial() || map.custommode) diff --git a/desktop_version/src/Game.h b/desktop_version/src/Game.h index b416859a..05817b05 100644 --- a/desktop_version/src/Game.h +++ b/desktop_version/src/Game.h @@ -226,6 +226,7 @@ public: void remaining_textbox(void); void actionprompt_textbox(void); void show_save_fail(void); + void checkpoint_save(void); void savetele_textbox(void); void setstate(int gamestate); diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 9160e7fe..b4cd8f9b 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -1207,17 +1207,7 @@ void scriptclass::run(void) game.savedir = obj.entities[i].dir; } - if (game.checkpoint_saving) - { - bool success = game.savequick(); - game.gamesaved = success; - game.gamesavefailed = !success; - - if (game.gamesavefailed) { - game.show_save_fail(); - graphics.textboxapplyposition(); - } - } + game.checkpoint_save(); } else if (words[0] == "gamestate") { From 8a00ea7aabd52877831f2a66ff4562488d44956c Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Wed, 23 Aug 2023 13:03:23 -0700 Subject: [PATCH 09/64] Add mapexplored(), mapreveal() commands --- desktop_version/src/Game.cpp | 6 ++++++ desktop_version/src/Map.cpp | 18 ++++++++++++++---- desktop_version/src/Map.h | 4 ++++ desktop_version/src/Script.cpp | 27 ++++++++++++++++++++++++++- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index c8fdc0d7..b33333a0 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -5930,6 +5930,10 @@ void Game::customloadquick(const std::string& savfile) { map.customshowmm = help.Int(pText); } + else if (SDL_strcmp(pKey, "mapreveal") == 0) + { + map.revealmap = help.Int(pText); + } else if (SDL_strcmp(pKey, "disabletemporaryaudiopause") == 0) { disabletemporaryaudiopause = help.Int(pText); @@ -6369,6 +6373,8 @@ bool Game::customsavequick(const std::string& savfile) xml::update_tag(msgs, "showminimap", (int) map.customshowmm); + xml::update_tag(msgs, "mapreveal", (int) map.revealmap); + xml::update_tag(msgs, "disabletemporaryaudiopause", (int) disabletemporaryaudiopause); xml::update_tag(msgs, "showtrinkets", (int) map.showtrinkets); diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index ee7a904f..2b822c11 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -55,6 +55,7 @@ mapclass::mapclass(void) custommmxoff=0; custommmyoff=0; custommmxsize=0; custommmysize=0; customzoom=0; customshowmm=true; + revealmap = true; rcol = 0; @@ -198,6 +199,12 @@ void mapclass::resetmap(void) SDL_memset(explored, 0, sizeof(explored)); } +void mapclass::fullmap(void) +{ + //mark the whole map as explored + SDL_memset(explored, 1, sizeof(explored)); +} + void mapclass::updateroomnames(void) { if (roomnameset) @@ -1304,12 +1311,15 @@ static void copy_short_to_int(int* dest, const short* src, const size_t size) void mapclass::loadlevel(int rx, int ry) { int t; - if (!finalmode) + if (revealmap) { - setexplored(rx - 100, ry - 100, true); - if (rx == 109 && !custommode) + if (!finalmode) { - exploretower(); + setexplored(rx - 100, ry - 100, true); + if (rx == 109 && !custommode) + { + exploretower(); + } } } diff --git a/desktop_version/src/Map.h b/desktop_version/src/Map.h index d809c2e7..243938c6 100644 --- a/desktop_version/src/Map.h +++ b/desktop_version/src/Map.h @@ -58,6 +58,8 @@ public: void resetmap(void); + void fullmap(void); + void updateroomnames(void); void initmapdata(void); @@ -125,6 +127,8 @@ public: bool isexplored(const int rx, const int ry); void setexplored(const int rx, const int ry, const bool status); + bool revealmap; + int background; int rcol; int tileset; diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index b4cd8f9b..188ef45c 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -1330,6 +1330,28 @@ void scriptclass::run(void) map.setexplored(19, 7, false); map.setexplored(19, 8, false); } + else if (words[0] == "mapexplored") + { + if (words[1] == "none") + { + map.resetmap(); + } + else if (words[1] == "all") + { + map.fullmap(); + } + } + else if (words[0] == "mapreveal") + { + if (words[1] == "on") + { + map.revealmap = true; + } + else if (words[1] == "off") + { + map.revealmap = false; + } + } else if (words[0] == "showteleporters") { map.showteleporters = true; @@ -2830,6 +2852,7 @@ void scriptclass::startgamemode(const enum StartMode mode) map.custommode = true; map.custommodeforreal = false; map.customshowmm = true; + map.revealmap = true; if (cl.levmusic > 0) { @@ -2856,6 +2879,7 @@ void scriptclass::startgamemode(const enum StartMode mode) cl.findstartpoint(); map.customshowmm = true; + map.revealmap = true; music.fadeout(); game.customstart(); @@ -3228,7 +3252,8 @@ void scriptclass::hardreset(void) map.cameraseekframe = 0; map.resumedelay = 0; graphics.towerbg.scrolldir = 0; - map.customshowmm=true; + map.customshowmm = true; + map.revealmap = true; SDL_memset(map.roomdeaths, 0, sizeof(map.roomdeaths)); SDL_memset(map.roomdeathsfinal, 0, sizeof(map.roomdeathsfinal)); From a0bd2f3da42da2f5249e2a4892e2b48b51b2fd86 Mon Sep 17 00:00:00 2001 From: Misa Date: Sat, 28 Sep 2024 00:52:19 +0000 Subject: [PATCH 10/64] Refactor: Use fullmap() everywhere This replaces all instances of unlocking all rooms on the map with calls to map.fullmap(), for consistency. This also fixes two comments that got swapped around in startgamemode(). I don't know how that happened. [skip ci] --- desktop_version/src/Script.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 188ef45c..7c005567 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -1437,7 +1437,7 @@ void scriptclass::run(void) { game.unlocknum(Unlock_SECRETLAB); game.insecretlab = true; - SDL_memset(map.explored, true, sizeof(map.explored)); + map.fullmap(); } else if (words[0] == "leavesecretlab") { @@ -2746,7 +2746,7 @@ void scriptclass::startgamemode(const enum StartMode mode) { game.timetrialcountdown = 0; game.timetrialparlost = true; - SDL_memset(map.explored, true, sizeof(map.explored)); + map.fullmap(); } graphics.fademode = FADE_START_FADEIN; @@ -2756,9 +2756,9 @@ void scriptclass::startgamemode(const enum StartMode mode) game.startspecial(0); /* Unlock the entire map */ - SDL_memset(obj.collect, true, sizeof(obj.collect[0]) * 20); + map.fullmap(); /* Give all 20 trinkets */ - SDL_memset(map.explored, true, sizeof(map.explored)); + SDL_memset(obj.collect, true, sizeof(obj.collect[0]) * 20); i = 400; /* previously a nested for-loop set this */ game.insecretlab = true; map.showteleporters = true; From c2642dbdefb13dd6d8f52043627cb70d51ba985e Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Tue, 1 Oct 2024 19:01:04 -0300 Subject: [PATCH 11/64] Add more checks for checkpoint saving --- desktop_version/src/Game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index b33333a0..86805c2a 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -847,7 +847,7 @@ void Game::show_save_fail(void) void Game::checkpoint_save(void) { - if (checkpoint_saving && !inspecial()) + if (checkpoint_saving && !inspecial() && (!map.custommode || (map.custommode && map.custommodeforreal)) && !cliplaytest) { bool success = map.custommode ? customsavequick(cl.ListOfMetaData[playcustomlevel].filename) : savequick(); gamesaved = success; From 4587fa46b0899764bc5f0966fecaf3f9571e1811 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Sat, 5 Oct 2024 16:33:24 -0400 Subject: [PATCH 12/64] update android sdl2 to 2.30.8 --- .github/workflows/android.yml | 4 ++-- desktop_version/VVVVVV-android/README.md | 10 +++++----- desktop_version/VVVVVV-android/app/build.gradle | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 37e9a960..3108e743 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -65,7 +65,7 @@ jobs: - uses: actions/checkout@v4 with: repository: libsdl-org/SDL - ref: release-2.28.5 + ref: release-2.30.8 path: 'SDL' - name: Build SDL @@ -73,7 +73,7 @@ jobs: sudo apt-get -y install ninja-build cd SDL ./build-scripts/android-prefab.sh - mvn install:install-file -Dfile=build-android-prefab/prefab-2.28.5/SDL2-2.28.5.aar -DpomFile=build-android-prefab/prefab-2.28.5/SDL2-2.28.5.pom + mvn install:install-file -Dfile=build-android-prefab/prefab-2.30.8/SDL2-2.30.8.aar -DpomFile=build-android-prefab/prefab-2.30.8/SDL2-2.30.8.pom - name: Build run: | diff --git a/desktop_version/VVVVVV-android/README.md b/desktop_version/VVVVVV-android/README.md index 46b6d401..b7305828 100644 --- a/desktop_version/VVVVVV-android/README.md +++ b/desktop_version/VVVVVV-android/README.md @@ -10,18 +10,18 @@ How to Build ------------ The recommended way is to install Android Studio and Maven. These instructions are for -SDL 2.28.5; adapt your SDL version accordingly. +SDL 2.30.8; adapt your SDL version accordingly. 1. Place a copy of `data.zip` in `desktop_version/VVVVVV-android/app/src/main/assets/`. (If the `assets/` folder doesn't exist, then create it.) -2. Obtain the SDL 2.28.5 Maven package. As of writing, SDL currently does not publish +2. Obtain the SDL 2.30.8 Maven package. As of writing, SDL currently does not publish Maven packages, so here is one way to obtain them (other methods are possible): - 1. Download the SDL 2.28.5 source code. + 1. Download the SDL 2.30.8 source code. 2. Run the `build-scripts/android-prefab.sh` script in the SDL repository. 3. After building, run `mvn install:install-file - -Dfile=build-android-prefab/prefab-2.28.5/SDL2-2.28.5.aar - -DpomFile=build-android-prefab/prefab-2.28.5/SDL2-2.28.5.pom` to install it to + -Dfile=build-android-prefab/prefab-2.30.8/SDL2-2.30.8.aar + -DpomFile=build-android-prefab/prefab-2.30.8/SDL2-2.30.8.pom` to install it to Maven Local. 3. Open the `desktop_version/VVVVVV-android/` folder in Android Studio. diff --git a/desktop_version/VVVVVV-android/app/build.gradle b/desktop_version/VVVVVV-android/app/build.gradle index 7eaecbdd..f1b358ce 100644 --- a/desktop_version/VVVVVV-android/app/build.gradle +++ b/desktop_version/VVVVVV-android/app/build.gradle @@ -110,5 +110,5 @@ dependencies { implementation 'org.jetbrains:annotations:15.0' implementation 'androidx.core:core:1.10.1' implementation 'androidx.exifinterface:exifinterface:1.3.6' - implementation 'org.libsdl.android:SDL2:2.28.5' + implementation 'org.libsdl.android:SDL2:2.30.8' } From 11d0e7f91e52f8d729503bd864109954d00e7ba9 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Thu, 10 Oct 2024 16:35:25 -0400 Subject: [PATCH 13/64] correctly set VVV_CXX_SRC flags (set_source_files_properties isn't cumulative) --- desktop_version/CMakeLists.txt | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/desktop_version/CMakeLists.txt b/desktop_version/CMakeLists.txt index 28b4b4b8..f2cfa3b9 100644 --- a/desktop_version/CMakeLists.txt +++ b/desktop_version/CMakeLists.txt @@ -280,17 +280,15 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") target_compile_options(VVVVVV PRIVATE -Wno-c99-extensions) endif() +# Set standards version, disable exceptions and RTTI if(MSVC) # MSVC doesn't have /std:c99 or /std:c++98 switches! # MSVC does not officially support disabling exceptions, # so this is as far as we are willing to go to disable them. string(REGEX REPLACE "/EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - set_source_files_properties(${VVV_CXX_SRC} PROPERTIES COMPILE_FLAGS /EHsc) - - # Disable RTTI string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - set_source_files_properties(${VVV_CXX_SRC} PROPERTIES COMPILE_FLAGS /GR-) + set_source_files_properties(${VVV_CXX_SRC} PROPERTIES COMPILE_FLAGS "/EHsc /GR-") if(MSVC_VERSION GREATER 1900) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8") @@ -301,15 +299,9 @@ else() set_source_files_properties(${VVV_C_SRC} PROPERTIES COMPILE_FLAGS -std=c99) string(REGEX REPLACE "-std=[a-z0-9+]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - set_source_files_properties(${VVV_CXX_SRC} PROPERTIES COMPILE_FLAGS -std=c++98) - - # Disable exceptions string(REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - set_source_files_properties(${VVV_CXX_SRC} PROPERTIES COMPILE_FLAGS -fno-exceptions) - - # Disable RTTI string(REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - set_source_files_properties(${VVV_CXX_SRC} PROPERTIES COMPILE_FLAGS -fno-rtti) + set_source_files_properties(${VVV_CXX_SRC} PROPERTIES COMPILE_FLAGS "-std=c++98 -fno-exceptions -fno-rtti") # Dependencies (as needed) set_source_files_properties(${FAUDIO_SRC} PROPERTIES COMPILE_FLAGS -std=c99) From 94620d809eb551c7553ec80bcd1f645b4af101bc Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Mon, 28 Oct 2024 17:31:21 -0400 Subject: [PATCH 14/64] CI: Migrate to SLR Sniper SDK for Linux builds --- .github/workflows/ci.yml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5339fd01..bc814578 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,41 +64,36 @@ jobs: run: ninja -C ${SRC_DIR_PATH}/build build-lin: - name: Build (CentOS 7) + name: Build (Steam Linux Runtime Sniper) runs-on: ubuntu-latest - container: ghcr.io/infoteddy/vvvvvv-build@sha256:50a2f769db3ca180286e9a76c1bf06b7016544a78e1fc7a9a0cc1144c675ced1 - - env: - CXXFLAGS: -I/usr/local/include/SDL2 - LDFLAGS: -L/usr/local/lib + container: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true - name: CMake configure (default version) run: | mkdir ${SRC_DIR_PATH}/build && cd ${SRC_DIR_PATH}/build - cmake .. + cmake -G Ninja .. - name: Build (default version) - run: make -j $(nproc) -C ${SRC_DIR_PATH}/build + run: ninja -C ${SRC_DIR_PATH}/build - name: CMake configure (official) run: | cd ${SRC_DIR_PATH}/build - cmake -DOFFICIAL_BUILD=ON .. + cmake -G Ninja -DOFFICIAL_BUILD=ON .. - name: Build (official) - run: | - make -j $(nproc) -C ${SRC_DIR_PATH}/build + run: ninja -C ${SRC_DIR_PATH}/build - name: CMake configure (M&P) run: | cd ${SRC_DIR_PATH}/build - cmake -DOFFICIAL_BUILD=OFF -DMAKEANDPLAY=ON .. + cmake -G Ninja -DOFFICIAL_BUILD=OFF -DMAKEANDPLAY=ON .. - name: Build (M&P) - run: make -j $(nproc) -C ${SRC_DIR_PATH}/build + run: ninja -C ${SRC_DIR_PATH}/build build-win: name: Build (windows-latest) From dedf941b253992acb543e30f08dc9a31a0153526 Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Fri, 5 Jul 2024 14:59:15 -0700 Subject: [PATCH 15/64] Update region system to current codebase due to PR rot --- desktop_version/src/CustomLevels.cpp | 42 ++----- desktop_version/src/Game.cpp | 89 +++++++++++++++ desktop_version/src/Graphics.cpp | 9 ++ desktop_version/src/Graphics.h | 4 + desktop_version/src/GraphicsResources.cpp | 30 +++++ desktop_version/src/Map.cpp | 124 ++++++++++++++++++++- desktop_version/src/Map.h | 36 +++++- desktop_version/src/Render.cpp | 130 ++++++++++------------ desktop_version/src/Script.cpp | 17 +++ 9 files changed, 366 insertions(+), 115 deletions(-) diff --git a/desktop_version/src/CustomLevels.cpp b/desktop_version/src/CustomLevels.cpp index 347bff9a..bd8ac2aa 100644 --- a/desktop_version/src/CustomLevels.cpp +++ b/desktop_version/src/CustomLevels.cpp @@ -1682,35 +1682,7 @@ bool customlevelclass::save(const std::string& _path) void customlevelclass::generatecustomminimap(void) { - map.customzoom = 1; - if (mapwidth <= 10 && mapheight <= 10) - { - map.customzoom = 2; - } - if (mapwidth <= 5 && mapheight <= 5) - { - map.customzoom = 4; - } - - // Set minimap offsets - switch (map.customzoom) - { - case 4: - map.custommmxoff = 24 * (5 - mapwidth); - map.custommmyoff = 18 * (5 - mapheight); - break; - case 2: - map.custommmxoff = 12 * (10 - mapwidth); - map.custommmyoff = 9 * (10 - mapheight); - break; - default: - map.custommmxoff = 6 * (20 - mapwidth); - map.custommmyoff = int(4.5 * (20 - mapheight)); - break; - } - - map.custommmxsize = 240 - (map.custommmxoff * 2); - map.custommmysize = 180 - (map.custommmyoff * 2); + const MapRenderData data = map.get_render_data(); // Start drawing the minimap @@ -1719,9 +1691,9 @@ void customlevelclass::generatecustomminimap(void) graphics.clear(); // Scan over the map size - for (int j2 = 0; j2 < mapheight; j2++) + for (int j2 = data.starty; j2 < data.starty + data.height; j2++) { - for (int i2 = 0; i2 < mapwidth; i2++) + for (int i2 = data.startx; i2 < data.startx + data.width; i2++) { std::vector dark_points; std::vector light_points; @@ -1729,12 +1701,12 @@ void customlevelclass::generatecustomminimap(void) bool dark = getroomprop(i2, j2)->tileset == 1; // Ok, now scan over each square - for (int j = 0; j < 9 * map.customzoom; j++) + for (int j = 0; j < 9 * data.zoom; j++) { - for (int i = 0; i < 12 * map.customzoom; i++) + for (int i = 0; i < 12 * data.zoom; i++) { int tile; - switch (map.customzoom) + switch (data.zoom) { case 4: tile = absfree( @@ -1759,7 +1731,7 @@ void customlevelclass::generatecustomminimap(void) if (tile >= 1) { // Add this pixel - SDL_Point point = { (i2 * 12 * map.customzoom) + i, (j2 * 9 * map.customzoom) + j }; + SDL_Point point = { ((i2 - data.startx) * 12 * data.zoom) + i, ((j2 - data.starty) * 9 * data.zoom) + j }; if (dark) { dark_points.push_back(point); diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 86805c2a..3f0d3ad0 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -229,6 +229,16 @@ void Game::init(void) customcol=0; + map.currentregion = 0; + for (size_t i = 0; i < SDL_arraysize(map.region); i++) + { + map.region[i].isvalid = false; + map.region[i].rx = 0; + map.region[i].ry = 0; + map.region[i].rx2 = 0; + map.region[i].ry2 = 0; + } + SDL_memset(crewstats, false, sizeof(crewstats)); SDL_memset(ndmresultcrewstats, false, sizeof(ndmresultcrewstats)); SDL_memset(besttimes, -1, sizeof(besttimes)); @@ -5948,6 +5958,50 @@ void Game::customloadquick(const std::string& savfile) map.roomnameset = true; map.roomname_special = true; } + else if (SDL_strcmp(pKey, "currentregion") == 0) + { + map.currentregion = help.Int(pText); + } +#if !defined(NO_CUSTOM_LEVELS) + else if (SDL_strcmp(pKey, "regions") == 0) + { + tinyxml2::XMLElement* pElem2; + for (pElem2 = pElem->FirstChildElement(); pElem2 != NULL; pElem2 = pElem2->NextSiblingElement()) + { + int thisid = 0; + int thisrx = 0; + int thisry = 0; + int thisrx2 = (cl.mapwidth - 1); + int thisry2 = (cl.mapheight - 1); + if (pElem2->Attribute("id")) + { + thisid = help.Int(pElem2->Attribute("id")); + } + + for (tinyxml2::XMLElement* pElem3 = pElem2->FirstChildElement(); pElem3 != NULL; pElem3 = pElem3->NextSiblingElement()) + { + if (SDL_strcmp(pElem3->Value(), "rx") == 0 && pElem3->GetText() != NULL) + { + thisrx = help.Int(pElem3->GetText()); + } + if (SDL_strcmp(pElem3->Value(), "ry") == 0 && pElem3->GetText() != NULL) + { + thisry = help.Int(pElem3->GetText()); + } + if (SDL_strcmp(pElem3->Value(), "rx2") == 0 && pElem3->GetText() != NULL) + { + thisrx2 = help.Int(pElem3->GetText()); + } + if (SDL_strcmp(pElem3->Value(), "ry2") == 0 && pElem3->GetText() != NULL) + { + thisry2 = help.Int(pElem3->GetText()); + } + } + + map.setregion(thisid, thisrx, thisry, thisrx2, thisry2); + } + } +#endif } } @@ -6332,6 +6386,41 @@ bool Game::customsavequick(const std::string& savfile) xml::update_tag(msgs, "crewmates", crewmates()); + xml::update_tag(msgs, "currentregion", map.currentregion); + + tinyxml2::XMLElement* msg = xml::update_element_delete_contents(msgs, "regions"); + for (size_t i = 0; i < SDL_arraysize(map.region); i++) + { + if (map.region[i].isvalid) + { + tinyxml2::XMLElement* region_el; + region_el = doc.NewElement("region"); + + region_el->SetAttribute("id", (help.String(i).c_str())); + + tinyxml2::XMLElement* rx_el; + rx_el = doc.NewElement("rx"); + rx_el->LinkEndChild(doc.NewText(help.String(map.region[i].rx).c_str())); + region_el->LinkEndChild(rx_el); + + tinyxml2::XMLElement* ry_el; + ry_el = doc.NewElement("ry"); + ry_el->LinkEndChild(doc.NewText(help.String(map.region[i].ry).c_str())); + region_el->LinkEndChild(ry_el); + + tinyxml2::XMLElement* rx2_el; + rx2_el = doc.NewElement("rx2"); + rx2_el->LinkEndChild(doc.NewText(help.String(map.region[i].rx2).c_str())); + region_el->LinkEndChild(rx2_el); + + tinyxml2::XMLElement* ry2_el; + ry2_el = doc.NewElement("ry2"); + ry2_el->LinkEndChild(doc.NewText(help.String(map.region[i].ry2).c_str())); + region_el->LinkEndChild(ry2_el); + + msg->LinkEndChild(region_el); + } + } //Special stats diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index 0c2dba35..e38ed3ac 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -1271,6 +1271,15 @@ void Graphics::draw_grid_tile( draw_grid_tile(texture, t, x, y, width, height, color, 1, 1); } +void Graphics::draw_region_image(int t, int xp, int yp, int wp, int hp) +{ + if (!INBOUNDS_ARR(t, customminimaps) || customminimaps[t] == NULL) + { + return; + } + draw_texture_part(customminimaps[t], xp, yp, 0, 0, wp, hp, 1, 1); +} + void Graphics::cutscenebars(void) { const int usethispos = lerp(oldcutscenebarspos, cutscenebarspos); diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index c37622a2..bc1dba69 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -172,6 +172,8 @@ public: void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height, SDL_Color color, int scalex, int scaley); void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height, SDL_Color color); + void draw_region_image(int t, int xp, int yp, int wp, int hp); + void updatetextboxes(void); const char* textbox_line(char* buffer, size_t buffer_len, size_t textbox_i, size_t line_i); void drawgui(void); @@ -337,6 +339,8 @@ public: SDL_Texture* images[NUM_IMAGES]; + SDL_Texture* customminimaps[401]; + bool flipmode; bool setflipmode; bool notextoutline; diff --git a/desktop_version/src/GraphicsResources.cpp b/desktop_version/src/GraphicsResources.cpp index 571a1f00..7e25545f 100644 --- a/desktop_version/src/GraphicsResources.cpp +++ b/desktop_version/src/GraphicsResources.cpp @@ -442,6 +442,28 @@ void GraphicsResources::init(void) SDL_assert(0 && "Failed to create minimap texture! See stderr."); return; } + + SDL_zeroa(graphics.customminimaps); + + EnumHandle handle = {}; + const char* item; + char full_item[73]; + while ((item = FILESYSTEM_enumerateAssets("graphics", &handle)) != NULL) + { + if (SDL_strncmp(item, "region", 6) != 0) + { + continue; + } + char* end; + int i = SDL_strtol(&item[6], &end, 10); + if (item == end || SDL_strcmp(end, ".png") != 0) + { + continue; + } + SDL_snprintf(full_item, sizeof(full_item), "graphics/%s", item); + graphics.customminimaps[i] = LoadImage(full_item); + } + FILESYSTEM_freeEnumerate(&handle); } @@ -476,6 +498,14 @@ void GraphicsResources::destroy(void) CLEAR(im_sprites_translated); CLEAR(im_flipsprites_translated); + + for (size_t i = 0; i < SDL_arraysize(graphics.customminimaps); i++) + { + if (graphics.customminimaps[i] != NULL) + { + CLEAR(graphics.customminimaps[i]); + } + } #undef CLEAR VVV_freefunc(SDL_FreeSurface, im_sprites_surf); diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index 2b822c11..ac5a19e7 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -52,8 +52,6 @@ mapclass::mapclass(void) custommode=false; custommodeforreal=false; - custommmxoff=0; custommmyoff=0; custommmxsize=0; custommmysize=0; - customzoom=0; customshowmm=true; revealmap = true; @@ -2205,16 +2203,16 @@ void mapclass::twoframedelayfix(void) // A bit kludge-y, but it's the least we can do without changing the frame ordering. if (GlitchrunnerMode_less_than_or_equal(Glitchrunner2_2) - || !custommode - || game.deathseq != -1) + || !custommode + || game.deathseq != -1) return; int block_idx = -1; // obj.checktrigger() sets block_idx int activetrigger = obj.checktrigger(&block_idx); if (activetrigger <= -1 - || !INBOUNDS_VEC(block_idx, obj.blocks) - || activetrigger < 300) + || !INBOUNDS_VEC(block_idx, obj.blocks) + || activetrigger < 300) { return; } @@ -2225,3 +2223,117 @@ void mapclass::twoframedelayfix(void) game.setstatedelay(0); script.load(game.newscript); } + +MapRenderData mapclass::get_render_data(void) +{ + MapRenderData data; + data.width = getwidth(); + data.height = getheight(); + + data.startx = 0; + data.starty = 0; + + // Region handling + if (region[currentregion].isvalid) + { + data.startx = region[currentregion].rx; + data.starty = region[currentregion].ry; + data.width = ((region[currentregion].rx2 - data.startx) + 1); + data.height = ((region[currentregion].ry2 - data.starty) + 1); + } + + data.zoom = 1; + + if (data.width <= 10 && data.height <= 10) + { + data.zoom = 2; + } + if (data.width <= 5 && data.height <= 5) + { + data.zoom = 4; + } + + data.xoff = 0; + data.yoff = 0; + + // Set minimap offsets + switch (data.zoom) + { + case 4: + data.xoff = 24 * (5 - data.width); + data.yoff = 18 * (5 - data.height); + break; + case 2: + data.xoff = 12 * (10 - data.width); + data.yoff = 9 * (10 - data.height); + break; + default: + data.xoff = 6 * (20 - data.width); + data.yoff = (int)(4.5 * (20 - data.height)); + break; + } + + data.pixelsx = 240 - (data.xoff * 2); + data.pixelsy = 180 - (data.yoff * 2); + + data.legendxoff = 40 + data.xoff; + data.legendyoff = 21 + data.yoff; + + // Magic numbers for centering legend tiles. + switch (data.zoom) + { + case 4: + data.legendxoff += 21; + data.legendyoff += 16; + break; + case 2: + data.legendxoff += 9; + data.legendyoff += 5; + break; + default: + data.legendxoff += 3; + data.legendyoff += 1; + break; + } + + return data; +} + +void mapclass::setregion(int id, int rx, int ry, int rx2, int ry2) +{ +#if !defined(NO_CUSTOM_LEVELS) + if (INBOUNDS_ARR(id, region)) + { + region[id].isvalid = true; + region[id].rx = SDL_clamp(rx, 0, cl.mapwidth - 1); + region[id].ry = SDL_clamp(ry, 0, cl.mapheight - 1); + region[id].rx2 = SDL_clamp(rx2, 0, cl.mapwidth - 1); + region[id].ry2 = SDL_clamp(ry2, 0, cl.mapheight - 1); + } +#endif +} + +void mapclass::removeregion(int id) +{ +#if !defined(NO_CUSTOM_LEVELS) + if (INBOUNDS_ARR(id, region)) + { + region[id].isvalid = false; + region[id].rx = 0; + region[id].ry = 0; + region[id].rx2 = 0; + region[id].ry2 = 0; + } +#endif +} + +void mapclass::changeregion(int id) +{ +#if !defined(NO_CUSTOM_LEVELS) + if (INBOUNDS_ARR(id, region)) + { + currentregion = id; + cl.generatecustomminimap(); + } +#endif +} \ No newline at end of file diff --git a/desktop_version/src/Map.h b/desktop_version/src/Map.h index 243938c6..fa2f3533 100644 --- a/desktop_version/src/Map.h +++ b/desktop_version/src/Map.h @@ -12,6 +12,21 @@ #include "TowerBG.h" #include "WarpClass.h" +struct MapRenderData +{ + int zoom; + int xoff; + int yoff; + int legendxoff; + int legendyoff; + int startx; + int starty; + int width; + int height; + int pixelsx; + int pixelsy; +}; + struct Roomtext { int x, y; @@ -163,8 +178,6 @@ public: //Variables for playing custom levels bool custommode; bool custommodeforreal; - int custommmxoff, custommmyoff, custommmxsize, custommmysize; - int customzoom; bool customshowmm; //final level colour cycling stuff @@ -198,6 +211,25 @@ public: //Map cursor int cursorstate, cursordelay; + + //Region system + struct regionstruct + { + bool isvalid; + int rx; + int ry; + int rx2; + int ry2; + }; + struct regionstruct region[401]; + void setregion(int id, int rx, int ry, int rx2, int ry2); + void removeregion(int id); + void changeregion(int id); + int currentregion; + int regionx, regiony; + int regionwidth, regionheight; + + MapRenderData get_render_data(void); }; #ifndef MAP_DEFINITION diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index 252dc53d..495cd9d5 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -32,15 +32,6 @@ static int tr; static int tg; static int tb; -struct MapRenderData -{ - int zoom; - int xoff; - int yoff; - int legendxoff; - int legendyoff; -}; - static inline void drawslowdowntext(const int y) { switch (game.slowdown) @@ -2789,42 +2780,26 @@ static void draw_roomname_menu(void) #define FLIP_PR_CJK_LOW (graphics.flipmode ? PR_CJK_HIGH : PR_CJK_LOW) #define FLIP_PR_CJK_HIGH (graphics.flipmode ? PR_CJK_LOW : PR_CJK_HIGH) -static MapRenderData getmaprenderdata(void) -{ - MapRenderData data; - - data.zoom = map.custommode ? map.customzoom : 1; - data.xoff = map.custommode ? map.custommmxoff : 0; - data.yoff = map.custommode ? map.custommmyoff : 0; - data.legendxoff = 40 + data.xoff; - data.legendyoff = 21 + data.yoff; - - // Magic numbers for centering legend tiles. - switch (data.zoom) - { - case 4: - data.legendxoff += 20; - data.legendyoff += 14; - break; - case 2: - data.legendxoff += 8; - data.legendyoff += 5; - break; - default: - data.legendxoff += 2; - data.legendyoff += 1; - break; - } - - return data; -} - static void rendermap(void) { if (map.custommode && map.customshowmm) { - graphics.drawpixeltextbox(35 + map.custommmxoff, 16 + map.custommmyoff, map.custommmxsize + 10, map.custommmysize + 10, 65, 185, 207); - graphics.drawpartimage(graphics.minimap_mounted ? IMAGE_MINIMAP : IMAGE_CUSTOMMINIMAP, 40 + map.custommmxoff, 21 + map.custommmyoff, map.custommmxsize, map.custommmysize); + const MapRenderData data = map.get_render_data(); + + graphics.drawpixeltextbox(35 + data.xoff, 16 + data.yoff, data.pixelsx + 10, data.pixelsy + 10, 65, 185, 207); + + if (graphics.customminimaps[map.currentregion] != NULL) + { + graphics.draw_region_image(map.currentregion, 40 + data.xoff, 21 + data.yoff, data.pixelsx, data.pixelsy); + } + else if (map.currentregion == 0 && graphics.minimap_mounted) + { + graphics.drawpartimage(IMAGE_MINIMAP, 40 + data.xoff, 21 + data.yoff, data.pixelsx, data.pixelsy); + } + else + { + graphics.drawpartimage(IMAGE_CUSTOMMINIMAP, 40 + data.xoff, 21 + data.yoff, data.pixelsx, data.pixelsy); + } return; } @@ -2834,11 +2809,11 @@ static void rendermap(void) static void rendermapfog(void) { - const MapRenderData data = getmaprenderdata(); + const MapRenderData data = map.get_render_data(); - for (int j = 0; j < map.getheight(); j++) + for (int j = data.starty; j < data.starty + data.height; j++) { - for (int i = 0; i < map.getwidth(); i++) + for (int i = data.startx; i < data.startx + data.width; i++) { if (!map.isexplored(i, j)) { @@ -2847,7 +2822,7 @@ static void rendermapfog(void) { for (int y = 0; y < data.zoom; y++) { - graphics.drawimage(IMAGE_COVERED, data.xoff + 40 + (x * 12) + (i * (12 * data.zoom)), data.yoff + 21 + (y * 9) + (j * (9 * data.zoom)), false); + graphics.drawimage(IMAGE_COVERED, data.xoff + 40 + (x * 12) + ((i - data.startx) * (12 * data.zoom)), data.yoff + 21 + (y * 9) + ((j - data.starty) * (9 * data.zoom)), false); } } } @@ -2859,17 +2834,22 @@ static void rendermaplegend(void) { // Draw the map legend, aka teleports/targets/trinkets - const MapRenderData data = getmaprenderdata(); + const MapRenderData data = map.get_render_data(); for (size_t i = 0; i < map.teleporters.size(); i++) { - if (map.showteleporters && map.isexplored(map.teleporters[i].x, map.teleporters[i].y)) + int x = map.teleporters[i].x - data.startx; + int y = map.teleporters[i].y - data.starty; + if (x >= 0 && y >= 0 && x < data.width && y < data.height) { - font::print(PR_FONT_8X8 | PR_FULLBOR, data.legendxoff + (map.teleporters[i].x * 12 * data.zoom), data.legendyoff + (map.teleporters[i].y * 9 * data.zoom), "💿", 171, 255, 252); - } - else if (map.showtargets && !map.isexplored(map.teleporters[i].x, map.teleporters[i].y)) - { - font::print(PR_FONT_8X8 | PR_FULLBOR, data.legendxoff + (map.teleporters[i].x * 12 * data.zoom), data.legendyoff + (map.teleporters[i].y * 9 * data.zoom), "❓", 64, 64, 64); + if (map.showteleporters && map.isexplored(x + data.startx, y + data.starty)) + { + font::print(PR_FONT_8X8 | PR_FULLBOR, data.legendxoff + (x * 12 * data.zoom), data.legendyoff + (y * 9 * data.zoom), "💿", 171, 255, 252); + } + else if (map.showtargets && !map.isexplored(x + data.startx, y + data.starty)) + { + font::print(PR_FONT_8X8 | PR_FULLBOR, data.legendxoff + (x * 12 * data.zoom), data.legendyoff + (y * 9 * data.zoom), "❓", 64, 64, 64); + } } } @@ -2879,7 +2859,12 @@ static void rendermaplegend(void) { if (!obj.collect[i]) { - font::print(PR_FONT_8X8 | PR_FULLBOR, data.legendxoff + (map.shinytrinkets[i].x * 12 * data.zoom), data.legendyoff + (map.shinytrinkets[i].y * 9 * data.zoom), "🪙", 254, 252, 58); + int x = map.shinytrinkets[i].x - data.startx; + int y = map.shinytrinkets[i].y - data.starty; + if (x >= 0 && y >= 0 && x < data.width && y < data.height) + { + font::print(PR_FONT_8X8 | PR_FULLBOR, data.legendxoff + (x * 12 * data.zoom), data.legendyoff + (y * 9 * data.zoom), "🪙", 254, 252, 58); + } } } } @@ -2887,44 +2872,45 @@ static void rendermaplegend(void) static void rendermapcursor(const bool flashing) { - const MapRenderData data = getmaprenderdata(); + const MapRenderData data = map.get_render_data(); + int room_x = game.roomx - data.startx - 100; + int room_y = game.roomy - data.starty - 100; + int pixels_x = room_x * 12; + int pixels_y = room_y * 9; if (!map.custommode && game.roomx == 109) { // Draw the tower specially if (!flashing || game.noflashingmode) { - graphics.draw_rect(40 + ((game.roomx - 100) * 12) + 2, 21 + 2, 12 - 4, 180 - 4, 16, 245 - (help.glow * 2), 245 - (help.glow * 2)); + graphics.draw_rect(40 + pixels_x + 2, 21 + 2, 12 - 4, 180 - 4, 16, 245 - (help.glow * 2), 245 - (help.glow * 2)); } else if (map.cursorstate == 1) { if (int(map.cursordelay / 4) % 2 == 0) { - graphics.draw_rect(40 + ((game.roomx - 100) * 12), 21, 12, 180, 255, 255, 255); - graphics.draw_rect(40 + ((game.roomx - 100) * 12) + 2, 21 + 2, 12 - 4, 180 - 4, 255, 255, 255); + graphics.draw_rect(40 + pixels_x, 21, 12, 180, 255, 255, 255); + graphics.draw_rect(40 + pixels_x + 2, 21 + 2, 12 - 4, 180 - 4, 255, 255, 255); } } else if (map.cursorstate == 2 && (int(map.cursordelay / 15) % 2 == 0)) { - graphics.draw_rect(40 + ((game.roomx - 100) * 12) + 2, 21 + 2, 12 - 4, 180 - 4, 16, 245 - (help.glow), 245 - (help.glow)); + graphics.draw_rect(40 + pixels_x + 2, 21 + 2, 12 - 4, 180 - 4, 16, 245 - (help.glow), 245 - (help.glow)); } return; } - if (!flashing || ((map.cursorstate == 2 && int(map.cursordelay / 15) % 2 == 0) || game.noflashingmode)) + if (room_x >= 0 && room_y >= 0 && room_x < data.width && room_y < data.height) { - int margin = (data.zoom == 4) ? 2 : 1; - graphics.draw_rect( - 40 + ((game.roomx - 100) * 12 * data.zoom) + margin + data.xoff, - 21 + ((game.roomy - 100) * 9 * data.zoom) + margin + data.yoff, - (12 * data.zoom) - (2 * margin), (9 * data.zoom) - (2 * margin), - 16, 245 - (help.glow), 245 - (help.glow) - ); - } - else if (map.cursorstate == 1 && int(map.cursordelay / 4) % 2 == 0) - { - graphics.draw_rect(40 + ((game.roomx - 100) * 12 * data.zoom) + data.xoff, 21 + ((game.roomy - 100) * 9 * data.zoom) + data.yoff, 12 * data.zoom, 9 * data.zoom, 255, 255, 255); - graphics.draw_rect(40 + ((game.roomx - 100) * 12 * data.zoom) + 2 + data.xoff, 21 + ((game.roomy - 100) * 9 * data.zoom) + 2 + data.yoff, (12 * data.zoom) - 4, (9 * data.zoom) - 4, 255, 255, 255); + if (!flashing || ((map.cursorstate == 2 && int(map.cursordelay / 15) % 2 == 0) || game.noflashingmode)) + { + graphics.draw_rect(40 + (pixels_x * data.zoom) + 2 + data.xoff, 21 + (pixels_y * data.zoom) + 2 + data.yoff, (12 * data.zoom) - 4, (9 * data.zoom) - 4, 16, 245 - (help.glow), 245 - (help.glow)); + } + else if (map.cursorstate == 1 && int(map.cursordelay / 4) % 2 == 0) + { + graphics.draw_rect(40 + (pixels_x * data.zoom) + data.xoff, 21 + (pixels_y * data.zoom) + data.yoff, 12 * data.zoom, 9 * data.zoom, 255, 255, 255); + graphics.draw_rect(40 + (pixels_x * data.zoom) + 2 + data.xoff, 21 + (pixels_y * data.zoom) + 2 + data.yoff, (12 * data.zoom) - 4, (9 * data.zoom) - 4, 255, 255, 255); + } } } @@ -3491,7 +3477,7 @@ void teleporterrender(void) // Draw a box around the currently selected teleporter - const MapRenderData data = getmaprenderdata(); + const MapRenderData data = map.get_render_data(); if (game.useteleporter) { diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 7c005567..84f388ef 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -371,6 +371,23 @@ void scriptclass::run(void) map.customshowmm=false; } } + else if (words[0] == "setregion") + { + map.setregion( + ss_toi(words[1]), + ss_toi(words[2]), + ss_toi(words[3]), + ss_toi(words[4]), + ss_toi(words[5])); + } + else if (words[0] == "removeregion") + { + map.removeregion(ss_toi(words[1])); + } + else if (words[0] == "changeregion") + { + map.changeregion(ss_toi(words[1])); + } if (words[0] == "delay") { //USAGE: delay(frames) From 1fb0afb99de43a06c746f78f6f78cd925847347c Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Sun, 3 Nov 2024 14:16:57 -0800 Subject: [PATCH 16/64] Apply PR review changes Co-authored-by: Misa Elizabeth Kai --- desktop_version/src/Game.cpp | 2 -- desktop_version/src/GraphicsResources.cpp | 5 +---- desktop_version/src/Map.cpp | 12 +----------- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 3f0d3ad0..0a587d21 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -5962,7 +5962,6 @@ void Game::customloadquick(const std::string& savfile) { map.currentregion = help.Int(pText); } -#if !defined(NO_CUSTOM_LEVELS) else if (SDL_strcmp(pKey, "regions") == 0) { tinyxml2::XMLElement* pElem2; @@ -6001,7 +6000,6 @@ void Game::customloadquick(const std::string& savfile) map.setregion(thisid, thisrx, thisry, thisrx2, thisry2); } } -#endif } } diff --git a/desktop_version/src/GraphicsResources.cpp b/desktop_version/src/GraphicsResources.cpp index 7e25545f..279ee8b1 100644 --- a/desktop_version/src/GraphicsResources.cpp +++ b/desktop_version/src/GraphicsResources.cpp @@ -501,10 +501,7 @@ void GraphicsResources::destroy(void) for (size_t i = 0; i < SDL_arraysize(graphics.customminimaps); i++) { - if (graphics.customminimaps[i] != NULL) - { - CLEAR(graphics.customminimaps[i]); - } + CLEAR(graphics.customminimaps[i]); } #undef CLEAR diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index ac5a19e7..3c28a070 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -2301,7 +2301,6 @@ MapRenderData mapclass::get_render_data(void) void mapclass::setregion(int id, int rx, int ry, int rx2, int ry2) { -#if !defined(NO_CUSTOM_LEVELS) if (INBOUNDS_ARR(id, region)) { region[id].isvalid = true; @@ -2310,30 +2309,21 @@ void mapclass::setregion(int id, int rx, int ry, int rx2, int ry2) region[id].rx2 = SDL_clamp(rx2, 0, cl.mapwidth - 1); region[id].ry2 = SDL_clamp(ry2, 0, cl.mapheight - 1); } -#endif } void mapclass::removeregion(int id) { -#if !defined(NO_CUSTOM_LEVELS) if (INBOUNDS_ARR(id, region)) { - region[id].isvalid = false; - region[id].rx = 0; - region[id].ry = 0; - region[id].rx2 = 0; - region[id].ry2 = 0; + SDL_zero(region[id]); } -#endif } void mapclass::changeregion(int id) { -#if !defined(NO_CUSTOM_LEVELS) if (INBOUNDS_ARR(id, region)) { currentregion = id; cl.generatecustomminimap(); } -#endif } \ No newline at end of file From 54b2aaae96827449e86698254030f8d3250555e3 Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Sun, 3 Nov 2024 15:20:33 -0800 Subject: [PATCH 17/64] Region system PR review changes Fixes errors or oversights with the region system for the PR review --- desktop_version/src/Game.cpp | 10 ---------- desktop_version/src/GraphicsResources.cpp | 7 ++++++- desktop_version/src/Map.cpp | 19 ++++++++++++++++--- desktop_version/src/Map.h | 4 ++-- desktop_version/src/Script.cpp | 2 ++ 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 0a587d21..6114a446 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -229,16 +229,6 @@ void Game::init(void) customcol=0; - map.currentregion = 0; - for (size_t i = 0; i < SDL_arraysize(map.region); i++) - { - map.region[i].isvalid = false; - map.region[i].rx = 0; - map.region[i].ry = 0; - map.region[i].rx2 = 0; - map.region[i].ry2 = 0; - } - SDL_memset(crewstats, false, sizeof(crewstats)); SDL_memset(ndmresultcrewstats, false, sizeof(ndmresultcrewstats)); SDL_memset(besttimes, -1, sizeof(besttimes)); diff --git a/desktop_version/src/GraphicsResources.cpp b/desktop_version/src/GraphicsResources.cpp index 279ee8b1..8d13f8df 100644 --- a/desktop_version/src/GraphicsResources.cpp +++ b/desktop_version/src/GraphicsResources.cpp @@ -447,7 +447,7 @@ void GraphicsResources::init(void) EnumHandle handle = {}; const char* item; - char full_item[73]; + char full_item[64]; while ((item = FILESYSTEM_enumerateAssets("graphics", &handle)) != NULL) { if (SDL_strncmp(item, "region", 6) != 0) @@ -456,6 +456,11 @@ void GraphicsResources::init(void) } char* end; int i = SDL_strtol(&item[6], &end, 10); + // make sure the region id is actually in bounds! + if (i < 1 || i > 400) + { + continue; + } if (item == end || SDL_strcmp(end, ".png") != 0) { continue; diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index 3c28a070..826384bf 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -87,6 +87,9 @@ mapclass::mapclass(void) roomtexton = false; nexttowercolour_set = false; + + currentregion = 0; + SDL_zeroa(region); } static char roomname_static[SCREEN_WIDTH_CHARS]; @@ -2301,21 +2304,31 @@ MapRenderData mapclass::get_render_data(void) void mapclass::setregion(int id, int rx, int ry, int rx2, int ry2) { - if (INBOUNDS_ARR(id, region)) + if (INBOUNDS_ARR(id, region) && id > 0) { region[id].isvalid = true; region[id].rx = SDL_clamp(rx, 0, cl.mapwidth - 1); region[id].ry = SDL_clamp(ry, 0, cl.mapheight - 1); region[id].rx2 = SDL_clamp(rx2, 0, cl.mapwidth - 1); region[id].ry2 = SDL_clamp(ry2, 0, cl.mapheight - 1); + + if (id == currentregion) + { + cl.generatecustomminimap(); + } } } void mapclass::removeregion(int id) { - if (INBOUNDS_ARR(id, region)) + if (INBOUNDS_ARR(id, region) && id > 0) { SDL_zero(region[id]); + + if (id == currentregion) + { + cl.generatecustomminimap(); + } } } @@ -2326,4 +2339,4 @@ void mapclass::changeregion(int id) currentregion = id; cl.generatecustomminimap(); } -} \ No newline at end of file +} diff --git a/desktop_version/src/Map.h b/desktop_version/src/Map.h index fa2f3533..b025916e 100644 --- a/desktop_version/src/Map.h +++ b/desktop_version/src/Map.h @@ -213,7 +213,7 @@ public: int cursorstate, cursordelay; //Region system - struct regionstruct + struct Region { bool isvalid; int rx; @@ -221,7 +221,7 @@ public: int rx2; int ry2; }; - struct regionstruct region[401]; + struct Region region[401]; void setregion(int id, int rx, int ry, int rx2, int ry2); void removeregion(int id); void changeregion(int id); diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 84f388ef..6a75d560 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -3275,6 +3275,8 @@ void scriptclass::hardreset(void) SDL_memset(map.roomdeaths, 0, sizeof(map.roomdeaths)); SDL_memset(map.roomdeathsfinal, 0, sizeof(map.roomdeathsfinal)); map.resetmap(); + map.currentregion = 0; + SDL_zeroa(map.region); //entityclass obj.nearelephant = false; obj.upsetmode = false; From 2875af0492ffe5a0d2148079895a3498465c6a7d Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Sun, 3 Nov 2024 17:48:11 -0800 Subject: [PATCH 18/64] Fix coordinates being allowed in the wrong order --- desktop_version/src/Map.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index 826384bf..069a322e 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -2306,6 +2306,20 @@ void mapclass::setregion(int id, int rx, int ry, int rx2, int ry2) { if (INBOUNDS_ARR(id, region) && id > 0) { + // swap the variables if they're entered in the wrong order + if (rx2 > rx) + { + int temp = rx; + rx = rx2; + rx2 = temp; + } + if (ry2 > ry) + { + int temp = ry; + ry = ry2; + ry2 = temp; + } + region[id].isvalid = true; region[id].rx = SDL_clamp(rx, 0, cl.mapwidth - 1); region[id].ry = SDL_clamp(ry, 0, cl.mapheight - 1); From b572e2164b9f6d6a63438356532b8e27c8792a27 Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Sun, 3 Nov 2024 21:16:26 -0800 Subject: [PATCH 19/64] fix flipped inequality sign Co-authored-by: Misa Elizabeth Kai --- desktop_version/src/Map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index 069a322e..18e83ff2 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -2307,7 +2307,7 @@ void mapclass::setregion(int id, int rx, int ry, int rx2, int ry2) if (INBOUNDS_ARR(id, region) && id > 0) { // swap the variables if they're entered in the wrong order - if (rx2 > rx) + if (rx2 < rx) { int temp = rx; rx = rx2; From d8a8e44afac17795fba1aad1a5bfefd07f8c2428 Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Sun, 3 Nov 2024 21:16:33 -0800 Subject: [PATCH 20/64] fix flipped inequality sign Co-authored-by: Misa Elizabeth Kai --- desktop_version/src/Map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index 18e83ff2..c6cca16b 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -2313,7 +2313,7 @@ void mapclass::setregion(int id, int rx, int ry, int rx2, int ry2) rx = rx2; rx2 = temp; } - if (ry2 > ry) + if (ry2 < ry) { int temp = ry; ry = ry2; From 45e60fa69c4a182d182b9970ba03aa5965679bf3 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Sun, 3 Nov 2024 15:08:24 -0400 Subject: [PATCH 21/64] Add position(force) This argument forces the textbox position, meaning it won't be moved to be inside of the bounds of the screen (nor have the 10 pixel padding on each side.) --- desktop_version/src/Graphics.cpp | 13 +++++++++++++ desktop_version/src/Graphics.h | 2 ++ desktop_version/src/Script.cpp | 31 ++++++++++++++++++++++++------- desktop_version/src/Script.h | 1 + desktop_version/src/Textbox.cpp | 27 ++++++++++++++++----------- desktop_version/src/Textbox.h | 2 ++ 6 files changed, 58 insertions(+), 18 deletions(-) diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index e38ed3ac..73c813dd 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -3204,6 +3204,19 @@ SDL_Color Graphics::bigchunkygetcol(int t) return color; } +void Graphics::textboxforcepos(int x, int y) +{ + if (!INBOUNDS_VEC(m, textboxes)) + { + vlog_error("textboxforcepos() out-of-bounds!"); + return; + } + + textboxes[m].position_forced = true; + textboxes[m].xp = x; + textboxes[m].yp = y; +} + void Graphics::textboxcenterx(void) { if (!INBOUNDS_VEC(m, textboxes)) diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index bc1dba69..4f805c56 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -94,6 +94,8 @@ public: int r, int g, int b ); + void textboxforcepos(int x, int y); + void textboxcenterx(void); int textboxwidth(void); diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 6a75d560..f3e95342 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -53,6 +53,7 @@ scriptclass::scriptclass(void) textlarge = false; textbox_sprites.clear(); textbox_image = TEXTIMAGE_NONE; + textbox_forcepos = false; } void scriptclass::add_default_colours(void) @@ -566,11 +567,13 @@ void scriptclass::run(void) textcrewmateposition = TextboxCrewmatePosition(); textbox_sprites.clear(); textbox_image = TEXTIMAGE_NONE; + textbox_forcepos = false; } else if (words[0] == "position") { //are we facing left or right? for some objects we don't care, default at 0. j = 0; + textbox_forcepos = false; //the first word is the object to position relative to if (words[1] == "centerx") @@ -592,6 +595,13 @@ void scriptclass::run(void) textx = -500; texty = -500; } + else if (words[1] == "force") + { + words[2] = "donothing"; + j = -1; + textbox_forcepos = true; + + } else // Well, are they asking for a crewmate...? { i = getcrewmanfromname(words[1]); @@ -774,16 +784,23 @@ void scriptclass::run(void) graphics.setimage(textbox_image); - if (textx == -500 || textx == -1) + if (textbox_forcepos) { - graphics.textboxcenterx(); - textcrewmateposition.override_x = false; + graphics.textboxforcepos(textx, texty); } - - if (texty == -500) + else { - graphics.textboxcentery(); - textcrewmateposition.override_y = false; + if (textx == -500 || textx == -1) + { + graphics.textboxcenterx(); + textcrewmateposition.override_x = false; + } + + if (texty == -500) + { + graphics.textboxcentery(); + textcrewmateposition.override_y = false; + } } TextboxOriginalContext context = TextboxOriginalContext(); diff --git a/desktop_version/src/Script.h b/desktop_version/src/Script.h index aa71220d..304f1276 100644 --- a/desktop_version/src/Script.h +++ b/desktop_version/src/Script.h @@ -122,6 +122,7 @@ public: int textboxtimer; std::vector textbox_sprites; TextboxImage textbox_image; + bool textbox_forcepos; //Misc int i, j, k; diff --git a/desktop_version/src/Textbox.cpp b/desktop_version/src/Textbox.cpp index a95eb87c..5a57a88b 100644 --- a/desktop_version/src/Textbox.cpp +++ b/desktop_version/src/Textbox.cpp @@ -29,6 +29,8 @@ textboxclass::textboxclass(int gap) large = false; + position_forced = false; + should_centerx = false; should_centery = false; @@ -78,18 +80,21 @@ void textboxclass::centery(void) void textboxclass::applyposition(void) { resize(); - reposition(); - if (should_centerx) + if (!position_forced) { - centerx(); - } - if (should_centery) - { - centery(); - } - if (translate == TEXTTRANSLATE_CUTSCENE) - { - adjust(); + reposition(); + if (should_centerx) + { + centerx(); + } + if (should_centery) + { + centery(); + } + if (translate == TEXTTRANSLATE_CUTSCENE) + { + adjust(); + } } } diff --git a/desktop_version/src/Textbox.h b/desktop_version/src/Textbox.h index 97b12d61..edd7a5de 100644 --- a/desktop_version/src/Textbox.h +++ b/desktop_version/src/Textbox.h @@ -125,6 +125,8 @@ public: bool large; + bool position_forced; + bool should_centerx; bool should_centery; From 98a0931225fcf839f032c92550afa35c57dbddd1 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Sun, 3 Nov 2024 16:07:55 -0400 Subject: [PATCH 22/64] Add textoutline(on/off/default) This commit adds a new scripting command for textbox visual control, where you're able to force the transparent textbox's outline on or off. --- desktop_version/src/Graphics.cpp | 33 +++++++++++++++++++++++++------- desktop_version/src/Graphics.h | 2 ++ desktop_version/src/Script.cpp | 24 +++++++++++++++++++++++ desktop_version/src/Script.h | 2 ++ desktop_version/src/Textbox.cpp | 3 +++ desktop_version/src/Textbox.h | 3 +++ 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index 73c813dd..c0885ead 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -929,13 +929,20 @@ void Graphics::drawgui(void) size_t j; for (j = 0; j < textboxes[i].lines.size(); j++) { - font::print( - print_flags | PR_BOR, - text_xp, - yp + text_yoff + text_sign * (j * (font_height + textboxes[i].linegap)), - textbox_line(buffer, sizeof(buffer), i, j), - 0, 0, 0 - ); + const int x = text_xp; + const int y = yp + text_yoff + text_sign * (j * (font_height + textboxes[i].linegap)); + if (!textboxes[i].force_outline) + { + font::print(print_flags | PR_BOR, x, y, textbox_line(buffer, sizeof(buffer), i, j), 0, 0, 0); + } + else if (textboxes[i].outline) + { + // We're forcing an outline, so we'll have to draw it ourselves instead of relying on PR_BOR. + font::print(print_flags, x - 1, y, textbox_line(buffer, sizeof(buffer), i, j), 0, 0, 0); + font::print(print_flags, x + 1, y, textbox_line(buffer, sizeof(buffer), i, j), 0, 0, 0); + font::print(print_flags, x, y - 1, textbox_line(buffer, sizeof(buffer), i, j), 0, 0, 0); + font::print(print_flags, x, y + 1, textbox_line(buffer, sizeof(buffer), i, j), 0, 0, 0); + } } for (j = 0; j < textboxes[i].lines.size(); j++) { @@ -1483,6 +1490,18 @@ void Graphics::setimage(TextboxImage image) textboxes[m].setimage(image); } +void Graphics::textboxoutline(bool enabled) +{ + if (!INBOUNDS_VEC(m, textboxes)) + { + vlog_error("textboxoutline() out-of-bounds!"); + return; + } + + textboxes[m].force_outline = true; + textboxes[m].outline = enabled; +} + void Graphics::addline( const std::string& t ) { if (!INBOUNDS_VEC(m, textboxes)) diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index 4f805c56..ae93e42d 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -137,6 +137,8 @@ public: void setimage(TextboxImage image); + void textboxoutline(bool enabled); + void textboxindex(int index); void textboxremove(void); diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index f3e95342..81c9717d 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -568,6 +568,8 @@ void scriptclass::run(void) textbox_sprites.clear(); textbox_image = TEXTIMAGE_NONE; textbox_forcepos = false; + textbox_force_outline = false; + textbox_outline = false; } else if (words[0] == "position") { @@ -746,6 +748,23 @@ void scriptclass::run(void) textbox_image = TEXTIMAGE_NONE; } } + else if (words[0] == "textoutline") + { + if (words[1] == "default") + { + textbox_force_outline = false; + } + else if (words[1] == "on") + { + textbox_force_outline = true; + textbox_outline = true; + } + else if (words[1] == "off") + { + textbox_force_outline = true; + textbox_outline = false; + } + } else if (words[0] == "flipme") { textflipme = !textflipme; @@ -803,6 +822,11 @@ void scriptclass::run(void) } } + if (textbox_force_outline) + { + graphics.textboxoutline(textbox_outline); + } + TextboxOriginalContext context = TextboxOriginalContext(); context.text_case = textcase; context.lines = std::vector(txt); diff --git a/desktop_version/src/Script.h b/desktop_version/src/Script.h index 304f1276..2f9ee29e 100644 --- a/desktop_version/src/Script.h +++ b/desktop_version/src/Script.h @@ -123,6 +123,8 @@ public: std::vector textbox_sprites; TextboxImage textbox_image; bool textbox_forcepos; + bool textbox_force_outline; + bool textbox_outline; //Misc int i, j, k; diff --git a/desktop_version/src/Textbox.cpp b/desktop_version/src/Textbox.cpp index 5a57a88b..0a164b03 100644 --- a/desktop_version/src/Textbox.cpp +++ b/desktop_version/src/Textbox.cpp @@ -43,6 +43,9 @@ textboxclass::textboxclass(int gap) image = TEXTIMAGE_NONE; + force_outline = false; + outline = false; + crewmate_position = TextboxCrewmatePosition(); original = TextboxOriginalContext(); original.text_case = 1; diff --git a/desktop_version/src/Textbox.h b/desktop_version/src/Textbox.h index edd7a5de..ad3e1546 100644 --- a/desktop_version/src/Textbox.h +++ b/desktop_version/src/Textbox.h @@ -137,6 +137,9 @@ public: std::vector sprites; TextboxImage image; + bool force_outline; + bool outline; + TextboxCrewmatePosition crewmate_position; TextboxOriginalContext original; TextboxSpacing spacing; From 6174d62f6fda45ded3189d60a8d7692d41a17bb5 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Sun, 3 Nov 2024 21:01:54 -0400 Subject: [PATCH 23/64] position(force) -> position(absolute) --- desktop_version/src/Graphics.cpp | 6 +++--- desktop_version/src/Graphics.h | 2 +- desktop_version/src/Script.cpp | 14 +++++++------- desktop_version/src/Script.h | 2 +- desktop_version/src/Textbox.cpp | 4 ++-- desktop_version/src/Textbox.h | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index c0885ead..c4aa3fb5 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -3223,15 +3223,15 @@ SDL_Color Graphics::bigchunkygetcol(int t) return color; } -void Graphics::textboxforcepos(int x, int y) +void Graphics::textboxabsolutepos(int x, int y) { if (!INBOUNDS_VEC(m, textboxes)) { - vlog_error("textboxforcepos() out-of-bounds!"); + vlog_error("textboxabsolutepos() out-of-bounds!"); return; } - textboxes[m].position_forced = true; + textboxes[m].position_absolute = true; textboxes[m].xp = x; textboxes[m].yp = y; } diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index ae93e42d..ea9a2130 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -94,7 +94,7 @@ public: int r, int g, int b ); - void textboxforcepos(int x, int y); + void textboxabsolutepos(int x, int y); void textboxcenterx(void); diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 81c9717d..75c518d8 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -53,7 +53,7 @@ scriptclass::scriptclass(void) textlarge = false; textbox_sprites.clear(); textbox_image = TEXTIMAGE_NONE; - textbox_forcepos = false; + textbox_absolutepos = false; } void scriptclass::add_default_colours(void) @@ -567,7 +567,7 @@ void scriptclass::run(void) textcrewmateposition = TextboxCrewmatePosition(); textbox_sprites.clear(); textbox_image = TEXTIMAGE_NONE; - textbox_forcepos = false; + textbox_absolutepos = false; textbox_force_outline = false; textbox_outline = false; } @@ -575,7 +575,7 @@ void scriptclass::run(void) { //are we facing left or right? for some objects we don't care, default at 0. j = 0; - textbox_forcepos = false; + textbox_absolutepos = false; //the first word is the object to position relative to if (words[1] == "centerx") @@ -597,11 +597,11 @@ void scriptclass::run(void) textx = -500; texty = -500; } - else if (words[1] == "force") + else if (words[1] == "absolute") { words[2] = "donothing"; j = -1; - textbox_forcepos = true; + textbox_absolutepos = true; } else // Well, are they asking for a crewmate...? @@ -803,9 +803,9 @@ void scriptclass::run(void) graphics.setimage(textbox_image); - if (textbox_forcepos) + if (textbox_absolutepos) { - graphics.textboxforcepos(textx, texty); + graphics.textboxabsolutepos(textx, texty); } else { diff --git a/desktop_version/src/Script.h b/desktop_version/src/Script.h index 2f9ee29e..07607def 100644 --- a/desktop_version/src/Script.h +++ b/desktop_version/src/Script.h @@ -122,7 +122,7 @@ public: int textboxtimer; std::vector textbox_sprites; TextboxImage textbox_image; - bool textbox_forcepos; + bool textbox_absolutepos; bool textbox_force_outline; bool textbox_outline; diff --git a/desktop_version/src/Textbox.cpp b/desktop_version/src/Textbox.cpp index 0a164b03..40285c8e 100644 --- a/desktop_version/src/Textbox.cpp +++ b/desktop_version/src/Textbox.cpp @@ -29,7 +29,7 @@ textboxclass::textboxclass(int gap) large = false; - position_forced = false; + position_absolute = false; should_centerx = false; should_centery = false; @@ -83,7 +83,7 @@ void textboxclass::centery(void) void textboxclass::applyposition(void) { resize(); - if (!position_forced) + if (!position_absolute) { reposition(); if (should_centerx) diff --git a/desktop_version/src/Textbox.h b/desktop_version/src/Textbox.h index ad3e1546..1e09b1bf 100644 --- a/desktop_version/src/Textbox.h +++ b/desktop_version/src/Textbox.h @@ -125,7 +125,7 @@ public: bool large; - bool position_forced; + bool position_absolute; bool should_centerx; bool should_centery; From fa8517a521559ed65833f8b62594c4c1cfe1ecf8 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 15 Nov 2024 20:33:10 -0500 Subject: [PATCH 24/64] iOS port (for desktop_version) (#1137) --- .../AppIcon.appiconset/AppIcon.png | Bin 0 -> 293434 bytes .../AppIcon.appiconset/Contents.json | 14 ++++++ .../AppIcon.xcassets/Contents.json | 6 +++ desktop_version/CMakeLists.txt | 45 +++++++++++++++++- desktop_version/Info.plist | 8 ++++ .../VVVVVV-android/app/build.gradle | 4 +- desktop_version/src/ButtonGlyphs.cpp | 2 +- desktop_version/src/FileSystemUtils.cpp | 13 +++++ desktop_version/src/Game.cpp | 2 +- desktop_version/src/SDL_uikit_main.c | 23 +++++++++ desktop_version/src/Screen.cpp | 2 +- desktop_version/src/Vlogging.c | 3 +- desktop_version/src/main.cpp | 2 + 13 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 desktop_version/AppIcon.xcassets/AppIcon.appiconset/AppIcon.png create mode 100644 desktop_version/AppIcon.xcassets/AppIcon.appiconset/Contents.json create mode 100644 desktop_version/AppIcon.xcassets/Contents.json create mode 100644 desktop_version/Info.plist create mode 100644 desktop_version/src/SDL_uikit_main.c diff --git a/desktop_version/AppIcon.xcassets/AppIcon.appiconset/AppIcon.png b/desktop_version/AppIcon.xcassets/AppIcon.appiconset/AppIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..6b3a72b78c9a33b7457236a0a0a7af624ea00652 GIT binary patch literal 293434 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­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 literal 0 HcmV?d00001 diff --git a/desktop_version/AppIcon.xcassets/AppIcon.appiconset/Contents.json b/desktop_version/AppIcon.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..cefcc878 --- /dev/null +++ b/desktop_version/AppIcon.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "AppIcon.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/desktop_version/AppIcon.xcassets/Contents.json b/desktop_version/AppIcon.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/desktop_version/AppIcon.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/desktop_version/CMakeLists.txt b/desktop_version/CMakeLists.txt index f2cfa3b9..bc316c5e 100644 --- a/desktop_version/CMakeLists.txt +++ b/desktop_version/CMakeLists.txt @@ -25,7 +25,7 @@ option(REMOVE_ABSOLUTE_PATHS "If supported by the compiler, replace all absolute # Architecture Flags -if(APPLE) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") # Wow, Apple is a huge jerk these days huh? set(OSX_10_9_SDK_PATH /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk) if(NOT CMAKE_OSX_SYSROOT) @@ -38,6 +38,8 @@ if(APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) link_directories(/usr/local/lib) add_compile_options(-Werror=partial-availability) +elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0) # SDL goes back to iOS 8.0, but modern Xcode doesn't endif() project(VVVVVV) @@ -48,7 +50,10 @@ endif() # RPATH if(NOT WIN32) - if(APPLE) + if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(BIN_LIBROOT "Frameworks") + set(BIN_RPATH "@executable_path/Frameworks") + elseif(APPLE) set(BIN_LIBROOT "osx") set(BIN_RPATH "@executable_path/osx") elseif(CMAKE_SIZEOF_VOID_P MATCHES "8") @@ -128,6 +133,9 @@ endif() if(GOG) list(APPEND VVV_C_SRC src/GOGNetwork.c) endif() +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + list(APPEND VVV_C_SRC src/SDL_uikit_main.c) +endif() set(VVV_SRC ${VVV_CXX_SRC} ${VVV_C_SRC}) @@ -136,6 +144,30 @@ if(WIN32) add_executable(VVVVVV WIN32 ${VVV_SRC} icon.rc) elseif(ANDROID) add_library(VVVVVV SHARED ${VVV_SRC}) +elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") + file(GLOB_RECURSE REPO_RESOURCES "fonts/*" "lang/*") + + add_executable(VVVVVV MACOSX_BUNDLE ${VVV_SRC} ${DATA_ZIP} AppIcon.xcassets ${REPO_RESOURCES}) + set_target_properties(VVVVVV PROPERTIES + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.distractionware.vvvvvvmobile" + XCODE_ATTRIBUTE_PRODUCT_NAME "VVVVVV" + XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2" # iPhone, iPad + XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "2.5" + XCODE_ATTRIBUTE_MARKETING_VERSION "2.5" + XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME AppIcon + XCODE_ATTRIBUTE_GENERATE_INFOPLIST_FILE YES + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist" + XCODE_ATTRIBUTE_INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace YES + XCODE_ATTRIBUTE_INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents YES + RESOURCE "${DATA_ZIP};AppIcon.xcassets" + ) + + foreach(REPO_FILE ${REPO_RESOURCES}) + file(RELATIVE_PATH REPO_FILE_REL "${CMAKE_CURRENT_SOURCE_DIR}" ${REPO_FILE}) + get_filename_component(REPO_FILE_DIR ${REPO_FILE_REL} DIRECTORY) + set_property(SOURCE ${REPO_FILE} PROPERTY MACOSX_PACKAGE_LOCATION "Resources/${REPO_FILE_DIR}") + source_group("Resources/${REPO_FILE_DIR}" FILES "${REPO_FILE}") + endforeach() else() add_executable(VVVVVV ${VVV_SRC}) endif() @@ -419,6 +451,15 @@ elseif (EMSCRIPTEN) target_compile_options(faudio-static PUBLIC -sUSE_SDL=2) target_link_libraries(faudio-static -sUSE_SDL=2) endif() +elseif(DEFINED SDL2_FRAMEWORK) + message(STATUS "Using pre-defined SDL2 variable SDL2_FRAMEWORK") + target_include_directories(VVVVVV SYSTEM PRIVATE "$") + target_link_libraries(VVVVVV ${SDL2_FRAMEWORK}) + if(BUNDLE_DEPENDENCIES) + target_include_directories(faudio-static SYSTEM PRIVATE "$") + target_link_libraries(faudio-static ${SDL2_FRAMEWORK}) + endif() + set_target_properties(VVVVVV PROPERTIES XCODE_EMBED_FRAMEWORKS ${SDL2_FRAMEWORK}) else() # Only try to autodetect if both SDL2 variables aren't explicitly set find_package(SDL2 CONFIG) diff --git a/desktop_version/Info.plist b/desktop_version/Info.plist new file mode 100644 index 00000000..ff579a6c --- /dev/null +++ b/desktop_version/Info.plist @@ -0,0 +1,8 @@ + + + + + UIFileSharingEnabled + + + diff --git a/desktop_version/VVVVVV-android/app/build.gradle b/desktop_version/VVVVVV-android/app/build.gradle index f1b358ce..58692135 100644 --- a/desktop_version/VVVVVV-android/app/build.gradle +++ b/desktop_version/VVVVVV-android/app/build.gradle @@ -14,8 +14,8 @@ android { defaultConfig { minSdkVersion 29 targetSdkVersion 34 - versionCode 20004000 - versionName "2.4" + versionCode 20005000 + versionName "2.5" applicationId "air.com.distractionware.vvvvvvmobile" externalNativeBuild { cmake { diff --git a/desktop_version/src/ButtonGlyphs.cpp b/desktop_version/src/ButtonGlyphs.cpp index 53171708..4abbf4ed 100644 --- a/desktop_version/src/ButtonGlyphs.cpp +++ b/desktop_version/src/ButtonGlyphs.cpp @@ -178,7 +178,7 @@ bool BUTTONGLYPHS_keyboard_is_available(void) return true; } -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(TARGET_OS_IPHONE) return false; #else return !SDL_GetHintBoolean("SteamDeck", SDL_FALSE); diff --git a/desktop_version/src/FileSystemUtils.cpp b/desktop_version/src/FileSystemUtils.cpp index 5f61146a..cd3e6e2c 100644 --- a/desktop_version/src/FileSystemUtils.cpp +++ b/desktop_version/src/FileSystemUtils.cpp @@ -1331,6 +1331,19 @@ static int PLATFORM_getOSDirectory(char* output, const size_t output_size) } SDL_snprintf(output, output_size, "%s/", externalStoragePath); return 1; +#elif defined(TARGET_OS_IPHONE) + // (ab)use SDL APIs to get the path to the Documents folder without needing Objective-C + const char* prefsPath = SDL_GetPrefPath("", ""); + if (prefsPath == NULL) + { + vlog_error( + "Could not get OS directory: %s", + SDL_GetError() + ); + return 0; + } + SDL_snprintf(output, output_size, "%s/../../Documents/", prefsPath); + return 1; #else const char* prefDir = PHYSFS_getPrefDir("distractionware", "VVVVVV"); if (prefDir == NULL) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 6114a446..201007c2 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -377,7 +377,7 @@ void Game::init(void) screenshot_border_timer = 0; screenshot_saved_success = false; -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(TARGET_OS_IPHONE) checkpoint_saving = true; #else checkpoint_saving = false; diff --git a/desktop_version/src/SDL_uikit_main.c b/desktop_version/src/SDL_uikit_main.c new file mode 100644 index 00000000..6ce34929 --- /dev/null +++ b/desktop_version/src/SDL_uikit_main.c @@ -0,0 +1,23 @@ +/* + SDL_uikit_main.c, placed in the public domain by Sam Lantinga 3/18/2019 +*/ + +/* Include the SDL main definition header */ +#include "SDL_main.h" + +#if defined(__IPHONEOS__) || defined(__TVOS__) + +#ifndef SDL_MAIN_HANDLED +#ifdef main +#undef main +#endif + +int main(int argc, char *argv[]) +{ + return SDL_UIKitRunApp(argc, argv, SDL_main); +} +#endif /* !SDL_MAIN_HANDLED */ + +#endif /* __IPHONEOS__ || __TVOS__ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/desktop_version/src/Screen.cpp b/desktop_version/src/Screen.cpp index cedf3115..6dabc8ba 100644 --- a/desktop_version/src/Screen.cpp +++ b/desktop_version/src/Screen.cpp @@ -383,7 +383,7 @@ bool Screen::isForcedFullscreen(void) * If you're working on a tenfoot-only build, add a def that always * returns true! */ -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(TARGET_OS_IPHONE) return true; #else return SDL_GetHintBoolean("SteamTenfoot", SDL_FALSE); diff --git a/desktop_version/src/Vlogging.c b/desktop_version/src/Vlogging.c index c0d19781..8a3a730a 100644 --- a/desktop_version/src/Vlogging.c +++ b/desktop_version/src/Vlogging.c @@ -3,8 +3,9 @@ #include #include -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(TARGET_OS_IPHONE) // forward to SDL logging on Android, since stdout/stderr are /dev/null +// they exist on iOS, but just get forwarded to the system log anyway, so might as well provide proper metadata #define VLOG_USE_SDL 1 #endif diff --git a/desktop_version/src/main.cpp b/desktop_version/src/main.cpp index 2f884ec7..4b87dbff 100644 --- a/desktop_version/src/main.cpp +++ b/desktop_version/src/main.cpp @@ -604,6 +604,8 @@ int main(int argc, char *argv[]) /* We already do the button swapping in ButtonGlyphs, disable SDL's swapping */ SDL_SetHintWithPriority(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0", SDL_HINT_OVERRIDE); + SDL_SetHintWithPriority(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight", SDL_HINT_OVERRIDE); + if(!FILESYSTEM_init(argv[0], baseDir, assetsPath, langDir, fontsDir)) { vlog_error("Unable to initialize filesystem!"); From 9c45dfb84560ed2ee99c34d03bfe9a80f3256028 Mon Sep 17 00:00:00 2001 From: Reese Rivers <44736084+Fussmatte@users.noreply.github.com> Date: Fri, 15 Nov 2024 21:05:40 -0500 Subject: [PATCH 25/64] Tweak one word in the Esperanto localisation "Rekordo" (record) flows better than "altpoentaro", which is a literal translation of "high score". --- desktop_version/lang/eo/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/lang/eo/strings.xml b/desktop_version/lang/eo/strings.xml index 63fcd003..cc34e896 100644 --- a/desktop_version/lang/eo/strings.xml +++ b/desktop_version/lang/eo/strings.xml @@ -456,7 +456,7 @@ - + From 63880169e6e567f65795ff721b911b99eb88a721 Mon Sep 17 00:00:00 2001 From: Ally Date: Sun, 17 Nov 2024 12:45:57 -0400 Subject: [PATCH 26/64] Convert entity `type`s to an enum (#1007) In an effort to remove magic numbers, I've given every entity type a name. Hopefully I didn't miss anywhere. Also, add `createentity` case 100 for backwards compatibility. Co-authored-by: NyakoFox Co-authored-by: Dav999 --- desktop_version/src/Ent.cpp | 10 +- desktop_version/src/Ent.h | 31 ++++- desktop_version/src/Entity.cpp | 192 +++++++++++++++----------- desktop_version/src/LevelDebugger.cpp | 18 +-- desktop_version/src/Logic.cpp | 32 +++-- desktop_version/src/Map.cpp | 10 +- desktop_version/src/Script.cpp | 8 +- 7 files changed, 181 insertions(+), 120 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index 35db8bf6..f159547f 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -11,7 +11,7 @@ entclass::entclass(void) void entclass::clear(void) { invis = false; - type = 0; + type = EntityType_PLAYER; size = 0; tile = 0; rule = 0; @@ -650,8 +650,8 @@ void entclass::updatecolour(void) bool entclass::ishumanoid(void) { - return type == 0 - || type == 12 - || type == 14 - || type == 55; + return type == EntityType_PLAYER + || type == EntityType_CREWMATE + || type == EntityType_SUPERCREWMATE + || type == EntityType_COLLECTABLE_CREWMATE; } diff --git a/desktop_version/src/Ent.h b/desktop_version/src/Ent.h index f4ddd43c..d422a519 100644 --- a/desktop_version/src/Ent.h +++ b/desktop_version/src/Ent.h @@ -5,6 +5,34 @@ #define rn( rx, ry) ((rx) + ((ry) * 100)) +enum EntityType +{ + EntityType_INVALID = -1, + EntityType_PLAYER, + EntityType_MOVING, + EntityType_DISAPPEARING_PLATFORM, + EntityType_QUICKSAND, + EntityType_GRAVITY_TOKEN, + EntityType_PARTICLE, + EntityType_COIN, + EntityType_TRINKET, + EntityType_CHECKPOINT, + EntityType_HORIZONTAL_GRAVITY_LINE, + EntityType_VERTICAL_GRAVITY_LINE, + EntityType_WARP_TOKEN, + EntityType_CREWMATE, + EntityType_TERMINAL, + EntityType_SUPERCREWMATE, + EntityType_TROPHY, + EntityType_GRAVITRON_ENEMY = 23, + EntityType_WARP_LINE_LEFT = 51, + EntityType_WARP_LINE_RIGHT = 52, + EntityType_WARP_LINE_TOP = 53, + EntityType_WARP_LINE_BOTTOM = 54, + EntityType_COLLECTABLE_CREWMATE = 55, + EntityType_TELEPORTER = 100 +}; + class entclass { public: @@ -26,7 +54,8 @@ public: public: //Fundamentals bool invis; - int type, size, tile, rule; + EntityType type; + int size, tile, rule; int state, statedelay; int behave, animate; float para; diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 5023b16b..d329e3a8 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -123,7 +123,7 @@ void entityclass::swnenemiescol( int t ) //change the colour of all SWN enemies to the current one for (size_t i = 0; i < entities.size(); i++) { - if (entities[i].type == 23) + if (entities[i].type == EntityType_GRAVITRON_ENEMY) { entities[i].colour = swncolour(t); } @@ -1133,7 +1133,7 @@ bool entityclass::disableentity(int t) entities[t].invis = true; entities[t].size = -1; - entities[t].type = -1; + entities[t].type = EntityType_INVALID; entities[t].rule = -1; entities[t].isplatform = false; @@ -1269,7 +1269,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int { if (entities[i].invis && entities[i].size == -1 - && entities[i].type == -1 + && entities[i].type == EntityType_INVALID && entities[i].rule == -1 && !entities[i].isplatform) { @@ -1318,7 +1318,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entclass& entity = *entptr; entity.xp = xp; entity.yp = yp; - entity.type = t; + entity.type = EntityType_INVALID; switch(t) { case 0: //Player @@ -1330,6 +1330,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.w = 12; entity.h = 21; entity.dir = 1; + entity.type = EntityType_PLAYER; /* Fix wrong y-position if spawning in on conveyor */ entity.newxp = xp; @@ -1358,6 +1359,8 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.animate = 0; entity.colour = 8; + entity.type = EntityType_MOVING; + if (game.roomy == 111 && (game.roomx >= 113 && game.roomx <= 117)) { entity.setenemy(0); @@ -1386,7 +1389,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 2: //A moving platform entity.rule = 2; - entity.type = 1; + entity.type = EntityType_MOVING; entity.size = 2; entity.tile = 1; @@ -1454,7 +1457,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 3: //Disappearing platforms entity.rule = 3; - entity.type = 2; + entity.type = EntityType_DISAPPEARING_PLATFORM; entity.size = 2; entity.tile = 2; //appearance again depends on location @@ -1484,7 +1487,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 4: //Breakable blocks entity.rule = 6; - entity.type = 3; + entity.type = EntityType_QUICKSAND; entity.size = 1; entity.tile = 10; entity.cy = -1; @@ -1499,7 +1502,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 5: //Gravity Tokens entity.rule = 3; - entity.type = 4; + entity.type = EntityType_GRAVITY_TOKEN; entity.size = 0; entity.tile = 11; entity.w = 16; @@ -1511,7 +1514,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 6: //Decorative particles entity.rule = 2; - entity.type = 5; //Particles + entity.type = EntityType_PARTICLE; //Particles entity.colour = 1; entity.size = 3; entity.vx = meta1; @@ -1521,7 +1524,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 7: //Decorative particles entity.rule = 2; - entity.type = 5; //Particles + entity.type = EntityType_PARTICLE; //Particles entity.colour = 2; entity.size = 3; entity.vx = meta1; @@ -1531,7 +1534,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 8: //Small collectibles entity.rule = 3; - entity.type = 6; + entity.type = EntityType_COIN; entity.size = 4; entity.tile = 48; entity.w = 8; @@ -1545,7 +1548,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 9: //Something Shiny entity.rule = 3; - entity.type = 7; + entity.type = EntityType_TRINKET; entity.size = 0; entity.tile = 22; entity.w = 16; @@ -1560,7 +1563,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 10: //Savepoint entity.rule = 3; - entity.type = 8; + entity.type = EntityType_CHECKPOINT; entity.size = 0; entity.tile = 20 + meta1; entity.w = 16; @@ -1583,7 +1586,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 11: //Horizontal Gravity Line entity.rule = 4; - entity.type = 9; + entity.type = EntityType_HORIZONTAL_GRAVITY_LINE; entity.size = 5; entity.life = 0; entity.w = meta1; @@ -1592,7 +1595,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 12: //Vertical Gravity Line entity.rule = 5; - entity.type = 10; + entity.type = EntityType_VERTICAL_GRAVITY_LINE; entity.size = 6; entity.life = 0; entity.w = 1; @@ -1602,7 +1605,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 13: //Warp token entity.rule = 3; - entity.type = 11; + entity.type = EntityType_WARP_TOKEN; entity.size = 0; entity.tile = 18; entity.w = 16; @@ -1616,7 +1619,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 14: // Teleporter entity.rule = 3; - entity.type = 100; + entity.type = EntityType_TELEPORTER; entity.size = 7; entity.tile = 1; //inactive entity.w = 96; @@ -1628,7 +1631,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 15: // Crew Member (warp zone) entity.rule = 6; - entity.type = 12; //A special case! + entity.type = EntityType_CREWMATE; //A special case! entity.tile = 144; entity.colour = 13; //144 for sad :( entity.cx = 6; @@ -1643,7 +1646,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 16: // Crew Member, upside down (space station) entity.rule = 7; - entity.type = 12; //A special case! + entity.type = EntityType_CREWMATE; //A special case! entity.tile = 144+6; entity.colour = 14; //144 for sad (upside down+12):( entity.cx = 6; @@ -1658,7 +1661,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 17: // Crew Member (Lab) entity.rule = 6; - entity.type = 12; //A special case! + entity.type = EntityType_CREWMATE; //A special case! entity.tile = 144; entity.colour = 16; //144 for sad :( entity.cx = 6; @@ -1674,7 +1677,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int case 18: // Crew Member (Ship) //This is the scriping crewmember entity.rule = 6; - entity.type = 12; //A special case! + entity.type = EntityType_CREWMATE; //A special case! entity.colour = meta1; if (meta2 == 0) { @@ -1702,7 +1705,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 19: // Crew Member (Ship) More tests! entity.rule = 6; - entity.type = 12; //A special case! + entity.type = EntityType_CREWMATE; //A special case! entity.tile = 0; entity.colour = 6; //54 for sad :( entity.cx = 6; @@ -1717,7 +1720,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 20: //Terminal entity.rule = 3; - entity.type = 13; + entity.type = EntityType_TERMINAL; entity.size = 0; entity.tile = 16 + meta1; entity.w = 16; @@ -1729,7 +1732,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 21: //as above, except doesn't highlight entity.rule = 3; - entity.type = 13; + entity.type = EntityType_TERMINAL; entity.size = 0; entity.tile = 16 + meta1; entity.w = 16; @@ -1741,7 +1744,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 22: //Fake trinkets, only appear if you've collected them entity.rule = 3; - entity.type = 7; + entity.type = EntityType_TRINKET; entity.size = 0; entity.tile = 22; entity.w = 16; @@ -1757,7 +1760,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int case 23: //SWN Enemies //Given a different behavior, these enemies are especially for SWN mode and disappear outside the screen. entity.rule = 1; - entity.type = 23; + entity.type = EntityType_GRAVITRON_ENEMY; entity.behave = meta1; entity.para = meta2; entity.w = 16; @@ -1786,7 +1789,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int case 24: // Super Crew Member //This special crewmember is way more advanced than the usual kind, and can interact with game objects entity.rule = 6; - entity.type = 14; //A special case! + entity.type = EntityType_SUPERCREWMATE; //A special case! entity.colour = meta1; if (meta1 == 16) { @@ -1828,7 +1831,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 25: //Trophies entity.rule = 3; - entity.type = 15; + entity.type = EntityType_TROPHY; entity.size = 0; entity.w = 16; entity.h = 16; @@ -2003,7 +2006,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 26: //Epilogue super warp token entity.rule = 3; - entity.type = 11; + entity.type = EntityType_WARP_TOKEN; entity.size = 0; entity.tile = 18; entity.w = 16; @@ -2020,7 +2023,23 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int case 52: /* Vertical */ case 53: /* Horizontal */ case 54: /* Horizontal */ - entity.type = t; + if (t == 51) + { + entity.type = EntityType_WARP_LINE_LEFT; + } + else if (t == 52) + { + entity.type = EntityType_WARP_LINE_RIGHT; + } + else if (t == 53) + { + entity.type = EntityType_WARP_LINE_TOP; + } + else + { + entity.type = EntityType_WARP_LINE_BOTTOM; + } + entity.onentity = 1; entity.invis = true; entity.life = 0; @@ -2052,7 +2071,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int //1 - position in array //2 - colour entity.rule = 3; - entity.type = 55; + entity.type = EntityType_COLLECTABLE_CREWMATE; if(INBOUNDS_ARR(meta2, customcrewmoods) && customcrewmoods[meta2]==1){ entity.tile = 144; @@ -2078,7 +2097,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int break; case 56: //Custom enemy entity.rule = 1; - entity.type = 1; + entity.type = EntityType_MOVING; entity.behave = meta1; entity.para = meta2; entity.w = 16; @@ -2154,6 +2173,9 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entityclonefix(&entity); break; + case 100: // Invalid enemy, but gets treated as a teleporter + entity.type = EntityType_TELEPORTER; + break; } entity.lerpoldxp = entity.xp; @@ -2169,7 +2191,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int * This is a bit kludge-y but it's better than copy-pasting * and is okay to do because entity 12 does not change state on its own */ - if (entity.type == 12) + if (entity.type == EntityType_CREWMATE) { size_t indice; if (reuse) @@ -2222,9 +2244,9 @@ bool entityclass::updateentities( int i ) { switch(entities[i].type) { - case 0: //Player + case EntityType_PLAYER: //Player break; - case 1: //Movement behaviors + case EntityType_MOVING: //Movement behaviors //Enemies can have a number of different behaviors: switch(entities[i].behave) { @@ -2454,7 +2476,7 @@ bool entityclass::updateentities( int i ) { for (size_t j = 0; j < entities.size(); j++) { - if (entities[j].type == 2 && entities[j].state== 3 && entities[j].xp == (entities[i].xp-32) ) + if (entities[j].type == EntityType_DISAPPEARING_PLATFORM && entities[j].state== 3 && entities[j].xp == (entities[i].xp-32) ) { entities[i].state = 3; bool entitygone = updateentities(i); @@ -2484,7 +2506,7 @@ bool entityclass::updateentities( int i ) { for (size_t j = 0; j < entities.size(); j++) { - if (entities[j].type == 2 && entities[j].state==3 && entities[j].xp==entities[i].xp+32) + if (entities[j].type == EntityType_DISAPPEARING_PLATFORM && entities[j].state==3 && entities[j].xp==entities[i].xp+32) { entities[i].state = 3; bool entitygone = updateentities(i); @@ -2582,7 +2604,7 @@ bool entityclass::updateentities( int i ) break; } break; - case 2: //Disappearing platforms + case EntityType_DISAPPEARING_PLATFORM: //Disappearing platforms //wait for collision if (entities[i].state == 1) { @@ -2629,7 +2651,7 @@ bool entityclass::updateentities( int i ) } } break; - case 3: //Breakable blocks + case EntityType_QUICKSAND: //Breakable blocks //Only counts if vy of player entity is non zero if (entities[i].state == 1) { @@ -2649,7 +2671,7 @@ bool entityclass::updateentities( int i ) } } break; - case 4: //Gravity token + case EntityType_GRAVITY_TOKEN: //Gravity token //wait for collision if (entities[i].state == 1) { @@ -2659,7 +2681,7 @@ bool entityclass::updateentities( int i ) } break; - case 5: //Particle sprays + case EntityType_PARTICLE: //Particle sprays if (entities[i].state == 0) { entities[i].life--; @@ -2669,7 +2691,7 @@ bool entityclass::updateentities( int i ) } } break; - case 6: //Small pickup + case EntityType_COIN: //Small pickup //wait for collision if (entities[i].state == 1) { @@ -2682,7 +2704,7 @@ bool entityclass::updateentities( int i ) return disableentity(i); } break; - case 7: //Found a trinket + case EntityType_TRINKET: //Found a trinket //wait for collision if (entities[i].state == 1) { @@ -2710,14 +2732,14 @@ bool entityclass::updateentities( int i ) return disableentity(i); } break; - case 8: //Savepoints + case EntityType_CHECKPOINT: //Savepoints //wait for collision if (entities[i].state == 1) { //First, deactivate all other savepoints for (size_t j = 0; j < entities.size(); j++) { - if (entities[j].type == 8) + if (entities[j].type == EntityType_CHECKPOINT) { entities[j].colour = 4; entities[j].onentity = 1; @@ -2753,7 +2775,7 @@ bool entityclass::updateentities( int i ) game.checkpoint_save(); } break; - case 9: //Gravity Lines + case EntityType_HORIZONTAL_GRAVITY_LINE: //Gravity Lines if (entities[i].state == 1) { entities[i].life--; @@ -2766,7 +2788,7 @@ bool entityclass::updateentities( int i ) } } break; - case 10: //Vertical gravity Lines + case EntityType_VERTICAL_GRAVITY_LINE: //Vertical gravity Lines if (entities[i].state == 1) { entities[i].onentity = 3; @@ -2808,7 +2830,7 @@ bool entityclass::updateentities( int i ) entities[i].state = 2; } break; - case 11: //Warp point + case EntityType_WARP_TOKEN: //Warp point //wait for collision if (entities[i].state == 1) { @@ -2826,7 +2848,7 @@ bool entityclass::updateentities( int i ) if (int(entities[i].xp) == 21*8) game.teleportxpos = 4; } break; - case 12: //Crew member + case EntityType_CREWMATE: //Crew member //Somewhat complex AI: exactly what they do depends on room, location, state etc //At state 0, do nothing at all. if (entities[i].state == 1) @@ -3161,7 +3183,7 @@ bool entityclass::updateentities( int i ) } } break; - case 13: //Terminals (very similar to savepoints) + case EntityType_TERMINAL: //Terminals (very similar to savepoints) //wait for collision if (entities[i].state == 1) { @@ -3172,7 +3194,7 @@ bool entityclass::updateentities( int i ) entities[i].state = 0; } break; - case 14: //Super Crew member + case EntityType_SUPERCREWMATE: //Super Crew member //Actually needs less complex AI than the scripting crewmember if (entities[i].state == 0) { @@ -3228,7 +3250,7 @@ bool entityclass::updateentities( int i ) } } break; - case 15: //Trophy + case EntityType_TROPHY: //Trophy //wait for collision if (entities[i].state == 1) { @@ -3239,7 +3261,7 @@ bool entityclass::updateentities( int i ) entities[i].state = 0; } break; - case 23: + case EntityType_GRAVITRON_ENEMY: //swn game! switch(entities[i].behave) { @@ -3266,7 +3288,7 @@ bool entityclass::updateentities( int i ) } break; - case 51: //Vertical warp line + case EntityType_WARP_LINE_LEFT: //Vertical warp line if (entities[i].state == 2){ int j=getplayer(); if(INBOUNDS_VEC(j, entities) && entities[j].xp<=307){ @@ -3281,7 +3303,7 @@ bool entityclass::updateentities( int i ) customwarpmodevon=true; } break; - case 52: //Vertical warp line + case EntityType_WARP_LINE_RIGHT: //Vertical warp line if (entities[i].state == 2){ int j=getplayer(); if(INBOUNDS_VEC(j, entities) && entities[j].xp<=307){ @@ -3296,7 +3318,7 @@ bool entityclass::updateentities( int i ) customwarpmodevon=true; } break; - case 53: //Warp lines Horizonal + case EntityType_WARP_LINE_TOP: //Warp lines Horizonal if (entities[i].state == 2){ customwarpmodehon=false; entities[i].state = 0; @@ -3308,7 +3330,7 @@ bool entityclass::updateentities( int i ) customwarpmodehon=true; } break; - case 54: //Warp lines Horizonal + case EntityType_WARP_LINE_BOTTOM: //Warp lines Horizonal if (entities[i].state == 2){ customwarpmodehon=false; entities[i].state = 0; @@ -3320,7 +3342,7 @@ bool entityclass::updateentities( int i ) customwarpmodehon=true; } break; - case 55: //Collectable crewmate + case EntityType_COLLECTABLE_CREWMATE: //Collectable crewmate //wait for collision if (entities[i].state == 0) { @@ -3357,7 +3379,7 @@ bool entityclass::updateentities( int i ) return disableentity(i); } break; - case 100: //The teleporter + case EntityType_TELEPORTER: //The teleporter if (entities[i].state == 1) { //if inactive, activate! @@ -3383,7 +3405,7 @@ bool entityclass::updateentities( int i ) //First, deactivate all other savepoints for (size_t j = 0; j < entities.size(); j++) { - if (entities[j].type == 8) + if (entities[j].type == EntityType_CHECKPOINT) { entities[j].colour = 4; entities[j].onentity = 1; @@ -3422,6 +3444,8 @@ bool entityclass::updateentities( int i ) entities[i].state = 0; } break; + case EntityType_INVALID: // Invalid entity, do nothing! + break; } } else @@ -3448,7 +3472,7 @@ void entityclass::animateentities( int _i ) { switch(entities[_i].type) { - case 0: + case EntityType_PLAYER: entities[_i].framedelay--; if(entities[_i].dir==1) { @@ -3497,8 +3521,8 @@ void entityclass::animateentities( int _i ) if (game.gravitycontrol == 1) entities[_i].drawframe += 2; } break; - case 1: - case 23: + case EntityType_MOVING: + case EntityType_GRAVITRON_ENEMY: //Variable animation switch(entities[_i].animate) { @@ -3686,10 +3710,10 @@ void entityclass::animateentities( int _i ) break; } break; - case 2: //Disappearing platforms + case EntityType_DISAPPEARING_PLATFORM: //Disappearing platforms entities[_i].drawframe = entities[_i].tile + entities[_i].walkingframe; break; - case 11: + case EntityType_WARP_TOKEN: entities[_i].drawframe = entities[_i].tile; if(entities[_i].animate==2) { @@ -3709,9 +3733,9 @@ void entityclass::animateentities( int _i ) entities[_i].drawframe += entities[_i].walkingframe; } break; - case 12: - case 55: - case 14: //Crew member! Very similar to hero + case EntityType_CREWMATE: + case EntityType_COLLECTABLE_CREWMATE: + case EntityType_SUPERCREWMATE: //Crew member! Very similar to hero entities[_i].framedelay--; if(entities[_i].dir==1) { @@ -3754,7 +3778,7 @@ void entityclass::animateentities( int _i ) //if (game.gravitycontrol == 1) entities[_i].drawframe += 2; } break; - case 100: //the teleporter! + case EntityType_TELEPORTER: //the teleporter! if (entities[_i].tile == 1 || game.noflashingmode) { //it's inactive @@ -3880,7 +3904,7 @@ void entityclass::animatehumanoidcollision(const int i) { ++entity->collisiondrawframe; - if (entity->type == 0 && game.gravitycontrol == 1) + if (entity->type == EntityType_PLAYER && game.gravitycontrol == 1) { entity->collisiondrawframe += 6; } @@ -3896,8 +3920,8 @@ void entityclass::animatehumanoidcollision(const int i) entity->collisiondrawframe = 12; } - if ((entity->type == 0 && game.gravitycontrol == 1) - || (entity->type != 0 && entity->rule == 7)) + if ((entity->type == EntityType_PLAYER && game.gravitycontrol == 1) + || (entity->type != EntityType_PLAYER && entity->rule == 7)) { entity->collisiondrawframe += 2; } @@ -3927,7 +3951,7 @@ int entityclass::getplayer(void) //Returns the index of the first player entity for (size_t i = 0; i < entities.size(); i++) { - if(entities[i].type==0) + if (entities[i].type == EntityType_PLAYER) { return i; } @@ -3941,7 +3965,7 @@ int entityclass::getscm(void) //Returns the supercrewmate for (size_t i = 0; i < entities.size(); i++) { - if(entities[i].type==14) + if (entities[i].type == EntityType_SUPERCREWMATE) { return i; } @@ -3973,7 +3997,7 @@ int entityclass::getcrewman( int t, int fallback /*= 0*/ ) for (size_t i = 0; i < entities.size(); i++) { - if ((entities[i].type == 12 || entities[i].type == 14) + if ((entities[i].type == EntityType_CREWMATE || entities[i].type == EntityType_SUPERCREWMATE) && (entities[i].rule == 6 || entities[i].rule == 7)) { if(entities[i].colour==t) @@ -3998,9 +4022,9 @@ int entityclass::getcustomcrewman( int t ) for (size_t i = 0; i < entities.size(); i++) { - if (entities[i].type == 55) + if (entities[i].type == EntityType_COLLECTABLE_CREWMATE) { - if(entities[i].colour==t) + if (entities[i].colour == t) { return i; } @@ -4014,7 +4038,7 @@ int entityclass::getteleporter(void) { for (size_t i = 0; i < entities.size(); i++) { - if(entities[i].type==100) + if (entities[i].type == EntityType_TELEPORTER) { return i; } @@ -4053,7 +4077,7 @@ bool entityclass::checkdamage(bool scm /*= false*/) //Returns true if player (or supercrewmate) collides with a damagepoint for(size_t i=0; i < entities.size(); i++) { - if((scm && entities[i].type == 14) || (!scm && entities[i].rule == 0)) + if((scm && entities[i].type == EntityType_SUPERCREWMATE) || (!scm && entities[i].rule == 0)) { SDL_Rect temprect; temprect.x = entities[i].xp + entities[i].cx; @@ -4468,7 +4492,7 @@ bool entityclass::testwallsx( int t, int tx, int ty, const bool skipdirblocks ) temprect.w = entities[t].w; temprect.h = entities[t].h; - bool skipblocks = entities[t].rule < 2 || entities[t].type == 14; + bool skipblocks = entities[t].rule < 2 || entities[t].type == EntityType_SUPERCREWMATE; float dx = 0; float dy = 0; if (entities[t].rule == 0) dx = entities[t].vx; @@ -4514,7 +4538,7 @@ bool entityclass::testwallsy( int t, int tx, int ty ) temprect.w = entities[t].w; temprect.h = entities[t].h; - bool skipblocks = entities[t].rule < 2 || entities[t].type == 14; + bool skipblocks = entities[t].rule < 2 || entities[t].type == EntityType_SUPERCREWMATE; float dx = 0; float dy = 0; @@ -4696,13 +4720,13 @@ void entityclass::customwarplinecheck(int i) { for (int j = 0; j < (int) entities.size(); j++) { if (i != j) { if (entities[i].rule == 0 && entities[j].rule == 5 //Player vs vertical line! - && (entities[j].type == 51 || entities[j].type == 52) + && (entities[j].type == EntityType_WARP_LINE_LEFT || entities[j].type == EntityType_WARP_LINE_RIGHT) && entitywarpvlinecollide(i, j)) { customwarpmodevon = true; } if (entities[i].rule == 0 && entities[j].rule == 7 //Player vs horizontal WARP line - && (entities[j].type == 53 || entities[j].type == 54) + && (entities[j].type == EntityType_WARP_LINE_TOP || entities[j].type == EntityType_WARP_LINE_BOTTOM) && entitywarphlinecollide(i, j)) { customwarpmodehon = true; } @@ -4715,7 +4739,7 @@ void entityclass::entitycollisioncheck(void) for (size_t i = 0; i < entities.size(); i++) { bool player = entities[i].rule == 0; - bool scm = game.supercrewmate && entities[i].type == 14; + bool scm = game.supercrewmate && entities[i].type == EntityType_SUPERCREWMATE; if (!player && !scm) { continue; diff --git a/desktop_version/src/LevelDebugger.cpp b/desktop_version/src/LevelDebugger.cpp index b0f64810..b180b704 100644 --- a/desktop_version/src/LevelDebugger.cpp +++ b/desktop_version/src/LevelDebugger.cpp @@ -282,11 +282,11 @@ namespace level_debugger graphics.draw_rect(bounding_box.x, bounding_box.y, bounding_box.w, bounding_box.h, graphics.getRGB(15, 90, 90)); // For gravity lines, show the true hitbox. - if (obj.entities[i].type == 9) + if (obj.entities[i].type == EntityType_HORIZONTAL_GRAVITY_LINE) { graphics.draw_rect(bounding_box.x - 1, bounding_box.y + 1, bounding_box.w + 2, bounding_box.h, graphics.getRGB(90, 90, 15)); } - else if (obj.entities[i].type == 10) + else if (obj.entities[i].type == EntityType_VERTICAL_GRAVITY_LINE) { graphics.fill_rect(bounding_box.x - 2, bounding_box.y - 1, bounding_box.w + 1, bounding_box.h + 2, graphics.getRGB(90, 90, 15)); } @@ -390,33 +390,35 @@ namespace level_debugger // Mostly contains duplicates, but for ease of use switch (entity->type) { - case 0: + case EntityType_PLAYER: // Player render_info(line++, "Gravity", help.String(game.gravitycontrol)); render_info(line++, "Checkpoint", help.String(game.savepoint)); break; - case 1: + case EntityType_MOVING: // Moving platforms and enemies render_info(line++, "Speed", help.String(entity->para)); render_info(line++, "Movement type", help.String(entity->behave)); break; - case 7: + case EntityType_TRINKET: // Trinkets render_info(line++, "ID", help.String(entity->para)); break; - case 8: + case EntityType_CHECKPOINT: // Checkpoints render_info(line++, "ID", help.String(entity->para)); render_info(line++, "Active", game.savepoint == entity->para ? "True" : "False"); break; - case 9: + case EntityType_HORIZONTAL_GRAVITY_LINE: // Horizontal gravity lines render_info(line++, "Horizontal"); break; - case 10: + case EntityType_VERTICAL_GRAVITY_LINE: // Vertical gravity lines render_info(line++, "Vertical"); break; + default: + break; } diff --git a/desktop_version/src/Logic.cpp b/desktop_version/src/Logic.cpp index 67dd637a..958bc8b2 100644 --- a/desktop_version/src/Logic.cpp +++ b/desktop_version/src/Logic.cpp @@ -373,7 +373,7 @@ void gamelogic(void) { if (game.roomx == 111 && game.roomy == 107 && !map.custommode) { - if (obj.entities[i].type == 1) + if (obj.entities[i].type == EntityType_MOVING) { if (obj.entities[i].xp < 152) { @@ -391,7 +391,7 @@ void gamelogic(void) } } } - if (obj.entities[i].type == 2 && obj.entities[i].state == 3) + if (obj.entities[i].type == EntityType_DISAPPEARING_PLATFORM && obj.entities[i].state == 3) { //Ok! super magical exception for the room with the intention death for the shiny trinket //fix this when the maps are finalised @@ -405,7 +405,7 @@ void gamelogic(void) map.settile(18, 9, 59); } } - else if (obj.entities[i].type == 2 && obj.entities[i].state == 2) + else if (obj.entities[i].type == EntityType_DISAPPEARING_PLATFORM && obj.entities[i].state == 2) { //ok, unfortunate case where the disappearing platform hasn't fully disappeared. Accept a little //graphical uglyness to avoid breaking the room! @@ -421,7 +421,7 @@ void gamelogic(void) } if (!entitygone) obj.entities[i].state = 4; } - else if (obj.entities[i].type == 23 && game.swnmode && game.deathseq<15) + else if (obj.entities[i].type == EntityType_GRAVITRON_ENEMY && game.swnmode && game.deathseq<15) { //if playing SWN, get the enemies offscreen. obj.entities[i].xp += obj.entities[i].vx*5; @@ -730,7 +730,7 @@ void gamelogic(void) bool square_onscreen = false; for (size_t i = 0; i < obj.entities.size(); i++) { - if (obj.entities[i].type == 23) + if (obj.entities[i].type == EntityType_GRAVITRON_ENEMY) { square_onscreen = true; break; @@ -1036,9 +1036,11 @@ void gamelogic(void) size_t i; for (i = 0; i < obj.entities.size(); ++i) { - if ((obj.entities[i].type >= 51 - && obj.entities[i].type <= 54) /* Don't warp warp lines */ - || obj.entities[i].size == 12) /* Don't warp gravitron squares */ + if (obj.entities[i].type == EntityType_WARP_LINE_LEFT + || obj.entities[i].type == EntityType_WARP_LINE_RIGHT + || obj.entities[i].type == EntityType_WARP_LINE_TOP + || obj.entities[i].type == EntityType_WARP_LINE_BOTTOM /* Don't warp warp lines */ + || obj.entities[i].size == 12) /* Don't warp gravitron squares */ { continue; } @@ -1094,8 +1096,10 @@ void gamelogic(void) size_t i; for (i = 0; i < obj.entities.size(); ++i) { - if (obj.entities[i].type >= 51 - && obj.entities[i].type <= 54) /* Don't warp warp lines */ + if (obj.entities[i].type == EntityType_WARP_LINE_LEFT + || obj.entities[i].type == EntityType_WARP_LINE_RIGHT + || obj.entities[i].type == EntityType_WARP_LINE_TOP + || obj.entities[i].type == EntityType_WARP_LINE_BOTTOM) /* Don't warp warp lines */ { continue; } @@ -1126,9 +1130,11 @@ void gamelogic(void) size_t i; for (i = 0; i < obj.entities.size(); ++i) { - if ((obj.entities[i].type >= 51 - && obj.entities[i].type <= 54) /* Don't warp warp lines */ - || obj.entities[i].rule == 0) /* Don't warp the player */ + if ((obj.entities[i].type == EntityType_WARP_LINE_LEFT + || obj.entities[i].type == EntityType_WARP_LINE_RIGHT + || obj.entities[i].type == EntityType_WARP_LINE_TOP + || obj.entities[i].type == EntityType_WARP_LINE_BOTTOM) /* Don't warp warp lines */ + || obj.entities[i].rule == 0) /* Don't warp the player */ { continue; } diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index c6cca16b..c06d21a6 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -519,7 +519,7 @@ void mapclass::changefinalcol(int t) //Next, entities for (size_t i = 0; i < obj.entities.size(); i++) { - if (obj.entities[i].type == 1) //something with a movement behavior + if (obj.entities[i].type == EntityType_MOVING) { if (obj.entities[i].animate == 10 || obj.entities[i].animate == 11) //treadmill { @@ -542,7 +542,7 @@ void mapclass::changefinalcol(int t) obj.entities[i].colour = maptiletoenemycol(temp); } } - else if (obj.entities[i].type == 2) //disappearing platforms + else if (obj.entities[i].type == EntityType_DISAPPEARING_PLATFORM) { obj.entities[i].tile = 915+(temp*40); } @@ -892,7 +892,7 @@ void mapclass::gotoroom(int rx, int ry) //Ok, let's save the position of all lines on the screen for (size_t i = 0; i < obj.entities.size(); i++) { - if (obj.entities[i].type == 9) + if (obj.entities[i].type == EntityType_HORIZONTAL_GRAVITY_LINE) { //It's a horizontal line if (obj.entities[i].xp <= 0 || (obj.entities[i].xp + obj.entities[i].w) >= 312) @@ -1030,7 +1030,7 @@ void mapclass::gotoroom(int rx, int ry) for (size_t i = 0; i < obj.entities.size(); i++) { - if (obj.entities[i].type == 9) + if (obj.entities[i].type == EntityType_HORIZONTAL_GRAVITY_LINE) { //It's a horizontal line if (obj.entities[i].xp <= 0 || obj.entities[i].xp + obj.entities[i].w >= 312) @@ -2058,7 +2058,7 @@ void mapclass::loadlevel(int rx, int ry) for (size_t i = 0; i < obj.entities.size(); i++) { - if (obj.entities[i].type == 1 && obj.entities[i].behave >= 8 && obj.entities[i].behave < 10) + if (obj.entities[i].type == EntityType_MOVING && obj.entities[i].behave >= 8 && obj.entities[i].behave < 10) { //put a block underneath int temp = obj.entities[i].xp / 8.0f; diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 75c518d8..5aa50fe5 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -295,7 +295,7 @@ void scriptclass::run(void) { for (size_t edi = 0; edi < obj.entities.size(); edi++) { - if (obj.entities[edi].type == 9 || obj.entities[edi].type == 10) + if (obj.entities[edi].type == EntityType_HORIZONTAL_GRAVITY_LINE || obj.entities[edi].type == EntityType_VERTICAL_GRAVITY_LINE) { obj.disableentity(edi); } @@ -305,7 +305,7 @@ void scriptclass::run(void) { for (size_t edi = 0; edi < obj.entities.size(); edi++) { - if (obj.entities[edi].type == 11) + if (obj.entities[edi].type == EntityType_WARP_TOKEN) { obj.disableentity(edi); } @@ -332,7 +332,7 @@ void scriptclass::run(void) for (size_t edi = 0; edi < obj.entities.size(); edi++) { obj.disableblockat(obj.entities[edi].xp, obj.entities[edi].yp); - if (obj.entities[edi].type == 2 && obj.entities[edi].rule == 3) + if (obj.entities[edi].type == EntityType_DISAPPEARING_PLATFORM && obj.entities[edi].rule == 3) { obj.disableentity(edi); } @@ -1648,7 +1648,7 @@ void scriptclass::run(void) { for (j = 0; j < (int) obj.entities.size(); j++) { - if (obj.entities[j].type == 13) + if (obj.entities[j].type == EntityType_TERMINAL) { obj.entities[j].colour = 4; } From d4e472db1b53bf4951c44f23db5d734faca1b811 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Fri, 15 Nov 2024 20:19:08 -0400 Subject: [PATCH 27/64] Make 0-length gravity lines invisible again --- desktop_version/src/Graphics.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index c4aa3fb5..be992db0 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -1864,6 +1864,11 @@ void Graphics::drawgravityline(const int t, const int x, const int y, const int return; } + if (w <= 0 && h <= 0) + { + return; + } + if (obj.entities[t].life == 0) { if (game.noflashingmode) From 420683a80f4de21a4d4885e1053e65c692b46080 Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Sat, 14 Dec 2024 16:49:47 -0800 Subject: [PATCH 28/64] introduce functions to modulate user volume --- desktop_version/src/Music.cpp | 24 +++++++++++++++++------- desktop_version/src/Music.h | 3 +++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/desktop_version/src/Music.cpp b/desktop_version/src/Music.cpp index 4da6f695..7e172b7a 100644 --- a/desktop_version/src/Music.cpp +++ b/desktop_version/src/Music.cpp @@ -909,6 +909,16 @@ void musicclass::destroy(void) VVV_freefunc(FAudio_Release, faudioctx); } +void musicclass::set_music_volume(int volume) +{ + MusicTrack::SetVolume(volume * user_music_volume / USER_VOLUME_MAX); +} + +void musicclass::set_sound_volume(int volume) +{ + SoundTrack::SetVolume(volume * user_sound_volume / USER_VOLUME_MAX); +} + void musicclass::play(int t) { if (mmmmmm && usingmmmmmm) @@ -962,7 +972,7 @@ void musicclass::play(int t) m_doFadeInVol = false; m_doFadeOutVol = false; musicVolume = VVV_MAX_VOLUME; - MusicTrack::SetVolume(VVV_MAX_VOLUME * user_music_volume / USER_VOLUME_MAX); + set_music_volume(musicVolume); } } else @@ -1100,7 +1110,7 @@ void musicclass::fadeMusicVolumeIn(int ms) musicVolume = 0; /* Fix 1-frame glitch */ - MusicTrack::SetVolume(0); + set_music_volume(0); fade.step_ms = 0; fade.duration_ms = ms; @@ -1299,20 +1309,20 @@ void musicclass::updatemutestate(void) { if (game.muted) { - MusicTrack::SetVolume(0); - SoundTrack::SetVolume(0); + set_music_volume(0); + set_sound_volume(0); } else { - SoundTrack::SetVolume(VVV_MAX_VOLUME * user_sound_volume / USER_VOLUME_MAX); + set_sound_volume(VVV_MAX_VOLUME); if (game.musicmuted) { - MusicTrack::SetVolume(0); + set_music_volume(0); } else { - MusicTrack::SetVolume(musicVolume * user_music_volume / USER_VOLUME_MAX); + set_music_volume(musicVolume); } } } diff --git a/desktop_version/src/Music.h b/desktop_version/src/Music.h index 4085fb0b..fcfad927 100644 --- a/desktop_version/src/Music.h +++ b/desktop_version/src/Music.h @@ -70,6 +70,9 @@ public: void init(void); void destroy(void); + void set_music_volume(int volume); + void set_sound_volume(int volume); + void play(int t); void resume(void); void resumefade(const int fadein_ms); From d90f3c3c08b1e7ce3f2c72638027b1984c487882 Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Sat, 14 Dec 2024 16:54:50 -0800 Subject: [PATCH 29/64] :3 --- desktop_version/src/Render.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index 495cd9d5..abb6aebc 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -105,7 +105,7 @@ static void volumesliderrender(void) } char slider[40 + 1]; - slider_get(slider, sizeof(slider), volume_max_position*volume/USER_VOLUME_MAX, volume_max_position+1, 240); + slider_get(slider, sizeof(slider), volume_max_position * volume / USER_VOLUME_MAX, volume_max_position + 1, 240); char buffer[SCREEN_WIDTH_CHARS + 1]; From f9f9f076b419157efe51ec100232918f179c1c0e Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Sat, 14 Dec 2024 17:29:52 -0800 Subject: [PATCH 30/64] musicVolume -> controlVolume for clarity --- desktop_version/src/Music.cpp | 26 +++++++++++++------------- desktop_version/src/Music.h | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/desktop_version/src/Music.cpp b/desktop_version/src/Music.cpp index 7e172b7a..2e2ba84e 100644 --- a/desktop_version/src/Music.cpp +++ b/desktop_version/src/Music.cpp @@ -504,9 +504,9 @@ end: } } - static void SetVolume(int musicVolume) + static void SetVolume(int controlVolume) { - float adj_vol = (float) musicVolume / VVV_MAX_VOLUME; + float adj_vol = (float)controlVolume / VVV_MAX_VOLUME; if (!IsHalted()) { FAudioVoice_SetVolume(musicVoice, adj_vol, FAUDIO_COMMIT_NOW); @@ -715,7 +715,7 @@ musicclass::musicclass(void) safeToProcessMusic= false; m_doFadeInVol = false; m_doFadeOutVol = false; - musicVolume = 0; + controlVolume = 0; user_music_volume = USER_VOLUME_MAX; user_sound_volume = USER_VOLUME_MAX; @@ -971,8 +971,8 @@ void musicclass::play(int t) { m_doFadeInVol = false; m_doFadeOutVol = false; - musicVolume = VVV_MAX_VOLUME; - set_music_volume(musicVolume); + controlVolume = VVV_MAX_VOLUME; + set_music_volume(controlVolume); } } else @@ -1050,7 +1050,7 @@ void musicclass::haltdasmusik(const bool from_fade) void musicclass::silencedasmusik(void) { - musicVolume = 0; + controlVolume = 0; m_doFadeInVol = false; m_doFadeOutVol = false; } @@ -1107,7 +1107,7 @@ void musicclass::fadeMusicVolumeIn(int ms) m_doFadeOutVol = false; /* Ensure it starts at 0 */ - musicVolume = 0; + controlVolume = 0; /* Fix 1-frame glitch */ set_music_volume(0); @@ -1130,8 +1130,8 @@ void musicclass::fadeMusicVolumeOut(const int fadeout_ms) fade.step_ms = 0; /* Duration is proportional to current volume. */ - fade.duration_ms = fadeout_ms * musicVolume / VVV_MAX_VOLUME; - fade.start_volume = musicVolume; + fade.duration_ms = fadeout_ms * controlVolume / VVV_MAX_VOLUME; + fade.start_volume = controlVolume; fade.end_volume = 0; } @@ -1143,7 +1143,7 @@ void musicclass::fadeout(const bool quick_fade_ /*= true*/) void musicclass::processmusicfadein(void) { - enum FadeCode fade_code = processmusicfade(&fade, &musicVolume); + enum FadeCode fade_code = processmusicfade(&fade, &controlVolume); if (fade_code == Fade_finished) { m_doFadeInVol = false; @@ -1152,10 +1152,10 @@ void musicclass::processmusicfadein(void) void musicclass::processmusicfadeout(void) { - enum FadeCode fade_code = processmusicfade(&fade, &musicVolume); + enum FadeCode fade_code = processmusicfade(&fade, &controlVolume); if (fade_code == Fade_finished) { - musicVolume = 0; + controlVolume = 0; m_doFadeOutVol = false; haltdasmusik(true); } @@ -1322,7 +1322,7 @@ void musicclass::updatemutestate(void) } else { - set_music_volume(musicVolume); + set_music_volume(controlVolume); } } } diff --git a/desktop_version/src/Music.h b/desktop_version/src/Music.h index fcfad927..5e994977 100644 --- a/desktop_version/src/Music.h +++ b/desktop_version/src/Music.h @@ -108,7 +108,7 @@ public: bool m_doFadeInVol; bool m_doFadeOutVol; - int musicVolume; + int controlVolume; /* 0..USER_VOLUME_MAX */ int user_music_volume; From d709db4b45615782ce59e8ab4d4e377d76ab184d Mon Sep 17 00:00:00 2001 From: Dav999 Date: Sat, 21 Dec 2024 04:21:44 +0100 Subject: [PATCH 31/64] Fix squeak and save spam in gamepad menu If you push a button to set a controller binding, you may either hear one Viridian squeak, two Viridian squeaks (a louder one), or Viridian doesn't stop squeaking until you let go of the button. While you hear the continuous squeaking, your save file is also repeatedly saved. There are two small bugs at play here: - the squeak is actually played in two different places at the same time (both in titleinput() whenever a button is pressed, and in updatebuttonmappings() when a mapping is succesfully changed) - titleinput() doesn't register that a button is held down and applies the button (and saves to file) every frame for as long as the button is held This commit fixes both these issues. Now a single button press always causes one squeak, and only if the bindings actually changed. Your save file is also no longer saved repeatedly from holding down the button. --- desktop_version/src/Input.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index c00f7362..1599dc4a 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -2377,17 +2377,26 @@ void titleinput(void) game.jumpheld = true; } + static bool controller_held = false; + if ( game.currentmenuname == Menu::controller && game.currentmenuoption > 0 && game.currentmenuoption < 6 && (game.separate_interact || game.currentmenuoption < 5) && key.controllerButtonDown() ) { - updatebuttonmappings(game.currentmenuoption); - music.playef(Sound_VIRIDIAN); - game.savestatsandsettings_menu(); + if (!controller_held) + { + controller_held = true; + updatebuttonmappings(game.currentmenuoption); + game.savestatsandsettings_menu(); + } return; } + else + { + controller_held = false; + } if (game.menustart && game.menucountdown <= 0 From e318df24bcab585b90495b7b108fd00152ac8d4e Mon Sep 17 00:00:00 2001 From: Dav999 Date: Wed, 5 Feb 2025 16:33:22 +0100 Subject: [PATCH 32/64] Change name of Silesian option by request of translator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our Silesian translator asked for "Ślonsko godka" to be changed to "Ślōnsko". --- desktop_version/lang/szl/meta.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/lang/szl/meta.xml b/desktop_version/lang/szl/meta.xml index 23366352..1f4c67e3 100644 --- a/desktop_version/lang/szl/meta.xml +++ b/desktop_version/lang/szl/meta.xml @@ -3,7 +3,7 @@ 1 - ślonsko godka + ślōnsko Ślōnski przekłŏd: Kuba Kallus From 343790f12b5fc665e46eeecd846020d951c63544 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Tue, 18 Feb 2025 05:38:15 +0100 Subject: [PATCH 33/64] Change name of Silesian option (part 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out there was a little miscommunication with the translator - they said the option needed to say "Ślōnsko" but were only talking about correcting the first word, where I thought the whole thing needed to be replaced. --- desktop_version/lang/szl/meta.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/lang/szl/meta.xml b/desktop_version/lang/szl/meta.xml index 1f4c67e3..fae781f1 100644 --- a/desktop_version/lang/szl/meta.xml +++ b/desktop_version/lang/szl/meta.xml @@ -3,7 +3,7 @@ 1 - ślōnsko + ślōnsko gŏdka Ślōnski przekłŏd: Kuba Kallus From d419c6ed5bdc9958f6b5b52d9bca07d25261a52d Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Wed, 5 Feb 2025 01:22:03 -0400 Subject: [PATCH 34/64] Remove extra unnecessary palettes This merges the colors from other palettes into the general entity palette function. --- desktop_version/src/Ent.cpp | 17 +++-- desktop_version/src/Entity.cpp | 9 ++- desktop_version/src/Graphics.cpp | 119 ++++++++++++------------------- desktop_version/src/Graphics.h | 3 - 4 files changed, 62 insertions(+), 86 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index f159547f..1a6a206c 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -613,17 +613,24 @@ void entclass::updatecolour(void) switch (size) { case 0: // Sprites + case 3: // Big chunky pixels! + case 4: // Small pickups case 7: // Teleporter case 9: // Really Big Sprite! (2x2) case 10: // 2x1 Sprite case 13: // Special for epilogue: huge hero! realcol = graphics.getcol(colour); break; - case 3: // Big chunky pixels! - realcol = graphics.bigchunkygetcol(colour); - break; - case 4: // Small pickups - realcol = graphics.huetilegetcol(); + case 5: // Horizontal gravity line + case 6: // Vertical gravity line + if (life == 0) + { + realcol = graphics.getcol(colour); + } + else + { + realcol = graphics.getcol(24); + } break; case 11: // The fucking elephant if (game.noflashingmode) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index d329e3a8..7fe5efec 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -1292,7 +1292,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int //Size 1 is a tile //Beyond that are special cases (to do) //Size 2 is a moving platform of width 4 (32) - //Size 3 is apparently a "bug chunky pixel" + //Size 3 is apparently a "big chunky pixel" //Size 4 is a coin/small pickup //Size 5 is a horizontal line, 6 is vertical @@ -1515,7 +1515,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int case 6: //Decorative particles entity.rule = 2; entity.type = EntityType_PARTICLE; //Particles - entity.colour = 1; + entity.colour = 27; entity.size = 3; entity.vx = meta1; entity.vy = meta2; @@ -1525,7 +1525,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int case 7: //Decorative particles entity.rule = 2; entity.type = EntityType_PARTICLE; //Particles - entity.colour = 2; + entity.colour = 0; entity.size = 3; entity.vx = meta1; entity.vy = meta2; @@ -1536,6 +1536,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.rule = 3; entity.type = EntityType_COIN; entity.size = 4; + entity.colour = 26; entity.tile = 48; entity.w = 8; entity.h = 8; @@ -1589,6 +1590,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.type = EntityType_HORIZONTAL_GRAVITY_LINE; entity.size = 5; entity.life = 0; + entity.colour = 25; entity.w = meta1; entity.h = 1; entity.onentity = 1; @@ -1598,6 +1600,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.type = EntityType_VERTICAL_GRAVITY_LINE; entity.size = 6; entity.life = 0; + entity.colour = 25; entity.w = 1; entity.h = meta1; //entity.colour = 0; diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index be992db0..ef6d24f6 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -1869,53 +1869,7 @@ void Graphics::drawgravityline(const int t, const int x, const int y, const int return; } - if (obj.entities[t].life == 0) - { - if (game.noflashingmode) - { - set_color(200 - 20, 200 - 20, 200 - 20); - draw_line(x, y, x + w, y + h); - return; - } - - switch(linestate) - { - case 0: - set_color(200 - 20, 200 - 20, 200 - 20); - break; - case 1: - set_color(245 - 30, 245 - 30, 225 - 30); - break; - case 2: - set_color(225 - 30, 245 - 30, 245 - 30); - break; - case 3: - set_color(200 - 20, 200 - 20, 164 - 10); - break; - case 4: - set_color(196 - 20, 255 - 30, 224 - 20); - break; - case 5: - set_color(196 - 20, 235 - 30, 205 - 20); - break; - case 6: - set_color(164 - 10, 164 - 10, 164 - 10); - break; - case 7: - set_color(205 - 20, 245 - 30, 225 - 30); - break; - case 8: - set_color(225 - 30, 255 - 30, 205 - 20); - break; - case 9: - set_color(245 - 30, 245 - 30, 245 - 30); - break; - } - } - else - { - set_color(96, 96, 96); - } + set_color(obj.entities[t].realcol); draw_line(x, y, x + w, y + h); } @@ -3084,8 +3038,49 @@ SDL_Color Graphics::getcol( int t ) case 23: // Enemy : Indicator Gray return getRGB(255 - help.glow / 2 - (int) (GETCOL_RANDOM * 40), 255 - help.glow/2 - (int) (GETCOL_RANDOM * 40), 255 - help.glow/2 - (int) (GETCOL_RANDOM * 40)); - // Trophies - // cyan + case 24: // Gravity line (Inactive) + return getRGB(96, 96, 96); + case 25: // Gravity line (Active) + if (game.noflashingmode) + { + return getRGB(200 - 20, 200 - 20, 200 - 20); + } + + switch (linestate) + { + default: + case 0: + return getRGB(200 - 20, 200 - 20, 200 - 20); + case 1: + return getRGB(245 - 30, 245 - 30, 225 - 30); + case 2: + return getRGB(225 - 30, 245 - 30, 245 - 30); + case 3: + return getRGB(200 - 20, 200 - 20, 164 - 10); + case 4: + return getRGB(196 - 20, 255 - 30, 224 - 20); + case 5: + return getRGB(196 - 20, 235 - 30, 205 - 20); + case 6: + return getRGB(164 - 10, 164 - 10, 164 - 10); + case 7: + return getRGB(205 - 20, 245 - 30, 225 - 30); + case 8: + return getRGB(225 - 30, 255 - 30, 205 - 20); + case 9: + return getRGB(245 - 30, 245 - 30, 245 - 30); + } + case 26: // Coin + if (game.noflashingmode) + { + return getRGB(234, 234, 10); + } + return getRGB(250 - (int) (GETCOL_RANDOM * 32), 250 - (int) (GETCOL_RANDOM * 32), 10); + case 27: // Particle flashy red + return getRGB((GETCOL_RANDOM * 64), 10, 10); + + // Trophies + // cyan case 30: return RGBf(160, 200, 220); // Purple @@ -3202,32 +3197,6 @@ void Graphics::menuoffrender(void) } } -SDL_Color Graphics::huetilegetcol() -{ - if (game.noflashingmode) - { - return getRGB(234, 234, 10); - } - - return getRGB(250 - (int) (fRandom() * 32), 250 - (int) (fRandom() * 32), 10); -} - -SDL_Color Graphics::bigchunkygetcol(int t) -{ - // A seperate index of colours, for simplicity - float random = game.noflashingmode ? 0.5 : fRandom(); - - switch (t) - { - case 1: - return getRGB(random * 64, 10, 10); - case 2: - return getRGB(160 - help.glow / 2 - (int) (random * 20), 200 - help.glow / 2, 220 - help.glow); - } - const SDL_Color color = {0, 0, 0, 0}; - return color; -} - void Graphics::textboxabsolutepos(int x, int y) { if (!INBOUNDS_VEC(m, textboxes)) diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index ea9a2130..e04ddf6d 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -51,9 +51,6 @@ public: GraphicsResources grphx; - SDL_Color huetilegetcol(); - SDL_Color bigchunkygetcol(int t); - void drawgravityline(int t, int x, int y, int w, int h); void drawcoloredtile(int x, int y, int t, int r, int g, int b); From b0d53e85a045345563710cc6a67a53fcbb12bed6 Mon Sep 17 00:00:00 2001 From: mothbeanie Date: Sat, 12 Apr 2025 13:41:30 -0700 Subject: [PATCH 35/64] Crew screen tweaks for custom levels. See #1226 for a full overview with comparison images. --- desktop_version/src/Graphics.cpp | 7 ++-- desktop_version/src/Render.cpp | 63 ++++++++++++++++++-------------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index ef6d24f6..c37a5586 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -425,22 +425,23 @@ void Graphics::print_level_creator( int width_for_face = 17; int total_width = width_for_face + font::len(print_flags, creator.c_str()); int face_x, text_x, sprite_x; + int offset_x = -7; if (!font::is_rtl(print_flags)) { face_x = (SCREEN_WIDTH_PIXELS - total_width) / 2; text_x = face_x + width_for_face; - sprite_x = 7; + sprite_x = 0; } else { face_x = (SCREEN_WIDTH_PIXELS + total_width) / 2; text_x = face_x - width_for_face; face_x -= 10; // sprite origin - sprite_x = 103; + sprite_x = 96; print_flags |= PR_RIGHT; } set_texture_color_mod(grphx.im_sprites, r, g, b); - draw_texture_part(grphx.im_sprites, face_x, y - 1, sprite_x, 2, 10, 10, 1, 1); + draw_texture_part(grphx.im_sprites, face_x + offset_x, y - 3, sprite_x, 0, 24, 12, 1, 1); set_texture_color_mod(grphx.im_sprites, 255, 255, 255); font::print(print_flags, text_x, y, creator, r, g, b); } diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index abb6aebc..c3c1d7c0 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -3102,26 +3102,30 @@ void maprender(void) font::print(title_flags | PR_2X | PR_CEN, -1, FLIP(45, 8), meta.title, 196, 196, 255 - help.glow); int sp = SDL_max(10, font::height(PR_FONT_LEVEL)); + int desc_pos = (cl.numcrewmates() > 0) ? 70 : 70 + (sp*2); graphics.print_level_creator(creator_flags, FLIP(70, 8), meta.creator, 196, 196, 255 - help.glow); - font::print(PR_FONT_LEVEL | PR_CEN, -1, FLIP(70+sp, 8), meta.website, 196, 196, 255 - help.glow); - font::print(PR_FONT_LEVEL | PR_CEN, -1, FLIP(70+sp*3, 8), meta.Desc1, 196, 196, 255 - help.glow); - font::print(PR_FONT_LEVEL | PR_CEN, -1, FLIP(70+sp*4, 8), meta.Desc2, 196, 196, 255 - help.glow); + font::print(PR_FONT_LEVEL | PR_CEN, -1, FLIP(70 + sp, 8), meta.website, 196, 196, 255 - help.glow); + font::print(PR_FONT_LEVEL | PR_CEN, -1, FLIP(desc_pos + sp*3, 8), meta.Desc1, 196, 196, 255 - help.glow); + font::print(PR_FONT_LEVEL | PR_CEN, -1, FLIP(desc_pos + sp*4, 8), meta.Desc2, 196, 196, 255 - help.glow); if (sp <= 10) { - font::print(PR_FONT_LEVEL | PR_CEN, -1, FLIP(70+sp*5, 8), meta.Desc3, 196, 196, 255 - help.glow); + font::print(PR_FONT_LEVEL | PR_CEN, -1, FLIP(desc_pos + sp*5, 8), meta.Desc3, 196, 196, 255 - help.glow); } - int remaining = cl.numcrewmates() - game.crewmates(); + if (cl.numcrewmates() > 0) + { + int remaining = cl.numcrewmates() - game.crewmates(); - char buffer[SCREEN_WIDTH_CHARS + 1]; - loc::gettext_plural_fill( - buffer, sizeof(buffer), - "{n_crew|wordy} crewmates remain", - "{n_crew|wordy} crewmate remains", - "n_crew:int", - remaining - ); - font::print_wrap(PR_CEN, -1, FLIP(165, 8), buffer, 196, 196, 255 - help.glow); + char buffer[SCREEN_WIDTH_CHARS + 1]; + loc::gettext_plural_fill( + buffer, sizeof(buffer), + "{n_crew|wordy} crewmates remain", + "{n_crew|wordy} crewmate remains", + "n_crew:int", + remaining + ); + font::print_wrap(PR_CEN, -1, FLIP(165, 8), buffer, 196, 196, 255 - help.glow); + } } else { @@ -3194,21 +3198,26 @@ void maprender(void) } /* Stats. */ - font::print(PR_CEN | FLIP_PR_CJK_HIGH, -1, FLIP(52, 8), loc::gettext("[Trinkets found]"), 196, 196, 255 - help.glow); - char buffer[SCREEN_WIDTH_CHARS + 1]; - vformat_buf( - buffer, sizeof(buffer), - loc::gettext("{n_trinkets|wordy} out of {max_trinkets|wordy}"), - "n_trinkets:int, max_trinkets:int", - game.trinkets(), max_trinkets - ); - font::print(PR_CEN | FLIP_PR_CJK_LOW, -1, FLIP(64, 8), buffer, 96, 96, 96); + int deaths_pos = (cl.numtrinkets() > 0) ? 102 : 72; + int time_pos = (cl.numtrinkets() > 0) ? 152 : 132; + if (cl.numtrinkets() > 0) + { + font::print(PR_CEN | FLIP_PR_CJK_HIGH, -1, FLIP(52, 8), loc::gettext("[Trinkets found]"), 196, 196, 255 - help.glow); + char buffer[SCREEN_WIDTH_CHARS + 1]; + vformat_buf( + buffer, sizeof(buffer), + loc::gettext("{n_trinkets|wordy} out of {max_trinkets|wordy}"), + "n_trinkets:int, max_trinkets:int", + game.trinkets(), max_trinkets + ); + font::print(PR_CEN | FLIP_PR_CJK_LOW, -1, FLIP(64, 8), buffer, 96, 96, 96); + } - font::print(PR_CEN | FLIP_PR_CJK_HIGH, -1, FLIP(102, 8), loc::gettext("[Number of Deaths]"), 196, 196, 255 - help.glow); - font::print(PR_CEN | FLIP_PR_CJK_LOW, -1, FLIP(114, 8), help.String(game.deathcounts), 96, 96, 96); + font::print(PR_CEN | FLIP_PR_CJK_HIGH, -1, FLIP(deaths_pos, 8), loc::gettext("[Number of Deaths]"), 196, 196, 255 - help.glow); + font::print(PR_CEN | FLIP_PR_CJK_LOW, -1, FLIP(deaths_pos + 12, 8), help.String(game.deathcounts), 96, 96, 96); - font::print(PR_CEN | FLIP_PR_CJK_HIGH, -1, FLIP(152, 8), loc::gettext("[Time Taken]"), 196, 196, 255 - help.glow); - font::print(PR_CEN | FLIP_PR_CJK_LOW, -1, FLIP(164, 8), game.timestring(), 96, 96, 96); + font::print(PR_CEN | FLIP_PR_CJK_HIGH, -1, FLIP(time_pos, 8), loc::gettext("[Time Taken]"), 196, 196, 255 - help.glow); + font::print(PR_CEN | FLIP_PR_CJK_LOW, -1, FLIP(time_pos + 12, 8), game.timestring(), 96, 96, 96); break; } case 3: From 5816e6f51a1577945f1283b54b12ec633e8065ac Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Fri, 11 Apr 2025 00:21:47 -0300 Subject: [PATCH 36/64] Add player colour as a level property This PR adds a new XML property for the player's colour. It is 0 by default, but you can change it to any colour ID. For example, making the player use the trinket color is `3`. This is mostly a quality-of-life addition, as the player's colour is always 0 unless changed by scripts. A lot of levels which use different player colours use an intro script which both changes the player's colour and sets their respawn colour, which works great for finished, completed levels, but makes playtesting a little more annoying as they will spawn in as the wrong colour. Adding a level property for the default player colour fixes this annoyance. Additionally, this changes the behavior of `restoreplayercolour`. This command used to set the player's colour to 0 (ignoring the respawn colour, so when Viridian would die, they would revert to the respawn colour). Now, it sets both Viridian's colour AND the respawn colour to what was present in the level file. This way, you can temporarily change the player colour using the script commands, and then use `restoreplayercolour` to revert back to what the player colour normally is. The start point colour has also changed, to show the player colour instead of always colour 0. Like most changes like this, a way to change this in-editor does not yet exist, but is planned for the future. --- desktop_version/src/CustomLevels.cpp | 21 +++++++++++++++++++++ desktop_version/src/CustomLevels.h | 2 ++ desktop_version/src/Editor.cpp | 6 ++++-- desktop_version/src/Script.cpp | 9 ++++++--- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/desktop_version/src/CustomLevels.cpp b/desktop_version/src/CustomLevels.cpp index bd8ac2aa..2e3f84fe 100644 --- a/desktop_version/src/CustomLevels.cpp +++ b/desktop_version/src/CustomLevels.cpp @@ -404,6 +404,8 @@ void customlevelclass::reset(void) script.textbox_colours.clear(); script.add_default_colours(); map.specialroomnames.clear(); + + player_colour = 0; } const int* customlevelclass::loadlevel( int rxi, int ryi ) @@ -1414,6 +1416,11 @@ next: map.specialroomnames.push_back(name); } } + + if (SDL_strcmp(pKey, "PlayerColour") == 0) + { + player_colour = help.Int(pText); + } } if (mapwidth < maxwidth) @@ -1558,6 +1565,20 @@ bool customlevelclass::save(const std::string& _path) } } + if (player_colour != 0) + { + xml::update_tag(msg, "PlayerColour", player_colour); + } + else + { + // Get rid of this one as well, since older levels don't have this property anyways + tinyxml2::XMLElement* element; + while ((element = msg->FirstChildElement("PlayerColour")) != NULL) + { + doc.DeleteNode(element); + } + } + xml::update_tag(data, "mapwidth", mapwidth); xml::update_tag(data, "mapheight", mapheight); diff --git a/desktop_version/src/CustomLevels.h b/desktop_version/src/CustomLevels.h index b728d412..22285182 100644 --- a/desktop_version/src/CustomLevels.h +++ b/desktop_version/src/CustomLevels.h @@ -170,6 +170,8 @@ public: SDL_Color getonewaycol(int rx, int ry); SDL_Color getonewaycol(void); bool onewaycol_override; + + int player_colour; }; bool translate_title(const std::string& title); diff --git a/desktop_version/src/Editor.cpp b/desktop_version/src/Editor.cpp index 2a04509e..fe89d98d 100644 --- a/desktop_version/src/Editor.cpp +++ b/desktop_version/src/Editor.cpp @@ -1048,11 +1048,11 @@ static void draw_entities(void) if (entity->p1 == 0) // Facing right { - graphics.draw_sprite(x - 4, y, 0, graphics.col_crewcyan); + graphics.draw_sprite(x - 4, y, 0, graphics.getcol(cl.player_colour)); } else // Non-zero is facing left { - graphics.draw_sprite(x - 4, y, 3, graphics.col_crewcyan); + graphics.draw_sprite(x - 4, y, 3, graphics.getcol(cl.player_colour)); } graphics.draw_rect(x, y, 16, 24, graphics.getRGB(255, 255, 164)); @@ -1959,6 +1959,8 @@ void editorrenderfixed(void) const RoomProperty* const room = cl.getroomprop(ed.levx, ed.levy); graphics.updatetitlecolours(); + graphics.trinketcolset = false; + game.customcol = cl.getlevelcol(room->tileset, room->tilecol) + 1; ed.entcol = cl.getenemycol(game.customcol); diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 5aa50fe5..b384f68c 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -1850,8 +1850,9 @@ void scriptclass::run(void) i = obj.getplayer(); if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 0; + obj.entities[i].colour = cl.player_colour; } + game.savecolour = cl.player_colour; } else if (words[0] == "changeplayercolour") { @@ -2652,7 +2653,7 @@ void scriptclass::startgamemode(const enum StartMode mode) } } - /* Containers which need to be reset before gameplay starts + /* State which needs to be reset before gameplay starts * ex. before custom levels get loaded */ switch (mode) @@ -2662,6 +2663,8 @@ void scriptclass::startgamemode(const enum StartMode mode) default: textbox_colours.clear(); add_default_colours(); + cl.onewaycol_override = false; + cl.player_colour = 0; break; } @@ -3207,7 +3210,7 @@ void scriptclass::hardreset(void) game.savey = 0; game.savegc = 0; } - game.savecolour = 0; + game.savecolour = cl.player_colour; game.intimetrial = false; game.timetrialcountdown = 0; From 6809aa01351679490f5aa2819c287cb8774bcf9c Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Sat, 12 Apr 2025 01:41:32 -0300 Subject: [PATCH 37/64] Attempt to fix external playtesting not respecting colour --- desktop_version/src/CustomLevels.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop_version/src/CustomLevels.cpp b/desktop_version/src/CustomLevels.cpp index 2e3f84fe..8a8e98a4 100644 --- a/desktop_version/src/CustomLevels.cpp +++ b/desktop_version/src/CustomLevels.cpp @@ -1420,6 +1420,7 @@ next: if (SDL_strcmp(pKey, "PlayerColour") == 0) { player_colour = help.Int(pText); + game.savecolour = player_colour; } } From b8bcdf39df431455598f776fa7ae37ed3abb08bd Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Sat, 12 Apr 2025 02:05:11 -0300 Subject: [PATCH 38/64] Move saving outside of MetaData (oops!) --- desktop_version/src/CustomLevels.cpp | 29 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/desktop_version/src/CustomLevels.cpp b/desktop_version/src/CustomLevels.cpp index 8a8e98a4..58365528 100644 --- a/desktop_version/src/CustomLevels.cpp +++ b/desktop_version/src/CustomLevels.cpp @@ -1566,20 +1566,6 @@ bool customlevelclass::save(const std::string& _path) } } - if (player_colour != 0) - { - xml::update_tag(msg, "PlayerColour", player_colour); - } - else - { - // Get rid of this one as well, since older levels don't have this property anyways - tinyxml2::XMLElement* element; - while ((element = msg->FirstChildElement("PlayerColour")) != NULL) - { - doc.DeleteNode(element); - } - } - xml::update_tag(data, "mapwidth", mapwidth); xml::update_tag(data, "mapheight", mapheight); @@ -1699,6 +1685,21 @@ bool customlevelclass::save(const std::string& _path) } xml::update_tag(data, "script", scriptString.c_str()); + + if (player_colour != 0) + { + xml::update_tag(data, "PlayerColour", player_colour); + } + else + { + // Get rid of this one as well, since older levels don't have this property anyways + tinyxml2::XMLElement* element; + while ((element = data->FirstChildElement("PlayerColour")) != NULL) + { + doc.DeleteNode(element); + } + } + return FILESYSTEM_saveTiXml2Document(newpath.c_str(), doc); } From 0e9c4f98a65e273ebbd469a14b56c6d66590002d Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Fri, 4 Apr 2025 16:57:50 -0300 Subject: [PATCH 39/64] Replace colour IDs with an enum Entity colors are just integers. Their colour ID gets passed through a big switch, returning different RGB values depending on the colour ID (and can also get affected by randomness or other game state.) But because of this, there's a bunch of random numbers floating around, with no actual description on what they are other than comments which, while most of the time are accurate, only exist in the switch. To fix this, this commit adds a new enum which labels every colour. While we can't use it as a type (as we need to allow colours outside of what are defined, in case people want a "pure white", and scripting can set any colour ID they want), colours have to stay as `int`. --- desktop_version/src/Ent.cpp | 102 +++++++++--------- desktop_version/src/Ent.h | 3 +- desktop_version/src/Entity.cpp | 163 ++++++++++++++--------------- desktop_version/src/Entity.h | 20 +--- desktop_version/src/Game.cpp | 54 +++++----- desktop_version/src/Graphics.cpp | 14 +-- desktop_version/src/Graphics.h | 48 +++++++++ desktop_version/src/Input.cpp | 16 +-- desktop_version/src/Map.cpp | 18 ++-- desktop_version/src/Otherlevel.cpp | 3 +- desktop_version/src/Script.cpp | 99 +++++++++--------- 11 files changed, 286 insertions(+), 254 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index 1a6a206c..f78da9da 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -18,7 +18,7 @@ void entclass::clear(void) state = 0; statedelay = 0; life = 0; - colour = 0; + colour = EntityColour_CREW_CYAN; para = 0; behave = 0; animate = 0; @@ -108,7 +108,7 @@ void entclass::setenemy( int t ) case 0: tile = 60; animate = 2; - colour = 6; + colour = EntityColour_ENEMY_RED; behave = 10; w = 32; h = 32; @@ -119,7 +119,7 @@ void entclass::setenemy( int t ) lerpoldyp += 10; tile = 63; animate = 100; //LIES - colour = 6; + colour = EntityColour_ENEMY_RED; behave = 11; para = 9; //destroyed when outside x1 = -200; @@ -132,7 +132,7 @@ void entclass::setenemy( int t ) case 2: tile = 62; animate = 100; - colour = 6; + colour = EntityColour_ENEMY_RED; behave = -1; w = 32; h = 32; @@ -147,7 +147,7 @@ void entclass::setenemy( int t ) tile = 72; animate = 3; size = 9; - colour = 6; + colour = EntityColour_ENEMY_RED; behave = 12; w = 64; h = 40; @@ -161,7 +161,7 @@ void entclass::setenemy( int t ) lerpoldyp -= 4; tile = 76; animate = 100; // Clouds - colour = 6; + colour = EntityColour_ENEMY_RED; behave = 13; para = -6; //destroyed when outside x2 = 400; @@ -173,7 +173,7 @@ void entclass::setenemy( int t ) case 2: tile = 77; animate = 100; - colour = 6; + colour = EntityColour_ENEMY_RED; behave = -1; w = 32; h = 16; @@ -195,32 +195,32 @@ void entclass::setenemyroom( int rx, int ry ) //Space Station 1 case rn(12, 3): //Security Drone tile = 36; - colour = 8; + colour = EntityColour_ENEMY_PINK; animate = 1; break; case rn(13, 3): //Wavelengths tile = 32; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 1; w = 32; break; case rn(15, 3): //Traffic tile = 28; - colour = 6; + colour = EntityColour_ENEMY_RED; animate = 1; w = 22; h = 32; break; case rn(12, 5): //The Yes Men tile = 40; - colour = 9; + colour = EntityColour_ENEMY_YELLOW; animate = 1; w = 20; h = 20; break; case rn(13, 6): //Hunchbacked Guards tile = 44; - colour = 8; + colour = EntityColour_ENEMY_PINK; animate = 1; w = 16; h = 20; @@ -231,7 +231,7 @@ void entclass::setenemyroom( int rx, int ry ) { //transmittor tile = 104; - colour = 4; + colour = EntityColour_INACTIVE_ENTITY; animate = 7; w = 16; h = 16; @@ -244,7 +244,7 @@ void entclass::setenemyroom( int rx, int ry ) { //radar dish tile =124; - colour = 4; + colour = EntityColour_INACTIVE_ENTITY; animate = 6; w = 32; h = 32; @@ -260,37 +260,37 @@ void entclass::setenemyroom( int rx, int ry ) //The Lab case rn(4, 0): tile = 78; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 1; w = 16; h = 16; break; case rn(2, 0): tile = 88; - colour = 11; + colour = EntityColour_ENEMY_CYAN; animate = 1; w = 16; h = 16; break; //Space Station 2 case rn(14, 11): - colour = 17; + colour = EntityColour_ENEMY_ORANGE; break; //Lies case rn(16, 11): - colour = 8; + colour = EntityColour_ENEMY_PINK; break; //Lies case rn(13, 10): - colour = 11; + colour = EntityColour_ENEMY_CYAN; break; //Factory case rn(13, 9): - colour = 9; + colour = EntityColour_ENEMY_YELLOW; break; //Factory case rn(13, 8): - colour = 8; + colour = EntityColour_ENEMY_PINK; break; //Factory case rn(11, 13): //Truth tile = 64; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 100; w = 44; h = 10; @@ -298,7 +298,7 @@ void entclass::setenemyroom( int rx, int ry ) break; case rn(17, 7): //Brass sent us under the top tile =82; - colour = 8; + colour = EntityColour_ENEMY_PINK; animate = 5; w = 28; h = 32; @@ -306,42 +306,42 @@ void entclass::setenemyroom( int rx, int ry ) break; case rn(10, 7): // (deception) tile = 92; - colour = 6; + colour = EntityColour_ENEMY_RED; animate = 1; w = 16; h = 16; break; case rn(14, 13): // (chose poorly) tile = 56; - colour = 6; + colour = EntityColour_ENEMY_RED; animate = 1; w = 15; h = 24; break; case rn(13, 12): // (backsliders) tile = 164; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 1; w = 16; h = 16; break; case rn(14, 8): // (wheel of fortune room) tile = 116; - colour = 12; + colour = EntityColour_ENEMY_BLUE; animate = 1; w = 32; h = 32; break; case rn(16, 9): // (seeing dollar signs) tile = 68; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 1; w = 16; h = 16; break; case rn(16, 7): // (tomb of mad carew) tile = 106; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 2; w = 24; h = 25; @@ -349,7 +349,7 @@ void entclass::setenemyroom( int rx, int ry ) //Warp Zone case rn(15, 2): // (numbers) tile = 100; - colour = 6; + colour = EntityColour_ENEMY_RED; animate = 1; w = 32; h = 14; @@ -358,7 +358,7 @@ void entclass::setenemyroom( int rx, int ry ) break; case rn(16, 2): // (Manequins) tile = 52; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 5; w = 16; h = 25; @@ -367,28 +367,28 @@ void entclass::setenemyroom( int rx, int ry ) break; case rn(18, 0): // (Obey) tile = 51; - colour = 11; + colour = EntityColour_ENEMY_CYAN; animate = 100; w = 30; h = 14; break; case rn(19, 1): // Ascending and Descending tile = 48; - colour = 9; + colour = EntityColour_ENEMY_YELLOW; animate = 5; w = 16; h = 16; break; case rn(19, 2): // Shockwave Rider tile = 176; - colour = 6; + colour = EntityColour_ENEMY_RED; animate = 1; w = 16; h = 16; break; case rn(18, 3): // Mind the gap tile = 168; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 1; w = 16; h = 16; @@ -397,7 +397,7 @@ void entclass::setenemyroom( int rx, int ry ) if (yp ==96) { tile = 160; - colour = 8; + colour = EntityColour_ENEMY_PINK; animate = 1; w = 16; h = 16; @@ -405,7 +405,7 @@ void entclass::setenemyroom( int rx, int ry ) else { tile = 156; - colour = 8; + colour = EntityColour_ENEMY_PINK; animate = 1; w = 16; h = 16; @@ -413,14 +413,14 @@ void entclass::setenemyroom( int rx, int ry ) break; case rn(16, 0): // I love you tile = 112; - colour = 8; + colour = EntityColour_ENEMY_PINK; animate = 5; w = 16; h = 16; break; case rn(14, 2): // That's why I have to kill you tile = 114; - colour = 6; + colour = EntityColour_ENEMY_RED; animate = 5; w = 16; h = 16; @@ -430,7 +430,7 @@ void entclass::setenemyroom( int rx, int ry ) if (xp ==88) { tile = 54+12; - colour = 12; + colour = EntityColour_ENEMY_BLUE; animate = 100; w = 60; h = 16; @@ -439,7 +439,7 @@ void entclass::setenemyroom( int rx, int ry ) else { tile = 54; - colour = 12; + colour = EntityColour_ENEMY_BLUE; animate = 100; w = 60; h = 16; @@ -449,62 +449,62 @@ void entclass::setenemyroom( int rx, int ry ) //Final level case rn(50-100, 53-100): //The Yes Men tile = 40; - colour = 9; + colour = EntityColour_ENEMY_YELLOW; animate = 1; w = 20; h = 20; break; case rn(48-100, 51-100): //Wavelengths tile = 32; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 1; w = 32; break; case rn(43-100,52-100): // Ascending and Descending tile = 48; - colour = 9; + colour = EntityColour_ENEMY_YELLOW; animate = 5; w = 16; h = 16; break; case rn(46-100,51-100): //kids his age tile = 88; - colour = 11; + colour = EntityColour_ENEMY_CYAN; animate = 1; w = 16; h = 16; break; case rn(43-100,51-100): // Mind the gap tile = 168; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 1; w = 16; h = 16; break; case rn(44-100,51-100): // vertigo? tile = 172; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 100; w = 32; h = 32; break; case rn(44-100,52-100): // (backsliders) tile = 164; - colour = 7; + colour = EntityColour_ENEMY_GREEN; animate = 1; w = 16; h = 16; break; case rn(43-100, 56-100): //Intermission 1 tile = 88; - colour = 21; + colour = EntityColour_ENEMY_GRAVITRON; animate = 1; w = 16; h = 16; break; case rn(45-100, 56-100): //Intermission 1 tile = 88; - colour = 21; + colour = EntityColour_ENEMY_GRAVITRON; animate = 1; w = 16; h = 16; @@ -515,7 +515,7 @@ void entclass::setenemyroom( int rx, int ry ) case rn(11, 8): case rn(12, 8): tile = 0; - colour = 102; + colour = EntityColour_TELEPORTER_FLASHING; animate = 0; w = 464; h = 320; diff --git a/desktop_version/src/Ent.h b/desktop_version/src/Ent.h index d422a519..3e375a53 100644 --- a/desktop_version/src/Ent.h +++ b/desktop_version/src/Ent.h @@ -59,7 +59,8 @@ public: int state, statedelay; int behave, animate; float para; - int life, colour; + int life; + int colour; // As out-of-bounds colours are allowed, this should be an int instead of an EnemyColour. //Position and velocity int oldxp, oldyp; diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 7fe5efec..0c20bc42 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -109,13 +109,13 @@ void entityclass::resetallflags(void) int entityclass::swncolour( int t ) { //given colour t, return colour in setcol - if (t == 0) return 11; - if (t == 1) return 6; - if (t == 2) return 8; - if (t == 3) return 12; - if (t == 4) return 9; - if (t == 5) return 7; - return 0; + if (t == 0) return EntityColour_ENEMY_CYAN; + if (t == 1) return EntityColour_ENEMY_RED; + if (t == 2) return EntityColour_ENEMY_PINK; + if (t == 3) return EntityColour_ENEMY_BLUE; + if (t == 4) return EntityColour_ENEMY_YELLOW; + if (t == 5) return EntityColour_ENEMY_GREEN; + return EntityColour_CREW_CYAN; // Fallback to color 0 } void entityclass::swnenemiescol( int t ) @@ -1324,7 +1324,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int case 0: //Player entity.rule = 0; //Playable character entity.tile = 0; - entity.colour = 0; + entity.colour = EntityColour_CREW_CYAN; entity.cx = 6; entity.cy = 2; entity.w = 12; @@ -1357,7 +1357,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.harmful = true; entity.tile = 24; entity.animate = 0; - entity.colour = 8; + entity.colour = EntityColour_ENEMY_PINK; entity.type = EntityType_MOVING; @@ -1375,7 +1375,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int { //MAVVERRRICK entity.tile = 96; - entity.colour = 6; + entity.colour = EntityColour_ENEMY_RED; entity.size = 9; entity.w = 64; entity.h = 44; @@ -1515,7 +1515,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int case 6: //Decorative particles entity.rule = 2; entity.type = EntityType_PARTICLE; //Particles - entity.colour = 27; + entity.colour = EntityColour_PARTICLE_RED; entity.size = 3; entity.vx = meta1; entity.vy = meta2; @@ -1525,7 +1525,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int case 7: //Decorative particles entity.rule = 2; entity.type = EntityType_PARTICLE; //Particles - entity.colour = 0; + entity.colour = EntityColour_CREW_CYAN; entity.size = 3; entity.vx = meta1; entity.vy = meta2; @@ -1536,7 +1536,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.rule = 3; entity.type = EntityType_COIN; entity.size = 4; - entity.colour = 26; + entity.colour = EntityColour_COIN; entity.tile = 48; entity.w = 8; entity.h = 8; @@ -1554,7 +1554,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.tile = 22; entity.w = 16; entity.h = 16; - entity.colour = 3; + entity.colour = EntityColour_TRINKET; entity.onentity = 1; entity.animate = 100; @@ -1569,14 +1569,14 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.tile = 20 + meta1; entity.w = 16; entity.h = 16; - entity.colour = 4; + entity.colour = EntityColour_INACTIVE_ENTITY; entity.onentity = 1; entity.animate = 100; entity.para = meta2; if (game.savepoint == meta2) { - entity.colour = 5; + entity.colour = EntityColour_ACTIVE_ENTITY; entity.onentity = 0; } @@ -1590,7 +1590,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.type = EntityType_HORIZONTAL_GRAVITY_LINE; entity.size = 5; entity.life = 0; - entity.colour = 25; + entity.colour = EntityColour_GRAVITY_LINE_ACTIVE; entity.w = meta1; entity.h = 1; entity.onentity = 1; @@ -1600,10 +1600,10 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.type = EntityType_VERTICAL_GRAVITY_LINE; entity.size = 6; entity.life = 0; - entity.colour = 25; + entity.colour = EntityColour_GRAVITY_LINE_ACTIVE; entity.w = 1; entity.h = meta1; - //entity.colour = 0; + //entity.colour = EntityColour_CREW_CYAN; entity.onentity = 1; break; case 13: //Warp token @@ -1613,7 +1613,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.tile = 18; entity.w = 16; entity.h = 16; - entity.colour = 10; + entity.colour = EntityColour_WARP_TOKEN; entity.onentity = 1; entity.animate = 2; //Added in port, hope it doesn't break anything @@ -1627,7 +1627,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.tile = 1; //inactive entity.w = 96; entity.h = 96; - entity.colour = 100; + entity.colour = EntityColour_TELEPORTER_INACTIVE; entity.onentity = 1; entity.animate = 100; entity.para = meta2; @@ -1636,7 +1636,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.rule = 6; entity.type = EntityType_CREWMATE; //A special case! entity.tile = 144; - entity.colour = 13; //144 for sad :( + entity.colour = EntityColour_CREW_GREEN; //144 for sad :( entity.cx = 6; entity.cy = 2; entity.w = 12; @@ -1651,7 +1651,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.rule = 7; entity.type = EntityType_CREWMATE; //A special case! entity.tile = 144+6; - entity.colour = 14; //144 for sad (upside down+12):( + entity.colour = EntityColour_CREW_YELLOW; //144 for sad (upside down+12):( entity.cx = 6; entity.cy = 2; entity.w = 12; @@ -1666,7 +1666,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.rule = 6; entity.type = EntityType_CREWMATE; //A special case! entity.tile = 144; - entity.colour = 16; //144 for sad :( + entity.colour = EntityColour_CREW_BLUE; //144 for sad :( entity.cx = 6; entity.cy = 2; entity.w = 12; @@ -1710,7 +1710,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.rule = 6; entity.type = EntityType_CREWMATE; //A special case! entity.tile = 0; - entity.colour = 6; //54 for sad :( + entity.colour = EntityColour_ENEMY_RED; //54 for sad :( entity.cx = 6; entity.cy = 2; entity.w = 12; @@ -1728,7 +1728,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.tile = 16 + meta1; entity.w = 16; entity.h = 16; - entity.colour = 4; + entity.colour = EntityColour_INACTIVE_ENTITY; entity.onentity = 1; entity.animate = 100; entity.para = meta2; @@ -1740,7 +1740,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.tile = 16 + meta1; entity.w = 16; entity.h = 16; - entity.colour = 4; + entity.colour = EntityColour_INACTIVE_ENTITY; entity.onentity = 0; entity.animate = 100; entity.para = meta2; @@ -1752,7 +1752,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.tile = 22; entity.w = 16; entity.h = 16; - entity.colour = 3; + entity.colour = EntityColour_TRINKET; entity.onentity = 0; entity.animate = 100; @@ -1780,7 +1780,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int //initilise tiles here based on behavior entity.size = 12; //don't wrap around - entity.colour = 21; + entity.colour = EntityColour_ENEMY_GRAVITRON; entity.tile = 78; //default case entity.animate = 1; if (game.swngame == SWN_SUPERGRAVITRON) @@ -1838,7 +1838,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.size = 0; entity.w = 16; entity.h = 16; - entity.colour = 4; + entity.colour = EntityColour_INACTIVE_ENTITY; entity.onentity = 1; entity.animate = 100; entity.para = meta2; @@ -1852,42 +1852,42 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if (game.bestrank[TimeTrial_SPACESTATION1] >= 3) { entity.tile = 184 + meta1; - entity.colour = 31; + entity.colour = EntityColour_TROPHY_SPACE_STATION_1; } break; case 2: if (game.bestrank[TimeTrial_LABORATORY] >= 3) { entity.tile = 186 + meta1; - entity.colour = 35; + entity.colour = EntityColour_TROPHY_LABORATORY; } break; case 3: if (game.bestrank[TimeTrial_TOWER] >= 3) { entity.tile = 184 + meta1; - entity.colour = 33; + entity.colour = EntityColour_TROPHY_TOWER; } break; case 4: if (game.bestrank[TimeTrial_SPACESTATION2] >= 3) { entity.tile = 184 + meta1; - entity.colour = 32; + entity.colour = EntityColour_TROPHY_SPACE_STATION_2; } break; case 5: if (game.bestrank[TimeTrial_WARPZONE] >= 3) { entity.tile = 184 + meta1; - entity.colour = 34; + entity.colour = EntityColour_TROPHY_WARP_ZONE; } break; case 6: if (game.bestrank[TimeTrial_FINALLEVEL] >= 3) { entity.tile = 184 + meta1; - entity.colour = 30; + entity.colour = EntityColour_TROPHY_FINAL_LEVEL; } break; @@ -1895,7 +1895,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if (game.unlock[UnlockTrophy_GAME_COMPLETE]) { entity.tile = 188 + meta1; - entity.colour = 37; + entity.colour = EntityColour_TROPHY_GAME_COMPLETE; entity.h += 3; entity.yp -= 3; } @@ -1904,7 +1904,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if (game.unlock[UnlockTrophy_FLIPMODE_COMPLETE]) { entity.tile = 188 + meta1; - entity.colour = 37; + entity.colour = EntityColour_TROPHY_GAME_COMPLETE; entity.h += 3; } break; @@ -1915,7 +1915,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if (game.bestgamedeaths <= 50) { entity.tile = 182 + meta1; - entity.colour = 40; + entity.colour = EntityColour_TROPHY_FLASHY; } } break; @@ -1925,7 +1925,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if (game.bestgamedeaths <= 100) { entity.tile = 182 + meta1; - entity.colour = 36; + entity.colour = EntityColour_TROPHY_GOLD; } } break; @@ -1935,7 +1935,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if (game.bestgamedeaths <= 250) { entity.tile = 182 + meta1; - entity.colour = 38; + entity.colour = EntityColour_TROPHY_SILVER; } } break; @@ -1945,7 +1945,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if (game.bestgamedeaths <= 500) { entity.tile = 182 + meta1; - entity.colour = 39; + entity.colour = EntityColour_TROPHY_BRONZE; } } break; @@ -1954,42 +1954,42 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if(game.swnbestrank>=1) { entity.tile = 182 + meta1; - entity.colour = 39; + entity.colour = EntityColour_TROPHY_BRONZE; } break; case 14: if(game.swnbestrank>=2) { entity.tile = 182 + meta1; - entity.colour = 39; + entity.colour = EntityColour_TROPHY_BRONZE; } break; case 15: if(game.swnbestrank>=3) { entity.tile = 182 + meta1; - entity.colour = 39; + entity.colour = EntityColour_TROPHY_BRONZE; } break; case 16: if(game.swnbestrank>=4) { entity.tile = 182 + meta1; - entity.colour = 38; + entity.colour = EntityColour_TROPHY_SILVER; } break; case 17: if(game.swnbestrank>=5) { entity.tile = 182 + meta1; - entity.colour = 36; + entity.colour = EntityColour_TROPHY_GOLD; } break; case 18: if(game.swnbestrank>=6) { entity.tile = 182 + meta1; - entity.colour = 40; + entity.colour = EntityColour_TROPHY_FLASHY; } break; @@ -1997,7 +1997,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int if (game.unlock[UnlockTrophy_NODEATHMODE_COMPLETE]) { entity.tile = 3; - entity.colour = 102; + entity.colour = EntityColour_TELEPORTER_FLASHING; entity.size = 13; entity.xp -= 64; entity.yp -= 128; @@ -2014,7 +2014,7 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int entity.tile = 18; entity.w = 16; entity.h = 16; - entity.colour = 3; + entity.colour = EntityColour_TRINKET; entity.onentity = 0; entity.animate = 100; entity.para = meta2; @@ -2137,41 +2137,41 @@ void entityclass::createentity(int xp, int yp, int t, int meta1, int meta2, int //RED case 3: case 7: case 12: case 23: case 28: case 34: case 42: case 48: case 58: - entity.colour = 6; break; + entity.colour = EntityColour_ENEMY_RED; break; //GREEN case 5: case 9: case 22: case 25: case 29: case 31: case 38: case 46: case 52: case 53: - entity.colour = 7; break; + entity.colour = EntityColour_ENEMY_GREEN; break; //BLUE case 1: case 6: case 14: case 27: case 33: case 44: case 50: case 57: - entity.colour = 12; break; + entity.colour = EntityColour_ENEMY_BLUE; break; //YELLOW case 4: case 17: case 24: case 30: case 37: case 45: case 51: case 55: - entity.colour = 9; break; + entity.colour = EntityColour_ENEMY_YELLOW; break; //PURPLE case 2: case 11: case 15: case 19: case 32: case 36: case 49: - entity.colour = 20; break; + entity.colour = EntityColour_CREW_PURPLE; break; //CYAN case 8: case 10: case 13: case 18: case 26: case 35: case 41: case 47: case 54: - entity.colour = 11; break; + entity.colour = EntityColour_ENEMY_CYAN; break; //PINK case 16: case 20: case 39: case 43: case 56: - entity.colour = 8; break; + entity.colour = EntityColour_ENEMY_PINK; break; //ORANGE case 21: case 40: - entity.colour = 17; break; + entity.colour = EntityColour_ENEMY_ORANGE; break; default: - entity.colour = 6; + entity.colour = EntityColour_ENEMY_RED; break; } } if(custom_gray){ - entity.colour = 18; + entity.colour = EntityColour_ENEMY_GRAY; } entityclonefix(&entity); @@ -2744,11 +2744,11 @@ bool entityclass::updateentities( int i ) { if (entities[j].type == EntityType_CHECKPOINT) { - entities[j].colour = 4; + entities[j].colour = EntityColour_INACTIVE_ENTITY; entities[j].onentity = 1; } } - entities[i].colour = 5; + entities[i].colour = EntityColour_ACTIVE_ENTITY; entities[i].onentity = 0; game.savepoint = entities[i].para; music.playef(Sound_CHECKPOINT); @@ -2936,7 +2936,7 @@ bool entityclass::updateentities( int i ) else if (entities[i].state == 11) { //11-15 means to follow a specific character, in crew order (cyan, purple, yellow, red, green, blue) - int j=getcrewman(PURPLE); + int j=getcrewman(EntityColour_CREW_PURPLE); if (INBOUNDS_VEC(j, entities)) { if (entities[j].xp > entities[i].xp + 5) @@ -2961,7 +2961,7 @@ bool entityclass::updateentities( int i ) else if (entities[i].state == 12) { //11-15 means to follow a specific character, in crew order (cyan, purple, yellow, red, green, blue) - int j=getcrewman(YELLOW); + int j=getcrewman(EntityColour_CREW_YELLOW); if (INBOUNDS_VEC(j, entities)) { if (entities[j].xp > entities[i].xp + 5) @@ -2986,7 +2986,7 @@ bool entityclass::updateentities( int i ) else if (entities[i].state == 13) { //11-15 means to follow a specific character, in crew order (cyan, purple, yellow, red, green, blue) - int j=getcrewman(RED); + int j=getcrewman(EntityColour_CREW_RED); if (INBOUNDS_VEC(j, entities)) { if (entities[j].xp > entities[i].xp + 5) @@ -3011,7 +3011,7 @@ bool entityclass::updateentities( int i ) else if (entities[i].state == 14) { //11-15 means to follow a specific character, in crew order (cyan, purple, yellow, red, green, blue) - int j=getcrewman(GREEN); + int j=getcrewman(EntityColour_CREW_GREEN); if (INBOUNDS_VEC(j, entities)) { if (entities[j].xp > entities[i].xp + 5) @@ -3036,7 +3036,7 @@ bool entityclass::updateentities( int i ) else if (entities[i].state == 15) { //11-15 means to follow a specific character, in crew order (cyan, purple, yellow, red, green, blue) - int j=getcrewman(BLUE); + int j=getcrewman(EntityColour_CREW_BLUE); if (INBOUNDS_VEC(j, entities)) { if (entities[j].xp > entities[i].xp + 5) @@ -3190,7 +3190,7 @@ bool entityclass::updateentities( int i ) //wait for collision if (entities[i].state == 1) { - entities[i].colour = 5; + entities[i].colour = EntityColour_ACTIVE_ENTITY; entities[i].onentity = 0; music.playef(Sound_TERMINALTOUCH); @@ -3390,7 +3390,7 @@ bool entityclass::updateentities( int i ) { music.playef(Sound_GAMESAVED); entities[i].tile = 2; - entities[i].colour = 101; + entities[i].colour = EntityColour_TELEPORTER_ACTIVE; if(!game.intimetrial && !game.nodeathmode) { game.setstate(2000); @@ -3410,7 +3410,7 @@ bool entityclass::updateentities( int i ) { if (entities[j].type == EntityType_CHECKPOINT) { - entities[j].colour = 4; + entities[j].colour = EntityColour_INACTIVE_ENTITY; entities[j].onentity = 1; } } @@ -3436,7 +3436,7 @@ bool entityclass::updateentities( int i ) //Initilise the teleporter without changing the game state or playing sound entities[i].onentity = 0; entities[i].tile = 6; - entities[i].colour = 102; + entities[i].colour = EntityColour_TELEPORTER_FLASHING; game.activetele = true; game.teleblock.x = entities[i].xp - 32; @@ -3994,34 +3994,29 @@ int entityclass::getlineat( int t ) return 0; } -int entityclass::getcrewman( int t, int fallback /*= 0*/ ) +int entityclass::getcrewman(int t) { - //Returns the index of the crewman with colour index given by t + // Returns the index of the crewman with colour index given by t. + // Note: this takes an int, not an EntityColour, as invalid colours are allowed in scripting for (size_t i = 0; i < entities.size(); i++) { if ((entities[i].type == EntityType_CREWMATE || entities[i].type == EntityType_SUPERCREWMATE) - && (entities[i].rule == 6 || entities[i].rule == 7)) + && (entities[i].rule == 6 || entities[i].rule == 7)) { - if(entities[i].colour==t) + if (entities[i].colour == t) { return i; } } } - return fallback; + return -1; } -int entityclass::getcustomcrewman( int t ) +int entityclass::getcustomcrewman(int t) { - //Returns the index of the crewman with colour index given by t - if (t == 0) t = 0; - if (t == 1) t = 20; - if (t == 2) t = 14; - if (t == 3) t = 15; - if (t == 4) t = 13; - if (t == 5) t = 16; + // like getcrewman, this returns the index of the CUSTOM crewman with colour index given by t for (size_t i = 0; i < entities.size(); i++) { diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index 796918b3..25197a5e 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -5,10 +5,10 @@ #include #include -#include "Maths.h" -#include "Ent.h" #include "BlockV.h" +#include "Ent.h" #include "Game.h" +#include "Maths.h" enum { @@ -20,18 +20,6 @@ enum ACTIVITY = 5 }; -enum -{ - CYAN = 0, - PURPLE = 20, - YELLOW = 14, - RED = 15, - GREEN = 13, - BLUE = 16, - GRAY = 19, - TELEPORTER = 102 -}; - class entityclass { public: @@ -56,7 +44,7 @@ public: createblock(DAMAGE, 312, -8, 16, 260); } - int swncolour(int t ); + int swncolour(int t); void swnenemiescol(int t); @@ -106,7 +94,7 @@ public: int getlineat(int t); - int getcrewman(int t, int fallback = 0); + int getcrewman(int t); int getcustomcrewman(int t); int getteleporter(void); diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 201007c2..d5b734f7 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -146,7 +146,7 @@ void Game::init(void) prevroomy = 0; saverx = 0; savery = 0; - savecolour = 0; + savecolour = EntityColour_CREW_CYAN; mutebutton = 0; muted = false; @@ -2563,7 +2563,7 @@ void Game::updatestate(void) int i = obj.getplayer(); if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = false; int j = obj.getteleporter(); @@ -2584,7 +2584,7 @@ void Game::updatestate(void) if (INBOUNDS_VEC(i, obj.entities)) { obj.entities[i].tile = 1; - obj.entities[i].colour = 101; + obj.entities[i].colour = EntityColour_TELEPORTER_ACTIVE; } break; } @@ -2757,7 +2757,7 @@ void Game::updatestate(void) int i = obj.getplayer(); if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = true; } @@ -2771,7 +2771,7 @@ void Game::updatestate(void) if (INBOUNDS_VEC(i, obj.entities)) { obj.entities[i].tile = 1; - obj.entities[i].colour = 100; + obj.entities[i].colour = EntityColour_TELEPORTER_INACTIVE; } break; } @@ -3365,7 +3365,7 @@ void Game::updatestate(void) int i = obj.getplayer(); if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 102; + obj.entities[i].colour = EntityColour_TELEPORTER_FLASHING; } incstate(); @@ -3407,7 +3407,7 @@ void Game::updatestate(void) int i = obj.getplayer(); if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = true; } @@ -3492,7 +3492,7 @@ void Game::updatestate(void) int i = obj.getplayer(); if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = true; } @@ -3500,7 +3500,7 @@ void Game::updatestate(void) if(INBOUNDS_VEC(i, obj.entities)) { obj.entities[i].tile = 1; - obj.entities[i].colour = 100; + obj.entities[i].colour = EntityColour_TELEPORTER_INACTIVE; } break; } @@ -3544,9 +3544,9 @@ void Game::updatestate(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; - obj.entities[j].colour = 101; + obj.entities[j].colour = EntityColour_TELEPORTER_ACTIVE; } - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = false; obj.entities[i].dir = 1; @@ -3675,9 +3675,9 @@ void Game::updatestate(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; - obj.entities[j].colour = 101; + obj.entities[j].colour = EntityColour_TELEPORTER_ACTIVE; } - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = false; obj.entities[i].dir = 1; @@ -3788,9 +3788,9 @@ void Game::updatestate(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; - obj.entities[j].colour = 101; + obj.entities[j].colour = EntityColour_TELEPORTER_ACTIVE; } - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = false; obj.entities[i].dir = 0; @@ -3901,9 +3901,9 @@ void Game::updatestate(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; - obj.entities[j].colour = 101; + obj.entities[j].colour = EntityColour_TELEPORTER_ACTIVE; } - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = false; obj.entities[i].dir = 1; @@ -4019,9 +4019,9 @@ void Game::updatestate(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; - obj.entities[j].colour = 101; + obj.entities[j].colour = EntityColour_TELEPORTER_ACTIVE; } - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = false; obj.entities[i].dir = 1; @@ -4137,9 +4137,9 @@ void Game::updatestate(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; - obj.entities[j].colour = 101; + obj.entities[j].colour = EntityColour_TELEPORTER_ACTIVE; } - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = false; obj.entities[i].dir = 0; @@ -4253,7 +4253,7 @@ void Game::updatestate(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; - obj.entities[j].colour = 101; + obj.entities[j].colour = EntityColour_TELEPORTER_ACTIVE; } obj.entities[i].invis = false; obj.entities[i].dir = 1; @@ -4366,9 +4366,9 @@ void Game::updatestate(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; - obj.entities[j].colour = 101; + obj.entities[j].colour = EntityColour_TELEPORTER_ACTIVE; } - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = false; obj.entities[i].dir = 1; @@ -4479,9 +4479,9 @@ void Game::updatestate(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; - obj.entities[j].colour = 101; + obj.entities[j].colour = EntityColour_TELEPORTER_ACTIVE; } - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].invis = false; obj.entities[i].dir = 1; @@ -5363,7 +5363,7 @@ void Game::deathsequence(void) } if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 1; + obj.entities[i].colour = EntityColour_DEAD; obj.entities[i].invis = false; } diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index c37a5586..72b50c01 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -3423,19 +3423,19 @@ int Graphics::crewcolour(const int t) switch (t) { case 0: - return CYAN; + return EntityColour_CREW_CYAN; case 1: - return PURPLE; + return EntityColour_CREW_PURPLE; case 2: - return YELLOW; + return EntityColour_CREW_YELLOW; case 3: - return RED; + return EntityColour_CREW_RED; case 4: - return GREEN; + return EntityColour_CREW_GREEN; case 5: - return BLUE; + return EntityColour_CREW_BLUE; default: - return 0; + return EntityColour_CREW_CYAN; } } diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index e04ddf6d..b9c9a53f 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -40,6 +40,54 @@ enum ImageNames #define FADEMODE_IS_FADING(mode) ((mode) != FADE_NONE && (mode) != FADE_FULLY_BLACK) +enum EntityColour +{ + EntityColour_CREW_CYAN = 0, + EntityColour_DEAD = 1, + EntityColour_ENEMY_DARK_ORANGE = 2, + EntityColour_TRINKET = 3, + EntityColour_INACTIVE_ENTITY = 4, + EntityColour_ACTIVE_ENTITY = 5, + EntityColour_ENEMY_RED = 6, + EntityColour_ENEMY_GREEN = 7, + EntityColour_ENEMY_PINK = 8, + EntityColour_ENEMY_YELLOW = 9, + EntityColour_WARP_TOKEN = 10, + EntityColour_ENEMY_CYAN = 11, + EntityColour_ENEMY_BLUE = 12, + EntityColour_CREW_GREEN = 13, + EntityColour_CREW_YELLOW = 14, + EntityColour_CREW_RED = 15, + EntityColour_CREW_BLUE = 16, + EntityColour_ENEMY_ORANGE = 17, + EntityColour_ENEMY_GRAY = 18, + + EntityColour_CREW_GRAY = 19, // Despite the comment in the color code saying this is for enemies, it's used as a fallback for crew colors. + + EntityColour_CREW_PURPLE = 20, + EntityColour_ENEMY_GRAVITRON = 21, + EntityColour_ENEMY_LIGHT_GRAY = 22, + EntityColour_GRAVITRON_INDICATOR = 23, + EntityColour_GRAVITY_LINE_TOUCHED = 24, + EntityColour_GRAVITY_LINE_ACTIVE = 25, + EntityColour_COIN = 26, + EntityColour_PARTICLE_RED = 27, + EntityColour_TROPHY_FINAL_LEVEL = 30, + EntityColour_TROPHY_SPACE_STATION_1 = 31, + EntityColour_TROPHY_SPACE_STATION_2 = 32, + EntityColour_TROPHY_TOWER = 33, + EntityColour_TROPHY_WARP_ZONE = 34, + EntityColour_TROPHY_LABORATORY = 35, + EntityColour_TROPHY_GOLD = 36, + EntityColour_TROPHY_GAME_COMPLETE = 37, + EntityColour_TROPHY_SILVER = 38, + EntityColour_TROPHY_BRONZE = 39, + EntityColour_TROPHY_FLASHY = 40, + EntityColour_TELEPORTER_INACTIVE = 100, + EntityColour_TELEPORTER_ACTIVE = 101, + EntityColour_TELEPORTER_FLASHING = 102 +}; + class Graphics { public: diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index 1599dc4a..ef298851 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -2737,14 +2737,14 @@ void gameinput(void) int player = obj.getplayer(); if (INBOUNDS_VEC(player, obj.entities)) { - obj.entities[player].colour = 102; + obj.entities[player].colour = EntityColour_TELEPORTER_FLASHING; } int teleporter = obj.getteleporter(); if (INBOUNDS_VEC(teleporter, obj.entities)) { obj.entities[teleporter].tile = 6; - obj.entities[teleporter].colour = 102; + obj.entities[teleporter].colour = EntityColour_TELEPORTER_FLASHING; } //which teleporter script do we use? it depends on the companion! game.setstate(4000); @@ -2768,16 +2768,16 @@ void gameinput(void) int player = obj.getplayer(); if (INBOUNDS_VEC(player, obj.entities)) { - obj.entities[player].colour = 102; + obj.entities[player].colour = EntityColour_TELEPORTER_FLASHING; } int companion = obj.getcompanion(); - if(INBOUNDS_VEC(companion, obj.entities)) obj.entities[companion].colour = 102; + if(INBOUNDS_VEC(companion, obj.entities)) obj.entities[companion].colour = EntityColour_TELEPORTER_FLASHING; int teleporter = obj.getteleporter(); if (INBOUNDS_VEC(teleporter, obj.entities)) { obj.entities[teleporter].tile = 6; - obj.entities[teleporter].colour = 102; + obj.entities[teleporter].colour = EntityColour_TELEPORTER_FLASHING; } //which teleporter script do we use? it depends on the companion! game.setstate(3000); @@ -3241,7 +3241,7 @@ static void mapmenuactionpress(const bool version2_2) int i = obj.getplayer(); if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 102; + obj.entities[i].colour = EntityColour_TELEPORTER_FLASHING; } //which teleporter script do we use? it depends on the companion! @@ -3463,14 +3463,14 @@ void teleporterinput(void) int i = obj.getplayer(); if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 102; + obj.entities[i].colour = EntityColour_TELEPORTER_FLASHING; } i = obj.getteleporter(); if (INBOUNDS_VEC(i, obj.entities)) { obj.entities[i].tile = 6; - obj.entities[i].colour = 102; + obj.entities[i].colour = EntityColour_TELEPORTER_FLASHING; } //which teleporter script do we use? it depends on the companion! game.setstate(4000); diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index c06d21a6..e60d6200 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -486,28 +486,28 @@ int mapclass::maptiletoenemycol(int t) switch(t) { case 0: - return 11; + return EntityColour_ENEMY_CYAN; break; case 1: - return 6; + return EntityColour_ENEMY_RED; break; case 2: - return 8; + return EntityColour_ENEMY_PINK; break; case 3: - return 12; + return EntityColour_ENEMY_BLUE; break; case 4: - return 9; + return EntityColour_ENEMY_YELLOW; break; case 5: - return 7; + return EntityColour_ENEMY_GREEN; break; case 6: - return 18; + return EntityColour_ENEMY_GRAY; break; } - return 11; + return EntityColour_ENEMY_CYAN; } void mapclass::changefinalcol(int t) @@ -2185,7 +2185,7 @@ void mapclass::loadlevel(int rx, int ry) { //A slight varation - she's upside down obj.createentity(249, 62, 18, 16, 0, 18); - int j = obj.getcrewman(BLUE); + int j = obj.getcrewman(EntityColour_CREW_BLUE); if (INBOUNDS_VEC(j, obj.entities)) { obj.entities[j].rule = 7; diff --git a/desktop_version/src/Otherlevel.cpp b/desktop_version/src/Otherlevel.cpp index 74c7a514..c3528cce 100644 --- a/desktop_version/src/Otherlevel.cpp +++ b/desktop_version/src/Otherlevel.cpp @@ -1,6 +1,7 @@ #include "Otherlevel.h" #include "Game.h" +#include "Graphics.h" #include "Entity.h" #include "MakeAndPlay.h" #include "UtilityClass.h" @@ -8904,7 +8905,7 @@ const short* otherlevelclass::loadlevel(int rx, int ry) //violet obj.createentity(83, 126, 18, 20, 0, 18); - int crewman = obj.getcrewman(PURPLE); + int crewman = obj.getcrewman(EntityColour_CREW_PURPLE); if (INBOUNDS_VEC(crewman, obj.entities)) { obj.entities[crewman].rule = 7; diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index b384f68c..2d5487ce 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -134,16 +134,16 @@ void scriptclass::tokenize( const std::string& t ) static int getcolorfromname(std::string name) { - if (name == "player") return CYAN; - else if (name == "cyan") return CYAN; - else if (name == "red") return RED; - else if (name == "green") return GREEN; - else if (name == "yellow") return YELLOW; - else if (name == "blue") return BLUE; - else if (name == "purple") return PURPLE; - else if (name == "customcyan") return CYAN; - else if (name == "gray") return GRAY; - else if (name == "teleporter") return TELEPORTER; + if (name == "player") return EntityColour_CREW_CYAN; + else if (name == "cyan") return EntityColour_CREW_CYAN; + else if (name == "red") return EntityColour_CREW_RED; + else if (name == "green") return EntityColour_CREW_GREEN; + else if (name == "yellow") return EntityColour_CREW_YELLOW; + else if (name == "blue") return EntityColour_CREW_BLUE; + else if (name == "purple") return EntityColour_CREW_PURPLE; + else if (name == "customcyan") return EntityColour_CREW_CYAN; + else if (name == "gray") return EntityColour_CREW_GRAY; + else if (name == "teleporter") return EntityColour_TELEPORTER_FLASHING; int color = help.Int(name.c_str(), -1); if (color < 0) return -1; // Not a number (or it's negative), so we give up @@ -158,7 +158,6 @@ static int getcrewmanfromname(std::string name) return obj.getcrewman(color); } - /* Also used in gamestate 1001. */ void foundtrinket_textbox1(textboxclass* THIS); void foundtrinket_textbox2(textboxclass* THIS); @@ -638,37 +637,37 @@ void scriptclass::run(void) //the first word is the object to position relative to if (words[1] == "player") { - i = obj.getcustomcrewman(0); + i = obj.getcustomcrewman(EntityColour_CREW_CYAN); j = obj.entities[i].dir; } else if (words[1] == "cyan") { - i = obj.getcustomcrewman(0); + i = obj.getcustomcrewman(EntityColour_CREW_CYAN); j = obj.entities[i].dir; } else if (words[1] == "purple") { - i = obj.getcustomcrewman(1); + i = obj.getcustomcrewman(EntityColour_CREW_PURPLE); j = obj.entities[i].dir; } else if (words[1] == "yellow") { - i = obj.getcustomcrewman(2); + i = obj.getcustomcrewman(EntityColour_CREW_YELLOW); j = obj.entities[i].dir; } else if (words[1] == "red") { - i = obj.getcustomcrewman(3); + i = obj.getcustomcrewman(EntityColour_CREW_RED); j = obj.entities[i].dir; } else if (words[1] == "green") { - i = obj.getcustomcrewman(4); + i = obj.getcustomcrewman(EntityColour_CREW_GREEN); j = obj.entities[i].dir; } else if (words[1] == "blue") { - i = obj.getcustomcrewman(5); + i = obj.getcustomcrewman(EntityColour_CREW_BLUE); j = obj.entities[i].dir; } else if (words[1] == "centerx") @@ -910,7 +909,7 @@ void scriptclass::run(void) obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[i].size = 13; - obj.entities[i].colour = 23; + obj.entities[i].colour = EntityColour_GRAVITRON_INDICATOR; obj.entities[i].cx = 36;// 6; obj.entities[i].cy = 12+80;// 2; obj.entities[i].h = 126-80;// 21; @@ -925,7 +924,7 @@ void scriptclass::run(void) obj.entities[i].xp = 100; obj.entities[i].lerpoldxp = obj.entities[i].xp; obj.entities[i].size = 0; - obj.entities[i].colour = 0; + obj.entities[i].colour = EntityColour_CREW_CYAN; obj.entities[i].cx = 6; obj.entities[i].cy = 2; obj.entities[i].h = 21; @@ -1022,47 +1021,47 @@ void scriptclass::run(void) { if (words[1] == "player") { - i=obj.getcustomcrewman(0); + i=obj.getcustomcrewman(EntityColour_CREW_CYAN); obj.customcrewmoods[0]=ss_toi(words[2]); } else if (words[1] == "cyan") { - i=obj.getcustomcrewman(0); + i=obj.getcustomcrewman(EntityColour_CREW_CYAN); obj.customcrewmoods[0]=ss_toi(words[2]); } else if (words[1] == "customcyan") { - i=obj.getcustomcrewman(0); + i=obj.getcustomcrewman(EntityColour_CREW_CYAN); obj.customcrewmoods[0]=ss_toi(words[2]); } else if (words[1] == "red") { - i=obj.getcustomcrewman(3); + i=obj.getcustomcrewman(EntityColour_CREW_RED); obj.customcrewmoods[3]=ss_toi(words[2]); } else if (words[1] == "green") { - i=obj.getcustomcrewman(4); + i=obj.getcustomcrewman(EntityColour_CREW_GREEN); obj.customcrewmoods[4]=ss_toi(words[2]); } else if (words[1] == "yellow") { - i=obj.getcustomcrewman(2); + i=obj.getcustomcrewman(EntityColour_CREW_YELLOW); obj.customcrewmoods[2]=ss_toi(words[2]); } else if (words[1] == "blue") { - i=obj.getcustomcrewman(5); + i=obj.getcustomcrewman(EntityColour_CREW_BLUE); obj.customcrewmoods[5]=ss_toi(words[2]); } else if (words[1] == "purple") { - i=obj.getcustomcrewman(1); + i=obj.getcustomcrewman(EntityColour_CREW_PURPLE); obj.customcrewmoods[1]=ss_toi(words[2]); } else if (words[1] == "pink") { - i=obj.getcustomcrewman(1); + i=obj.getcustomcrewman(EntityColour_CREW_PURPLE); obj.customcrewmoods[1]=ss_toi(words[2]); } @@ -1188,7 +1187,7 @@ void scriptclass::run(void) if (INBOUNDS_VEC(i, obj.entities)) { obj.entities[i].tile = 6; - obj.entities[i].colour = 102; + obj.entities[i].colour = EntityColour_TELEPORTER_FLASHING; } } else if (words[0] == "changecolour") @@ -1650,7 +1649,7 @@ void scriptclass::run(void) { if (obj.entities[j].type == EntityType_TERMINAL) { - obj.entities[j].colour = 4; + obj.entities[j].colour = EntityColour_INACTIVE_ENTITY; } } if (ss_toi(words[1]) == 1) @@ -1660,7 +1659,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 88 && obj.entities[j].yp==80) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1671,7 +1670,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 128 && obj.entities[j].yp==80) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1682,7 +1681,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 176 && obj.entities[j].yp==80) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1693,7 +1692,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 216 && obj.entities[j].yp==80) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1704,7 +1703,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 88 && obj.entities[j].yp==128) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1715,7 +1714,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 176 && obj.entities[j].yp==128) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1726,7 +1725,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 40 && obj.entities[j].yp==40) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1737,7 +1736,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 216 && obj.entities[j].yp==128) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1748,7 +1747,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 128 && obj.entities[j].yp==128) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1759,7 +1758,7 @@ void scriptclass::run(void) { if (obj.entities[j].xp == 264 && obj.entities[j].yp==40) { - obj.entities[j].colour = 5; + obj.entities[j].colour = EntityColour_ACTIVE_ENTITY; } } } @@ -1770,31 +1769,31 @@ void scriptclass::run(void) if (words[1] == "red") { i = 3; - crew_color = RED; + crew_color = EntityColour_CREW_RED; } else if (words[1] == "green") { i = 4; - crew_color = GREEN; + crew_color = EntityColour_CREW_GREEN; } else if (words[1] == "yellow") { i = 2; - crew_color = YELLOW; + crew_color = EntityColour_CREW_YELLOW; } else if (words[1] == "blue") { i = 5; - crew_color = BLUE; + crew_color = EntityColour_CREW_BLUE; } else if (words[1] == "purple") { i = 1; - crew_color = PURPLE; + crew_color = EntityColour_CREW_PURPLE; } int crewman = obj.getcrewman(crew_color); - if (INBOUNDS_VEC(crewman, obj.entities) && crew_color == GREEN) + if (INBOUNDS_VEC(crewman, obj.entities) && crew_color == EntityColour_CREW_GREEN) { obj.createblock(5, obj.entities[crewman].xp - 32, obj.entities[crewman].yp-20, 96, 60, i, "", (i == 35)); } @@ -1876,7 +1875,7 @@ void scriptclass::run(void) i = obj.getteleporter(); if (INBOUNDS_VEC(i, obj.entities)) { - obj.entities[i].colour = 101; + obj.entities[i].colour = EntityColour_TELEPORTER_ACTIVE; } } else if (words[0] == "foundtrinket") @@ -1991,9 +1990,9 @@ void scriptclass::run(void) else if (words[0] == "createlastrescued") { r = graphics.crewcolour(game.lastsaved); - if (r == 0 || r == PURPLE) + if (r == EntityColour_CREW_CYAN || r == EntityColour_CREW_PURPLE) { - r = GRAY; // Default to gray if invalid color. + r = EntityColour_CREW_GRAY; // Default to gray if invalid color. } obj.createentity(200, 153, 18, r, 0, 19, 30); From c1eaeca9f61a59bf662aff572203fdd2b1c2c697 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Mon, 28 Apr 2025 00:17:36 -0300 Subject: [PATCH 40/64] Fix "invalid" activity zones not spawning There's a problem in #1224 where it breaks spawning custom activity zones. After a bit of confusion after this was reported, I realized that I removed the fallback from `getcrewman` and changed the return value to `-1` if the entity isn't found, to avoid returning the wrong entity (entity 0, aka probably the player). Unfortunately, it seems like a ton of levels (including my older ones) rely on this behavior. Creating custom activity zones is a long process which uses a bunch of unintended behaviour, which includes targeting a crewmate with color 35. With the change I mentioned earlier, the `getcrewman` function would return `-1` instead, which was out of bounds of the entity array, so the game avoided spawning the activity zone at all. The prior behaviour of falling back to entity 0 (most likely the player) would spawn the activity zone around the player instead. Nowadays, I try to spawn a crewmate with color 35 anyways so I can control where the box spawns (instead of on the player always), however most people don't (and haven't) so reverting this change seems best for now. If we wanted to reintroduce the `-1` fallback in the future, things that call `getcrewman` would have to check for `-1` and use `0` instead, but that would require a lot more testing and studying where it's used, and I'd rather squash this bug quickly and worry about cleanliness later. --- desktop_version/src/Entity.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 0c20bc42..a1d5fc30 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -4011,7 +4011,11 @@ int entityclass::getcrewman(int t) } } - return -1; + // Return entity 0 as a fallback + // Unfortunately some levels rely on this, where targeting a non-existent crewman returns the first entity... + // Which, most of the time, is the player. + + return 0; } int entityclass::getcustomcrewman(int t) From 2ee5aef3fab5fef7d5a616bccdda09714fe05ca5 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Tue, 29 Apr 2025 21:14:06 -0300 Subject: [PATCH 41/64] Fix the campaign trinket count missing from stats PR #1226 tweaks both the crew and the stats screens. When there's no trinkets in the level, it removes the trinket count from the STATS screen in the menu. This, however, is missing a `custommode` check, meaning that the main game is ALSO missing the trinket count. This PR fixes that oversight. --- desktop_version/src/Render.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index c3c1d7c0..428172cb 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -3198,9 +3198,12 @@ void maprender(void) } /* Stats. */ - int deaths_pos = (cl.numtrinkets() > 0) ? 102 : 72; - int time_pos = (cl.numtrinkets() > 0) ? 152 : 132; - if (cl.numtrinkets() > 0) + + // Always show trinkets if you're in the main game, otherwise only show them if any exist in the level + bool show_trinkets = map.custommode ? (cl.numtrinkets() > 0) : true; + int deaths_pos = show_trinkets ? 102 : 72; + int time_pos = show_trinkets ? 152 : 132; + if (show_trinkets) { font::print(PR_CEN | FLIP_PR_CJK_HIGH, -1, FLIP(52, 8), loc::gettext("[Trinkets found]"), 196, 196, 255 - help.glow); char buffer[SCREEN_WIDTH_CHARS + 1]; From 6810c5fa8ce063c97f050f56943940329baad1e7 Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Mon, 28 Apr 2025 01:03:17 -0300 Subject: [PATCH 42/64] Fix #1223 (analogue mode segfault) When `SDL_RenderReadPixels` fails for some reason, the game tries to free the temporary source surface it creates. Unfortunately, it never sets it to `NULL` after, so the next time the game tries to render the filter, it'll try to work with a memory region that was already freed. To fix this, I just replaced `SDL_FreeSurface(*src);` with `VVV_freefunc(SDL_FreeSurface, *src);` which is a helper macro which sets the pointer to NULL after freeing. Now, there's a new issue -- since the temporary buffer is now NULL, next frame we'll try to remake it! So I've introduced a static bool which disables the filter entirely if `SDL_RenderReadPixels` fails. Without this, it'd create and destroy a surface every frame, which could lead to slowdown. (Not as slow as the filter when it DOES work, but still...) I also added a line which frees the second temporary surface... it's weird that was missing in the first place, but I think reimplementing analogue mode was one of the last things I did for the renderer rewrite anyways. Resolves #1223. --- desktop_version/src/GraphicsUtil.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/desktop_version/src/GraphicsUtil.cpp b/desktop_version/src/GraphicsUtil.cpp index 55e89b1a..33ffb256 100644 --- a/desktop_version/src/GraphicsUtil.cpp +++ b/desktop_version/src/GraphicsUtil.cpp @@ -189,8 +189,15 @@ void UpdateFilter(void) } } +static bool disabled_filter = false; + void ApplyFilter(SDL_Surface** src, SDL_Surface** dest) { + if (disabled_filter) + { + return; + } + if (src == NULL || dest == NULL) { SDL_assert(0 && "NULL src or dest!"); @@ -214,7 +221,9 @@ void ApplyFilter(SDL_Surface** src, SDL_Surface** dest) const int result = SDL_RenderReadPixels(gameScreen.m_renderer, NULL, 0, (*src)->pixels, (*src)->pitch); if (result != 0) { - SDL_FreeSurface(*src); + disabled_filter = true; + VVV_freefunc(SDL_FreeSurface, *src); + VVV_freefunc(SDL_FreeSurface, *dest); WHINE_ONCE_ARGS(("Could not read pixels from renderer: %s", SDL_GetError())); return; } From 719ed9a67b206ce1978438c0c39a1456bf3766cc Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Mon, 28 Apr 2025 01:15:31 -0300 Subject: [PATCH 43/64] Fix uncommon division-by-zero Every now and then, the game crashes for me because of a division by zero, due to the rect returned by `Graphics::get_stretch_info`. I don't fully know how the width and height get set to 0, but this should protect against it. As I always use integer scaling, my guess is that `Screen::GetScreenSize` (which later calls `SDL_GetRendererOutputSize`) returns 0 sometimes, and the code trusts that -- but I know that windows and things can be finicky, so the clamp is probably a good idea. --- desktop_version/src/Graphics.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index 72b50c01..8841a69e 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -3536,12 +3536,15 @@ void Graphics::get_stretch_info(SDL_Rect* rect) break; default: SDL_assert(0 && "Invalid scaling mode!"); - /* Width and height should be nonzero to avoid division by zero. */ rect->x = 0; rect->y = 0; rect->w = width; rect->h = height; } + + // In case anything accidentally set the width/height to 0, we'll clamp it to avoid crashing from a division by 0 + rect->w = SDL_max(1, rect->w); + rect->h = SDL_max(1, rect->h); } void Graphics::render(void) From 3eb88e0ac0f391aab4fa6437c943e3b29fdef786 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Sun, 13 Apr 2025 04:11:31 +0200 Subject: [PATCH 44/64] Add files for Persian localization A bit overdue since this was delivered a few weeks ago (oops), but here it is! Thanks to Amir Arzani and Masoud Varaste. --- desktop_version/lang/fa/cutscenes.xml | 945 ++++++++++++++++++ .../lang/fa/graphics/flipsprites.png | Bin 0 -> 2106 bytes desktop_version/lang/fa/graphics/sprites.png | Bin 0 -> 2426 bytes .../lang/fa/graphics/spritesmask.xml | 9 + desktop_version/lang/fa/meta.xml | 38 + desktop_version/lang/fa/numbers.xml | 124 +++ desktop_version/lang/fa/roomnames.xml | 193 ++++ desktop_version/lang/fa/roomnames_special.xml | 71 ++ desktop_version/lang/fa/strings.xml | 811 +++++++++++++++ desktop_version/lang/fa/strings_plural.xml | 32 + 10 files changed, 2223 insertions(+) create mode 100644 desktop_version/lang/fa/cutscenes.xml create mode 100644 desktop_version/lang/fa/graphics/flipsprites.png create mode 100644 desktop_version/lang/fa/graphics/sprites.png create mode 100644 desktop_version/lang/fa/graphics/spritesmask.xml create mode 100644 desktop_version/lang/fa/meta.xml create mode 100644 desktop_version/lang/fa/numbers.xml create mode 100644 desktop_version/lang/fa/roomnames.xml create mode 100644 desktop_version/lang/fa/roomnames_special.xml create mode 100644 desktop_version/lang/fa/strings.xml create mode 100644 desktop_version/lang/fa/strings_plural.xml diff --git a/desktop_version/lang/fa/cutscenes.xml b/desktop_version/lang/fa/cutscenes.xml new file mode 100644 index 00000000..a1b570cd --- /dev/null +++ b/desktop_version/lang/fa/cutscenes.xml @@ -0,0 +1,945 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/desktop_version/lang/fa/graphics/flipsprites.png b/desktop_version/lang/fa/graphics/flipsprites.png new file mode 100644 index 0000000000000000000000000000000000000000..d8c893e05b803bb602d53308d5ab51602d66ff1d GIT binary patch literal 2106 zcmeHHSx{4F6h4;=NkAh3af@YBMyqITMX(Y{f`EvMvegA5i5n^r1gS>Bz>T(yYm#wk zwOT|$3j`sk2rfX}8gU^31E@d(Dm9V;Y#}TmOE0aC4^AKY+UY-Y=KtoKbIzRoK-jWi zvK`e90LUSW0wVwr48RIV1e`f^_ND>g#6|dy1YnjyCxs#zhtGG*9EE zMw`~jiGAp5ZmxIzW>!IZ?*LNiY@^&CHeK;_G{$R4Jd(T+ zJxFE9Eb+I!W{*^;Sna;&V^g~AFn4QC7lGuVihgsJk6tS?7f!78iv4kn+}t3 z+$xEs*}#nObKmad+np&kl;{PyaZfn)>??G!s&?sRJp*Y-7wT&p}hVoGk4hRUaD1IU&;z7U=-2C&%(u5(}g6a{!IhXk!zz=o7=l5 zqhY3Dy)M$>4=x_c${nZh2-$`d9a?>4m12cuo?h@;O}3XahIYAKr^QJ-7-e)ZtM~Fg z!w-CnxiXPnU`gpftNGtA(Va6Z3hh0{Inz5vWVk7H8b)mU=FYMf0Qm?W>_k<%1N;y7p7b6sOm8+WLX3yudz$sX%t z=2m$FCr|sXn#D$8!6gb^Qr`er)cJs^>rFYQE2$tot__P|N5bAfqS!Dz8GfmWK3Ti- zEQJQ_W+k^t7z0&+$kRdaSvg?f?1-easYvx5svaYMwN!w`knNLD66a?Of7`*$FiZ|fJi%w?uhff?~Z(gb^^NV!j1I|kw8>#ZDDzeaqeH$eQ#Sv$(Vk(n&G{Kc8*?Wj}L*q@p!UCJ5)6u*1E@>CTdwnpqj6PACV|Bf+D{ez57Nfc& z>3^0Z>$1HoanG2-3MM4$ntuZ6Ro;SvF?E+rYTLmq9sS12WVz!}0?coq>0bG@@vgEx z!_v^oenYe(rZF1eTS8#iY6ljp^neqsL4zpN;pKMRl|A1tfKB?0fm-j;gkQ#+{s(vv-( zSk`p5w8yzK2Z0$ce21vI9WzaBa$Z^4rrwQ*HQTxcjv$1&-BvUQQihEYh+ LvcRGRoV|Yn7R$AY literal 0 HcmV?d00001 diff --git a/desktop_version/lang/fa/graphics/sprites.png b/desktop_version/lang/fa/graphics/sprites.png new file mode 100644 index 0000000000000000000000000000000000000000..e8d9f5641a22067957c783e33ee734e5791d5bcc GIT binary patch literal 2426 zcmeHJX*e6$8a_#+2*xs8YZIk3LC0-ts|wLkM5RI8a$7}cW!k8*^p@6=aE&qcwXI5p zsaRUIlp>8KV;!#L)+ol(c2G-;NG%DPnA~mt%rigc=RD6nf6jN_=bZ1H_dV}9&-abn zIVS~#76JgEfOmHA002S<019LdNRU(}XIIimQS1r!0Muo~?78OxAghjdu=k8&tj-K( zPg$q}{}-L4wd(H_f~7;a@aE*aSv?=RcBu3eow`1AWDtEfR3S`OoFL^K^V&7&sd0|t zG@AF**9jq(lFYxSq5X0>5S;Izz%SE$5!)6wX+Z0mtoO2^KQez!!!D>MuzOh{y|2Qk ztZ$*j@GUNf$ zmyb++wxihE=%pQE*(%aU18#**1aDz4lZ=pw`XHImR}j@XkE)iNzc!q&2?4yk5g0E8 zw|3JfUm2{IHXxhl+fn*J*NCEMV`81cwM_$bcPCSE&zNo%tdt@JIxk!V$HLe}f&CznVTlhpOWtIcv$K(D-rBV5cR#;O9xZj}-DJ}1d8YzsL32)q1X zm*r|_m?|(N5Y8skR)s!y&-fP&6a*r7V;>bg{$G}^BHS(Z>%ukW1b>!kXX{q-IQWWg zn_>dQcmR(KWO`r&jA491D)E6UB#bj7K6j*Q^}D2TrTrK_Jr?zLe**p<%b2$UBGg@_tah_~~D(8&~QSy0prYy!&P75;(_r z+crWCXLaAw^kG2X`rEiKx4jvR3v^^k{h?qqYN#cm}Q*-a-#(gN66Ks`h zLwn`62v9G->ZsXv=S18)tCMrR^BKeD7!VxZU3#NCI^hrkJl3fbUi<)!SQQMLFD)yn z85Voo?sjUd+}@Km5(q^*e4*&%MWW}wRVLv;z6XfP;q+qKkaoRSBP{7H9tMSL)`Pvw z)CE?z#2C*pz{Vh5rj^a9hfB|cfJ(8J1F`Hsq7g~dR@kUN;@S5@jxF|d!A z$x4C(Hw+vgMq@ty*i{zgD#}WM;zqrpkH}hOiF>@JLur>fX|Qb;__GlOs`U;Y*`7-$ zpW?)aTa%&HVb-NR(LtzJ&T0KS8bK!F?CTi5Snb#Lr&DVyJ%jwjJA&)=H7Ht}xrn(~ zWG9$j7amMAj#*=Jre4Z*@?)V^VfQ(rBHmNKRoJMf_?j3-7WV;@p z8ad^+>q(4iISuuOfr`BUF#h!^e?jOfl2;n|ZmTlTMXfRRAF+&`F9GH4sd&qKxwXDi z+x+l$OQ!~kY4qX6i7i#g8?zpjvHO?LUm!M9i77YJ(^Y$_{YGBHs=H+TAKu+-)pT(? z8!aY7(;h_LNRY3YdUo}yc1LOZGX>lQ1P&_Ft2Nw-9G9gbt%H_%O`Fqu0wtJOvuKkqGFnJK@fU+Y@Pfv~2c*KU8Yi;lTYSTR^I923hp=_PHD!12Od zdZ64OY25YbOS5sE2uCc};-xy>0Q&|z+v8iv0oo^;TFD;Fh>zadO^BLt)7v?ArCzZR zG(os|?%rl+qSe+OtM6&zy!B|3$|T(DylCH_l-fiNCzwAQAx=j8DQnzB3{5)*^{&{T z@1HD>4H##98oA5{pT~SsOzDeho|j`3D05vz@ct6!(aTVS6VQp`eVdrzL!?=0m&;O0 z=4zq= zmTH$zl>&@(Xl+)JZKxW8yWhCd3k!9$m6dnHU?*jxi8~s90c;Hj@O0swh@U{)^N{EQ zsr=-ly7c<&Qj2vA`OQGpZ++&!nC1V$A6bDuku-l;TD6$6 + + + + + + + + diff --git a/desktop_version/lang/fa/meta.xml b/desktop_version/lang/fa/meta.xml new file mode 100644 index 00000000..1ee34692 --- /dev/null +++ b/desktop_version/lang/fa/meta.xml @@ -0,0 +1,38 @@ + + + 1 + + + فارسی + + + Persian Localization: Amir Arzani & Masoud Varaste + + + برای انتخاب روی اسپیس، Z، یا V بزن + + + برای انتخاب روی {button} بزن + + + 1 + + + 1 + + + 0 + + + 0 + + + 1 + + + [ {label} ] + [{label}] + + + font_ar + diff --git a/desktop_version/lang/fa/numbers.xml b/desktop_version/lang/fa/numbers.xml new file mode 100644 index 00000000..705ecdce --- /dev/null +++ b/desktop_version/lang/fa/numbers.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/desktop_version/lang/fa/roomnames.xml b/desktop_version/lang/fa/roomnames.xml new file mode 100644 index 00000000..e7fdc0a8 --- /dev/null +++ b/desktop_version/lang/fa/roomnames.xml @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/desktop_version/lang/fa/roomnames_special.xml b/desktop_version/lang/fa/roomnames_special.xml new file mode 100644 index 00000000..0bdf5cfa --- /dev/null +++ b/desktop_version/lang/fa/roomnames_special.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/desktop_version/lang/fa/strings.xml b/desktop_version/lang/fa/strings.xml new file mode 100644 index 00000000..fe23b64c --- /dev/null +++ b/desktop_version/lang/fa/strings.xml @@ -0,0 +1,811 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/desktop_version/lang/fa/strings_plural.xml b/desktop_version/lang/fa/strings_plural.xml new file mode 100644 index 00000000..4dff7b4f --- /dev/null +++ b/desktop_version/lang/fa/strings_plural.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 0b00415ab3c8049ba12f714bba6ca9b51e3abcb2 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Sun, 13 Apr 2025 04:30:47 +0200 Subject: [PATCH 45/64] Add Persian to credits screen --- desktop_version/lang/en/strings.xml | 1 + desktop_version/src/Credits.h | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/desktop_version/lang/en/strings.xml b/desktop_version/lang/en/strings.xml index ee3db7b6..c545f900 100644 --- a/desktop_version/lang/en/strings.xml +++ b/desktop_version/lang/en/strings.xml @@ -789,6 +789,7 @@ You have found the secret lab!" translation="" explanation="" max="34*4"/> + diff --git a/desktop_version/src/Credits.h b/desktop_version/src/Credits.h index a21eab65..a6c6f630 100644 --- a/desktop_version/src/Credits.h +++ b/desktop_version/src/Credits.h @@ -28,6 +28,9 @@ static const char* translators[] = { "Spanish (ARG.)", " LocQuest", " Guido Di Carlo", + "Persian", + " Amir Arzani", + " Masoud Varaste", "French", " Words of Magic", "Irish", @@ -74,7 +77,7 @@ static const char* translators[] = { }; /* Hardcoded pagesizes for the translator credits. Simplifies paging backwards and forwards */ -static const int translator_pagesize[] = { 6, 6, 9, 12, 10, 11, 10 }; +static const int translator_pagesize[] = { 6, 6, 12, 12, 10, 11, 10 }; /* Terry's Patrons... */ static const char* superpatrons[] = { From 374ce11425a8e5412dfb6a6c3819c0a7d2c92018 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Sun, 13 Apr 2025 04:33:46 +0200 Subject: [PATCH 46/64] Sync language files This adds "Persian" to all the languages, and brings the Persian files up-to-date (mainly removing outdated strings and adding some late 2.4 stuff that we'll contact all translators for soon) --- desktop_version/lang/ar/strings.xml | 1 + desktop_version/lang/ca/strings.xml | 1 + desktop_version/lang/cy/strings.xml | 1 + desktop_version/lang/de/strings.xml | 1 + desktop_version/lang/eo/strings.xml | 1 + desktop_version/lang/es/strings.xml | 1 + desktop_version/lang/es_419/strings.xml | 1 + desktop_version/lang/es_AR/strings.xml | 1 + desktop_version/lang/fa/cutscenes.xml | 3 +- desktop_version/lang/fa/strings.xml | 42 ++++++++++--------------- desktop_version/lang/fr/strings.xml | 1 + desktop_version/lang/ga/strings.xml | 1 + desktop_version/lang/it/strings.xml | 1 + desktop_version/lang/ja/strings.xml | 1 + desktop_version/lang/ko/strings.xml | 1 + desktop_version/lang/nl/strings.xml | 1 + desktop_version/lang/pl/strings.xml | 1 + desktop_version/lang/pt_BR/strings.xml | 1 + desktop_version/lang/pt_PT/strings.xml | 1 + desktop_version/lang/ru/strings.xml | 1 + desktop_version/lang/szl/strings.xml | 1 + desktop_version/lang/tr/strings.xml | 1 + desktop_version/lang/uk/strings.xml | 1 + desktop_version/lang/zh/strings.xml | 1 + desktop_version/lang/zh_TW/strings.xml | 1 + 25 files changed, 40 insertions(+), 28 deletions(-) diff --git a/desktop_version/lang/ar/strings.xml b/desktop_version/lang/ar/strings.xml index 7c192c43..40d26b75 100644 --- a/desktop_version/lang/ar/strings.xml +++ b/desktop_version/lang/ar/strings.xml @@ -803,6 +803,7 @@ You have found the secret lab!" translation="تهانينا! + diff --git a/desktop_version/lang/ca/strings.xml b/desktop_version/lang/ca/strings.xml index fa956d2f..dd78c943 100644 --- a/desktop_version/lang/ca/strings.xml +++ b/desktop_version/lang/ca/strings.xml @@ -795,6 +795,7 @@ Has trobat el laboratori secret!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/cy/strings.xml b/desktop_version/lang/cy/strings.xml index 90b23913..393d1aaf 100644 --- a/desktop_version/lang/cy/strings.xml +++ b/desktop_version/lang/cy/strings.xml @@ -795,6 +795,7 @@ Rwyt ti wedi dod o hyd i'r labordy cyfrinachol!" explanation="" max="34*4"/ + diff --git a/desktop_version/lang/de/strings.xml b/desktop_version/lang/de/strings.xml index e869c9db..21c3a418 100644 --- a/desktop_version/lang/de/strings.xml +++ b/desktop_version/lang/de/strings.xml @@ -795,6 +795,7 @@ Du hast das Geheimlabor gefunden!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/eo/strings.xml b/desktop_version/lang/eo/strings.xml index cc34e896..3561d4c9 100644 --- a/desktop_version/lang/eo/strings.xml +++ b/desktop_version/lang/eo/strings.xml @@ -795,6 +795,7 @@ Vi trovis la sekretan labon!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/es/strings.xml b/desktop_version/lang/es/strings.xml index c2cfae35..410d861e 100644 --- a/desktop_version/lang/es/strings.xml +++ b/desktop_version/lang/es/strings.xml @@ -795,6 +795,7 @@ You have found the secret lab!" translation="¡Enhorabuena! + diff --git a/desktop_version/lang/es_419/strings.xml b/desktop_version/lang/es_419/strings.xml index ea6a1cf9..c73a2252 100644 --- a/desktop_version/lang/es_419/strings.xml +++ b/desktop_version/lang/es_419/strings.xml @@ -795,6 +795,7 @@ You have found the secret lab!" translation="¡Felicitaciones! + diff --git a/desktop_version/lang/es_AR/strings.xml b/desktop_version/lang/es_AR/strings.xml index e9bf98b1..460554a2 100644 --- a/desktop_version/lang/es_AR/strings.xml +++ b/desktop_version/lang/es_AR/strings.xml @@ -795,6 +795,7 @@ You have found the secret lab!" translation="¡Felicitaciones! + diff --git a/desktop_version/lang/fa/cutscenes.xml b/desktop_version/lang/fa/cutscenes.xml index a1b570cd..0bae1ffd 100644 --- a/desktop_version/lang/fa/cutscenes.xml +++ b/desktop_version/lang/fa/cutscenes.xml @@ -76,10 +76,9 @@ - + - diff --git a/desktop_version/lang/fa/strings.xml b/desktop_version/lang/fa/strings.xml index fe23b64c..3afb4a98 100644 --- a/desktop_version/lang/fa/strings.xml +++ b/desktop_version/lang/fa/strings.xml @@ -232,6 +232,11 @@ + + + + + @@ -317,6 +322,9 @@ + + + @@ -428,16 +436,13 @@ - - - - - + + @@ -449,7 +454,6 @@ - @@ -463,7 +467,6 @@ - @@ -478,7 +481,6 @@ - @@ -564,21 +566,13 @@ - - - - - - - - @@ -592,25 +586,17 @@ - - - - - - - - @@ -641,6 +627,7 @@ + @@ -677,9 +664,7 @@ - - @@ -785,6 +770,7 @@ You have found the secret lab!" translation="مبارکه! + @@ -806,6 +792,10 @@ You have found the secret lab!" translation="مبارکه! + + + + diff --git a/desktop_version/lang/fr/strings.xml b/desktop_version/lang/fr/strings.xml index b7f69dc4..6fe683dd 100644 --- a/desktop_version/lang/fr/strings.xml +++ b/desktop_version/lang/fr/strings.xml @@ -795,6 +795,7 @@ Vous avez trouvé le labo secret !" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/ga/strings.xml b/desktop_version/lang/ga/strings.xml index bb19ca2c..5e7416e5 100644 --- a/desktop_version/lang/ga/strings.xml +++ b/desktop_version/lang/ga/strings.xml @@ -797,6 +797,7 @@ Fuair tú an tsaotharlann rúnda!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/it/strings.xml b/desktop_version/lang/it/strings.xml index 4a3c32f3..f601dfca 100644 --- a/desktop_version/lang/it/strings.xml +++ b/desktop_version/lang/it/strings.xml @@ -795,6 +795,7 @@ Hai trovato il laboratorio segreto!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/ja/strings.xml b/desktop_version/lang/ja/strings.xml index 0586db9e..bc4a391c 100644 --- a/desktop_version/lang/ja/strings.xml +++ b/desktop_version/lang/ja/strings.xml @@ -861,6 +861,7 @@ You have found the secret lab!" translation="よくやった! + diff --git a/desktop_version/lang/ko/strings.xml b/desktop_version/lang/ko/strings.xml index 10ff2981..a1987824 100755 --- a/desktop_version/lang/ko/strings.xml +++ b/desktop_version/lang/ko/strings.xml @@ -795,6 +795,7 @@ You have found the secret lab!" translation="축하합니다! + diff --git a/desktop_version/lang/nl/strings.xml b/desktop_version/lang/nl/strings.xml index 09a551ae..38ad3fe1 100644 --- a/desktop_version/lang/nl/strings.xml +++ b/desktop_version/lang/nl/strings.xml @@ -796,6 +796,7 @@ Je hebt het geheime lab gevonden!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/pl/strings.xml b/desktop_version/lang/pl/strings.xml index c88a28fa..33f9a007 100644 --- a/desktop_version/lang/pl/strings.xml +++ b/desktop_version/lang/pl/strings.xml @@ -795,6 +795,7 @@ Znaleziono tajne laboratorium!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/pt_BR/strings.xml b/desktop_version/lang/pt_BR/strings.xml index dd5d677b..8a3a076e 100644 --- a/desktop_version/lang/pt_BR/strings.xml +++ b/desktop_version/lang/pt_BR/strings.xml @@ -795,6 +795,7 @@ Você encontrou o laboratório secreto!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/pt_PT/strings.xml b/desktop_version/lang/pt_PT/strings.xml index 51ca859b..3f8a5c00 100644 --- a/desktop_version/lang/pt_PT/strings.xml +++ b/desktop_version/lang/pt_PT/strings.xml @@ -795,6 +795,7 @@ Encontraste o laboratório secreto!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/ru/strings.xml b/desktop_version/lang/ru/strings.xml index 3b310c88..b9cc70b3 100644 --- a/desktop_version/lang/ru/strings.xml +++ b/desktop_version/lang/ru/strings.xml @@ -820,6 +820,7 @@ You have found the secret lab!" translation="Поздравляем! + diff --git a/desktop_version/lang/szl/strings.xml b/desktop_version/lang/szl/strings.xml index 38640252..8f9e3960 100644 --- a/desktop_version/lang/szl/strings.xml +++ b/desktop_version/lang/szl/strings.xml @@ -795,6 +795,7 @@ Wysznupano tajne laboratoriōm!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/tr/strings.xml b/desktop_version/lang/tr/strings.xml index cd98037d..9d4f43d0 100644 --- a/desktop_version/lang/tr/strings.xml +++ b/desktop_version/lang/tr/strings.xml @@ -795,6 +795,7 @@ Gizli laboratuvarı buldun!" explanation="" max="34*4"/> + diff --git a/desktop_version/lang/uk/strings.xml b/desktop_version/lang/uk/strings.xml index 33c6fa97..e147c6f0 100644 --- a/desktop_version/lang/uk/strings.xml +++ b/desktop_version/lang/uk/strings.xml @@ -795,6 +795,7 @@ You have found the secret lab!" translation="Поздоровляємо! + diff --git a/desktop_version/lang/zh/strings.xml b/desktop_version/lang/zh/strings.xml index a9b83ef0..9295329e 100644 --- a/desktop_version/lang/zh/strings.xml +++ b/desktop_version/lang/zh/strings.xml @@ -805,6 +805,7 @@ You have found the secret lab!" translation="恭喜你! + diff --git a/desktop_version/lang/zh_TW/strings.xml b/desktop_version/lang/zh_TW/strings.xml index 9d58c94e..94b34e22 100644 --- a/desktop_version/lang/zh_TW/strings.xml +++ b/desktop_version/lang/zh_TW/strings.xml @@ -805,6 +805,7 @@ You have found the secret lab!" translation="恭喜你! + From 48c3e175a3ab95fa49902830d965e6ed24f7ea76 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Sun, 13 Apr 2025 04:59:31 +0200 Subject: [PATCH 47/64] Fix save summary sometimes getting misordered in Arabic The Persian localizers noticed an issue where the translation for "Dimension VVVVVV, 12:34:56" would become "VVVVVV, 12:34:56 noisnemiD", rather than "12:34:56 ,VVVVVV noisnemiD" as expected. This was fixed for Persian but the same issue also affected Arabic, so I added a RIGHT-TO-LEFT MARK (U+200F) to fix it there as well. --- desktop_version/lang/ar/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/lang/ar/strings.xml b/desktop_version/lang/ar/strings.xml index 40d26b75..d9c028da 100644 --- a/desktop_version/lang/ar/strings.xml +++ b/desktop_version/lang/ar/strings.xml @@ -663,7 +663,7 @@ - + From 1a1bf2a4f96b131790e82b1e8e8c9a2ba73e242d Mon Sep 17 00:00:00 2001 From: Dav999 Date: Tue, 15 Apr 2025 22:15:05 +0200 Subject: [PATCH 48/64] Add new strings for Persian New strings were delivered already today, so let's add them immediately in this PR so we have a little less on our checklist later! --- desktop_version/lang/fa/strings.xml | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/desktop_version/lang/fa/strings.xml b/desktop_version/lang/fa/strings.xml index 3afb4a98..3c0c5902 100644 --- a/desktop_version/lang/fa/strings.xml +++ b/desktop_version/lang/fa/strings.xml @@ -232,11 +232,11 @@ - - - - - + + + + + @@ -322,9 +322,9 @@ - - - + + + @@ -441,8 +441,8 @@ - - + + @@ -627,7 +627,7 @@ - + @@ -770,7 +770,7 @@ You have found the secret lab!" translation="مبارکه! - + @@ -792,9 +792,9 @@ You have found the secret lab!" translation="مبارکه! - - - + + + From 75035047ad48f82f68220af10a82d08f5d0f59f9 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Wed, 16 Apr 2025 21:13:07 +0200 Subject: [PATCH 49/64] Update name of Arabic/Persian font The level font menu now shows both names, since the font is used for both Arabic and Persian. --- desktop_version/fonts/font_ar.fontmeta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/fonts/font_ar.fontmeta b/desktop_version/fonts/font_ar.fontmeta index ba5d788b..9ca2556b 100644 --- a/desktop_version/fonts/font_ar.fontmeta +++ b/desktop_version/fonts/font_ar.fontmeta @@ -1,6 +1,6 @@ - العربية + العربية/فارسی 8 10 1 From d730528118812d356c708425592e97c68983d0f5 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Wed, 16 Apr 2025 05:44:13 +0200 Subject: [PATCH 50/64] Add confirmation and removal to bindings menu This makes the following improvements to the gamepad bindings menu: - The menu now shows a hint that you can press a button while any of the bind options are selected (or that you can navigate away from those options) - Instead of button presses immediately setting a binding, they now ask for confirmation: press the same button a second time to confirm - You can now remove a binding, the same way you add it (this has the same type of confirmation) - This menu used to be inconsistent with pretty much every other menu in the game by showing a permanent title and description for the menu itself ("Game Pad", "Change controller options.") rather than showing a title and description for the currently selected option. This inconsistency is now fixed. --- desktop_version/lang/en/strings.xml | 13 ++- desktop_version/src/ButtonGlyphs.cpp | 4 +- desktop_version/src/ButtonGlyphs.h | 1 + desktop_version/src/Game.cpp | 6 +- desktop_version/src/Game.h | 4 + desktop_version/src/Input.cpp | 51 +++++++++- desktop_version/src/Render.cpp | 147 ++++++++++++++++++++------- 7 files changed, 182 insertions(+), 44 deletions(-) diff --git a/desktop_version/lang/en/strings.xml b/desktop_version/lang/en/strings.xml index c545f900..a4f701b6 100644 --- a/desktop_version/lang/en/strings.xml +++ b/desktop_version/lang/en/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/src/ButtonGlyphs.cpp b/desktop_version/src/ButtonGlyphs.cpp index 4abbf4ed..229a0e32 100644 --- a/desktop_version/src/ButtonGlyphs.cpp +++ b/desktop_version/src/ButtonGlyphs.cpp @@ -272,7 +272,7 @@ const char* BUTTONGLYPHS_get_wasd_text(void) return loc::gettext("Press left/right to move"); } -static const char* sdlbutton_to_glyph(const SDL_GameControllerButton button) +const char* BUTTONGLYPHS_sdlbutton_to_glyph(const SDL_GameControllerButton button) { if (button > SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) { @@ -292,7 +292,7 @@ static const char* glyph_for_vector( return NULL; } - return sdlbutton_to_glyph(buttons[index]); + return BUTTONGLYPHS_sdlbutton_to_glyph(buttons[index]); } const char* BUTTONGLYPHS_get_button(const ActionSet actionset, const Action action, int binding) diff --git a/desktop_version/src/ButtonGlyphs.h b/desktop_version/src/ButtonGlyphs.h index bef8f805..78416117 100644 --- a/desktop_version/src/ButtonGlyphs.h +++ b/desktop_version/src/ButtonGlyphs.h @@ -20,6 +20,7 @@ void BUTTONGLYPHS_keyboard_set_active(bool active); void BUTTONGLYPHS_update_layout(SDL_GameController *c); const char* BUTTONGLYPHS_get_wasd_text(void); +const char* BUTTONGLYPHS_sdlbutton_to_glyph(SDL_GameControllerButton button); const char* BUTTONGLYPHS_get_button(ActionSet actionset, Action action, int binding); char* BUTTONGLYPHS_get_all_gamepad_buttons( diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index d5b734f7..196c4d54 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -254,6 +254,10 @@ void Game::init(void) levelpage=0; playcustomlevel=0; + gpmenu_lastbutton = SDL_CONTROLLER_BUTTON_INVALID; + gpmenu_confirming = false; + gpmenu_showremove = false; + silence_settings_error = false; deathcounts = 0; @@ -7009,7 +7013,7 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ ) option(loc::gettext("bind restart")); option(loc::gettext("bind interact"), separate_interact); option(loc::gettext("return")); - menuyoff = 0; + menuyoff = 12; maxspacing = 10; break; case Menu::language: diff --git a/desktop_version/src/Game.h b/desktop_version/src/Game.h index 05817b05..b053d1b4 100644 --- a/desktop_version/src/Game.h +++ b/desktop_version/src/Game.h @@ -404,6 +404,10 @@ public: int creditposx, creditposy, creditposdelay; int oldcreditposx; + SDL_GameControllerButton gpmenu_lastbutton; + bool gpmenu_confirming; + bool gpmenu_showremove; + bool silence_settings_error; diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index ef298851..4ee34af7 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -35,6 +35,37 @@ static void updatebuttonmappings(int bind) ) { if (key.isDown(i)) { + if (!game.gpmenu_confirming || i != game.gpmenu_lastbutton) + { + game.gpmenu_confirming = true; + game.gpmenu_lastbutton = i; + + // Is this button already in the list for this action? + std::vector* vec = NULL; + switch (bind) + { + case 1: vec = &game.controllerButton_flip; break; + case 2: vec = &game.controllerButton_map; break; + case 3: vec = &game.controllerButton_esc; break; + case 4: vec = &game.controllerButton_restart; break; + case 5: vec = &game.controllerButton_interact; break; + default: return; + } + + game.gpmenu_showremove = false; + for (size_t j = 0; j < vec->size(); j += 1) + { + if (i == (*vec)[j]) + { + game.gpmenu_showremove = true; + break; + } + } + + return; + } + game.gpmenu_confirming = false; + bool dupe = false; switch (bind) { @@ -46,13 +77,14 @@ static void updatebuttonmappings(int bind) if (i == game.controllerButton_flip[j]) { dupe = true; + game.controllerButton_flip.erase(game.controllerButton_flip.begin() + j); } } if (!dupe) { game.controllerButton_flip.push_back(i); - music.playef(Sound_VIRIDIAN); } + music.playef(Sound_VIRIDIAN); for (j = 0; j < game.controllerButton_map.size(); j += 1) { if (i == game.controllerButton_map[j]) @@ -91,13 +123,14 @@ static void updatebuttonmappings(int bind) if (i == game.controllerButton_map[j]) { dupe = true; + game.controllerButton_map.erase(game.controllerButton_map.begin() + j); } } if (!dupe) { game.controllerButton_map.push_back(i); - music.playef(Sound_VIRIDIAN); } + music.playef(Sound_VIRIDIAN); for (j = 0; j < game.controllerButton_flip.size(); j += 1) { if (i == game.controllerButton_flip[j]) @@ -136,13 +169,14 @@ static void updatebuttonmappings(int bind) if (i == game.controllerButton_esc[j]) { dupe = true; + game.controllerButton_esc.erase(game.controllerButton_esc.begin() + j); } } if (!dupe) { game.controllerButton_esc.push_back(i); - music.playef(Sound_VIRIDIAN); } + music.playef(Sound_VIRIDIAN); for (j = 0; j < game.controllerButton_flip.size(); j += 1) { if (i == game.controllerButton_flip[j]) @@ -181,13 +215,14 @@ static void updatebuttonmappings(int bind) if (i == game.controllerButton_restart[j]) { dupe = true; + game.controllerButton_restart.erase(game.controllerButton_restart.begin() + j); } } if (!dupe) { game.controllerButton_restart.push_back(i); - music.playef(Sound_VIRIDIAN); } + music.playef(Sound_VIRIDIAN); for (j = 0; j < game.controllerButton_flip.size(); j += 1) { if (i == game.controllerButton_flip[j]) @@ -226,13 +261,14 @@ static void updatebuttonmappings(int bind) if (i == game.controllerButton_interact[j]) { dupe = true; + game.controllerButton_interact.erase(game.controllerButton_interact.begin() + j); } } if (!dupe) { game.controllerButton_interact.push_back(i); - music.playef(Sound_VIRIDIAN); } + music.playef(Sound_VIRIDIAN); for (j = 0; j < game.controllerButton_flip.size(); j += 1) { if (i == game.controllerButton_flip[j]) @@ -2526,6 +2562,11 @@ void titleinput(void) { game.currentmenuoption++; } + + if (game.currentmenuname == Menu::controller && (game.press_left || game.press_right)) + { + game.gpmenu_confirming = false; + } } else { diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index 428172cb..771927bf 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -691,9 +691,6 @@ static void menurender(void) } case Menu::controller: { - font::print(PR_2X | PR_CEN, -1, 30, loc::gettext("Game Pad"), tr, tg, tb); - font::print_wrap(PR_CEN, -1, 55, loc::gettext("Change controller options."), tr, tg, tb); - int spacing = font::height(0); spacing = SDL_max(spacing, 10); @@ -701,12 +698,15 @@ static void menurender(void) { case 0: { - font::print(PR_RTL_XFLIP, 32, 75, loc::gettext("Low"), tr, tg, tb); - font::print(PR_CEN, -1, 75, loc::gettext("Medium"), tr, tg, tb); - font::print(PR_RIGHT | PR_RTL_XFLIP, 288, 75, loc::gettext("High"), tr, tg, tb); + font::print(PR_2X | PR_CEN, -1, 30, loc::gettext("Stick Sensitivity"), tr, tg, tb); + font::print_wrap(PR_CEN, -1, 55, loc::gettext("Change the sensitivity of the analog stick."), tr, tg, tb); + + font::print(PR_RTL_XFLIP, 32, 95, loc::gettext("Low"), tr, tg, tb); + font::print(PR_CEN, -1, 95, loc::gettext("Medium"), tr, tg, tb); + font::print(PR_RIGHT | PR_RTL_XFLIP, 288, 95, loc::gettext("High"), tr, tg, tb); char slider[SCREEN_WIDTH_CHARS + 1]; slider_get(slider, sizeof(slider), key.sensitivity, 5, 240); - font::print(PR_CEN, -1, 75+spacing, slider, tr, tg, tb); + font::print(PR_CEN, -1, 95+spacing, slider, tr, tg, tb); break; } case 1: @@ -715,38 +715,117 @@ static void menurender(void) case 4: case 5: { - char buffer_a[SCREEN_WIDTH_CHARS + 1]; - char buffer_b[SCREEN_WIDTH_CHARS + 1]; + const char* title = ""; + switch (game.currentmenuoption) + { + case 1: title = loc::gettext("Bind Flip"); break; + case 2: title = loc::gettext("Bind Enter"); break; + case 3: title = loc::gettext("Bind Menu"); break; + case 4: title = loc::gettext("Bind Restart"); break; + case 5: title = loc::gettext("Bind Interact"); break; + } + font::print(PR_2X | PR_CEN, -1, 30, title, tr, tg, tb); - SDL_snprintf(buffer_a, sizeof(buffer_a), "%s%s", - loc::gettext("Flip is bound to: "), - BUTTONGLYPHS_get_all_gamepad_buttons(buffer_b, sizeof(buffer_b), ActionSet_InGame, Action_InGame_ACTION) - ); - font::print(PR_CEN, -1, 75, buffer_a, tr, tg, tb); + if (game.currentmenuoption == 5 && !game.separate_interact) + { + font::print_wrap( + PR_CEN, -1, 55, + loc::gettext("Interact is currently Enter!|See speedrunner options."), + tr, tg, tb + ); + } + else if (!game.gpmenu_confirming) + { + font::print_wrap( + PR_CEN | PR_BRIGHTNESS(255 - help.glow*2), -1, 55, + loc::gettext("Press a button...|(or press ↑↓)"), + tr, tg, tb + ); + } + else + { + char expl[SCREEN_WIDTH_CHARS*3 + 1]; + const char* expl_template; - SDL_snprintf(buffer_a, sizeof(buffer_a), "%s%s", - loc::gettext("Enter is bound to: "), - BUTTONGLYPHS_get_all_gamepad_buttons(buffer_b, sizeof(buffer_b), ActionSet_InGame, Action_InGame_Map) - ); - font::print(PR_CEN, -1, 75+spacing, buffer_a, tr, tg, tb); + if (game.gpmenu_showremove) + { + expl_template = loc::gettext("Remove {button}?|Press again to confirm"); + } + else + { + expl_template = loc::gettext("Add {button}?|Press again to confirm"); + } - SDL_snprintf(buffer_a, sizeof(buffer_a), "%s%s", - loc::gettext("Menu is bound to: "), - BUTTONGLYPHS_get_all_gamepad_buttons(buffer_b, sizeof(buffer_b), ActionSet_InGame, Action_InGame_Esc) - ); - font::print(PR_CEN, -1, 75+spacing*2, buffer_a, tr, tg, tb); + vformat_buf( + expl, sizeof(expl), + expl_template, + "button:str", + BUTTONGLYPHS_sdlbutton_to_glyph(game.gpmenu_lastbutton) + ); - SDL_snprintf(buffer_a, sizeof(buffer_a), "%s%s", - loc::gettext("Restart is bound to: "), - BUTTONGLYPHS_get_all_gamepad_buttons(buffer_b, sizeof(buffer_b), ActionSet_InGame, Action_InGame_Restart) - ); - font::print(PR_CEN, -1, 75+spacing*3, buffer_a, tr, tg, tb); + font::print_wrap(PR_CEN, -1, 55, expl, tr, tg, tb); + } + + for (int bind = 1; bind <= 5; bind++) + { + char buffer_a[SCREEN_WIDTH_CHARS + 1]; + char buffer_b[SCREEN_WIDTH_CHARS + 1]; + + const char* lbl; + ActionSet actionset; + int action; + + switch (bind) + { + case 1: + lbl = loc::gettext("Flip is bound to: "); + actionset = ActionSet_InGame; + action = Action_InGame_ACTION; + break; + case 2: + lbl = loc::gettext("Enter is bound to: "); + actionset = ActionSet_InGame; + action = Action_InGame_Map; + break; + case 3: + lbl = loc::gettext("Menu is bound to: "); + actionset = ActionSet_InGame; + action = Action_InGame_Esc; + break; + case 4: + lbl = loc::gettext("Restart is bound to: "); + actionset = ActionSet_InGame; + action = Action_InGame_Restart; + break; + default: + lbl = loc::gettext("Interact is bound to: "); + actionset = ActionSet_InGame; + action = Action_InGame_Interact; + } + + SDL_snprintf( + buffer_a, sizeof(buffer_a), "%s%s", lbl, + BUTTONGLYPHS_get_all_gamepad_buttons(buffer_b, sizeof(buffer_b), actionset, action) + ); + + int brightness = 255; + if (bind == 5 && !game.separate_interact) + { + brightness = 128; + } + else if (game.gpmenu_confirming && game.currentmenuoption == bind) + { + brightness = 255 - help.glow*2; + } + + font::print( + PR_CEN | PR_BRIGHTNESS(brightness), + -1, 85 + (spacing * (bind-1)), + buffer_a, + tr, tg, tb + ); + } - SDL_snprintf(buffer_a, sizeof(buffer_a), "%s%s", - loc::gettext("Interact is bound to: "), - BUTTONGLYPHS_get_all_gamepad_buttons(buffer_b, sizeof(buffer_b), ActionSet_InGame, Action_InGame_Interact) - ); - font::print(PR_CEN | PR_BRIGHTNESS(game.separate_interact ? 255 : 128), -1, 75+spacing*4, buffer_a, tr, tg, tb); break; } } From 37b788c1c882b40fcefa774034c4422858167651 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Wed, 16 Apr 2025 21:12:51 +0200 Subject: [PATCH 51/64] Add check for converting negative SDL_GameControllerButton to glyph A SDL_GameControllerButton below 0 is out of array bounds, so that should trip the assert and return GLYPH_UNKNOWN just like when the value is too high. --- desktop_version/src/ButtonGlyphs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_version/src/ButtonGlyphs.cpp b/desktop_version/src/ButtonGlyphs.cpp index 229a0e32..3060fd42 100644 --- a/desktop_version/src/ButtonGlyphs.cpp +++ b/desktop_version/src/ButtonGlyphs.cpp @@ -274,7 +274,7 @@ const char* BUTTONGLYPHS_get_wasd_text(void) const char* BUTTONGLYPHS_sdlbutton_to_glyph(const SDL_GameControllerButton button) { - if (button > SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) + if (button < 0 || button > SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) { SDL_assert(0 && "Unhandled button!"); return glyph[GLYPH_UNKNOWN]; From 1de20780144dd6e308b010c5adcb96625c053b2c Mon Sep 17 00:00:00 2001 From: Dav999 Date: Wed, 23 Apr 2025 04:22:16 +0200 Subject: [PATCH 52/64] Sync new gamepad strings into all language files Also including all the localizations I already have right now. --- desktop_version/lang/ar/strings.xml | 13 +++++++++++-- desktop_version/lang/ca/strings.xml | 13 +++++++++++-- desktop_version/lang/cy/strings.xml | 13 +++++++++++-- desktop_version/lang/de/strings.xml | 13 +++++++++++-- desktop_version/lang/eo/strings.xml | 13 +++++++++++-- desktop_version/lang/es/strings.xml | 13 +++++++++++-- desktop_version/lang/es_419/strings.xml | 13 +++++++++++-- desktop_version/lang/es_AR/strings.xml | 13 +++++++++++-- desktop_version/lang/fr/strings.xml | 13 +++++++++++-- desktop_version/lang/ga/strings.xml | 13 +++++++++++-- desktop_version/lang/it/strings.xml | 13 +++++++++++-- desktop_version/lang/ja/strings.xml | 13 +++++++++++-- desktop_version/lang/ko/strings.xml | 13 +++++++++++-- desktop_version/lang/nl/strings.xml | 13 +++++++++++-- desktop_version/lang/pl/strings.xml | 13 +++++++++++-- desktop_version/lang/pt_BR/strings.xml | 13 +++++++++++-- desktop_version/lang/pt_PT/strings.xml | 13 +++++++++++-- desktop_version/lang/ru/strings.xml | 13 +++++++++++-- desktop_version/lang/szl/strings.xml | 13 +++++++++++-- desktop_version/lang/tr/strings.xml | 13 +++++++++++-- desktop_version/lang/uk/strings.xml | 13 +++++++++++-- desktop_version/lang/zh/strings.xml | 13 +++++++++++-- desktop_version/lang/zh_TW/strings.xml | 13 +++++++++++-- 23 files changed, 253 insertions(+), 46 deletions(-) diff --git a/desktop_version/lang/ar/strings.xml b/desktop_version/lang/ar/strings.xml index d9c028da..6bda7700 100644 --- a/desktop_version/lang/ar/strings.xml +++ b/desktop_version/lang/ar/strings.xml @@ -46,10 +46,8 @@ - - @@ -139,19 +137,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/ca/strings.xml b/desktop_version/lang/ca/strings.xml index dd78c943..ed86a9ba 100644 --- a/desktop_version/lang/ca/strings.xml +++ b/desktop_version/lang/ca/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/cy/strings.xml b/desktop_version/lang/cy/strings.xml index 393d1aaf..7c74db23 100644 --- a/desktop_version/lang/cy/strings.xml +++ b/desktop_version/lang/cy/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/de/strings.xml b/desktop_version/lang/de/strings.xml index 21c3a418..528bdce6 100644 --- a/desktop_version/lang/de/strings.xml +++ b/desktop_version/lang/de/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/eo/strings.xml b/desktop_version/lang/eo/strings.xml index 3561d4c9..5b6b8c37 100644 --- a/desktop_version/lang/eo/strings.xml +++ b/desktop_version/lang/eo/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/es/strings.xml b/desktop_version/lang/es/strings.xml index 410d861e..048194d3 100644 --- a/desktop_version/lang/es/strings.xml +++ b/desktop_version/lang/es/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/es_419/strings.xml b/desktop_version/lang/es_419/strings.xml index c73a2252..2e89862f 100644 --- a/desktop_version/lang/es_419/strings.xml +++ b/desktop_version/lang/es_419/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/es_AR/strings.xml b/desktop_version/lang/es_AR/strings.xml index 460554a2..0df8391e 100644 --- a/desktop_version/lang/es_AR/strings.xml +++ b/desktop_version/lang/es_AR/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/fr/strings.xml b/desktop_version/lang/fr/strings.xml index 6fe683dd..b0a3f9b1 100644 --- a/desktop_version/lang/fr/strings.xml +++ b/desktop_version/lang/fr/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/ga/strings.xml b/desktop_version/lang/ga/strings.xml index 5e7416e5..2725864a 100644 --- a/desktop_version/lang/ga/strings.xml +++ b/desktop_version/lang/ga/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/it/strings.xml b/desktop_version/lang/it/strings.xml index f601dfca..2fcd37b7 100644 --- a/desktop_version/lang/it/strings.xml +++ b/desktop_version/lang/it/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/ja/strings.xml b/desktop_version/lang/ja/strings.xml index bc4a391c..834afe4d 100644 --- a/desktop_version/lang/ja/strings.xml +++ b/desktop_version/lang/ja/strings.xml @@ -47,9 +47,7 @@ - - @@ -142,19 +140,30 @@ OFFにしますか?" explanation="" max="38*6" max_local="38*5"/> + + + + + + + + + + + diff --git a/desktop_version/lang/ko/strings.xml b/desktop_version/lang/ko/strings.xml index a1987824..f1a3a205 100755 --- a/desktop_version/lang/ko/strings.xml +++ b/desktop_version/lang/ko/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/nl/strings.xml b/desktop_version/lang/nl/strings.xml index 38ad3fe1..770f988b 100644 --- a/desktop_version/lang/nl/strings.xml +++ b/desktop_version/lang/nl/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/pl/strings.xml b/desktop_version/lang/pl/strings.xml index 33f9a007..ca27b53e 100644 --- a/desktop_version/lang/pl/strings.xml +++ b/desktop_version/lang/pl/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/pt_BR/strings.xml b/desktop_version/lang/pt_BR/strings.xml index 8a3a076e..ad9ffe4e 100644 --- a/desktop_version/lang/pt_BR/strings.xml +++ b/desktop_version/lang/pt_BR/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/pt_PT/strings.xml b/desktop_version/lang/pt_PT/strings.xml index 3f8a5c00..ab0aef48 100644 --- a/desktop_version/lang/pt_PT/strings.xml +++ b/desktop_version/lang/pt_PT/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/ru/strings.xml b/desktop_version/lang/ru/strings.xml index b9cc70b3..52b02b4b 100644 --- a/desktop_version/lang/ru/strings.xml +++ b/desktop_version/lang/ru/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/szl/strings.xml b/desktop_version/lang/szl/strings.xml index 8f9e3960..c86a963a 100644 --- a/desktop_version/lang/szl/strings.xml +++ b/desktop_version/lang/szl/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/tr/strings.xml b/desktop_version/lang/tr/strings.xml index 9d4f43d0..154fdc9f 100644 --- a/desktop_version/lang/tr/strings.xml +++ b/desktop_version/lang/tr/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/uk/strings.xml b/desktop_version/lang/uk/strings.xml index e147c6f0..9e01f485 100644 --- a/desktop_version/lang/uk/strings.xml +++ b/desktop_version/lang/uk/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/zh/strings.xml b/desktop_version/lang/zh/strings.xml index 9295329e..ffb521b5 100644 --- a/desktop_version/lang/zh/strings.xml +++ b/desktop_version/lang/zh/strings.xml @@ -46,9 +46,7 @@ - - @@ -136,19 +134,30 @@ + + + + + + + + + + + diff --git a/desktop_version/lang/zh_TW/strings.xml b/desktop_version/lang/zh_TW/strings.xml index 94b34e22..da8af647 100644 --- a/desktop_version/lang/zh_TW/strings.xml +++ b/desktop_version/lang/zh_TW/strings.xml @@ -46,9 +46,7 @@ - - @@ -136,19 +134,30 @@ + + + + + + + + + + + From 0e312538764de215f16ff37ac22ceb68d65379ce Mon Sep 17 00:00:00 2001 From: NyakoFox Date: Sat, 3 May 2025 15:29:24 -0300 Subject: [PATCH 53/64] Fix mouse coordinates being wrong on HiDPI displays When writing the initial stretch mode code, the existence of HiDPI displays completely slipped my mind -- or at least I didn't realize that they'd be a problem. We implement scaling modes ourselves, so transforming the mouse coordinates to our 320x240 viewport is done manually. Unfortunately, that code did not take into account HiDPI scaling whatsoever, meaning that all of the math which assumes the window size and the renderer size is wrong. To fix this, we use `SDL_GetWindowSizeInPixels` and `SDL_GetWindow` to find the scaling factor, and then apply that to the mouse coordinates to get the mouse coordinates in the pixel-space instead, and then we do all of our normal logic after. Due to our usage of `SDL_GetWindowSizeInPixels`, this bumps the minimum SDL version to 2.26.0. Closes #1235. --- .github/workflows/ci.yml | 2 +- desktop_version/src/KeyPoll.cpp | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc814578..7ba9eae1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,7 +101,7 @@ jobs: runs-on: windows-latest env: - SDL_VERSION: 2.24.0 + SDL_VERSION: 2.26.0 steps: - uses: actions/checkout@v1 diff --git a/desktop_version/src/KeyPoll.cpp b/desktop_version/src/KeyPoll.cpp index 44ef3aec..4439d470 100644 --- a/desktop_version/src/KeyPoll.cpp +++ b/desktop_version/src/KeyPoll.cpp @@ -571,8 +571,20 @@ void KeyPoll::Poll(void) SDL_Rect rect; graphics.get_stretch_info(&rect); - mousex = (raw_mousex - rect.x) * SCREEN_WIDTH_PIXELS / rect.w; - mousey = (raw_mousey - rect.y) * SCREEN_HEIGHT_PIXELS / rect.h; + int window_width; + int window_height; + SDL_GetWindowSizeInPixels(gameScreen.m_window, &window_width, &window_height); + + int scaled_window_width; + int scaled_window_height; + SDL_GetWindowSize(gameScreen.m_window, &scaled_window_width, &scaled_window_height); + + float scale_x = (float)window_width / (float)scaled_window_width; + float scale_y = (float)window_height / (float)scaled_window_height; + + // Use screen stretch information to modify the coordinates (as we implement stretching manually) + mousex = ((raw_mousex * scale_x) - rect.x) * SCREEN_WIDTH_PIXELS / rect.w; + mousey = ((raw_mousey * scale_y) - rect.y) * SCREEN_HEIGHT_PIXELS / rect.h; active_input_device_changed = keyboard_was_active != BUTTONGLYPHS_keyboard_is_active(); should_recompute_textboxes |= active_input_device_changed; From 8bf6b25b5b0ced02aefcc49c4dbaf9d13e555950 Mon Sep 17 00:00:00 2001 From: Nate Eagleson Date: Tue, 6 May 2025 21:47:08 -0400 Subject: [PATCH 54/64] Fix typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 477f218f..cdcbf441 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This is the source code to VVVVVV, the 2010 indie game by [Terry Cavanagh](http: The source code for the desktop version is in [this folder](desktop_version). -VVVVVV is still commerically available at [thelettervsixtim.es](https://thelettervsixtim.es/) if you'd like to support it, but you are completely free to compile the game for your own personal use. If you're interested in distributing a compiled version of the game, see [LICENSE.md](LICENSE.md) for more information. +VVVVVV is still commercially available at [thelettervsixtim.es](https://thelettervsixtim.es/) if you'd like to support it, but you are completely free to compile the game for your own personal use. If you're interested in distributing a compiled version of the game, see [LICENSE.md](LICENSE.md) for more information. Discussion about VVVVVV updates mainly happens on the "unofficial" [VVVVVV discord](https://discord.gg/Zf7Nzea), in the `vvvvvv-code` channel. From 902acdd2acfd34f3b3b9d185eec0b7f4859233e6 Mon Sep 17 00:00:00 2001 From: Terry Cavanagh Date: Fri, 9 May 2025 14:40:46 +0100 Subject: [PATCH 55/64] Added PortMaster project to License exceptions --- License exceptions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/License exceptions.md b/License exceptions.md index 4bc88ba3..fbc132f8 100644 --- a/License exceptions.md +++ b/License exceptions.md @@ -21,5 +21,6 @@ Last updated on January 23rd, 2024. | Dreamcast Port | [Gustavo Aranda](https://github.com/gusarba/) | Port for the Sega Dreamcast. | Permission is given to distribute a ready-to-use CD image file for the Sega Dreamcast containing the data.zip assets for non commercial use only. | [github repo](https://github.com/gusarba/VVVVVVDC)| | XBox One/UWP Port | [tunip3](https://github.com/tunip3) | Port for XBOX ONE (DURANGO) via UWP. | Permission is given to distribute a pre-compiled package (containing the data.zip assets) for people to run on development mode xboxes, for non commercial use only. | [github repo](https://github.com/tunip3/DURANGO-V6)| | armhf Port | [johnnyonFlame](https://github.com/johnnyonFlame/) | Armhf port for Raspberry PI and other SBC devices| Permission is for non commercial use only. Display the following text in the readme to make it clear that this is an exception: "VVVVVV is a commercial game! The author has given special permission to make this port available for free. If you enjoy the game, please consider purchasing a copy at [thelettervsixtim.es](http://thelettervsixtim.es)."| [github release](https://github.com/JohnnyonFlame/VVVVVV/releases/tag/v2.4-r1) | +| PortMaster distributions of the game for Linux Handheld devices | [portmaster](https://portmaster.games/) | A port manager GUI for Linux handheld devices | Permission is for non commercial use only. Display the following text in the readme to make it clear that this is an exception: "VVVVVV is a commercial game! The author has given special permission to make this port available for free. If you enjoy the game, please consider purchasing a copy at [thelettervsixtim.es](http://thelettervsixtim.es)."| [website](https://portmaster.games/detail.html?name=vvvvvv) | | Wii Port | [Alberto Mardegan](https://github.com/mardy/) | Port for the Nintendo Wii. | Permission is given to distribute a ready-to-use build for the Nintendo Wii containing the data.zip assets for non commercial use only. | [github repo](https://github.com/mardy/VVVVVV/tree/wii) | | Recalbox Port | [digitalLumberjack](https://gitlab.com/recalbox/recalbox) | Port for Recalbox project. | Display the following text in the readme to make it clear that this is an exception: "VVVVVV is a commercial game! The author has given special permission to make this port available for free. If you enjoy the game, please consider purchasing a copy at [thelettervsixtim.es](http://thelettervsixtim.es)." | [website](https://recalbox.com/) | From 0d16cd136938c4f38c4623ef18eb99aa5bc3fa1b Mon Sep 17 00:00:00 2001 From: David Fisher Date: Tue, 6 May 2025 21:36:21 -0400 Subject: [PATCH 56/64] feat(ci): Enhance GitHub Actions workflow - Update actions/checkout to v4 - Add build caching for macOS and Linux jobs - Implement concurrency control to cancel redundant runs - Restrict GITHUB_TOKEN permissions for security These changes improve CI performance, stability, and security. --- .github/workflows/ci.yml | 53 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ba9eae1..c21fd943 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,14 @@ on: - "third_party/**" - ".github/workflows/ci.yml" +permissions: + contents: read + statuses: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: SRC_DIR_PATH: desktop_version @@ -32,19 +40,42 @@ jobs: env: CXXFLAGS: -I/usr/local/include/SDL2 LDFLAGS: -L/usr/local/lib + HOMEBREW_NO_ENV_HINTS: 1 # Suppress brew update hints steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true + - name: Cache Homebrew packages + id: cache-brew + uses: actions/cache@v3 + with: + path: | + /usr/local/Cellar/ninja + /usr/local/Cellar/sdl2 + /usr/local/opt/sdl2 # Symlink often used + key: ${{ runner.os }}-brew-${{ hashFiles('/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/ninja.rb', '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/sdl2.rb') }} # Using hash of formula files if available, or a fixed key for simplicity if not easily determined + - name: Install dependencies + if: steps.cache-brew.outputs.cache-hit != 'true' run: brew install ninja sdl2 + - name: Cache CMake build folder + id: cache-cmake-build + uses: actions/cache@v3 + with: + path: ${{ env.SRC_DIR_PATH }}/build + key: ${{ runner.os }}-${{ env.container_image_tag }}-cmake-build-${{ hashFiles(format('{0}/CMakeLists.txt', env.SRC_DIR_PATH)) }} + # Using a more specific key including a reference to the container if possible + # We need to define container_image_tag in the env or find a way to get it + - name: CMake configure (default version) run: | - mkdir ${SRC_DIR_PATH}/build && cd ${SRC_DIR_PATH}/build - cmake -GNinja .. + mkdir -p ${SRC_DIR_PATH}/build && cd ${SRC_DIR_PATH}/build + # If cache was hit and build dir exists, this cmake might just verify. + # If build dir is empty, it will configure. + cmake -G Ninja .. - name: Build (default version) run: ninja -C ${SRC_DIR_PATH}/build @@ -68,15 +99,27 @@ jobs: runs-on: ubuntu-latest container: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta + env: + CONTAINER_IMAGE_TAG: beta steps: - uses: actions/checkout@v4 with: submodules: true + - name: Cache CMake build folder + id: cache-cmake-build + uses: actions/cache@v3 + with: + path: ${{ env.SRC_DIR_PATH }}/build + key: ${{ runner.os }}-${{ env.CONTAINER_IMAGE_TAG }}-cmake-build-${{ hashFiles(format('{0}/CMakeLists.txt', env.SRC_DIR_PATH)) }} + # Using a more specific key including a reference to the container + - name: CMake configure (default version) run: | - mkdir ${SRC_DIR_PATH}/build && cd ${SRC_DIR_PATH}/build + mkdir -p ${SRC_DIR_PATH}/build && cd ${SRC_DIR_PATH}/build + # If cache was hit and build dir exists, this cmake might just verify. + # If build dir is empty, it will configure. cmake -G Ninja .. - name: Build (default version) run: ninja -C ${SRC_DIR_PATH}/build @@ -104,7 +147,7 @@ jobs: SDL_VERSION: 2.26.0 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true From 37bb4f30fdc62c3a4a240f698907abca5ca1aa44 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sun, 8 Jun 2025 17:01:45 -0400 Subject: [PATCH 57/64] CI: Remove CMake caching. Seems like the build root can change and CMake rightfully gets confused at the conflicting paths, so let's just use the minutes to do this from scratch. --- .github/workflows/ci.yml | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c21fd943..ef4acc96 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,20 +61,9 @@ jobs: if: steps.cache-brew.outputs.cache-hit != 'true' run: brew install ninja sdl2 - - name: Cache CMake build folder - id: cache-cmake-build - uses: actions/cache@v3 - with: - path: ${{ env.SRC_DIR_PATH }}/build - key: ${{ runner.os }}-${{ env.container_image_tag }}-cmake-build-${{ hashFiles(format('{0}/CMakeLists.txt', env.SRC_DIR_PATH)) }} - # Using a more specific key including a reference to the container if possible - # We need to define container_image_tag in the env or find a way to get it - - name: CMake configure (default version) run: | mkdir -p ${SRC_DIR_PATH}/build && cd ${SRC_DIR_PATH}/build - # If cache was hit and build dir exists, this cmake might just verify. - # If build dir is empty, it will configure. cmake -G Ninja .. - name: Build (default version) run: ninja -C ${SRC_DIR_PATH}/build @@ -107,19 +96,9 @@ jobs: with: submodules: true - - name: Cache CMake build folder - id: cache-cmake-build - uses: actions/cache@v3 - with: - path: ${{ env.SRC_DIR_PATH }}/build - key: ${{ runner.os }}-${{ env.CONTAINER_IMAGE_TAG }}-cmake-build-${{ hashFiles(format('{0}/CMakeLists.txt', env.SRC_DIR_PATH)) }} - # Using a more specific key including a reference to the container - - name: CMake configure (default version) run: | mkdir -p ${SRC_DIR_PATH}/build && cd ${SRC_DIR_PATH}/build - # If cache was hit and build dir exists, this cmake might just verify. - # If build dir is empty, it will configure. cmake -G Ninja .. - name: Build (default version) run: ninja -C ${SRC_DIR_PATH}/build @@ -166,19 +145,7 @@ jobs: Invoke-WebRequest "https://github.com/libsdl-org/SDL/releases/download/release-$env:SDL_VERSION/SDL2-devel-$env:SDL_VERSION-VC.zip" -OutFile C:\SDL.zip Expand-Archive C:\SDL.zip -DestinationPath C:\ - - name: Cache build folder for this CMakeLists.txt - id: cache-windows-build-folder - uses: actions/cache@v3 - env: - cache-name: cache-windows-build-folder-VS2022 - with: - path: | - desktop_version/build - desktop_version/CMakeLists.txt - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('desktop_version/CMakeLists.txt') }}-SDL${{ env.SDL_VERSION }} - - - if: ${{ steps.cache-windows-build-folder.outputs.cache-hit != 'true' }} - name: CMake initial configure/generate + - name: CMake initial configure/generate run: | mkdir $env:SRC_DIR_PATH/build cd $env:SRC_DIR_PATH/build From 70cbde18feee4c85987a42da32ade47ded988ba4 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sun, 8 Jun 2025 17:03:46 -0400 Subject: [PATCH 58/64] CI: Move Sniper SDK from beta to latest. This was a carryover from FNA when I was doing the initial move to SDL3; VVV won't have to care about this now that 3.2.0 has been out for a while. --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef4acc96..446b49df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,9 +87,7 @@ jobs: name: Build (Steam Linux Runtime Sniper) runs-on: ubuntu-latest - container: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta - env: - CONTAINER_IMAGE_TAG: beta + container: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest steps: - uses: actions/checkout@v4 From 26d27c7df58fb7b402c66933ecba28875f5936bd Mon Sep 17 00:00:00 2001 From: Dav999 Date: Sat, 3 May 2025 18:58:10 +0200 Subject: [PATCH 59/64] Apply translations for 2.4 strings This includes translations that were missing translations, with varying extent between different languages, for the following things: - "X mode is enabled" in-game warnings - "Press {button} to freeze/unfreeze gameplay" for the level debugger - Some credits strings for the post-2.4.0 extra Spanish options, the PT_BR proofread, and Persian - The recent gamepad menu changes (#1229) Furthermore: - "TAB" (used in the level debugger string) is now a separate string instead of being hardcoded, because some languages needed it translated - Added missing arrows to Arabic/Persian font (needed for the gamepad menu, and also a translator menu actually) --- desktop_version/fonts/font_ar.fontmeta | 1 + desktop_version/fonts/font_ar.png | Bin 2857 -> 3232 bytes desktop_version/lang/ar/strings.xml | 11 ++-- desktop_version/lang/ca/strings.xml | 43 ++++++++-------- desktop_version/lang/cy/strings.xml | 49 +++++++++--------- desktop_version/lang/de/strings.xml | 43 ++++++++-------- desktop_version/lang/en/strings.xml | 1 + desktop_version/lang/eo/strings.xml | 3 +- desktop_version/lang/es/strings.xml | 25 ++++----- desktop_version/lang/es_419/strings.xml | 25 ++++----- desktop_version/lang/es_AR/strings.xml | 25 ++++----- desktop_version/lang/fa/strings.xml | 14 ++++- desktop_version/lang/fr/strings.xml | 65 ++++++++++++------------ desktop_version/lang/ga/strings.xml | 53 +++++++++---------- desktop_version/lang/it/strings.xml | 43 ++++++++-------- desktop_version/lang/ja/strings.xml | 25 ++++----- desktop_version/lang/ko/strings.xml | 21 ++++---- desktop_version/lang/nl/strings.xml | 3 +- desktop_version/lang/pl/strings.xml | 63 ++++++++++++----------- desktop_version/lang/pt_BR/strings.xml | 25 ++++----- desktop_version/lang/pt_PT/strings.xml | 21 ++++---- desktop_version/lang/ru/strings.xml | 21 ++++---- desktop_version/lang/szl/strings.xml | 65 ++++++++++++------------ desktop_version/lang/tr/strings.xml | 21 ++++---- desktop_version/lang/uk/strings.xml | 43 ++++++++-------- desktop_version/lang/zh/strings.xml | 21 ++++---- desktop_version/lang/zh_TW/strings.xml | 21 ++++---- desktop_version/src/LevelDebugger.cpp | 2 +- 28 files changed, 394 insertions(+), 359 deletions(-) diff --git a/desktop_version/fonts/font_ar.fontmeta b/desktop_version/fonts/font_ar.fontmeta index 9ca2556b..0f6c09df 100644 --- a/desktop_version/fonts/font_ar.fontmeta +++ b/desktop_version/fonts/font_ar.fontmeta @@ -10,6 +10,7 @@ + diff --git a/desktop_version/fonts/font_ar.png b/desktop_version/fonts/font_ar.png index 3d02abc38cdfbdde2a6f78be728877b651023e26..3e6e8d797ea2495a294c0059ca57895f07b4ea71 100644 GIT binary patch literal 3232 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 Hu0mjfo32{c diff --git a/desktop_version/lang/ar/strings.xml b/desktop_version/lang/ar/strings.xml index 6bda7700..0e80d24b 100644 --- a/desktop_version/lang/ar/strings.xml +++ b/desktop_version/lang/ar/strings.xml @@ -233,6 +233,7 @@ + @@ -787,7 +788,7 @@ You have found the secret lab!" translation="تهانينا! - + @@ -809,10 +810,10 @@ You have found the secret lab!" translation="تهانينا! - - - - + + + + diff --git a/desktop_version/lang/ca/strings.xml b/desktop_version/lang/ca/strings.xml index ed86a9ba..47d37013 100644 --- a/desktop_version/lang/ca/strings.xml +++ b/desktop_version/lang/ca/strings.xml @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,7 +780,7 @@ Has trobat el laboratori secret!" explanation="" max="34*4"/> - + @@ -801,10 +802,10 @@ Has trobat el laboratori secret!" explanation="" max="34*4"/> - - - - + + + + diff --git a/desktop_version/lang/cy/strings.xml b/desktop_version/lang/cy/strings.xml index 7c74db23..2d6d1fca 100644 --- a/desktop_version/lang/cy/strings.xml +++ b/desktop_version/lang/cy/strings.xml @@ -133,30 +133,30 @@ - - + + - - - + + + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -295,7 +296,7 @@ - + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,7 +780,7 @@ Rwyt ti wedi dod o hyd i'r labordy cyfrinachol!" explanation="" max="34*4"/ - + @@ -801,10 +802,10 @@ Rwyt ti wedi dod o hyd i'r labordy cyfrinachol!" explanation="" max="34*4"/ - - - - + + + + diff --git a/desktop_version/lang/de/strings.xml b/desktop_version/lang/de/strings.xml index 528bdce6..5ff471b0 100644 --- a/desktop_version/lang/de/strings.xml +++ b/desktop_version/lang/de/strings.xml @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,7 +780,7 @@ Du hast das Geheimlabor gefunden!" explanation="" max="34*4"/> - + @@ -801,10 +802,10 @@ Du hast das Geheimlabor gefunden!" explanation="" max="34*4"/> - - - - + + + + diff --git a/desktop_version/lang/en/strings.xml b/desktop_version/lang/en/strings.xml index a4f701b6..45154fc9 100644 --- a/desktop_version/lang/en/strings.xml +++ b/desktop_version/lang/en/strings.xml @@ -229,6 +229,7 @@ + diff --git a/desktop_version/lang/eo/strings.xml b/desktop_version/lang/eo/strings.xml index 5b6b8c37..1cb635ff 100644 --- a/desktop_version/lang/eo/strings.xml +++ b/desktop_version/lang/eo/strings.xml @@ -229,6 +229,7 @@ + @@ -804,7 +805,7 @@ Vi trovis la sekretan labon!" explanation="" max="34*4"/> - + diff --git a/desktop_version/lang/es/strings.xml b/desktop_version/lang/es/strings.xml index 048194d3..e9266203 100644 --- a/desktop_version/lang/es/strings.xml +++ b/desktop_version/lang/es/strings.xml @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -804,7 +805,7 @@ You have found the secret lab!" translation="¡Enhorabuena! - + diff --git a/desktop_version/lang/es_419/strings.xml b/desktop_version/lang/es_419/strings.xml index 2e89862f..fe91b449 100644 --- a/desktop_version/lang/es_419/strings.xml +++ b/desktop_version/lang/es_419/strings.xml @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -804,7 +805,7 @@ You have found the secret lab!" translation="¡Felicitaciones! - + diff --git a/desktop_version/lang/es_AR/strings.xml b/desktop_version/lang/es_AR/strings.xml index 0df8391e..89f7a358 100644 --- a/desktop_version/lang/es_AR/strings.xml +++ b/desktop_version/lang/es_AR/strings.xml @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -804,7 +805,7 @@ You have found the secret lab!" translation="¡Felicitaciones! - + diff --git a/desktop_version/lang/fa/strings.xml b/desktop_version/lang/fa/strings.xml index 3c0c5902..d81835a8 100644 --- a/desktop_version/lang/fa/strings.xml +++ b/desktop_version/lang/fa/strings.xml @@ -46,9 +46,7 @@ - - @@ -135,19 +133,30 @@ + + + + + + + + + + + @@ -220,6 +229,7 @@ + diff --git a/desktop_version/lang/fr/strings.xml b/desktop_version/lang/fr/strings.xml index b0a3f9b1..46fc4c5d 100644 --- a/desktop_version/lang/fr/strings.xml +++ b/desktop_version/lang/fr/strings.xml @@ -133,30 +133,30 @@ - - + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -545,7 +546,7 @@ - + @@ -779,7 +780,7 @@ Vous avez trouvé le labo secret !" explanation="" max="34*4"/> - + @@ -801,10 +802,10 @@ Vous avez trouvé le labo secret !" explanation="" max="34*4"/> - - - - + + + + diff --git a/desktop_version/lang/ga/strings.xml b/desktop_version/lang/ga/strings.xml index 2725864a..db829832 100644 --- a/desktop_version/lang/ga/strings.xml +++ b/desktop_version/lang/ga/strings.xml @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -230,6 +230,7 @@ Déan cóip chúltaca, ar eagla na heagla." explanation="translation maintenance + @@ -332,9 +333,9 @@ Déan cóip chúltaca, ar eagla na heagla." explanation="translation maintenance - - - + + + @@ -452,8 +453,8 @@ Déan cóip chúltaca, ar eagla na heagla." explanation="translation maintenance - - + + @@ -608,7 +609,7 @@ Déan cóip chúltaca, ar eagla na heagla." explanation="translation maintenance - + @@ -655,7 +656,7 @@ Déan cóip chúltaca, ar eagla na heagla." explanation="translation maintenance - + @@ -694,7 +695,7 @@ Fuair tú ornáid lonrach!" explanation="" max="34*4"/> You have found a lost crewmate!" translation="Comhghairdeas! -Fuair tú leathbhádóir a bhí ar strae!" explanation="" max="34*4"/> +Fuair tú loingseoir a bhí ar strae!" explanation="" max="34*4"/> - + - + @@ -781,7 +782,7 @@ Fuair tú an tsaotharlann rúnda!" explanation="" max="34*4"/> - + @@ -803,10 +804,10 @@ Fuair tú an tsaotharlann rúnda!" explanation="" max="34*4"/> - - - - + + + + diff --git a/desktop_version/lang/it/strings.xml b/desktop_version/lang/it/strings.xml index 2fcd37b7..ebd3f200 100644 --- a/desktop_version/lang/it/strings.xml +++ b/desktop_version/lang/it/strings.xml @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,7 +780,7 @@ Hai trovato il laboratorio segreto!" explanation="" max="34*4"/> - + @@ -801,10 +802,10 @@ Hai trovato il laboratorio segreto!" explanation="" max="34*4"/> - - - - + + + + diff --git a/desktop_version/lang/ja/strings.xml b/desktop_version/lang/ja/strings.xml index 834afe4d..47ab8604 100644 --- a/desktop_version/lang/ja/strings.xml +++ b/desktop_version/lang/ja/strings.xml @@ -140,30 +140,30 @@ OFFにしますか?" explanation="" max="38*6" max_local="38*5"/> - - + + - + - + - + - + - + - - - - + + + + @@ -243,6 +243,7 @@ Escキーを押すと表示を終了する。" explanation="" max="38*6" max_loc + @@ -870,7 +871,7 @@ You have found the secret lab!" translation="よくやった! - + diff --git a/desktop_version/lang/ko/strings.xml b/desktop_version/lang/ko/strings.xml index f1a3a205..675ab7c3 100755 --- a/desktop_version/lang/ko/strings.xml +++ b/desktop_version/lang/ko/strings.xml @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,7 +780,7 @@ You have found the secret lab!" translation="축하합니다! - + @@ -801,10 +802,10 @@ You have found the secret lab!" translation="축하합니다! - - - - + + + + diff --git a/desktop_version/lang/nl/strings.xml b/desktop_version/lang/nl/strings.xml index 770f988b..b28e560a 100644 --- a/desktop_version/lang/nl/strings.xml +++ b/desktop_version/lang/nl/strings.xml @@ -229,6 +229,7 @@ + @@ -805,7 +806,7 @@ Je hebt het geheime lab gevonden!" explanation="" max="34*4"/> - + diff --git a/desktop_version/lang/pl/strings.xml b/desktop_version/lang/pl/strings.xml index ca27b53e..9504a525 100644 --- a/desktop_version/lang/pl/strings.xml +++ b/desktop_version/lang/pl/strings.xml @@ -122,7 +122,7 @@ - + @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,32 +780,32 @@ Znaleziono tajne laboratorium!" explanation="" max="34*4"/> - + - + - + - - - + + + - + - - - - - - - + + + + + + + diff --git a/desktop_version/lang/pt_BR/strings.xml b/desktop_version/lang/pt_BR/strings.xml index ad9ffe4e..aac2f1fc 100644 --- a/desktop_version/lang/pt_BR/strings.xml +++ b/desktop_version/lang/pt_BR/strings.xml @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -804,7 +805,7 @@ Você encontrou o laboratório secreto!" explanation="" max="34*4"/> - + diff --git a/desktop_version/lang/pt_PT/strings.xml b/desktop_version/lang/pt_PT/strings.xml index ab0aef48..018c1854 100644 --- a/desktop_version/lang/pt_PT/strings.xml +++ b/desktop_version/lang/pt_PT/strings.xml @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,7 +780,7 @@ Encontraste o laboratório secreto!" explanation="" max="34*4"/> - + @@ -801,10 +802,10 @@ Encontraste o laboratório secreto!" explanation="" max="34*4"/> - - - - + + + + diff --git a/desktop_version/lang/ru/strings.xml b/desktop_version/lang/ru/strings.xml index 52b02b4b..e61db94d 100644 --- a/desktop_version/lang/ru/strings.xml +++ b/desktop_version/lang/ru/strings.xml @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -804,7 +805,7 @@ You have found the secret lab!" translation="Поздравляем! - + @@ -826,10 +827,10 @@ You have found the secret lab!" translation="Поздравляем! - - - - + + + + diff --git a/desktop_version/lang/szl/strings.xml b/desktop_version/lang/szl/strings.xml index c86a963a..46f52928 100644 --- a/desktop_version/lang/szl/strings.xml +++ b/desktop_version/lang/szl/strings.xml @@ -122,7 +122,7 @@ - + @@ -132,31 +132,31 @@ - - - + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,7 +780,7 @@ Wysznupano tajne laboratoriōm!" explanation="" max="34*4"/> - + @@ -802,9 +803,9 @@ Wysznupano tajne laboratoriōm!" explanation="" max="34*4"/> - - - + + + diff --git a/desktop_version/lang/tr/strings.xml b/desktop_version/lang/tr/strings.xml index 154fdc9f..9c4e104a 100644 --- a/desktop_version/lang/tr/strings.xml +++ b/desktop_version/lang/tr/strings.xml @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,7 +780,7 @@ Gizli laboratuvarı buldun!" explanation="" max="34*4"/> - + @@ -801,10 +802,10 @@ Gizli laboratuvarı buldun!" explanation="" max="34*4"/> - - - - + + + + diff --git a/desktop_version/lang/uk/strings.xml b/desktop_version/lang/uk/strings.xml index 9e01f485..c335d7d3 100644 --- a/desktop_version/lang/uk/strings.xml +++ b/desktop_version/lang/uk/strings.xml @@ -133,30 +133,30 @@ - - + + - + - + - + - + - + - - - - + + + + @@ -229,6 +229,7 @@ + @@ -331,9 +332,9 @@ - - - + + + @@ -450,8 +451,8 @@ - - + + @@ -779,7 +780,7 @@ You have found the secret lab!" translation="Поздоровляємо! - + @@ -801,10 +802,10 @@ You have found the secret lab!" translation="Поздоровляємо! - - - - + + + + diff --git a/desktop_version/lang/zh/strings.xml b/desktop_version/lang/zh/strings.xml index ffb521b5..d10f60c5 100644 --- a/desktop_version/lang/zh/strings.xml +++ b/desktop_version/lang/zh/strings.xml @@ -235,6 +235,7 @@ + @@ -338,9 +339,9 @@ - - - + + + @@ -460,8 +461,8 @@ - - + + @@ -789,7 +790,7 @@ You have found the secret lab!" translation="恭喜你! - + @@ -811,10 +812,10 @@ You have found the secret lab!" translation="恭喜你! - - - - + + + + diff --git a/desktop_version/lang/zh_TW/strings.xml b/desktop_version/lang/zh_TW/strings.xml index da8af647..e3bd3d7f 100644 --- a/desktop_version/lang/zh_TW/strings.xml +++ b/desktop_version/lang/zh_TW/strings.xml @@ -235,6 +235,7 @@ + @@ -338,9 +339,9 @@ - - - + + + @@ -460,8 +461,8 @@ - - + + @@ -789,7 +790,7 @@ You have found the secret lab!" translation="恭喜你! - + @@ -811,10 +812,10 @@ You have found the secret lab!" translation="恭喜你! - - - - + + + + diff --git a/desktop_version/src/LevelDebugger.cpp b/desktop_version/src/LevelDebugger.cpp index b180b704..ff16badb 100644 --- a/desktop_version/src/LevelDebugger.cpp +++ b/desktop_version/src/LevelDebugger.cpp @@ -461,7 +461,7 @@ namespace level_debugger buffer, sizeof(buffer), text, "button:str", - "TAB" + loc::gettext("TAB") ); font::print(PR_BOR, 5, 14, buffer, 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2)); From 7dccc2d328a5e5aa57679042a9d6d918aae0d6e5 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Mon, 28 Apr 2025 23:47:49 +0200 Subject: [PATCH 60/64] Apply translations for 2.5 strings This includes translations for checkpoint saving and enemy speed in the editor. --- desktop_version/lang/ar/strings.xml | 12 ++++++------ desktop_version/lang/ca/strings.xml | 12 ++++++------ desktop_version/lang/cy/strings.xml | 12 ++++++------ desktop_version/lang/de/strings.xml | 12 ++++++------ desktop_version/lang/eo/strings.xml | 12 ++++++------ desktop_version/lang/es/strings.xml | 12 ++++++------ desktop_version/lang/es_419/strings.xml | 12 ++++++------ desktop_version/lang/es_AR/strings.xml | 12 ++++++------ desktop_version/lang/fr/strings.xml | 12 ++++++------ desktop_version/lang/ga/strings.xml | 12 ++++++------ desktop_version/lang/it/strings.xml | 12 ++++++------ desktop_version/lang/ja/strings.xml | 12 ++++++------ desktop_version/lang/ko/strings.xml | 12 ++++++------ desktop_version/lang/nl/strings.xml | 12 ++++++------ desktop_version/lang/pl/strings.xml | 12 ++++++------ desktop_version/lang/pt_BR/strings.xml | 12 ++++++------ desktop_version/lang/pt_PT/strings.xml | 12 ++++++------ desktop_version/lang/ru/strings.xml | 12 ++++++------ desktop_version/lang/szl/strings.xml | 12 ++++++------ desktop_version/lang/tr/strings.xml | 12 ++++++------ desktop_version/lang/uk/strings.xml | 12 ++++++------ desktop_version/lang/zh/strings.xml | 12 ++++++------ desktop_version/lang/zh_TW/strings.xml | 12 ++++++------ 23 files changed, 138 insertions(+), 138 deletions(-) diff --git a/desktop_version/lang/ar/strings.xml b/desktop_version/lang/ar/strings.xml index 0e80d24b..e2dd70db 100644 --- a/desktop_version/lang/ar/strings.xml +++ b/desktop_version/lang/ar/strings.xml @@ -246,11 +246,11 @@ - - - - - + + + + + - + diff --git a/desktop_version/lang/ca/strings.xml b/desktop_version/lang/ca/strings.xml index 47d37013..29d89131 100644 --- a/desktop_version/lang/ca/strings.xml +++ b/desktop_version/lang/ca/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/cy/strings.xml b/desktop_version/lang/cy/strings.xml index 2d6d1fca..d9aa1816 100644 --- a/desktop_version/lang/cy/strings.xml +++ b/desktop_version/lang/cy/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/de/strings.xml b/desktop_version/lang/de/strings.xml index 5ff471b0..979aaad6 100644 --- a/desktop_version/lang/de/strings.xml +++ b/desktop_version/lang/de/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/eo/strings.xml b/desktop_version/lang/eo/strings.xml index 1cb635ff..735fe1e7 100644 --- a/desktop_version/lang/eo/strings.xml +++ b/desktop_version/lang/eo/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/es/strings.xml b/desktop_version/lang/es/strings.xml index e9266203..4ad7b06c 100644 --- a/desktop_version/lang/es/strings.xml +++ b/desktop_version/lang/es/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/es_419/strings.xml b/desktop_version/lang/es_419/strings.xml index fe91b449..5c316b44 100644 --- a/desktop_version/lang/es_419/strings.xml +++ b/desktop_version/lang/es_419/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/es_AR/strings.xml b/desktop_version/lang/es_AR/strings.xml index 89f7a358..66d225b2 100644 --- a/desktop_version/lang/es_AR/strings.xml +++ b/desktop_version/lang/es_AR/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/fr/strings.xml b/desktop_version/lang/fr/strings.xml index 46fc4c5d..8cfd849f 100644 --- a/desktop_version/lang/fr/strings.xml +++ b/desktop_version/lang/fr/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/ga/strings.xml b/desktop_version/lang/ga/strings.xml index db829832..625d9d6e 100644 --- a/desktop_version/lang/ga/strings.xml +++ b/desktop_version/lang/ga/strings.xml @@ -243,11 +243,11 @@ Déan cóip chúltaca, ar eagla na heagla." explanation="translation maintenance - - - - - + + + + + @@ -639,7 +639,7 @@ Déan cóip chúltaca, ar eagla na heagla." explanation="translation maintenance - + diff --git a/desktop_version/lang/it/strings.xml b/desktop_version/lang/it/strings.xml index ebd3f200..5075f520 100644 --- a/desktop_version/lang/it/strings.xml +++ b/desktop_version/lang/it/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/ja/strings.xml b/desktop_version/lang/ja/strings.xml index 47ab8604..166d1b58 100644 --- a/desktop_version/lang/ja/strings.xml +++ b/desktop_version/lang/ja/strings.xml @@ -256,11 +256,11 @@ Escキーを押すと表示を終了する。" explanation="" max="38*6" max_loc - - - - - + + + + + @@ -673,7 +673,7 @@ Steam Deckには対応していません。" explanation="" max="38*5" max_local - + diff --git a/desktop_version/lang/ko/strings.xml b/desktop_version/lang/ko/strings.xml index 675ab7c3..9d47d4ec 100755 --- a/desktop_version/lang/ko/strings.xml +++ b/desktop_version/lang/ko/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/nl/strings.xml b/desktop_version/lang/nl/strings.xml index b28e560a..4dd6a972 100644 --- a/desktop_version/lang/nl/strings.xml +++ b/desktop_version/lang/nl/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/pl/strings.xml b/desktop_version/lang/pl/strings.xml index 9504a525..c0c44798 100644 --- a/desktop_version/lang/pl/strings.xml +++ b/desktop_version/lang/pl/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/pt_BR/strings.xml b/desktop_version/lang/pt_BR/strings.xml index aac2f1fc..1a01283f 100644 --- a/desktop_version/lang/pt_BR/strings.xml +++ b/desktop_version/lang/pt_BR/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/pt_PT/strings.xml b/desktop_version/lang/pt_PT/strings.xml index 018c1854..3d009543 100644 --- a/desktop_version/lang/pt_PT/strings.xml +++ b/desktop_version/lang/pt_PT/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/ru/strings.xml b/desktop_version/lang/ru/strings.xml index e61db94d..d412935e 100644 --- a/desktop_version/lang/ru/strings.xml +++ b/desktop_version/lang/ru/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -662,7 +662,7 @@ - + diff --git a/desktop_version/lang/szl/strings.xml b/desktop_version/lang/szl/strings.xml index 46f52928..df9585b3 100644 --- a/desktop_version/lang/szl/strings.xml +++ b/desktop_version/lang/szl/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/tr/strings.xml b/desktop_version/lang/tr/strings.xml index 9c4e104a..5a8817f5 100644 --- a/desktop_version/lang/tr/strings.xml +++ b/desktop_version/lang/tr/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/uk/strings.xml b/desktop_version/lang/uk/strings.xml index c335d7d3..75ec7058 100644 --- a/desktop_version/lang/uk/strings.xml +++ b/desktop_version/lang/uk/strings.xml @@ -242,11 +242,11 @@ - - - - - + + + + + @@ -637,7 +637,7 @@ - + diff --git a/desktop_version/lang/zh/strings.xml b/desktop_version/lang/zh/strings.xml index d10f60c5..1487c97c 100644 --- a/desktop_version/lang/zh/strings.xml +++ b/desktop_version/lang/zh/strings.xml @@ -248,11 +248,11 @@ - - - - - + + + + + @@ -647,7 +647,7 @@ - + diff --git a/desktop_version/lang/zh_TW/strings.xml b/desktop_version/lang/zh_TW/strings.xml index e3bd3d7f..cb176772 100644 --- a/desktop_version/lang/zh_TW/strings.xml +++ b/desktop_version/lang/zh_TW/strings.xml @@ -248,11 +248,11 @@ - - - - - + + + + + @@ -647,7 +647,7 @@ - + From d53861553e68fe3b249137c1a8a46c73805126f8 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Tue, 10 Jun 2025 16:21:21 +0200 Subject: [PATCH 61/64] Update SheenBidi to 2.9.0 This fixes our problem with Valgrind reporting a jump based on an uninitialized value; see https://github.com/Tehreer/SheenBidi/issues/19 Just to be sure nothing unexpected happens, I tested that this doesn't cause any changes in behavior by outputting bidi-transformed versions of all strings in strings.xml to a file for both our Arabic and Persian localizations before and after the update, and confirming that the files are the same. --- desktop_version/src/FontBidi.cpp | 2 +- third_party/SheenBidi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/desktop_version/src/FontBidi.cpp b/desktop_version/src/FontBidi.cpp index 5c4d948d..6f09b3fe 100644 --- a/desktop_version/src/FontBidi.cpp +++ b/desktop_version/src/FontBidi.cpp @@ -1,6 +1,7 @@ #include "FontBidi.h" #include +#include #include "Alloc.h" #include "UTF8.h" @@ -8,7 +9,6 @@ extern "C" { #include -#include } namespace font diff --git a/third_party/SheenBidi b/third_party/SheenBidi index e667eb3a..83f77108 160000 --- a/third_party/SheenBidi +++ b/third_party/SheenBidi @@ -1 +1 @@ -Subproject commit e667eb3a63ee704194f8d94834d8e12b18db5b21 +Subproject commit 83f77108a2873600283f6da4b326a2dca7a3a7a6 From 65b024a9a3d617227e59c08659f0d2d99cbda561 Mon Sep 17 00:00:00 2001 From: Dav999 Date: Sun, 15 Jun 2025 19:54:39 +0200 Subject: [PATCH 62/64] Fix vertical position of Comms Relay textbox Fixes #1242. Turns out it was a really simple fix - the X positions were good, but the Y positions were always at the top of the screen regardless of the height of the textbox. Now they're vertically centered respective to the speaker. --- desktop_version/src/Graphics.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index 8841a69e..6df6c6f7 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -3402,6 +3402,7 @@ static void commsrelay_textbox(textboxclass* THIS) THIS->wrap(11); THIS->resize(); THIS->xp = 224 - THIS->w; + THIS->yp = 32 - THIS->h/2; } void Graphics::textboxcommsrelay(const char* text) From 6ae4de1f94e294612e5f7a3a677e8461d7d07f1f Mon Sep 17 00:00:00 2001 From: leo60228 Date: Thu, 19 Jun 2025 13:07:14 -0400 Subject: [PATCH 63/64] Fix TARGET_OS_IPHONE checks --- desktop_version/src/ButtonGlyphs.cpp | 2 +- desktop_version/src/FileSystemUtils.cpp | 2 +- desktop_version/src/Game.cpp | 2 +- desktop_version/src/Screen.cpp | 2 +- desktop_version/src/Vlogging.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop_version/src/ButtonGlyphs.cpp b/desktop_version/src/ButtonGlyphs.cpp index 3060fd42..82610025 100644 --- a/desktop_version/src/ButtonGlyphs.cpp +++ b/desktop_version/src/ButtonGlyphs.cpp @@ -178,7 +178,7 @@ bool BUTTONGLYPHS_keyboard_is_available(void) return true; } -#if defined(__ANDROID__) || defined(TARGET_OS_IPHONE) +#if defined(__ANDROID__) || TARGET_OS_IPHONE return false; #else return !SDL_GetHintBoolean("SteamDeck", SDL_FALSE); diff --git a/desktop_version/src/FileSystemUtils.cpp b/desktop_version/src/FileSystemUtils.cpp index cd3e6e2c..beb41917 100644 --- a/desktop_version/src/FileSystemUtils.cpp +++ b/desktop_version/src/FileSystemUtils.cpp @@ -1331,7 +1331,7 @@ static int PLATFORM_getOSDirectory(char* output, const size_t output_size) } SDL_snprintf(output, output_size, "%s/", externalStoragePath); return 1; -#elif defined(TARGET_OS_IPHONE) +#elif TARGET_OS_IPHONE // (ab)use SDL APIs to get the path to the Documents folder without needing Objective-C const char* prefsPath = SDL_GetPrefPath("", ""); if (prefsPath == NULL) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 196c4d54..d41d63c9 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -381,7 +381,7 @@ void Game::init(void) screenshot_border_timer = 0; screenshot_saved_success = false; -#if defined(__ANDROID__) || defined(TARGET_OS_IPHONE) +#if defined(__ANDROID__) || TARGET_OS_IPHONE checkpoint_saving = true; #else checkpoint_saving = false; diff --git a/desktop_version/src/Screen.cpp b/desktop_version/src/Screen.cpp index 6dabc8ba..1bc4c29a 100644 --- a/desktop_version/src/Screen.cpp +++ b/desktop_version/src/Screen.cpp @@ -383,7 +383,7 @@ bool Screen::isForcedFullscreen(void) * If you're working on a tenfoot-only build, add a def that always * returns true! */ -#if defined(__ANDROID__) || defined(TARGET_OS_IPHONE) +#if defined(__ANDROID__) || TARGET_OS_IPHONE return true; #else return SDL_GetHintBoolean("SteamTenfoot", SDL_FALSE); diff --git a/desktop_version/src/Vlogging.c b/desktop_version/src/Vlogging.c index 8a3a730a..15c6a69a 100644 --- a/desktop_version/src/Vlogging.c +++ b/desktop_version/src/Vlogging.c @@ -3,7 +3,7 @@ #include #include -#if defined(__ANDROID__) || defined(TARGET_OS_IPHONE) +#if defined(__ANDROID__) || TARGET_OS_IPHONE // forward to SDL logging on Android, since stdout/stderr are /dev/null // they exist on iOS, but just get forwarded to the system log anyway, so might as well provide proper metadata #define VLOG_USE_SDL 1 From cd26810e9a8b2dbee130787fd51e2cd61829fb11 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sat, 5 Jul 2025 18:07:45 -0400 Subject: [PATCH 64/64] CMake: Use rpath, not runpath --- desktop_version/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop_version/CMakeLists.txt b/desktop_version/CMakeLists.txt index bc316c5e..26d191d4 100644 --- a/desktop_version/CMakeLists.txt +++ b/desktop_version/CMakeLists.txt @@ -59,6 +59,7 @@ if(NOT WIN32) elseif(CMAKE_SIZEOF_VOID_P MATCHES "8") set(BIN_LIBROOT "lib64") set(BIN_RPATH "\$ORIGIN/lib64") + set(CMAKE_EXE_LINKER_FLAGS "-Wl,--disable-new-dtags") else() set(BIN_LIBROOT "lib") set(BIN_RPATH "\$ORIGIN/lib")

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