From 53066024f6a91d5f83241b379b94d8557d43a646 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Wed, 19 Jun 2013 14:30:22 +0000 Subject: [PATCH] Add drowning --- doc/lua_api.txt | 1 + .../minimal/mods/default/textures/bubble.png | Bin 0 -> 273 bytes src/client.cpp | 7 +++ src/client.h | 1 + src/environment.cpp | 40 +++++++++++++++++- src/environment.h | 2 + src/game.cpp | 2 +- src/hud.cpp | 5 ++- src/hud.h | 3 +- src/nodedef.cpp | 3 ++ src/nodedef.h | 1 + src/player.cpp | 4 +- src/player.h | 1 + src/script/common/c_content.cpp | 1 + src/script/lua_api/l_object.cpp | 1 + 15 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 games/minimal/mods/default/textures/bubble.png diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 85f6ca5a6..d3d427d69 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -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 index 0000000000000000000000000000000000000000..3bca7e11cce4c0bfcb34180eea447b6c5e1c6655 GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(`}iP--rF2vCHxz$3Dl zfq`2Xgc%uT&5-~KvX^-Jy0YJ86XqAEak-ar*3}gS;$?9Igj*qa4@{jx zfS~Wym2M%QSNVk)2cErr_0)ne&zBFbDZP(jV3;Cg*>alIuCd(vPEJ)l@128H*Iphs zocDLyrW-<2ygSf6aSvd4KH{{hql% Pmoj*|`njxgN@xNAc5-JP literal 0 HcmV?d00001 diff --git a/src/client.cpp b/src/client.cpp index 6b1789fe0..5f53e14f7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -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) diff --git a/src/client.h b/src/client.h index f0cc55868..1d231a5a3 100644 --- a/src/client.h +++ b/src/client.h @@ -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); } diff --git a/src/environment.cpp b/src/environment.cpp index a97a9bd08..99da5190c 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -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 */ diff --git a/src/environment.h b/src/environment.h index a62173a11..ac479999c 100644 --- a/src/environment.h +++ b/src/environment.h @@ -494,6 +494,8 @@ private: Queue 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 m_player_names; }; diff --git a/src/game.cpp b/src/game.cpp index 30d9c7faf..88be47b39 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -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()); } /* diff --git a/src/hud.cpp b/src/hud.cpp index a3ae38bcb..9404ed997 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -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)); } diff --git a/src/hud.h b/src/hud.h index fa9d33f8b..c7289f7c4 100644 --- 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(); diff --git a/src/nodedef.cpp b/src/nodedef.cpp index ba3e42e98..7d8ce70d3 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -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) {}; } diff --git a/src/nodedef.h b/src/nodedef.h index 2691aca33..e397d20e0 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -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; diff --git a/src/player.cpp b/src/player.cpp index 4eb5955c0..a199c9a6c 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -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; } diff --git a/src/player.h b/src/player.h index d3738fd52..517bd354d 100644 --- a/src/player.h +++ b/src/player.h @@ -232,6 +232,7 @@ public: float physics_override_gravity; u16 hp; + u16 breath; float hurt_tilt_timer; float hurt_tilt_strength; diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index c7966a0be..64c76ef7c 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -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); diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 1e45610a6..f90b59285 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -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}, };