* Adds in-game display of certain rando collectibles. Before, these were only available through the Item Tracker ImGui Window. With this commit, they can be accessed via holding C-Up on the Map Screen. Currently I've added Greg and Triforce Pieces (when applicable) to this menu. Boss Souls, Ocarina Buttons, and eventually Silver Rupees will be added later. * Adds ocarina buttons to in-game display * Initial pass on rendering the text on a black background. * Starting to render boss soul icons * Better alignment and rendering of Boss Soul icons. * Adds icons prefixing the list entries. * Switches boss souls to 32x32 icon. * Partially working Matrix/Vtx implementation Currently hardcoded Greg text, replacing map screen completely. * Now rendering properly thanks to Archez! * Better implementation of accessing the new page. - now attached to Quest status instead of Map - now triggered by a toggle instead of holding a button - now has its own background (temporarily save screen but will be replaced with something custom later) * Make KaleidoEntry's reactive to game state Adds Greg proper and Triforce Hunt to the Misc. Collectibles Page. * Conditionally render Triforce Hunt * Documentation/Cleanup * WIP Ocarina Buttons rendering * Working ocarina buttons display * Renders buttons as Gray instead of using Grayscale This may seem inconsistent, but with Grayscale they technically render as different shades of gray, especially with custom cosmetics. With this they now render as the same shade of gray. * Makes Ocarina Icon gray when no buttons have been collected. * Adds Boss Souls. Currently they run off the menu, need to implement scrolling. * Implement Scrolling for the menu. Need to figure out how to throttle the stick inputs still. * Moves input handling to draw function. I hate it but that's how Kaleido does it and there's some input throttling logic in there, so in order to make this feel like a kaleido menu I have to also handle input in the draw function. * Removes custom cosmetic handling of Ocarina Buttons. I've chosen not to respect the cosmetics for the sake of accessibility and color contrast, but the code is still present and commented out in case we want to reverse that decision. * Hopefully fixes mac build errors. * Implements update function via Hook. * Another mac fix hopefully * Cleans up unused code from the rectangle based attempt. * Clean up more unused code * Commit Boss Soul icon * Fix typo * Remove commented code * Improve toggle functionality * Re-introduce cosmetic matching for ocarina buttons * Revert some unnecessary formatting changes * Fix cursor/page turning issue More improvements to come here (drawing arrows, custom text at the bottom, etc.) * Fix some more formatting changes * One last batch of formatting reverts
847 lines
31 KiB
C++
847 lines
31 KiB
C++
#pragma once
|
|
|
|
#ifndef GameInteractor_h
|
|
#define GameInteractor_h
|
|
|
|
#include "libultraship/libultraship.h"
|
|
#include "GameInteractionEffect.h"
|
|
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
|
#include <z64.h>
|
|
|
|
typedef enum {
|
|
GI_SCHEME_SAIL,
|
|
GI_SCHEME_CROWD_CONTROL,
|
|
} GIScheme;
|
|
|
|
typedef enum {
|
|
/* 0x00 */ GI_LINK_SIZE_NORMAL,
|
|
/* 0x01 */ GI_LINK_SIZE_GIANT,
|
|
/* 0x02 */ GI_LINK_SIZE_MINISH,
|
|
/* 0x03 */ GI_LINK_SIZE_PAPER,
|
|
/* 0x03 */ GI_LINK_SIZE_SQUISHED,
|
|
/* 0x04 */ GI_LINK_SIZE_RESET
|
|
} GILinkSize;
|
|
|
|
typedef enum {
|
|
/* 0x00 */ GI_GRAVITY_LEVEL_LIGHT,
|
|
/* 0x01 */ GI_GRAVITY_LEVEL_NORMAL,
|
|
/* 0x02 */ GI_GRAVITY_LEVEL_HEAVY,
|
|
} GIGravityLevel;
|
|
|
|
typedef enum {
|
|
/* 0x00 */ GI_BUTTONS_CBUTTONS,
|
|
/* 0x01 */ GI_BUTTONS_DPAD,
|
|
} GIButtonSet;
|
|
|
|
typedef enum {
|
|
/* */ GI_TIMEOFDAY_DAWN = 32768,
|
|
/* */ GI_TIMEOFDAY_NOON = 49152,
|
|
/* */ GI_TIMEOFDAY_DUSK = 0,
|
|
/* */ GI_TIMEOFDAY_MIDNIGHT = 16384,
|
|
} GITimeOfDay;
|
|
|
|
typedef enum {
|
|
/* 0x00 */ GI_COSMETICS_TUNICS,
|
|
/* 0x01 */ GI_COSMETICS_NAVI,
|
|
/* 0x02 */ GI_COSMETICS_HAIR,
|
|
} GICosmeticCategories;
|
|
|
|
typedef enum {
|
|
/* 0x00 */ GI_COLOR_RED,
|
|
/* 0x01 */ GI_COLOR_GREEN,
|
|
/* 0x02 */ GI_COLOR_BLUE,
|
|
/* 0x03 */ GI_COLOR_ORANGE,
|
|
/* 0x04 */ GI_COLOR_YELLOW,
|
|
/* 0x05 */ GI_COLOR_PURPLE,
|
|
/* 0x06 */ GI_COLOR_PINK,
|
|
/* 0x07 */ GI_COLOR_BROWN,
|
|
/* 0x08 */ GI_COLOR_BLACK,
|
|
} GIColors;
|
|
|
|
typedef enum {
|
|
/* */ GI_TP_DEST_LINKSHOUSE = ENTR_LINKS_HOUSE_0,
|
|
/* */ GI_TP_DEST_MINUET = ENTR_SACRED_FOREST_MEADOW_2,
|
|
/* */ GI_TP_DEST_BOLERO = ENTR_DEATH_MOUNTAIN_CRATER_4,
|
|
/* */ GI_TP_DEST_SERENADE = ENTR_LAKE_HYLIA_8,
|
|
/* */ GI_TP_DEST_REQUIEM = ENTR_DESERT_COLOSSUS_5,
|
|
/* */ GI_TP_DEST_NOCTURNE = ENTR_GRAVEYARD_7,
|
|
/* */ GI_TP_DEST_PRELUDE = ENTR_TEMPLE_OF_TIME_7,
|
|
} GITeleportDestinations;
|
|
|
|
typedef enum {
|
|
// Vanilla condition: gSaveContext.showTitleCard
|
|
VB_SHOW_TITLE_CARD,
|
|
// Opt: *EnWonderTalk2
|
|
VB_WONDER_TALK,
|
|
// Opt: *ElfMsg
|
|
VB_NAVI_TALK,
|
|
// Vanilla condition: INFTABLE_GREETED_BY_SARIA
|
|
VB_NOT_BE_GREETED_BY_SARIA,
|
|
// Opt: *EnMd
|
|
VB_MIDO_SPAWN,
|
|
// Opt: *EnMd
|
|
// Vanilla condition: EnMd->interactInfo.talkState == NPC_TALK_STATE_ACTION
|
|
VB_MOVE_MIDO_IN_KOKIRI_FOREST,
|
|
// Opt: *EnMd
|
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)
|
|
VB_MIDO_CONSIDER_DEKU_TREE_DEAD,
|
|
// Opt: *ObjDekujr
|
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)
|
|
VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED,
|
|
// Opt: *EnKo
|
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)
|
|
VB_OPEN_KOKIRI_FOREST,
|
|
// Opt: *EnOwl
|
|
// Vanilla condition: EnOwl->actor.xzDistToPlayer < targetDist
|
|
VB_OWL_INTERACTION,
|
|
// Vanilla condition: EVENTCHKINF_TALON_RETURNED_FROM_CASTLE
|
|
VB_MALON_RETURN_FROM_CASTLE,
|
|
// Vanilla condition: CUR_UPG_VALUE(UPG_STRENGTH) <= 0
|
|
VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD,
|
|
/* Vanilla condition:
|
|
```
|
|
LINK_IS_ADULT &&
|
|
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) &&
|
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) &&
|
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
|
|
!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
|
```
|
|
*/
|
|
VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS,
|
|
// Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SARIA)
|
|
VB_BE_ELIGIBLE_FOR_SARIAS_SONG,
|
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_SONG_EPONA)
|
|
VB_MALON_ALREADY_TAUGHT_EPONAS_SONG,
|
|
// Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)
|
|
VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER,
|
|
// Vanilla condition: (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT
|
|
VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER,
|
|
// Vanilla condition: !EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT and EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP
|
|
VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT,
|
|
VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE,
|
|
/* Vanilla Condition:
|
|
```
|
|
LINK_IS_ADULT &&
|
|
gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 &&
|
|
Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) &&
|
|
Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) &&
|
|
Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) &&
|
|
!Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL);
|
|
```
|
|
*/
|
|
VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW,
|
|
// Opt: *EnGo2
|
|
// Vanilla condition: CUR_CAPACITY(UPG_BOMB_BAG) >= 20 && this->waypoint > 7 && this->waypoint < 12
|
|
VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD,
|
|
// Vanilla condition: !CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON)
|
|
VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE,
|
|
// Opt: *EnMs
|
|
// Vanilla condition: gSaveContext.rupees >= sPrices[BEANS_BOUGHT]
|
|
VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE,
|
|
// Opt: *EnItem00
|
|
// Vanilla condition: Flags_GetCollectible(play, this->collectibleFlag)
|
|
VB_ITEM00_DESPAWN,
|
|
// Opt: *ItemBHeart
|
|
// Vanilla condition: Flags_GetCollectible(play, 0x1F)
|
|
VB_ITEM_B_HEART_DESPAWN,
|
|
// Opt: *EnTk
|
|
// Vanilla condition: gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD
|
|
VB_DAMPE_IN_GRAVEYARD_DESPAWN,
|
|
// Opt: *EnTk
|
|
// Vanilla condition: this->validDigHere == 1
|
|
VB_BE_VALID_GRAVEDIGGING_SPOT,
|
|
// Opt: *EnTk
|
|
// Vanilla condition: this->currentReward == 3
|
|
VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE,
|
|
// Opt: *EnTk
|
|
// Vanilla condition: !Flags_GetItemGetInf(ITEMGETINF_1C)
|
|
VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE,
|
|
// Opt: *EnShopnuts
|
|
/* Vanilla Condition:
|
|
```
|
|
((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) ||
|
|
((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) ||
|
|
((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193)))
|
|
```
|
|
*/
|
|
VB_BUSINESS_SCRUB_DESPAWN,
|
|
// Opt: *EnCow
|
|
// Vanilla condition: play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE))
|
|
VB_DESPAWN_HORSE_RACE_COW,
|
|
// Opt: *EnHs
|
|
// Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30)
|
|
VB_DESPAWN_GROG,
|
|
// Opt: *EnKo
|
|
// Vanilla condition: (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false;
|
|
VB_SPAWN_LW_FADO,
|
|
// Opt: *EnMk
|
|
VB_PLAY_EYEDROP_CREATION_ANIM,
|
|
// Opt: *EnDs
|
|
VB_PLAY_ODD_POTION_ANIM,
|
|
// Opt: *EnMk
|
|
// Vanilla condition: INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS
|
|
VB_USE_EYEDROP_DIALOGUE,
|
|
// Opt: *EnMk
|
|
// Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30)
|
|
VB_OFFER_BLUE_POTION,
|
|
// Vanilla condition: Inventory_HasEmptyBottle() == 0
|
|
VB_NEED_BOTTLE_FOR_GRANNYS_ITEM,
|
|
// Opt: *EnNiwLady
|
|
VB_SET_CUCCO_COUNT,
|
|
// Opt: *EnKz
|
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)
|
|
VB_KING_ZORA_THANK_CHILD,
|
|
// Opt: *EnKz
|
|
// Vanilla condition: this->actor.textId == 0x401A
|
|
VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER,
|
|
// Opt: *EnKz
|
|
// Vanilla condition: Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)
|
|
VB_KING_ZORA_BE_MOVED,
|
|
// Vanilla condition: gSaveState.bgsFlag
|
|
VB_BIGGORON_CONSIDER_TRADE_COMPLETE,
|
|
// Vanilla condition: gSaveState.bgsFlag
|
|
VB_BIGGORON_CONSIDER_SWORD_COLLECTED,
|
|
// Vanilla condition: Environment_GetBgsDayCount() >= 3
|
|
VB_BIGGORON_CONSIDER_SWORD_FORGED,
|
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)
|
|
VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED,
|
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_GORON_RUBY)
|
|
VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED,
|
|
// Opt: *uint16_t
|
|
// Vanilla condition: false
|
|
VB_OVERRIDE_LINK_THE_GORON_DIALOGUE,
|
|
// Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)
|
|
VB_GORONS_CONSIDER_TUNIC_COLLECTED,
|
|
// Opt: *EnSyatekiMan
|
|
// Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50)
|
|
VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD,
|
|
// Opt: *EnOkarinaTag
|
|
// Vanilla condition: !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME)
|
|
VB_BE_ELIGIBLE_TO_OPEN_DOT,
|
|
// Opt: *BgDyYoseizo
|
|
// Vanilla condition: see soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c
|
|
VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD,
|
|
// Vanilla condition: see CheckCarpentersFreed in z_en_ge1 and z_en_ge2
|
|
VB_GERUDOS_BE_FRIENDLY,
|
|
// Vanilla condition: switch
|
|
VB_GTG_GATE_BE_OPEN,
|
|
// Opt: *s16 (item id)
|
|
/* Vanilla condition:
|
|
In one case:
|
|
```
|
|
true
|
|
```
|
|
In the other case:
|
|
```
|
|
(i == ITEM_STICK) ||
|
|
(i == ITEM_NUT) ||
|
|
(i == ITEM_BOMB) ||
|
|
(i == ITEM_BOW) ||
|
|
(
|
|
(i >= ITEM_BOW_ARROW_FIRE) &&
|
|
(i <= ITEM_BOW_ARROW_LIGHT)
|
|
) ||
|
|
(i == ITEM_SLINGSHOT) ||
|
|
(i == ITEM_BOMBCHU) ||
|
|
(i == ITEM_BEAN)
|
|
```
|
|
*/
|
|
VB_DRAW_AMMO_COUNT,
|
|
VB_FREEZE_LINK_FOR_BLOCK_THROW,
|
|
VB_MOVE_THROWN_ACTOR,
|
|
|
|
/*** Play Cutscenes ***/
|
|
|
|
VB_PLAY_TRANSITION_CS,
|
|
// Opt: *EventChkInf flag
|
|
VB_PLAY_ENTRANCE_CS,
|
|
// Opt: *cutsceneId
|
|
VB_PLAY_ONEPOINT_CS,
|
|
// Opt: *actor
|
|
VB_PLAY_ONEPOINT_ACTOR_CS,
|
|
// Opt: *BgTreemouth
|
|
VB_PLAY_DEKU_TREE_INTRO_CS,
|
|
// Vanilla condition: !EventChkInf except for spirit & shadow temple which are !medallion, and Jabu which always is true
|
|
VB_PLAY_BLUE_WARP_CS,
|
|
VB_PLAY_DARUNIAS_JOY_CS,
|
|
VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS,
|
|
// Vanilla condition: !EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL
|
|
VB_PLAY_PULL_MASTER_SWORD_CS,
|
|
VB_PLAY_DROP_FISH_FOR_JABU_CS,
|
|
// Vanilla condition: player->getItemId == GI_GAUNTLETS_SILVER
|
|
VB_PLAY_NABOORU_CAPTURED_CS,
|
|
VB_PLAY_ZELDAS_LULLABY_CS,
|
|
// Opt: *EnSa
|
|
VB_PLAY_SARIAS_SONG_CS,
|
|
VB_PLAY_PRELUDE_OF_LIGHT_CS,
|
|
VB_PLAY_MINUET_OF_FOREST_CS,
|
|
VB_PLAY_BOLERO_OF_FIRE_CS,
|
|
VB_PLAY_SERENADE_OF_WATER_CS,
|
|
VB_PLAY_EYEDROPS_CS,
|
|
// Opt: *EnOkarinaTag
|
|
VB_PLAY_DRAIN_WELL_CS,
|
|
// Opt: *EnOkarinaTag
|
|
// Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SUN)
|
|
VB_PLAY_SUNS_SONG_CS,
|
|
// Opt: *EnOkarinaTag
|
|
VB_PLAY_ROYAL_FAMILY_TOMB_CS,
|
|
VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE,
|
|
// Opt: *EnOkarinaTag
|
|
VB_PLAY_DOOR_OF_TIME_CS,
|
|
VB_PLAY_RAINBOW_BRIDGE_CS,
|
|
// Opt: *EnBox
|
|
VB_PLAY_SLOW_CHEST_CS,
|
|
//*Opt f32 sFishOnHandLength
|
|
// Vanilla condition: (s16)sFishingRecordLength < (s16)sFishOnHandLength
|
|
VB_SHOULD_CHECK_FOR_FISHING_RECORD,
|
|
//*Opt f32 sFishOnHandLength
|
|
// Vanilla condition is implied from previous code that could be bypassed by above hook
|
|
VB_SHOULD_SET_FISHING_RECORD,
|
|
//*Opt *s32 getItemId
|
|
VB_SHOULD_GIVE_VANILLA_FISHING_PRIZE,
|
|
VB_GIVE_RANDO_FISHING_PRIZE,
|
|
VB_PLAY_THROW_ANIMATION,
|
|
|
|
/*** Give Items ***/
|
|
|
|
// Opt: *EnBox
|
|
VB_GIVE_ITEM_FROM_CHEST,
|
|
VB_GIVE_ITEM_FROM_BLUE_WARP,
|
|
// Opt: *EnItem00
|
|
VB_GIVE_ITEM_FROM_ITEM_00,
|
|
// Opt: *EnSi
|
|
VB_GIVE_ITEM_SKULL_TOKEN,
|
|
// Opt: *EnCow
|
|
VB_GIVE_ITEM_FROM_COW,
|
|
// Opt: *EnDns
|
|
VB_GIVE_ITEM_FROM_BUSINESS_SCRUB,
|
|
// Opt: *EnMk
|
|
VB_GIVE_ITEM_FROM_LAB_DIVE,
|
|
// Opt: *EnDs
|
|
VB_GIVE_ITEM_FROM_GRANNYS_SHOP,
|
|
// Opt: *EnNiwLady
|
|
VB_GIVE_ITEM_FROM_ANJU_AS_CHILD,
|
|
// Opt: *EnNiwLady
|
|
VB_GIVE_ITEM_FROM_ANJU_AS_ADULT,
|
|
// Opt: *EnKz
|
|
// Vanilla condition: !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA)
|
|
VB_GIVE_ITEM_FROM_THAWING_KING_ZORA,
|
|
// Opt: *EnGo2
|
|
VB_GIVE_ITEM_FROM_GORON,
|
|
// Opt: *EnJs
|
|
VB_GIVE_ITEM_FROM_CARPET_SALESMAN,
|
|
VB_GIVE_BOMBCHUS_FROM_CARPET_SALESMAN,
|
|
// Opt: *EnGm
|
|
VB_GIVE_ITEM_FROM_MEDIGORON,
|
|
// Opt: *EnMs
|
|
VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN,
|
|
// Opt: *EnFr
|
|
VB_GIVE_ITEM_FROM_FROGS,
|
|
// Opt: *EnSkj
|
|
VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME,
|
|
// Opt: *EnSkj
|
|
VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG,
|
|
VB_GIVE_ITEM_FROM_MAN_ON_ROOF,
|
|
// Opt: *EnSyatekiMan
|
|
VB_GIVE_ITEM_FROM_SHOOTING_GALLERY,
|
|
// Opt: *EnExItem
|
|
VB_GIVE_ITEM_FROM_TARGET_IN_WOODS,
|
|
// Opt: *EnTa
|
|
VB_GIVE_ITEM_FROM_TALONS_CHICKENS,
|
|
// Opt: *EnDivingGame
|
|
VB_GIVE_ITEM_FROM_DIVING_MINIGAME,
|
|
// Opt: *EnGe1
|
|
VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY,
|
|
// Opt: *EnSth
|
|
VB_GIVE_ITEM_FROM_SKULLTULA_REWARD,
|
|
// Opt: *EnHy
|
|
VB_GIVE_ITEM_FROM_LOST_DOG,
|
|
// Opt: *EnBomBowlPit
|
|
VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING,
|
|
|
|
VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD,
|
|
|
|
VB_GIVE_ITEM_FAIRY_OCARINA,
|
|
VB_GIVE_ITEM_WEIRD_EGG,
|
|
VB_GIVE_ITEM_LIGHT_ARROW,
|
|
VB_GIVE_ITEM_STRENGTH_1,
|
|
VB_GIVE_ITEM_ZELDAS_LETTER,
|
|
VB_GIVE_ITEM_MASTER_SWORD,
|
|
VB_GIVE_ITEM_OCARINA_OF_TIME,
|
|
VB_GIVE_ITEM_KOKIRI_EMERALD,
|
|
VB_GIVE_ITEM_GORON_RUBY,
|
|
VB_GIVE_ITEM_ZORA_SAPPHIRE,
|
|
VB_GIVE_ITEM_LIGHT_MEDALLION,
|
|
VB_GIVE_ITEM_FOREST_MEDALLION,
|
|
VB_GIVE_ITEM_FIRE_MEDALLION,
|
|
VB_GIVE_ITEM_WATER_MEDALLION,
|
|
VB_GIVE_ITEM_SPIRIT_MEDALLION,
|
|
VB_GIVE_ITEM_SHADOW_MEDALLION,
|
|
|
|
/*** Give Songs ***/
|
|
|
|
VB_GIVE_ITEM_ZELDAS_LULLABY,
|
|
VB_GIVE_ITEM_SARIAS_SONG,
|
|
VB_GIVE_ITEM_EPONAS_SONG,
|
|
VB_GIVE_ITEM_SUNS_SONG,
|
|
VB_GIVE_ITEM_SONG_OF_TIME,
|
|
VB_GIVE_ITEM_SONG_OF_STORMS,
|
|
VB_GIVE_ITEM_MINUET_OF_FOREST,
|
|
VB_GIVE_ITEM_BOLERO_OF_FIRE,
|
|
VB_GIVE_ITEM_SERENADE_OF_WATER,
|
|
VB_GIVE_ITEM_REQUIEM_OF_SPIRIT,
|
|
VB_GIVE_ITEM_NOCTURNE_OF_SHADOW,
|
|
VB_GIVE_ITEM_PRELUDE_OF_LIGHT,
|
|
|
|
/*** Adult Trade ***/
|
|
// Opt: *EnNiwLady
|
|
VB_TRADE_POCKET_CUCCO,
|
|
// Opt: *EnHs
|
|
VB_TRADE_COJIRO,
|
|
// Opt: *EnDs
|
|
VB_TRADE_ODD_MUSHROOM,
|
|
// Opt: *EnKo
|
|
VB_TRADE_ODD_POTION,
|
|
// Opt: *EnToryo
|
|
VB_TRADE_SAW,
|
|
// Opt: *EnKz,
|
|
VB_TRADE_PRESCRIPTION,
|
|
// Opt: *EnMk
|
|
VB_TRADE_FROG,
|
|
|
|
VB_TRADE_TIMER_ODD_MUSHROOM,
|
|
VB_TRADE_TIMER_EYEDROPS,
|
|
VB_TRADE_TIMER_FROG,
|
|
// Opt: *EnNiwLady
|
|
VB_ANJU_SET_OBTAINED_TRADE_ITEM,
|
|
|
|
/*** Fixes ***/
|
|
// Vanilla condition: false
|
|
VB_FIX_SAW_SOFTLOCK,
|
|
|
|
/*** Cheats? ***/
|
|
VB_DEKU_STICK_BE_ON_FIRE,
|
|
VB_DEKU_STICK_BREAK,
|
|
VB_DEKU_STICK_BURN_DOWN,
|
|
VB_DEKU_STICK_BURN_OUT,
|
|
VB_DEKU_UPDATE_BURNING_DEKU_STICK,
|
|
|
|
/*** Quick Boss Deaths ***/
|
|
// Vanilla condition: true
|
|
VB_PHANTOM_GANON_DEATH_SCENE,
|
|
VB_NABOORU_KNUCKLE_DEATH_SCENE,
|
|
|
|
/*** Fishsanity ***/
|
|
// Vanilla condition: Actor is ACTOR_EN_ELF, ACTOR_EN_FISH, ACTOR_EN_ICE_HONO, or ACTOR_EN_INSECT
|
|
// Opt: *Actor
|
|
VB_BOTTLE_ACTOR,
|
|
} GIVanillaBehavior;
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
uint8_t GameInteractor_NoUIActive();
|
|
GILinkSize GameInteractor_GetLinkSize();
|
|
void GameInteractor_SetLinkSize(GILinkSize size);
|
|
uint8_t GameInteractor_InvisibleLinkActive();
|
|
uint8_t GameInteractor_OneHitKOActive();
|
|
uint8_t GameInteractor_PacifistModeActive();
|
|
uint8_t GameInteractor_DisableZTargetingActive();
|
|
uint8_t GameInteractor_ReverseControlsActive();
|
|
int32_t GameInteractor_DefenseModifier();
|
|
int32_t GameInteractor_RunSpeedModifier();
|
|
GIGravityLevel GameInteractor_GravityLevel();
|
|
uint32_t GameInteractor_GetEmulatedButtons();
|
|
void GameInteractor_SetEmulatedButtons(uint32_t buttons);
|
|
uint8_t GameInteractor_GetRandomBombFuseTimerActive();
|
|
uint8_t GameInteractor_GetDisableLedgeGrabsActive();
|
|
uint8_t GameInteractor_GetRandomWindActive();
|
|
uint8_t GameInteractor_GetRandomBonksActive();
|
|
uint8_t GameInteractor_GetSlipperyFloorActive();
|
|
uint8_t GameInteractor_SecondCollisionUpdate();
|
|
void GameInteractor_SetTriforceHuntPieceGiven(uint8_t state);
|
|
void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state);
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef __cplusplus
|
|
#include <thread>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
#include <functional>
|
|
#include <string>
|
|
#include <version>
|
|
#ifdef __cpp_lib_source_location
|
|
#include <source_location>
|
|
#else
|
|
#pragma message("Compiling without <source_location> support, the Hook Debugger will not be avaliable")
|
|
#endif
|
|
|
|
#ifdef ENABLE_REMOTE_CONTROL
|
|
#include <SDL2/SDL_net.h>
|
|
#include <nlohmann/json.hpp>
|
|
#endif
|
|
|
|
typedef uint32_t HOOK_ID;
|
|
|
|
enum HookType {
|
|
HOOK_TYPE_NORMAL,
|
|
HOOK_TYPE_ID,
|
|
HOOK_TYPE_PTR,
|
|
HOOK_TYPE_FILTER,
|
|
};
|
|
|
|
struct HookRegisteringInfo {
|
|
bool valid;
|
|
const char* file;
|
|
std::uint_least32_t line;
|
|
std::uint_least32_t column;
|
|
const char* function;
|
|
HookType type;
|
|
|
|
HookRegisteringInfo() : valid(false), file("unknown file"), line(0), column(0), function("unknown function"), type(HOOK_TYPE_NORMAL) {}
|
|
|
|
HookRegisteringInfo(const char* _file, std::uint_least32_t _line, std::uint_least32_t _column, const char* _function, HookType _type) :
|
|
valid(true), file(_file), line(_line), column(_column), function(_function), type(_type) {}
|
|
};
|
|
|
|
struct HookInfo {
|
|
uint32_t calls;
|
|
HookRegisteringInfo registering;
|
|
|
|
HookInfo() : calls(0), registering(HookRegisteringInfo{}) {}
|
|
HookInfo(HookRegisteringInfo _registering) : calls(0), registering(_registering) {}
|
|
};
|
|
|
|
#ifdef __cpp_lib_source_location
|
|
#define GET_CURRENT_REGISTERING_INFO(type) HookRegisteringInfo{location.file_name(), location.line(), location.column(), location.function_name(), type}
|
|
#else
|
|
#define GET_CURRENT_REGISTERING_INFO(type) HookRegisteringInfo{}
|
|
#endif
|
|
|
|
#define REGISTER_VB_SHOULD(flag, body) \
|
|
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(flag, [](GIVanillaBehavior _, bool* should, void* opt) body)
|
|
|
|
class GameInteractor {
|
|
public:
|
|
static GameInteractor* Instance;
|
|
|
|
// Game State
|
|
class State {
|
|
public:
|
|
static bool NoUIActive;
|
|
static GILinkSize LinkSize;
|
|
static bool InvisibleLinkActive;
|
|
static bool OneHitKOActive;
|
|
static bool PacifistModeActive;
|
|
static bool DisableZTargetingActive;
|
|
static bool ReverseControlsActive;
|
|
static int32_t DefenseModifier;
|
|
static int32_t RunSpeedModifier;
|
|
static GIGravityLevel GravityLevel;
|
|
static uint32_t EmulatedButtons;
|
|
static uint8_t RandomBombFuseTimerActive;
|
|
static uint8_t DisableLedgeGrabsActive;
|
|
static uint8_t RandomWindActive;
|
|
static uint8_t RandomWindSecondsSinceLastDirectionChange;
|
|
static uint8_t RandomBonksActive;
|
|
static uint8_t SlipperyFloorActive;
|
|
static uint8_t SecondCollisionUpdate;
|
|
static uint8_t TriforceHuntPieceGiven;
|
|
static uint8_t TriforceHuntCreditsWarpActive;
|
|
|
|
static void SetPacifistMode(bool active);
|
|
};
|
|
|
|
#ifdef ENABLE_REMOTE_CONTROL
|
|
bool isRemoteInteractorEnabled;
|
|
bool isRemoteInteractorConnected;
|
|
|
|
void EnableRemoteInteractor();
|
|
void DisableRemoteInteractor();
|
|
void RegisterRemoteDataHandler(std::function<void(char payload[512])> method);
|
|
void RegisterRemoteJsonHandler(std::function<void(nlohmann::json)> method);
|
|
void RegisterRemoteConnectedHandler(std::function<void()> method);
|
|
void RegisterRemoteDisconnectedHandler(std::function<void()> method);
|
|
void TransmitDataToRemote(const char* payload);
|
|
void TransmitJsonToRemote(nlohmann::json packet);
|
|
#endif
|
|
|
|
// Effects
|
|
static GameInteractionEffectQueryResult CanApplyEffect(GameInteractionEffectBase* effect);
|
|
static GameInteractionEffectQueryResult ApplyEffect(GameInteractionEffectBase* effect);
|
|
static GameInteractionEffectQueryResult RemoveEffect(RemovableGameInteractionEffect* effect);
|
|
|
|
// Game Hooks
|
|
HOOK_ID nextHookId = 1;
|
|
template <typename H> struct RegisteredGameHooks {
|
|
inline static std::unordered_map<HOOK_ID, typename H::fn> functions;
|
|
inline static std::unordered_map<int32_t, std::unordered_map<HOOK_ID, typename H::fn>> functionsForID;
|
|
inline static std::unordered_map<uintptr_t, std::unordered_map<HOOK_ID, typename H::fn>> functionsForPtr;
|
|
inline static std::unordered_map<HOOK_ID, std::pair<typename H::filter, typename H::fn>> functionsForFilter;
|
|
|
|
//Used for the hook debugger
|
|
inline static std::unordered_map<HOOK_ID, HookInfo> hookData;
|
|
};
|
|
|
|
template <typename H> struct HooksToUnregister {
|
|
inline static std::vector<HOOK_ID> hooks;
|
|
inline static std::vector<HOOK_ID> hooksForID;
|
|
inline static std::vector<HOOK_ID> hooksForPtr;
|
|
inline static std::vector<HOOK_ID> hooksForFilter;
|
|
};
|
|
|
|
template <typename H> std::unordered_map<uint32_t, HookInfo> GetHookData() {
|
|
return RegisteredGameHooks<H>::hookData;
|
|
}
|
|
|
|
// General Hooks
|
|
template <typename H> HOOK_ID RegisterGameHook(
|
|
typename H::fn h
|
|
#ifdef __cpp_lib_source_location
|
|
, const std::source_location location = std::source_location::current()
|
|
#endif
|
|
) {
|
|
// Ensure hook id is unique and not 0, which is reserved for invalid hooks
|
|
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1;
|
|
while (RegisteredGameHooks<H>::functions.find(this->nextHookId) != RegisteredGameHooks<H>::functions.end()) {
|
|
this->nextHookId++;
|
|
}
|
|
|
|
RegisteredGameHooks<H>::functions[this->nextHookId] = h;
|
|
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_NORMAL)};
|
|
return this->nextHookId++;
|
|
}
|
|
|
|
template <typename H> void UnregisterGameHook(HOOK_ID hookId) {
|
|
if (hookId == 0) return;
|
|
HooksToUnregister<H>::hooks.push_back(hookId);
|
|
}
|
|
|
|
template <typename H, typename... Args> void ExecuteHooks(Args&&... args) {
|
|
for (auto& hookId : HooksToUnregister<H>::hooks) {
|
|
RegisteredGameHooks<H>::functions.erase(hookId);
|
|
RegisteredGameHooks<H>::hookData.erase(hookId);
|
|
}
|
|
HooksToUnregister<H>::hooks.clear();
|
|
for (auto& hook : RegisteredGameHooks<H>::functions) {
|
|
hook.second(std::forward<Args>(args)...);
|
|
RegisteredGameHooks<H>::hookData[hook.first].calls += 1;
|
|
}
|
|
}
|
|
|
|
// ID based Hooks
|
|
template <typename H> HOOK_ID RegisterGameHookForID(
|
|
int32_t id, typename H::fn h
|
|
#ifdef __cpp_lib_source_location
|
|
, const std::source_location location = std::source_location::current()
|
|
#endif
|
|
) {
|
|
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1;
|
|
while (RegisteredGameHooks<H>::functionsForID[id].find(this->nextHookId) != RegisteredGameHooks<H>::functionsForID[id].end()) {
|
|
this->nextHookId++;
|
|
}
|
|
|
|
RegisteredGameHooks<H>::functionsForID[id][this->nextHookId] = h;
|
|
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_ID)};
|
|
return this->nextHookId++;
|
|
}
|
|
|
|
template <typename H> void UnregisterGameHookForID(HOOK_ID hookId) {
|
|
if (hookId == 0) return;
|
|
HooksToUnregister<H>::hooksForID.push_back(hookId);
|
|
}
|
|
|
|
template <typename H, typename... Args> void ExecuteHooksForID(int32_t id, Args&&... args) {
|
|
for (auto& hookId : HooksToUnregister<H>::hooksForID) {
|
|
for (auto it = RegisteredGameHooks<H>::functionsForID[id].begin(); it != RegisteredGameHooks<H>::functionsForID[id].end(); ) {
|
|
if (it->first == hookId) {
|
|
it = RegisteredGameHooks<H>::functionsForID[id].erase(it);
|
|
HooksToUnregister<H>::hooksForID.erase(std::remove(HooksToUnregister<H>::hooksForID.begin(), HooksToUnregister<H>::hooksForID.end(), hookId), HooksToUnregister<H>::hooksForID.end());
|
|
RegisteredGameHooks<H>::hookData.erase(hookId);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
for (auto& hook : RegisteredGameHooks<H>::functionsForID[id]) {
|
|
hook.second(std::forward<Args>(args)...);
|
|
RegisteredGameHooks<H>::hookData[hook.first].calls += 1;
|
|
}
|
|
}
|
|
|
|
// PTR based Hooks
|
|
template <typename H> HOOK_ID RegisterGameHookForPtr(
|
|
uintptr_t ptr, typename H::fn h
|
|
#ifdef __cpp_lib_source_location
|
|
, const std::source_location location = std::source_location::current()
|
|
#endif
|
|
) {
|
|
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1;
|
|
while (RegisteredGameHooks<H>::functionsForPtr[ptr].find(this->nextHookId) != RegisteredGameHooks<H>::functionsForPtr[ptr].end()) {
|
|
this->nextHookId++;
|
|
}
|
|
|
|
RegisteredGameHooks<H>::functionsForPtr[ptr][this->nextHookId] = h;
|
|
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_PTR)};
|
|
return this->nextHookId++;
|
|
}
|
|
|
|
template <typename H> void UnregisterGameHookForPtr(HOOK_ID hookId) {
|
|
if (hookId == 0) return;
|
|
HooksToUnregister<H>::hooksForPtr.push_back(hookId);
|
|
}
|
|
|
|
template <typename H, typename... Args> void ExecuteHooksForPtr(uintptr_t ptr, Args&&... args) {
|
|
for (auto& hookId : HooksToUnregister<H>::hooksForPtr) {
|
|
for (auto it = RegisteredGameHooks<H>::functionsForPtr[ptr].begin(); it != RegisteredGameHooks<H>::functionsForPtr[ptr].end(); ) {
|
|
if (it->first == hookId) {
|
|
it = RegisteredGameHooks<H>::functionsForPtr[ptr].erase(it);
|
|
HooksToUnregister<H>::hooksForPtr.erase(std::remove(HooksToUnregister<H>::hooksForPtr.begin(), HooksToUnregister<H>::hooksForPtr.end(), hookId), HooksToUnregister<H>::hooksForPtr.end());
|
|
RegisteredGameHooks<H>::hookData.erase(hookId);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
for (auto& hook : RegisteredGameHooks<H>::functionsForPtr[ptr]) {
|
|
hook.second(std::forward<Args>(args)...);
|
|
RegisteredGameHooks<H>::hookData[hook.first].calls += 1;
|
|
}
|
|
}
|
|
|
|
// Filter based Hooks
|
|
template <typename H> HOOK_ID RegisterGameHookForFilter(
|
|
typename H::filter f, typename H::fn h
|
|
#ifdef __cpp_lib_source_location
|
|
, const std::source_location location = std::source_location::current()
|
|
#endif
|
|
) {
|
|
if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1;
|
|
while (RegisteredGameHooks<H>::functionsForFilter.find(this->nextHookId) != RegisteredGameHooks<H>::functionsForFilter.end()) {
|
|
this->nextHookId++;
|
|
}
|
|
|
|
RegisteredGameHooks<H>::functionsForFilter[this->nextHookId] = std::make_pair(f, h);
|
|
RegisteredGameHooks<H>::hookData[this->nextHookId] = HookInfo{GET_CURRENT_REGISTERING_INFO(HOOK_TYPE_FILTER)};
|
|
return this->nextHookId++;
|
|
}
|
|
|
|
template <typename H> void UnregisterGameHookForFilter(HOOK_ID hookId) {
|
|
if (hookId == 0) return;
|
|
HooksToUnregister<H>::hooksForFilter.push_back(hookId);
|
|
}
|
|
|
|
template <typename H, typename... Args> void ExecuteHooksForFilter(Args&&... args) {
|
|
for (auto& hookId : HooksToUnregister<H>::hooksForFilter) {
|
|
RegisteredGameHooks<H>::functionsForFilter.erase(hookId);
|
|
RegisteredGameHooks<H>::hookData.erase(hookId);
|
|
}
|
|
HooksToUnregister<H>::hooksForFilter.clear();
|
|
for (auto& hook : RegisteredGameHooks<H>::functionsForFilter) {
|
|
if (hook.second.first(std::forward<Args>(args)...)) {
|
|
hook.second.second(std::forward<Args>(args)...);
|
|
RegisteredGameHooks<H>::hookData[hook.first].calls += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
class HookFilter {
|
|
public:
|
|
static auto ActorNotPlayer(Actor* actor) {
|
|
return actor->id != ACTOR_PLAYER;
|
|
}
|
|
// For use with Should hooks
|
|
static auto SActorNotPlayer(Actor* actor, bool* result) {
|
|
return actor->id != ACTOR_PLAYER;
|
|
}
|
|
static auto ActorMatchIdAndParams(int16_t id, int16_t params) {
|
|
return [id, params](Actor* actor) {
|
|
return actor->id == id && actor->params == params;
|
|
};
|
|
}
|
|
// For use with Should hooks
|
|
static auto SActorMatchIdAndParams(int16_t id, int16_t params) {
|
|
return [id, params](Actor* actor, bool* result) {
|
|
return actor->id == id && actor->params == params;
|
|
};
|
|
}
|
|
};
|
|
|
|
#define DEFINE_HOOK(name, args) \
|
|
struct name { \
|
|
typedef std::function<void args> fn; \
|
|
typedef std::function<bool args> filter; \
|
|
}
|
|
|
|
#include "GameInteractor_HookTable.h"
|
|
|
|
#undef DEFINE_HOOK
|
|
|
|
// Helpers
|
|
static bool IsSaveLoaded(bool allowDbgSave = false);
|
|
static bool IsGameplayPaused();
|
|
static bool CanSpawnActor();
|
|
static bool CanAddOrTakeAmmo(int16_t amount, int16_t item);
|
|
|
|
class RawAction {
|
|
public:
|
|
static void SetSceneFlag(int16_t sceneNum, int16_t flagType, int16_t flag);
|
|
static void UnsetSceneFlag(int16_t sceneNum, int16_t flagType, int16_t flag);
|
|
static bool CheckFlag(int16_t flagType, int16_t flag);
|
|
static void SetFlag(int16_t flagType, int16_t chestNum);
|
|
static void UnsetFlag(int16_t flagType, int16_t chestNum);
|
|
static void AddOrRemoveHealthContainers(int16_t amount);
|
|
static void AddOrRemoveMagic(int8_t amount);
|
|
static void HealOrDamagePlayer(int16_t hearts);
|
|
static void SetPlayerHealth(int16_t hearts);
|
|
static void SetLinkInvisibility(bool active);
|
|
static void SetWeatherStorm(bool active);
|
|
static void ForceEquipBoots(int8_t boots);
|
|
static void FreezePlayer();
|
|
static void BurnPlayer();
|
|
static void ElectrocutePlayer();
|
|
static void KnockbackPlayer(float strength);
|
|
static void GiveOrTakeShield(int32_t shield);
|
|
static void ForceInterfaceUpdate();
|
|
static void UpdateActor(void* refActor);
|
|
static void TeleportPlayer(int32_t nextEntrance);
|
|
static void ClearAssignedButtons(uint8_t buttonSet);
|
|
static void SetTimeOfDay(uint32_t time);
|
|
static void SetCollisionViewer(bool active);
|
|
static void SetCosmeticsColor(uint8_t cosmeticCategory, uint8_t colorValue);
|
|
static void RandomizeCosmeticsColors(bool excludeBiddingWarColors);
|
|
static void EmulateButtonPress(int32_t button);
|
|
static void AddOrTakeAmmo(int16_t amount, int16_t item);
|
|
static void EmulateRandomButtonPress(uint32_t chancePercentage = 100);
|
|
static void SetRandomWind(bool active);
|
|
static void SetPlayerInvincibility(bool active);
|
|
static void ClearCutscenePointer();
|
|
|
|
static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams);
|
|
static GameInteractionEffectQueryResult SpawnActor(uint32_t actorId, int32_t actorParams);
|
|
};
|
|
|
|
private:
|
|
#ifdef ENABLE_REMOTE_CONTROL
|
|
IPaddress remoteIP;
|
|
TCPsocket remoteSocket;
|
|
std::thread remoteThreadReceive;
|
|
std::function<void(char payload[512])> remoteDataHandler;
|
|
std::function<void(nlohmann::json)> remoteJsonHandler;
|
|
std::function<void()> remoteConnectedHandler;
|
|
std::function<void()> remoteDisconnectedHandler;
|
|
|
|
void ReceiveFromServer();
|
|
void HandleRemoteData(char payload[512]);
|
|
void HandleRemoteJson(std::string payload);
|
|
#endif
|
|
};
|
|
|
|
#undef GET_CURRENT_REGISTERING_INFO
|
|
|
|
#endif /* __cplusplus */
|
|
#endif /* GameInteractor_h */
|