Group "immortal" also protects players from damage
authorWuzzy <Wuzzy2@mail.ru>
Wed, 20 Feb 2019 23:36:17 +0000 (00:36 +0100)
committersfan5 <sfan5@live.de>
Thu, 1 Aug 2019 12:45:23 +0000 (14:45 +0200)
Document new meaning of immortal=1 for players

Disable breathing if player is immortal

Hide builtin statbars if player immortal (delayed)

Co-authored-by: ClobberXD <ClobberXD@gmail.com>
builtin/game/statbars.lua
doc/lua_api.txt
src/content_sao.cpp
src/content_sao.h
src/server.cpp

index da924d6f8f78229cea529dbfa377b5f63a1db428..bb88356d5a85de6046cb805c5a58a08253af6e2f 100644 (file)
@@ -50,7 +50,8 @@ local function update_builtin_statbars(player)
        end
        local hud = hud_ids[name]
 
-       if flags.healthbar and enable_damage then
+       local immortal = player:get_armor_groups().immortal == 1
+       if flags.healthbar and enable_damage and not immortal then
                local number = scaleToDefault(player, "hp")
                if hud.id_healthbar == nil then
                        local hud_def = table.copy(health_bar_definition)
@@ -65,7 +66,7 @@ local function update_builtin_statbars(player)
        end
 
        local breath_max = player:get_properties().breath_max
-       if flags.breathbar and enable_damage and
+       if flags.breathbar and enable_damage and not immortal and
                        player:get_breath() < breath_max then
                local number = 2 * scaleToDefault(player, "breath")
                if hud.id_breathbar == nil then
@@ -116,7 +117,7 @@ local function player_event_handler(player,eventname)
                end
        end
 
-       if eventname == "hud_changed" then
+       if eventname == "hud_changed" or eventname == "properties_changed" then
                update_builtin_statbars(player)
                return true
        end
index 22bd6f548ac9b0c37cccd64a2954460e151231e4..4026821ddaf980568e08f175e32df3cf74b6ba5d 100644 (file)
@@ -1533,7 +1533,9 @@ Another example: Make red wool from white wool and red dye:
 Special groups
 --------------
 
-* `immortal`: Disables the group damage system for an entity
+* `immortal`: Skips all damage and breath handling for an object. This group
+  will also hide the integrated HUD status bars for players, and is
+  automatically set to all players when damage is disabled on the server.
 * `punch_operable`: For entities; disables the regular damage mechanism for
   players punching it by hand or a non-tool item, so that it can do something
   else than take damage.
index 84a09d977f98dde74fc017475975f58107b93af8..c0bc25a4d93edd71bb2401bedfc25e1fc004c87d 100644 (file)
@@ -134,7 +134,7 @@ void UnitSAO::setArmorGroups(const ItemGroupList &armor_groups)
        m_armor_groups_sent = false;
 }
 
-const ItemGroupList &UnitSAO::getArmorGroups()
+const ItemGroupList &UnitSAO::getArmorGroups() const
 {
        return m_armor_groups;
 }
@@ -1015,14 +1015,14 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                }
        }
 
-       if (m_breathing_interval.step(dtime, 0.5f)) {
+       if (m_breathing_interval.step(dtime, 0.5f) && !isImmortal()) {
                // Get nose/mouth position, approximate with eye position
                v3s16 p = floatToInt(getEyePosition(), BS);
                MapNode n = m_env->getMap().getNodeNoEx(p);
                const ContentFeatures &c = m_env->getGameDef()->ndef()->get(n);
-               // If player is alive & no drowning & not in ignore, breathe
-               if (m_breath < m_prop.breath_max &&
-                               c.drowning == 0 && n.getContent() != CONTENT_IGNORE && m_hp > 0)
+               // If player is alive & not drowning & not in ignore & not immortal, breathe
+               if (m_breath < m_prop.breath_max && c.drowning == 0 &&
+                               n.getContent() != CONTENT_IGNORE && m_hp > 0)
                        setBreath(m_breath + 1);
        }
 
@@ -1069,6 +1069,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
                m_messages_out.push(aom);
+               m_env->getScriptIface()->player_event(this, "properties_changed");
        }
 
        // If attached, check that our parent is still there. If it isn't, detach.
@@ -1287,8 +1288,8 @@ int PlayerSAO::punch(v3f dir,
 
        FATAL_ERROR_IF(!puncher, "Punch action called without SAO");
 
-       // No effect if PvP disabled
-       if (!g_settings->getBool("enable_pvp")) {
+       // No effect if PvP disabled or if immortal
+       if (isImmortal() || !g_settings->getBool("enable_pvp")) {
                if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
                        std::string str = gob_cmd_punched(getHP());
                        // create message and add to list
index 0c503b4cbb1903cf93998b3423236ae36a9da1b1..c579474ee60fd1ee5ab85cececdff77cab049597 100644 (file)
@@ -45,11 +45,12 @@ public:
 
        inline bool isAttached() const
        { return getParent(); }
+
        inline bool isImmortal() const
-       { return itemgroup_get(m_armor_groups, "immortal"); }
+       { return itemgroup_get(getArmorGroups(), "immortal"); }
 
        void setArmorGroups(const ItemGroupList &armor_groups);
-       const ItemGroupList &getArmorGroups();
+       const ItemGroupList &getArmorGroups() const;
        void setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop);
        void getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop);
        void setAnimationSpeed(float frame_speed);
@@ -107,7 +108,7 @@ class LuaEntitySAO : public UnitSAO
 {
 public:
        LuaEntitySAO(ServerEnvironment *env, v3f pos,
-                    const std::string &name, const std::string &state);
+               const std::string &name, const std::string &state);
        ~LuaEntitySAO();
        ActiveObjectType getType() const
        { return ACTIVEOBJECT_TYPE_LUAENTITY; }
@@ -115,16 +116,16 @@ public:
        { return ACTIVEOBJECT_TYPE_GENERIC; }
        virtual void addedToEnvironment(u32 dtime_s);
        static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
-                       const std::string &data);
+               const std::string &data);
        void step(float dtime, bool send_recommended);
        std::string getClientInitializationData(u16 protocol_version);
        bool isStaticAllowed() const
        { return m_prop.static_save; }
        void getStaticData(std::string *result) const;
        int punch(v3f dir,
-                       const ToolCapabilities *toolcap=NULL,
-                       ServerActiveObject *puncher=NULL,
-                       float time_from_last_punch=1000000);
+               const ToolCapabilities *toolcap = nullptr,
+               ServerActiveObject *puncher = nullptr,
+               float time_from_last_punch = 1000000);
        void rightClick(ServerActiveObject *clicker);
        void setPos(const v3f &pos);
        void moveTo(v3f pos, bool continuous);
@@ -132,6 +133,7 @@ public:
        std::string getDescription();
        void setHP(s32 hp, const PlayerHPChangeReason &reason);
        u16 getHP() const;
+
        /* LuaEntitySAO-specific */
        void setVelocity(v3f velocity);
        void addVelocity(v3f velocity)
index f3c13bad11aaf300e75f9db36c9c48764e7f335f..b3a6b49091ef5441c37facba993afe0f4e55c9fc 100644 (file)
@@ -1429,7 +1429,7 @@ void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason
        if (playersao->isImmortal())
                return;
 
-       session_t peer_id   = playersao->getPeerID();
+       session_t peer_id = playersao->getPeerID();
        bool is_alive = playersao->getHP() > 0;
 
        if (is_alive)