From 89bdf1a33b08e6843ea4500e9f916579f88c1c24 Mon Sep 17 00:00:00 2001 From: Malacath Date: Sun, 19 Sep 2021 15:29:54 +0200 Subject: [PATCH 1/2] Add some small utility --- docs/game_data/spel2.lua | 1 + docs/script-api.md | 8 +++++++- src/game_api/math.hpp | 10 ++++++++++ src/game_api/rpc.cpp | 15 +++++++++++++++ src/game_api/rpc.hpp | 3 +++ src/game_api/script/lua_vm.cpp | 5 +++++ src/game_api/script/usertypes/hitbox_lua.cpp | 6 ++++-- 7 files changed, 45 insertions(+), 3 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index 93f6b4c59..262daaa05 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -4828,6 +4828,7 @@ entity_has_item_type = function(...) end entity_has_item_uid = function(...) end entity_remove_item = function(...) end f = {} +filter_entities = function(...) end flip_entity = function(...) end force_co_subtheme = function(...) end force_dark_level = function(...) end diff --git a/docs/script-api.md b/docs/script-api.md index 21bfe6a6b..3260d6d77 100644 --- a/docs/script-api.md +++ b/docs/script-api.md @@ -312,6 +312,9 @@ Get the [EntityDB](#entitydb) behind an ENT_TYPE... ### [`get_grid_entity_at`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_grid_entity_at) `int get_grid_entity_at(float x, float y, LAYER layer)`
Gets a grid entity, such as floor or spikes, at the given position and layer. +### [`filter_entities`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=filter_entities) +`array filter_entities(array entities, function predicate)`
+Returns a list of all uids in `entities` for which `predicate(get_entity(uid))` returns true ### [`get_entities_by`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_entities_by) `array get_entities_by(array entity_types, int mask, LAYER layer)`
Get uids of entities by some conditions. Set `entity_type` or `mask` to `0` to ignore that, can also use table of entity_types @@ -3079,11 +3082,14 @@ Copy an axis aligned bounding box - [`AABB(float left_, float top_, float right_, float bottom_)`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=AABB) \ Create a new axis aligned bounding box by specifying its values -- [`bool overlaps_with(const AABB& other)`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=overlaps_with) &AABB::overlaps_with - [`float left`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=left) &AABB::left - [`float bottom`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bottom) &AABB::bottom - [`float right`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=right) &AABB::right - [`float top`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=top) &AABB::top +- [`bool overlaps_with(const AABB& other)`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=overlaps_with) &AABB::overlaps_with +- [`AABB& abs()`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=abs) &AABB::abs +\ +Fixes the AABB if any of the sides have negative length - [`AABB& extrude(float amount)`](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=extrude) &AABB::extrude \ Grows or shrinks the AABB by the given amount in all directions. diff --git a/src/game_api/math.hpp b/src/game_api/math.hpp index 02130efcd..71c87fcfe 100644 --- a/src/game_api/math.hpp +++ b/src/game_api/math.hpp @@ -24,6 +24,16 @@ struct AABB return !(left == 0.0f && right == 0.0f && top == 0.0f && bottom == 0.0f); } + /// Fixes the AABB if any of the sides have negative length + AABB& abs() + { + if (left > right) + std::swap(left, right); + if (bottom > top) + std::swap(bottom, top); + return *this; + } + /// Grows or shrinks the AABB by the given amount in all directions. /// If `amount < 0` and `abs(amount) > right/top - left/bottom` the respective dimension of the AABB will become `0`. AABB& extrude(float amount) diff --git a/src/game_api/rpc.cpp b/src/game_api/rpc.cpp index a9025a6f7..ecb1f8208 100644 --- a/src/game_api/rpc.cpp +++ b/src/game_api/rpc.cpp @@ -463,6 +463,21 @@ float screen_distance(float x) return b.first - a.first; } +std::vector filter_entities(std::vector entities, std::function predicate) +{ + std::vector filtered_entities{std::move(entities)}; + auto filter_fun = [&](uint32_t uid) + { + if (Entity* entity = get_entity_ptr(uid)) + { + return !predicate(entity); + } + return false; + }; + std::erase_if(filtered_entities, filter_fun); + return filtered_entities; +} + std::vector get_entities() { return get_entities_by({}, 0, LAYER::BOTH); diff --git a/src/game_api/rpc.hpp b/src/game_api/rpc.hpp index 395241288..c3df17b26 100644 --- a/src/game_api/rpc.hpp +++ b/src/game_api/rpc.hpp @@ -3,7 +3,9 @@ #include "entities_chars.hpp" #include "screen.hpp" #include "state.hpp" + #include +#include #include void teleport(float x, float y, bool s, float vx, float vy, bool snap); @@ -37,6 +39,7 @@ std::pair screen_position(float x, float y); std::tuple screen_aabb(float x1, float y1, float x2, float y2); float screen_distance(float x); float get_zoom_level(); +std::vector filter_entities(std::vector entities, std::function predicate); std::vector get_entities(); std::vector get_entities_by(std::vector entity_types, uint32_t mask, LAYER layer); std::vector get_entities_by(ENT_TYPE entity_type, uint32_t mask, LAYER layer); diff --git a/src/game_api/script/lua_vm.cpp b/src/game_api/script/lua_vm.cpp index 64896b2f9..991c37c0b 100644 --- a/src/game_api/script/lua_vm.cpp +++ b/src/game_api/script/lua_vm.cpp @@ -543,6 +543,11 @@ end /// Deprecated /// Use `get_entities_by(0, MASK.ANY, LAYER.BOTH)` instead lua["get_entities"] = get_entities; + /// Returns a list of all uids in `entities` for which `predicate(get_entity(uid))` returns true + lua["filter_entities"] = [&lua](std::vector entities, sol::function predicate) -> std::vector { + return filter_entities(std::move(entities), [&lua, pred = std::move(predicate)](Entity* entity) + { return pred(lua["cast_entity"](entity)); }); + }; auto get_entities_by = sol::overload( static_cast (*)(ENT_TYPE, uint32_t, LAYER)>(::get_entities_by), diff --git a/src/game_api/script/usertypes/hitbox_lua.cpp b/src/game_api/script/usertypes/hitbox_lua.cpp index 8afaceff0..adc2d8287 100644 --- a/src/game_api/script/usertypes/hitbox_lua.cpp +++ b/src/game_api/script/usertypes/hitbox_lua.cpp @@ -54,8 +54,6 @@ void register_usertypes(sol::state& lua) lua.new_usertype( "AABB", sol::constructors{}, - "overlaps_with", - &AABB::overlaps_with, "left", &AABB::left, "bottom", @@ -64,6 +62,10 @@ void register_usertypes(sol::state& lua) &AABB::right, "top", &AABB::top, + "overlaps_with", + &AABB::overlaps_with, + "abs", + &AABB::abs, "extrude", &AABB::extrude, "offset", From c92c08c031a71524fdd33f787776187126372b1b Mon Sep 17 00:00:00 2001 From: Malacath Date: Sun, 19 Sep 2021 15:57:39 +0200 Subject: [PATCH 2/2] Fix an issue with filter_entities --- src/game_api/script/lua_vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game_api/script/lua_vm.cpp b/src/game_api/script/lua_vm.cpp index 991c37c0b..cfe7d4702 100644 --- a/src/game_api/script/lua_vm.cpp +++ b/src/game_api/script/lua_vm.cpp @@ -545,7 +545,7 @@ end lua["get_entities"] = get_entities; /// Returns a list of all uids in `entities` for which `predicate(get_entity(uid))` returns true lua["filter_entities"] = [&lua](std::vector entities, sol::function predicate) -> std::vector { - return filter_entities(std::move(entities), [&lua, pred = std::move(predicate)](Entity* entity) + return filter_entities(std::move(entities), [&lua, pred = std::move(predicate)](Entity* entity) -> bool { return pred(lua["cast_entity"](entity)); }); };