diff --git a/builtin/game/chat.lua b/builtin/game/chat.lua index ac64650da..b6a6aab02 100644 --- a/builtin/game/chat.lua +++ b/builtin/game/chat.lua @@ -1348,7 +1348,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", custom_type="__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 fa3590ac6..d1b98cb34 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", custom_type="__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 d5b33711c..03bd1d692 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -6226,26 +6226,14 @@ Call these functions only at load time! * Historically, the new HP value was clamped to [0, 65535] before 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`. + * `reason`: a `PlayerHPChangeReason` table. * `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 @@ -6986,7 +6974,7 @@ Formspec functions * `"VAL"`: not changed * `core.show_death_screen(player, reason)` * Called when the death screen should be shown. - * `player` is an ObjectRef, `reason` is a PlayerHPChangeReason table or nil. + * `player` is an ObjectRef, `reason` is a `PlayerHPChangeReason` table or nil. * By default, this shows a simple formspec with the option to respawn. Respawning is done via `ObjectRef:respawn`. * You can override this to show a custom death screen. @@ -8495,7 +8483,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` @@ -11314,6 +11302,40 @@ See [Decoration types](#decoration-types). Used by `core.register_decoration`. } ``` +`PlayerHPChangeReason` table definition +--------------------------------------- + +The `PlayerHPChangeReason` table specifies a reason for player health changes. + +* The `type` field is for providing one of the possible damage types + supported natively by the engine. It will have one of the following values: + * `set_hp`: A mod, builtin or the engine called `set_hp`, either + without giving a damage type, 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 `custom_type` field may optionally be used to provide a reason that is not + supported by the engine, as a string. It will be ignored by the engine, + but it can be used to communicate to other mods about custom damage types. + If provided, it must be a string. It's recommended to follow the + `modname:reason` naming convention. + These custom types 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` is ignored by `ObjectRef:set_hp`, the engine will always +set it to `mod`. + Chat command definition ----------------------- diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 35d9ebf57..96b4bc6ea 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -159,7 +159,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 acfe7d02d..02bd1aa82 100644 --- a/src/server/player_sao.h +++ b/src/server/player_sao.h @@ -250,7 +250,7 @@ struct PlayerHPChangeReason // For PLAYER_PUNCH ServerActiveObject *object = nullptr; - // For NODE_DAMAGE + // For NODE_DAMAGE and DROWNING std::string node; v3s16 node_pos;