Add node field to PlayerHPChangeReason table (#8368)
authorPaul Ouellette <oue.paul18@gmail.com>
Thu, 11 Apr 2019 19:45:39 +0000 (15:45 -0400)
committerrubenwardy <rw@rubenwardy.com>
Thu, 11 Apr 2019 19:45:39 +0000 (20:45 +0100)
doc/lua_api.txt
src/content_sao.cpp
src/content_sao.h
src/script/cpp_api/s_base.cpp
src/script/lua_api/l_object.cpp

index 538e2dee75ecf097b60175b223f9c755bd9f7ea8..41e8e0c968473199040d9807990b7186055c1f73 100644 (file)
@@ -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
index cb0a969ebb61d9640217e598198f51e35e48d456..2f849d3fc878f5fe5fc78703c1da2246a8900937 100644 (file)
@@ -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);
                }
index f54bc16c2d4a1bc4aba41870710ef4b54ce27591..1321edb91633e84de419e064736333aad6aa6ac4 100644 (file)
@@ -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)
+       {}
 };
index a8ed902dd1a28d836f74f28676c1ab745131c698..e73f613ce6a1013071ac037eace60366db2c74cb 100644 (file)
@@ -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()
index 597cb84a8f91c16822e98031c61813f2726258fd..2efcd894a5f2b6af7cf767d310d22d79fd956a05 100644 (file)
@@ -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