summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/game/statbars.lua4
-rw-r--r--doc/lua_api.txt16
-rw-r--r--doc/texture_packs.txt4
-rw-r--r--src/client/clientevent.h1
-rw-r--r--src/client/game.cpp7
-rw-r--r--src/client/hud.cpp96
-rw-r--r--src/client/hud.h5
-rw-r--r--src/hud.cpp1
-rw-r--r--src/hud.h2
-rw-r--r--src/network/clientpackethandler.cpp15
-rw-r--r--src/network/networkprotocol.h6
-rw-r--r--src/script/common/c_content.cpp8
-rw-r--r--src/server.cpp3
-rw-r--r--textures/base/pack/bubble_gone.pngbin0 -> 68 bytes
-rw-r--r--textures/base/pack/heart_gone.pngbin0 -> 68 bytes
15 files changed, 132 insertions, 36 deletions
diff --git a/builtin/game/statbars.lua b/builtin/game/statbars.lua
index 6b5b54428..d192029c5 100644
--- a/builtin/game/statbars.lua
+++ b/builtin/game/statbars.lua
@@ -5,7 +5,9 @@ local health_bar_definition = {
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "heart.png",
+ text2 = "heart_gone.png",
number = core.PLAYER_MAX_HP_DEFAULT,
+ item = core.PLAYER_MAX_HP_DEFAULT,
direction = 0,
size = {x = 24, y = 24},
offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 16)},
@@ -15,7 +17,9 @@ local breath_bar_definition = {
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
text = "bubble.png",
+ text2 = "bubble_gone.png",
number = core.PLAYER_MAX_BREATH_DEFAULT,
+ item = core.PLAYER_MAX_BREATH_DEFAULT * 2,
direction = 0,
size = {x = 24, y = 24},
offset = {x = 25, y= -(48 + 24 + 16)},
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 961e1ff37..4078e21a1 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -1289,9 +1289,9 @@ To account for differing resolutions, the position coordinates are the
percentage of the screen, ranging in value from `0` to `1`.
The name field is not yet used, but should contain a description of what the
-HUD element represents. The direction field is the direction in which something
-is drawn.
+HUD element represents.
+The `direction` field is the direction in which something is drawn.
`0` draws from left to right, `1` draws from right to left, `2` draws from
top to bottom, and `3` draws from bottom to top.
@@ -1355,12 +1355,16 @@ Displays text on the HUD.
### `statbar`
-Displays a horizontal bar made up of half-images.
+Displays a horizontal bar made up of half-images with an optional background.
-* `text`: The name of the texture that is used.
+* `text`: The name of the texture to use.
+* `text2`: Optional texture name to enable a background / "off state"
+ texture (useful to visualize the maximal value). Both textures
+ must have the same size.
* `number`: The number of half-textures that are displayed.
If odd, will end with a vertically center-split texture.
-* `direction`
+* `item`: Same as `number` but for the "off state" texture
+* `direction`: To which direction the images will extend to
* `offset`: offset in pixels from position.
* `size`: If used, will force full-image size to this value (override texture
pack image size)
@@ -7772,6 +7776,8 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`.
text = "<text>",
+ text2 = "<text>",
+
number = 2,
item = 3,
diff --git a/doc/texture_packs.txt b/doc/texture_packs.txt
index 4e7bc93c4..94151f1a4 100644
--- a/doc/texture_packs.txt
+++ b/doc/texture_packs.txt
@@ -64,6 +64,8 @@ by texture packs. All existing fallback textures can be found in the directory
* `bubble.png`: the bubble texture when the player is drowning
(default size: 12×12)
+* `bubble_gone.png`: like `bubble.png`, but denotes lack of breath
+ (transparent by default, same size as bubble.png)
* `crack_anylength.png`: node overlay texture when digging
@@ -76,6 +78,8 @@ by texture packs. All existing fallback textures can be found in the directory
* `heart.png`: used to display the health points of the player
(default size: 12×12)
+* `heart_gone.png`: like `heart.png`, but denotes lack of health points
+ (transparent by default, same size as heart.png)
* `minimap_mask_round.png`: round minimap mask, white gets replaced by the map
* `minimap_mask_square.png`: mask used for the square minimap
diff --git a/src/client/clientevent.h b/src/client/clientevent.h
index f5689c25b..7f3984b03 100644
--- a/src/client/clientevent.h
+++ b/src/client/clientevent.h
@@ -136,6 +136,7 @@ struct ClientEvent
v3f *world_pos;
v2s32 *size;
s16 z_index;
+ std::string *text2;
} hudadd;
struct
{
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 4d7a85526..422e17d4f 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -2672,6 +2672,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
delete event->hudadd.offset;
delete event->hudadd.world_pos;
delete event->hudadd.size;
+ delete event->hudadd.text2;
return;
}
@@ -2689,6 +2690,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
e->world_pos = *event->hudadd.world_pos;
e->size = *event->hudadd.size;
e->z_index = event->hudadd.z_index;
+ e->text2 = *event->hudadd.text2;
hud_server_to_client[server_id] = player->addHud(e);
delete event->hudadd.pos;
@@ -2699,6 +2701,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
delete event->hudadd.offset;
delete event->hudadd.world_pos;
delete event->hudadd.size;
+ delete event->hudadd.text2;
}
void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam)
@@ -2771,6 +2774,10 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca
case HUD_STAT_Z_INDEX:
e->z_index = event->hudchange.data;
break;
+
+ case HUD_STAT_TEXT2:
+ e->text2 = *event->hudchange.sdata;
+ break;
}
delete event->hudchange.v3fdata;
diff --git a/src/client/hud.cpp b/src/client/hud.cpp
index 56763e7e4..f8f712762 100644
--- a/src/client/hud.cpp
+++ b/src/client/hud.cpp
@@ -332,7 +332,8 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
break; }
case HUD_ELEM_STATBAR: {
v2s32 offs(e->offset.X, e->offset.Y);
- drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs, e->size);
+ drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->text2,
+ e->number, e->item, offs, e->size);
break; }
case HUD_ELEM_INVENTORY: {
InventoryList *inv = inventory->getList(e->text);
@@ -401,8 +402,9 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
}
-void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &texture,
- s32 count, v2s32 offset, v2s32 size)
+void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
+ const std::string &texture, const std::string &bgtexture,
+ s32 count, s32 maxcount, v2s32 offset, v2s32 size)
{
const video::SColor color(255, 255, 255, 255);
const video::SColor colors[] = {color, color, color, color};
@@ -411,6 +413,11 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &tex
if (!stat_texture)
return;
+ video::ITexture *stat_texture_bg = nullptr;
+ if (!bgtexture.empty()) {
+ stat_texture_bg = tsrc->getTexture(bgtexture);
+ }
+
core::dimension2di srcd(stat_texture->getOriginalSize());
core::dimension2di dstd;
if (size == v2s32()) {
@@ -430,43 +437,100 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &tex
p += offset;
v2s32 steppos;
- core::rect<s32> srchalfrect, dsthalfrect;
switch (drawdir) {
case HUD_DIR_RIGHT_LEFT:
steppos = v2s32(-1, 0);
- srchalfrect = core::rect<s32>(srcd.Width / 2, 0, srcd.Width, srcd.Height);
- dsthalfrect = core::rect<s32>(dstd.Width / 2, 0, dstd.Width, dstd.Height);
break;
case HUD_DIR_TOP_BOTTOM:
steppos = v2s32(0, 1);
- srchalfrect = core::rect<s32>(0, 0, srcd.Width, srcd.Height / 2);
- dsthalfrect = core::rect<s32>(0, 0, dstd.Width, dstd.Height / 2);
break;
case HUD_DIR_BOTTOM_TOP:
steppos = v2s32(0, -1);
- srchalfrect = core::rect<s32>(0, srcd.Height / 2, srcd.Width, srcd.Height);
- dsthalfrect = core::rect<s32>(0, dstd.Height / 2, dstd.Width, dstd.Height);
break;
default:
+ // From left to right
steppos = v2s32(1, 0);
- srchalfrect = core::rect<s32>(0, 0, srcd.Width / 2, srcd.Height);
- dsthalfrect = core::rect<s32>(0, 0, dstd.Width / 2, dstd.Height);
+ break;
+ }
+
+ auto calculate_clipping_rect = [] (core::dimension2di src,
+ v2s32 steppos) -> core::rect<s32> {
+
+ // Create basic rectangle
+ core::rect<s32> rect(0, 0,
+ src.Width - std::abs(steppos.X) * src.Width / 2,
+ src.Height - std::abs(steppos.Y) * src.Height / 2
+ );
+ // Move rectangle left or down
+ if (steppos.X == -1)
+ rect += v2s32(src.Width / 2, 0);
+ if (steppos.Y == -1)
+ rect += v2s32(0, src.Height / 2);
+ return rect;
+ };
+ // Rectangles for 1/2 the actual value to display
+ core::rect<s32> srchalfrect, dsthalfrect;
+ // Rectangles for 1/2 the "off state" texture
+ core::rect<s32> srchalfrect2, dsthalfrect2;
+
+ if (count % 2 == 1) {
+ // Need to draw halves: Calculate rectangles
+ srchalfrect = calculate_clipping_rect(srcd, steppos);
+ dsthalfrect = calculate_clipping_rect(dstd, steppos);
+ srchalfrect2 = calculate_clipping_rect(srcd, steppos * -1);
+ dsthalfrect2 = calculate_clipping_rect(dstd, steppos * -1);
}
+
steppos.X *= dstd.Width;
steppos.Y *= dstd.Height;
+ // Draw full textures
for (s32 i = 0; i < count / 2; i++) {
core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
- core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
+ core::rect<s32> dstrect(0, 0, dstd.Width, dstd.Height);
dstrect += p;
- draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
+ draw2DImageFilterScaled(driver, stat_texture,
+ dstrect, srcrect, NULL, colors, true);
p += steppos;
}
if (count % 2 == 1) {
- dsthalfrect += p;
- draw2DImageFilterScaled(driver, stat_texture, dsthalfrect, srchalfrect, NULL, colors, true);
+ // Draw half a texture
+ draw2DImageFilterScaled(driver, stat_texture,
+ dsthalfrect + p, srchalfrect, NULL, colors, true);
+
+ if (stat_texture_bg && maxcount > count) {
+ draw2DImageFilterScaled(driver, stat_texture_bg,
+ dsthalfrect2 + p, srchalfrect2,
+ NULL, colors, true);
+ p += steppos;
+ }
+ }
+
+ if (stat_texture_bg && maxcount > count / 2) {
+ // Draw "off state" textures
+ s32 start_offset;
+ if (count % 2 == 1)
+ start_offset = count / 2 + 1;
+ else
+ start_offset = count / 2;
+ for (s32 i = start_offset; i < maxcount / 2; i++) {
+ core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
+ core::rect<s32> dstrect(0, 0, dstd.Width, dstd.Height);
+
+ dstrect += p;
+ draw2DImageFilterScaled(driver, stat_texture_bg,
+ dstrect, srcrect,
+ NULL, colors, true);
+ p += steppos;
+ }
+
+ if (maxcount % 2 == 1) {
+ draw2DImageFilterScaled(driver, stat_texture_bg,
+ dsthalfrect + p, srchalfrect,
+ NULL, colors, true);
+ }
}
}
diff --git a/src/client/hud.h b/src/client/hud.h
index cab115990..6274b1a83 100644
--- a/src/client/hud.h
+++ b/src/client/hud.h
@@ -82,8 +82,9 @@ public:
private:
bool calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *pos);
- void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &texture,
- s32 count, v2s32 offset, v2s32 size = v2s32());
+ void drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
+ const std::string &texture, const std::string& bgtexture,
+ s32 count, s32 maxcount, v2s32 offset, v2s32 size = v2s32());
void drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
s32 inv_offset, InventoryList *mainlist, u16 selectitem,
diff --git a/src/hud.cpp b/src/hud.cpp
index 39625b5fd..3079b5cd8 100644
--- a/src/hud.cpp
+++ b/src/hud.cpp
@@ -46,6 +46,7 @@ const struct EnumString es_HudElementStat[] =
{HUD_STAT_WORLD_POS, "world_pos"},
{HUD_STAT_SIZE, "size"},
{HUD_STAT_Z_INDEX, "z_index"},
+ {HUD_STAT_TEXT2, "text2"},
{0, NULL},
};
diff --git a/src/hud.h b/src/hud.h
index b0977c6a4..bab420ed2 100644
--- a/src/hud.h
+++ b/src/hud.h
@@ -77,6 +77,7 @@ enum HudElementStat {
HUD_STAT_WORLD_POS,
HUD_STAT_SIZE,
HUD_STAT_Z_INDEX,
+ HUD_STAT_TEXT2,
};
struct HudElement {
@@ -93,6 +94,7 @@ struct HudElement {
v3f world_pos;
v2s32 size;
s16 z_index = 0;
+ std::string text2;
};
extern const EnumString es_HudElementType[];
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 8d0225a3d..7b1b1368c 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -1102,22 +1102,16 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
v3f world_pos;
v2s32 size;
s16 z_index = 0;
+ std::string text2;
*pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item
>> dir >> align >> offset;
try {
*pkt >> world_pos;
- }
- catch(SerializationError &e) {};
-
- try {
*pkt >> size;
- } catch(SerializationError &e) {};
-
- try {
*pkt >> z_index;
- }
- catch(PacketError &e) {}
+ *pkt >> text2;
+ } catch(PacketError &e) {};
ClientEvent *event = new ClientEvent();
event->type = CE_HUDADD;
@@ -1135,6 +1129,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
event->hudadd.world_pos = new v3f(world_pos);
event->hudadd.size = new v2s32(size);
event->hudadd.z_index = z_index;
+ event->hudadd.text2 = new std::string(text2);
m_client_event_queue.push(event);
}
@@ -1171,7 +1166,7 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt)
if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE ||
stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET)
*pkt >> v2fdata;
- else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT)
+ else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT || stat == HUD_STAT_TEXT2)
*pkt >> sdata;
else if (stat == HUD_STAT_WORLD_POS)
*pkt >> v3fdata;
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index 527ebba7c..ab924f1db 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -560,10 +560,10 @@ enum ToClientCommand
u32 id
u8 type
v2f1000 pos
- u32 len
+ u16 len
u8[len] name
v2f1000 scale
- u32 len2
+ u16 len2
u8[len2] text
u32 number
u32 item
@@ -573,6 +573,8 @@ enum ToClientCommand
v3f1000 world_pos
v2s32 size
s16 z_index
+ u16 len3
+ u8[len3] text2
*/
TOCLIENT_HUDRM = 0x4a,
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index dac828316..540b7222f 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -1871,6 +1871,7 @@ void read_hud_element(lua_State *L, HudElement *elem)
elem->dir = getintfield_default(L, 2, "direction", 0);
elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX,
getintfield_default(L, 2, "z_index", 0)));
+ elem->text2 = getstringfield_default(L, 2, "text2", "");
// Deprecated, only for compatibility's sake
if (elem->dir == 0)
@@ -1939,6 +1940,9 @@ void push_hud_element(lua_State *L, HudElement *elem)
lua_pushnumber(L, elem->z_index);
lua_setfield(L, -2, "z_index");
+
+ lua_pushstring(L, elem->text2.c_str());
+ lua_setfield(L, -2, "text2");
}
HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
@@ -2000,6 +2004,10 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX, luaL_checknumber(L, 4)));
*value = &elem->z_index;
break;
+ case HUD_STAT_TEXT2:
+ elem->text2 = luaL_checkstring(L, 4);
+ *value = &elem->text2;
+ break;
}
return stat;
}
diff --git a/src/server.cpp b/src/server.cpp
index 16e026ce2..b28c30e1e 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1621,7 +1621,7 @@ void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
pkt << id << (u8) form->type << form->pos << form->name << form->scale
<< form->text << form->number << form->item << form->dir
<< form->align << form->offset << form->world_pos << form->size
- << form->z_index;
+ << form->z_index << form->text2;
Send(&pkt);
}
@@ -1647,6 +1647,7 @@ void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void
break;
case HUD_STAT_NAME:
case HUD_STAT_TEXT:
+ case HUD_STAT_TEXT2:
pkt << *(std::string *) value;
break;
case HUD_STAT_WORLD_POS:
diff --git a/textures/base/pack/bubble_gone.png b/textures/base/pack/bubble_gone.png
new file mode 100644
index 000000000..240ca4f8d
--- /dev/null
+++ b/textures/base/pack/bubble_gone.png
Binary files differ
diff --git a/textures/base/pack/heart_gone.png b/textures/base/pack/heart_gone.png
new file mode 100644
index 000000000..240ca4f8d
--- /dev/null
+++ b/textures/base/pack/heart_gone.png
Binary files differ