Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raw input #354

Merged
merged 10 commits into from
Nov 5, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/game_data/spel2.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions docs/src/includes/_enums.md
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,8 @@ Name | Data | Description
[POST_LEVEL_DESTRUCTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.POST_LEVEL_DESTRUCTION) | ON::POST_LEVEL_DESTRUCTION | Runs right after the current level has been unloaded and all entities destroyed. Runs in pretty much all screens, even ones without entities. The screen has already changed at this point, meaning the screen being destoyed is in state.screen_last.<br/>
[PRE_LAYER_DESTRUCTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.PRE_LAYER_DESTRUCTION) | ON::PRE_LAYER_DESTRUCTION | Params: [LAYER](#LAYER) layer<br/>Runs right before a layer is unloaded and any entities there destroyed. Runs in pretty much all screens, even ones without entities. The screen has already changed at this point, meaning the screen being destoyed is in state.screen_last.<br/>
[POST_LAYER_DESTRUCTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.POST_LAYER_DESTRUCTION) | ON::POST_LAYER_DESTRUCTION | Params: [LAYER](#LAYER) layer<br/>Runs right after a layer has been unloaded and any entities there destroyed. Runs in pretty much all screens, even ones without entities. The screen has already changed at this point, meaning the screen being destoyed is in state.screen_last.<br/>
[PRE_PROCESS_INPUT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.PRE_PROCESS_INPUT) | ON::PRE_PROCESS_INPUT | Runs right before the game gets input from various devices and writes to a bunch of buttons-variables. Return true to disable all game input completely.<br/>
[POST_PROCESS_INPUT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.POST_PROCESS_INPUT) | ON::POST_PROCESS_INPUT | Runs right after the game gets input from various devices and writes to a bunch of buttons-variables. Probably the first chance you have to capture or edit buttons_gameplay or buttons_menu sort of things.<br/>

## PARTICLEEMITTER

Expand Down
14 changes: 14 additions & 0 deletions docs/src/includes/_events.md
Original file line number Diff line number Diff line change
Expand Up @@ -605,3 +605,17 @@ Params: [LAYER](#LAYER) layer<br/>Runs right before a layer is unloaded and any
> Search script examples for [ON.POST_LAYER_DESTRUCTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.POST_LAYER_DESTRUCTION)

Params: [LAYER](#LAYER) layer<br/>Runs right after a layer has been unloaded and any entities there destroyed. Runs in pretty much all screens, even ones without entities. The screen has already changed at this point, meaning the screen being destoyed is in state.screen_last.<br/>

## ON.PRE_PROCESS_INPUT


> Search script examples for [ON.PRE_PROCESS_INPUT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.PRE_PROCESS_INPUT)

Runs right before the game gets input from various devices and writes to a bunch of buttons-variables. Return true to disable all game input completely.<br/>

## ON.POST_PROCESS_INPUT


> Search script examples for [ON.POST_PROCESS_INPUT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.POST_PROCESS_INPUT)

Runs right after the game gets input from various devices and writes to a bunch of buttons-variables. Probably the first chance you have to capture or edit buttons_gameplay or buttons_menu sort of things.<br/>
9 changes: 9 additions & 0 deletions docs/src/includes/_globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -2064,6 +2064,15 @@ Returns: [ImGuiIO](#ImGuiIO) for raw keyboard, mouse and xinput gamepad stuff.
- Note: [Overlunky](#Overlunky)/etc will eat all keys it is currently configured to use, your script will only get leftovers.
- Note: [Gamepad](#Gamepad) is basically [XINPUT_GAMEPAD](https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_gamepad) but variables are renamed and values are normalized to -1.0..1.0 range.

### get_raw_input


> Search script examples for [get_raw_input](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_raw_input)

#### [RawInput](#RawInput) get_raw_input()

Returns [RawInput](#RawInput), a game structure for raw keyboard and controller state

### mouse_position


Expand Down
41 changes: 41 additions & 0 deletions docs/src/includes/_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,14 @@ tuple&lt;int, int, int, int&gt; | [get_rgba()](https://github.com/spelunky-fyi/o
[Color](#Color) | [set_ucolor(uColor color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_ucolor) | Changes color based on given [uColor](#Aliases)
[Color](#Color) | [set(Color other)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set) | Copies the values of different [Color](#Color) to this one

### ControllerButton


Type | Name | Description
---- | ---- | -----------
bool | [down](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=down) | [Button](#Button) is being held
bool | [pressed](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=pressed) | [Button](#Button) was just pressed down this frame

### CutsceneBehavior


Expand Down Expand Up @@ -744,6 +752,13 @@ Type | Name | Description
[ENT_TYPE](#ENT_TYPE) | [owner_type](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=owner_type) |
int | [owner_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=owner_uid) |

### KeyboardKey


Type | Name | Description
---- | ---- | -----------
bool | [down](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=down) | Key is being held

### Letter


Expand Down Expand Up @@ -983,6 +998,13 @@ tuple&lt;float, float&gt; | [split()](https://github.com/spelunky-fyi/overlunky/
## Input types


### ControllerInput


Type | Name | Description
---- | ---- | -----------
array&lt;[ControllerButton](#ControllerButton), 16&gt; | [buttons](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=buttons) |

### Gamepad

Used in [ImGuiIO](#ImGuiIO)
Expand Down Expand Up @@ -1061,6 +1083,23 @@ array&lt;[PlayerSlotSettings](#PlayerSlotSettings), MAX_PLAYERS&gt; | [player_se
[PlayerSlotSettings](#PlayerSlotSettings) | [player_slot_3_settings](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_slot_3_settings) |
[PlayerSlotSettings](#PlayerSlotSettings) | [player_slot_4_settings](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_slot_4_settings) |

### RawInput


Type | Name | Description
---- | ---- | -----------
array&lt;[KeyboardKey](#KeyboardKey), 112&gt; | [keyboard](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=keyboard) | State of all keyboard buttons in a random game order as usual
array&lt;[ControllerInput](#ControllerInput), 12&gt; | [controller](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=controller) | State of controller buttons per controller. Zero-based indexing, i.e. use game_props.input_index directly to index this.

### SomeInput


Type | Name | Description
---- | ---- | -----------
bool | [enabled](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=enabled) |
int | [input_index](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=input_index) |
int | [buttons](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=buttons) |

## Journal types


Expand Down Expand Up @@ -2793,6 +2832,8 @@ int | [buttons_extra](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=b
[MENU_INPUT](#MENU_INPUT) | [buttons_menu](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=buttons_menu) | Inputs used to control all the menus, separate from player inputs. You can probably capture and edit this in [ON](#ON).PRE_UPDATE.
bool | [game_has_focus](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=game_has_focus) |
int | [modal_open](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=modal_open) |
array&lt;[SomeInput](#SomeInput), 12&gt; | [some_input](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=some_input) | Yet another place for some buttons in some random order, too tired to make another enum for them
array&lt;int, 5&gt; | [input_index](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=input_index) | Input index for players 1-4 and maybe for the menu controls. -1: disabled, 0..3: keyboards, 4..7: Xinput, 8..11: other controllers

### Items

Expand Down
16 changes: 16 additions & 0 deletions src/game_api/flags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -767,3 +767,19 @@ std::array renderer_flags1{
"Liquid smoothing",
"unknown",
};

std::array player_inputs{
"Disabled",
"Keyboard 1",
"Keyboard 2",
"Keyboard 3",
"Keyboard 4",
"XInput 1",
"XInput 2",
"XInput 3",
"XInput 4",
"Controller 1",
"Controller 2",
"Controller 3",
"Controller 4",
};
6 changes: 6 additions & 0 deletions src/game_api/game_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ GameManager* get_game_manager()
static GameManager** gm = (GameManager**)get_address("game_manager"sv);
return *gm;
}

RawInput* get_raw_input()
{
static auto offset = get_address("input_table");
return reinterpret_cast<RawInput*>(offset);
}
46 changes: 42 additions & 4 deletions src/game_api/game_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,43 @@ struct BackgroundMusic
uint32_t unknown22;
};

struct KeyboardKey
{
/// Key is being held
bool down;
size_t unknown;
};

struct ControllerButton
{
/// Button is being held
bool down;
/// Button was just pressed down this frame
bool pressed;
};

struct ControllerInput
{
std::array<ControllerButton, 16> buttons;
};

struct RawInput
{
/// State of all keyboard buttons in a random game order as usual
std::array<KeyboardKey, 112> keyboard;
/// State of controller buttons per controller. Zero-based indexing, i.e. use game_props.input_index directly to index this.
std::array<ControllerInput, 12> controller;
};

struct SomeInput
{
bool enabled;
uint8_t padding1[3];
int8_t input_index;
uint8_t padding2[3];
uint32_t buttons;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The struct is
4x bool
int8 input_index
//probably padding
int32 buttons
int8 unknown

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the first bool is disabled not enabled
second one is like enabled or something (setting false disables it)
dunno about third
fourth is "connected" - if set to false you get popup about controller disconnected

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, third one is like "can_use_menu"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah I figured there must be more of them, but didn't actually even test what the first one does. The controllers kept getting reserved, not being able to switch to again, even though not set in any input_index, and some of these is probably why

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last byte is used as first parameter to XInputSetState, at least for the XInput controllers

Copy link
Contributor

@Mr-Auto Mr-Auto Nov 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the first bool is disabled not enabled
second one is like enabled or something (setting false disables it)
dunno about third
fourth is "connected" - if set to false you get popup about controller disconnected

these didn't make any sense after all, everything you said seems backwards

the fourth i made mistake it's more like "lost_connection" the rest should be correct, so by default you have:

false
true
true
false

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except for keyboard those are not default

Copy link
Contributor

@Mr-Auto Mr-Auto Nov 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess we're wrong about the first two (what they mean), and keyboard doesn't seam to care about the menu one
or the struct are different for keyboard vs controller

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whatever, not really even smart to expose that struct to the api...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also the struct is much larger, seen accessed qword at offset 0x280

};

struct GameProps
{
/// Might be used for some menu inputs not found in buttons_menu
Expand All @@ -90,11 +127,11 @@ struct GameProps
bool game_has_focus;
bool unknown9;
bool unknown10;
// there's more stuff here
std::array<size_t*, 12> unknown11; // pointers to something
/// Yet another place for some buttons in some random order, too tired to make another enum for them
std::array<SomeInput*, 12> some_input;

int8_t input_index[5]; // not sure, just came up with this name, if not used it's -1
// for example if you just run the game and use OL to warp somewhere immediately there will be no controller setup, so all of those will be -1
/// Input index for players 1-4 and maybe for the menu controls. -1: disabled, 0..3: keyboards, 4..7: Xinput, 8..11: other controllers
std::array<int8_t, 5> input_index;

// uint8_t padding_probably1[3];

Expand Down Expand Up @@ -160,3 +197,4 @@ struct GameManager
};

GameManager* get_game_manager();
RawInput* get_raw_input();
26 changes: 26 additions & 0 deletions src/game_api/script/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,3 +486,29 @@ bool pre_set_feat(FEAT feat)
});
return block;
}

bool pre_process_input()
{
bool return_val = false;
LuaBackend::for_each_backend(
[=, &return_val](LuaBackend::LockedBackend backend)
{
if (backend->on_pre_process_input())
{
return_val = true;
return false;
}
return true;
});
return return_val;
}

void post_process_input()
{
LuaBackend::for_each_backend(
[&](LuaBackend::LockedBackend backend)
{
backend->on_post_process_input();
return true;
});
}
2 changes: 2 additions & 0 deletions src/game_api/script/events.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ bool pre_init_level();
bool pre_init_layer(LAYER layer);
bool pre_unload_level();
bool pre_unload_layer(LAYER layer);
bool pre_process_input();

void post_room_generation();
void post_level_generation();
Expand All @@ -30,6 +31,7 @@ void post_init_level();
void post_init_layer(LAYER layer);
void post_unload_level();
void post_unload_layer(LAYER layer);
void post_process_input();

void on_death_message(STRINGID stringid);
std::optional<bool> pre_get_feat(FEAT feat);
Expand Down
51 changes: 51 additions & 0 deletions src/game_api/script/lua_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1856,3 +1856,54 @@ void LuaBackend::on_set_user_data(Entity* ent)
}
}
}

bool LuaBackend::on_pre_process_input()
{
if (!get_enabled())
return false;

auto now = get_frame_count();
std::lock_guard lock{global_lua_lock};

for (auto& [id, callback] : callbacks)
{
if (is_callback_cleared(id))
continue;

if (callback.screen == ON::PRE_PROCESS_INPUT)
{
callback.lastRan = now;
set_current_callback(-1, id, CallbackType::Normal);
if (handle_function<bool>(this, callback.func).value_or(false))
{
clear_current_callback();
return true;
}
clear_current_callback();
}
}
return false;
}

void LuaBackend::on_post_process_input()
{
if (!get_enabled())
return;

auto now = get_frame_count();
std::lock_guard lock{global_lua_lock};

for (auto& [id, callback] : callbacks)
{
if (is_callback_cleared(id))
continue;

if (callback.screen == ON::POST_PROCESS_INPUT)
{
callback.lastRan = now;
set_current_callback(-1, id, CallbackType::Normal);
handle_function<void>(this, callback.func);
clear_current_callback();
}
}
}
4 changes: 4 additions & 0 deletions src/game_api/script/lua_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ enum class ON
POST_LEVEL_DESTRUCTION,
PRE_LAYER_DESTRUCTION,
POST_LAYER_DESTRUCTION,
PRE_PROCESS_INPUT,
POST_PROCESS_INPUT,
};

struct IntOption
Expand Down Expand Up @@ -435,6 +437,8 @@ class LuaBackend
bool on_pre_state_update();
void on_set_user_data(Entity* ent);
void load_user_data();
bool on_pre_process_input();
void on_post_process_input();
};

template <class Inheriting>
Expand Down
Loading
Loading