Add drowning 780/head
authorPilzAdam <pilzadam@minetest.net>
Wed, 19 Jun 2013 14:30:22 +0000 (14:30 +0000)
committerPilzAdam <pilzadam@minetest.net>
Wed, 19 Jun 2013 15:47:00 +0000 (15:47 +0000)
15 files changed:
doc/lua_api.txt
games/minimal/mods/default/textures/bubble.png [new file with mode: 0644]
src/client.cpp
src/client.h
src/environment.cpp
src/environment.h
src/game.cpp
src/hud.cpp
src/hud.h
src/nodedef.cpp
src/nodedef.h
src/player.cpp
src/player.h
src/script/common/c_content.cpp
src/script/lua_api/l_object.cpp

index 85f6ca5a6afa012b8c16f2e14f2a8632c8fb68b0..d3d427d69dff15213dd621839801d3c08cca6166 100644 (file)
@@ -1710,6 +1710,7 @@ Node definition (register_node)
     liquid_alternative_source = "", -- Source version of flowing liquid
     liquid_viscosity = 0, -- Higher viscosity = slower flow (max. 7)
     liquid_renewable = true, -- Can new liquid source be created by placing
+    drowning = true, -- Player will drown in these
     two or more sources nearly?
     light_source = 0, -- Amount of light emitted by node
     damage_per_second = 0, -- If player is inside node, this damage is caused
diff --git a/games/minimal/mods/default/textures/bubble.png b/games/minimal/mods/default/textures/bubble.png
new file mode 100644 (file)
index 0000000..3bca7e1
Binary files /dev/null and b/games/minimal/mods/default/textures/bubble.png differ
index 6b1789fe095a51a4f963dd25cedc48c2f82936d2..5f53e14f7c73b19b25048496a14e1ed9d3d8c027 100644 (file)
@@ -2680,6 +2680,13 @@ u16 Client::getHP()
        return player->hp;
 }
 
+u16 Client::getBreath()
+{
+       Player *player = m_env.getLocalPlayer();
+       assert(player != NULL);
+       return player->breath;
+}
+
 bool Client::getChatMessage(std::wstring &message)
 {
        if(m_chat_queue.size() == 0)
index f0cc5586816372c007532ef6101854491784ddca..1d231a5a3be27b9de468c0138f12a3c3f0e0134b 100644 (file)
@@ -349,6 +349,7 @@ public:
        void setCrack(int level, v3s16 pos);
 
        u16 getHP();
+       u16 getBreath();
 
        bool checkPrivilege(const std::string &priv)
        { return (m_privileges.count(priv) != 0); }
index a97a9bd08d73de324036a617a4248375a8c7bcc3..99da5190c0dedaef2985b253e0333e76837695aa 100644 (file)
@@ -2227,7 +2227,45 @@ void ClientEnvironment::step(float dtime)
                        damageLocalPlayer(damage_per_second, true);
                }
        }
-       
+
+       /*
+               Drowning
+       */
+       if(m_drowning_interval.step(dtime, 2.0))
+       {
+               v3f pf = lplayer->getPosition();
+
+               // head
+               v3s16 p = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
+               MapNode n = m_map->getNodeNoEx(p);
+               ContentFeatures c = m_gamedef->ndef()->get(n);
+
+               if(c.isLiquid() && c.drowning){
+                       if(lplayer->breath > 10)
+                               lplayer->breath = 11;
+                       if(lplayer->breath > 0)
+                               lplayer->breath -= 1;
+               }
+
+               if(lplayer->breath == 0){
+                       damageLocalPlayer(1, true);
+               }
+       }
+       if(m_breathing_interval.step(dtime, 0.5))
+       {
+               v3f pf = lplayer->getPosition();
+
+               // head
+               v3s16 p = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
+               MapNode n = m_map->getNodeNoEx(p);
+               ContentFeatures c = m_gamedef->ndef()->get(n);
+
+               if(!c.isLiquid() || !c.drowning){
+                       if(lplayer->breath <= 10)
+                               lplayer->breath += 1;
+               }
+       }
+
        /*
                Stuff that can be done in an arbitarily large dtime
        */
index a62173a11f51a4481fd8fa86399a9d21ce51c82c..ac479999cf748d29a09f5a18e72b74afd64dc7be 100644 (file)
@@ -494,6 +494,8 @@ private:
        Queue<ClientEnvEvent> m_client_event_queue;
        IntervalLimiter m_active_object_light_update_interval;
        IntervalLimiter m_lava_hurt_interval;
+       IntervalLimiter m_drowning_interval;
+       IntervalLimiter m_breathing_interval;
        std::list<std::string> m_player_names;
 };
 
index 30d9c7fafe9b9ceb7cab6c191f0b6a55bf721ebf..88be47b396ae80db3c0d67b0264a9a5ecfb3c1c1 100644 (file)
@@ -3310,7 +3310,7 @@ void the_game(
                if (show_hud)
                {
                        hud.drawHotbar(v2s32(displaycenter.X, screensize.Y),
-                                       client.getHP(), client.getPlayerItem());
+                                       client.getHP(), client.getPlayerItem(), client.getBreath());
                }
 
                /*
index a3ae38bcb7a241b75832d9ced81ff8b3b85551ff..9404ed997e66971bd9ccd8085b701a98ff9a5bc5 100644 (file)
@@ -278,7 +278,7 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s
 }
 
 
-void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
+void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, s32 breath) {
        InventoryList *mainlist = inventory->getList("main");
        if (mainlist == NULL) {
                errorstream << "draw_hotbar(): mainlist == NULL" << std::endl;
@@ -295,6 +295,9 @@ void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
        if (player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)
                drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT,
                                "heart.png", halfheartcount, v2s32(0, 0));
+       if (player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE && breath <= 10)
+               drawStatbar(pos - v2s32(-180, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT,
+                               "bubble.png", breath*2, v2s32(0, 0));
 }
 
 
index fa9d33f8b5d5e02b6b79801bfaa066a3a94d2337..c7289f7c4f79244b963f17cd6ef00266c3c960f0 100644 (file)
--- a/src/hud.h
+++ b/src/hud.h
@@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define HUD_FLAG_HEALTHBAR_VISIBLE (1 << 1)
 #define HUD_FLAG_CROSSHAIR_VISIBLE (1 << 2)
 #define HUD_FLAG_WIELDITEM_VISIBLE (1 << 3)
+#define HUD_FLAG_BREATHBAR_VISIBLE (1 << 4)
 
 #define HUD_PARAM_HOTBAR_ITEMCOUNT 1
 
@@ -122,7 +123,7 @@ public:
        void drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
                                         std::string texture, s32 count, v2s32 offset);
        
-       void drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem);
+       void drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, s32 breath);
        void resizeHotbar();
        
        void drawCrosshair();
index ba3e42e980a36e9901183533c3d2f1aff6db11d5..7d8ce70d312470cbb1ba673ded75f88b433347c5 100644 (file)
@@ -211,6 +211,7 @@ void ContentFeatures::reset()
        liquid_alternative_source = "";
        liquid_viscosity = 0;
        liquid_renewable = true;
+       drowning = true;
        light_source = 0;
        damage_per_second = 0;
        node_box = NodeBox();
@@ -279,6 +280,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
        writeU8(os, rightclickable);
        // Stuff below should be moved to correct place in a version that otherwise changes
        // the protocol version
+       writeU8(os, drowning);
 }
 
 void ContentFeatures::deSerialize(std::istream &is)
@@ -343,6 +345,7 @@ void ContentFeatures::deSerialize(std::istream &is)
        try{
                // Stuff below should be moved to correct place in a version that
                // otherwise changes the protocol version
+               drowning = readU8(is);
        }catch(SerializationError &e) {};
 }
 
index 2691aca33eb59376bec13174eb465639310479b6..e397d20e026de2c170bc1f74ef69e61c690fadc2 100644 (file)
@@ -219,6 +219,7 @@ struct ContentFeatures
        u8 liquid_viscosity;
        // Is liquid renewable (new liquid source will be created between 2 existing)
        bool liquid_renewable;
+       bool drowning;
        // Amount of light the node emits
        u8 light_source;
        u32 damage_per_second;
index 4eb5955c089461c5632a96e184aed0742ede3188..a199c9a6c2ff13f6257b5f93b179622e42adccec 100644 (file)
@@ -36,6 +36,7 @@ Player::Player(IGameDef *gamedef):
        camera_barely_in_ceiling(false),
        inventory(gamedef->idef()),
        hp(PLAYER_MAX_HP),
+       breath(-1),
        peer_id(PEER_ID_INEXISTENT),
 // protected
        m_gamedef(gamedef),
@@ -80,7 +81,8 @@ Player::Player(IGameDef *gamedef):
        physics_override_gravity = 1;
 
        hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
-                        HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE;
+                        HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE |
+                        HUD_FLAG_BREATHBAR_VISIBLE;
 
        hud_hotbar_itemcount = HUD_HOTBAR_ITEMCOUNT_DEFAULT;
 }
index d3738fd528b46b6afd28a5bfbdeacaa01d73bb2c..517bd354dad0fed5161e340534ff3f75dd181386 100644 (file)
@@ -232,6 +232,7 @@ public:
        float physics_override_gravity;
 
        u16 hp;
+       u16 breath;
 
        float hurt_tilt_timer;
        float hurt_tilt_strength;
index c7966a0be83d0eac2143b4acf0a60b7dba126ba7..64c76ef7c4d446158eca7787c1ad63c44a4bd2c2 100644 (file)
@@ -389,6 +389,7 @@ ContentFeatures read_content_features(lua_State *L, int index)
        f.liquid_viscosity = getintfield_default(L, index,
                        "liquid_viscosity", f.liquid_viscosity);
        getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
+       getboolfield(L, index, "drowning", f.drowning);
        // Amount of light the node emits
        f.light_source = getintfield_default(L, index,
                        "light_source", f.light_source);
index 1e45610a65bd3ba13d5274b06c785a70af8e536c..f90b59285bdde7de38a9c71888cb70f472b83c5f 100644 (file)
@@ -62,6 +62,7 @@ struct EnumString es_HudBuiltinElement[] =
        {HUD_FLAG_HEALTHBAR_VISIBLE, "healthbar"},
        {HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"},
        {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"},
+       {HUD_FLAG_BREATHBAR_VISIBLE, "breathbar"},
        {0, NULL},
 };