From 22ad820aa459e055fde817d94f31a9461aac2726 Mon Sep 17 00:00:00 2001 From: Paul Ouellette Date: Thu, 11 Apr 2019 15:45:39 -0400 Subject: [PATCH] Add node field to PlayerHPChangeReason table (#8368) --- doc/lua_api.txt | 9 +++++---- src/content_sao.cpp | 17 ++++++++++++----- src/content_sao.h | 16 ++++++++++++++-- src/script/cpp_api/s_base.cpp | 4 ++++ src/script/lua_api/l_object.cpp | 7 ++++--- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 538e2dee7..41e8e0c96 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3738,15 +3738,16 @@ Call these functions only at load time! 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 neighbouring node. + * `node_damage`: `damage_per_second` from a neighbouring node. + `reason.node` will hold the node name or nil. * `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. + 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. * `minetest.register_on_dieplayer(function(ObjectRef, reason))` * Called when a player dies * `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange diff --git a/src/content_sao.cpp b/src/content_sao.cpp index cb0a969eb..2f849d3fc 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -1022,6 +1022,7 @@ void PlayerSAO::step(float dtime, bool send_recommended) if (m_node_hurt_interval.step(dtime, 1.0f)) { u32 damage_per_second = 0; + std::string nodename; // Lowest and highest damage points are 0.1 within collisionbox float dam_top = m_prop.collisionbox.MaxEdge.Y - 0.1f; @@ -1031,20 +1032,26 @@ void PlayerSAO::step(float dtime, bool send_recommended) v3s16 p = floatToInt(m_base_position + v3f(0.0f, dam_height * BS, 0.0f), BS); MapNode n = m_env->getMap().getNodeNoEx(p); - damage_per_second = std::max(damage_per_second, - m_env->getGameDef()->ndef()->get(n).damage_per_second); + const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n); + if (c.damage_per_second > damage_per_second) { + damage_per_second = c.damage_per_second; + nodename = c.name; + } } // Top damage point v3s16 ptop = floatToInt(m_base_position + v3f(0.0f, dam_top * BS, 0.0f), BS); MapNode ntop = m_env->getMap().getNodeNoEx(ptop); - damage_per_second = std::max(damage_per_second, - m_env->getGameDef()->ndef()->get(ntop).damage_per_second); + const ContentFeatures &c = m_env->getGameDef()->ndef()->get(ntop); + if (c.damage_per_second > damage_per_second) { + damage_per_second = c.damage_per_second; + nodename = c.name; + } if (damage_per_second != 0 && m_hp > 0) { s32 newhp = (s32)m_hp - (s32)damage_per_second; - PlayerHPChangeReason reason(PlayerHPChangeReason::NODE_DAMAGE); + PlayerHPChangeReason reason(PlayerHPChangeReason::NODE_DAMAGE, nodename); setHP(newhp, reason); m_env->getGameDef()->SendPlayerHPOrDie(this, reason); } diff --git a/src/content_sao.h b/src/content_sao.h index f54bc16c2..1321edb91 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -401,10 +401,14 @@ struct PlayerHPChangeReason { }; Type type = SET_HP; - ServerActiveObject *object; bool from_mod = false; int lua_reference = -1; + // For PLAYER_PUNCH + ServerActiveObject *object = nullptr; + // For NODE_DAMAGE + std::string node; + inline bool hasLuaReference() const { return lua_reference >= 0; @@ -450,7 +454,15 @@ struct PlayerHPChangeReason { } } - PlayerHPChangeReason(Type type, ServerActiveObject *object=NULL): + PlayerHPChangeReason(Type type): + type(type) + {} + + PlayerHPChangeReason(Type type, ServerActiveObject *object): type(type), object(object) {} + + PlayerHPChangeReason(Type type, std::string node): + type(type), node(node) + {} }; diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index a8ed902dd..e73f613ce 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -404,6 +404,10 @@ void ScriptApiBase::pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeR objectrefGetOrCreate(L, reason.object); lua_setfield(L, -2, "object"); } + if (!reason.node.empty()) { + lua_pushstring(L, reason.node.c_str()); + lua_setfield(L, -2, "node"); + } } Server* ScriptApiBase::getServer() diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 597cb84a8..2efcd894a 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -170,8 +170,8 @@ int ObjectRef::l_punch(lua_State *L) ObjectRef *puncher_ref = checkobject(L, 2); ServerActiveObject *co = getobject(ref); ServerActiveObject *puncher = getobject(puncher_ref); - if (co == NULL) return 0; - if (puncher == NULL) return 0; + if (!co || !puncher) + return 0; v3f dir; if (lua_type(L, 5) != LUA_TTABLE) dir = co->getBasePosition() - puncher->getBasePosition(); @@ -192,7 +192,8 @@ int ObjectRef::l_punch(lua_State *L) // If the punched is a player, and its HP changed if (src_original_hp != co->getHP() && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) { - getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher)); + getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, + PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher)); } // If the puncher is a player, and its HP changed