aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWuzzy <wuzzy2@mail.ru>2021-10-31 22:33:33 +0000
committerGitHub <noreply@github.com>2021-10-31 22:33:33 +0000
commit6910c8d920acedb3f1df1ac03a5cdf14f5fb6081 (patch)
treeae01925fc35e2301a87ec53897f96b1f56c955fb
parent38ba813c55489595cd78ab2f952be2e954083cfa (diff)
downloadminetest-6910c8d920acedb3f1df1ac03a5cdf14f5fb6081.tar.gz
minetest-6910c8d920acedb3f1df1ac03a5cdf14f5fb6081.tar.bz2
minetest-6910c8d920acedb3f1df1ac03a5cdf14f5fb6081.zip
Fix number of tool uses being off by 1..32767 (#11110)
-rw-r--r--builtin/game/item.lua2
-rw-r--r--doc/lua_api.txt13
-rw-r--r--games/devtest/mods/basetools/init.lua44
-rw-r--r--games/devtest/mods/basetools/textures/basetools_dirtpick.pngbin307 -> 0 bytes
-rw-r--r--games/devtest/mods/util_commands/init.lua53
-rw-r--r--src/client/content_cao.cpp3
-rw-r--r--src/client/game.cpp3
-rw-r--r--src/network/serverpackethandler.cpp7
-rw-r--r--src/script/lua_api/l_object.cpp2
-rw-r--r--src/script/lua_api/l_util.cpp19
-rw-r--r--src/script/lua_api/l_util.h4
-rw-r--r--src/server/luaentity_sao.cpp8
-rw-r--r--src/server/luaentity_sao.h5
-rw-r--r--src/server/player_sao.cpp7
-rw-r--r--src/server/player_sao.h4
-rw-r--r--src/server/serveractiveobject.h7
-rw-r--r--src/tool.cpp99
-rw-r--r--src/tool.h18
18 files changed, 228 insertions, 70 deletions
diff --git a/builtin/game/item.lua b/builtin/game/item.lua
index 039947584..c9ccb8801 100644
--- a/builtin/game/item.lua
+++ b/builtin/game/item.lua
@@ -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
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index e47df4686..f3007671b 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -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)
diff --git a/games/devtest/mods/basetools/init.lua b/games/devtest/mods/basetools/init.lua
index bd7480030..fd83b82eb 100644
--- a/games/devtest/mods/basetools/init.lua
+++ b/games/devtest/mods/basetools/init.lua
@@ -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
index 20a021d72..000000000
--- a/games/devtest/mods/basetools/textures/basetools_dirtpick.png
+++ /dev/null
Binary files differ
diff --git a/games/devtest/mods/util_commands/init.lua b/games/devtest/mods/util_commands/init.lua
index ca5dca2d9..79acaa0d0 100644
--- a/games/devtest/mods/util_commands/init.lua
+++ b/games/devtest/mods/util_commands/init.lua
@@ -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]",
diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp
index 1e79d00c9..5c8465b22 100644
--- a/src/client/content_cao.cpp
+++ b/src/client/content_cao.cpp
@@ -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)
{
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 57951dc95..7f0aff49c 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -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) {
diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp
index d4bef3ca2..c1ddb5005 100644
--- a/src/network/serverpackethandler.cpp
+++ b/src/network/serverpackethandler.cpp
@@ -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,
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index b7185f7ec..072b13d80 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -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;
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index 2405cd90d..53319ccfd 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -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;
}
diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h
index cc91e8d39..314e92f5c 100644
--- a/src/script/lua_api/l_util.h
+++ b/src/script/lua_api/l_util.h
@@ -50,10 +50,10 @@ private:
// 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)
diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp
index 1d65ac306..82f6da231 100644
--- a/src/server/luaentity_sao.cpp
+++ b/src/server/luaentity_sao.cpp
@@ -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);
diff --git a/src/server/luaentity_sao.h b/src/server/luaentity_sao.h
index 6883ae1b9..87b664a8b 100644
--- a/src/server/luaentity_sao.h
+++ b/src/server/luaentity_sao.h
@@ -44,9 +44,10 @@ public:
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);
diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp
index 690823bb7..83e17f830 100644
--- a/src/server/player_sao.cpp
+++ b/src/server/player_sao.cpp
@@ -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();
diff --git a/src/server/player_sao.h b/src/server/player_sao.h
index 1429d7129..47fe85413 100644
--- a/src/server/player_sao.h
+++ b/src/server/player_sao.h
@@ -109,8 +109,8 @@ public:
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
{
diff --git a/src/server/serveractiveobject.h b/src/server/serveractiveobject.h
index 51f445914..5b0ee2d9b 100644
--- a/src/server/serveractiveobject.h
+++ b/src/server/serveractiveobject.h
@@ -145,11 +145,12 @@ public:
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)
{}
diff --git a/src/tool.cpp b/src/tool.cpp
index 3f639a69e..b0749286d 100644
--- a/src/tool.cpp
+++ b/src/tool.cpp
@@ -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;
diff --git a/src/tool.h b/src/tool.h
index 59dd501f5..0e3388485 100644
--- a/src/tool.h
+++ b/src/tool.h
@@ -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);