diff --git a/builtin/game/chat.lua b/builtin/game/chat.lua index 80c9a6e81..277b20fcd 100644 --- a/builtin/game/chat.lua +++ b/builtin/game/chat.lua @@ -1346,7 +1346,7 @@ local function handle_kill_command(killer, victim) core.log("action", string.format("%s killed %s", killer, victim)) end -- Kill victim - victimref:set_hp(0) + victimref:set_hp(0, {type="set_hp", detail="__builtin:kill_command"}) return true, S("@1 has been killed.", victim) end diff --git a/builtin/game/item.lua b/builtin/game/item.lua index 4d68f1136..7bc6c6fb3 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -435,7 +435,7 @@ function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed core.add_item(pos, replace_with_item) end - user:set_hp(user:get_hp() + hp_change) + user:set_hp(user:get_hp() + hp_change, {type="set_hp", detail="__builtin:item_eat"}) return nil -- don't overwrite wield item a second time end diff --git a/doc/lua_api.md b/doc/lua_api.md index b34e571c2..2f38bb25c 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -6172,25 +6172,13 @@ Call these functions only at load time! calculating the HP change. This clamping has been removed as of version 5.10.0 * `reason`: a PlayerHPChangeReason table. - * The `type` field will have one of the following values: - * `set_hp`: A mod or the engine called `set_hp` without - giving a type - use this for custom damage types. - * `punch`: Was punched. `reason.object` will hold the puncher, or nil if none. - * `fall` - * `node_damage`: `damage_per_second` from a neighboring node. - `reason.node` will hold the node name or nil. - `reason.node_pos` will hold the position of the node - * `drown` - * `respawn` - * Any of the above types may have additional fields from mods. - * `reason.from` will be `mod` or `engine`. * `modifier`: when true, the function should return the actual `hp_change`. Note: modifiers only get a temporary `hp_change` that can be modified by later modifiers. Modifiers can return true as a second argument to stop the execution of further functions. Non-modifiers receive the final HP change calculated by the modifiers. * `core.register_on_dieplayer(function(ObjectRef, reason))` * Called when a player dies - * `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange + * `reason`: a `PlayerHPChangeReason` table * For customizing the death screen, see `core.show_death_screen`. * `core.register_on_respawnplayer(function(ObjectRef))` * Called when player is to be respawned @@ -8410,7 +8398,7 @@ child will follow movement and rotation of that bone. * note: this is called `right_click` for historical reasons only * `get_hp()`: returns number of health points * `set_hp(hp, reason)`: set number of health points - * See reason in register_on_player_hpchange + * reason: A PlayerHPChangeReason table (optional) * Is limited to the range of 0 ... 65535 (2^16 - 1) * For players: HP are also limited by `hp_max` specified in object properties * `get_inventory()`: returns an `InvRef` for players, otherwise returns `nil` @@ -11196,6 +11184,36 @@ See [Decoration types]. Used by `core.register_decoration`. } ``` +PlayerHPChangeReason table definition +------------------------------------- + +The `PlayerHPChangeReason` table specifies a reason for player health changes. + +* The `type` field will have one of the following values: + * `set_hp`: A mod or the engine called `set_hp`, either without + giving a reason, or by setting `set_hp` as damage type + explicitly + * `punch`: Was punched. `reason.object` will hold the puncher, or nil if none. + * `fall`: Fall damage. + * `node_damage`: `damage_per_second` from a neighboring node. + `reason.node` will hold the node name or nil. + `reason.node_pos` will hold the position of the node + * `drown`: Drowning damage from a node with the `drowning` field set. + `reason.node` and `reason.node_pos` are same as for `node_damage` + * `respawn`: HP restored by respawning. +* The `detail` field may optionally be used to provide a more detailed reason + as a string. It's recommended to follow the `modname:detail` naming convention. + These detail names exist by default: + * `__builtin:item_eat`: HP change caused by `core.do_item_eat` + * `__builtin:kill_command`: `/kill` command +* The `from` field denotes the origin of the HP change: + * `engine`: Engine + * `mod`: Mod or builtin +* Mods may add additional fields + +Note: The `from` field doesn't need to be provided in the `set_hp` method, +the engine will automatically set it to `mod`. + Chat command definition ----------------------- diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 068b2b29f..0be301a79 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -154,7 +154,8 @@ void PlayerSAO::step(float dtime, bool send_recommended) // No more breath, damage player if (m_breath == 0) { - PlayerHPChangeReason reason(PlayerHPChangeReason::DROWNING); + std::string nodename = c.name; + PlayerHPChangeReason reason(PlayerHPChangeReason::DROWNING, nodename, p); setHP(m_hp - c.drowning, reason); } } diff --git a/src/server/player_sao.h b/src/server/player_sao.h index a19177a7e..052f2941c 100644 --- a/src/server/player_sao.h +++ b/src/server/player_sao.h @@ -245,7 +245,7 @@ struct PlayerHPChangeReason // For PLAYER_PUNCH ServerActiveObject *object = nullptr; - // For NODE_DAMAGE + // For NODE_DAMAGE and DROWNING std::string node; v3s16 node_pos;