diff --git a/res/content/base/modules/util.lua b/res/content/base/modules/util.lua index 874e6d3d6..dbad0c2a1 100644 --- a/res/content/base/modules/util.lua +++ b/res/content/base/modules/util.lua @@ -1,5 +1,44 @@ local util = {} +local DROP_FORCE = 8 +local DROP_INIT_VEL = {0, 3, 0} + +---@param mode integer 0 - whole stack, 1 - single item, 2 - dupe whole stack +function util.drop_from_slot(invid, slot, mode) + if invid == 0 then + return + end + local pid = hud.get_player() + if mode == 2 and !player.is_infinite_items(pid) then + return + end + local itemid, itemcount = inventory.get(invid, slot) + if itemid == 0 then + return + end + + local drop_itemcount = 1 + if mode == 0 then + drop_itemcount = itemcount + end + if mode == 2 then + drop_itemcount = item.stack_size(itemid) + else + inventory.set(invid, slot, itemid, itemcount - drop_itemcount) + end + + local data = inventory.get_all_data(invid, slot) + local pvel = { player.get_vel(pid) } + local ppos = vec3.add({ player.get_pos(pid) }, { 0, 0.7, 0 }) + local throw_force = vec3.mul(player.get_dir(pid), DROP_FORCE) + local drop = util.drop(ppos, itemid, drop_itemcount, data, 1.5) + if not drop then + return + end + local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL)) + drop.rigidbody:set_vel(velocity) +end + function util.drop(ppos, itemid, count, data, pickup_delay) if itemid == 0 or not itemid then return nil diff --git a/res/content/base/scripts/hud.lua b/res/content/base/scripts/hud.lua index 3620566e5..d0e3d1532 100644 --- a/res/content/base/scripts/hud.lua +++ b/res/content/base/scripts/hud.lua @@ -1,46 +1,10 @@ local base_util = require "util" -local DROP_FORCE = 8 -local DROP_INIT_VEL = {0, 3, 0} - ----@param mode integer 0 - whole stack, 1 - single item, 2 - dupe whole stack -function drop_from_slot(invid, slot, mode) - local pid = hud.get_player() - if mode == 2 and !player.is_infinite_items(pid) then - return - end - local itemid, itemcount = inventory.get(invid, slot) - if itemid == 0 then - return - end - - local drop_itemcount = 1 - if mode == 0 then - drop_itemcount = itemcount - end - if mode == 2 then - drop_itemcount = item.stack_size(itemid) - else - inventory.set(invid, slot, itemid, itemcount - drop_itemcount) - end - - local data = inventory.get_all_data(invid, slot) - local pvel = { player.get_vel(pid) } - local ppos = vec3.add({ player.get_pos(pid) }, { 0, 0.7, 0 }) - local throw_force = vec3.mul(player.get_dir(pid), DROP_FORCE) - local drop = base_util.drop(ppos, itemid, drop_itemcount, data, 1.5) - if not drop then - return - end - local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL)) - drop.rigidbody:set_vel(velocity) -end - -function on_inventory_clicked_outside(exc_invid, exc_slot, mode) - drop_from_slot(exc_invid, exc_slot, mode) -end - function on_hud_open() + events.on("core:drop_outside_inventory", function(mode) + local invid = hud.get_exchange_inventory() + base_util.drop_from_slot(invid, 0, mode) + end) input.add_callback("player.drop", function() if hud.is_paused() or hud.is_inventory_open() then return @@ -51,7 +15,7 @@ function on_hud_open() if input.is_pressed("key:left-ctrl") or input.is_pressed("key:right-ctrl") then mode = 0 end - drop_from_slot(invid, slot, mode) + base_util.drop_from_slot(invid, slot, mode) end) rules.create("do-loot-non-player", true) end diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 1aa03436b..d89571089 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -1,3 +1,5 @@ +#include + #include "hud.hpp" #include "ContentGfxCache.hpp" @@ -174,6 +176,14 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player) gui, "" ); + + inventoryDropArea = guiutil::create( + gui, + R"()" + ); uicamera = std::make_unique(glm::vec3(), 1); uicamera->perspective = false; @@ -188,6 +198,7 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player) gui.add(debugPanel); gui.add(darkOverlay); + gui.add(inventoryDropArea); gui.add(hotbarView); gui.add(contentAccessPanel); @@ -213,6 +224,7 @@ Hud::~Hud() { } gui.remove(hotbarView); gui.remove(darkOverlay); + gui.remove(inventoryDropArea); gui.remove(contentAccessPanel); gui.remove(debugPanel); } @@ -358,6 +370,7 @@ void Hud::update(bool visible) { contentAccess->setMinSize(glm::vec2(1, windowSize.y)); hotbarView->setVisible(visible && !(secondUI && !inventoryView)); darkOverlay->setVisible(isMenuOpen); + inventoryDropArea->setVisible(inventoryOpen); menu.setVisible(isMenuOpen); if (visible) { @@ -739,6 +752,10 @@ std::shared_ptr Hud::getSecondInventory() { return nullptr; } +std::shared_ptr Hud::getExchangeInventory() { + return exchangeSlotInv; +} + bool Hud::isContentAccess() const { return showContentPanel; } diff --git a/src/frontend/hud.hpp b/src/frontend/hud.hpp index f80c36369..f40a53581 100644 --- a/src/frontend/hud.hpp +++ b/src/frontend/hud.hpp @@ -93,6 +93,8 @@ class Hud : public util::ObjectsKeeper { std::shared_ptr debugPanel; /// @brief Overlay used in pause mode std::shared_ptr darkOverlay; + /// @brief Overlay used in inventory + std::shared_ptr inventoryDropArea; /// @brief Inventories interaction agent (grabbed item) std::shared_ptr exchangeSlot; /// @brief Exchange slot inventory (1 slot only) @@ -207,6 +209,8 @@ public: std::shared_ptr getSecondInventory(); + std::shared_ptr getExchangeInventory(); + bool isContentAccess() const; void setContentAccess(bool flag); diff --git a/src/logic/scripting/lua/libs/libhud.cpp b/src/logic/scripting/lua/libs/libhud.cpp index 7f5c893c5..a457ca6ee 100644 --- a/src/logic/scripting/lua/libs/libhud.cpp +++ b/src/logic/scripting/lua/libs/libhud.cpp @@ -149,6 +149,15 @@ static int l_get_second_inventory(lua::State* L) { } } +static int l_get_exchange_inventory(lua::State* L) { + auto inventory = hud->getExchangeInventory(); + if (inventory == nullptr) { + return lua::pushinteger(L, 0); + } else { + return lua::pushinteger(L, inventory->getId()); + } +} + static int l_get_player(lua::State* L) { auto player = hud->getPlayer(); return lua::pushinteger(L, player->getId()); @@ -216,6 +225,7 @@ const luaL_Reg hudlib[] = { {"show_overlay", wrap_hud}, {"get_block_inventory", wrap_hud}, {"get_second_inventory", wrap_hud}, + {"get_exchange_inventory", wrap_hud}, {"close", wrap_hud}, {"pause", wrap_hud}, {"resume", wrap_hud},