From 806746471e9a31b5830c1ac2b16d65b6f17a8434 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Wed, 26 Jun 2024 21:11:05 +0200 Subject: [PATCH 1/5] use Vec2 more, some small issues fix, more unknown stuff about camera and Hud --- docs/game_data/spel2.lua | 39 +++++- docs/src/includes/_types.md | 39 +++++- src/game_api/containers/custom_allocator.cpp | 4 +- src/game_api/entities_mounts.hpp | 13 +- src/game_api/entity.cpp | 12 +- src/game_api/entity.hpp | 6 +- src/game_api/entity_db.hpp | 15 +-- src/game_api/game_api.hpp | 28 ++-- src/game_api/illumination.cpp | 14 +- src/game_api/layer.cpp | 10 +- src/game_api/level_api.cpp | 12 +- src/game_api/level_api.hpp | 6 +- src/game_api/render_api.hpp | 127 +++++++++++++++--- src/game_api/rpc.cpp | 14 +- src/game_api/screen.hpp | 8 +- src/game_api/script/lua_vm.cpp | 2 +- src/game_api/script/usertypes/entity_lua.cpp | 4 +- src/game_api/script/usertypes/screen_lua.cpp | 8 +- src/game_api/script/usertypes/state_lua.cpp | 4 + .../script/usertypes/vanilla_render_lua.cpp | 27 +++- src/game_api/sound_manager.hpp | 2 +- src/game_api/spawn_api.cpp | 54 ++++---- src/game_api/state.cpp | 18 +-- src/game_api/state.hpp | 8 +- src/game_api/state_structs.hpp | 36 +++-- src/game_api/thread_utils.hpp | 1 - src/injected/ui.cpp | 19 +-- src/injected/ui_util.cpp | 2 +- 28 files changed, 356 insertions(+), 176 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index 740da2263..42b3ba990 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -2236,8 +2236,12 @@ do ---@field shake_multiplier_x number ---@field shake_multiplier_y number ---@field uniform_shake boolean - ---@field focused_entity_uid integer + ---@field focused_entity_uid integer @if set to -1, you have free control over camera focus through focus_x, focus_y ---@field inertia number @This is a bad name, but it represents the camera tweening speed. [0..5] where 0=still, 1=default (move 20% of distance per frame), 5=max (move 5*20% or 100% aka instantly to destination per frame) + ---@field peek_timer integer @amount of frames to freeze camera in place and move to the peek_layer
during the peek you can freely set camera position no matter if focused_entity_uid is set to -1 or not + ---@field peek_layer integer + ---@field get_bounds fun(self): AABB + ---@field set_bounds fun(self, bounds: AABB): nil ---@class Online ---@field online_players OnlinePlayer[] @size: 4 @@ -5418,11 +5422,12 @@ function VanillaRenderContext:draw_world_poly_filled(points, color) end ---@field ropes integer ---@field ankh boolean ---@field kapala boolean - ---@field kapala_blood integer + ---@field kapala_sprite SpritePosition ---@field poison boolean ---@field curse boolean ---@field elixir boolean ---@field crown ENT_TYPE @Powerup type or 0 + ---@field powerup_sprites SpritePosition[] @size: 18 ---@field item_count integer @Amount of generic pickup items at the bottom. Set to 0 to not draw them. ---@class HudElement @@ -5445,16 +5450,38 @@ function VanillaRenderContext:draw_world_poly_filled(points, color) end ---@field udjat boolean ---@field money_total integer ---@field money_counter integer - ---@field time_total integer - ---@field time_level integer + ---@field time_total integer @in ms + ---@field time_level integer @in ms ---@field world_num integer ---@field level_num integer + ---@field angry_shopkeeper boolean + ---@field seed_shown boolean ---@field seed integer ---@field opacity number + ---@field roll_in number ---@field players HudPlayer[] @size: MAX_PLAYERS ---@field money HudMoney + ---@field money_increase_sparkles ParticleEmitterInfo ---@field timer HudElement ---@field level HudElement + ---@field clover_falling_apart_timer number + ---@field player_cursed_paricles ParticleEmitterInfo[] @size: MAX_PLAYERS + ---@field player_poisoned_paricles ParticleEmitterInfo[] @size: MAX_PLAYERS + ---@field player_highlight TextureRenderingInfo @For player related icons, they use the same TextureRendering, just offset while drawing + ---@field player_heart TextureRenderingInfo + ---@field player_ankh TextureRenderingInfo + ---@field kapala_icon TextureRenderingInfo + ---@field player_crown TextureRenderingInfo + ---@field player_bomb TextureRenderingInfo + ---@field player_rope TextureRenderingInfo + ---@field udjat_icon TextureRenderingInfo + ---@field money_and_time_highlight TextureRenderingInfo @Money and time use the same TextureRendering, just offset while drawing + ---@field dollar_icon TextureRenderingInfo + ---@field hourglass_icon TextureRenderingInfo + ---@field clover_icon TextureRenderingInfo + ---@field level_highlight TextureRenderingInfo + ---@field level_icon TextureRenderingInfo + ---@field seed_background TextureRenderingInfo ---@class Hud ---@field y number @@ -5644,7 +5671,7 @@ function Quad:is_point_inside(x, y, epsilon) end ---@field music SoundMeta ---@field torch_sound SoundMeta ----@class SpearDanglerAnimFrames +---@class SpritePosition ---@field column integer ---@field row integer @@ -5680,7 +5707,7 @@ function Quad:is_point_inside(x, y, epsilon) end ---@field transfer_to_menu_id integer ---@field menu_text_opacity number ---@field spear_position number[] @size: 6 - ---@field spear_dangler SpearDanglerAnimFrames[] @size: 6 + ---@field spear_dangler SpritePosition[] @size: 6 ---@field spear_dangle_momentum integer[] @size: 6 ---@field spear_dangle_angle integer[] @size: 6 ---@field play_scroll_descend_timer number diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 01bf3445b..12c89b278 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -501,11 +501,12 @@ int | [bombs](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bombs) | int | [ropes](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ropes) | bool | [ankh](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ankh) | bool | [kapala](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kapala) | -int | [kapala_blood](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kapala_blood) | +[SpritePosition](#SpritePosition) | [kapala_sprite](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kapala_sprite) | bool | [poison](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=poison) | bool | [curse](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=curse) | bool | [elixir](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=elixir) | [ENT_TYPE](#ENT_TYPE) | [crown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=crown) | [Powerup](#Powerup) type or 0 +array<[SpritePosition](#SpritePosition), 18> | [powerup_sprites](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=powerup_sprites) | int | [item_count](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=item_count) | Amount of generic pickup items at the bottom. Set to 0 to not draw them. ### Inventory @@ -706,16 +707,38 @@ array<[HudInventory](#HudInventory), MAX_PLAYERS> | [inventory](https://gi bool | [udjat](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=udjat) | int | [money_total](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=money_total) | int | [money_counter](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=money_counter) | -int | [time_total](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=time_total) | -int | [time_level](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=time_level) | +int | [time_total](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=time_total) | in ms +int | [time_level](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=time_level) | in ms int | [world_num](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=world_num) | int | [level_num](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=level_num) | +bool | [angry_shopkeeper](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=angry_shopkeeper) | +bool | [seed_shown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=seed_shown) | int | [seed](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=seed) | float | [opacity](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=opacity) | +float | [roll_in](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=roll_in) | array<[HudPlayer](#HudPlayer), MAX_PLAYERS> | [players](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=players) | [HudMoney](#HudMoney) | [money](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=money) | +[ParticleEmitterInfo](#ParticleEmitterInfo) | [money_increase_sparkles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=money_increase_sparkles) | [HudElement](#HudElement) | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | [HudElement](#HudElement) | [level](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=level) | +float | [clover_falling_apart_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clover_falling_apart_timer) | +array<[ParticleEmitterInfo](#ParticleEmitterInfo), MAX_PLAYERS> | [player_cursed_paricles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_cursed_paricles) | +array<[ParticleEmitterInfo](#ParticleEmitterInfo), MAX_PLAYERS> | [player_poisoned_paricles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_poisoned_paricles) | +[TextureRenderingInfo](#TextureRenderingInfo) | [player_highlight](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_highlight) | For player related icons, they use the same TextureRendering, just offset while drawing +[TextureRenderingInfo](#TextureRenderingInfo) | [player_heart](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_heart) | +[TextureRenderingInfo](#TextureRenderingInfo) | [player_ankh](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_ankh) | +[TextureRenderingInfo](#TextureRenderingInfo) | [kapala_icon](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kapala_icon) | +[TextureRenderingInfo](#TextureRenderingInfo) | [player_crown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_crown) | +[TextureRenderingInfo](#TextureRenderingInfo) | [player_bomb](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_bomb) | +[TextureRenderingInfo](#TextureRenderingInfo) | [player_rope](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_rope) | +[TextureRenderingInfo](#TextureRenderingInfo) | [udjat_icon](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=udjat_icon) | +[TextureRenderingInfo](#TextureRenderingInfo) | [money_and_time_highlight](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=money_and_time_highlight) | Money and time use the same TextureRendering, just offset while drawing +[TextureRenderingInfo](#TextureRenderingInfo) | [dollar_icon](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=dollar_icon) | +[TextureRenderingInfo](#TextureRenderingInfo) | [hourglass_icon](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hourglass_icon) | +[TextureRenderingInfo](#TextureRenderingInfo) | [clover_icon](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clover_icon) | +[TextureRenderingInfo](#TextureRenderingInfo) | [level_highlight](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=level_highlight) | +[TextureRenderingInfo](#TextureRenderingInfo) | [level_icon](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=level_icon) | +[TextureRenderingInfo](#TextureRenderingInfo) | [seed_background](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=seed_background) | ### HudElement @@ -998,7 +1021,7 @@ Type | Name | Description float | [x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=x) | float | [y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=y) | -### SpearDanglerAnimFrames +### SpritePosition Type | Name | Description @@ -2485,7 +2508,7 @@ int | [menu_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=menu_id int | [transfer_to_menu_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=transfer_to_menu_id) | float | [menu_text_opacity](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=menu_text_opacity) | array<float, 6> | [spear_position](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spear_position) | -array<[SpearDanglerAnimFrames](#SpearDanglerAnimFrames), 6> | [spear_dangler](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spear_dangler) | +array<[SpritePosition](#SpritePosition), 6> | [spear_dangler](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spear_dangler) | array<int, 6> | [spear_dangle_momentum](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spear_dangle_momentum) | array<int, 6> | [spear_dangle_angle](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spear_dangle_angle) | float | [play_scroll_descend_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=play_scroll_descend_timer) | @@ -2832,8 +2855,12 @@ float | [shake_amplitude](https://github.com/spelunky-fyi/overlunky/search?l=Lua float | [shake_multiplier_x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=shake_multiplier_x) | float | [shake_multiplier_y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=shake_multiplier_y) | bool | [uniform_shake](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=uniform_shake) | -int | [focused_entity_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=focused_entity_uid) | +int | [focused_entity_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=focused_entity_uid) | if set to -1, you have free control over camera focus through focus_x, focus_y float | [inertia](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=inertia) | This is a bad name, but it represents the camera tweening speed. [0..5] where 0=still, 1=default (move 20% of distance per frame), 5=max (move 5*20% or 100% aka instantly to destination per frame) +int | [peek_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=peek_timer) | amount of frames to freeze camera in place and move to the peek_layer
during the peek you can freely set camera position no matter if focused_entity_uid is set to -1 or not +int | [peek_layer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=peek_layer) | +[AABB](#AABB) | [get_bounds()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_bounds) | +nil | [set_bounds(AABB bounds)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_bounds) | ### GameManager diff --git a/src/game_api/containers/custom_allocator.cpp b/src/game_api/containers/custom_allocator.cpp index 8237b9a2e..0c39c79e1 100644 --- a/src/game_api/containers/custom_allocator.cpp +++ b/src/game_api/containers/custom_allocator.cpp @@ -12,12 +12,12 @@ using CustomFreeFun = void*(void*, void*); void* custom_malloc(std::size_t size) { static CustomMallocFun* _malloc = (CustomMallocFun*)get_address("custom_malloc"sv); - static void* _alloc_base = OnHeapPointer(*(size_t*)get_address("malloc_base"sv)).decode(); + static void* _alloc_base = OnHeapPointer(*(size_t*)get_address("malloc_base"sv)).decode(); // probably should be decode_local return _malloc(_alloc_base, size); } void custom_free(void* mem) { static CustomFreeFun* _free = (CustomFreeFun*)get_address("custom_free"sv); - static void* _alloc_base = OnHeapPointer(*(size_t*)get_address("malloc_base"sv)).decode(); + static void* _alloc_base = OnHeapPointer(*(size_t*)get_address("malloc_base"sv)).decode(); // probably should be decode_local _free(_alloc_base, mem); } diff --git a/src/game_api/entities_mounts.hpp b/src/game_api/entities_mounts.hpp index 49f316254..41ee4d4a3 100644 --- a/src/game_api/entities_mounts.hpp +++ b/src/game_api/entities_mounts.hpp @@ -4,6 +4,7 @@ #include // for pair #include "entities_chars.hpp" // for PowerupCapable +#include "math.h" // for Vec2 class Movable; struct SoundMeta; @@ -28,12 +29,12 @@ class Mount : public PowerupCapable void tame(bool value); - virtual std::pair& get_special_offset(std::pair& offset) = 0; // gets special offset for the raider when jumping on mount - virtual std::pair& v96(std::pair& value) = 0; // gets something for when crouching on mount - virtual bool used_double_jump() = 0; // checks can_doublejump and unknown9b - virtual uint32_t v98(bool) = 0; // returns some constant value - virtual uint32_t v99() = 0; // returns some constant value - virtual void play_jump_on_sound() = 0; // checks if it has rider + virtual Vec2& get_special_offset(Vec2& offset) = 0; // gets special offset for the raider when jumping on mount + virtual Vec2& v96(Vec2& value) = 0; // gets something for when crouching on mount + virtual bool used_double_jump() = 0; // checks can_doublejump and unknown9b + virtual uint32_t v98(bool) = 0; // returns some constant value + virtual uint32_t v99() = 0; // returns some constant value + virtual void play_jump_on_sound() = 0; // checks if it has rider virtual void remove_rider() = 0; virtual float v102() = 0; // get offset? mech returns 0.9, the rest 0.5 virtual uint32_t v103() = 0; // returns some constant value diff --git a/src/game_api/entity.cpp b/src/game_api/entity.cpp index 4d0f09f38..9d1ca68a2 100644 --- a/src/game_api/entity.cpp +++ b/src/game_api/entity.cpp @@ -168,7 +168,7 @@ void Entity::perform_teleport(uint8_t delta_x, uint8_t delta_y) tp(this, delta_x, delta_y); } -std::pair Entity::position() +Vec2 Entity::position() { auto [x_pos, y_pos] = position_self(); @@ -183,9 +183,9 @@ std::pair Entity::position() return {x_pos, y_pos}; } -std::pair Entity::position_self() const +Vec2 Entity::position_self() const { - return std::pair(x, y); + return {x, y}; } void Entity::remove_item(uint32_t item_uid) @@ -257,7 +257,7 @@ std::tuple get_position(uint32_t uid) { Entity* ent = get_entity_ptr(uid); if (ent) - return std::make_tuple(ent->position().first, ent->position().second, ent->layer); + return std::make_tuple(ent->position().x, ent->position().y, ent->layer); return {0.0f, 0.0f, (uint8_t)0}; } @@ -290,8 +290,8 @@ std::tuple get_velocity(uint32_t uid) else if (ent->is_liquid()) { auto liquid_engine = State::get().get_correct_liquid_engine(ent->type->id); - vx = liquid_engine->entity_velocities->first; - vy = liquid_engine->entity_velocities->second; + vx = liquid_engine->entity_velocities->x; + vy = liquid_engine->entity_velocities->y; } if (ent->overlay) { diff --git a/src/game_api/entity.hpp b/src/game_api/entity.hpp index 5a90e0137..203b81799 100644 --- a/src/game_api/entity.hpp +++ b/src/game_api/entity.hpp @@ -18,7 +18,7 @@ #include "entity_db.hpp" // for EntityDB #include "entity_structs.hpp" // for CollisionInfo #include "layer.hpp" // for EntityList -#include "math.hpp" // for AABB +#include "math.hpp" // for AABB, Vec2 struct RenderInfo; struct Texture; @@ -115,7 +115,7 @@ class Entity return (size_t)this; } - std::pair position(); + Vec2 position(); void teleport(float dx, float dy, bool s, float vx, float vy, bool snap); void teleport_abs(float dx, float dy, float vx, float vy); @@ -185,7 +185,7 @@ class Entity return overlaps_with(other_left, other_bottom, other_right, other_top); } - std::pair position_self() const; + Vec2 position_self() const; void remove_item(uint32_t item_uid); TEXTURE get_texture(); diff --git a/src/game_api/entity_db.hpp b/src/game_api/entity_db.hpp index 6cabb4fcd..ba8f3a268 100644 --- a/src/game_api/entity_db.hpp +++ b/src/game_api/entity_db.hpp @@ -14,6 +14,7 @@ #include "aliases.hpp" // for ENT_TYPE, LAYER, TEXTURE, STRINGID #include "color.hpp" // for Color +#include "containers/custom_vector.hpp" // for custom_vector #include "containers/game_unordered_map.hpp" // for game_unordered_map #include "containers/identity_hasher.hpp" // for identity_hasher #include "entity_structs.hpp" // for CollisionInfo @@ -127,12 +128,6 @@ struct EntityItem } }; -struct EntityBucket -{ - void** begin; - void** current; // Note, counts down from end to begin instead of up from begin to end :shrug: - void** end; -}; struct EntityPool { std::uint32_t slot_size; @@ -140,15 +135,15 @@ struct EntityPool std::uint32_t slots_growth; std::uint32_t current_slots; std::uint64_t _ulong_0; - EntityBucket* _some_bucket; - EntityBucket* bucket; + custom_vector* _some_bucket; + custom_vector* empty_buckets; }; struct EntityFactory { EntityDB types[0x395]; bool type_set[0x395]; - std::unordered_map> entity_instance_map; - EntityMap entity_map; + std::unordered_map> entity_instance_map; // game_unorderedmap probably + EntityMap entity_map; // game_unorderedmap probably void* _ptr_7; }; diff --git a/src/game_api/game_api.hpp b/src/game_api/game_api.hpp index 025a018e3..aef0ea015 100644 --- a/src/game_api/game_api.hpp +++ b/src/game_api/game_api.hpp @@ -110,6 +110,20 @@ struct UnknownAPIStuff uint32_t unknown7; // padding? }; +struct STEAM_CALLBACK // just guessing +{ + size_t _vtable; // 4 functions, last one is destructor + uint8_t unknown1; + uint8_t padding1[3]; + uint32_t padding2; // probably base class padding + + // subclass OnGameOverlayActivated ? + bool steam_overlay_open; + uint32_t unknown_timer; + float unknown_timer_related; + uint32_t unknown11; // padding? +}; + struct GameAPI // size 0x60 { static GameAPI* get(); @@ -125,15 +139,13 @@ struct GameAPI // size 0x60 uint32_t window_width; uint32_t window_height; - size_t unknown5; // garbage? - size_t unknown6; // exe start - size_t unknown7; // some offset - size_t unknown8; // garbage? - size_t SteamAPI_Callback; // just vtable? don't know much about steam stuff + // all this below can probably be steam related stuff - uint8_t unknown10a; // bool ? - uint32_t unknown10b; + size_t unknown5; // steam related? + size_t exe_begin; + size_t unknown7; // some offset, OnHeapPointer? + size_t unknown8; // function pointer? + STEAM_CALLBACK SteamAPI_Callback; - size_t unknown11; // garbage? size_t unknown12; // garbage? }; diff --git a/src/game_api/illumination.cpp b/src/game_api/illumination.cpp index 02590c1b0..491a1f31d 100644 --- a/src/game_api/illumination.cpp +++ b/src/game_api/illumination.cpp @@ -41,12 +41,14 @@ Illumination* create_illumination(Color color, float size, int32_t uid) void refresh_illumination(Illumination* illumination) { - static uint32_t* offset = 0; - if (offset == 0) - { - size_t** heap_offset = (size_t**)get_address("refresh_illumination_heap_offset"); - auto illumination_counter = OnHeapPointer(**heap_offset); + static size_t** heap_offset = (size_t**)get_address("refresh_illumination_heap_offset"); + if (heap_offset == nullptr) + return; + + auto illumination_counter = OnHeapPointer(**heap_offset); + uint32_t* offset = illumination_counter.decode_local(); + if (offset == nullptr) offset = illumination_counter.decode(); - } + illumination->timer = *offset; } diff --git a/src/game_api/layer.cpp b/src/game_api/layer.cpp index 0a2bd6f9f..cbb932299 100644 --- a/src/game_api/layer.cpp +++ b/src/game_api/layer.cpp @@ -197,8 +197,8 @@ void Layer::move_grid_entity(Entity* ent, uint32_t x, uint32_t y, Layer* dest_la if (ent) { const auto pos = ent->position(); - const uint32_t current_grid_x = static_cast(std::round(pos.first)); - const uint32_t current_grid_y = static_cast(std::round(pos.second)); + const uint32_t current_grid_x = static_cast(std::round(pos.x)); + const uint32_t current_grid_y = static_cast(std::round(pos.y)); if (current_grid_x < g_level_max_x && current_grid_y < g_level_max_y) { if (grid_entities[current_grid_y][current_grid_x] == ent) @@ -231,14 +231,14 @@ void Layer::destroy_grid_entity(Entity* ent) } const auto pos = ent->position(); - const uint32_t current_grid_x = static_cast(std::round(pos.first)); - const uint32_t current_grid_y = static_cast(std::round(pos.second)); + const uint32_t current_grid_x = static_cast(std::round(pos.x)); + const uint32_t current_grid_y = static_cast(std::round(pos.y)); if (current_grid_x < g_level_max_x && current_grid_y < g_level_max_y) { if (grid_entities[current_grid_y][current_grid_x] == ent) { grid_entities[current_grid_y][current_grid_x] = nullptr; - update_liquid_collision_at(pos.first, pos.second, false); + update_liquid_collision_at(pos.x, pos.y, false); } } diff --git a/src/game_api/level_api.cpp b/src/game_api/level_api.cpp index bf199eb50..abc0493ec 100644 --- a/src/game_api/level_api.cpp +++ b/src/game_api/level_api.cpp @@ -760,7 +760,7 @@ struct ExtraSpawnLogicProviderImpl std::uint32_t transient_num_remaining_spawns_backlayer; }; }; - std::vector> transient_valid_positions; + std::vector transient_valid_positions; }; std::mutex g_extra_spawn_logic_providers_lock; std::uint32_t g_current_extra_spawn_id{0}; @@ -1875,15 +1875,11 @@ void LevelGenSystem::do_procedural_spawn_hook(ThemeInfo* self, SpawnInfo* spawn_ std::pair LevelGenSystem::get_room_index(float x, float y) { - return std::pair{ - static_cast(std::ceil(x - 3.5f)) / 10, - static_cast(std::ceil(121.5f - y)) / 8}; + return {static_cast(std::ceil(x - 3.5f)) / 10, static_cast(std::ceil(121.5f - y)) / 8}; } -std::pair LevelGenSystem::get_room_pos(uint32_t x, uint32_t y) +Vec2 LevelGenSystem::get_room_pos(uint32_t x, uint32_t y) { - return std::pair{ - static_cast(x * 10) + 2.5f, - 122.5f - static_cast(y * 8)}; + return {static_cast(x * 10) + 2.5f, 122.5f - static_cast(y * 8)}; } std::optional LevelGenSystem::get_room_template(uint32_t x, uint32_t y, uint8_t l) { diff --git a/src/game_api/level_api.hpp b/src/game_api/level_api.hpp index f85562239..32ee8c5ca 100644 --- a/src/game_api/level_api.hpp +++ b/src/game_api/level_api.hpp @@ -385,9 +385,7 @@ struct LevelGenRoomsMeta class SpecialLevelGeneration { public: - virtual ~SpecialLevelGeneration() - { - } + virtual ~SpecialLevelGeneration(){}; // For bees, sets rooms to be behive rooms. virtual void set_rooms() = 0; @@ -530,7 +528,7 @@ struct LevelGenSystem uint32_t unknown52; static std::pair get_room_index(float x, float y); - static std::pair get_room_pos(uint32_t x, uint32_t y); + static Vec2 get_room_pos(uint32_t x, uint32_t y); std::optional get_room_template(uint32_t x, uint32_t y, uint8_t l); bool set_room_template(uint32_t x, uint32_t y, int l, uint16_t room_template); diff --git a/src/game_api/render_api.hpp b/src/game_api/render_api.hpp index d0c90d1f7..71d52cec0 100644 --- a/src/game_api/render_api.hpp +++ b/src/game_api/render_api.hpp @@ -1,5 +1,6 @@ #pragma once +#include // for array #include // for size_t #include // for uint32_t, uint8_t, uint16_t, int32_t #include // for equal_to @@ -10,10 +11,13 @@ #include // for _Umap_traits<>::allocator_type, unordered_map #include // for pair -#include "aliases.hpp" // for TEXTURE -#include "color.hpp" // for Color -#include "math.hpp" // for Quad, AABB (ptr only) -#include "texture.hpp" // for Texture +#include "aliases.hpp" // for TEXTURE +#include "color.hpp" // for Color +#include "containers/game_unordered_map.hpp" // for game_unordered_map +#include "containers/game_vector.hpp" // for game_vector +#include "math.hpp" // for Quad, AABB (ptr only) +#include "particles.hpp" // for ParticleEmitterInfo +#include "texture.hpp" // for Texture struct JournalUI; struct Layer; @@ -367,6 +371,12 @@ void on_open_journal_chapter(JournalUI* journal_ui, uint8_t chapter, bool instan void render_draw_depth(Layer* layer, uint8_t draw_depth, float bbox_left, float bbox_bottom, float bbox_right, float bbox_top); float get_layer_transition_zoom_offset(uint8_t layer); +struct SpritePosition +{ + uint32_t column; + uint32_t row; +}; + struct HudInventory { bool enabled; @@ -378,36 +388,35 @@ struct HudInventory bool ankh; bool kapala; uint8_t b03; + float kapala_scale; - uint32_t u03; - - uint32_t kapala_blood; - - uint32_t u0c; - + union + { + /// NoDoc + uint32_t kapala_blood; + SpritePosition kapala_sprite; + }; bool poison; bool curse; bool elixir; uint8_t b13; - /// Powerup type or 0 ENT_TYPE crown; - - uint8_t skip[176 - 7 * 4 - 4]; // TODO: individual item icons + std::array powerup_sprites; /// Amount of generic pickup items at the bottom. Set to 0 to not draw them. - uint32_t item_count; + uint32_t powerup_count; }; static_assert(sizeof(HudInventory) == 176); struct HudElement { /// Hide background and dim if using the auto adjust setting. - bool dim; + bool dim; // it acutally 3 states: 0 - bright, 1 - dim, anything above - hide completely /// Background will be drawn if this is not 0.5 float opacity; /// Level time when element should dim again after hilighted, INT_MAX if dimmed on auto adjust. 0 on opaque. - int32_t time_dim; + int32_t time_dim; // it's set to INT_MAX after it was dimmed }; struct HudPlayer : HudElement @@ -415,6 +424,7 @@ struct HudPlayer : HudElement int16_t health; int16_t bombs; int16_t ropes; + // int16_t padding; int32_t idunno; }; static_assert(sizeof(HudPlayer) == 24); @@ -424,28 +434,103 @@ struct HudMoney : HudElement int32_t total; int32_t counter; uint8_t timer; - // padding? + // uint8_t padding[3]; }; struct HudData { std::array inventory; bool udjat; + // uint8_t padding[3]; int32_t money_total; int32_t money_counter; - uint32_t time_total; + /// in ms uint32_t time_level; + /// in ms + uint32_t time_total; uint8_t world_num; uint8_t level_num; + bool angry_shopkeeper; + bool seed_shown; uint32_t seed; float opacity; - uint8_t skip[1640]; // TODO: probably rendering coordinates all the way down + + /// For player related icons, they use the same TextureRendering, just offset while drawing + TextureRenderingInfo player_highlight; + TextureRenderingInfo player_heart; + TextureRenderingInfo player_ankh; + TextureRenderingInfo kapala_icon; + TextureRenderingInfo player_crown; + TextureRenderingInfo unknown_texture5; + TextureRenderingInfo player_bomb; + TextureRenderingInfo player_rope; + TextureRenderingInfo unknown_texture8; + TextureRenderingInfo unknown_texture9; + TextureRenderingInfo unknown_texture10; + TextureRenderingInfo unknown_texture11; + TextureRenderingInfo unknown_texture12; + TextureRenderingInfo udjat_icon; + TextureRenderingInfo unknown_texture14; + /// Money and time use the same TextureRendering, just offset while drawing + TextureRenderingInfo money_and_time_highlight; + TextureRenderingInfo dollar_icon; + TextureRenderingInfo hourglass_icon; + TextureRenderingInfo clover_icon; + TextureRenderingInfo level_highlight; + TextureRenderingInfo level_icon; + TextureRenderingInfo seed_background; + float roll_in; + float unknown6; + float unknown7; + float unknown8; + float unknown9; + float unknown10; + std::array player_zoom; // ? + float unknown15; + float unknown16; + float unknown17; + float unknown18; + std::array players; HudMoney money; - size_t p9c0; + ParticleEmitterInfo* money_increase_sparkles; HudElement timer; HudElement level; - // there's a few pointers and some timer missing, doesn't seem important + game_vector elements; // not sure what's for, just lists all the elements above, even for the unactive players + + uint32_t unknown20; + uint8_t unknown21; + uint8_t unknown22; + uint16_t unknown23; + float clover_falling_apart_timer; + float unknown25; + ParticleEmitterInfo* unknown26; + TextureRenderingInfo unknown27; + TextureRenderingInfo unknown28; + TextureRenderingInfo unknown29; + float unknown30; + // uint32_t unknown31; // probably padding + game_unordered_map unknown32; + float unknown33; + float unknown34; + float unknown35; + float unknown36; + float unknown37; + float unknown38; + float unknown39; + TextureRenderingInfo loading_dragon; + float loading_dragon_visibility; + float unknown42; + float unknown43; + TextureRenderingInfo loading_cog; + float unknown45; + uint32_t loading_cog_timer; + uint32_t unknown47; + bool unknown48; + // uint8_t unknown49[3]; //probably padding + float unknown51; + std::array player_cursed_paricles; + std::array player_poisoned_paricles; }; // static_assert(sizeof(HudData) <= 0xa00); diff --git a/src/game_api/rpc.cpp b/src/game_api/rpc.cpp index a54751d14..cfb3ca82b 100644 --- a/src/game_api/rpc.cpp +++ b/src/game_api/rpc.cpp @@ -169,15 +169,15 @@ void move_entity_abs(uint32_t uid, float x, float y, float vx, float vy, LAYER l auto ent = get_entity_ptr(uid); if (ent) { - std::pair offset; + Vec2 offset; enum_to_layer(layer, offset); if (ent->is_liquid()) { - move_liquid_abs(uid, offset.first + x, offset.second + y, vx, vy); + move_liquid_abs(uid, offset.x + x, offset.y + y, vx, vy); } else { - ent->teleport_abs(offset.first + x, offset.second + y, vx, vy); + ent->teleport_abs(offset.x + x, offset.y + y, vx, vy); ent->set_layer(layer); } } @@ -283,7 +283,7 @@ float screen_distance(float x) { auto a = State::screen_position(0, 0); auto b = State::screen_position(x, 0); - return b.first - a.first; + return b.x - a.x; } std::vector filter_entities(std::vector entities, std::function predicate) @@ -1211,10 +1211,10 @@ void move_grid_entity(int32_t uid, float x, float y, LAYER layer) if (auto entity = get_entity_ptr(uid)) { auto& state = State::get(); - std::pair offset; + Vec2 offset; const auto actual_layer = enum_to_layer(layer, offset); - state.layer(entity->layer)->move_grid_entity(entity, offset.first + x, offset.first + y, state.layer(actual_layer)); - entity->teleport_abs(offset.first + x, offset.first + y, 0, 0); + state.layer(entity->layer)->move_grid_entity(entity, offset.x + x, offset.y + y, state.layer(actual_layer)); + entity->teleport_abs(offset.x + x, offset.y + y, 0, 0); entity->set_layer(layer); } } diff --git a/src/game_api/screen.hpp b/src/game_api/screen.hpp index 2200623c2..8e317acf5 100644 --- a/src/game_api/screen.hpp +++ b/src/game_api/screen.hpp @@ -145,12 +145,6 @@ class ScreenTitle : public Screen // ID: 3 SoundMeta* torch_sound; }; -struct SpearDanglerAnimFrames -{ - uint32_t column; - uint32_t row; -}; - struct MenuOption { // return and first param are the same, pointer on stack, it really seam to be just two 32bit fields @@ -241,7 +235,7 @@ class ScreenMenu : public Screen // ID: 4 uint32_t transfer_to_menu_id; float menu_text_opacity; std::array spear_position; - std::array spear_dangler; + std::array spear_dangler; std::array spear_dangle_momentum; std::array spear_dangle_angle; diff --git a/src/game_api/script/lua_vm.cpp b/src/game_api/script/lua_vm.cpp index f6845ecc9..1dda7a8e6 100644 --- a/src/game_api/script/lua_vm.cpp +++ b/src/game_api/script/lua_vm.cpp @@ -1261,7 +1261,7 @@ end if (ea == nullptr || eb == nullptr) return -1.0f; else - return (float)std::sqrt(std::pow(ea->position().first - eb->position().first, 2) + std::pow(ea->position().second - eb->position().second, 2)); + return (float)std::sqrt(std::pow(ea->position().x - eb->position().x, 2) + std::pow(ea->position().y - eb->position().y, 2)); }; /// Basically gets the absolute coordinates of the area inside the unbreakable bedrock walls, from wall to wall. Every solid entity should be /// inside these boundaries. The order is: left x, top y, right x, bottom y diff --git a/src/game_api/script/usertypes/entity_lua.cpp b/src/game_api/script/usertypes/entity_lua.cpp index 7e4e0ec5e..bfac166e6 100644 --- a/src/game_api/script/usertypes/entity_lua.cpp +++ b/src/game_api/script/usertypes/entity_lua.cpp @@ -234,14 +234,14 @@ void register_usertypes(sol::state& lua) entity_type["abs_x"] = sol::property([](Entity& e) -> float { if (e.abs_x == -FLT_MAX) - return e.position().first; + return e.position().x; return e.abs_x; }); // entity_type["abs_y"] = &Entity::abs_y; /// NoDoc entity_type["abs_y"] = sol::property([](Entity& e) -> float { if (e.abs_y == -FLT_MAX) - return e.position().second; + return e.position().y; return e.abs_y; }); entity_type["layer"] = &Entity::layer; entity_type["width"] = &Entity::w; diff --git a/src/game_api/script/usertypes/screen_lua.cpp b/src/game_api/script/usertypes/screen_lua.cpp index f6ed822b2..737dfbed1 100644 --- a/src/game_api/script/usertypes/screen_lua.cpp +++ b/src/game_api/script/usertypes/screen_lua.cpp @@ -181,12 +181,12 @@ void register_usertypes(sol::state& lua) sol::base_classes, sol::bases()); - lua.new_usertype( - "SpearDanglerAnimFrames", + lua.new_usertype( + "SpritePosition", "column", - &SpearDanglerAnimFrames::column, + &SpritePosition::column, "row", - &SpearDanglerAnimFrames::row); + &SpritePosition::row); auto screenmenu_type = lua.new_usertype("ScreenMenu", sol::base_classes, sol::bases()); screenmenu_type["state"] = &ScreenMenu::state; diff --git a/src/game_api/script/usertypes/state_lua.cpp b/src/game_api/script/usertypes/state_lua.cpp index 1b4a5615a..8fa709e6c 100644 --- a/src/game_api/script/usertypes/state_lua.cpp +++ b/src/game_api/script/usertypes/state_lua.cpp @@ -492,6 +492,10 @@ void register_usertypes(sol::state& lua) camera_type["uniform_shake"] = &Camera::uniform_shake; camera_type["focused_entity_uid"] = &Camera::focused_entity_uid; camera_type["inertia"] = &Camera::inertia; + camera_type["peek_timer"] = &Camera::peek_timer; + camera_type["peek_layer"] = &Camera::peek_layer; + camera_type["get_bounds"] = &Camera::get_bounds; + camera_type["set_bounds"] = &Camera::set_bounds; /// Can be accessed via global [online](#online) lua.new_usertype( diff --git a/src/game_api/script/usertypes/vanilla_render_lua.cpp b/src/game_api/script/usertypes/vanilla_render_lua.cpp index 072cb0218..c5fad4003 100644 --- a/src/game_api/script/usertypes/vanilla_render_lua.cpp +++ b/src/game_api/script/usertypes/vanilla_render_lua.cpp @@ -903,11 +903,13 @@ void register_usertypes(sol::state& lua) hudinventory_type["ankh"] = &HudInventory::ankh; hudinventory_type["kapala"] = &HudInventory::kapala; hudinventory_type["kapala_blood"] = &HudInventory::kapala_blood; + hudinventory_type["kapala_sprite"] = &HudInventory::kapala_sprite; hudinventory_type["poison"] = &HudInventory::poison; hudinventory_type["curse"] = &HudInventory::curse; hudinventory_type["elixir"] = &HudInventory::elixir; hudinventory_type["crown"] = &HudInventory::crown; - hudinventory_type["item_count"] = &HudInventory::item_count; + hudinventory_type["powerup_sprites"] = &HudInventory::powerup_sprites; + hudinventory_type["item_count"] = &HudInventory::powerup_count; auto hudelement_type = lua.new_usertype("HudElement"); hudelement_type["dim"] = &HudElement::dim; @@ -933,12 +935,35 @@ void register_usertypes(sol::state& lua) huddata_type["time_level"] = &HudData::time_level; huddata_type["world_num"] = &HudData::world_num; huddata_type["level_num"] = &HudData::level_num; + huddata_type["angry_shopkeeper"] = &HudData::angry_shopkeeper; + huddata_type["seed_shown"] = &HudData::seed_shown; huddata_type["seed"] = &HudData::seed; huddata_type["opacity"] = &HudData::opacity; + huddata_type["roll_in"] = &HudData::roll_in; huddata_type["players"] = &HudData::players; huddata_type["money"] = &HudData::money; + huddata_type["money_increase_sparkles"] = &HudData::money_increase_sparkles; huddata_type["timer"] = &HudData::timer; huddata_type["level"] = &HudData::level; + huddata_type["clover_falling_apart_timer"] = &HudData::clover_falling_apart_timer; + huddata_type["player_cursed_paricles"] = &HudData::player_cursed_paricles; + huddata_type["player_poisoned_paricles"] = &HudData::player_poisoned_paricles; + + huddata_type["player_highlight"] = &HudData::player_highlight; + huddata_type["player_heart"] = &HudData::player_heart; + huddata_type["player_ankh"] = &HudData::player_ankh; + huddata_type["kapala_icon"] = &HudData::kapala_icon; + huddata_type["player_crown"] = &HudData::player_crown; + huddata_type["player_bomb"] = &HudData::player_bomb; + huddata_type["player_rope"] = &HudData::player_rope; + huddata_type["udjat_icon"] = &HudData::udjat_icon; + huddata_type["money_and_time_highlight"] = &HudData::money_and_time_highlight; + huddata_type["dollar_icon"] = &HudData::dollar_icon; + huddata_type["hourglass_icon"] = &HudData::hourglass_icon; + huddata_type["clover_icon"] = &HudData::clover_icon; + huddata_type["level_highlight"] = &HudData::level_highlight; + huddata_type["level_icon"] = &HudData::level_icon; + huddata_type["seed_background"] = &HudData::seed_background; auto hud_type = lua.new_usertype("Hud"); hud_type["y"] = &Hud::y; diff --git a/src/game_api/sound_manager.hpp b/src/game_api/sound_manager.hpp index c23011705..bb59e0ef1 100644 --- a/src/game_api/sound_manager.hpp +++ b/src/game_api/sound_manager.hpp @@ -257,7 +257,7 @@ struct SoundInfo int64_t unknown1; uint32_t sound_id; int32_t unknown2; // padding probably - std::string sound_name; // not 100% sure it's standard + std::string sound_name; // not 100% sure if it's standard }; struct SoundMeta diff --git a/src/game_api/spawn_api.cpp b/src/game_api/spawn_api.cpp index 28013a6dd..4ed5b0a21 100644 --- a/src/game_api/spawn_api.cpp +++ b/src/game_api/spawn_api.cpp @@ -171,10 +171,10 @@ int32_t spawn_entity_abs(ENT_TYPE entity_type, float x, float y, LAYER layer, fl OnScopeExit pop{[] { pop_spawn_type_flags(SPAWN_TYPE_SCRIPT); }}; - std::pair offset_position; + Vec2 offset_position; uint8_t actual_layer = enum_to_layer(layer, offset_position); - return State::get().layer(actual_layer)->spawn_entity(entity_type, x + offset_position.first, y + offset_position.second, false, vx, vy, false)->uid; + return State::get().layer(actual_layer)->spawn_entity(entity_type, x + offset_position.x, y + offset_position.y, false, vx, vy, false)->uid; } int32_t spawn_entity_snap_to_floor(ENT_TYPE entity_type, float x, float y, LAYER layer) @@ -183,10 +183,10 @@ int32_t spawn_entity_snap_to_floor(ENT_TYPE entity_type, float x, float y, LAYER OnScopeExit pop{[] { pop_spawn_type_flags(SPAWN_TYPE_SCRIPT); }}; - std::pair offset_position; + Vec2 offset_position; uint8_t actual_layer = enum_to_layer(layer, offset_position); - return State::get().layer(actual_layer)->spawn_entity_snap_to_floor(entity_type, x + offset_position.first, y + offset_position.second)->uid; + return State::get().layer(actual_layer)->spawn_entity_snap_to_floor(entity_type, x + offset_position.x, y + offset_position.y)->uid; } int32_t spawn_entity_snap_to_grid(ENT_TYPE entity_type, float x, float y, LAYER layer) @@ -195,10 +195,10 @@ int32_t spawn_entity_snap_to_grid(ENT_TYPE entity_type, float x, float y, LAYER OnScopeExit pop{[] { pop_spawn_type_flags(SPAWN_TYPE_SCRIPT); }}; - std::pair offset_position; + Vec2 offset_position; uint8_t actual_layer = enum_to_layer(layer, offset_position); - return State::get().layer(actual_layer)->spawn_entity(entity_type, x + offset_position.first, y + offset_position.second, false, 0.0f, 0.0f, true)->uid; + return State::get().layer(actual_layer)->spawn_entity(entity_type, x + offset_position.x, y + offset_position.y, false, 0.0f, 0.0f, true)->uid; } int32_t spawn_entity_abs_nonreplaceable(ENT_TYPE entity_type, float x, float y, LAYER layer, float vx, float vy) @@ -232,10 +232,10 @@ int32_t spawn_door_abs(float x, float y, LAYER layer, uint8_t w, uint8_t l, uint OnScopeExit pop{[] { pop_spawn_type_flags(SPAWN_TYPE_SCRIPT); }}; - std::pair offset_position; + Vec2 offset_position; uint8_t actual_layer = enum_to_layer(layer, offset_position); - return State::get().layer(actual_layer)->spawn_door(x + offset_position.first, y + offset_position.second, w, l, t)->uid; + return State::get().layer(actual_layer)->spawn_door(x + offset_position.x, y + offset_position.y, w, l, t)->uid; } void spawn_backdoor_abs(float x, float y) @@ -260,10 +260,10 @@ int32_t spawn_apep(float x, float y, LAYER layer, bool right) OnScopeExit pop{[] { pop_spawn_type_flags(SPAWN_TYPE_SCRIPT); }}; - std::pair offset_position; + Vec2 offset_position; uint8_t actual_layer = enum_to_layer(layer, offset_position); - return State::get().layer(actual_layer)->spawn_apep(x + offset_position.first, y + offset_position.second, right)->uid; + return State::get().layer(actual_layer)->spawn_apep(x + offset_position.x, y + offset_position.y, right)->uid; } int32_t spawn_tree(float x, float y, LAYER layer) @@ -276,11 +276,11 @@ int32_t spawn_tree(float x, float y, LAYER layer, uint16_t height) OnScopeExit pop{[] { pop_spawn_type_flags(SPAWN_TYPE_SCRIPT); }}; - std::pair offset_position; + Vec2 offset_position; uint8_t actual_layer = enum_to_layer(layer, offset_position); - x = std::roundf(x + offset_position.first); - y = std::roundf(y + offset_position.second); + x = std::roundf(x + offset_position.x); + y = std::roundf(y + offset_position.y); Layer* layer_ptr = State::get().layer(actual_layer); @@ -335,13 +335,13 @@ int32_t spawn_tree(float x, float y, LAYER layer, uint16_t height) }; auto test_pos = current_piece->position(); - if (static_cast(test_pos.first) + 1 < g_level_max_x && layer_ptr->get_grid_entity_at(test_pos.first + 1, test_pos.second) == nullptr && + if (static_cast(test_pos.x) + 1 < g_level_max_x && layer_ptr->get_grid_entity_at(test_pos.x + 1, test_pos.y) == nullptr && prng.random_chance(2, PRNG::PRNG_CLASS::ENTITY_VARIATION)) { Entity* branch = layer_ptr->spawn_entity_over(tree_branch, current_piece, 1.02f, 0.0f); spawn_deco(branch, false); } - if (static_cast(test_pos.first) - 1 > 0 && layer_ptr->get_grid_entity_at(test_pos.first - 1, test_pos.second) == nullptr && + if (static_cast(test_pos.x) - 1 > 0 && layer_ptr->get_grid_entity_at(test_pos.x - 1, test_pos.y) == nullptr && prng.random_chance(2, PRNG::PRNG_CLASS::ENTITY_VARIATION)) { Entity* branch = layer_ptr->spawn_entity_over(tree_branch, current_piece, -1.02f, 0.0f); @@ -364,11 +364,11 @@ int32_t spawn_mushroom(float x, float y, LAYER l, uint16_t height) // height rel OnScopeExit pop{[] { pop_spawn_type_flags(SPAWN_TYPE_SCRIPT); }}; - std::pair offset(0.0f, 0.0f); + Vec2 offset(0.0f, 0.0f); const auto actual_layer = enum_to_layer(l, offset); const auto layer_ptr = State::get().layer(actual_layer); - const uint32_t i_x = static_cast(x + offset.first + 0.5f); - uint32_t i_y = static_cast(y + offset.second + 0.5f); + const uint32_t i_x = static_cast(x + offset.x + 0.5f); + uint32_t i_y = static_cast(y + offset.y + 0.5f); static const auto base = to_id("ENT_TYPE_FLOOR_MUSHROOM_BASE"); static const auto trunk = to_id("ENT_TYPE_FLOOR_MUSHROOM_TRUNK"); static const auto top = to_id("ENT_TYPE_FLOOR_MUSHROOM_TOP"); @@ -433,11 +433,11 @@ int32_t spawn_unrolled_player_rope(float x, float y, LAYER layer, TEXTURE textur static const auto setup_top_rope_rendering_info_two = (setup_top_rope_rendering_info_two_fun*)get_address("setup_top_rope_rendering_info_two"sv); static const auto rope_ent = to_id("ENT_TYPE_ITEM_CLIMBABLE_ROPE"); - std::pair offset(0.0f, 0.0f); + Vec2 offset(0.0f, 0.0f); const auto actual_layer = enum_to_layer(layer, offset); const auto layer_ptr = State::get().layer(actual_layer); - const uint32_t i_x = static_cast(x + offset.first + 0.5f); - const uint32_t i_y = static_cast(y + offset.second + 0.5f); + const uint32_t i_x = static_cast(x + offset.x + 0.5f); + const uint32_t i_y = static_cast(y + offset.y + 0.5f); const float g_x = static_cast(i_x); const float g_y = static_cast(i_y); @@ -523,10 +523,10 @@ Entity* spawn_impostor_lake(AABB aabb, LAYER layer, ENT_TYPE impostor_type, floa OnScopeExit pop{[] { pop_spawn_type_flags(SPAWN_TYPE_SCRIPT); }}; - std::pair offset_position; + Vec2 offset_position; uint8_t actual_layer = enum_to_layer(layer, offset_position); - aabb.offset(offset_position.first, offset_position.second); + aabb.offset(offset_position.x, offset_position.y); auto [x, y] = aabb.center(); @@ -735,10 +735,10 @@ int32_t spawn_companion(ENT_TYPE companion_type, float x, float y, LAYER layer) typedef Player* spawn_companion_func(StateMemory*, float x, float y, size_t layer, uint32_t entity_type); static spawn_companion_func* sc = (spawn_companion_func*)(offset); - std::pair pos_offset; + Vec2 pos_offset; const auto actual_layer = enum_to_layer(layer, pos_offset); - Player* spawned = sc(state, x + pos_offset.first, y + pos_offset.second, actual_layer, companion_type); + Player* spawned = sc(state, x + pos_offset.x, y + pos_offset.y, actual_layer, companion_type); return spawned->uid; } return -1; @@ -796,7 +796,7 @@ int32_t spawn_playerghost(ENT_TYPE char_type, float x, float y, LAYER layer) OnScopeExit pop{[] { pop_spawn_type_flags(SPAWN_TYPE_SCRIPT); }}; - std::pair offset; + Vec2 offset; const auto l = enum_to_layer(layer, offset); auto level_layer = State::get().layer(l); @@ -809,7 +809,7 @@ int32_t spawn_playerghost(ENT_TYPE char_type, float x, float y, LAYER layer) if (char_type < ana || char_type > egg_child) return -1; - auto player_ghost_entity = level_layer->spawn_entity(player_ghost, x + offset.first, y + offset.second, false, 0, 0, false)->as(); + auto player_ghost_entity = level_layer->spawn_entity(player_ghost, x + offset.x, y + offset.y, false, 0, 0, false)->as(); if (player_ghost_entity) { player_ghost_entity->player_inputs = &dummy_player_controls; diff --git a/src/game_api/state.cpp b/src/game_api/state.cpp index 20e010c2f..583bc1dcf 100644 --- a/src/game_api/state.cpp +++ b/src/game_api/state.cpp @@ -72,10 +72,10 @@ void fix_liquid_out_of_bounds() for (uint32_t i = 0; i < it.physics_engine->entity_count; ++i) { auto liquid_coordinates = it.physics_engine->entity_coordinates + i; - if (liquid_coordinates->second < 0 // y < 0 - || liquid_coordinates->first < 0 // x < 0 - || liquid_coordinates->first > g_level_max_x // x > g_level_max_x - || liquid_coordinates->second > g_level_max_y + 16) // y > g_level_max_y + if (liquid_coordinates->y < 0 // y < 0 + || liquid_coordinates->x < 0 // x < 0 + || liquid_coordinates->x > g_level_max_x // x > g_level_max_x + || liquid_coordinates->y > g_level_max_y + 16) // y > g_level_max_y { if (!*(it.physics_engine->unknown61 + i)) // just some bs continue; @@ -356,7 +356,7 @@ float get_zoom_level() return game_api->get_current_zoom(); } -std::pair State::click_position(float x, float y) +Vec2 State::click_position(float x, float y) { float cz = get_zoom_level(); auto [cx, cy] = get_camera_position(); @@ -365,7 +365,7 @@ std::pair State::click_position(float x, float y) return {rx, ry}; } -std::pair State::screen_position(float x, float y) +Vec2 State::screen_position(float x, float y) { float cz = get_zoom_level(); auto [cx, cy] = get_camera_position(); @@ -458,7 +458,7 @@ void State::darkmode(bool g) } } -std::pair State::get_camera_position() +Vec2 State::get_camera_position() { static const auto addr = (float*)get_address("camera_position"); auto cx = *addr; @@ -539,7 +539,7 @@ void State::set_seed(uint32_t seed) SaveData* State::savedata() { auto gm = get_game_manager(); - return gm->save_related->savedata.decode(); + return gm->save_related->savedata.decode(); // wondering if it matters if it's local or not? } uint32_t lowbias32(uint32_t x) { @@ -811,7 +811,7 @@ void init_game_loop_hook() } } -uint8_t enum_to_layer(const LAYER layer, std::pair& player_position) +uint8_t enum_to_layer(const LAYER layer, Vec2& player_position) { if (layer == LAYER::FRONT) { diff --git a/src/game_api/state.hpp b/src/game_api/state.hpp index 68bd709d2..3abe16348 100644 --- a/src/game_api/state.hpp +++ b/src/game_api/state.hpp @@ -355,8 +355,8 @@ struct State void zoom(float level); void zoom_reset(); - static std::pair click_position(float x, float y); - static std::pair screen_position(float x, float y); + static Vec2 click_position(float x, float y); + static Vec2 screen_position(float x, float y); uint32_t flags() const { @@ -380,7 +380,7 @@ struct State static Entity* find(StateMemory* state, uint32_t uid); - static std::pair get_camera_position(); + static Vec2 get_camera_position(); void set_camera_position(float cx, float cy); void warp(uint8_t w, uint8_t l, uint8_t t); void set_seed(uint32_t seed); @@ -399,7 +399,7 @@ void init_state_update_hook(); void init_process_input_hook(); void init_game_loop_hook(); -uint8_t enum_to_layer(const LAYER layer, std::pair& player_position); +uint8_t enum_to_layer(const LAYER layer, Vec2& player_position); uint8_t enum_to_layer(const LAYER layer); uint32_t lowbias32(uint32_t x); diff --git a/src/game_api/state_structs.hpp b/src/game_api/state_structs.hpp index a34d6a108..a30eeea7d 100644 --- a/src/game_api/state_structs.hpp +++ b/src/game_api/state_structs.hpp @@ -4,6 +4,7 @@ #include "containers/custom_map.hpp" #include "containers/custom_vector.hpp" #include "layer.hpp" +#include "math.h" // for AABB, Vec2 #include "render_api.hpp" #include #include @@ -137,17 +138,30 @@ struct Camera float shake_multiplier_x; // set to 0 to eliminate horizontal shake; negative inverts direction float shake_multiplier_y; // set to 0 to eliminate vertical shake; negative inverts direction bool uniform_shake; // if false, the shake gets randomized a bit - uint8_t padding1; - uint8_t padding2; - uint8_t padding3; - int32_t focused_entity_uid; // if set to -1, you have free control over camera focus through focus_x, focus_y - uint32_t freeze_timer; // if > 0, disables camera movement for this amount of frames - uint32_t unknown4; + uint8_t padding1[3]; + /// if set to -1, you have free control over camera focus through focus_x, focus_y + int32_t focused_entity_uid; + /// amount of frames to freeze camera in place and move to the peek_layer + /// during the peek you can freely set camera position no matter if focused_entity_uid is set to -1 or not + uint32_t peek_timer; + uint8_t peek_layer; + uint8_t padding2[3]; + /// This is a bad name, but it represents the camera tweening speed. [0..5] where 0=still, 1=default (move 20% of distance per frame), 5=max (move 5*20% or 100% aka instantly to destination per frame) float inertia; uint32_t unknown5; - uint32_t unknown6; - uint32_t unknown7; + + AABB get_bounds() const + { + return AABB(bounds_left, bounds_top, bounds_right, bounds_bottom); + } + void set_bounds(const AABB& bounds) + { + bounds_left = bounds.left; + bounds_right = bounds.right; + bounds_bottom = bounds.bottom; + bounds_top = bounds.top; + } }; struct JournalProgressStickerSlot @@ -721,10 +735,10 @@ struct LiquidPhysicsEngine uint32_t* liquid_flags; // array int32_t unknown47a; // size related for the array above int32_t unknown47b; // padding - std::pair* entity_coordinates; // array + Vec2* entity_coordinates; // array int32_t unknown49a; // size related for the array above int32_t unknown49b; // padding - std::pair* entity_velocities; // array + Vec2* entity_velocities; // array int32_t unknown51a; // size related for the array above int32_t unknown51b; // padding std::pair* unknown52; // not sure about the type, it's defenetly a 64bit @@ -1018,7 +1032,7 @@ struct MultiLineTextRendering size_t* timer; // some struct? game increments this value and one at +0x40, seam to be related to rendering, touching just the first one freezes the game std::vector lines; // each line is separete TextRenderingInfo float x; // center of the text box? - float z; // center of the text box? + float y; // center of the text box? }; struct EntityLookup diff --git a/src/game_api/thread_utils.hpp b/src/game_api/thread_utils.hpp index 007a5dbff..d36fd826d 100644 --- a/src/game_api/thread_utils.hpp +++ b/src/game_api/thread_utils.hpp @@ -15,7 +15,6 @@ class OnHeapPointer int64_t ptr_; public: - OnHeapPointer() = default; explicit OnHeapPointer(size_t ptr) : ptr_(ptr) { diff --git a/src/injected/ui.cpp b/src/injected/ui.cpp index affa782d5..af72ef7f0 100644 --- a/src/injected/ui.cpp +++ b/src/injected/ui.cpp @@ -518,7 +518,7 @@ void version_check(bool force = false) version_check_status.state = VERSION_CHECK::CHECKING; DEBUG("UpdateCheck: {}", version_check_messages[(int)version_check_status.state].message); - new HttpRequest(std::move(version_check_url), get_version_info); + new HttpRequest(version_check_url, get_version_info); } void hook_savegame() @@ -825,7 +825,7 @@ void refresh_script_files() unload_scripts.push_back(script.second->get_file()); } } - for (auto id : unload_scripts) + for (auto& id : unload_scripts) { auto it = g_scripts.find(id); if (it != g_scripts.end()) @@ -853,7 +853,7 @@ void refresh_script_files() unload_scripts.push_back(script.second->get_file()); } } - for (auto id : unload_scripts) + for (auto& id : unload_scripts) { auto it = g_scripts.find(id); if (it != g_scripts.end()) @@ -869,7 +869,7 @@ void refresh_script_files() void autorun_scripts() { - for (auto file : g_script_autorun) + for (auto& file : g_script_autorun) { std::string script = scriptpath + "/" + file; if (std::filesystem::exists(script) && std::filesystem::is_regular_file(script)) @@ -1336,15 +1336,15 @@ void smart_delete(Entity* ent, bool unsafe = false) { auto pos = ent->position(); auto layer = (LAYER)ent->layer; - UI::cleanup_at(pos.first, pos.second, layer, ent->type->id); + UI::cleanup_at(pos.x, pos.y, layer, ent->type->id); } if (ent->type->search_flags & 0x180) { auto pos = ent->position(); auto layer = (LAYER)ent->layer; ENT_TYPE type = ent->type->id; - fix_decorations_at(std::round(pos.first), std::round(pos.second), layer); - UI::cleanup_at(std::round(pos.first), std::round(pos.second), layer, type); + fix_decorations_at(std::round(pos.x), std::round(pos.y), layer); + UI::cleanup_at(std::round(pos.x), std::round(pos.y), layer, type); } } @@ -4938,16 +4938,17 @@ void render_messages() auto in_time_t = std::chrono::system_clock::to_time_t(now); std::tm time_buf; localtime_s(&time_buf, &in_time_t); - std::vector messages; + for (auto& [name, script] : g_scripts) { + std::vector messages; for (auto&& message : script->consume_messages()) messages.push_back(message); if (messages.size() > 0) g_Console->push_history(fmt::format("--- [{}] at {:%Y-%m-%d %X}", script->get_name(), time_buf), std::move(messages)); } - messages.clear(); { + std::vector messages; for (auto&& message : g_Console->consume_messages()) messages.push_back(message); if (messages.size() > 0) diff --git a/src/injected/ui_util.cpp b/src/injected/ui_util.cpp index 33e427fe2..8be35fc2a 100644 --- a/src/injected/ui_util.cpp +++ b/src/injected/ui_util.cpp @@ -109,7 +109,7 @@ float UI::screen_distance(float x) { auto a = State::screen_position(0, 0); auto b = State::screen_position(x, 0); - return b.first - a.first; + return b.x - a.x; } Entity* UI::get_entity_at(float x, float y, bool s, float radius, uint32_t mask) { From ce28897b55e6097d09f2bfdbf0c028fefc6ab302 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 27 Jun 2024 18:23:41 +0200 Subject: [PATCH 2/5] fix the weird error? --- src/game_api/render_api.hpp | 2 +- src/game_api/script/usertypes/vanilla_render_lua.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game_api/render_api.hpp b/src/game_api/render_api.hpp index 71d52cec0..9cf53850c 100644 --- a/src/game_api/render_api.hpp +++ b/src/game_api/render_api.hpp @@ -16,13 +16,13 @@ #include "containers/game_unordered_map.hpp" // for game_unordered_map #include "containers/game_vector.hpp" // for game_vector #include "math.hpp" // for Quad, AABB (ptr only) -#include "particles.hpp" // for ParticleEmitterInfo #include "texture.hpp" // for Texture struct JournalUI; struct Layer; class Entity; struct Renderer; +struct ParticleEmitterInfo; using VANILLA_TEXT_ALIGNMENT = uint32_t; using VANILLA_FONT_STYLE = uint32_t; diff --git a/src/game_api/script/usertypes/vanilla_render_lua.cpp b/src/game_api/script/usertypes/vanilla_render_lua.cpp index c5fad4003..9047087f2 100644 --- a/src/game_api/script/usertypes/vanilla_render_lua.cpp +++ b/src/game_api/script/usertypes/vanilla_render_lua.cpp @@ -9,6 +9,7 @@ #include // for get #include // for move, declval +#include "particles.hpp" // for ParticleEmitterInfo #include "render_api.hpp" // for TextureRenderingInfo, WorldShader, TextRen... #include "state.hpp" // for enum_to_layer #include "texture.hpp" // for Texture, get_texture From 416e27820bbb12e58f78f995715774959f33d2b3 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Fri, 28 Jun 2024 20:07:44 +0200 Subject: [PATCH 3/5] thing in `EntityPool` --- src/game_api/entity_db.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game_api/entity_db.hpp b/src/game_api/entity_db.hpp index ba8f3a268..2cc86e3f3 100644 --- a/src/game_api/entity_db.hpp +++ b/src/game_api/entity_db.hpp @@ -134,9 +134,9 @@ struct EntityPool std::uint32_t initial_slots; std::uint32_t slots_growth; std::uint32_t current_slots; - std::uint64_t _ulong_0; - custom_vector* _some_bucket; - custom_vector* empty_buckets; + std::uint64_t unknown; + custom_vector* pools_begin; // saved the first entity address that causes the slot size to increase (including the initial) + custom_vector* empty_buckets; // empty entity slots }; struct EntityFactory { From 931c063585836ef6c82903d65baf44628b7489d5 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 11 Jul 2024 18:57:32 +0200 Subject: [PATCH 4/5] fix size --- src/game_api/game_api.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/game_api/game_api.hpp b/src/game_api/game_api.hpp index a63a68ff1..d60a5c601 100644 --- a/src/game_api/game_api.hpp +++ b/src/game_api/game_api.hpp @@ -112,13 +112,14 @@ struct UnknownAPIStuff struct STEAM_CALLBACK // just guessing { - size_t _vtable; // 4 functions, last one is destructor - uint8_t unknown1; + size_t _vtable; // 4 functions, last one is destructor + uint8_t unknown1; // probably bool? uint8_t padding1[3]; uint32_t padding2; // probably base class padding // subclass OnGameOverlayActivated ? bool steam_overlay_open; + // padding uint32_t unknown_timer; float unknown_timer_related; uint32_t unknown11; // padding? @@ -149,6 +150,4 @@ struct GameAPI size_t unknown7; // some offset, OnHeapPointer? size_t unknown8; // function pointer? STEAM_CALLBACK SteamAPI_Callback; - - size_t unknown12; // garbage? }; From bbc2224f8a4d610a364f70085e1f0652b0b217dc Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:27:12 +0200 Subject: [PATCH 5/5] typo --- docs/game_data/spel2.lua | 6 +++--- docs/src/includes/_types.md | 6 +++--- src/game_api/render_api.hpp | 4 ++-- src/game_api/script/usertypes/vanilla_render_lua.cpp | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index 971579b85..98c78065f 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -2435,7 +2435,7 @@ function PRNG:random(min, max) end ---@field hitboxy number ---@field draw_depth integer ---@field collision2_mask integer @MASK, will only call collision2 when colliding with entities that match this mask. - ---@field collision_mask integer @MASK used for collision with floors. + ---@field collision_mask integer @MASK used for collision with floors, walls etc. ---@field friction number ---@field elasticity number ---@field weight number @@ -5489,8 +5489,8 @@ function VanillaRenderContext:draw_world_poly_filled(points, color) end ---@field timer HudElement ---@field level HudElement ---@field clover_falling_apart_timer number - ---@field player_cursed_paricles ParticleEmitterInfo[] @size: MAX_PLAYERS - ---@field player_poisoned_paricles ParticleEmitterInfo[] @size: MAX_PLAYERS + ---@field player_cursed_particles ParticleEmitterInfo[] @size: MAX_PLAYERS + ---@field player_poisoned_particles ParticleEmitterInfo[] @size: MAX_PLAYERS ---@field player_highlight TextureRenderingInfo @For player related icons, they use the same TextureRendering, just offset while drawing ---@field player_heart TextureRenderingInfo ---@field player_ankh TextureRenderingInfo diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 1360e6094..af595c64c 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -462,7 +462,7 @@ float | [hitboxx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hitbo float | [hitboxy](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hitboxy) | int | [draw_depth](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_depth) | int | [collision2_mask](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collision2_mask) | [MASK](#MASK), will only call collision2 when colliding with entities that match this mask. -int | [collision_mask](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collision_mask) | [MASK](#MASK) used for collision with floors. +int | [collision_mask](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collision_mask) | [MASK](#MASK) used for collision with floors, walls etc. float | [friction](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=friction) | float | [elasticity](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=elasticity) | float | [weight](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=weight) | @@ -719,8 +719,8 @@ array<[HudPlayer](#HudPlayer), MAX_PLAYERS> | [players](https://github.com [HudElement](#HudElement) | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | [HudElement](#HudElement) | [level](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=level) | float | [clover_falling_apart_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clover_falling_apart_timer) | -array<[ParticleEmitterInfo](#ParticleEmitterInfo), MAX_PLAYERS> | [player_cursed_paricles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_cursed_paricles) | -array<[ParticleEmitterInfo](#ParticleEmitterInfo), MAX_PLAYERS> | [player_poisoned_paricles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_poisoned_paricles) | +array<[ParticleEmitterInfo](#ParticleEmitterInfo), MAX_PLAYERS> | [player_cursed_particles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_cursed_particles) | +array<[ParticleEmitterInfo](#ParticleEmitterInfo), MAX_PLAYERS> | [player_poisoned_particles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_poisoned_particles) | [TextureRenderingInfo](#TextureRenderingInfo) | [player_highlight](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_highlight) | For player related icons, they use the same TextureRendering, just offset while drawing [TextureRenderingInfo](#TextureRenderingInfo) | [player_heart](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_heart) | [TextureRenderingInfo](#TextureRenderingInfo) | [player_ankh](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_ankh) | diff --git a/src/game_api/render_api.hpp b/src/game_api/render_api.hpp index 02b1408f2..dcca080de 100644 --- a/src/game_api/render_api.hpp +++ b/src/game_api/render_api.hpp @@ -529,8 +529,8 @@ struct HudData bool unknown48; // uint8_t unknown49[3]; //probably padding float unknown51; - std::array player_cursed_paricles; - std::array player_poisoned_paricles; + std::array player_cursed_particles; + std::array player_poisoned_particles; }; // static_assert(sizeof(HudData) <= 0xa00); diff --git a/src/game_api/script/usertypes/vanilla_render_lua.cpp b/src/game_api/script/usertypes/vanilla_render_lua.cpp index 9047087f2..5e5f4246f 100644 --- a/src/game_api/script/usertypes/vanilla_render_lua.cpp +++ b/src/game_api/script/usertypes/vanilla_render_lua.cpp @@ -947,8 +947,8 @@ void register_usertypes(sol::state& lua) huddata_type["timer"] = &HudData::timer; huddata_type["level"] = &HudData::level; huddata_type["clover_falling_apart_timer"] = &HudData::clover_falling_apart_timer; - huddata_type["player_cursed_paricles"] = &HudData::player_cursed_paricles; - huddata_type["player_poisoned_paricles"] = &HudData::player_poisoned_paricles; + huddata_type["player_cursed_particles"] = &HudData::player_cursed_particles; + huddata_type["player_poisoned_particles"] = &HudData::player_poisoned_particles; huddata_type["player_highlight"] = &HudData::player_highlight; huddata_type["player_heart"] = &HudData::player_heart;