]> git.lizzy.rs Git - minetest.git/commitdiff
Fix number of tool uses being off by 1..32767 (#11110)
authorWuzzy <wuzzy2@mail.ru>
Sun, 31 Oct 2021 22:33:33 +0000 (22:33 +0000)
committerGitHub <noreply@github.com>
Sun, 31 Oct 2021 22:33:33 +0000 (22:33 +0000)
18 files changed:
builtin/game/item.lua
doc/lua_api.txt
games/devtest/mods/basetools/init.lua
games/devtest/mods/basetools/textures/basetools_dirtpick.png [deleted file]
games/devtest/mods/util_commands/init.lua
src/client/content_cao.cpp
src/client/game.cpp
src/network/serverpackethandler.cpp
src/script/lua_api/l_object.cpp
src/script/lua_api/l_util.cpp
src/script/lua_api/l_util.h
src/server/luaentity_sao.cpp
src/server/luaentity_sao.h
src/server/player_sao.cpp
src/server/player_sao.h
src/server/serveractiveobject.h
src/tool.cpp
src/tool.h

index 03994758425b7ce912398e0c3d15d17c516d190a..c9ccb8801458206014f2931369698cef34346455 100644 (file)
@@ -613,7 +613,7 @@ function core.node_dig(pos, node, digger)
        if wielded then
                local wdef = wielded:get_definition()
                local tp = wielded:get_tool_capabilities()
-               local dp = core.get_dig_params(def and def.groups, tp)
+               local dp = core.get_dig_params(def and def.groups, tp, wielded:get_wear())
                if wdef and wdef.after_use then
                        wielded = wdef.after_use(wielded, digger, node, dp) or wielded
                else
index e47df468698728aa99f827cfeca43b2eed6c8834..f3007671bafc3e4a6206427d1cbe277044b0afa9 100644 (file)
@@ -1953,8 +1953,9 @@ to implement this.
 ### Uses (tools only)
 
 Determines how many uses the tool has when it is used for digging a node,
-of this group, of the maximum level. For lower leveled nodes, the use count
-is multiplied by `3^leveldiff`.
+of this group, of the maximum level. The maximum supported number of
+uses is 65535. The special number 0 is used for infinite uses.
+For lower leveled nodes, the use count is multiplied by `3^leveldiff`.
 `leveldiff` is the difference of the tool's `maxlevel` `groupcaps` and the
 node's `level` group. The node cannot be dug if `leveldiff` is less than zero.
 
@@ -3475,8 +3476,8 @@ Helper functions
 * `minetest.pointed_thing_to_face_pos(placer, pointed_thing)`: returns a
   position.
     * returns the exact position on the surface of a pointed node
-* `minetest.get_dig_params(groups, tool_capabilities)`: Simulates an item
-    that digs a node.
+* `minetest.get_dig_params(groups, tool_capabilities [, wear])`:
+    Simulates an item that digs a node.
     Returns a table with the following fields:
     * `diggable`: `true` if node can be dug, `false` otherwise.
     * `time`: Time it would take to dig the node.
@@ -3485,7 +3486,8 @@ Helper functions
     Parameters:
     * `groups`: Table of the node groups of the node that would be dug
     * `tool_capabilities`: Tool capabilities table of the item
-* `minetest.get_hit_params(groups, tool_capabilities [, time_from_last_punch])`:
+    * `wear`: Amount of wear the tool starts with (default: 0)
+* `minetest.get_hit_params(groups, tool_capabilities [, time_from_last_punch [, wear]])`:
     Simulates an item that punches an object.
     Returns a table with the following fields:
     * `hp`: How much damage the punch would cause.
@@ -3494,6 +3496,7 @@ Helper functions
     * `groups`: Damage groups of the object
     * `tool_capabilities`: Tool capabilities table of the item
     * `time_from_last_punch`: time in seconds since last punch action
+    * `wear`: Amount of wear the item starts with (default: 0)
 
 
 
index bd7480030fe837146d0e33017100f2bdd7f9c4c7..fd83b82eb61508b7b10c935c1c3084c1eb2365ec 100644 (file)
@@ -16,11 +16,11 @@ Tool types:
 
 Tool materials:
 
-* Dirt: dig nodes of rating 3, one use only
 * Wood: dig nodes of rating 3
 * Stone: dig nodes of rating 3 or 2
 * Steel: dig nodes of rating 3, 2 or 1
 * Mese: dig "everything" instantly
+* n-Uses: can be used n times before breaking
 ]]
 
 -- The hand
@@ -92,20 +92,6 @@ minetest.register_tool("basetools:pick_mese", {
 -- Pickaxes: Dig cracky
 --
 
--- This should break after only 1 use
-minetest.register_tool("basetools:pick_dirt", {
-       description = "Dirt Pickaxe".."\n"..
-               "Digs cracky=3".."\n"..
-               "1 use only",
-       inventory_image = "basetools_dirtpick.png",
-       tool_capabilities = {
-               max_drop_level=0,
-               groupcaps={
-                       cracky={times={[3]=2.00}, uses=1, maxlevel=0}
-               },
-       },
-})
-
 minetest.register_tool("basetools:pick_wood", {
        description = "Wooden Pickaxe".."\n"..
                "Digs cracky=3",
@@ -348,3 +334,31 @@ minetest.register_tool("basetools:dagger_steel", {
                damage_groups = {fleshy=2},
        }
 })
+
+-- Test tool uses and punch_attack_uses
+local uses = { 1, 2, 3, 5, 10, 50, 100, 1000, 10000, 65535 }
+for i=1, #uses do
+       local u = uses[i]
+       local color = string.format("#FF00%02X", math.floor(((i-1)/#uses) * 255))
+       minetest.register_tool("basetools:pick_uses_"..string.format("%05d", u), {
+               description = u.."-Uses Pickaxe".."\n"..
+                       "Digs cracky=3",
+               inventory_image = "basetools_steelpick.png^[colorize:"..color..":127",
+               tool_capabilities = {
+                       max_drop_level=0,
+                       groupcaps={
+                               cracky={times={[3]=0.1, [2]=0.2, [1]=0.3}, uses=u, maxlevel=0}
+                       },
+               },
+       })
+
+       minetest.register_tool("basetools:sword_uses_"..string.format("%05d", u), {
+               description = u.."-Uses Sword".."\n"..
+                       "Damage: fleshy=1",
+               inventory_image = "basetools_woodsword.png^[colorize:"..color..":127",
+               tool_capabilities = {
+                       damage_groups = {fleshy=1},
+                       punch_attack_uses = u,
+               },
+       })
+end
diff --git a/games/devtest/mods/basetools/textures/basetools_dirtpick.png b/games/devtest/mods/basetools/textures/basetools_dirtpick.png
deleted file mode 100644 (file)
index 20a021d..0000000
Binary files a/games/devtest/mods/basetools/textures/basetools_dirtpick.png and /dev/null differ
index ca5dca2d950114ec10f862f246cb125c3fcb6e74..79acaa0d0f8ee0e1cb50d7d8e82b7c09b62308d0 100644 (file)
@@ -114,6 +114,59 @@ minetest.register_chatcommand("detach", {
        end,
 })
 
+minetest.register_chatcommand("use_tool", {
+       params = "(dig <group> <leveldiff>) | (hit <damage_group> <time_from_last_punch>) [<uses>]",
+       description = "Apply tool wear a number of times, as if it were used for digging",
+       func = function(name, param)
+               local player = minetest.get_player_by_name(name)
+               if not player then
+                       return false, "No player."
+               end
+               local mode, group, level, uses = string.match(param, "([a-z]+) ([a-z0-9]+) (-?%d+) (%d+)")
+               if not mode then
+                       mode, group, level = string.match(param, "([a-z]+) ([a-z0-9]+) (-?%d+)")
+                       uses = 1
+               end
+               if not mode or not group or not level then
+                       return false
+               end
+               if mode ~= "dig" and mode ~= "hit" then
+                       return false
+               end
+               local tool = player:get_wielded_item()
+               local caps = tool:get_tool_capabilities()
+               if not caps or tool:get_count() == 0 then
+                       return false, "No tool in hand."
+               end
+               local actual_uses = 0
+               for u=1, uses do
+                       local wear = tool:get_wear()
+                       local dp
+                       if mode == "dig" then
+                               dp = minetest.get_dig_params({[group]=3, level=level}, caps, wear)
+                       else
+                               dp = minetest.get_hit_params({[group]=100}, caps, level, wear)
+                       end
+                       tool:add_wear(dp.wear)
+                       actual_uses = actual_uses + 1
+                       if tool:get_count() == 0 then
+                               break
+                       end
+               end
+               player:set_wielded_item(tool)
+               if tool:get_count() == 0 then
+                       return true, string.format("Tool used %d time(s). "..
+                                       "The tool broke after %d use(s).", uses, actual_uses)
+               else
+                       local wear = tool:get_wear()
+                       return true, string.format("Tool used %d time(s). "..
+                                       "Final wear=%d", uses, wear)
+               end
+       end,
+})
+
+
+
 -- Use this to test waypoint capabilities
 minetest.register_chatcommand("test_waypoints", {
        params = "[change_immediate]",
index 1e79d00c9f384eb224f0dafc4f4e92d8fec90983..5c8465b2230d172c98114daa26bb9aee1ffc226a 100644 (file)
@@ -1870,7 +1870,8 @@ bool GenericCAO::directReportPunch(v3f dir, const ItemStack *punchitem,
                        m_armor_groups,
                        toolcap,
                        punchitem,
-                       time_from_last_punch);
+                       time_from_last_punch,
+                       punchitem->wear);
 
        if(result.did_punch && result.damage != 0)
        {
index 57951dc95ce4cb7a4a1583bf3a33c5ce59917c01..7f0aff49cb1354d9bbb24a9d1f2a2a6b336616ce 100644 (file)
@@ -3619,7 +3619,8 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
        // cheat detection.
        // Get digging parameters
        DigParams params = getDigParams(nodedef_manager->get(n).groups,
-                       &selected_item.getToolCapabilities(itemdef_manager));
+                       &selected_item.getToolCapabilities(itemdef_manager),
+                       selected_item.wear);
 
        // If can't dig, try hand
        if (!params.diggable) {
index d4bef3ca2b3d7ed4dd9f8d42aece20577871f86c..c1ddb500521402250137fa6b32af39b581b75426 100644 (file)
@@ -1119,8 +1119,8 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
                float time_from_last_punch =
                        playersao->resetTimeFromLastPunch();
 
-               u16 wear = pointed_object->punch(dir, &toolcap, playersao,
-                               time_from_last_punch);
+               u32 wear = pointed_object->punch(dir, &toolcap, playersao,
+                               time_from_last_punch, tool_item.wear);
 
                // Callback may have changed item, so get it again
                playersao->getWieldedItem(&selected_item);
@@ -1173,7 +1173,8 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
 
                        // Get diggability and expected digging time
                        DigParams params = getDigParams(m_nodedef->get(n).groups,
-                                       &selected_item.getToolCapabilities(m_itemdef));
+                                       &selected_item.getToolCapabilities(m_itemdef),
+                                       selected_item.wear);
                        // If can't dig, try hand
                        if (!params.diggable) {
                                params = getDigParams(m_nodedef->get(n).groups,
index b7185f7ec5a98f711cfdd2ea0473e28f50258d17..072b13d806cb476d74f11d0e0847331c1ac0db9a 100644 (file)
@@ -174,7 +174,7 @@ int ObjectRef::l_punch(lua_State *L)
        v3f dir = readParam<v3f>(L, 5, sao->getBasePosition() - puncher->getBasePosition());
        dir.normalize();
 
-       u16 wear = sao->punch(dir, &toolcap, puncher, time_from_last_punch);
+       u32 wear = sao->punch(dir, &toolcap, puncher, time_from_last_punch);
        lua_pushnumber(L, wear);
 
        return 1;
index 2405cd90dc365e0d052aff1c3d3a51e3c9ea0ada..53319ccfd2a21f569446181be0ba80a63f5a0096 100644 (file)
@@ -160,28 +160,33 @@ int ModApiUtil::l_write_json(lua_State *L)
        return 1;
 }
 
-// get_dig_params(groups, tool_capabilities)
+// get_dig_params(groups, tool_capabilities[, wear])
 int ModApiUtil::l_get_dig_params(lua_State *L)
 {
        NO_MAP_LOCK_REQUIRED;
        ItemGroupList groups;
        read_groups(L, 1, groups);
        ToolCapabilities tp = read_tool_capabilities(L, 2);
-       push_dig_params(L, getDigParams(groups, &tp));
+       if (lua_isnoneornil(L, 3)) {
+               push_dig_params(L, getDigParams(groups, &tp));
+       } else {
+               u16 wear = readParam<int>(L, 3);
+               push_dig_params(L, getDigParams(groups, &tp, wear));
+       }
        return 1;
 }
 
-// get_hit_params(groups, tool_capabilities[, time_from_last_punch])
+// get_hit_params(groups, tool_capabilities[, time_from_last_punch, [, wear]])
 int ModApiUtil::l_get_hit_params(lua_State *L)
 {
        NO_MAP_LOCK_REQUIRED;
        std::unordered_map<std::string, int> groups;
        read_groups(L, 1, groups);
        ToolCapabilities tp = read_tool_capabilities(L, 2);
-       if(lua_isnoneornil(L, 3))
-               push_hit_params(L, getHitParams(groups, &tp));
-       else
-               push_hit_params(L, getHitParams(groups, &tp, readParam<float>(L, 3)));
+       float time_from_last_punch = readParam<float>(L, 3, 1000000);
+       int wear = readParam<int>(L, 4, 0);
+       push_hit_params(L, getHitParams(groups, &tp,
+               time_from_last_punch, wear));
        return 1;
 }
 
index cc91e8d399764440a4c4cd4b41d6c794b246ecb7..314e92f5c6398a8a0563a679b5f66cc0c6104291 100644 (file)
@@ -50,10 +50,10 @@ class ModApiUtil : public ModApiBase
        // write_json(data[, styled])
        static int l_write_json(lua_State *L);
 
-       // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
+       // get_dig_params(groups, tool_capabilities[, wear])
        static int l_get_dig_params(lua_State *L);
 
-       // get_hit_params(groups, tool_capabilities[, time_from_last_punch])
+       // get_hit_params(groups, tool_capabilities[, time_from_last_punch[, wear]])
        static int l_get_hit_params(lua_State *L);
 
        // check_password_entry(name, entry, password)
index 1d65ac306d355fc7e2b81ca1a7dcebec79a0bb5a..82f6da2314f8392d66b924844f53d3d6a3a385c2 100644 (file)
@@ -305,10 +305,11 @@ void LuaEntitySAO::getStaticData(std::string *result) const
        *result = os.str();
 }
 
-u16 LuaEntitySAO::punch(v3f dir,
+u32 LuaEntitySAO::punch(v3f dir,
                const ToolCapabilities *toolcap,
                ServerActiveObject *puncher,
-               float time_from_last_punch)
+               float time_from_last_punch,
+               u16 initial_wear)
 {
        if (!m_registered) {
                // Delete unknown LuaEntities when punched
@@ -326,7 +327,8 @@ u16 LuaEntitySAO::punch(v3f dir,
                        m_armor_groups,
                        toolcap,
                        &tool_item,
-                       time_from_last_punch);
+                       time_from_last_punch,
+                       initial_wear);
 
        bool damage_handled = m_env->getScriptIface()->luaentity_Punch(m_id, puncher,
                        time_from_last_punch, toolcap, dir, result.did_punch ? result.damage : 0);
index 6883ae1b9ad3c3eb35eccaf43ed55622b30fd2a6..87b664a8b282708acaaf717581f26df2d8b758e6 100644 (file)
@@ -44,9 +44,10 @@ class LuaEntitySAO : public UnitSAO
        bool isStaticAllowed() const { return m_prop.static_save; }
        bool shouldUnload() const { return true; }
        void getStaticData(std::string *result) const;
-       u16 punch(v3f dir, const ToolCapabilities *toolcap = nullptr,
+       u32 punch(v3f dir, const ToolCapabilities *toolcap = nullptr,
                        ServerActiveObject *puncher = nullptr,
-                       float time_from_last_punch = 1000000.0f);
+                       float time_from_last_punch = 1000000.0f,
+                       u16 initial_wear = 0);
        void rightClick(ServerActiveObject *clicker);
        void setPos(const v3f &pos);
        void moveTo(v3f pos, bool continuous);
index 690823bb78b4880ca0bed9ea75885dfe4731ba50..83e17f8308ebfbed967bc7102cc8fb25835e1a1a 100644 (file)
@@ -409,10 +409,11 @@ void PlayerSAO::setLookPitchAndSend(const float pitch)
        m_env->getGameDef()->SendMovePlayer(m_peer_id);
 }
 
-u16 PlayerSAO::punch(v3f dir,
+u32 PlayerSAO::punch(v3f dir,
        const ToolCapabilities *toolcap,
        ServerActiveObject *puncher,
-       float time_from_last_punch)
+       float time_from_last_punch,
+       u16 initial_wear)
 {
        if (!toolcap)
                return 0;
@@ -430,7 +431,7 @@ u16 PlayerSAO::punch(v3f dir,
 
        s32 old_hp = getHP();
        HitParams hitparams = getHitParams(m_armor_groups, toolcap,
-                       time_from_last_punch);
+                       time_from_last_punch, initial_wear);
 
        PlayerSAO *playersao = m_player->getPlayerSAO();
 
index 1429d7129ce7d9f0d635c999d3fbcd8ed0374335..47fe85413b97a647d6e21081c0906ddf15097459 100644 (file)
@@ -109,8 +109,8 @@ class PlayerSAO : public UnitSAO
                Interaction interface
        */
 
-       u16 punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher,
-                       float time_from_last_punch);
+       u32 punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher,
+                       float time_from_last_punch, u16 initial_wear = 0);
        void rightClick(ServerActiveObject *clicker);
        void setHP(s32 hp, const PlayerHPChangeReason &reason) override
        {
index 51f44591427df4d373cb6025dc172e7142fe4320..5b0ee2d9b3127bd1575419930fc697d3dd8d2851 100644 (file)
@@ -145,11 +145,12 @@ class ServerActiveObject : public ActiveObject
        virtual bool shouldUnload() const
        { return true; }
 
-       // Returns tool wear
-       virtual u16 punch(v3f dir,
+       // Returns added tool wear
+       virtual u32 punch(v3f dir,
                        const ToolCapabilities *toolcap = nullptr,
                        ServerActiveObject *puncher = nullptr,
-                       float time_from_last_punch = 1000000.0f)
+                       float time_from_last_punch = 1000000.0f,
+                       u16 initial_wear = 0)
        { return 0; }
        virtual void rightClick(ServerActiveObject *clicker)
        {}
index 3f639a69ee3b7c1c40ce85a2eeaa22950e3c05e0..b0749286d11042fa3cb474de57f821f56eb5cc47 100644 (file)
@@ -183,9 +183,74 @@ void ToolCapabilities::deserializeJson(std::istream &is)
        }
 }
 
+static u32 calculateResultWear(const u32 uses, const u16 initial_wear)
+{
+       if (uses == 0) {
+               // Trivial case: Infinite uses
+               return 0;
+       }
+       /* Finite uses. This is not trivial,
+       as the maximum wear is not neatly evenly divisible by
+       most possible uses numbers. For example, for 128
+       uses, the calculation of wear is trivial, as
+       65536 / 128 uses = 512 wear,
+       so the tool will get 512 wear 128 times in its lifetime.
+       But for a number like 130, this does not work:
+       65536 / 130 uses = 504.123... wear.
+       Since wear must be an integer, we will get
+       504*130 = 65520, which would lead to the wrong number
+       of uses.
+
+       Instead, we partition the "wear range" into blocks:
+       A block represents a single use and can be
+       of two possible sizes: normal and oversized.
+       A normal block is equal to floor(65536 / uses).
+       An oversized block is a normal block plus 1.
+       Then we determine how many oversized and normal
+       blocks we need and finally, whether we add
+       the normal wear or the oversized wear.
+
+       Example for 130 uses:
+       * Normal wear = 504
+       * Number of normal blocks = 114
+       * Oversized wear = 505
+       * Number of oversized blocks = 16
+
+       If we add everything together, we get:
+         114*504 + 16*505 = 65536
+       */
+       u32 result_wear;
+       u32 wear_normal = ((U16_MAX+1) / uses);
+       // Will be non-zero if its not evenly divisible
+       u16 blocks_oversize = (U16_MAX+1) % uses;
+       // Whether to add one extra wear point in case
+       // of oversized wear.
+       u16 wear_extra = 0;
+       if (blocks_oversize > 0) {
+               u16 blocks_normal = uses - blocks_oversize;
+               /* When the wear has reached this value, we
+                  know that wear_normal has been applied
+                  for blocks_normal times, therefore,
+                  only oversized blocks remain.
+                  This also implies the raw tool wear number
+                  increases a bit faster after this point,
+                  but this should be barely noticable by the
+                  player.
+               */
+               u16 wear_extra_at = blocks_normal * wear_normal;
+               if (initial_wear >= wear_extra_at) {
+                       wear_extra = 1;
+               }
+       }
+       result_wear = wear_normal + wear_extra;
+       return result_wear;
+}
+
 DigParams getDigParams(const ItemGroupList &groups,
-               const ToolCapabilities *tp)
+               const ToolCapabilities *tp,
+               const u16 initial_wear)
 {
+
        // Group dig_immediate defaults to fixed time and no wear
        if (tp->groupcaps.find("dig_immediate") == tp->groupcaps.cend()) {
                switch (itemgroup_get(groups, "dig_immediate")) {
@@ -201,7 +266,7 @@ DigParams getDigParams(const ItemGroupList &groups,
        // Values to be returned (with a bit of conversion)
        bool result_diggable = false;
        float result_time = 0.0;
-       float result_wear = 0.0;
+       u32 result_wear = 0;
        std::string result_main_group;
 
        int level = itemgroup_get(groups, "level");
@@ -224,20 +289,22 @@ DigParams getDigParams(const ItemGroupList &groups,
                if (!result_diggable || time < result_time) {
                        result_time = time;
                        result_diggable = true;
-                       if (cap.uses != 0)
-                               result_wear = 1.0 / cap.uses / pow(3.0, leveldiff);
-                       else
-                               result_wear = 0;
+                       // The actual number of uses increases
+                       // exponentially with leveldiff.
+                       // If the levels are equal, real_uses equals cap.uses.
+                       u32 real_uses = cap.uses * pow(3.0, leveldiff);
+                       real_uses = MYMIN(real_uses, U16_MAX);
+                       result_wear = calculateResultWear(real_uses, initial_wear);
                        result_main_group = groupname;
                }
        }
 
-       u16 wear_i = U16_MAX * result_wear;
-       return DigParams(result_diggable, result_time, wear_i, result_main_group);
+       return DigParams(result_diggable, result_time, result_wear, result_main_group);
 }
 
 HitParams getHitParams(const ItemGroupList &armor_groups,
-               const ToolCapabilities *tp, float time_from_last_punch)
+               const ToolCapabilities *tp, float time_from_last_punch,
+               u16 initial_wear)
 {
        s16 damage = 0;
        float result_wear = 0.0f;
@@ -249,10 +316,12 @@ HitParams getHitParams(const ItemGroupList &armor_groups,
                damage += damageGroup.second * punch_interval_multiplier * armor / 100.0;
        }
 
-       if (tp->punch_attack_uses > 0)
-               result_wear = 1.0f / tp->punch_attack_uses * punch_interval_multiplier;
+       if (tp->punch_attack_uses > 0) {
+               result_wear = calculateResultWear(tp->punch_attack_uses, initial_wear);
+               result_wear *= punch_interval_multiplier;
+       }
 
-       u16 wear_i = U16_MAX * result_wear;
+       u32 wear_i = (u32) result_wear;
        return {damage, wear_i};
 }
 
@@ -266,7 +335,8 @@ PunchDamageResult getPunchDamage(
                const ItemGroupList &armor_groups,
                const ToolCapabilities *toolcap,
                const ItemStack *punchitem,
-               float time_from_last_punch
+               float time_from_last_punch,
+               u16 initial_wear
 ){
        bool do_hit = true;
        {
@@ -286,7 +356,8 @@ PunchDamageResult getPunchDamage(
        if(do_hit)
        {
                HitParams hitparams = getHitParams(armor_groups, toolcap,
-                               time_from_last_punch);
+                               time_from_last_punch,
+                               punchitem->wear);
                result.did_punch = true;
                result.wear = hitparams.wear;
                result.damage = hitparams.hp;
index 59dd501f51de3a75b0694ff42cf47cf6c18df6cd..0e3388485113ec5c28fb5409bea61c463ca32784 100644 (file)
@@ -88,10 +88,10 @@ struct DigParams
        // Digging time in seconds
        float time;
        // Caused wear
-       u16 wear;
+       u32 wear; // u32 because wear could be 65536 (single-use tool)
        std::string main_group;
 
-       DigParams(bool a_diggable = false, float a_time = 0.0f, u16 a_wear = 0,
+       DigParams(bool a_diggable = false, float a_time = 0.0f, u32 a_wear = 0,
                        const std::string &a_main_group = ""):
                diggable(a_diggable),
                time(a_time),
@@ -101,21 +101,24 @@ struct DigParams
 };
 
 DigParams getDigParams(const ItemGroupList &groups,
-               const ToolCapabilities *tp);
+               const ToolCapabilities *tp,
+               const u16 initial_wear = 0);
 
 struct HitParams
 {
        s16 hp;
-       u16 wear;
+       // Caused wear
+       u32 wear; // u32 because wear could be 65536 (single-use weapon)
 
-       HitParams(s16 hp_ = 0, u16 wear_ = 0):
+       HitParams(s16 hp_ = 0, u32 wear_ = 0):
                hp(hp_),
                wear(wear_)
        {}
 };
 
 HitParams getHitParams(const ItemGroupList &armor_groups,
-               const ToolCapabilities *tp, float time_from_last_punch);
+               const ToolCapabilities *tp, float time_from_last_punch,
+               u16 initial_wear = 0);
 
 HitParams getHitParams(const ItemGroupList &armor_groups,
                const ToolCapabilities *tp);
@@ -135,7 +138,8 @@ PunchDamageResult getPunchDamage(
                const ItemGroupList &armor_groups,
                const ToolCapabilities *toolcap,
                const ItemStack *punchitem,
-               float time_from_last_punch
+               float time_from_last_punch,
+               u16 initial_wear = 0
 );
 
 f32 getToolRange(const ItemDefinition &def_selected, const ItemDefinition &def_hand);