From 1bf2d307439f42898a6a40bee537c1c03cfe3995 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:33:14 +0200 Subject: [PATCH 01/16] work on logic stuff --- src/game_api/state_structs.hpp | 137 ++++++++++++++++----------------- 1 file changed, 68 insertions(+), 69 deletions(-) diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index dd820d06c..cdb8d2f46 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -8,6 +8,7 @@ #include class Entity; +struct SoundMeta; struct RobinHoodTableEntry { @@ -426,56 +427,53 @@ class Logic class LogicOuroboros : public Logic { public: - size_t unknown3; // sound related? - uint16_t timer; - - virtual ~LogicOuroboros() = 0; + SoundMeta* sound; + uint32_t timer; }; class LogicBasecampSpeedrun : public Logic { public: - uint32_t official; // entity uid of the character that keeps the time - uint32_t crate; // entity uid; you must break this crate for the run to be valid, otherwise you're cheating - uint32_t unknown3; - uint32_t unknown4; - - virtual ~LogicBasecampSpeedrun() = 0; + /// entity uid of the character that keeps the time + uint32_t official; + /// entity uid. you must break this crate for the run to be valid, otherwise you're cheating + uint32_t crate; }; class LogicGhostToast : public Logic { public: uint32_t toast_timer; - - virtual ~LogicGhostToast() = 0; }; class LogicDiceShop : public Logic { public: - uint32_t boss; // entity uid; either tusk or the shopkeeper - uint32_t unknown4; - uint32_t bet_machine; // entity uid - uint32_t die1; // entity uid - uint32_t die2; // entity uid + uint32_t boss_uid; // either tusk or the shopkeeper + ENT_TYPE boss_type; + /// entity uid + uint32_t bet_machine; + /// entity uid + uint32_t die1; + /// entity uid + uint32_t die2; int8_t die_1_value; int8_t die_2_value; uint16_t unknown8; - uint32_t prize_dispenser; // entity uid - uint32_t prize; // entity uid - uint32_t forcefield; // entity uid + /// entity uid + uint32_t prize_dispenser; + /// entity uid + uint32_t prize; + /// entity uid + uint32_t forcefield; bool bet_active; bool forcefield_deactivated; bool boss_angry; uint8_t result_announcement_timer; // the time the boss waits after your second die throw to announce the results uint8_t won_prizes_count; // to see whether you achieved high roller status - uint8_t unknown14; - uint8_t unknown15; - uint8_t unknown16; + uint8_t padding[3]; int32_t balance; // cash balance of all the games - - virtual ~LogicDiceShop() = 0; + size_t unknown17; }; class LogicMoonChallenge : public Logic @@ -491,8 +489,6 @@ class LogicMoonChallenge : public Logic uint16_t unknown8a; uint16_t unknown8b; uint32_t mattock; // entity uid - - virtual ~LogicMoonChallenge() = 0; }; class LogicStarChallenge : public Logic @@ -507,9 +503,11 @@ class LogicStarChallenge : public Logic uint16_t unknown7; uint32_t unknown8; std::vector torches; - uint32_t start_countdown; - - virtual ~LogicStarChallenge() = 0; + uint8_t start_countdown; + uint8_t padding[3]; + uint32_t unknown9; + float unknown10; // position in from of tun and one tile higher, dunno what for? + float unknown11; }; class LogicSunChallenge : public Logic @@ -524,8 +522,10 @@ class LogicSunChallenge : public Logic uint16_t unknown7; uint32_t unknown8; uint8_t start_countdown; - - virtual ~LogicSunChallenge() = 0; + uint8_t padding[3]; + uint32_t unknown9; + float unknown10; // position in from of tun and one tile higher, dunno what for? + float unknown11; }; class LogicOlmecCutscene : public Logic @@ -544,8 +544,6 @@ class LogicOlmecCutscene : public Logic Entity* player; Entity* cinematic_anchor; uint32_t timer; - - virtual ~LogicOlmecCutscene() = 0; }; class LogicTiamatCutscene : public Logic @@ -560,8 +558,6 @@ class LogicTiamatCutscene : public Logic int32_t unknown5; uint32_t unknown6; uint32_t unknown7; - - virtual ~LogicTiamatCutscene() = 0; }; class LogicApepTrigger : public Logic @@ -570,34 +566,25 @@ class LogicApepTrigger : public Logic uint32_t spawn_cooldown; bool cooling_down; bool apep_journal_entry_logged; - uint32_t unknown4c; - uint32_t unknown4d; - uint32_t unknown5; - uint32_t unknown6; - - virtual ~LogicApepTrigger() = 0; }; class LogicCOGAnkhSacrifice : public Logic { uint8_t unknown3; uint8_t timer; - - virtual ~LogicCOGAnkhSacrifice() = 0; }; class LogicDuatBossesTrigger : public Logic { public: - virtual ~LogicDuatBossesTrigger() = 0; + uint32_t unknown3; // definitely is reserved memory, but doesn't seam used? + uint32_t unknown4; }; class LogicTiamatBubbles : public Logic { public: uint8_t bubble_spawn_timer; - - virtual ~LogicTiamatBubbles() = 0; }; class LogicTuskPleasurePalace : public Logic @@ -605,8 +592,6 @@ class LogicTuskPleasurePalace : public Logic public: uint32_t locked_door; // entity uid uint32_t unknown4; - - virtual ~LogicTuskPleasurePalace() = 0; }; class LogicArena1 : public Logic @@ -616,47 +601,61 @@ class LogicArena1 : public Logic uint32_t unknown4; uint32_t unknown5; uint32_t unknown6; - - virtual ~LogicArena1() = 0; }; class LogicArenaAlienBlast : public Logic { public: uint32_t timer; - - virtual ~LogicArenaAlienBlast() = 0; }; class LogicArenaLooseBombs : public Logic { public: uint32_t timer; +}; + +class LogicUnderwaterBubbles : public Logic +{ + public: + float unknown1; + int16_t unknown2; + int8_t unknown3; +}; - virtual ~LogicArenaLooseBombs() = 0; +class LogicTunPreChallenge : public Logic +{ + // except for Tun the rest of the values do not make any sense (garbage) + // the logic.perform does only ever touches the tun as well, first one always 0? + size_t unknown1; + size_t unknown2; + size_t unknown3; + int32_t tun; }; struct LogicList { Logic* tutorial; - LogicOuroboros* ouroboros; - LogicBasecampSpeedrun* basecamp_speedrun; - Logic* ghost_trigger; - LogicGhostToast* ghost_toast_trigger; - Logic* tun_aggro; - LogicDiceShop* diceshop; - Logic* tun_pre_challenge; - LogicMoonChallenge* tun_moon_challenge; - LogicStarChallenge* tun_star_challenge; - LogicSunChallenge* tun_sun_challenge; - Logic* volcana_related; - Logic* water_related; + LogicOuroboros* ouroboros; // OK + LogicBasecampSpeedrun* basecamp_speedrun; // OK + Logic* ghost_trigger; // OK + LogicGhostToast* ghost_toast_trigger; // OK + Logic* tun_aggro; // OK + LogicDiceShop* diceshop; // OK + LogicTunPreChallenge* tun_pre_challenge; // OK + LogicMoonChallenge* tun_moon_challenge; // OK + LogicStarChallenge* tun_star_challenge; // OK + LogicSunChallenge* tun_sun_challenge; // OK + Logic* volcana_related; // OK + /// Only the bubbles that spawn from the floor + /// Even without it, entities moving in water still spawn bubbles + LogicUnderwaterBubbles* water_bubbles; // OK LogicOlmecCutscene* olmec_cutscene; LogicTiamatCutscene* tiamat_cutscene; - LogicApepTrigger* apep_trigger; + LogicApepTrigger* apep_trigger; // OK LogicCOGAnkhSacrifice* city_of_gold_ankh_sacrifice; - LogicDuatBossesTrigger* duat_bosses_trigger; - LogicTiamatBubbles* tiamat; + LogicDuatBossesTrigger* duat_bosses_trigger; // OK + LogicTiamatBubbles* bubbler; LogicTuskPleasurePalace* tusk_pleasure_palace; Logic* discovery_info; // black market, vlad, wet fur discovery; shows the toast Logic* black_market; From 6b80c6f585e56f2f28563a0d1c9a70b1f919dc9f Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:50:32 +0200 Subject: [PATCH 02/16] build errors --- src/game_api/state_structs.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index cdb8d2f46..bbd9854c5 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -391,7 +391,7 @@ class Logic { public: uint32_t logic_index; // array index into state.logic, where this instance resides - uint32_t padding; + uint32_t unused_padding; virtual ~Logic() = 0; @@ -570,6 +570,7 @@ class LogicApepTrigger : public Logic class LogicCOGAnkhSacrifice : public Logic { + public: uint8_t unknown3; uint8_t timer; }; @@ -625,6 +626,7 @@ class LogicUnderwaterBubbles : public Logic class LogicTunPreChallenge : public Logic { + public: // except for Tun the rest of the values do not make any sense (garbage) // the logic.perform does only ever touches the tun as well, first one always 0? size_t unknown1; From 6668bad101263023cae35d8c6cc4883ed49e0ddf Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Tue, 26 Sep 2023 22:53:16 +0200 Subject: [PATCH 03/16] cutscenes --- src/game_api/state_structs.hpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index bbd9854c5..bd256f526 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -531,14 +531,10 @@ class LogicSunChallenge : public Logic class LogicOlmecCutscene : public Logic { public: - uint8_t unknown6a; - uint8_t unknown6b; - uint8_t unknown6c; - uint8_t unknown6d; - uint8_t unknown7a; - uint8_t unknown7b; - uint8_t unknown7c; - uint8_t unknown7d; + /// Copied over [buttons_gameplay](#PlayerSlot) from the leader, used to skip the cutscene + /// You can skip the cutscene if you set it to 1 or 4 + uint8_t leader_inputs; + uint8_t padding[7]; Entity* fx_olmecpart_large; Entity* olmec; Entity* player; @@ -549,15 +545,14 @@ class LogicOlmecCutscene : public Logic class LogicTiamatCutscene : public Logic { public: - uint32_t unknown3; - uint32_t unknown4; + /// Copied over [buttons_gameplay](#PlayerSlot) from the leader, used to skip the cutscene + /// You can skip the cutscene if you set it to 1 or 4 + uint8_t leader_inputs; + uint8_t padding[7]; Entity* tiamat; Entity* player; Entity* cinematic_anchor; uint32_t timer; - int32_t unknown5; - uint32_t unknown6; - uint32_t unknown7; }; class LogicApepTrigger : public Logic @@ -652,7 +647,7 @@ struct LogicList /// Only the bubbles that spawn from the floor /// Even without it, entities moving in water still spawn bubbles LogicUnderwaterBubbles* water_bubbles; // OK - LogicOlmecCutscene* olmec_cutscene; + LogicOlmecCutscene* olmec_cutscene; // OK LogicTiamatCutscene* tiamat_cutscene; LogicApepTrigger* apep_trigger; // OK LogicCOGAnkhSacrifice* city_of_gold_ankh_sacrifice; From a2e6ead78227e28d9aadc75775d21d22217f11ed Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 28 Sep 2023 18:36:16 +0200 Subject: [PATCH 04/16] fix potential memory leaks --- src/game_api/render_api.cpp | 2 +- src/injected/ui_util.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game_api/render_api.cpp b/src/game_api/render_api.cpp index 8ea4ed966..95b7aefd8 100644 --- a/src/game_api/render_api.cpp +++ b/src/game_api/render_api.cpp @@ -378,7 +378,7 @@ void on_open_journal_chapter(JournalUI* journal_ui, uint8_t chapter, bool instan { if (p.second) { - p.first->~JournalPage(); + delete p.first; } } } diff --git a/src/injected/ui_util.cpp b/src/injected/ui_util.cpp index d74586c2f..3fcc543c7 100644 --- a/src/injected/ui_util.cpp +++ b/src/injected/ui_util.cpp @@ -612,7 +612,7 @@ void UI::safe_destroy(Entity* ent, bool unsafe, bool recurse) // if cutscene is still running, perform the last frame of cutscene before killing olmec state->logic->olmec_cutscene->timer = 809; state->logic->olmec_cutscene->perform(); - state->logic->olmec_cutscene->~LogicOlmecCutscene(); + delete state->logic->olmec_cutscene; state->logic->olmec_cutscene = nullptr; } destroy_entity_items(check); From 0bf17cea6625756860242e9ceae95414dc9b78db Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 28 Sep 2023 18:38:17 +0200 Subject: [PATCH 05/16] use the constant meant for this --- src/game_api/strings.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game_api/strings.cpp b/src/game_api/strings.cpp index 6e226c1fc..b2fd9e8e5 100644 --- a/src/game_api/strings.cpp +++ b/src/game_api/strings.cpp @@ -12,6 +12,7 @@ #include // for unordered_map, _Umap_traits... #include // for max, min, pair +#include "constants.hpp" // #include "containers/game_allocator.hpp" // for game_free, game_malloc #include "detours.h" // for DetourAttach, DetourTransac... #include "entity.hpp" // for get_type, Entity, EntityDB @@ -54,7 +55,7 @@ void OnNPCDialogue(size_t func, Entity* NPC, char16_t* buffer, int shoppie_sound { std::u16string str = pre_speach_bubble(NPC, buffer); char16_t* new_string = NULL; - if (str != u"~[:NO_RETURN:]#") + if (str != no_return_str) { if (str.empty()) { @@ -78,7 +79,7 @@ void OnToast(char16_t* buffer) { std::u16string str = pre_toast(buffer); char16_t* new_string = NULL; - if (str != u"~[:NO_RETURN:]#") + if (str != no_return_str) { if (str.empty()) { From 78436c2835aea41b8c5bdda1af35ab3f489bd515 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 28 Sep 2023 22:49:56 +0200 Subject: [PATCH 06/16] some more logic stuff, also missing vtable offset --- src/game_api/state_structs.hpp | 62 +++++++++++++++++++++------------- src/game_api/virtual_table.hpp | 2 +- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index 8c14e9edf..0b814ae8a 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -451,7 +451,7 @@ class LogicGhostToast : public Logic class LogicDiceShop : public Logic { public: - uint32_t boss_uid; // either tusk or the shopkeeper + uint32_t boss_uid; ENT_TYPE boss_type; /// entity uid uint32_t bet_machine; @@ -471,11 +471,12 @@ class LogicDiceShop : public Logic bool bet_active; bool forcefield_deactivated; bool boss_angry; - uint8_t result_announcement_timer; // the time the boss waits after your second die throw to announce the results - uint8_t won_prizes_count; // to see whether you achieved high roller status + /// the time the boss waits after your second die throw to announce the results + uint8_t result_announcement_timer; + uint8_t won_prizes_count; uint8_t padding[3]; - int32_t balance; // cash balance of all the games - size_t unknown17; + /// cash balance of all the games + int32_t balance; }; class LogicMoonChallenge : public Logic @@ -490,7 +491,8 @@ class LogicMoonChallenge : public Logic uint16_t unknown7; uint16_t unknown8a; uint16_t unknown8b; - uint32_t mattock; // entity uid + // entity uid + int32_t mattock; }; class LogicStarChallenge : public Logic @@ -508,7 +510,7 @@ class LogicStarChallenge : public Logic uint8_t start_countdown; uint8_t padding[3]; uint32_t unknown9; - float unknown10; // position in from of tun and one tile higher, dunno what for? + float unknown10; // position in front of tun and one tile higher, dunno what for? float unknown11; }; @@ -526,7 +528,7 @@ class LogicSunChallenge : public Logic uint8_t start_countdown; uint8_t padding[3]; uint32_t unknown9; - float unknown10; // position in from of tun and one tile higher, dunno what for? + float unknown10; // position in front of tun and one tile higher, dunno what for? float unknown11; }; @@ -590,6 +592,8 @@ class LogicTuskPleasurePalace : public Logic public: uint32_t locked_door; // entity uid uint32_t unknown4; + uint32_t unknown5; + uint32_t unknown6; // padding probably }; class LogicArena1 : public Logic @@ -629,34 +633,44 @@ class LogicTunPreChallenge : public Logic size_t unknown1; size_t unknown2; size_t unknown3; - int32_t tun; + int32_t tun_uid; +}; + +class LogicTutorial : public Logic +{ + public: + Entity* pet_tutorial; + uint32_t timer; }; struct LogicList { - Logic* tutorial; + /// Only the very begging of the tutorial, probably just setting things up + LogicTutorial* tutorial; // OK LogicOuroboros* ouroboros; // OK LogicBasecampSpeedrun* basecamp_speedrun; // OK Logic* ghost_trigger; // OK LogicGhostToast* ghost_toast_trigger; // OK - Logic* tun_aggro; // OK - LogicDiceShop* diceshop; // OK - LogicTunPreChallenge* tun_pre_challenge; // OK - LogicMoonChallenge* tun_moon_challenge; // OK - LogicStarChallenge* tun_star_challenge; // OK - LogicSunChallenge* tun_sun_challenge; // OK - Logic* volcana_related; // OK + /// Spawns tun at the door at 30s mark + Logic* tun_aggro; // OK + LogicDiceShop* diceshop; // OK + LogicTunPreChallenge* tun_pre_challenge; // OK + LogicMoonChallenge* tun_moon_challenge; // OK + LogicStarChallenge* tun_star_challenge; // OK + LogicSunChallenge* tun_sun_challenge; // OK + Logic* volcana_related; // OK /// Only the bubbles that spawn from the floor /// Even without it, entities moving in water still spawn bubbles LogicUnderwaterBubbles* water_bubbles; // OK LogicOlmecCutscene* olmec_cutscene; // OK - LogicTiamatCutscene* tiamat_cutscene; - LogicApepTrigger* apep_trigger; // OK - LogicCOGAnkhSacrifice* city_of_gold_ankh_sacrifice; - LogicDuatBossesTrigger* duat_bosses_trigger; // OK - LogicTiamatBubbles* bubbler; - LogicTuskPleasurePalace* tusk_pleasure_palace; - Logic* discovery_info; // black market, vlad, wet fur discovery; shows the toast + LogicTiamatCutscene* tiamat_cutscene; // OK + LogicApepTrigger* apep_trigger; // OK + /// All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) + LogicCOGAnkhSacrifice* city_of_gold_ankh_sacrifice; // OK + LogicDuatBossesTrigger* duat_bosses_trigger; // OK + LogicTiamatBubbles* bubbler; // OK + LogicTuskPleasurePalace* tusk_pleasure_palace; // OK TODO: van helsing + Logic* discovery_info; // black market, vlad, wet fur discovery; shows the toast // OK Logic* black_market; Logic* cosmic_ocean; LogicArena1* arena_1; diff --git a/src/game_api/virtual_table.hpp b/src/game_api/virtual_table.hpp index 2739eaab3..6d611fae1 100644 --- a/src/game_api/virtual_table.hpp +++ b/src/game_api/virtual_table.hpp @@ -924,7 +924,7 @@ enum class VTABLE_OFFSET THEME_HUNDUN = 51582, THEME_BASECAMP = 51634, THEME_ARENA = 51686, - // LOGIC_TUTORIAL = UNKNOWN + LOGIC_TUTORIAL = 52047, LOGIC_OUROBOROS = 52035, LOGIC_BASECAMP_SPEEDRUN = 52039, LOGIC_GHOST_TRIGGER = 52013, From 8555adbe37226302ec31ce8588cff76be730c3e1 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Fri, 29 Sep 2023 23:23:50 +0200 Subject: [PATCH 07/16] all logic looked at, except arena_2 --- src/game_api/state_structs.hpp | 112 ++++++++++++++------------------- 1 file changed, 48 insertions(+), 64 deletions(-) diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index 0b814ae8a..74ccf08bf 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -398,32 +398,8 @@ class Logic virtual ~Logic() = 0; // Continuously performs the main functionality of the logic instance - // Tutorial: handles dropping of the torch and rope in intro routine - // Ouroboros: transitions to level when music finished - // Basecamp speedrun: keep track of time, player position passing official - // Ghost trigger: spawns ghost when time is up (checks cursed for earlier ghost) - // Ghost toast trigger: shows the 'A terrible chill...' toast after 90 frames - // Tun aggro: spawns Tun after 30 seconds - // Dice shop: runs the logic of the dice shop - // Tun pre challenge: unknown - // Moon challenge: handles waitroom forcefields + tracks mattock breakage - // Star challenge: handles waitroom forcefields + tracks torches/timer - // Sun challenge: handles waitroom forcefields + tracks timer - // Volcana/Lava: spawns magmamen at random (and does other things) - // Water: unknown - // Olmec cutscene: runs the cutscene - // Tiamat cutscene: runs the cutscene - // Apep trigger: tracks player position, spawns APEP_HEAD - // COG Ankh sacrifice: countdown timer (100 frames) from the moment you die, triggers transitioning to duat - // Duat bosses trigger: tracks player position, spawns ANUBIS2 and OSIRIS_HEAD - // Tiamat: spawns bubbles - // Tusk pleasure palace: triggers aggro on everyone when non-high roller enters door - // Discovery: shows the toast - // Black market: lifts camera bounds restrictions - // Cosmic ocean: spawns jelly when time is up - // Arena 1: handles crate spawning - // Arena 3: handles death mist - virtual void perform() = 0; + // If it returns false, game will call deconstructor next in most cases + virtual bool perform() = 0; }; class LogicOuroboros : public Logic @@ -574,13 +550,6 @@ class LogicCOGAnkhSacrifice : public Logic uint8_t timer; }; -class LogicDuatBossesTrigger : public Logic -{ - public: - uint32_t unknown3; // definitely is reserved memory, but doesn't seam used? - uint32_t unknown4; -}; - class LogicTiamatBubbles : public Logic { public: @@ -590,19 +559,16 @@ class LogicTiamatBubbles : public Logic class LogicTuskPleasurePalace : public Logic { public: - uint32_t locked_door; // entity uid - uint32_t unknown4; - uint32_t unknown5; - uint32_t unknown6; // padding probably + int32_t locked_door; // entity uid + uint32_t unknown4; // always 1552 + uint32_t unknown5; // dunno + uint32_t unknown6; // padding probably }; class LogicArena1 : public Logic { public: uint32_t crate_spawn_timer; - uint32_t unknown4; - uint32_t unknown5; - uint32_t unknown6; }; class LogicArenaAlienBlast : public Logic @@ -620,9 +586,10 @@ class LogicArenaLooseBombs : public Logic class LogicUnderwaterBubbles : public Logic { public: - float unknown1; - int16_t unknown2; - int8_t unknown3; + // no idea what does are, messing with them can crash + float unknown1; // 1.0 + int16_t unknown2; // 1000 + int8_t unknown3; // 1 or 0, probably bool }; class LogicTunPreChallenge : public Logic @@ -648,37 +615,54 @@ struct LogicList /// Only the very begging of the tutorial, probably just setting things up LogicTutorial* tutorial; // OK LogicOuroboros* ouroboros; // OK - LogicBasecampSpeedrun* basecamp_speedrun; // OK - Logic* ghost_trigger; // OK - LogicGhostToast* ghost_toast_trigger; // OK + union + { + std::array logic_indexed; + struct + { + /// Handles dropping of the torch and rope in intro routine (first time play) + LogicTutorial* tutorial; + LogicOuroboros* ouroboros; + /// Keep track of time, player position passing official + LogicBasecampSpeedrun* basecamp_speedrun; + Logic* ghost_trigger; // virtual does nothing, all the code elsewhere, the only purpose is to mark if ghost should spawn this level or not + LogicGhostToast* ghost_toast_trigger; /// Spawns tun at the door at 30s mark - Logic* tun_aggro; // OK - LogicDiceShop* diceshop; // OK - LogicTunPreChallenge* tun_pre_challenge; // OK - LogicMoonChallenge* tun_moon_challenge; // OK - LogicStarChallenge* tun_star_challenge; // OK - LogicSunChallenge* tun_sun_challenge; // OK - Logic* volcana_related; // OK + Logic* tun_aggro; + LogicDiceShop* diceshop; + LogicTunPreChallenge* tun_pre_challenge; + LogicMoonChallenge* tun_moon_challenge; + LogicStarChallenge* tun_star_challenge; + LogicSunChallenge* tun_sun_challenge; + Logic* volcana_related; /// Only the bubbles that spawn from the floor /// Even without it, entities moving in water still spawn bubbles - LogicUnderwaterBubbles* water_bubbles; // OK - LogicOlmecCutscene* olmec_cutscene; // OK - LogicTiamatCutscene* tiamat_cutscene; // OK - LogicApepTrigger* apep_trigger; // OK + LogicUnderwaterBubbles* water_bubbles; + LogicOlmecCutscene* olmec_cutscene; + LogicTiamatCutscene* tiamat_cutscene; + LogicApepTrigger* apep_spawner; /// All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) - LogicCOGAnkhSacrifice* city_of_gold_ankh_sacrifice; // OK - LogicDuatBossesTrigger* duat_bosses_trigger; // OK - LogicTiamatBubbles* bubbler; // OK - LogicTuskPleasurePalace* tusk_pleasure_palace; // OK TODO: van helsing - Logic* discovery_info; // black market, vlad, wet fur discovery; shows the toast // OK + LogicCOGAnkhSacrifice* city_of_gold_ankh_sacrifice; + Logic* duat_bosses_spawner; + /// Spawn rising bubbles at Tiamat (position hardcoded) + LogicTiamatBubbles* bubbler; + /// Triggers aggro on everyone when non-high roller enters door + LogicTuskPleasurePalace* tusk_pleasure_palace; // TODO: van helsing? + /// black market, vlad, wet fur discovery, logic shows the toast + Logic* discovery_info; + /// Changes the camera bounds when you reach black market Logic* black_market; - Logic* cosmic_ocean; + Logic* jellyfish_trigger; // same as ghost_trigger + /// Handles create spawns and more, is cleared as soon as the winner is decided (on last player alive) LogicArena1* arena_1; - Logic* arena_2; + Logic* arena_2; // can't trigger + /// Handles time end death Logic* arena_3; LogicArenaAlienBlast* arena_alien_blast; LogicArenaLooseBombs* arena_loose_bombs; }; + }; +}; struct LiquidPhysicsEngine { From f5af7442acfc7fb1722e52efc33c6f53d5166072 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sat, 30 Sep 2023 11:09:18 +0200 Subject: [PATCH 08/16] add functions to kill and create Logic --- src/game_api/state.cpp | 200 +++++++++++++++++++++++++++++++++ src/game_api/state_structs.hpp | 62 +++++++--- 2 files changed, 248 insertions(+), 14 deletions(-) diff --git a/src/game_api/state.cpp b/src/game_api/state.cpp index 3d773134c..185ab98b0 100644 --- a/src/game_api/state.cpp +++ b/src/game_api/state.cpp @@ -9,6 +9,7 @@ #include // for allocator, operator""sv, operator""s #include // for move +#include "containers/custom_allocator.hpp" // #include "entities_chars.hpp" // for Player #include "entity.hpp" // for to_id, Entity, HookWithId, EntityDB #include "entity_hooks_info.hpp" // for Player @@ -716,3 +717,202 @@ uint8_t enum_to_layer(const LAYER layer) } return 0; } + +Logic* LogicList::start_logic(LOGIC idx) +{ + if ((int)idx > 27 || logic_indexed[(uint32_t)idx] != nullptr) + return; + + int size = 0; + VTABLE_OFFSET offset = VTABLE_OFFSET::NONE; + switch (idx) + { + case LOGIC::GHOST: + { + offset = VTABLE_OFFSET::LOGIC_GHOST_TRIGGER; + size = sizeof(Logic); + break; + } + case LOGIC::TUN_AGGRO: + { + offset = VTABLE_OFFSET::LOGIC_TUN_AGGRO; + size = sizeof(Logic); + break; + } + case LOGIC::DUAT_BOSSES: + { + offset = VTABLE_OFFSET::LOGIC_DUAT_BOSSES_TRIGGER; + size = sizeof(Logic); + break; + } + case LOGIC::DISCOVERY_INFO: + { + offset = VTABLE_OFFSET::LOGIC_DISCOVERY_INFO; + size = sizeof(Logic); + break; + } + case LOGIC::BLACK_MARKET: + { + offset = VTABLE_OFFSET::LOGIC_BLACK_MARKET; + size = sizeof(Logic); + break; + } + case LOGIC::JELLYFISH: + { + offset = VTABLE_OFFSET::LOGIC_COSMIC_OCEAN; + size = sizeof(Logic); + break; + } + case LOGIC::ARENA_3: + { + offset = VTABLE_OFFSET::LOGIC_ARENA_3; + size = sizeof(Logic); + break; + } + case LOGIC::SPEEDRUN: + { + offset = VTABLE_OFFSET::LOGIC_BASECAMP_SPEEDRUN; + size = sizeof(LogicBasecampSpeedrun); + break; + } + case LOGIC::GHOST_TOAST: + { + offset = VTABLE_OFFSET::LOGIC_GHOST_TOAST_TRIGGER; + size = sizeof(LogicGhostToast); + break; + } + case LOGIC::WATER_BUBBLES: + { + offset = VTABLE_OFFSET::LOGIC_WATER_RELATED; + size = sizeof(LogicUnderwaterBubbles); + break; + } + case LOGIC::APEP: + { + offset = VTABLE_OFFSET::LOGIC_APEP_TRIGGER; + size = sizeof(LogicApepTrigger); + break; + } + case LOGIC::COG_SACRIFICE: + { + offset = VTABLE_OFFSET::LOGIC_CITY_OF_GOLD_ANKH_SACRIFICE; + size = sizeof(LogicCOGAnkhSacrifice); + break; + } + case LOGIC::BUBBLER: + { + offset = VTABLE_OFFSET::LOGIC_TIAMAT; + size = sizeof(LogicTiamatBubbles); + break; + } + case LOGIC::ARENA_1: + { + offset = VTABLE_OFFSET::LOGIC_ARENA_1; + size = sizeof(LogicArena1); + break; + } + case LOGIC::ARENA_ALIEN_BLAST: + { + offset = VTABLE_OFFSET::LOGIC_ARENA_ALIEN_BLAST; + size = sizeof(LogicArenaAlienBlast); + break; + } + case LOGIC::ARENA_LOOSE_BOMBS: + { + offset = VTABLE_OFFSET::LOGIC_ARENA_LOOSE_BOMBS; + size = sizeof(LogicArenaLooseBombs); + break; + } + case LOGIC::TUTORIAL: + { + offset = VTABLE_OFFSET::LOGIC_TUTORIAL; + size = sizeof(LogicTutorial); + break; + } + case LOGIC::OUROBOROS: + { + offset = VTABLE_OFFSET::LOGIC_OUROBOROS; + size = sizeof(LogicOuroboros); + break; + } + case LOGIC::PLEASURE_PALACE: + { + offset = VTABLE_OFFSET::LOGIC_TUSK_PLEASURE_PALACE; + size = sizeof(LogicTuskPleasurePalace); + break; + } + case LOGIC::MAGMAN_SPAWN: + { + offset = VTABLE_OFFSET::LOGIC_VOLCANA_RELATED; + size = sizeof(LogicMagmamanSpawn); + break; + } + case LOGIC::PRE_CHALLENGE: + { + offset = VTABLE_OFFSET::LOGIC_TUN_PRE_CHALLENGE; + size = sizeof(LogicTunPreChallenge); + break; + } + case LOGIC::MOON_CHALLENGE: + { + offset = VTABLE_OFFSET::LOGIC_TUN_MOON_CHALLENGE; + size = sizeof(LogicMoonChallenge); + break; + } + case LOGIC::SUN_CHALLENGE: + { + offset = VTABLE_OFFSET::LOGIC_TUN_SUN_CHALLENGE; + size = sizeof(LogicSunChallenge); + break; + } + case LOGIC::TIAMAT_CUTSCENE: + { + offset = VTABLE_OFFSET::LOGIC_TIAMAT_CUTSCENE; + size = sizeof(LogicTiamatCutscene); + break; + } + case LOGIC::DICESHOP: + { + offset = VTABLE_OFFSET::LOGIC_DICESHOP; + size = sizeof(LogicDiceShop); + break; + } + case LOGIC::OLMEC_CUTSCENE: + { + offset = VTABLE_OFFSET::LOGIC_OLMEC_CUTSCENE; + size = sizeof(LogicOlmecCutscene); + break; + } + case LOGIC::STAR_CHALLENGE: + { + offset = VTABLE_OFFSET::LOGIC_TUN_STAR_CHALLENGE; + size = sizeof(LogicStarChallenge); + break; + } + case LOGIC::ARENA_2: + // offset = VTABLE_OFFSET::LOGIC_ARENA_2; + // size = ?; + default: + return; + } + static auto first_table_entry = get_address("virtual_functions_table"); + VTABLE_OFFSET::LOGIC_APEP_TRIGGER; + + auto addr = (size_t*)custom_malloc(size); + std::memset(addr, 0, size); // just in case + + *addr = first_table_entry + (size_t)offset; // set up vtable + Logic* new_logic = (Logic*)addr; + new_logic->logic_index = idx; + logic_indexed[(uint32_t)idx] = new_logic; + return new_logic; +} + +void LogicList::stop_logic(LOGIC idx) +{ + if ((uint32_t)idx > 27 || logic_indexed[(uint32_t)idx] == nullptr) + return; + + delete logic_indexed[(uint32_t)idx]; + logic_indexed[(uint32_t)idx] = nullptr; +} diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index 74ccf08bf..e3a8e4b37 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -389,10 +389,42 @@ struct ArenaState bool punish_ball; }; +enum class LOGIC : uint32_t +{ + TUTORIAL = 0, + OUROBOROS, + SPEEDRUN, + GHOST, + GHOST_TOAST, + TUN_AGGRO, + DICESHOP, + PRE_CHALLENGE, + MOON_CHALLENGE, + STAR_CHALLENGE, + SUN_CHALLENGE, + MAGMAN_SPAWN, + WATER_BUBBLES, + OLMEC_CUTSCENE, + TIAMAT_CUTSCENE, + APEP, + COG_SACRIFICE, + DUAT_BOSSES, + BUBBLER, + PLEASURE_PALACE, + DISCOVERY_INFO, + BLACK_MARKET, + JELLYFISH, + ARENA_1, + ARENA_2, + ARENA_3, + ARENA_ALIEN_BLAST, + ARENA_LOOSE_BOMBS, +}; + class Logic { public: - uint32_t logic_index; // array index into state.logic, where this instance resides + LOGIC logic_index; uint32_t unused_padding; virtual ~Logic() = 0; @@ -612,9 +644,11 @@ class LogicTutorial : public Logic struct LogicList { - /// Only the very begging of the tutorial, probably just setting things up - LogicTutorial* tutorial; // OK - LogicOuroboros* ouroboros; // OK + /// This only properly constructs the base class + /// you probably will need to set the parameters correctly + Logic* start_logic(LOGIC idx); + void stop_logic(LOGIC idx); + union { std::array logic_indexed; @@ -627,7 +661,7 @@ struct LogicList LogicBasecampSpeedrun* basecamp_speedrun; Logic* ghost_trigger; // virtual does nothing, all the code elsewhere, the only purpose is to mark if ghost should spawn this level or not LogicGhostToast* ghost_toast_trigger; - /// Spawns tun at the door at 30s mark + /// Spawns tun at the door at 30s mark Logic* tun_aggro; LogicDiceShop* diceshop; LogicTunPreChallenge* tun_pre_challenge; @@ -635,13 +669,13 @@ struct LogicList LogicStarChallenge* tun_star_challenge; LogicSunChallenge* tun_sun_challenge; Logic* volcana_related; - /// Only the bubbles that spawn from the floor - /// Even without it, entities moving in water still spawn bubbles + /// Only the bubbles that spawn from the floor + /// Even without it, entities moving in water still spawn bubbles LogicUnderwaterBubbles* water_bubbles; LogicOlmecCutscene* olmec_cutscene; LogicTiamatCutscene* tiamat_cutscene; LogicApepTrigger* apep_spawner; - /// All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) + /// All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) LogicCOGAnkhSacrifice* city_of_gold_ankh_sacrifice; Logic* duat_bosses_spawner; /// Spawn rising bubbles at Tiamat (position hardcoded) @@ -651,16 +685,16 @@ struct LogicList /// black market, vlad, wet fur discovery, logic shows the toast Logic* discovery_info; /// Changes the camera bounds when you reach black market - Logic* black_market; + Logic* black_market; Logic* jellyfish_trigger; // same as ghost_trigger /// Handles create spawns and more, is cleared as soon as the winner is decided (on last player alive) - LogicArena1* arena_1; + LogicArena1* arena_1; Logic* arena_2; // can't trigger /// Handles time end death - Logic* arena_3; - LogicArenaAlienBlast* arena_alien_blast; - LogicArenaLooseBombs* arena_loose_bombs; -}; + Logic* arena_3; + LogicArenaAlienBlast* arena_alien_blast; + LogicArenaLooseBombs* arena_loose_bombs; + }; }; }; From 157c587f8366cfe5544f99448965468ebb49a7b1 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sat, 30 Sep 2023 15:33:15 +0200 Subject: [PATCH 09/16] `add_spawn` and `remove_spawn` for `LogicMagmamanSpawn`, expose `start_logic` and `stop_logic` --- src/game_api/script/usertypes/state_lua.cpp | 23 ++++++++++++++++++- src/game_api/state.cpp | 25 +++++++++++++++++---- src/game_api/state_structs.hpp | 11 +++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/game_api/script/usertypes/state_lua.cpp b/src/game_api/script/usertypes/state_lua.cpp index e4f65b7b9..6adbc3338 100644 --- a/src/game_api/script/usertypes/state_lua.cpp +++ b/src/game_api/script/usertypes/state_lua.cpp @@ -497,6 +497,7 @@ void register_usertypes(sol::state& lua) }), "get_code", &OnlineLobby::get_code); + /// Used in StateMemory lua.new_usertype( "LogicList", @@ -507,7 +508,16 @@ void register_usertypes(sol::state& lua) "magmaman_spawn", &LogicList::magmaman_spawn, "diceshop", - &LogicList::diceshop); + &LogicList::diceshop, + "start_logic", + [&lua](LogicList& l, LOGIC idx) -> sol::object // -> Logic + { + auto return_logic = l.start_logic(idx); + // TODO: cast to proper logic type + return sol::make_object(lua, return_logic); + }, + "stop_logic", + &LogicList::stop_logic); /// Used in LogicList lua.new_usertype( "Logic", @@ -549,10 +559,21 @@ void register_usertypes(sol::state& lua) &MagmamanSpawnPosition::y, "timer", &MagmamanSpawnPosition::timer); + auto add_spawn = sol::overload( + static_cast(&LogicMagmamanSpawn::add_spawn), + static_cast(&LogicMagmamanSpawn::add_spawn)); + auto remove_spawn = sol::overload( + static_cast(&LogicMagmamanSpawn::remove_spawn), + static_cast(&LogicMagmamanSpawn::remove_spawn)); + lua.new_usertype( "LogicVolcana", "magmaman_positions", &LogicMagmamanSpawn::magmaman_positions, + "add_spawn", + add_spawn, + "remove_spawn", + remove_spawn, sol::base_classes, sol::bases()); diff --git a/src/game_api/state.cpp b/src/game_api/state.cpp index 9deb45309..f39bf575a 100644 --- a/src/game_api/state.cpp +++ b/src/game_api/state.cpp @@ -729,8 +729,8 @@ uint8_t enum_to_layer(const LAYER layer) Logic* LogicList::start_logic(LOGIC idx) { - if ((int)idx > 27 || logic_indexed[(uint32_t)idx] != nullptr) - return; + if ((uint32_t)idx > 27 || logic_indexed[(uint32_t)idx] != nullptr) + return nullptr; int size = 0; VTABLE_OFFSET offset = VTABLE_OFFSET::NONE; @@ -902,7 +902,7 @@ Logic* LogicList::start_logic(LOGIC idx) // offset = VTABLE_OFFSET::LOGIC_ARENA_2; // size = ?; default: - return; + return nullptr; } static auto first_table_entry = get_address("virtual_functions_table"); VTABLE_OFFSET::LOGIC_APEP_TRIGGER; @@ -910,9 +910,10 @@ Logic* LogicList::start_logic(LOGIC idx) auto addr = (size_t*)custom_malloc(size); std::memset(addr, 0, size); // just in case - *addr = first_table_entry + (size_t)offset; // set up vtable + *addr = first_table_entry + (size_t)offset * 8; // set up vtable Logic* new_logic = (Logic*)addr; new_logic->logic_index = idx; + logic_indexed[(uint32_t)idx] = new_logic; return new_logic; } @@ -925,3 +926,19 @@ void LogicList::stop_logic(LOGIC idx) delete logic_indexed[(uint32_t)idx]; logic_indexed[(uint32_t)idx] = nullptr; } + +void LogicMagmamanSpawn::add_spawn(uint32_t x, uint32_t y) +{ + magmaman_positions.emplace_back(x, y); +} + +void LogicMagmamanSpawn::remove_spawn(uint32_t x, uint32_t y) +{ + for (auto it = magmaman_positions.begin(); it < magmaman_positions.end(); ++it) + { + if (it->x == x && it->y == y) + { + magmaman_positions.erase(it); + } + } +} diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index 6a53e09c4..ffef32c6a 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -554,6 +554,17 @@ class LogicMagmamanSpawn : public Logic { public: custom_vector magmaman_positions; + + void add_spawn(uint32_t x, uint32_t y); + void add_spawn(MagmamanSpawnPosition ms) + { + add_spawn(ms.x, ms.y); + }; + void remove_spawn(uint32_t x, uint32_t y); + void remove_spawn(MagmamanSpawnPosition ms) + { + remove_spawn(ms.x, ms.y); + }; }; class LogicOlmecCutscene : public Logic From a94c974b1ec078d1a4fe1083c054780ee590733f Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sat, 30 Sep 2023 15:55:43 +0200 Subject: [PATCH 10/16] add all logics to `LogicList` --- src/game_api/script/usertypes/state_lua.cpp | 79 ++++++++++++++++++--- 1 file changed, 68 insertions(+), 11 deletions(-) diff --git a/src/game_api/script/usertypes/state_lua.cpp b/src/game_api/script/usertypes/state_lua.cpp index 6adbc3338..152c4d90a 100644 --- a/src/game_api/script/usertypes/state_lua.cpp +++ b/src/game_api/script/usertypes/state_lua.cpp @@ -498,31 +498,88 @@ void register_usertypes(sol::state& lua) "get_code", &OnlineLobby::get_code); + auto start_logic = sol::overload( + [&lua](LogicList& l, LOGIC idx) -> sol::object + { + auto return_logic = l.start_logic(idx); + // TODO: cast to proper logic type + return sol::make_object(lua, return_logic); + }, + [&lua](LogicList& l, Logic* logic) -> sol::object + { + auto return_logic = l.start_logic(logic->logic_index); + // TODO: cast to proper logic type + return sol::make_object(lua, return_logic); + }); + /// Used in StateMemory lua.new_usertype( "LogicList", + "tutorial", + &LogicList::tutorial, + "ouroboros", + &LogicList::ouroboros, + "basecamp_speedrun", + &LogicList::basecamp_speedrun, + "ghost_trigger", + &LogicList::ghost_trigger, + "ghost_toast_trigger", + &LogicList::ghost_toast_trigger, + "tun_aggro", + &LogicList::tun_aggro, + "diceshop", + &LogicList::diceshop, + "tun_pre_challenge", + &LogicList::tun_pre_challenge, + "tun_moon_challenge", + &LogicList::tun_moon_challenge, + "tun_star_challenge", + &LogicList::tun_star_challenge, + "tun_sun_challenge", + &LogicList::tun_sun_challenge, + "magmaman_spawn", + &LogicList::magmaman_spawn, + "water_bubbles", + &LogicList::water_bubbles, "olmec_cutscene", &LogicList::olmec_cutscene, "tiamat_cutscene", &LogicList::tiamat_cutscene, - "magmaman_spawn", - &LogicList::magmaman_spawn, - "diceshop", - &LogicList::diceshop, + "apep_spawner", + &LogicList::apep_spawner, + "city_of_gold_ankh_sacrifice", + &LogicList::city_of_gold_ankh_sacrifice, + "duat_bosses_spawner", + &LogicList::duat_bosses_spawner, + "bubbler", + &LogicList::bubbler, + "tusk_pleasure_palace", + &LogicList::tusk_pleasure_palace, + "discovery_info", + &LogicList::discovery_info, + "black_market", + &LogicList::black_market, + "jellyfish_trigger", + &LogicList::jellyfish_trigger, + "arena_1", + &LogicList::arena_1, + "arena_2", + &LogicList::arena_2, + "arena_3", + &LogicList::arena_3, + "arena_alien_blast", + &LogicList::arena_alien_blast, + "arena_loose_bombs", + &LogicList::arena_loose_bombs, "start_logic", - [&lua](LogicList& l, LOGIC idx) -> sol::object // -> Logic - { - auto return_logic = l.start_logic(idx); - // TODO: cast to proper logic type - return sol::make_object(lua, return_logic); - }, + start_logic, "stop_logic", &LogicList::stop_logic); /// Used in LogicList lua.new_usertype( "Logic", "logic_index", - &Logic::logic_index); + sol::readonly(&Logic::logic_index)); /// Used in LogicList lua.new_usertype( "LogicOlmecCutscene", From 790638bcb809a5e64004e353cdbe7775cf5b05a1 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sun, 1 Oct 2023 14:25:17 +0200 Subject: [PATCH 11/16] expose enum --- src/game_api/script/usertypes/state_lua.cpp | 58 +++++++++++++++++++++ src/game_api/state.cpp | 1 - 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/game_api/script/usertypes/state_lua.cpp b/src/game_api/script/usertypes/state_lua.cpp index 152c4d90a..8e71e84fc 100644 --- a/src/game_api/script/usertypes/state_lua.cpp +++ b/src/game_api/script/usertypes/state_lua.cpp @@ -512,6 +512,64 @@ void register_usertypes(sol::state& lua) return sol::make_object(lua, return_logic); }); + lua.create_named_table("LOGIC", // + "TUTORIAL", + LOGIC::TUTORIAL, + "OUROBOROS", + LOGIC::OUROBOROS, + "SPEEDRUN", + LOGIC::SPEEDRUN, + "GHOST", + LOGIC::GHOST, + "GHOST_TOAST", + LOGIC::GHOST_TOAST, + "TUN_AGGRO", + LOGIC::TUN_AGGRO, + "DICESHOP", + LOGIC::DICESHOP, + "PRE_CHALLENGE", + LOGIC::PRE_CHALLENGE, + "MOON_CHALLENGE", + LOGIC::MOON_CHALLENGE, + "STAR_CHALLENGE", + LOGIC::STAR_CHALLENGE, + "SUN_CHALLENGE", + LOGIC::SUN_CHALLENGE, + "MAGMAN_SPAWN", + LOGIC::MAGMAN_SPAWN, + "WATER_BUBBLES", + LOGIC::WATER_BUBBLES, + "OLMEC_CUTSCENE", + LOGIC::OLMEC_CUTSCENE, + "TIAMAT_CUTSCENE", + LOGIC::TIAMAT_CUTSCENE, + "APEP", + LOGIC::APEP, + "COG_SACRIFICE", + LOGIC::COG_SACRIFICE, + "DUAT_BOSSES", + LOGIC::DUAT_BOSSES, + "BUBBLER", + LOGIC::BUBBLER, + "PLEASURE_PALACE", + LOGIC::PLEASURE_PALACE, + "DISCOVERY_INFO", + LOGIC::DISCOVERY_INFO, + "BLACK_MARKET", + LOGIC::BLACK_MARKET, + "JELLYFISH", + LOGIC::JELLYFISH, + "ARENA_1", + LOGIC::ARENA_1, + "ARENA_2", + LOGIC::ARENA_2, + "ARENA_3", + LOGIC::ARENA_3, + "ARENA_ALIEN_BLAST", + LOGIC::ARENA_ALIEN_BLAST, + "ARENA_LOOSE_BOMBS", + LOGIC::ARENA_LOOSE_BOMBS); + /// Used in StateMemory lua.new_usertype( "LogicList", diff --git a/src/game_api/state.cpp b/src/game_api/state.cpp index f39bf575a..e7cf93825 100644 --- a/src/game_api/state.cpp +++ b/src/game_api/state.cpp @@ -905,7 +905,6 @@ Logic* LogicList::start_logic(LOGIC idx) return nullptr; } static auto first_table_entry = get_address("virtual_functions_table"); - VTABLE_OFFSET::LOGIC_APEP_TRIGGER; auto addr = (size_t*)custom_malloc(size); std::memset(addr, 0, size); // just in case From 6b0d08fec00fac6e97b69ab24f96aa5605c8b41b Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Wed, 4 Oct 2023 21:38:40 +0200 Subject: [PATCH 12/16] move logic to separate file, expose all the knows logic stuff --- src/game_api/script/lua_vm.cpp | 2 + src/game_api/script/usertypes/logic_lua.cpp | 373 ++++++++++++++++++++ src/game_api/script/usertypes/logic_lua.hpp | 11 + src/game_api/script/usertypes/state_lua.cpp | 211 ----------- src/game_api/state.cpp | 12 + src/game_api/state_structs.hpp | 9 +- 6 files changed, 403 insertions(+), 215 deletions(-) create mode 100644 src/game_api/script/usertypes/logic_lua.cpp create mode 100644 src/game_api/script/usertypes/logic_lua.hpp diff --git a/src/game_api/script/lua_vm.cpp b/src/game_api/script/lua_vm.cpp index a9f789d9b..7d53814cd 100644 --- a/src/game_api/script/lua_vm.cpp +++ b/src/game_api/script/lua_vm.cpp @@ -81,6 +81,7 @@ #include "usertypes/gui_lua.hpp" // for register_usertypes #include "usertypes/hitbox_lua.hpp" // for register_usertypes #include "usertypes/level_lua.hpp" // for register_usertypes +#include "usertypes/logic_lua.hpp" // for register_usertypes #include "usertypes/particles_lua.hpp" // for register_usertypes #include "usertypes/player_lua.hpp" // for register_usertypes #include "usertypes/prng_lua.hpp" // for register_usertypes @@ -291,6 +292,7 @@ end NBehavior::register_usertypes(lua); NSteam::register_usertypes(lua); NVTables::register_usertypes(lua); + NLogic::register_usertypes(lua); StateMemory* main_state = State::get().ptr_main(); diff --git a/src/game_api/script/usertypes/logic_lua.cpp b/src/game_api/script/usertypes/logic_lua.cpp new file mode 100644 index 000000000..cd69d193f --- /dev/null +++ b/src/game_api/script/usertypes/logic_lua.cpp @@ -0,0 +1,373 @@ +#include "logic_lua.hpp" + +#include +#include // for data_t, global_table, state, proxy... +#include // for basic_usertype + +#include "entity.hpp" +#include "sound_manager.hpp" +#include "state.hpp" +#include "state_structs.hpp" + +namespace NLogic +{ +void register_usertypes(sol::state& lua) +{ + + auto stop_logic = sol::overload( + static_cast(&LogicList::stop_logic), + static_cast(&LogicList::stop_logic)); + + lua.create_named_table("LOGIC", // + "TUTORIAL", + LOGIC::TUTORIAL, + "OUROBOROS", + LOGIC::OUROBOROS, + "SPEEDRUN", + LOGIC::SPEEDRUN, + "GHOST", + LOGIC::GHOST, + "GHOST_TOAST", + LOGIC::GHOST_TOAST, + "TUN_AGGRO", + LOGIC::TUN_AGGRO, + "DICESHOP", + LOGIC::DICESHOP, + "PRE_CHALLENGE", + LOGIC::PRE_CHALLENGE, + "MOON_CHALLENGE", + LOGIC::MOON_CHALLENGE, + "STAR_CHALLENGE", + LOGIC::STAR_CHALLENGE, + "SUN_CHALLENGE", + LOGIC::SUN_CHALLENGE, + "MAGMAN_SPAWN", + LOGIC::MAGMAN_SPAWN, + "WATER_BUBBLES", + LOGIC::WATER_BUBBLES, + "OLMEC_CUTSCENE", + LOGIC::OLMEC_CUTSCENE, + "TIAMAT_CUTSCENE", + LOGIC::TIAMAT_CUTSCENE, + "APEP", + LOGIC::APEP, + "COG_SACRIFICE", + LOGIC::COG_SACRIFICE, + "DUAT_BOSSES", + LOGIC::DUAT_BOSSES, + "BUBBLER", + LOGIC::BUBBLER, + "PLEASURE_PALACE", + LOGIC::PLEASURE_PALACE, + "DISCOVERY_INFO", + LOGIC::DISCOVERY_INFO, + "BLACK_MARKET", + LOGIC::BLACK_MARKET, + "JELLYFISH", + LOGIC::JELLYFISH, + "ARENA_1", + LOGIC::ARENA_1, + "ARENA_2", + LOGIC::ARENA_2, + "ARENA_3", + LOGIC::ARENA_3, + "ARENA_ALIEN_BLAST", + LOGIC::ARENA_ALIEN_BLAST, + "ARENA_LOOSE_BOMBS", + LOGIC::ARENA_LOOSE_BOMBS); + + /// Used in StateMemory + lua.new_usertype( + "LogicList", + "tutorial", + &LogicList::tutorial, + "ouroboros", + &LogicList::ouroboros, + "basecamp_speedrun", + &LogicList::basecamp_speedrun, + "ghost_trigger", + &LogicList::ghost_trigger, + "ghost_toast_trigger", + &LogicList::ghost_toast_trigger, + "tun_aggro", + &LogicList::tun_aggro, + "diceshop", + &LogicList::diceshop, + "tun_pre_challenge", + &LogicList::tun_pre_challenge, + "tun_moon_challenge", + &LogicList::tun_moon_challenge, + "tun_star_challenge", + &LogicList::tun_star_challenge, + "tun_sun_challenge", + &LogicList::tun_sun_challenge, + "magmaman_spawn", + &LogicList::magmaman_spawn, + "water_bubbles", + &LogicList::water_bubbles, + "olmec_cutscene", + &LogicList::olmec_cutscene, + "tiamat_cutscene", + &LogicList::tiamat_cutscene, + "apep_spawner", + &LogicList::apep_spawner, + "city_of_gold_ankh_sacrifice", + &LogicList::city_of_gold_ankh_sacrifice, + "duat_bosses_spawner", + &LogicList::duat_bosses_spawner, + "bubbler", + &LogicList::bubbler, + "tusk_pleasure_palace", + &LogicList::tusk_pleasure_palace, + "discovery_info", + &LogicList::discovery_info, + "black_market", + &LogicList::black_market, + "jellyfish_trigger", + &LogicList::jellyfish_trigger, + "arena_1", + &LogicList::arena_1, + "arena_2", + &LogicList::arena_2, + "arena_3", + &LogicList::arena_3, + "arena_alien_blast", + &LogicList::arena_alien_blast, + "arena_loose_bombs", + &LogicList::arena_loose_bombs, + "start_logic", + [&lua](LogicList& l, LOGIC idx) -> sol::object // -> Logic* + { + auto return_logic = l.start_logic(idx); + // TODO: cast to proper logic type + return sol::make_object(lua, return_logic); + }, + "stop_logic", + stop_logic); + /// Used in LogicList + lua.new_usertype( + "Logic", + "logic_index", + sol::readonly(&Logic::logic_index)); + /// Used in LogicList + lua.new_usertype( + "LogicTutorial", + "pet_tutorial", + &LogicTutorial::pet_tutorial, + "timer", + &LogicTutorial::timer, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicOuroboros", + "sound", + &LogicOuroboros::sound, + "timer", + &LogicOuroboros::timer, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicBasecampSpeedrun", + "administrator", + &LogicBasecampSpeedrun::administrator, + "crate", + &LogicBasecampSpeedrun::crate, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicGhostToast", + "toast_timer", + &LogicGhostToast::toast_timer, + sol::base_classes, + sol::bases()); + /// Used in LogicList + auto logicdiceshop_type = lua.new_usertype("LogicDiceShop", sol::base_classes, sol::bases()); + logicdiceshop_type["boss_uid"] = &LogicDiceShop::boss_uid; + logicdiceshop_type["boss_type"] = &LogicDiceShop::boss_type; + logicdiceshop_type["bet_machine"] = &LogicDiceShop::bet_machine; + logicdiceshop_type["die1"] = &LogicDiceShop::die1; + logicdiceshop_type["die2"] = &LogicDiceShop::die2; + logicdiceshop_type["die_1_value"] = &LogicDiceShop::die_1_value; + logicdiceshop_type["die_2_value"] = &LogicDiceShop::die_2_value; + logicdiceshop_type["prize_dispenser"] = &LogicDiceShop::prize_dispenser; + logicdiceshop_type["prize"] = &LogicDiceShop::prize; + logicdiceshop_type["forcefield"] = &LogicDiceShop::forcefield; + logicdiceshop_type["bet_active"] = &LogicDiceShop::bet_active; + logicdiceshop_type["forcefield_deactivated"] = &LogicDiceShop::forcefield_deactivated; + logicdiceshop_type["boss_angry"] = &LogicDiceShop::boss_angry; + logicdiceshop_type["result_announcement_timer"] = &LogicDiceShop::result_announcement_timer; + logicdiceshop_type["won_prizes_count"] = &LogicDiceShop::won_prizes_count; + logicdiceshop_type["balance"] = &LogicDiceShop::balance; + /// Used in LogicList + lua.new_usertype( + "LogicTunPreChallenge", + "tun_uid", + &LogicTunPreChallenge::tun_uid, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicMoonChallenge", + "floor_challenge_entrance_uid", + &LogicMoonChallenge::floor_challenge_entrance_uid, + "floor_challenge_waitroom_uid", + &LogicMoonChallenge::floor_challenge_waitroom_uid, + "challenge_active", + &LogicMoonChallenge::challenge_active, + "forcefield_countdown", + &LogicMoonChallenge::forcefield_countdown, + "mattock_uid", + &LogicMoonChallenge::mattock_uid, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicStarChallenge", + "floor_challenge_entrance_uid", + &LogicStarChallenge::floor_challenge_entrance_uid, + "floor_challenge_waitroom_uid", + &LogicStarChallenge::floor_challenge_waitroom_uid, + "challenge_active", + &LogicStarChallenge::challenge_active, + "forcefield_countdown", + &LogicStarChallenge::forcefield_countdown, + "torches", + &LogicStarChallenge::torches, + "start_countdown", + &LogicStarChallenge::start_countdown, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicSunChallenge", + "floor_challenge_entrance_uid", + &LogicSunChallenge::floor_challenge_entrance_uid, + "floor_challenge_waitroom_uid", + &LogicSunChallenge::floor_challenge_waitroom_uid, + "challenge_active", + &LogicSunChallenge::challenge_active, + "forcefield_countdown", + &LogicSunChallenge::forcefield_countdown, + "start_countdown", + &LogicSunChallenge::start_countdown, + sol::base_classes, + sol::bases()); + auto add_spawn = sol::overload( + static_cast(&LogicMagmamanSpawn::add_spawn), + static_cast(&LogicMagmamanSpawn::add_spawn)); + auto remove_spawn = sol::overload( + static_cast(&LogicMagmamanSpawn::remove_spawn), + static_cast(&LogicMagmamanSpawn::remove_spawn)); + /// Used in LogicList + lua.new_usertype( + "LogicMagmamanSpawn", + "magmaman_positions", + &LogicMagmamanSpawn::magmaman_positions, + "add_spawn", + add_spawn, + "remove_spawn", + remove_spawn, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicUnderwaterBubbles", + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicOlmecCutscene", + "fx_olmecpart_large", + &LogicOlmecCutscene::fx_olmecpart_large, + "olmec", + &LogicOlmecCutscene::olmec, + "player", + &LogicOlmecCutscene::player, + "cinematic_anchor", + &LogicOlmecCutscene::cinematic_anchor, + "timer", + &LogicOlmecCutscene::timer, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicTiamatCutscene", + "tiamat", + &LogicTiamatCutscene::tiamat, + "player", + &LogicTiamatCutscene::player, + "cinematic_anchor", + &LogicTiamatCutscene::cinematic_anchor, + "timer", + &LogicTiamatCutscene::timer, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicApepTrigger", + "spawn_cooldown", + &LogicApepTrigger::spawn_cooldown, + "cooling_down", + &LogicApepTrigger::cooling_down, + "apep_journal_entry_logged", + &LogicApepTrigger::apep_journal_entry_logged, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicCOGAnkhSacrifice", + "timer", + &LogicCOGAnkhSacrifice::timer, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicTiamatBubbles", + "bubble_spawn_timer", + &LogicTiamatBubbles::bubble_spawn_timer, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicTuskPleasurePalace", + "locked_door", + &LogicTuskPleasurePalace::locked_door, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicArena1", + "crate_spawn_timer", + &LogicArena1::crate_spawn_timer, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicArenaAlienBlast", + "timer", + &LogicArenaAlienBlast::timer, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicArenaLooseBombs", + "timer", + &LogicArenaLooseBombs::timer, + sol::base_classes, + sol::bases()); + + /// Used in LogicMagmamanSpawn + lua.new_usertype( + "MagmamanSpawnPosition", + sol::constructors{}, + "x", + &MagmamanSpawnPosition::x, + "y", + &MagmamanSpawnPosition::y, + "timer", + &MagmamanSpawnPosition::timer); +} +} // namespace NLogic diff --git a/src/game_api/script/usertypes/logic_lua.hpp b/src/game_api/script/usertypes/logic_lua.hpp new file mode 100644 index 000000000..ea4308ac2 --- /dev/null +++ b/src/game_api/script/usertypes/logic_lua.hpp @@ -0,0 +1,11 @@ +#pragma once + +namespace sol +{ +class state; +} // namespace sol + +namespace NLogic +{ +void register_usertypes(sol::state& lua); +}; diff --git a/src/game_api/script/usertypes/state_lua.cpp b/src/game_api/script/usertypes/state_lua.cpp index 8e71e84fc..0e770ea02 100644 --- a/src/game_api/script/usertypes/state_lua.cpp +++ b/src/game_api/script/usertypes/state_lua.cpp @@ -498,217 +498,6 @@ void register_usertypes(sol::state& lua) "get_code", &OnlineLobby::get_code); - auto start_logic = sol::overload( - [&lua](LogicList& l, LOGIC idx) -> sol::object - { - auto return_logic = l.start_logic(idx); - // TODO: cast to proper logic type - return sol::make_object(lua, return_logic); - }, - [&lua](LogicList& l, Logic* logic) -> sol::object - { - auto return_logic = l.start_logic(logic->logic_index); - // TODO: cast to proper logic type - return sol::make_object(lua, return_logic); - }); - - lua.create_named_table("LOGIC", // - "TUTORIAL", - LOGIC::TUTORIAL, - "OUROBOROS", - LOGIC::OUROBOROS, - "SPEEDRUN", - LOGIC::SPEEDRUN, - "GHOST", - LOGIC::GHOST, - "GHOST_TOAST", - LOGIC::GHOST_TOAST, - "TUN_AGGRO", - LOGIC::TUN_AGGRO, - "DICESHOP", - LOGIC::DICESHOP, - "PRE_CHALLENGE", - LOGIC::PRE_CHALLENGE, - "MOON_CHALLENGE", - LOGIC::MOON_CHALLENGE, - "STAR_CHALLENGE", - LOGIC::STAR_CHALLENGE, - "SUN_CHALLENGE", - LOGIC::SUN_CHALLENGE, - "MAGMAN_SPAWN", - LOGIC::MAGMAN_SPAWN, - "WATER_BUBBLES", - LOGIC::WATER_BUBBLES, - "OLMEC_CUTSCENE", - LOGIC::OLMEC_CUTSCENE, - "TIAMAT_CUTSCENE", - LOGIC::TIAMAT_CUTSCENE, - "APEP", - LOGIC::APEP, - "COG_SACRIFICE", - LOGIC::COG_SACRIFICE, - "DUAT_BOSSES", - LOGIC::DUAT_BOSSES, - "BUBBLER", - LOGIC::BUBBLER, - "PLEASURE_PALACE", - LOGIC::PLEASURE_PALACE, - "DISCOVERY_INFO", - LOGIC::DISCOVERY_INFO, - "BLACK_MARKET", - LOGIC::BLACK_MARKET, - "JELLYFISH", - LOGIC::JELLYFISH, - "ARENA_1", - LOGIC::ARENA_1, - "ARENA_2", - LOGIC::ARENA_2, - "ARENA_3", - LOGIC::ARENA_3, - "ARENA_ALIEN_BLAST", - LOGIC::ARENA_ALIEN_BLAST, - "ARENA_LOOSE_BOMBS", - LOGIC::ARENA_LOOSE_BOMBS); - - /// Used in StateMemory - lua.new_usertype( - "LogicList", - "tutorial", - &LogicList::tutorial, - "ouroboros", - &LogicList::ouroboros, - "basecamp_speedrun", - &LogicList::basecamp_speedrun, - "ghost_trigger", - &LogicList::ghost_trigger, - "ghost_toast_trigger", - &LogicList::ghost_toast_trigger, - "tun_aggro", - &LogicList::tun_aggro, - "diceshop", - &LogicList::diceshop, - "tun_pre_challenge", - &LogicList::tun_pre_challenge, - "tun_moon_challenge", - &LogicList::tun_moon_challenge, - "tun_star_challenge", - &LogicList::tun_star_challenge, - "tun_sun_challenge", - &LogicList::tun_sun_challenge, - "magmaman_spawn", - &LogicList::magmaman_spawn, - "water_bubbles", - &LogicList::water_bubbles, - "olmec_cutscene", - &LogicList::olmec_cutscene, - "tiamat_cutscene", - &LogicList::tiamat_cutscene, - "apep_spawner", - &LogicList::apep_spawner, - "city_of_gold_ankh_sacrifice", - &LogicList::city_of_gold_ankh_sacrifice, - "duat_bosses_spawner", - &LogicList::duat_bosses_spawner, - "bubbler", - &LogicList::bubbler, - "tusk_pleasure_palace", - &LogicList::tusk_pleasure_palace, - "discovery_info", - &LogicList::discovery_info, - "black_market", - &LogicList::black_market, - "jellyfish_trigger", - &LogicList::jellyfish_trigger, - "arena_1", - &LogicList::arena_1, - "arena_2", - &LogicList::arena_2, - "arena_3", - &LogicList::arena_3, - "arena_alien_blast", - &LogicList::arena_alien_blast, - "arena_loose_bombs", - &LogicList::arena_loose_bombs, - "start_logic", - start_logic, - "stop_logic", - &LogicList::stop_logic); - /// Used in LogicList - lua.new_usertype( - "Logic", - "logic_index", - sol::readonly(&Logic::logic_index)); - /// Used in LogicList - lua.new_usertype( - "LogicOlmecCutscene", - "olmec", - &LogicOlmecCutscene::olmec, - "player", - &LogicOlmecCutscene::player, - "cinematic_anchor", - &LogicOlmecCutscene::cinematic_anchor, - "timer", - &LogicOlmecCutscene::timer, - sol::base_classes, - sol::bases()); - /// Used in LogicList - lua.new_usertype( - "LogicTiamatCutscene", - "tiamat", - &LogicTiamatCutscene::tiamat, - "player", - &LogicTiamatCutscene::player, - "cinematic_anchor", - &LogicTiamatCutscene::cinematic_anchor, - "timer", - &LogicTiamatCutscene::timer, - sol::base_classes, - sol::bases()); - /// Used in LogicList - lua.new_usertype( - "MagmamanSpawnPosition", - sol::constructors{}, - "x", - &MagmamanSpawnPosition::x, - "y", - &MagmamanSpawnPosition::y, - "timer", - &MagmamanSpawnPosition::timer); - auto add_spawn = sol::overload( - static_cast(&LogicMagmamanSpawn::add_spawn), - static_cast(&LogicMagmamanSpawn::add_spawn)); - auto remove_spawn = sol::overload( - static_cast(&LogicMagmamanSpawn::remove_spawn), - static_cast(&LogicMagmamanSpawn::remove_spawn)); - - lua.new_usertype( - "LogicVolcana", - "magmaman_positions", - &LogicMagmamanSpawn::magmaman_positions, - "add_spawn", - add_spawn, - "remove_spawn", - remove_spawn, - sol::base_classes, - sol::bases()); - - /// Used in LogicList - auto logicdiceshop_type = lua.new_usertype("LogicDiceShop", sol::base_classes, sol::bases()); - logicdiceshop_type["bet_machine"] = &LogicDiceShop::bet_machine; - logicdiceshop_type["die1"] = &LogicDiceShop::die1; - logicdiceshop_type["die2"] = &LogicDiceShop::die2; - logicdiceshop_type["die_1_value"] = &LogicDiceShop::die_1_value; - logicdiceshop_type["die_2_value"] = &LogicDiceShop::die_2_value; - logicdiceshop_type["prize_dispenser"] = &LogicDiceShop::prize_dispenser; - logicdiceshop_type["prize"] = &LogicDiceShop::prize; - logicdiceshop_type["forcefield"] = &LogicDiceShop::forcefield; - logicdiceshop_type["bet_active"] = &LogicDiceShop::bet_active; - logicdiceshop_type["forcefield_deactivated"] = &LogicDiceShop::forcefield_deactivated; - logicdiceshop_type["boss_angry"] = &LogicDiceShop::boss_angry; - logicdiceshop_type["result_announcement_timer"] = &LogicDiceShop::result_announcement_timer; - logicdiceshop_type["won_prizes_count"] = &LogicDiceShop::won_prizes_count; - logicdiceshop_type["balance"] = &LogicDiceShop::balance; - /// Used in StateMemory lua.new_usertype("RoomOwnersInfo", "owned_items", &RoomOwnersInfo::owned_items, "owned_rooms", &RoomOwnersInfo::owned_rooms); diff --git a/src/game_api/state.cpp b/src/game_api/state.cpp index e7cf93825..b46f97d73 100644 --- a/src/game_api/state.cpp +++ b/src/game_api/state.cpp @@ -913,6 +913,8 @@ Logic* LogicList::start_logic(LOGIC idx) Logic* new_logic = (Logic*)addr; new_logic->logic_index = idx; + // TODO: set up logic that is not possible to initialize thru the API + logic_indexed[(uint32_t)idx] = new_logic; return new_logic; } @@ -926,6 +928,16 @@ void LogicList::stop_logic(LOGIC idx) logic_indexed[(uint32_t)idx] = nullptr; } +void LogicList::stop_logic(Logic* log) +{ + if (log == nullptr) + return; + + auto idx = log->logic_index; + delete log; + logic_indexed[(uint32_t)idx] = nullptr; +} + void LogicMagmamanSpawn::add_spawn(uint32_t x, uint32_t y) { magmaman_positions.emplace_back(x, y); diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index ffef32c6a..66b743e45 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -445,7 +445,7 @@ class LogicBasecampSpeedrun : public Logic { public: /// entity uid of the character that keeps the time - uint32_t official; + uint32_t administrator; /// entity uid. you must break this crate for the run to be valid, otherwise you're cheating uint32_t crate; }; @@ -500,7 +500,7 @@ class LogicMoonChallenge : public Logic uint16_t unknown8a; uint16_t unknown8b; // entity uid - int32_t mattock; + int32_t mattock_uid; }; class LogicStarChallenge : public Logic @@ -514,7 +514,7 @@ class LogicStarChallenge : public Logic uint8_t forcefield_countdown; // waiting area forcefield activation timer (the one that locks you in) uint16_t unknown7; uint32_t unknown8; - std::vector torches; + std::vector torches; // TODO: check if custom vector (probably yes) uint8_t start_countdown; uint8_t padding[3]; uint32_t unknown9; @@ -672,9 +672,10 @@ class LogicTutorial : public Logic struct LogicList { /// This only properly constructs the base class - /// you probably will need to set the parameters correctly + /// you may still need to initialise the parameters correctly Logic* start_logic(LOGIC idx); void stop_logic(LOGIC idx); + void stop_logic(Logic* log); union { From b37dacecbb8c67a3092a15bd551a4e49f4ae68e9 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 5 Oct 2023 21:57:49 +0200 Subject: [PATCH 13/16] casting, some fixing, make it work --- src/game_api/entities_activefloors.cpp | 6 +- src/game_api/script/usertypes/logic_lua.cpp | 95 ++++++++++++++------- src/game_api/sound_manager.cpp | 12 +++ src/game_api/sound_manager.hpp | 5 ++ src/game_api/state.cpp | 22 ++++- src/game_api/state_structs.hpp | 54 ++++++------ 6 files changed, 129 insertions(+), 65 deletions(-) diff --git a/src/game_api/entities_activefloors.cpp b/src/game_api/entities_activefloors.cpp index 145540261..d0db120c7 100644 --- a/src/game_api/entities_activefloors.cpp +++ b/src/game_api/entities_activefloors.cpp @@ -38,8 +38,6 @@ void Drill::trigger() move_state = 6; flags = flags & ~(1U << (10 - 1)); - using construct_soundposition_ptr_fun_t = SoundMeta*(uint32_t id, bool background_sound); - static const auto construct_soundposition_ptr_call = (construct_soundposition_ptr_fun_t*)get_address("construct_soundmeta"); - sound1 = construct_soundposition_ptr_call(0x159, 0); - sound2 = construct_soundposition_ptr_call(0x153, 0); + sound1 = construct_soundmeta(0x159, false); + sound2 = construct_soundmeta(0x153, false); } diff --git a/src/game_api/script/usertypes/logic_lua.cpp b/src/game_api/script/usertypes/logic_lua.cpp index cd69d193f..7aefb1445 100644 --- a/src/game_api/script/usertypes/logic_lua.cpp +++ b/src/game_api/script/usertypes/logic_lua.cpp @@ -136,11 +136,56 @@ void register_usertypes(sol::state& lua) "arena_loose_bombs", &LogicList::arena_loose_bombs, "start_logic", - [&lua](LogicList& l, LOGIC idx) -> sol::object // -> Logic* + [&lua](LogicList& l, LOGIC idx) -> sol::object // -> mixed* { auto return_logic = l.start_logic(idx); - // TODO: cast to proper logic type - return sol::make_object(lua, return_logic); + switch (idx) + { + case LOGIC::TUTORIAL: + return sol::make_object(lua, (LogicTutorial*)return_logic); + case LOGIC::OUROBOROS: + return sol::make_object(lua, (LogicOuroboros*)return_logic); + case LOGIC::SPEEDRUN: + return sol::make_object(lua, (LogicBasecampSpeedrun*)return_logic); + case LOGIC::GHOST_TOAST: + return sol::make_object(lua, (LogicGhostToast*)return_logic); + case LOGIC::DICESHOP: + return sol::make_object(lua, (LogicDiceShop*)return_logic); + case LOGIC::PRE_CHALLENGE: + return sol::make_object(lua, (LogicTunPreChallenge*)return_logic); + case LOGIC::MOON_CHALLENGE: + return sol::make_object(lua, (LogicMoonChallenge*)return_logic); + case LOGIC::STAR_CHALLENGE: + return sol::make_object(lua, (LogicStarChallenge*)return_logic); + case LOGIC::SUN_CHALLENGE: + return sol::make_object(lua, (LogicSunChallenge*)return_logic); + case LOGIC::MAGMAN_SPAWN: + return sol::make_object(lua, (LogicMagmamanSpawn*)return_logic); + case LOGIC::WATER_BUBBLES: + return sol::make_object(lua, (LogicUnderwaterBubbles*)return_logic); + case LOGIC::OLMEC_CUTSCENE: + return sol::make_object(lua, (LogicOlmecCutscene*)return_logic); + case LOGIC::TIAMAT_CUTSCENE: + return sol::make_object(lua, (LogicTiamatCutscene*)return_logic); + case LOGIC::APEP: + return sol::make_object(lua, (LogicApepTrigger*)return_logic); + case LOGIC::COG_SACRIFICE: + return sol::make_object(lua, (LogicCOGAnkhSacrifice*)return_logic); + case LOGIC::BUBBLER: + return sol::make_object(lua, (LogicTiamatBubbles*)return_logic); + case LOGIC::PLEASURE_PALACE: + return sol::make_object(lua, (LogicTuskPleasurePalace*)return_logic); + case LOGIC::ARENA_1: + return sol::make_object(lua, (LogicArena1*)return_logic); + // case LOGIC::ARENA_2: + // return sol::make_object(lua, () return_logic); + case LOGIC::ARENA_ALIEN_BLAST: + return sol::make_object(lua, (LogicArenaAlienBlast*)return_logic); + case LOGIC::ARENA_LOOSE_BOMBS: + return sol::make_object(lua, (LogicArenaLooseBombs*)return_logic); + default: + return sol::make_object(lua, return_logic); + } }, "stop_logic", stop_logic); @@ -197,7 +242,8 @@ void register_usertypes(sol::state& lua) logicdiceshop_type["forcefield"] = &LogicDiceShop::forcefield; logicdiceshop_type["bet_active"] = &LogicDiceShop::bet_active; logicdiceshop_type["forcefield_deactivated"] = &LogicDiceShop::forcefield_deactivated; - logicdiceshop_type["boss_angry"] = &LogicDiceShop::boss_angry; + /// NoDoc + logicdiceshop_type["boss_angry"] = &LogicDiceShop::unknown; logicdiceshop_type["result_announcement_timer"] = &LogicDiceShop::result_announcement_timer; logicdiceshop_type["won_prizes_count"] = &LogicDiceShop::won_prizes_count; logicdiceshop_type["balance"] = &LogicDiceShop::balance; @@ -208,53 +254,42 @@ void register_usertypes(sol::state& lua) &LogicTunPreChallenge::tun_uid, sol::base_classes, sol::bases()); - /// Used in LogicList - lua.new_usertype( - "LogicMoonChallenge", + /// Used in LogicMoonChallenge, LogicStarChallenge, LogicSunChallenge + lua.new_usertype( + "LogicChallenge", "floor_challenge_entrance_uid", - &LogicMoonChallenge::floor_challenge_entrance_uid, + &LogicChallenge::floor_challenge_entrance_uid, "floor_challenge_waitroom_uid", - &LogicMoonChallenge::floor_challenge_waitroom_uid, + &LogicChallenge::floor_challenge_waitroom_uid, "challenge_active", - &LogicMoonChallenge::challenge_active, + &LogicChallenge::challenge_active, "forcefield_countdown", - &LogicMoonChallenge::forcefield_countdown, + &LogicChallenge::forcefield_countdown, + sol::base_classes, + sol::bases()); + /// Used in LogicList + lua.new_usertype( + "LogicMoonChallenge", "mattock_uid", &LogicMoonChallenge::mattock_uid, sol::base_classes, - sol::bases()); + sol::bases()); /// Used in LogicList lua.new_usertype( "LogicStarChallenge", - "floor_challenge_entrance_uid", - &LogicStarChallenge::floor_challenge_entrance_uid, - "floor_challenge_waitroom_uid", - &LogicStarChallenge::floor_challenge_waitroom_uid, - "challenge_active", - &LogicStarChallenge::challenge_active, - "forcefield_countdown", - &LogicStarChallenge::forcefield_countdown, "torches", &LogicStarChallenge::torches, "start_countdown", &LogicStarChallenge::start_countdown, sol::base_classes, - sol::bases()); + sol::bases()); /// Used in LogicList lua.new_usertype( "LogicSunChallenge", - "floor_challenge_entrance_uid", - &LogicSunChallenge::floor_challenge_entrance_uid, - "floor_challenge_waitroom_uid", - &LogicSunChallenge::floor_challenge_waitroom_uid, - "challenge_active", - &LogicSunChallenge::challenge_active, - "forcefield_countdown", - &LogicSunChallenge::forcefield_countdown, "start_countdown", &LogicSunChallenge::start_countdown, sol::base_classes, - sol::bases()); + sol::bases()); auto add_spawn = sol::overload( static_cast(&LogicMagmamanSpawn::add_spawn), static_cast(&LogicMagmamanSpawn::add_spawn)); diff --git a/src/game_api/sound_manager.cpp b/src/game_api/sound_manager.cpp index 75bfd3991..33c23252b 100644 --- a/src/game_api/sound_manager.cpp +++ b/src/game_api/sound_manager.cpp @@ -914,3 +914,15 @@ SoundMeta* play_sound(VANILLA_SOUND sound, uint32_t source_uid) } return sound_info; } + +SoundMeta* construct_soundmeta(VANILLA_SOUND sound, bool background_sound) +{ + return construct_soundmeta(sound_name_to_id(sound), background_sound); +} + +SoundMeta* construct_soundmeta(uint32_t sound_id, bool background_sound) +{ + using construct_soundposition_ptr_fun_t = SoundMeta*(uint32_t id, bool background_sound); + static const auto construct_soundposition_ptr_call = (construct_soundposition_ptr_fun_t*)get_address("construct_soundmeta"); + return construct_soundposition_ptr_call(sound_id, background_sound); +} diff --git a/src/game_api/sound_manager.hpp b/src/game_api/sound_manager.hpp index e1e41d137..14e5de664 100644 --- a/src/game_api/sound_manager.hpp +++ b/src/game_api/sound_manager.hpp @@ -294,3 +294,8 @@ struct BackgroundSound : public SoundMeta /// Use source_uid to make the sound be played at the location of that entity, set it -1 to just play it "everywhere" /// Returns SoundMeta (read only), beware that after the sound starts, that memory is no longer valid SoundMeta* play_sound(VANILLA_SOUND sound, uint32_t source_uid); + +// could probably be exposed if someone can actually figure out how to properly "register it"? +// it also needs to make sure the lua owns the returned object and it will properly delete it +SoundMeta* construct_soundmeta(VANILLA_SOUND sound, bool background_sound); +SoundMeta* construct_soundmeta(uint32_t sound_id, bool background_sound); diff --git a/src/game_api/state.cpp b/src/game_api/state.cpp index b46f97d73..c809e87d8 100644 --- a/src/game_api/state.cpp +++ b/src/game_api/state.cpp @@ -27,6 +27,7 @@ #include "script/lua_vm.hpp" // for get_lua_vm #include "script/usertypes/theme_vtable_lua.hpp" // for NThemeVTables #include "search.hpp" // for get_address +#include "sound_manager.hpp" // #include "spawn_api.hpp" // for init_spawn_hooks #include "steam_api.hpp" // for init_achievement_hooks #include "strings.hpp" // for strings_init @@ -913,7 +914,26 @@ Logic* LogicList::start_logic(LOGIC idx) Logic* new_logic = (Logic*)addr; new_logic->logic_index = idx; - // TODO: set up logic that is not possible to initialize thru the API + // set up logic that is not possible to initialize thru the API + if (idx == LOGIC::WATER_BUBBLES) + { + auto proper_type = (LogicUnderwaterBubbles*)new_logic; + proper_type->unknown1 = 1.0f; + proper_type->unknown2 = 1000; + proper_type->unknown3 = true; + } + else if (idx == LOGIC::OUROBOROS) + { + auto proper_type = (LogicOuroboros*)new_logic; + proper_type->sound = construct_soundmeta(0x51, false); + // proper_type->sound->start(); // it needs something more + // game stores the pointer in a special temp memory or something + } + else if (idx == LOGIC::PLEASURE_PALACE) + { + auto proper_type = (LogicTuskPleasurePalace*)new_logic; + proper_type->unknown4 = 1552; // magic? + } logic_indexed[(uint32_t)idx] = new_logic; return new_logic; diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index 66b743e45..6a3198187 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -453,6 +453,7 @@ class LogicBasecampSpeedrun : public Logic class LogicGhostToast : public Logic { public: + /// default 90 uint32_t toast_timer; }; @@ -478,7 +479,7 @@ class LogicDiceShop : public Logic uint32_t forcefield; bool bet_active; bool forcefield_deactivated; - bool boss_angry; + bool unknown; /// the time the boss waits after your second die throw to announce the results uint8_t result_announcement_timer; uint8_t won_prizes_count; @@ -487,7 +488,7 @@ class LogicDiceShop : public Logic int32_t balance; }; -class LogicMoonChallenge : public Logic +class LogicChallenge : public Logic { public: uint32_t unknown3; @@ -496,47 +497,35 @@ class LogicMoonChallenge : public Logic uint32_t floor_challenge_waitroom_uid; bool challenge_active; uint8_t forcefield_countdown; // waiting area forcefield activation timer (the one that locks you in) - uint16_t unknown7; - uint16_t unknown8a; - uint16_t unknown8b; - // entity uid + uint16_t padding1; + uint32_t padding2; +}; + +class LogicMoonChallenge : public LogicChallenge +{ + public: + /// entity uid int32_t mattock_uid; }; -class LogicStarChallenge : public Logic +class LogicStarChallenge : public LogicChallenge { public: - uint32_t unknown3; - uint32_t unknown4; - uint32_t floor_challenge_entrance_uid; - uint32_t floor_challenge_waitroom_uid; - bool challenge_active; - uint8_t forcefield_countdown; // waiting area forcefield activation timer (the one that locks you in) - uint16_t unknown7; - uint32_t unknown8; std::vector torches; // TODO: check if custom vector (probably yes) uint8_t start_countdown; uint8_t padding[3]; uint32_t unknown9; float unknown10; // position in front of tun and one tile higher, dunno what for? - float unknown11; + float unknown11; // kind of would make sense for the wanted poster, but you get this struct after you buy the challenge, not possible when tun is angry? }; -class LogicSunChallenge : public Logic +class LogicSunChallenge : public LogicChallenge { public: - uint32_t unknown3; - uint32_t unknown4; - uint32_t floor_challenge_entrance_uid; - uint32_t floor_challenge_waitroom_uid; - bool challenge_active; - uint8_t forcefield_countdown; // waiting area forcefield activation timer (the one that locks you in) - uint16_t unknown7; - uint32_t unknown8; uint8_t start_countdown; uint8_t padding[3]; uint32_t unknown9; - float unknown10; // position in front of tun and one tile higher, dunno what for? + float unknown10; // same as for LogicStarChallenge float unknown11; }; @@ -619,7 +608,7 @@ class LogicTuskPleasurePalace : public Logic { public: int32_t locked_door; // entity uid - uint32_t unknown4; // always 1552 + uint32_t unknown4; // default 1552 uint32_t unknown5; // dunno uint32_t unknown6; // padding probably }; @@ -646,9 +635,12 @@ class LogicUnderwaterBubbles : public Logic { public: // no idea what does are, messing with them can crash - float unknown1; // 1.0 - int16_t unknown2; // 1000 - int8_t unknown3; // 1 or 0, probably bool + float unknown1; // default: 1.0, excludes liquid from spawning the bubbles by y level from the top to bottom + // is treated like number (calculations to get the right grid entity level) + // it's more like a value in rooms than y coordinates + + int16_t unknown2; // default: 1000 + bool unknown3; // default: 1 or 0 }; class LogicTunPreChallenge : public Logic @@ -687,6 +679,7 @@ struct LogicList LogicOuroboros* ouroboros; /// Keep track of time, player position passing official LogicBasecampSpeedrun* basecamp_speedrun; + /// It's absence is the only reason why ghost doesn't spawn at boss levels or CO Logic* ghost_trigger; // virtual does nothing, all the code elsewhere, the only purpose is to mark if ghost should spawn this level or not LogicGhostToast* ghost_toast_trigger; /// Spawns tun at the door at 30s mark @@ -702,6 +695,7 @@ struct LogicList LogicUnderwaterBubbles* water_bubbles; LogicOlmecCutscene* olmec_cutscene; LogicTiamatCutscene* tiamat_cutscene; + /// Works only if the level has at least one room ROOM_TEMPLATE.APEP, and it still spawns apep at hardcoded positions LogicApepTrigger* apep_spawner; /// All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) LogicCOGAnkhSacrifice* city_of_gold_ankh_sacrifice; From ae5241ff7c486c3a3653ba99fdfe725dd198868d Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 5 Oct 2023 22:26:03 +0200 Subject: [PATCH 14/16] update doc, also not sure why i had to make the change in the `parse_source.py` but it was giving me a weird error --- docs/game_data/spel2.lua | 203 +++++++++++++++++++++++-------- docs/parse_source.py | 4 +- docs/src/includes/_enums.md | 38 ++++++ docs/src/includes/_types.md | 230 +++++++++++++++++++++++++++++++++--- 4 files changed, 408 insertions(+), 67 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index f9f06777c..869dcc6d4 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -2034,51 +2034,6 @@ do ---@field local_player_slot integer ---@field get_code fun(self): string @Gets the string equivalent of the code ----@class LogicList - ---@field olmec_cutscene LogicOlmecCutscene - ---@field tiamat_cutscene LogicTiamatCutscene - ---@field magmaman_spawn LogicMagmamanSpawn - ---@field diceshop LogicDiceShop - ----@class Logic - ---@field logic_index integer - ----@class LogicOlmecCutscene : Logic - ---@field olmec Entity - ---@field player Entity - ---@field cinematic_anchor Entity - ---@field timer integer - ----@class LogicTiamatCutscene : Logic - ---@field tiamat Entity - ---@field player Entity - ---@field cinematic_anchor Entity - ---@field timer integer - ----@class MagmamanSpawnPosition - ---@field x integer - ---@field y integer - ---@field timer integer - ----@class LogicVolcana : Logic - ---@field magmaman_positions custom_Array - ----@class LogicDiceShop : Logic - ---@field bet_machine integer - ---@field die1 integer - ---@field die2 integer - ---@field die_1_value integer - ---@field die_2_value integer - ---@field prize_dispenser integer - ---@field prize integer - ---@field forcefield integer - ---@field bet_active boolean - ---@field forcefield_deactivated boolean - ---@field boss_angry boolean - ---@field result_announcement_timer integer - ---@field won_prizes_count integer - ---@field balance integer - ---@class RoomOwnersInfo ---@field owned_items custom_map @key/index is the uid of an item ---@field owned_rooms RoomOwnerDetails[] @@ -5922,6 +5877,152 @@ function Quad:is_point_inside(x, y, epsilon) end ---@field player_create_giblets boolean[] @size: MAX_PLAYERS ---@field next_sidepanel_slidein_timer number +---@class LogicList + ---@field tutorial LogicTutorial @Handles dropping of the torch and rope in intro routine (first time play) + ---@field ouroboros LogicOuroboros + ---@field basecamp_speedrun LogicBasecampSpeedrun @Keep track of time, player position passing official + ---@field ghost_trigger Logic @It's absence is the only reason why ghost doesn't spawn at boss levels or CO + ---@field ghost_toast_trigger LogicGhostToast + ---@field tun_aggro Logic @Spawns tun at the door at 30s mark + ---@field diceshop LogicDiceShop + ---@field tun_pre_challenge LogicTunPreChallenge + ---@field tun_moon_challenge LogicMoonChallenge + ---@field tun_star_challenge LogicStarChallenge + ---@field tun_sun_challenge LogicSunChallenge + ---@field magmaman_spawn LogicMagmamanSpawn + ---@field water_bubbles LogicUnderwaterBubbles @Only the bubbles that spawn from the floor
Even without it, entities moving in water still spawn bubbles + ---@field olmec_cutscene LogicOlmecCutscene + ---@field tiamat_cutscene LogicTiamatCutscene + ---@field apep_spawner LogicApepTrigger @Works only if the level has at least one room ROOM_TEMPLATE.APEP, and it still spawns apep at hardcoded positions + ---@field city_of_gold_ankh_sacrifice LogicCOGAnkhSacrifice @All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) + ---@field duat_bosses_spawner Logic + ---@field bubbler LogicTiamatBubbles @Spawn rising bubbles at Tiamat (position hardcoded) + ---@field tusk_pleasure_palace LogicTuskPleasurePalace @Triggers aggro on everyone when non-high roller enters door + ---@field discovery_info Logic @black market, vlad, wet fur discovery, logic shows the toast + ---@field black_market Logic @Changes the camera bounds when you reach black market + ---@field jellyfish_trigger Logic + ---@field arena_1 LogicArena1 @Handles create spawns and more, is cleared as soon as the winner is decided (on last player alive) + ---@field arena_2 Logic + ---@field arena_3 Logic @Handles time end death + ---@field arena_alien_blast LogicArenaAlienBlast + ---@field arena_loose_bombs LogicArenaLooseBombs + ---@field start_logic any @[&lua](LogicList&l + +---@class Logic + ---@field logic_index LOGIC + +---@class LogicTutorial : Logic + ---@field pet_tutorial Entity + ---@field timer integer + +---@class LogicOuroboros : Logic + ---@field sound SoundMeta + ---@field timer integer + +---@class LogicBasecampSpeedrun : Logic + ---@field administrator integer @entity uid of the character that keeps the time + ---@field crate integer @entity uid. you must break this crate for the run to be valid, otherwise you're cheating + +---@class LogicGhostToast : Logic + ---@field toast_timer integer @ default 90 + +---@class LogicDiceShop : Logic + ---@field boss_uid integer + ---@field boss_type ENT_TYPE + ---@field bet_machine integer @entity uid + ---@field die1 integer @entity uid + ---@field die2 integer @entity uid + ---@field die_1_value integer + ---@field die_2_value integer + ---@field prize_dispenser integer @entity uid + ---@field prize integer @entity uid + ---@field forcefield integer @entity uid + ---@field bet_active boolean + ---@field forcefield_deactivated boolean + ---@field result_announcement_timer integer @the time the boss waits after your second die throw to announce the results + ---@field won_prizes_count integer + ---@field balance integer @cash balance of all the games + +---@class LogicTunPreChallenge : Logic + ---@field tun_uid integer + +---@class LogicChallenge : Logic + ---@field floor_challenge_entrance_uid integer + ---@field floor_challenge_waitroom_uid integer + ---@field challenge_active boolean + ---@field forcefield_countdown integer + +---@class LogicMoonChallenge : LogicChallenge + ---@field mattock_uid integer @entity uid + +---@class LogicStarChallenge : LogicChallenge + ---@field torches Entity[] + ---@field start_countdown integer + +---@class LogicSunChallenge : LogicChallenge + ---@field start_countdown integer + +---@class LogicMagmamanSpawn : Logic + ---@field magmaman_positions custom_Array +local LogicMagmamanSpawn = nil +---@param x integer +---@param y integer +---@return nil +function LogicMagmamanSpawn:add_spawn(x, y) end +---@param ms MagmamanSpawnPosition +---@return nil +function LogicMagmamanSpawn:add_spawn(ms) end +---@param x integer +---@param y integer +---@return nil +function LogicMagmamanSpawn:remove_spawn(x, y) end +---@param ms MagmamanSpawnPosition +---@return nil +function LogicMagmamanSpawn:remove_spawn(ms) end + +---@class LogicUnderwaterBubbles : Logic + +---@class LogicOlmecCutscene : Logic + ---@field fx_olmecpart_large Entity + ---@field olmec Entity + ---@field player Entity + ---@field cinematic_anchor Entity + ---@field timer integer + +---@class LogicTiamatCutscene : Logic + ---@field tiamat Entity + ---@field player Entity + ---@field cinematic_anchor Entity + ---@field timer integer + +---@class LogicApepTrigger : Logic + ---@field spawn_cooldown integer + ---@field cooling_down boolean + ---@field apep_journal_entry_logged boolean + +---@class LogicCOGAnkhSacrifice : Logic + ---@field timer integer + +---@class LogicTiamatBubbles : Logic + ---@field bubble_spawn_timer integer + +---@class LogicTuskPleasurePalace : Logic + ---@field locked_door integer + +---@class LogicArena1 : Logic + ---@field crate_spawn_timer integer + +---@class LogicArenaAlienBlast : Logic + ---@field timer integer + +---@class LogicArenaLooseBombs : Logic + ---@field timer integer + +---@class MagmamanSpawnPosition + ---@field x integer + ---@field y integer + ---@field timer integer + end --## Static class functions @@ -5960,12 +6061,6 @@ function Color:fuchsia() end function Color:purple() end --## Constructors - -MagmamanSpawnPosition = nil ----@param x_ integer ----@param y_ integer ----@return MagmamanSpawnPosition -function MagmamanSpawnPosition:new(x_, y_) end ---Create a new color - defaults to black ---@return Color function Color:new() end @@ -6084,6 +6179,12 @@ function Quad:new(_bottom_left_x, _bottom_left_y, _bottom_right_x, _bottom_right ---@return Quad function Quad:new(aabb) end +MagmamanSpawnPosition = nil +---@param x_ integer +---@param y_ integer +---@return MagmamanSpawnPosition +function MagmamanSpawnPosition:new(x_, y_) end + --## Enums diff --git a/docs/parse_source.py b/docs/parse_source.py index 8f00d989e..dbd0cec7c 100644 --- a/docs/parse_source.py +++ b/docs/parse_source.py @@ -104,6 +104,7 @@ "../src/game_api/script/usertypes/screen_arena_lua.cpp", "../src/game_api/script/usertypes/socket_lua.cpp", "../src/game_api/script/usertypes/steam_lua.cpp", + "../src/game_api/script/usertypes/logic_lua.cpp", ] vtable_api_files = [ "../src/game_api/script/usertypes/vtables_lua.cpp", @@ -891,7 +892,8 @@ def run_parse(): if not var: continue var = var.split(",") - vars.append({"name": var[0], "type": var[1]}) + if(len(var) > 1): + vars.append({"name": var[0], "type": var[1]}) enums.append({"name": name, "vars": vars}) data = open(file, "r").read() data = data.replace("\n", " ") diff --git a/docs/src/includes/_enums.md b/docs/src/includes/_enums.md index 0853597b3..a478b00a1 100644 --- a/docs/src/includes/_enums.md +++ b/docs/src/includes/_enums.md @@ -642,6 +642,44 @@ Name | Data | Description [COARSE_LAVA](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LIQUID_POOL.COARSE_LAVA) | 4 | [STAGNANT_LAVA](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LIQUID_POOL.STAGNANT_LAVA) | 5 | +## LOGIC + + +> Search script examples for [LOGIC](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC) + + + +Name | Data | Description +---- | ---- | ----------- +[TUTORIAL](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.TUTORIAL) | LOGIC::TUTORIAL | +[OUROBOROS](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.OUROBOROS) | LOGIC::OUROBOROS | +[SPEEDRUN](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.SPEEDRUN) | LOGIC::SPEEDRUN | +[GHOST](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.GHOST) | LOGIC::GHOST | +[GHOST_TOAST](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.GHOST_TOAST) | LOGIC::GHOST_TOAST | +[TUN_AGGRO](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.TUN_AGGRO) | LOGIC::TUN_AGGRO | +[DICESHOP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.DICESHOP) | LOGIC::DICESHOP | +[PRE_CHALLENGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.PRE_CHALLENGE) | LOGIC::PRE_CHALLENGE | +[MOON_CHALLENGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.MOON_CHALLENGE) | LOGIC::MOON_CHALLENGE | +[STAR_CHALLENGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.STAR_CHALLENGE) | LOGIC::STAR_CHALLENGE | +[SUN_CHALLENGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.SUN_CHALLENGE) | LOGIC::SUN_CHALLENGE | +[MAGMAN_SPAWN](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.MAGMAN_SPAWN) | LOGIC::MAGMAN_SPAWN | +[WATER_BUBBLES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.WATER_BUBBLES) | LOGIC::WATER_BUBBLES | +[OLMEC_CUTSCENE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.OLMEC_CUTSCENE) | LOGIC::OLMEC_CUTSCENE | +[TIAMAT_CUTSCENE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.TIAMAT_CUTSCENE) | LOGIC::TIAMAT_CUTSCENE | +[APEP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.APEP) | LOGIC::APEP | +[COG_SACRIFICE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.COG_SACRIFICE) | LOGIC::COG_SACRIFICE | +[DUAT_BOSSES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.DUAT_BOSSES) | LOGIC::DUAT_BOSSES | +[BUBBLER](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.BUBBLER) | LOGIC::BUBBLER | +[PLEASURE_PALACE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.PLEASURE_PALACE) | LOGIC::PLEASURE_PALACE | +[DISCOVERY_INFO](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.DISCOVERY_INFO) | LOGIC::DISCOVERY_INFO | +[BLACK_MARKET](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.BLACK_MARKET) | LOGIC::BLACK_MARKET | +[JELLYFISH](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.JELLYFISH) | LOGIC::JELLYFISH | +[ARENA_1](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.ARENA_1) | LOGIC::ARENA_1 | +[ARENA_2](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.ARENA_2) | LOGIC::ARENA_2 | +[ARENA_3](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.ARENA_3) | LOGIC::ARENA_3 | +[ARENA_ALIEN_BLAST](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.ARENA_ALIEN_BLAST) | LOGIC::ARENA_ALIEN_BLAST | +[ARENA_LOOSE_BOMBS](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.ARENA_LOOSE_BOMBS) | LOGIC::ARENA_LOOSE_BOMBS | + ## MASK diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index e62cc7f36..b2fa9fccc 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -152,6 +152,36 @@ bool | [final_ghost](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=fi int | [breath_cooldown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=breath_cooldown) | bool | [punish_ball](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=punish_ball) | +### LogicArena1 + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [crate_spawn_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=crate_spawn_timer) | + +### LogicArenaAlienBlast + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | + +### LogicArenaLooseBombs + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | + ## Callback context types @@ -709,7 +739,7 @@ nil | [set_quad(Quad quad)](https://github.com/spelunky-fyi/overlunky/search?l=L ### MagmamanSpawnPosition -Used in [LogicList](#LogicList) +Used in [LogicMagmamanSpawn](#LogicMagmamanSpawn) Type | Name | Description ---- | ---- | ----------- @@ -1293,7 +1323,53 @@ Used in [LogicList](#LogicList) Type | Name | Description ---- | ---- | ----------- -int | [logic_index](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=logic_index) | +[LOGIC](#LOGIC) | [logic_index](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=logic_index) | + +### LogicApepTrigger + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [spawn_cooldown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_cooldown) | +bool | [cooling_down](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=cooling_down) | +bool | [apep_journal_entry_logged](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apep_journal_entry_logged) | + +### LogicBasecampSpeedrun + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [administrator](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=administrator) | entity uid of the character that keeps the time +int | [crate](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=crate) | entity uid. you must break this crate for the run to be valid, otherwise you're cheating + +### LogicCOGAnkhSacrifice + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | + +### LogicChallenge + +Used in [LogicMoonChallenge](#LogicMoonChallenge), [LogicStarChallenge](#LogicStarChallenge), [LogicSunChallenge](#LogicSunChallenge) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [floor_challenge_entrance_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=floor_challenge_entrance_uid) | +int | [floor_challenge_waitroom_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=floor_challenge_waitroom_uid) | +bool | [challenge_active](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=challenge_active) | +int | [forcefield_countdown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=forcefield_countdown) | ### LogicDiceShop @@ -1303,20 +1379,31 @@ Derived from [Logic](#Logic) Type | Name | Description ---- | ---- | ----------- -int | [bet_machine](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bet_machine) | -int | [die1](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=die1) | -int | [die2](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=die2) | +int | [boss_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=boss_uid) | +[ENT_TYPE](#ENT_TYPE) | [boss_type](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=boss_type) | +int | [bet_machine](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bet_machine) | entity uid +int | [die1](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=die1) | entity uid +int | [die2](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=die2) | entity uid int | [die_1_value](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=die_1_value) | int | [die_2_value](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=die_2_value) | -int | [prize_dispenser](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=prize_dispenser) | -int | [prize](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=prize) | -int | [forcefield](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=forcefield) | +int | [prize_dispenser](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=prize_dispenser) | entity uid +int | [prize](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=prize) | entity uid +int | [forcefield](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=forcefield) | entity uid bool | [bet_active](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bet_active) | bool | [forcefield_deactivated](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=forcefield_deactivated) | -bool | [boss_angry](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=boss_angry) | -int | [result_announcement_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=result_announcement_timer) | +int | [result_announcement_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=result_announcement_timer) | the time the boss waits after your second die throw to announce the results int | [won_prizes_count](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=won_prizes_count) | -int | [balance](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=balance) | +int | [balance](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=balance) | cash balance of all the games + +### LogicGhostToast + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [toast_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=toast_timer) | default 90 ### LogicList @@ -1324,10 +1411,59 @@ Used in [StateMemory](#StateMemory) Type | Name | Description ---- | ---- | ----------- +[LogicTutorial](#LogicTutorial) | [tutorial](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tutorial) | Handles dropping of the torch and rope in intro routine (first time play) +[LogicOuroboros](#LogicOuroboros) | [ouroboros](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ouroboros) | +[LogicBasecampSpeedrun](#LogicBasecampSpeedrun) | [basecamp_speedrun](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=basecamp_speedrun) | Keep track of time, player position passing official +[Logic](#Logic) | [ghost_trigger](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ghost_trigger) | It's absence is the only reason why ghost doesn't spawn at boss levels or CO +[LogicGhostToast](#LogicGhostToast) | [ghost_toast_trigger](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ghost_toast_trigger) | +[Logic](#Logic) | [tun_aggro](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tun_aggro) | Spawns tun at the door at 30s mark +[LogicDiceShop](#LogicDiceShop) | [diceshop](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=diceshop) | +[LogicTunPreChallenge](#LogicTunPreChallenge) | [tun_pre_challenge](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tun_pre_challenge) | +[LogicMoonChallenge](#LogicMoonChallenge) | [tun_moon_challenge](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tun_moon_challenge) | +[LogicStarChallenge](#LogicStarChallenge) | [tun_star_challenge](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tun_star_challenge) | +[LogicSunChallenge](#LogicSunChallenge) | [tun_sun_challenge](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tun_sun_challenge) | +[LogicMagmamanSpawn](#LogicMagmamanSpawn) | [magmaman_spawn](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=magmaman_spawn) | +[LogicUnderwaterBubbles](#LogicUnderwaterBubbles) | [water_bubbles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=water_bubbles) | Only the bubbles that spawn from the floor
Even without it, entities moving in water still spawn bubbles [LogicOlmecCutscene](#LogicOlmecCutscene) | [olmec_cutscene](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=olmec_cutscene) | [LogicTiamatCutscene](#LogicTiamatCutscene) | [tiamat_cutscene](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tiamat_cutscene) | -LogicMagmamanSpawn | [magmaman_spawn](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=magmaman_spawn) | -[LogicDiceShop](#LogicDiceShop) | [diceshop](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=diceshop) | +[LogicApepTrigger](#LogicApepTrigger) | [apep_spawner](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apep_spawner) | Works only if the level has at least one room [ROOM_TEMPLATE](#ROOM_TEMPLATE).APEP, and it still spawns apep at hardcoded positions +[LogicCOGAnkhSacrifice](#LogicCOGAnkhSacrifice) | [city_of_gold_ankh_sacrifice](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=city_of_gold_ankh_sacrifice) | All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) +[Logic](#Logic) | [duat_bosses_spawner](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=duat_bosses_spawner) | +[LogicTiamatBubbles](#LogicTiamatBubbles) | [bubbler](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bubbler) | Spawn rising bubbles at [Tiamat](#Tiamat) (position hardcoded) +[LogicTuskPleasurePalace](#LogicTuskPleasurePalace) | [tusk_pleasure_palace](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tusk_pleasure_palace) | Triggers aggro on everyone when non-high roller enters door +[Logic](#Logic) | [discovery_info](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=discovery_info) | black market, vlad, wet fur discovery, logic shows the toast +[Logic](#Logic) | [black_market](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=black_market) | Changes the camera bounds when you reach black market +[Logic](#Logic) | [jellyfish_trigger](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=jellyfish_trigger) | +[LogicArena1](#LogicArena1) | [arena_1](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=arena_1) | Handles create spawns and more, is cleared as soon as the winner is decided (on last player alive) +[Logic](#Logic) | [arena_2](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=arena_2) | +[Logic](#Logic) | [arena_3](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=arena_3) | Handles time end death +[LogicArenaAlienBlast](#LogicArenaAlienBlast) | [arena_alien_blast](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=arena_alien_blast) | +[LogicArenaLooseBombs](#LogicArenaLooseBombs) | [arena_loose_bombs](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=arena_loose_bombs) | + | [start_logic](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=start_logic) | + +### LogicMagmamanSpawn + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +custom_array<[MagmamanSpawnPosition](#MagmamanSpawnPosition)> | [magmaman_positions](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=magmaman_positions) | +nil | [add_spawn(int x, int y)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=add_spawn) | +nil | [add_spawn(MagmamanSpawnPosition ms)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=add_spawn) | +nil | [remove_spawn(int x, int y)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=remove_spawn) | +nil | [remove_spawn(MagmamanSpawnPosition ms)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=remove_spawn) | + +### LogicMoonChallenge + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) [LogicChallenge](#LogicChallenge) + + +Type | Name | Description +---- | ---- | ----------- +int | [mattock_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=mattock_uid) | entity uid ### LogicOlmecCutscene @@ -1337,11 +1473,54 @@ Derived from [Logic](#Logic) Type | Name | Description ---- | ---- | ----------- +[Entity](#Entity) | [fx_olmecpart_large](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=fx_olmecpart_large) | [Entity](#Entity) | [olmec](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=olmec) | [Entity](#Entity) | [player](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player) | [Entity](#Entity) | [cinematic_anchor](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=cinematic_anchor) | int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | +### LogicOuroboros + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +[SoundMeta](#SoundMeta) | [sound](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound) | +int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | + +### LogicStarChallenge + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) [LogicChallenge](#LogicChallenge) + + +Type | Name | Description +---- | ---- | ----------- +array<[Entity](#Entity)> | [torches](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=torches) | +int | [start_countdown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=start_countdown) | + +### LogicSunChallenge + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) [LogicChallenge](#LogicChallenge) + + +Type | Name | Description +---- | ---- | ----------- +int | [start_countdown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=start_countdown) | + +### LogicTiamatBubbles + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [bubble_spawn_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bubble_spawn_timer) | + ### LogicTiamatCutscene Used in [LogicList](#LogicList) @@ -1355,14 +1534,35 @@ Type | Name | Description [Entity](#Entity) | [cinematic_anchor](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=cinematic_anchor) | int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | -### LogicVolcana +### LogicTuskPleasurePalace +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +int | [locked_door](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=locked_door) | + +### LogicTutorial + +Used in [LogicList](#LogicList) +Derived from [Logic](#Logic) + + +Type | Name | Description +---- | ---- | ----------- +[Entity](#Entity) | [pet_tutorial](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=pet_tutorial) | +int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | + +### LogicUnderwaterBubbles + +Used in [LogicList](#LogicList) Derived from [Logic](#Logic) Type | Name | Description ---- | ---- | ----------- -custom_array<[MagmamanSpawnPosition](#MagmamanSpawnPosition)> | [magmaman_positions](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=magmaman_positions) | ## Online types From 1b9ea22d6334bef588bc13c58d4c93057ea1cdc4 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 5 Oct 2023 22:48:00 +0200 Subject: [PATCH 15/16] fix doc --- docs/game_data/spel2.lua | 9 +- docs/src/includes/_types.md | 4 +- src/game_api/script/usertypes/logic_lua.cpp | 104 ++++++++++---------- 3 files changed, 64 insertions(+), 53 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index 869dcc6d4..e40f72db5 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -5906,7 +5906,14 @@ function Quad:is_point_inside(x, y, epsilon) end ---@field arena_3 Logic @Handles time end death ---@field arena_alien_blast LogicArenaAlienBlast ---@field arena_loose_bombs LogicArenaLooseBombs - ---@field start_logic any @[&lua](LogicList&l + ---@field start_logic fun(self, idx: LOGIC): Logic @This only properly constructs the base class
you may still need to initialise the parameters correctly +local LogicList = nil +---@param idx LOGIC +---@return nil +function LogicList:stop_logic(idx) end +---@param log Logic +---@return nil +function LogicList:stop_logic(log) end ---@class Logic ---@field logic_index LOGIC diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index b2fa9fccc..26f1d5134 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -1439,7 +1439,9 @@ Type | Name | Description [Logic](#Logic) | [arena_3](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=arena_3) | Handles time end death [LogicArenaAlienBlast](#LogicArenaAlienBlast) | [arena_alien_blast](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=arena_alien_blast) | [LogicArenaLooseBombs](#LogicArenaLooseBombs) | [arena_loose_bombs](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=arena_loose_bombs) | - | [start_logic](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=start_logic) | +[Logic](#Logic) | [start_logic(LOGIC idx)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=start_logic) | This only properly constructs the base class
you may still need to initialise the parameters correctly +nil | [stop_logic(LOGIC idx)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=stop_logic) | +nil | [stop_logic(Logic log)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=stop_logic) | ### LogicMagmamanSpawn diff --git a/src/game_api/script/usertypes/logic_lua.cpp b/src/game_api/script/usertypes/logic_lua.cpp index 7aefb1445..bb2395781 100644 --- a/src/game_api/script/usertypes/logic_lua.cpp +++ b/src/game_api/script/usertypes/logic_lua.cpp @@ -76,6 +76,58 @@ void register_usertypes(sol::state& lua) "ARENA_LOOSE_BOMBS", LOGIC::ARENA_LOOSE_BOMBS); + auto start_logic = [&lua](LogicList& l, LOGIC idx) -> sol::object + { + auto return_logic = l.start_logic(idx); + switch (idx) + { + case LOGIC::TUTORIAL: + return sol::make_object(lua, (LogicTutorial*)return_logic); + case LOGIC::OUROBOROS: + return sol::make_object(lua, (LogicOuroboros*)return_logic); + case LOGIC::SPEEDRUN: + return sol::make_object(lua, (LogicBasecampSpeedrun*)return_logic); + case LOGIC::GHOST_TOAST: + return sol::make_object(lua, (LogicGhostToast*)return_logic); + case LOGIC::DICESHOP: + return sol::make_object(lua, (LogicDiceShop*)return_logic); + case LOGIC::PRE_CHALLENGE: + return sol::make_object(lua, (LogicTunPreChallenge*)return_logic); + case LOGIC::MOON_CHALLENGE: + return sol::make_object(lua, (LogicMoonChallenge*)return_logic); + case LOGIC::STAR_CHALLENGE: + return sol::make_object(lua, (LogicStarChallenge*)return_logic); + case LOGIC::SUN_CHALLENGE: + return sol::make_object(lua, (LogicSunChallenge*)return_logic); + case LOGIC::MAGMAN_SPAWN: + return sol::make_object(lua, (LogicMagmamanSpawn*)return_logic); + case LOGIC::WATER_BUBBLES: + return sol::make_object(lua, (LogicUnderwaterBubbles*)return_logic); + case LOGIC::OLMEC_CUTSCENE: + return sol::make_object(lua, (LogicOlmecCutscene*)return_logic); + case LOGIC::TIAMAT_CUTSCENE: + return sol::make_object(lua, (LogicTiamatCutscene*)return_logic); + case LOGIC::APEP: + return sol::make_object(lua, (LogicApepTrigger*)return_logic); + case LOGIC::COG_SACRIFICE: + return sol::make_object(lua, (LogicCOGAnkhSacrifice*)return_logic); + case LOGIC::BUBBLER: + return sol::make_object(lua, (LogicTiamatBubbles*)return_logic); + case LOGIC::PLEASURE_PALACE: + return sol::make_object(lua, (LogicTuskPleasurePalace*)return_logic); + case LOGIC::ARENA_1: + return sol::make_object(lua, (LogicArena1*)return_logic); + // case LOGIC::ARENA_2: + // return sol::make_object(lua, () return_logic); + case LOGIC::ARENA_ALIEN_BLAST: + return sol::make_object(lua, (LogicArenaAlienBlast*)return_logic); + case LOGIC::ARENA_LOOSE_BOMBS: + return sol::make_object(lua, (LogicArenaLooseBombs*)return_logic); + default: + return sol::make_object(lua, return_logic); + } + }; + /// Used in StateMemory lua.new_usertype( "LogicList", @@ -136,57 +188,7 @@ void register_usertypes(sol::state& lua) "arena_loose_bombs", &LogicList::arena_loose_bombs, "start_logic", - [&lua](LogicList& l, LOGIC idx) -> sol::object // -> mixed* - { - auto return_logic = l.start_logic(idx); - switch (idx) - { - case LOGIC::TUTORIAL: - return sol::make_object(lua, (LogicTutorial*)return_logic); - case LOGIC::OUROBOROS: - return sol::make_object(lua, (LogicOuroboros*)return_logic); - case LOGIC::SPEEDRUN: - return sol::make_object(lua, (LogicBasecampSpeedrun*)return_logic); - case LOGIC::GHOST_TOAST: - return sol::make_object(lua, (LogicGhostToast*)return_logic); - case LOGIC::DICESHOP: - return sol::make_object(lua, (LogicDiceShop*)return_logic); - case LOGIC::PRE_CHALLENGE: - return sol::make_object(lua, (LogicTunPreChallenge*)return_logic); - case LOGIC::MOON_CHALLENGE: - return sol::make_object(lua, (LogicMoonChallenge*)return_logic); - case LOGIC::STAR_CHALLENGE: - return sol::make_object(lua, (LogicStarChallenge*)return_logic); - case LOGIC::SUN_CHALLENGE: - return sol::make_object(lua, (LogicSunChallenge*)return_logic); - case LOGIC::MAGMAN_SPAWN: - return sol::make_object(lua, (LogicMagmamanSpawn*)return_logic); - case LOGIC::WATER_BUBBLES: - return sol::make_object(lua, (LogicUnderwaterBubbles*)return_logic); - case LOGIC::OLMEC_CUTSCENE: - return sol::make_object(lua, (LogicOlmecCutscene*)return_logic); - case LOGIC::TIAMAT_CUTSCENE: - return sol::make_object(lua, (LogicTiamatCutscene*)return_logic); - case LOGIC::APEP: - return sol::make_object(lua, (LogicApepTrigger*)return_logic); - case LOGIC::COG_SACRIFICE: - return sol::make_object(lua, (LogicCOGAnkhSacrifice*)return_logic); - case LOGIC::BUBBLER: - return sol::make_object(lua, (LogicTiamatBubbles*)return_logic); - case LOGIC::PLEASURE_PALACE: - return sol::make_object(lua, (LogicTuskPleasurePalace*)return_logic); - case LOGIC::ARENA_1: - return sol::make_object(lua, (LogicArena1*)return_logic); - // case LOGIC::ARENA_2: - // return sol::make_object(lua, () return_logic); - case LOGIC::ARENA_ALIEN_BLAST: - return sol::make_object(lua, (LogicArenaAlienBlast*)return_logic); - case LOGIC::ARENA_LOOSE_BOMBS: - return sol::make_object(lua, (LogicArenaLooseBombs*)return_logic); - default: - return sol::make_object(lua, return_logic); - } - }, + start_logic, "stop_logic", stop_logic); /// Used in LogicList From d28b49f4b136b6002c20117a0be4d2b619f064b4 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Fri, 6 Oct 2023 17:25:34 +0200 Subject: [PATCH 16/16] typo --- docs/game_data/spel2.lua | 2 +- docs/src/includes/_enums.md | 2 +- docs/src/includes/_types.md | 2 +- src/game_api/script/usertypes/logic_lua.cpp | 6 +++--- src/game_api/state.cpp | 2 +- src/game_api/state_structs.hpp | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index e40f72db5..56fa8e5a1 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -5893,7 +5893,7 @@ function Quad:is_point_inside(x, y, epsilon) end ---@field water_bubbles LogicUnderwaterBubbles @Only the bubbles that spawn from the floor
Even without it, entities moving in water still spawn bubbles ---@field olmec_cutscene LogicOlmecCutscene ---@field tiamat_cutscene LogicTiamatCutscene - ---@field apep_spawner LogicApepTrigger @Works only if the level has at least one room ROOM_TEMPLATE.APEP, and it still spawns apep at hardcoded positions + ---@field apep_spawner LogicApepTrigger @Triggers and spawns Apep only in rooms set as ROOM_TEMPLATE.APEP ---@field city_of_gold_ankh_sacrifice LogicCOGAnkhSacrifice @All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) ---@field duat_bosses_spawner Logic ---@field bubbler LogicTiamatBubbles @Spawn rising bubbles at Tiamat (position hardcoded) diff --git a/docs/src/includes/_enums.md b/docs/src/includes/_enums.md index a478b00a1..5d0f07cf3 100644 --- a/docs/src/includes/_enums.md +++ b/docs/src/includes/_enums.md @@ -662,7 +662,7 @@ Name | Data | Description [MOON_CHALLENGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.MOON_CHALLENGE) | LOGIC::MOON_CHALLENGE | [STAR_CHALLENGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.STAR_CHALLENGE) | LOGIC::STAR_CHALLENGE | [SUN_CHALLENGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.SUN_CHALLENGE) | LOGIC::SUN_CHALLENGE | -[MAGMAN_SPAWN](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.MAGMAN_SPAWN) | LOGIC::MAGMAN_SPAWN | +[MAGMAMAN_SPAWN](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.MAGMAMAN_SPAWN) | LOGIC::MAGMAMAN_SPAWN | [WATER_BUBBLES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.WATER_BUBBLES) | LOGIC::WATER_BUBBLES | [OLMEC_CUTSCENE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.OLMEC_CUTSCENE) | LOGIC::OLMEC_CUTSCENE | [TIAMAT_CUTSCENE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=LOGIC.TIAMAT_CUTSCENE) | LOGIC::TIAMAT_CUTSCENE | diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 26f1d5134..044efcb96 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -1426,7 +1426,7 @@ Type | Name | Description [LogicUnderwaterBubbles](#LogicUnderwaterBubbles) | [water_bubbles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=water_bubbles) | Only the bubbles that spawn from the floor
Even without it, entities moving in water still spawn bubbles [LogicOlmecCutscene](#LogicOlmecCutscene) | [olmec_cutscene](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=olmec_cutscene) | [LogicTiamatCutscene](#LogicTiamatCutscene) | [tiamat_cutscene](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tiamat_cutscene) | -[LogicApepTrigger](#LogicApepTrigger) | [apep_spawner](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apep_spawner) | Works only if the level has at least one room [ROOM_TEMPLATE](#ROOM_TEMPLATE).APEP, and it still spawns apep at hardcoded positions +[LogicApepTrigger](#LogicApepTrigger) | [apep_spawner](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apep_spawner) | Triggers and spawns Apep only in rooms set as [ROOM_TEMPLATE](#ROOM_TEMPLATE).APEP [LogicCOGAnkhSacrifice](#LogicCOGAnkhSacrifice) | [city_of_gold_ankh_sacrifice](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=city_of_gold_ankh_sacrifice) | All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) [Logic](#Logic) | [duat_bosses_spawner](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=duat_bosses_spawner) | [LogicTiamatBubbles](#LogicTiamatBubbles) | [bubbler](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bubbler) | Spawn rising bubbles at [Tiamat](#Tiamat) (position hardcoded) diff --git a/src/game_api/script/usertypes/logic_lua.cpp b/src/game_api/script/usertypes/logic_lua.cpp index bb2395781..d5fd293ef 100644 --- a/src/game_api/script/usertypes/logic_lua.cpp +++ b/src/game_api/script/usertypes/logic_lua.cpp @@ -41,8 +41,8 @@ void register_usertypes(sol::state& lua) LOGIC::STAR_CHALLENGE, "SUN_CHALLENGE", LOGIC::SUN_CHALLENGE, - "MAGMAN_SPAWN", - LOGIC::MAGMAN_SPAWN, + "MAGMAMAN_SPAWN", + LOGIC::MAGMAMAN_SPAWN, "WATER_BUBBLES", LOGIC::WATER_BUBBLES, "OLMEC_CUTSCENE", @@ -99,7 +99,7 @@ void register_usertypes(sol::state& lua) return sol::make_object(lua, (LogicStarChallenge*)return_logic); case LOGIC::SUN_CHALLENGE: return sol::make_object(lua, (LogicSunChallenge*)return_logic); - case LOGIC::MAGMAN_SPAWN: + case LOGIC::MAGMAMAN_SPAWN: return sol::make_object(lua, (LogicMagmamanSpawn*)return_logic); case LOGIC::WATER_BUBBLES: return sol::make_object(lua, (LogicUnderwaterBubbles*)return_logic); diff --git a/src/game_api/state.cpp b/src/game_api/state.cpp index c809e87d8..466730bde 100644 --- a/src/game_api/state.cpp +++ b/src/game_api/state.cpp @@ -851,7 +851,7 @@ Logic* LogicList::start_logic(LOGIC idx) size = sizeof(LogicTuskPleasurePalace); break; } - case LOGIC::MAGMAN_SPAWN: + case LOGIC::MAGMAMAN_SPAWN: { offset = VTABLE_OFFSET::LOGIC_VOLCANA_RELATED; size = sizeof(LogicMagmamanSpawn); diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index 6a3198187..e913ddb32 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -402,7 +402,7 @@ enum class LOGIC : uint32_t MOON_CHALLENGE, STAR_CHALLENGE, SUN_CHALLENGE, - MAGMAN_SPAWN, + MAGMAMAN_SPAWN, WATER_BUBBLES, OLMEC_CUTSCENE, TIAMAT_CUTSCENE, @@ -695,7 +695,7 @@ struct LogicList LogicUnderwaterBubbles* water_bubbles; LogicOlmecCutscene* olmec_cutscene; LogicTiamatCutscene* tiamat_cutscene; - /// Works only if the level has at least one room ROOM_TEMPLATE.APEP, and it still spawns apep at hardcoded positions + /// Triggers and spawns Apep only in rooms set as ROOM_TEMPLATE.APEP LogicApepTrigger* apep_spawner; /// All it does is it runs transition to Duat after time delay (sets the state next theme etc. and state.items for proper player respawn) LogicCOGAnkhSacrifice* city_of_gold_ankh_sacrifice;