From 8619545f4824891c9473a7040875fbd74d94d874 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 16 Jan 2017 16:09:07 +0100 Subject: [PATCH] Include hudbars mods, dump old hud mod --- mods/{hud => default}/textures/crosshair.png | Bin mods/hbarmor/README.md | 43 ++ mods/hbarmor/depends.txt | 3 + mods/hbarmor/description.txt | 1 + mods/hbarmor/init.lua | 154 +++++ mods/hbarmor/locale/de.txt | 2 + mods/hbarmor/locale/template.txt | 4 + mods/hbarmor/mod.conf | 1 + mods/hbarmor/screenshot.png | Bin 0 -> 10821 bytes mods/hbarmor/settingtypes.txt | 7 + mods/hbarmor/textures/hbarmor_bar.png | Bin 0 -> 2770 bytes .../textures/hbarmor_bgicon.png} | Bin .../textures/hbarmor_icon.png} | Bin mods/hbhunger/README.md | 97 +++ mods/hbhunger/changelog.txt | 51 ++ mods/hbhunger/depends.txt | 32 + mods/hbhunger/description.txt | 1 + mods/hbhunger/hunger.lua | 470 +++++++++++++++ mods/hbhunger/init.lua | 155 +++++ mods/hbhunger/locale/de.txt | 1 + mods/hbhunger/locale/pt.txt | 1 + mods/hbhunger/locale/template.txt | 1 + mods/hbhunger/mod.conf | 1 + mods/hbhunger/screenshot.png | Bin 0 -> 8498 bytes mods/hbhunger/sounds/hbhunger_eat_generic.ogg | Bin 0 -> 61040 bytes mods/hbhunger/textures/hbhunger_bar.png | Bin 0 -> 80 bytes .../textures/hbhunger_bar_health_poison.png | Bin 0 -> 151 bytes .../textures/hbhunger_bgicon.png} | Bin .../textures/hbhunger_icon.png} | Bin .../textures/hbhunger_icon_health_poison.png | Bin 0 -> 526 bytes mods/hud/README.txt | 49 -- mods/hud/armor.lua | 31 - mods/hud/changelog.txt | 47 -- mods/hud/depends.txt | 1 - mods/hud/hud.conf.example | 33 -- mods/hud/hunger.lua | 68 --- mods/hud/init.lua | 215 ------- mods/hudbars/API.md | 193 ++++++ mods/hudbars/README.md | 56 ++ mods/hudbars/changelog.txt | 92 +++ mods/hudbars/depends.txt | 1 + mods/hudbars/description.txt | 1 + mods/hudbars/init.lua | 559 ++++++++++++++++++ mods/hudbars/locale/de.txt | 3 + mods/hudbars/locale/pt.txt | 5 + mods/hudbars/locale/template.txt | 5 + mods/hudbars/mod.conf | 1 + mods/hudbars/screenshot.png | Bin 0 -> 9556 bytes mods/hudbars/settingtypes.txt | 119 ++++ .../textures/hudbars_bar_background.png | Bin 0 -> 140 bytes mods/hudbars/textures/hudbars_bar_breath.png | Bin 0 -> 80 bytes mods/hudbars/textures/hudbars_bar_health.png | Bin 0 -> 80 bytes .../textures/hudbars_bgicon_breath.png | Bin 0 -> 237 bytes .../textures/hudbars_bgicon_health.png} | Bin .../textures/hudbars_icon_breath.png} | Bin .../textures/hudbars_icon_health.png} | Bin 56 files changed, 2060 insertions(+), 444 deletions(-) rename mods/{hud => default}/textures/crosshair.png (100%) create mode 100644 mods/hbarmor/README.md create mode 100644 mods/hbarmor/depends.txt create mode 100644 mods/hbarmor/description.txt create mode 100644 mods/hbarmor/init.lua create mode 100644 mods/hbarmor/locale/de.txt create mode 100644 mods/hbarmor/locale/template.txt create mode 100644 mods/hbarmor/mod.conf create mode 100644 mods/hbarmor/screenshot.png create mode 100644 mods/hbarmor/settingtypes.txt create mode 100644 mods/hbarmor/textures/hbarmor_bar.png rename mods/{hud/textures/hud_armor_bg.png => hbarmor/textures/hbarmor_bgicon.png} (100%) rename mods/{hud/textures/hud_armor_fg.png => hbarmor/textures/hbarmor_icon.png} (100%) create mode 100644 mods/hbhunger/README.md create mode 100644 mods/hbhunger/changelog.txt create mode 100644 mods/hbhunger/depends.txt create mode 100644 mods/hbhunger/description.txt create mode 100644 mods/hbhunger/hunger.lua create mode 100644 mods/hbhunger/init.lua create mode 100644 mods/hbhunger/locale/de.txt create mode 100644 mods/hbhunger/locale/pt.txt create mode 100644 mods/hbhunger/locale/template.txt create mode 100644 mods/hbhunger/mod.conf create mode 100644 mods/hbhunger/screenshot.png create mode 100644 mods/hbhunger/sounds/hbhunger_eat_generic.ogg create mode 100644 mods/hbhunger/textures/hbhunger_bar.png create mode 100644 mods/hbhunger/textures/hbhunger_bar_health_poison.png rename mods/{hud/textures/hud_hunger_bg.png => hbhunger/textures/hbhunger_bgicon.png} (100%) rename mods/{hud/textures/hud_hunger_fg.png => hbhunger/textures/hbhunger_icon.png} (100%) create mode 100644 mods/hbhunger/textures/hbhunger_icon_health_poison.png delete mode 100644 mods/hud/README.txt delete mode 100644 mods/hud/armor.lua delete mode 100644 mods/hud/changelog.txt delete mode 100644 mods/hud/depends.txt delete mode 100644 mods/hud/hud.conf.example delete mode 100644 mods/hud/hunger.lua delete mode 100644 mods/hud/init.lua create mode 100644 mods/hudbars/API.md create mode 100644 mods/hudbars/README.md create mode 100644 mods/hudbars/changelog.txt create mode 100644 mods/hudbars/depends.txt create mode 100644 mods/hudbars/description.txt create mode 100644 mods/hudbars/init.lua create mode 100644 mods/hudbars/locale/de.txt create mode 100644 mods/hudbars/locale/pt.txt create mode 100644 mods/hudbars/locale/template.txt create mode 100644 mods/hudbars/mod.conf create mode 100644 mods/hudbars/screenshot.png create mode 100644 mods/hudbars/settingtypes.txt create mode 100644 mods/hudbars/textures/hudbars_bar_background.png create mode 100644 mods/hudbars/textures/hudbars_bar_breath.png create mode 100644 mods/hudbars/textures/hudbars_bar_health.png create mode 100644 mods/hudbars/textures/hudbars_bgicon_breath.png rename mods/{hud/textures/hud_heart_bg.png => hudbars/textures/hudbars_bgicon_health.png} (100%) rename mods/{hud/textures/hud_air_fg.png => hudbars/textures/hudbars_icon_breath.png} (100%) rename mods/{hud/textures/hud_heart_fg.png => hudbars/textures/hudbars_icon_health.png} (100%) diff --git a/mods/hud/textures/crosshair.png b/mods/default/textures/crosshair.png similarity index 100% rename from mods/hud/textures/crosshair.png rename to mods/default/textures/crosshair.png diff --git a/mods/hbarmor/README.md b/mods/hbarmor/README.md new file mode 100644 index 000000000..680f9c443 --- /dev/null +++ b/mods/hbarmor/README.md @@ -0,0 +1,43 @@ +# HUD bar for `3d_armor` [`hbarmor`] + +* Version: 0.2.0 + +## Description +This mod adds a simple HUD bar which displays the current damage +of the player's armor (from the 3D Armor [`3d_armor`] mod) as a percentage (rounded). + +100% armor means the armor is in perfect shape. 0% means the armor is almost destroyed +or non-existant. Note that to reach 100%, the player must wear at least 4 different +pieces of armor in perfect shape. + +The armor bar also does not tell anything about the armor's strength, +only how worn out it already is. + +By default, the armor bar is hidden if the player wears no armor. + +## Dependencies +* HUD bars [`hudbars`], major version 1 +* 3D Armor [`3d_armor`] (tested with Minetest 0.4.14) + +## Licensing +This mod is entirly free softare. + +### Source code + +* License: WTFPL (see below) +* Authors: Wuzzy, forked from the mod “Better HUD (and hunger)” [`hud`] by BlockMen (2013-2014) + +### Textures + +* `hbarmor_icon.png`—Stu ([CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)), modified by BlockMen +* `hbarmor_bgicon.png`—Stu (CC BY-SA 3.0), modified by BlockMen +* `hbarmor_bar.png`—Wuzzy (WTFPL) + +Everything else is WTFPL: +© Copyright BlockMen (2013-2014) + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://sam.zoy.org/wtfpl/COPYING for more details. diff --git a/mods/hbarmor/depends.txt b/mods/hbarmor/depends.txt new file mode 100644 index 000000000..32c22245f --- /dev/null +++ b/mods/hbarmor/depends.txt @@ -0,0 +1,3 @@ +hudbars +3d_armor +intllib? diff --git a/mods/hbarmor/description.txt b/mods/hbarmor/description.txt new file mode 100644 index 000000000..02a8a34f9 --- /dev/null +++ b/mods/hbarmor/description.txt @@ -0,0 +1 @@ +Adds a HUD bar displaying the current damage of the player's armor. diff --git a/mods/hbarmor/init.lua b/mods/hbarmor/init.lua new file mode 100644 index 000000000..fb697e729 --- /dev/null +++ b/mods/hbarmor/init.lua @@ -0,0 +1,154 @@ +local S +if (minetest.get_modpath("intllib")) then + S = intllib.Getter() +else + S = function ( s ) return s end +end + +if (not armor) or (not armor.def) then + minetest.log("error", "[hbarmor] Outdated 3d_armor version. Please update your version of 3d_armor!") +end + +local hbarmor = {} + +-- HUD statbar values +hbarmor.armor = {} + +-- Stores if player's HUD bar has been initialized so far. +hbarmor.player_active = {} + +-- Time difference in seconds between updates to the HUD armor bar. +-- Increase this number for slow servers. +hbarmor.tick = 0.1 + +-- If true, the armor bar is hidden when the player does not wear any armor +hbarmor.autohide = true + +--load custom settings +local set = minetest.setting_getbool("hbarmor_autohide") +if set ~= nil then + hbarmor.autohide = set +end + +set = minetest.setting_get("hbarmor_tick") +if tonumber(set) ~= nil then + hbarmor.tick = tonumber(set) +end + + +local must_hide = function(playername, arm) + return ((not armor.def[playername].count or armor.def[playername].count == 0) and arm == 0) +end + +local arm_printable = function(arm) + return math.ceil(math.floor(arm+0.5)) +end + +local function custom_hud(player) + local name = player:get_player_name() + + if minetest.setting_getbool("enable_damage") then + local ret = hbarmor.get_armor(player) + if ret == false then + minetest.log("error", "[hbarmor] Call to hbarmor.get_armor in custom_hud returned with false!") + end + local arm = tonumber(hbarmor.armor[name]) + if not arm then arm = 0 end + local hide + if hbarmor.autohide then + hide = must_hide(name, arm) + else + hide = false + end + hb.init_hudbar(player, "armor", arm_printable(arm), nil, hide) + end +end + +--register and define armor HUD bar +hb.register_hudbar("armor", 0xFFFFFF, S("Armor"), { icon = "hbarmor_icon.png", bgicon = "hbarmor_bgicon.png", bar = "hbarmor_bar.png" }, 0, 100, hbarmor.autohide, S("%s: %d%%")) + +function hbarmor.get_armor(player) + if not player or not armor.def then + return false + end + local name = player:get_player_name() + local def = armor.def[name] or nil + if def and def.state and def.count then + hbarmor.set_armor(name, def.state, def.count) + else + return false + end + return true +end + +function hbarmor.set_armor(player_name, ges_state, items) + local max_items = 4 + if items == 5 then + max_items = items + end + local max = max_items * 65535 + local lvl = max - ges_state + lvl = lvl/max + if ges_state == 0 and items == 0 then + lvl = 0 + end + + hbarmor.armor[player_name] = math.min(lvl* (items * (100 / max_items)), 100) +end + +-- update hud elemtens if value has changed +local function update_hud(player) + local name = player:get_player_name() + --armor + local arm = tonumber(hbarmor.armor[name]) + if not arm then + arm = 0 + hbarmor.armor[name] = 0 + end + if hbarmor.autohide then + -- hide armor bar completely when there is none + if must_hide(name, arm) then + hb.hide_hudbar(player, "armor") + else + hb.change_hudbar(player, "armor", arm_printable(arm)) + hb.unhide_hudbar(player, "armor") + end + else + hb.change_hudbar(player, "armor", arm_printable(arm)) + end +end + +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + custom_hud(player) + hbarmor.player_active[name] = true +end) + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + hbarmor.player_active[name] = false +end) + +local main_timer = 0 +local timer = 0 +minetest.register_globalstep(function(dtime) + main_timer = main_timer + dtime + timer = timer + dtime + if main_timer > hbarmor.tick or timer > 4 then + if minetest.setting_getbool("enable_damage") then + if main_timer > hbarmor.tick then main_timer = 0 end + for _,player in ipairs(minetest.get_connected_players()) do + local name = player:get_player_name() + if hbarmor.player_active[name] == true then + local ret = hbarmor.get_armor(player) + if ret == false then + minetest.log("error", "[hbarmor] Call to hbarmor.get_armor in globalstep returned with false!") + end + -- update all hud elements + update_hud(player) + end + end + end + end + if timer > 4 then timer = 0 end +end) diff --git a/mods/hbarmor/locale/de.txt b/mods/hbarmor/locale/de.txt new file mode 100644 index 000000000..5a6bacdca --- /dev/null +++ b/mods/hbarmor/locale/de.txt @@ -0,0 +1,2 @@ +Armor = Panzerung +%s: %d%% = %s: %d%% diff --git a/mods/hbarmor/locale/template.txt b/mods/hbarmor/locale/template.txt new file mode 100644 index 000000000..d898abe48 --- /dev/null +++ b/mods/hbarmor/locale/template.txt @@ -0,0 +1,4 @@ +Armor = + +# Format string for displaying the armor. E.g. "Armor: 100%" +%s: %d%% = diff --git a/mods/hbarmor/mod.conf b/mods/hbarmor/mod.conf new file mode 100644 index 000000000..47352c19d --- /dev/null +++ b/mods/hbarmor/mod.conf @@ -0,0 +1 @@ +name = hbarmor diff --git a/mods/hbarmor/screenshot.png b/mods/hbarmor/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..907cf900de5407f5fffc0b6e7cb4d6ac082972f8 GIT binary patch literal 10821 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 P00000NkvXXu0mjftq_bx literal 0 HcmV?d00001 diff --git a/mods/hbarmor/settingtypes.txt b/mods/hbarmor/settingtypes.txt new file mode 100644 index 000000000..067d5045f --- /dev/null +++ b/mods/hbarmor/settingtypes.txt @@ -0,0 +1,7 @@ +#If true, automatically hides the armor HUD bar when the player wears no +#armor. Otherwise, the armor bar shows “0%”. +hbarmor_autohide (Automatically hide armor HUD bar) bool true + +#Time difference in seconds between updates to the armor HUD bar. +#Increase this number for slow servers. +hbarmor_tick (Armor HUD bar update frequency) float 0.1 0.0 4.0 diff --git a/mods/hbarmor/textures/hbarmor_bar.png b/mods/hbarmor/textures/hbarmor_bar.png new file mode 100644 index 0000000000000000000000000000000000000000..9623c4e9dfc56ab674ae08df4c278648129b4fa1 GIT binary patch literal 2770 zcmV;@3N7`CP)uJ@VVD_UC<6{NG_fI~0ue<-1QkJoA_k0xBC#Thg@9ne9*`iQ#9$Or zQF$}6R&?d%y_c8YA7_1QpS|}zXYYO1x&V;8{kgn!SPFnNo`4_X6{c}T{8k*B#$jdxfFg<9uYy1K45IaYvHg`_dOZM)Sy63ve6hvv z1)yUy0P^?0*fb9UASvow`@mQCp^4`uNg&9uGcn1|&Nk+9SjOUl{-OWr@Hh0;_l(8q z{wNRKos+;6rV8ldy0Owz(}jF`W(JeRp&R{qi2rfmU!TJ;gp(Kmm5I1s5m_f-n#TRsj}B0%?E`vOzxB2#P=n*a3EfYETOrKoe*ICqM@{4K9Go;5xVgZi5G4 z1dM~{UdP6d+Yd3o?MrAqM0Kc|iV92owdyL5UC#5<>aVCa44|hpM4E zs0sQWIt5*Tu0n&*J!lk~f_{hI!w5`*sjxDv4V%CW*ah~3!{C*0BD@;TgA3v9a1~q+ zAA{TB3-ERLHar49hi4Ih5D^-ph8Q6X#0?2VqLBoIkE}zAkxHZUgRb+f=nat zP#6>iMMoK->`~sRLq)(kHo*Vn{;LcG6+edD1=7D>9j^O?D{Qg|tCDK{ym)H7&wDr6*;uGTJg8GHjVbnL{!cWyUB7MT6o-VNo_w8Yq`2<5Ub)hw4L3rj}5@qxMs0 zWMyP6Wy582WNT#4$d1qunl{acmP#w5ouJ*Jy_Zv#bCKi7ZIf$}8d zZdVy&)LYdbX%I9R8VMQ|8r>Q*nyQ)sn)#Z|n)kKvS`4iu ztvy=3T65Yu+7a4Yv^%sXb>ww?bn(=Yu(!=O6^iuTp>)p_Y^{w=i z^lS773}6Fm1Fpe-gF!>Ip{*g$u-szvGhed;vo5pW&GpS$<~8QGEXWp~7V9lKEnZq0SaK{6Sl+dwSOr*Z zvFf(^Xl-N7w{EeXveC4Ov)N}e%%C!Y7^RFWwrE>d+x51mZQt2h+X?JW*!^a2WS?Sx z)P8cQ&Qi|OhNWW;>JChYI)@QQx?`Nj^#uJBl~d&PK+RZLOLos~K(b5>qmrMN0})tOkySZ3_W zICNY@+|jrX%s^&6b2i>5eqa0y%Z;^%^_=a@u3%4b9605ii3Ep)@`TAmhs0fpQ%O!q zl}XcFH*PieWwLj2ZSq`7V9Mc?h17`D)-+sNT-qs~3@?S(ldh7UlRlVXkWrK|vf6I- z?$tAVKYn8-l({mqQ$Q8{O!WzMg`0(=S&msXS#Pt$vrpzo=kRj+a`kh!z=6$;c zwT88(J6|n-WB%w`m$h~4pmp)YIh_ z3ETV2tjiAU!0h1dxU-n=E9e!)6|Z;4?!H=SSy{V>ut&IOq{_dl zbFb#!9eY1iCsp6Bajj|Hr?hX|zPbJE{X++w546-O*Ot`2Kgd0Jx6Z4syT zu9enWavU5N9)I?I-1m1*_?_rJ$vD~agVqoG+9++s?NEDe`%Fht$4F;X=in*dQ{7$m zU2Q)a|9JSc+Uc4zvS-T963!N$T{xF_ZuWe}`RNOZ7sk3{yB}PPym+f8xTpV;-=!;; zJuhGEb?H5K#o@~7t9DmUU1MD9xNd#Dz0azz?I)|B+WM{g+Xrk0I&awC=o(x)cy`EX z=)z6+o0o6-+`4{y+3mqQ%kSJBju{@g%f35#FZJHb`&swrA8dGtepviS>QUumrN{L@ z>;2q1Vm)$Z)P1z?N$8UYW2~{~zhwUMVZ87u`Dx{Z>O|9|`Q+&->FRy-Sjp7DHs zy69KwU-!MxeeuI@&cF4|M9z%AfP?@5 z`Tzg`fam}Kbua(`>RI+y?e7jT@qQ9J+u02fI_K~xCWW9;wm|Ifg{z`(=+1p~_f Y0D}nv%)1^G`v3p{07*qoM6N<$f-F^0_W%F@ literal 0 HcmV?d00001 diff --git a/mods/hud/textures/hud_armor_bg.png b/mods/hbarmor/textures/hbarmor_bgicon.png similarity index 100% rename from mods/hud/textures/hud_armor_bg.png rename to mods/hbarmor/textures/hbarmor_bgicon.png diff --git a/mods/hud/textures/hud_armor_fg.png b/mods/hbarmor/textures/hbarmor_icon.png similarity index 100% rename from mods/hud/textures/hud_armor_fg.png rename to mods/hbarmor/textures/hbarmor_icon.png diff --git a/mods/hbhunger/README.md b/mods/hbhunger/README.md new file mode 100644 index 000000000..fa245da81 --- /dev/null +++ b/mods/hbhunger/README.md @@ -0,0 +1,97 @@ +# Hunger with HUD bar [`hbhunger`] + +* Version: 0.5.2 + +## Using the mod + +This mod adds a mechanic for hunger. +This mod depends on the HUD bars mod [`hudbars`], version 1.4.1 or any later version +starting with “1.”. + +## About hunger +This mod adds a hunger mechanic to the game. Players get a new attribute called “satiation”: + +* A new player starts with 20 satiation points out of 30 +* Actions like digging, placing and walking cause exhaustion, which lower the satiation +* Every 800 seconds you lose 1 satiation point without doing anything +* At 1 or 0 satiation you will suffer damage and die in case you don't eat something +* If your satiation is 16 or higher, you will slowly regenerate health points +* Eating food will increase your satiation (Duh!) + +Important: Eating food will not directly increase your health anymore, as long as the food +item is supported by this mod (see below). + +Careful! Some foods may be poisoned. If you eat a poisoned item, you may still get a satiation +boost, but for a brief period you lose health points because of food poisoning. However, +food poisoning can never kill you. + +## Statbar mode +If you use the statbar mode of the HUD Bars mod, these things are important to know: +As with all mods using HUD Bars, the bread statbar symbols represent the rough percentage +out of 30 satiation points, in steps of 5%, so the symbols give you an estimate of your +satiation. This is different from the hunger mod by BlockMen. + +You gain health at 5.5 symbols or more, as 5.5 symbols correspond to 16 satiation points. +You *may* lose health at exactly 0.5 symbols, as 0.5 symbols correspond to 1-2 satiation points. + +## Supported food +All mods which add food through standard measures (`minetest.item_eat`) are already +supported automatically. Poisoned food needs special support. + +### Known supported food mods +* Apple from Minetest Game [`default`] +* Red and brown mushroom from Minetest Game [`flowers`] +* Bread from Minetest Game [`farming`] +* [`animalmaterials`] (Mob Framework (`mobf` modpack)) +* Bushes [`bushes`] +* [`bushes_classic`] +* Creatures [`creatures`] +* [`dwarves`] (beer and such) +* Docfarming [`docfarming`] +* Ethereal / Ethereal NG [`ethereal`] +* Farming Redo [`farming`] by TenPlus1 +* Farming plus [`farming_plus`] +* Ferns [`ferns`] +* Fishing [`fishing`] +* [`fruit`] +* Glooptest [`glooptest`] +* JKMod ([`jkanimals`], [`jkfarming`], [`jkwine`]) +* [`kpgmobs`] +* [`mobfcooking`] +* [`mooretrees`] +* [`mtfoods`] +* [`mushroom`] +* [`mush45`] +* Seaplants [`sea`] +* Simple mobs [`mobs`] +* Pizza [`pizza`] +* Not So Simple Mobs [`nssm`] + +### Supported mods without optional dependency (mods provide their own support) + +* Food ([`food`], [`food_basic`]) +* Sweet Foods [`food_sweet`] + +### Examples + +* Eating an apple (from Minetest Game) increases your satiation by 2; +* eating a bread (from Minetest Game) increases your satiation by 4. + +## Licensing +This mod is free software. + +### Source code + +* License: [LGPL v2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html) +* Author: by Wuzzy (2015-2016) +* Forked from the “Better HUD (and hunger)” mod by BlockMen (2013-2015), + most code comes from this mod. + +### Textures + +* `hbhunger_icon.png`—PilzAdam ([WTFPL](http://www.wtfpl.net/txt/copying/)), modified by BlockMen +* `hbhunger_bgicon.png`—PilzAdam (WTFPL), modified by BlockMen +* `hbhunger_bar.png—Wuzzy` (WTFPL) +* `hbhunger_icon_health_poison.png`—celeron55 ([CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)), modified by BlockMen, modified again by Wuzzy +* Everything else: WTFPL, by BlockMen and Wuzzy + diff --git a/mods/hbhunger/changelog.txt b/mods/hbhunger/changelog.txt new file mode 100644 index 000000000..a56dbcb89 --- /dev/null +++ b/mods/hbhunger/changelog.txt @@ -0,0 +1,51 @@ +0.1.0 +----- +Initial release + +0.2.0 +----- +- Change “saturation” to “satiation” +- Rename global table to “hbhunger” to avoid collisions +- General cleanup + +0.3.0 +----- +- Play simple eating sound when something is eaten + +0.3.1 +----- +- Add Ethereal orange +- Fix exhaus variable + +0.3.2 +----- +- Fix another crash + +0.4.0 +----- +- Generic eating functionality, items using the minetest.item_eat are automatically supported +- Change health bar and icon when poisoned +- Special support for red and brown mushroom from Minetest Game [flowers] +- Special support for [pizza] +- Special support for beans from Farming Redo [farming] +- Fix crash when poisoned player leaves server +- Changed license to LGPL v2.1 + +0.4.1 +----- +- Add foods from Not So Simple Mobs [nssm] + +0.5.0 +----- +- Fix custom sound not working +- Add Portuguese translation + +0.5.1 +----- +- Fix incompability problem with pipeworks mod + +0.5.2 +----- +- Fix mod not working with both intllib and mod security enabled +- Add missing screenshot +- Rewrite README and use Markdown format diff --git a/mods/hbhunger/depends.txt b/mods/hbhunger/depends.txt new file mode 100644 index 000000000..6bd271b34 --- /dev/null +++ b/mods/hbhunger/depends.txt @@ -0,0 +1,32 @@ +hudbars +intllib? +default? +flowers? +animalmaterials? +bucket? +bushes? +bushes_classic? +cooking? +creatures? +docfarming? +dwarves? +ethereal? +farming? +farming_plus? +ferns? +fishing? +fruit? +glooptest? +jkanimals? +jkfarming? +jkwine? +kpgmobs? +mobfcooking? +mobs? +moretrees? +mtfoods? +mush45? +mushroom? +seaplants? +pizza? +nssm? diff --git a/mods/hbhunger/description.txt b/mods/hbhunger/description.txt new file mode 100644 index 000000000..77e6159d5 --- /dev/null +++ b/mods/hbhunger/description.txt @@ -0,0 +1 @@ +Adds a simple hunger meachanic with satiation, food poisoning and different healing. diff --git a/mods/hbhunger/hunger.lua b/mods/hbhunger/hunger.lua new file mode 100644 index 000000000..dce52c06e --- /dev/null +++ b/mods/hbhunger/hunger.lua @@ -0,0 +1,470 @@ +-- Keep these for backwards compatibility +function hbhunger.save_hunger(player) + hbhunger.set_hunger_raw(player) +end +function hbhunger.load_hunger(player) + hbhunger.get_hunger_raw(player) +end + +-- wrapper for minetest.item_eat (this way we make sure other mods can't break this one) +local org_eat = core.do_item_eat +core.do_item_eat = function(hp_change, replace_with_item, itemstack, user, pointed_thing) + local old_itemstack = itemstack + itemstack = hbhunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing) + for _, callback in pairs(core.registered_on_item_eats) do + local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing, old_itemstack) + if result then + return result + end + end + return itemstack +end + +-- food functions +local food = hbhunger.food + +function hbhunger.register_food(name, hunger_change, replace_with_item, poisen, heal, sound) + food[name] = {} + food[name].saturation = hunger_change -- hunger points added + food[name].replace = replace_with_item -- what item is given back after eating + food[name].poisen = poisen -- time its poisening + food[name].healing = heal -- amount of HP + food[name].sound = sound -- special sound that is played when eating +end + +function hbhunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing) + local item = itemstack:get_name() + local def = food[item] + if not def then + def = {} + if type(hp_change) ~= "number" then + hp_change = 1 + core.log("error", "Wrong on_use() definition for item '" .. item .. "'") + end + def.saturation = hp_change * 1.3 + def.replace = replace_with_item + end + local func = hbhunger.item_eat(def.saturation, def.replace, def.poisen, def.healing, def.sound) + return func(itemstack, user, pointed_thing) +end + +-- Poison player +local function poisenp(tick, time, time_left, player) + -- First check if player is still there + if not player:is_player() then + return + end + time_left = time_left + tick + if time_left < time then + minetest.after(tick, poisenp, tick, time, time_left, player) + else + hbhunger.poisonings[player:get_player_name()] = hbhunger.poisonings[player:get_player_name()] - 1 + if hbhunger.poisonings[player:get_player_name()] <= 0 then + -- Reset HUD bar color + hb.change_hudbar(player, "health", nil, nil, "hudbars_icon_health.png", nil, "hudbars_bar_health.png") + end + end + if player:get_hp()-1 > 0 then + player:set_hp(player:get_hp()-1) + end + +end + +function hbhunger.item_eat(hunger_change, replace_with_item, poisen, heal, sound) + return function(itemstack, user, pointed_thing) + if itemstack:take_item() ~= nil and user ~= nil then + local name = user:get_player_name() + local h = tonumber(hbhunger.hunger[name]) + local hp = user:get_hp() + minetest.sound_play({name = sound or "hbhunger_eat_generic", gain = 1}, {pos=user:getpos(), max_hear_distance = 16}) + + -- Saturation + if h < 30 and hunger_change then + h = h + hunger_change + if h > 30 then h = 30 end + hbhunger.hunger[name] = h + hbhunger.set_hunger_raw(user) + end + -- Healing + if hp < 20 and heal then + hp = hp + heal + if hp > 20 then hp = 20 end + user:set_hp(hp) + end + -- Poison + if poisen then + -- Set poison bar + hb.change_hudbar(user, "health", nil, nil, "hbhunger_icon_health_poison.png", nil, "hbhunger_bar_health_poison.png") + hbhunger.poisonings[name] = hbhunger.poisonings[name] + 1 + poisenp(1, poisen, 0, user) + end + + --sound:eat + itemstack:add_item(replace_with_item) + end + return itemstack + end +end + +if minetest.get_modpath("default") ~= nil then + hbhunger.register_food("default:apple", 2) +end +if minetest.get_modpath("flowers") ~= nil then + hbhunger.register_food("flowers:mushroom_brown", 1) + hbhunger.register_food("flowers:mushroom_red", 1, "", 3) +end +if minetest.get_modpath("farming") ~= nil then + hbhunger.register_food("farming:bread", 4) +end + +if minetest.get_modpath("mobs") ~= nil then + if mobs.mod ~= nil and mobs.mod == "redo" then + hbhunger.register_food("mobs:cheese", 4) + hbhunger.register_food("mobs:meat", 8) + hbhunger.register_food("mobs:meat_raw", 4) + hbhunger.register_food("mobs:rat_cooked", 4) + hbhunger.register_food("mobs:honey", 2) + hbhunger.register_food("mobs:pork_raw", 3, "", 3) + hbhunger.register_food("mobs:pork_cooked", 8) + hbhunger.register_food("mobs:chicken_cooked", 6) + hbhunger.register_food("mobs:chicken_raw", 2, "", 3) + hbhunger.register_food("mobs:chicken_egg_fried", 2) + if minetest.get_modpath("bucket") then + hbhunger.register_food("mobs:bucket_milk", 3, "bucket:bucket_empty") + end + else + hbhunger.register_food("mobs:meat", 6) + hbhunger.register_food("mobs:meat_raw", 3) + hbhunger.register_food("mobs:rat_cooked", 5) + end +end + +if minetest.get_modpath("moretrees") ~= nil then + hbhunger.register_food("moretrees:coconut_milk", 1) + hbhunger.register_food("moretrees:raw_coconut", 2) + hbhunger.register_food("moretrees:acorn_muffin", 3) + hbhunger.register_food("moretrees:spruce_nuts", 1) + hbhunger.register_food("moretrees:pine_nuts", 1) + hbhunger.register_food("moretrees:fir_nuts", 1) +end + +if minetest.get_modpath("dwarves") ~= nil then + hbhunger.register_food("dwarves:beer", 2) + hbhunger.register_food("dwarves:apple_cider", 1) + hbhunger.register_food("dwarves:midus", 2) + hbhunger.register_food("dwarves:tequila", 2) + hbhunger.register_food("dwarves:tequila_with_lime", 2) + hbhunger.register_food("dwarves:sake", 2) +end + +if minetest.get_modpath("animalmaterials") ~= nil then + hbhunger.register_food("animalmaterials:milk", 2) + hbhunger.register_food("animalmaterials:meat_raw", 3) + hbhunger.register_food("animalmaterials:meat_pork", 3) + hbhunger.register_food("animalmaterials:meat_beef", 3) + hbhunger.register_food("animalmaterials:meat_chicken", 3) + hbhunger.register_food("animalmaterials:meat_lamb", 3) + hbhunger.register_food("animalmaterials:meat_venison", 3) + hbhunger.register_food("animalmaterials:meat_undead", 3, "", 3) + hbhunger.register_food("animalmaterials:meat_toxic", 3, "", 5) + hbhunger.register_food("animalmaterials:meat_ostrich", 3) + hbhunger.register_food("animalmaterials:fish_bluewhite", 2) + hbhunger.register_food("animalmaterials:fish_clownfish", 2) +end + +if minetest.get_modpath("fishing") ~= nil then + hbhunger.register_food("fishing:fish_raw", 2) + hbhunger.register_food("fishing:fish_cooked", 5) + hbhunger.register_food("fishing:sushi", 6) + hbhunger.register_food("fishing:shark", 4) + hbhunger.register_food("fishing:shark_cooked", 8) + hbhunger.register_food("fishing:pike", 4) + hbhunger.register_food("fishing:pike_cooked", 8) +end + +if minetest.get_modpath("glooptest") ~= nil then + hbhunger.register_food("glooptest:kalite_lump", 1) +end + +if minetest.get_modpath("bushes") ~= nil then + hbhunger.register_food("bushes:sugar", 1) + hbhunger.register_food("bushes:strawberry", 2) + hbhunger.register_food("bushes:berry_pie_raw", 3) + hbhunger.register_food("bushes:berry_pie_cooked", 4) + hbhunger.register_food("bushes:basket_pies", 15) +end + +if minetest.get_modpath("bushes_classic") then + -- bushes_classic mod, as found in the plantlife modpack + local berries = { + "strawberry", + "blackberry", + "blueberry", + "raspberry", + "gooseberry", + "mixed_berry"} + for _, berry in ipairs(berries) do + if berry ~= "mixed_berry" then + hbhunger.register_food("bushes:"..berry, 1) + end + hbhunger.register_food("bushes:"..berry.."_pie_raw", 2) + hbhunger.register_food("bushes:"..berry.."_pie_cooked", 5) + hbhunger.register_food("bushes:basket_"..berry, 15) + end +end + +if minetest.get_modpath("mushroom") ~= nil then + hbhunger.register_food("mushroom:brown", 1) + hbhunger.register_food("mushroom:red", 1, "", 3) + -- mushroom potions: red = strong poison, brown = light restorative + if minetest.get_modpath("vessels") then + hbhunger.register_food("mushroom:brown_essence", 1, "vessels:glass_bottle", nil, 4) + hbhunger.register_food("mushroom:poison", 1, "vessels:glass_bottle", 10) + end +end + +if minetest.get_modpath("docfarming") ~= nil then + hbhunger.register_food("docfarming:carrot", 3) + hbhunger.register_food("docfarming:cucumber", 2) + hbhunger.register_food("docfarming:corn", 3) + hbhunger.register_food("docfarming:potato", 4) + hbhunger.register_food("docfarming:bakedpotato", 5) + hbhunger.register_food("docfarming:raspberry", 3) +end + +if minetest.get_modpath("farming_plus") ~= nil then + hbhunger.register_food("farming_plus:carrot_item", 3) + hbhunger.register_food("farming_plus:banana", 2) + hbhunger.register_food("farming_plus:orange_item", 2) + hbhunger.register_food("farming:pumpkin_bread", 4) + hbhunger.register_food("farming_plus:strawberry_item", 2) + hbhunger.register_food("farming_plus:tomato_item", 2) + hbhunger.register_food("farming_plus:potato_item", 4) + hbhunger.register_food("farming_plus:rhubarb_item", 2) +end + +if minetest.get_modpath("mtfoods") ~= nil then + hbhunger.register_food("mtfoods:dandelion_milk", 1) + hbhunger.register_food("mtfoods:sugar", 1) + hbhunger.register_food("mtfoods:short_bread", 4) + hbhunger.register_food("mtfoods:cream", 1) + hbhunger.register_food("mtfoods:chocolate", 2) + hbhunger.register_food("mtfoods:cupcake", 2) + hbhunger.register_food("mtfoods:strawberry_shortcake", 2) + hbhunger.register_food("mtfoods:cake", 3) + hbhunger.register_food("mtfoods:chocolate_cake", 3) + hbhunger.register_food("mtfoods:carrot_cake", 3) + hbhunger.register_food("mtfoods:pie_crust", 3) + hbhunger.register_food("mtfoods:apple_pie", 3) + hbhunger.register_food("mtfoods:rhubarb_pie", 2) + hbhunger.register_food("mtfoods:banana_pie", 3) + hbhunger.register_food("mtfoods:pumpkin_pie", 3) + hbhunger.register_food("mtfoods:cookies", 2) + hbhunger.register_food("mtfoods:mlt_burger", 5) + hbhunger.register_food("mtfoods:potato_slices", 2) + hbhunger.register_food("mtfoods:potato_chips", 3) + --mtfoods:medicine + hbhunger.register_food("mtfoods:casserole", 3) + hbhunger.register_food("mtfoods:glass_flute", 2) + hbhunger.register_food("mtfoods:orange_juice", 2) + hbhunger.register_food("mtfoods:apple_juice", 2) + hbhunger.register_food("mtfoods:apple_cider", 2) + hbhunger.register_food("mtfoods:cider_rack", 2) +end + +if minetest.get_modpath("fruit") ~= nil then + hbhunger.register_food("fruit:apple", 2) + hbhunger.register_food("fruit:pear", 2) + hbhunger.register_food("fruit:bananna", 3) + hbhunger.register_food("fruit:orange", 2) +end + +if minetest.get_modpath("mush45") ~= nil then + hbhunger.register_food("mush45:meal", 4) +end + +if minetest.get_modpath("seaplants") ~= nil then + hbhunger.register_food("seaplants:kelpgreen", 1) + hbhunger.register_food("seaplants:kelpbrown", 1) + hbhunger.register_food("seaplants:seagrassgreen", 1) + hbhunger.register_food("seaplants:seagrassred", 1) + hbhunger.register_food("seaplants:seasaladmix", 6) + hbhunger.register_food("seaplants:kelpgreensalad", 1) + hbhunger.register_food("seaplants:kelpbrownsalad", 1) + hbhunger.register_food("seaplants:seagrassgreensalad", 1) + hbhunger.register_food("seaplants:seagrassgreensalad", 1) +end + +if minetest.get_modpath("mobfcooking") ~= nil then + hbhunger.register_food("mobfcooking:cooked_pork", 6) + hbhunger.register_food("mobfcooking:cooked_ostrich", 6) + hbhunger.register_food("mobfcooking:cooked_beef", 6) + hbhunger.register_food("mobfcooking:cooked_chicken", 6) + hbhunger.register_food("mobfcooking:cooked_lamb", 6) + hbhunger.register_food("mobfcooking:cooked_venison", 6) + hbhunger.register_food("mobfcooking:cooked_fish", 6) +end + +if minetest.get_modpath("creatures") ~= nil then + hbhunger.register_food("creatures:meat", 6) + hbhunger.register_food("creatures:flesh", 3) + hbhunger.register_food("creatures:rotten_flesh", 3, "", 3) +end + +if minetest.get_modpath("ethereal") then + hbhunger.register_food("ethereal:strawberry", 1) + hbhunger.register_food("ethereal:banana", 4) + hbhunger.register_food("ethereal:pine_nuts", 1) + hbhunger.register_food("ethereal:bamboo_sprout", 0, "", 3) + hbhunger.register_food("ethereal:fern_tubers", 1) + hbhunger.register_food("ethereal:banana_bread", 7) + hbhunger.register_food("ethereal:mushroom_plant", 2) + hbhunger.register_food("ethereal:coconut_slice", 2) + hbhunger.register_food("ethereal:golden_apple", 4, "", nil, 10) + hbhunger.register_food("ethereal:wild_onion_plant", 2) + hbhunger.register_food("ethereal:mushroom_soup", 4, "ethereal:bowl") + hbhunger.register_food("ethereal:mushroom_soup_cooked", 6, "ethereal:bowl") + hbhunger.register_food("ethereal:hearty_stew", 6, "ethereal:bowl", 3) + hbhunger.register_food("ethereal:hearty_stew_cooked", 10, "ethereal:bowl") + if minetest.get_modpath("bucket") then + hbhunger.register_food("ethereal:bucket_cactus", 2, "bucket:bucket_empty") + end + hbhunger.register_food("ethereal:fish_raw", 2) + hbhunger.register_food("ethereal:fish_cooked", 5) + hbhunger.register_food("ethereal:seaweed", 1) + hbhunger.register_food("ethereal:yellowleaves", 1, "", nil, 1) + hbhunger.register_food("ethereal:sashimi", 4) + hbhunger.register_food("ethereal:orange", 2) +end + +if minetest.get_modpath("farming") and farming.mod == "redo" then + hbhunger.register_food("farming:bread", 6) + hbhunger.register_food("farming:potato", 1) + hbhunger.register_food("farming:baked_potato", 6) + hbhunger.register_food("farming:cucumber", 4) + hbhunger.register_food("farming:tomato", 4) + hbhunger.register_food("farming:carrot", 3) + hbhunger.register_food("farming:carrot_gold", 6, "", nil, 8) + hbhunger.register_food("farming:corn", 3) + hbhunger.register_food("farming:corn_cob", 5) + hbhunger.register_food("farming:melon_slice", 2) + hbhunger.register_food("farming:pumpkin_slice", 1) + hbhunger.register_food("farming:pumpkin_bread", 9) + hbhunger.register_food("farming:coffee_cup", 2, "farming:drinking_cup") + hbhunger.register_food("farming:coffee_cup_hot", 3, "farming:drinking_cup", nil, 2) + hbhunger.register_food("farming:cookie", 2) + hbhunger.register_food("farming:chocolate_dark", 3) + hbhunger.register_food("farming:donut", 4) + hbhunger.register_food("farming:donut_chocolate", 6) + hbhunger.register_food("farming:donut_apple", 6) + hbhunger.register_food("farming:raspberries", 1) + hbhunger.register_food("farming:blueberries", 1) + hbhunger.register_food("farming:muffin_blueberry", 4) + if minetest.get_modpath("vessels") then + hbhunger.register_food("farming:smoothie_raspberry", 2, "vessels:drinking_glass") + end + hbhunger.register_food("farming:rhubarb", 1) + hbhunger.register_food("farming:rhubarb_pie", 6) + hbhunger.register_food("farming:beans", 1) +end + +if minetest.get_modpath("kpgmobs") ~= nil then + hbhunger.register_food("kpgmobs:uley", 3) + hbhunger.register_food("kpgmobs:meat", 6) + hbhunger.register_food("kpgmobs:rat_cooked", 5) + hbhunger.register_food("kpgmobs:med_cooked", 4) + if minetest.get_modpath("bucket") then + hbhunger.register_food("kpgmobs:bucket_milk", 4, "bucket:bucket_empty") + end +end + +if minetest.get_modpath("jkfarming") ~= nil then + hbhunger.register_food("jkfarming:carrot", 3) + hbhunger.register_food("jkfarming:corn", 3) + hbhunger.register_food("jkfarming:melon_part", 2) + hbhunger.register_food("jkfarming:cake", 3) +end + +if minetest.get_modpath("jkanimals") ~= nil then + hbhunger.register_food("jkanimals:meat", 6) +end + +if minetest.get_modpath("jkwine") ~= nil then + hbhunger.register_food("jkwine:grapes", 2) + hbhunger.register_food("jkwine:winebottle", 1) +end + +if minetest.get_modpath("cooking") ~= nil then + hbhunger.register_food("cooking:meat_beef_cooked", 4) + hbhunger.register_food("cooking:fish_bluewhite_cooked", 3) + hbhunger.register_food("cooking:fish_clownfish_cooked", 1) + hbhunger.register_food("cooking:meat_chicken_cooked", 2) + hbhunger.register_food("cooking:meat_cooked", 2) + hbhunger.register_food("cooking:meat_pork_cooked", 3) + hbhunger.register_food("cooking:meat_toxic_cooked", -3) + hbhunger.register_food("cooking:meat_venison_cooked", 3) + hbhunger.register_food("cooking:meat_undead_cooked", 1) +end + +-- ferns mod of plantlife_modpack +if minetest.get_modpath("ferns") ~= nil then + hbhunger.register_food("ferns:fiddlehead", 1, "", 1) + hbhunger.register_food("ferns:fiddlehead_roasted", 3) + hbhunger.register_food("ferns:ferntuber_roasted", 3) + hbhunger.register_food("ferns:horsetail_01", 1) +end + +if minetest.get_modpath("pizza") ~= nil then + hbhunger.register_food("pizza:pizza", 30, "", nil, 30) + hbhunger.register_food("pizza:pizzaslice", 5, "", nil, 5) +end + +if minetest.get_modpath("nssm") then + hbhunger.register_food("nssm:werewolf_leg", 3) + hbhunger.register_food("nssm:heron_leg", 2) + hbhunger.register_food("nssm:chichibios_heron_leg", 4) + hbhunger.register_food("nssm:crocodile_tail", 3) + hbhunger.register_food("nssm:duck_legs", 1) + hbhunger.register_food("nssm:ant_leg", 1) + hbhunger.register_food("nssm:spider_leg", 1) + hbhunger.register_food("nssm:tentacle", 2) + hbhunger.register_food("nssm:worm_flesh", 2, "", 2) -- poisonous + hbhunger.register_food("nssm:amphibian_heart", 1) + hbhunger.register_food("nssm:raw_scrausics_wing", 1) + -- superfoods + hbhunger.register_food("nssm:phoenix_nuggets", 20, "", nil, 20) + hbhunger.register_food("nssm:phoenix_tear", 20, "", nil, 20) +end + +-- player-action based hunger changes +function hbhunger.handle_node_actions(pos, oldnode, player, ext) + -- is_fake_player comes from the pipeworks, we are not interested in those + if not player or not player:is_player() or player.is_fake_player == true then + return + end + local name = player:get_player_name() + local exhaus = hbhunger.exhaustion[name] + if exhaus == nil then return end + local new = hbhunger.EXHAUST_PLACE + -- placenode event + if not ext then + new = hbhunger.EXHAUST_DIG + end + -- assume its send by main timer when movement detected + if not pos and not oldnode then + new = hbhunger.EXHAUST_MOVE + end + exhaus = exhaus + new + if exhaus > hbhunger.EXHAUST_LVL then + exhaus = 0 + local h = tonumber(hbhunger.hunger[name]) + h = h - 1 + if h < 0 then h = 0 end + hbhunger.hunger[name] = h + hbhunger.set_hunger_raw(player) + end + hbhunger.exhaustion[name] = exhaus +end + +minetest.register_on_placenode(hbhunger.handle_node_actions) +minetest.register_on_dignode(hbhunger.handle_node_actions) diff --git a/mods/hbhunger/init.lua b/mods/hbhunger/init.lua new file mode 100644 index 000000000..0a9a72222 --- /dev/null +++ b/mods/hbhunger/init.lua @@ -0,0 +1,155 @@ +local S +if (minetest.get_modpath("intllib")) then + S = intllib.Getter() +else + S = function ( s ) return s end +end + +if minetest.setting_getbool("enable_damage") then + +hbhunger = {} +hbhunger.food = {} + +-- HUD statbar values +hbhunger.hunger = {} +hbhunger.hunger_out = {} + +-- Count number of poisonings a player has at once +hbhunger.poisonings = {} + +-- HUD item ids +local hunger_hud = {} + +hbhunger.HUD_TICK = 0.1 + +--Some hunger settings +hbhunger.exhaustion = {} -- Exhaustion is experimental! + +hbhunger.HUNGER_TICK = 800 -- time in seconds after that 1 hunger point is taken +hbhunger.EXHAUST_DIG = 3 -- exhaustion increased this value after digged node +hbhunger.EXHAUST_PLACE = 1 -- exhaustion increased this value after placed +hbhunger.EXHAUST_MOVE = 0.3 -- exhaustion increased this value if player movement detected +hbhunger.EXHAUST_LVL = 160 -- at what exhaustion player satiation gets lowerd + + +--load custom settings +local set = io.open(minetest.get_modpath("hbhunger").."/hbhunger.conf", "r") +if set then + dofile(minetest.get_modpath("hbhunger").."/hbhunger.conf") + set:close() +end + +local function custom_hud(player) + hb.init_hudbar(player, "satiation", hbhunger.get_hunger_raw(player)) +end + +dofile(minetest.get_modpath("hbhunger").."/hunger.lua") + +-- register satiation hudbar +hb.register_hudbar("satiation", 0xFFFFFF, S("Satiation"), { icon = "hbhunger_icon.png", bgicon = "hbhunger_bgicon.png", bar = "hbhunger_bar.png" }, 20, 30, false) + +-- update hud elemtens if value has changed +local function update_hud(player) + local name = player:get_player_name() + --hunger + local h_out = tonumber(hbhunger.hunger_out[name]) + local h = tonumber(hbhunger.hunger[name]) + if h_out ~= h then + hbhunger.hunger_out[name] = h + hb.change_hudbar(player, "satiation", h) + end +end + +hbhunger.get_hunger_raw = function(player) + local inv = player:get_inventory() + if not inv then return nil end + local hgp = inv:get_stack("hunger", 1):get_count() + if hgp == 0 then + hgp = 21 + inv:set_stack("hunger", 1, ItemStack({name=":", count=hgp})) + else + hgp = hgp + end + return hgp-1 +end + +hbhunger.set_hunger_raw = function(player) + local inv = player:get_inventory() + local name = player:get_player_name() + local value = hbhunger.hunger[name] + if not inv or not value then return nil end + if value > 30 then value = 30 end + if value < 0 then value = 0 end + + inv:set_stack("hunger", 1, ItemStack({name=":", count=value+1})) + + return true +end + +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + local inv = player:get_inventory() + inv:set_size("hunger",1) + hbhunger.hunger[name] = hbhunger.get_hunger_raw(player) + hbhunger.hunger_out[name] = hbhunger.hunger[name] + hbhunger.exhaustion[name] = 0 + hbhunger.poisonings[name] = 0 + custom_hud(player) + hbhunger.set_hunger_raw(player) +end) + +minetest.register_on_respawnplayer(function(player) + -- reset hunger (and save) + local name = player:get_player_name() + hbhunger.hunger[name] = 20 + hbhunger.set_hunger_raw(player) + hbhunger.exhaustion[name] = 0 +end) + +local main_timer = 0 +local timer = 0 +local timer2 = 0 +minetest.register_globalstep(function(dtime) + main_timer = main_timer + dtime + timer = timer + dtime + timer2 = timer2 + dtime + if main_timer > hbhunger.HUD_TICK or timer > 4 or timer2 > hbhunger.HUNGER_TICK then + if main_timer > hbhunger.HUD_TICK then main_timer = 0 end + for _,player in ipairs(minetest.get_connected_players()) do + local name = player:get_player_name() + + local h = tonumber(hbhunger.hunger[name]) + local hp = player:get_hp() + if timer > 4 then + -- heal player by 1 hp if not dead and satiation is > 15 (of 30) + if h > 15 and hp > 0 and player:get_breath() > 0 then + player:set_hp(hp+1) + -- or damage player by 1 hp if satiation is < 2 (of 30) + elseif h <= 1 then + if hp-1 >= 0 then player:set_hp(hp-1) end + end + end + -- lower satiation by 1 point after xx seconds + if timer2 > hbhunger.HUNGER_TICK then + if h > 0 then + h = h-1 + hbhunger.hunger[name] = h + hbhunger.set_hunger_raw(player) + end + end + + -- update all hud elements + update_hud(player) + + local controls = player:get_player_control() + -- Determine if the player is walking + if controls.up or controls.down or controls.left or controls.right then + hbhunger.handle_node_actions(nil, nil, player) + end + end + end + if timer > 4 then timer = 0 end + if timer2 > hbhunger.HUNGER_TICK then timer2 = 0 end +end) + +end diff --git a/mods/hbhunger/locale/de.txt b/mods/hbhunger/locale/de.txt new file mode 100644 index 000000000..3a06d93f4 --- /dev/null +++ b/mods/hbhunger/locale/de.txt @@ -0,0 +1 @@ +Satiation = Sättigung diff --git a/mods/hbhunger/locale/pt.txt b/mods/hbhunger/locale/pt.txt new file mode 100644 index 000000000..44fe45217 --- /dev/null +++ b/mods/hbhunger/locale/pt.txt @@ -0,0 +1 @@ +Satiation = Saciedade diff --git a/mods/hbhunger/locale/template.txt b/mods/hbhunger/locale/template.txt new file mode 100644 index 000000000..37a578dcd --- /dev/null +++ b/mods/hbhunger/locale/template.txt @@ -0,0 +1 @@ +Satiation diff --git a/mods/hbhunger/mod.conf b/mods/hbhunger/mod.conf new file mode 100644 index 000000000..dc67cd6e9 --- /dev/null +++ b/mods/hbhunger/mod.conf @@ -0,0 +1 @@ +name = hbhunger diff --git a/mods/hbhunger/screenshot.png b/mods/hbhunger/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..5af6583667df4ff97d008c7b503a307616773244 GIT binary patch literal 8498 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 literal 0 HcmV?d00001 diff --git a/mods/hud/textures/hud_hunger_bg.png b/mods/hbhunger/textures/hbhunger_bgicon.png similarity index 100% rename from mods/hud/textures/hud_hunger_bg.png rename to mods/hbhunger/textures/hbhunger_bgicon.png diff --git a/mods/hud/textures/hud_hunger_fg.png b/mods/hbhunger/textures/hbhunger_icon.png similarity index 100% rename from mods/hud/textures/hud_hunger_fg.png rename to mods/hbhunger/textures/hbhunger_icon.png diff --git a/mods/hbhunger/textures/hbhunger_icon_health_poison.png b/mods/hbhunger/textures/hbhunger_icon_health_poison.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce2db8d3f4c0b6e713351bc8851b1705592a7b4 GIT binary patch literal 526 zcmV+p0`dKcP)Px#24YJ`L;zF(Q~*>nW5M+R000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jB<= z4G|!{QJPu+00E9kL_t(I%f*v1ZxcZfg}+%lXOdHLDJW172~a|s6hY}|k>F2I&{(+S zS5PAOC6??q1w~?^5Xnu7C^1SLoEQ>=kMqr)cPUP1V&x!33SPClnwfoX-i$csxCsn5 zL^(ffuD;>L`Uhux0l~}kf5wD<$HgqiP2S`Qm#b>E>msvB1cwmS2 zdKc=gszkjAA|Z4k-SIJ@3$X)-i~m@i9*nW)u2{m^$8Rj(xyP@KA?n50fkO`!GGlNG z=B8~^|S literal 0 HcmV?d00001 diff --git a/mods/hud/README.txt b/mods/hud/README.txt deleted file mode 100644 index e39db8ec8..000000000 --- a/mods/hud/README.txt +++ /dev/null @@ -1,49 +0,0 @@ -Minetest mod "Better HUD" -========================= -version: 1.1 - -License of source code: WTFPL ------------------------------ -(c) Copyright BlockMen (2013) - - -This program is free software. It comes without any warranty, to -the extent permitted by applicable law. You can redistribute it -and/or modify it under the terms of the Do What The Fuck You Want -To Public License, Version 2, as published by Sam Hocevar. See -http://sam.zoy.org/wtfpl/COPYING for more details. - - -Using the mod: --------------- - -This mod changes the HUD of Minetest. -It improves the apperance of the health and breath bar and adds a more fancy hotbar. Furthermore it adds a -costum crosshair, an armor bar (only for 3darmor mod) and a hunger bar. It includes also a mechanic for hunger. - - -You can create a "hud.conf" to costumize the positions of health, hunger, armor and breath bar. Take a look at "hud.conf.example" to get more infos. - -!!NOTICE: Keep in mind if running a server with this mod, that the costum position should be displayed correct on every screen size!! - - -Hunger: -This mod adds hunger to the game. You can disable this by setting "HUD_HUNGER_ENABLE = false" in "hud.conf", or "hud_hunger_enable = false" in minetest.conf. In case of conflict hud.conf configuration is dominant. - -Currently supported food: -- Apples (default) -- Bread (default) -- Drawves (beer and such) -- Mooretrees -- Simple mobs -- Animalmaterials (mobf modpack) -- Fishing -- Glooptest -- Bushes -- Docfarming -- Farming plus -- Mtfoods - -Example: 1 apple fills up the hunger bar by 1 bread, 1 bread (from farming) 2 breads in bar. - -Altough it show 20 hunger points (10 breads) in hunger bar you can fill it up to 30 points. (5 breads not shown then) diff --git a/mods/hud/armor.lua b/mods/hud/armor.lua deleted file mode 100644 index 2030c423d..000000000 --- a/mods/hud/armor.lua +++ /dev/null @@ -1,31 +0,0 @@ -minetest.after(0, function() - if not armor.def then - minetest.after(2,minetest.chat_send_all,"#Better HUD: Please update your version of 3darmor") - HUD_SHOW_ARMOR = false - end -end) - -function hud.get_armor(player) - if not player or not armor.def then - return - end - local name = player:get_player_name() - hud.set_armor(player, armor.def[name].state, armor.def[name].count) -end - -function hud.set_armor(player, ges_state, items) - if not player then return end - - local max_items = 4 - if items == 5 then max_items = items end - local max = max_items*65535 - local lvl = max - ges_state - lvl = lvl/max - if ges_state == 0 and items == 0 then - lvl = 0 - end - - hud.armor[player:get_player_name()] = lvl*(items*(20/max_items)) - - -end \ No newline at end of file diff --git a/mods/hud/changelog.txt b/mods/hud/changelog.txt deleted file mode 100644 index 50b024cef..000000000 --- a/mods/hud/changelog.txt +++ /dev/null @@ -1,47 +0,0 @@ -0.2 Beta --------- -- added support of costum config files -- you can eat max. 50% more than before (although it isnt shown in hunger bar) -- you get healed with 8 breads and more (in hunger bar) now -- a bread (from farming) == 2 breads in hunger bar - -0.2.1 Beta ----------- -- tweaked override of food -- added support for food of dwares, moretrees and simple mobs - -0.2.2 Beta ----------- -- added support for food of animalmaterials (mobf modpack),fishing - -0.2.3 Beta ----------- -- added support for food of glooptest and bushes (commit by CheeseKeg) - -0.3 Beta ----------- -- added fancy borders of hud inventory bar (only for screenheight <= 800) - -0.4 Beta ----------- -- enabled drowning - -0.5 Beta ----------- -- removed the fancy borders of hud inventory bar and moved to new native support -- moved crosshair to native support too - -1.0 ---- -- hunger is reset after death -- health and hunger bar is shown correct on all screen resolutions now -- switched to changed native hotbar image support -- fixed revival of player when drown -- hunger bar is not shown anymore if hunger is disabled -- hunger can be disabled by minetest.conf ("hud_hunger_enable = false") - -1.1 ---- -- added support for stu's 3darmor mod -- restructured and cleaned up code -- added support for poisen food (damages player, but does not kill) diff --git a/mods/hud/depends.txt b/mods/hud/depends.txt deleted file mode 100644 index 331d858ce..000000000 --- a/mods/hud/depends.txt +++ /dev/null @@ -1 +0,0 @@ -default \ No newline at end of file diff --git a/mods/hud/hud.conf.example b/mods/hud/hud.conf.example deleted file mode 100644 index ffa4cd761..000000000 --- a/mods/hud/hud.conf.example +++ /dev/null @@ -1,33 +0,0 @@ ---##Better HUD example config file## ------------------------------------- --- This example moves the health bar in the top left corner and the hunger bar in the top right corner - - --- --- general settings --- -HUD_ENABLE_HUNGER = true --enables/disables hunger -HUD_HUNGER_TICK = 300 --sets time for loosing 1/2 bread (of 10) (in seconds) - - ---!NOTICE!-- --- >>if damage is disabled neither health bar nor hunger bar or breath bar is shown - --- --- health bar --- -HUD_HEALTH_POS = {x=0,y=0} --min 0, max 1 -HUD_HEALTH_OFFSET = {x=5,y=30} --offset in pixel - --- --- hunger bar --- -HUD_HUNGER_POS = {x=1,y=0} --min 0, max 1 -HUD_HUNGER_OFFSET = {x=-175,y=30} --offset in pixel - --- --- breath bar --- -HUD_AIR_POS = {x=0.5,y=1} --min 0, max 1 -HUD_AIR_OFFSET = {x=15,y=-75} --offset in pixel - diff --git a/mods/hud/hunger.lua b/mods/hud/hunger.lua deleted file mode 100644 index 071bcf4f2..000000000 --- a/mods/hud/hunger.lua +++ /dev/null @@ -1,68 +0,0 @@ -function hud.save_hunger(player) - local file = io.open(minetest.get_worldpath().."/hud_"..player:get_player_name().."_hunger", "w+") - if file then - file:write(hud.hunger[player:get_player_name()]) - file:close() - end -end - -function hud.load_hunger(player) - local file = io.open(minetest.get_worldpath().."/hud_"..player:get_player_name().."_hunger", "r") - if file then - hud.hunger[player:get_player_name()] = file:read("*all") - file:close() - return hud.hunger[player:get_player_name()] - else - return - end - -end - -local function poisenp(tick, time, time_left, player) - time_left = time_left + tick - if time_left < time then - minetest.after(tick, poisenp, tick, time, time_left, player) - end - if player:get_hp()-1 > 0 then - player:set_hp(player:get_hp()-1) - end - -end - -function hud.item_eat(hunger_change, replace_with_item, poisen) - return function(itemstack, user, pointed_thing) - if itemstack:take_item() ~= nil then - local h = tonumber(hud.hunger[user:get_player_name()]) - h=h+hunger_change - if h>30 then h=30 end - hud.hunger[user:get_player_name()]=h - hud.save_hunger(user) - itemstack:add_item(replace_with_item) -- note: replace_with_item is optional - --sound:eat - if poisen then - poisenp(1.0, poisen, 0, user) - end - end - return itemstack - end -end - -local function overwrite(name, hunger_change, replace_with_item, poisen) - local tab = minetest.registered_items[name] - if tab == nil then return end - tab.on_use = hud.item_eat(hunger_change, replace_with_item, poisen) - minetest.registered_items[name] = tab -end - -minetest.after(0.5, function()--ensure all other mods get loaded -overwrite("default:fish_raw", 2) -overwrite("default:fish", 4) -overwrite("default:apple", 4) -overwrite("default:apple_gold", 8) -overwrite("farming:carrot_item", 1) -overwrite("farming:carrot_item_gold", 3) -overwrite("farming:potatoe_item", 2) -overwrite("farming:potatoe_item_baked", 2) -overwrite("farming:potatoe_item_poison", 2, nil, 1) -overwrite("farming:bread", 6) -end) diff --git a/mods/hud/init.lua b/mods/hud/init.lua deleted file mode 100644 index a0566d650..000000000 --- a/mods/hud/init.lua +++ /dev/null @@ -1,215 +0,0 @@ -hud = {} - -local health_hud = {} -hud.hunger = {} -local hunger_hud = {} -local air_hud = {} -hud.armor = {} -local armor_hud = {} - -local SAVE_INTERVAL = 0.5*60--currently useless - ---default settings -HUD_ENABLE_HUNGER = minetest.setting_getbool("hud_hunger_enable") -HUD_SHOW_ARMOR = false -if minetest.get_modpath("3d_armor") ~= nil then HUD_SHOW_ARMOR = true end -if HUD_ENABLE_HUNGER == nil then HUD_ENABLE_HUNGER = minetest.setting_getbool("enable_damage") end -HUD_HUNGER_TICK = 300 -HUD_HEALTH_POS = {x=0.5,y=0.89} -HUD_HEALTH_OFFSET = {x=-175, y=2} -HUD_HUNGER_POS = {x=0.5,y=0.89} -HUD_HUNGER_OFFSET = {x=15, y=2} -HUD_AIR_POS = {x=0.5,y=0.88} -HUD_AIR_OFFSET = {x=15,y=-15} -HUD_ARMOR_POS = {x=0.5,y=.88} -HUD_ARMOR_OFFSET = {x=-175, y=-15} - ---load costum settings -local set = io.open(minetest.get_modpath("hud").."/hud.conf", "r") -if set then - dofile(minetest.get_modpath("hud").."/hud.conf") - set:close() -else - if not HUD_ENABLE_HUNGER then - HUD_AIR_OFFSET = {x=15,y=0} - end -end - ---minetest.after(SAVE_INTERVAL, timer, SAVE_INTERVAL) - -local function hide_builtin(player) - player:hud_set_flags({crosshair = true, hotbar = true, healthbar = false, wielditem = true, breathbar = false}) -end - - -local function costum_hud(player) - - --fancy hotbar - --player:hud_set_hotbar_image("hud_hotbar.png") - --player:hud_set_hotbar_selected_image("hud_hotbar_selected.png") - - if minetest.setting_getbool("enable_damage") then - --hunger - if HUD_ENABLE_HUNGER then - player:hud_add({ - hud_elem_type = "statbar", - position = HUD_HUNGER_POS, - scale = {x=1, y=1}, - text = "hud_hunger_bg.png", - number = 20, - alignment = {x=-1,y=-1}, - offset = HUD_HUNGER_OFFSET, - }) - - hunger_hud[player:get_player_name()] = player:hud_add({ - hud_elem_type = "statbar", - position = HUD_HUNGER_POS, - scale = {x=1, y=1}, - text = "hud_hunger_fg.png", - number = 20, - alignment = {x=-1,y=-1}, - offset = HUD_HUNGER_OFFSET, - }) - end - --health - player:hud_add({ - hud_elem_type = "statbar", - position = HUD_HEALTH_POS, - scale = {x=1, y=1}, - text = "hud_heart_bg.png", - number = 20, - alignment = {x=-1,y=-1}, - offset = HUD_HEALTH_OFFSET, - }) - - health_hud[player:get_player_name()] = player:hud_add({ - hud_elem_type = "statbar", - position = HUD_HEALTH_POS, - scale = {x=1, y=1}, - text = "hud_heart_fg.png", - number = player:get_hp(), - alignment = {x=-1,y=-1}, - offset = HUD_HEALTH_OFFSET, - }) - - --air - air_hud[player:get_player_name()] = player:hud_add({ - hud_elem_type = "statbar", - position = HUD_AIR_POS, - scale = {x=1, y=1}, - text = "hud_air_fg.png", - number = 0, - alignment = {x=-1,y=-1}, - offset = HUD_AIR_OFFSET, - }) - - --armor - if HUD_SHOW_ARMOR then - player:hud_add({ - hud_elem_type = "statbar", - position = HUD_ARMOR_POS, - scale = {x=1, y=1}, - text = "hud_armor_bg.png", - number = 20, - alignment = {x=-1,y=-1}, - offset = HUD_ARMOR_OFFSET, - }) - - armor_hud[player:get_player_name()] = player:hud_add({ - hud_elem_type = "statbar", - position = HUD_ARMOR_POS, - scale = {x=1, y=1}, - text = "hud_armor_fg.png", - number = 0, - alignment = {x=-1,y=-1}, - offset = HUD_ARMOR_OFFSET, - }) - end - end - -end - ---needs to be set always(for 3darmor) -function hud.set_armor() -end - - -if HUD_ENABLE_HUNGER then dofile(minetest.get_modpath("hud").."/hunger.lua") end -if HUD_SHOW_ARMOR then dofile(minetest.get_modpath("hud").."/armor.lua") end - - -local function update_hud(player) - --air - local air = player:get_breath()*2 - if player:get_breath() > 10 then air = 0 end - player:hud_change(air_hud[player:get_player_name()], "number", air) - --health - player:hud_change(health_hud[player:get_player_name()], "number", player:get_hp()) - --armor - local arm = tonumber(hud.armor[player:get_player_name()]) - if not arm then arm = 0 end - player:hud_change(armor_hud[player:get_player_name()], "number", arm) - --hunger - local h = tonumber(hud.hunger[player:get_player_name()]) - if h>20 then h=20 end - player:hud_change(hunger_hud[player:get_player_name()], "number", h) -end - -local function timer(interval, player) - if interval > 0 then - hud.save_hunger(player) - minetest.after(interval, timer, interval, player) - end -end - -minetest.register_on_joinplayer(function(player) - hud.armor[player:get_player_name()] = 0 - if HUD_ENABLE_HUNGER then hud.hunger[player:get_player_name()] = hud.load_hunger(player) end - if not hud.hunger[player:get_player_name()] then - hud.hunger[player:get_player_name()] = 20 - end - minetest.after(0.5, function() - hide_builtin(player) - costum_hud(player) - if HUD_ENABLE_HUNGER then hud.save_hunger(player) end - end) -end) - -minetest.register_on_respawnplayer(function(player) - hud.hunger[player:get_player_name()] = 20 - minetest.after(0.5, function() - if HUD_ENABLE_HUNGER then hud.save_hunger(player) end - end) -end) - -local timer = 0 -local timer2 = 0 -minetest.after(2.5, function() - minetest.register_globalstep(function(dtime) - timer = timer + dtime - timer2 = timer2 + dtime - for _,player in ipairs(minetest.get_connected_players()) do - if minetest.setting_getbool("enable_damage") then - local h = tonumber(hud.hunger[player:get_player_name()]) - if HUD_ENABLE_HUNGER and timer > 4 then - if h>=16 and player:get_hp() > 0 then - player:set_hp(player:get_hp()+1) - elseif h<=1 and minetest.setting_getbool("enable_damage") then - if player:get_hp()-1 >= 1 then player:set_hp(player:get_hp()-1) end - end - end - if HUD_ENABLE_HUNGER and timer2>HUD_HUNGER_TICK then - if h>0 then - h=h-1 - hud.hunger[player:get_player_name()]=h - hud.save_hunger(player) - end - end - if HUD_SHOW_ARMOR then hud.get_armor(player) end - update_hud(player) - end - end - if timer>4 then timer=0 end - if timer2>HUD_HUNGER_TICK then timer2=0 end - end) -end) diff --git a/mods/hudbars/API.md b/mods/hudbars/API.md new file mode 100644 index 000000000..124da82cf --- /dev/null +++ b/mods/hudbars/API.md @@ -0,0 +1,193 @@ +API documentation for the HUD bars mod 1.7.0 +============================================ + +## Introduction +This API allows you to add, change, hide and unhide custom HUD bars for this mod. + +## Overview +To give you a *very* brief overview over this API, here is the basic workflow on how to add your own custom HUD bar: + +* Create images for your HUD bar +* Call `hb.register_hudbar` to make the definition of the HUD bar known to this mod +* Call `hb.init_hudbar` for each player for which you want to use previously defined HUD bar +* Use `hb.change_hudbar` whenever you need to change the values of a HUD bar of a certain player +* If you need it: Use `hb.hide_hudbar` and `hb.unhide_hudbar` to hide or unhide HUD bars of a certain player + +## The basic rules +In order to use this API, you should be aware of a few basic rules in order to understand it: + +* A HUD bar is an approximate graphical representation of the ratio of a current value and a maximum value, i.e. current health of 15 and maximum health of 20. A full HUD bar represents 100%, an empty HUD bar represents 0%. +* The current value must always be equal to or smaller then the maximum +* Both current value and maximum must not be smaller than 0 +* Both current value and maximum must be real numbers. So no NaN, infinity, etc. +* The HUD bar will be hidden if the maximum equals 0. This is intentional. +* The health and breath HUD bars are hardcoded. + +These are soft rules, the HUD bars mod will not enforce all of these. +But this mod has been programmed under the assumption that these rules are followed, for integrity. + +## Adding a HUD bar +To make a new HUD bar known to this mod, you need … + +* … an image of size 2×16 for the bar +* … an icon of size 16×16 (optional) +* … to register it with `hb.register_hudbar` + +### Bar image +The image for the bar will be repeated horizontally to denote the “value” of the HUD bar. +It **must** be of size 2×16. +If neccessary, the image will be split vertically in half, and only the left half of the image +is displayed. So the final HUD bar will always be displayed on a per-pixel basis. + +The default bar images are single-colored, but you can use other styles as well, for instance, +a vertical gradient. + +### Icon +A 16×16 image shown left of the HUD bar. This is optional. + +### `hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string)` +This function registers a new custom HUD bar definition to the HUD bars mod, so it can be later used to be displayed, changed, hidden +and unhidden on a per-player basis. +Note this does not yet display the HUD bar. + +The HUD bars will be displayed in a “first come, first serve” order. This API does not allow fow a custom order or a way to set it +manually in a reliable way. However, you can use the setting `hudbars_sorting` for this. See the advanced setting menu in Minetest +for more information. + + +#### Parameters +* `identifier`: A globally unique internal name for the HUD bar, will be used later to refer to it. Please only rely on alphanumeric characters for now. The identifiers “`health`” and “`breath`” are used internally for the built-in health and breath bar, respectively. Please do not use these names. +* `text_color`: A 3-octet number defining the color of the text. The octets denote, in this order red, green and blue and range from `0x00` (complete lack of this component) to `0xFF` (full intensity of this component). Example: `0xFFFFFF` for white. +* `label`: A string which is displayed on the HUD bar itself to describe the HUD bar. Try to keep this string short. +* `textures`: A table with the following fields: + * `bar`: The file name of the bar image (as string). This is only used for the `progress_bar` bar type (see `README.txt`, settings section). + * `icon`: The file name of the icon, as string. For the `progress_bar` type, it is shown as single image left of the bar, for the two statbar bar types, it is used as the statbar icon and will be repeated. This field can be `nil`, in which case no icon will be used, but this is not recommended, because the HUD bar will be invisible if the one of the statbar bar types is used. + * `bgicon`: The file name of the background icon, it is used as the background for the modern statbar mode only. This field can be `nil`, in which case no background icon will be displayed in this mode. +* `default_start_value`: If this HUD bar is added to a player, and no initial value is specified, this value will be used as initial current value +* `default_max_value`: If this HUD bar is added to a player, and no initial maximum value is specified, this value will be used as initial maximum value +* `default_start_hidden`: The HUD bar will be initially start hidden by default when added to a player. Use `hb.unhide_hudbar` to unhide it. +* `format_string`: This is optional; You can specify an alternative format string display the final text on the HUD bar. The default format string is “`%s: %d/%d`” (in this order: Label, current value, maximum value). See also the Lua documentation of `string.format`. + +#### Return value +Always `nil`. + + +## Displaying a HUD bar +After a HUD bar has been registered, they are not yet displayed yet for any player. HUD bars must be +explicitly initialized on a per-player basis. + +You probably want to do this in the `minetest.register_on_joinplayer`. + +### `hb.init_hudbar(player, identifier, start_value, start_max, start_hidden)` +This function initialzes and activates a previously registered HUD bar and assigns it to a +certain client/player. This has only to be done once per player and after that, you can change +the values using `hb.change_hudbar`. + +However, if `start_hidden` was set to `true` for the HUD bar (in `hb.register_hudbar`), the HUD bar +will initially be hidden, but the HUD elements are still sent to the client. Otherwise, +the HUD bar will be initially be shown to the player. + +#### Parameters +* `player`: `ObjectRef` of the player to which the new HUD bar should be displayed to. +* `identifier`: The identifier of the HUD bar type, as specified in `hb.register_hudbar`. +* `start_value`: The initial current value of the HUD bar. This is optional, `default_start_value` of the registration function will be used, if this is `nil`. +* `start_max`: The initial maximum value of the HUD bar. This is optional, `default_start_max` of the registration function will be used, if this is `nil` +* `start_hidden`: Whether the HUD bar is initially hidden. This is optional, `default_start_hidden` of the registration function will be used as default + +#### Return value +`true` on success, `false` otherwise. + + +## Modifying a HUD bar +After a HUD bar has been added, you can change the current and maximum value and other attributes on a per-player basis. +You use the function `hb.change_hudbar` for this. + +### `hb.change_hudbar(player, identifier, new_value, new_max_value, new_icon, new_bgicon, new_bar, new_label, new_text_color)` +Changes the values and the appearance of an initialized HUD bar for a certain player. `new_value` +and `new_max_value` are the most important parameters as they specify the new current and maximum new values, you do not need +to worry too much about the other parameters. + +The following parameters are less important and provided for styling the HUD bar after registration (if +this is desired). The “styling” parameters parallel the parameters of `hb.register_hudbar`. It is +recommended to not change the style of a HUD bar too often as this can be distracting or confusing +for players. + +`new_value`, `new_max_value` `new_icon`, `new_bgicon`, `new_bar`, `new_label` and `new_text_color` can be +`nil`; if one of them is `nil`, that means the value is unchanged. If all those values are `nil`, this +function is a no-op. + +This function tries to minimize the amount of calls to `hud_change` of the Minetest Lua API +(and thus, network traffic), when you only change the value and/or maximum value. In this case, +`hud_change` is only called if it is actually needed, e.g. when the actual length of the bar +or the displayed string changed, so you do not have to worry about it. There is, however, no +such network optimization for the “styling” parameters, so keep this in mind. + +#### Parameters +* `player`: `ObjectRef` of the player to which the HUD bar belongs to +* `identifier`: The identifier of the HUD bar type to change, as specified in `hb.register_hudbar`. +* `new_value`: The new current value of the HUD bar +* `new_max_value`: The new maximum value of the HUD bar +* `new_icon`: File name of the new icon +* `new_bgicon`: File name of the new background icon for the modern-style statbar +* `new_bar`: File name of the new bar segment image +* `new_label`: A new text label of the HUD bar. Note the format string still applies +* `new_text_color`: A 3-octet number defining the new color of the text. + +#### Return value +`true` on success, `false` otherwise. + + +## Hiding and unhiding a HUD bar +You can also hide custom HUD bars, meaning they will not be displayed for a certain player. You can still +use `hb.change_hudbar` on a hidden HUD bar, the new values will be correctly displayed after the HUD bar +has been unhidden. Both functions will only call `hud_change` if there has been an actual change to avoid +unneccessary traffic. + +Note that the hidden state of a HUD bar will *not* be saved by this mod on server shutdown, so you may need +to write your own routines for this or by setting the correct value for `start_hidden` when calling +`hb.init_hudbar`. + +### `hb.hide_hudbar(player, identifier)` +Hides the specified HUD bar from the screen of the specified player. + +#### Parameters +* `player`: `ObjectRef` of the player to which the HUD bar belongs to +* `identifier`: The identifier of the HUD bar type to hide, as specified in `hb.register_hudbar`. + +#### Return value +`true` on success, `false` otherwise. + + +### `hb.unhide_hudbar(player, identifier)` +Makes a previously hidden HUD bar visible again to a player. + +#### Parameters +* `player`: `ObjectRef` of the player to which the HUD bar belongs to +* `identifier`: The identifier of the HUD bar type to unhide, as specified in `hb.register_hudbar`. + +#### Return value +`true` on success, `false` otherwise. + + +## Reading HUD bar information +It is also possible to read information about an active HUD bar. + +### `hb.get_hudbar_state(player, identifier)` +Returns the current state of the active player's HUD bar. + +#### Parameters +* `player`: `ObjectRef` of the player to which the HUD bar belongs to +* `identifier`: The identifier of the HUD bar type to hide, as specified in `hb.register_hudbar`. + +#### Return value +On success, returns a table which holds information on the current state of the HUD bar. Note +the table is a deep copy of the internal HUD bar state, it is *not* a reference; the information +hold by the table is only true for the moment you called this function. The fields of this table are: + +* `value`: Current value of HUD bar. +* `max`: Current maximum value of HUD bar. +* `hidden`: Boolean denoting whether the HUD bar is hidden. +* `barlength`: The length of the HUD bar in pixels. This field is meaningless if the HUD bar is currently hidden. +* `text`: The text shown on the HUD bar. This fiels is meaningless if the HUD bar is currently hidden. + +If the player does not exist, returns `nil` instead. diff --git a/mods/hudbars/README.md b/mods/hudbars/README.md new file mode 100644 index 000000000..6571b7754 --- /dev/null +++ b/mods/hudbars/README.md @@ -0,0 +1,56 @@ +# HUD bars + +## Description +This mod changes the HUD of Minetest. It replaces the default health and breath +symbols by horizontal colored bars with text showing the number. + +Furthermore, it enables other mods to add their own custom bars to the HUD, +this mod will place them accordingly. + +**Important**: Keep in mind if running a server with this mod, that the custom +position should be displayed correctly on every screen size. + +## Current version +The current version is 1.7.0. + +This software uses [semantic versioning](http://semver.org), as defined by version 2.0.0 of the SemVer +standard. + +## Settings +This mod can be configured quite a bit. You can change HUD bar appearance, offsets, ordering, and more. +Use the advanced settings menu in Minetest for detailed configuration. + +## API +The API is used to add your own custom HUD bars. +Documentation for the API of this mod can be found in `API.md`. + +## Legal +### License of source code +Author: Wuzzy (2015) + +Also: This mod was forked from the “Better HUD” [hud] mod by BlockMen. + +Translations: + +* German: Wuzzy +* Portuguese: BrunoMine + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License (WTFPL), version 2, as published by Sam Hocevar. + +### Licenses of textures + +* `hudbars_icon_health.png`—celeron55 (CC BY-SA 3.0), modified by BlockMen +* `hudbars_bgicon_health.png`—celeron55 (CC BY-SA 3.0), modified by BlockMen +* `hudbars_icon_breath.png`—kaeza (WTFPL), modified by BlockMen, modified again by Wuzzy +* `hudbars_bgicon_breath.png`—based on previous image, edited by Wuzzy (WTFPL) +* `hudbars_bar_health.png`—Wuzzy (WTFPL) +* `hudbars_bar_breath.png`—Wuzzy (WTFPL) +* `hudbars_bar_background.png`—Wuzzy (WTFPL) + +### License references + +* [CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/) +* [WTFPL](http://sam.zoy.org/wtfpl/COPYING) diff --git a/mods/hudbars/changelog.txt b/mods/hudbars/changelog.txt new file mode 100644 index 000000000..e2e6b560f --- /dev/null +++ b/mods/hudbars/changelog.txt @@ -0,0 +1,92 @@ +Note: This software uses semantic versioning, +as of version 2.0.0 of the standard . + +0.1.0 +----- +- Initial release, forked from mod “Better HUD” [hud]. + +0.2.0 +----- +- Add API documentation + +0.3.0 +----- +- Rename main table from “hud” to “hb” (affects function names!) +- Arguments 3-4 of hb.change_hudbar can be nil for values which should not change +- Add proper function hb.init_hudbar, replaces odd call to hud.hudtables[identifier].add_all +- Update API documentation and fix mistakes +- Use “hudbars.conf” instead of “hud.conf” + +0.4.0 +----- +- New function: hb.get_hudbar_state to get information about the state of an active HUD bar, such as values, whether it is hidden, etc. +- hb.change_hudbar has been optimized to call hud_change fewer times, which is hopefully good for networking +- Rename hb.register_hudbar parameter “start_hide” to “start_hidden” +- start_hidden parameter now finally works +- Do not affect other HUD flags (crosshair, wielditem, etc.) when starting mod +- Show error message when trying to call hb.init_hudbar or hb.change_hudbar with bad values +- Update documentation +- Lots of refactoring +- Health and breath bar now use API + +1.0.0 +----- +- Add new parameter start_hidden to hb.init_hudbar, specified whether HUD bar is hidden on start +- Copy-editing of API.md and README.txt +- Internal: Fix add_all weirdness + +1.0.1 +----- +- Fix race condition causing crash at start of server + +1.0.2 +----- +- Fix other HUD elements disappearing for rejoining players +- Remove pointless delays for initializing the HUD for new or rejoining players + +1.0.3 +----- +- Adjust default HUD bars position for Minetest 0.4.12 + +1.1.0 +----- +- Add boolean minetest.conf setting support (hudbars_autohide_breathbar) to control whether the breath bar is automatically hidden when full (default: yes) + +1.2.0 +----- +- New setting: hudbars_sorting. You can now manually sort all the HUD bars. Useful if you don't like automatic order +- New setting: hudbars_bar_type. You now can change the appearance of the HUD bars. +- New HUD bar types, slightly experimental: Classic statbars and modern [hud]-style statbars +- New experimental/unfinished setting: hudbars_alignment_pattern: You can now make the HUD bars stack vertically instead of the current zig-zag pattern. Note you probably need to change source code to productively use this feature +- Various position-related HUD bar settings (see README.txt) +- Remove hudbars.conf support and hudbars.conf.example (was never officially supported anyways) + +1.2.1 +----- +- Fix crash when enable_damage is changed in mid-game + +1.3.0 +----- +- Make all settings avaialbe in Minetest's advanced settings menu +- Fix HUD bars overlap when both hudbars_tick and hudbars_vmargin were set +- Use Markdown syntax in readme file +- Fix some factual mistakes in readme file +- Add metadata: mod.conf, description.txt, screenshot.png + +1.4.0 +----- +- Allow to change HUD bar images and label after it has been registered +- Minor API.md correction + +1.4.1 +----- +- Fix bug in hb.change_hudbar being a no-op if new_value and new_max value are nil + +1.5.0 +----- +- Portuguese translation by BrunoMine + +1.5.1 +----- +- Fix critical bug: Mod does not work with both intllib and mod security enabled +- Update screenshot to use new 3:2 aspect ratio diff --git a/mods/hudbars/depends.txt b/mods/hudbars/depends.txt new file mode 100644 index 000000000..77e8d97c9 --- /dev/null +++ b/mods/hudbars/depends.txt @@ -0,0 +1 @@ +intllib? diff --git a/mods/hudbars/description.txt b/mods/hudbars/description.txt new file mode 100644 index 000000000..9e10e894e --- /dev/null +++ b/mods/hudbars/description.txt @@ -0,0 +1 @@ +Replaces the health and breath symbols in the HUD by “progress bars” and shows exact values. Other mods can add more progress bars for custom player stats. diff --git a/mods/hudbars/init.lua b/mods/hudbars/init.lua new file mode 100644 index 000000000..30a3491c8 --- /dev/null +++ b/mods/hudbars/init.lua @@ -0,0 +1,559 @@ +local S +if (minetest.get_modpath("intllib")) then + S = intllib.Getter() +else + S = function ( s ) return s end +end + +hb = {} + +hb.hudtables = {} + +-- number of registered HUD bars +hb.hudbars_count = 0 + +-- table which records which HUD bar slots have been “registered” so far; used for automatic positioning +hb.registered_slots = {} + +hb.settings = {} + +function hb.load_setting(sname, stype, defaultval, valid_values) + local sval + if stype == "string" then + sval = minetest.setting_get(sname) + elseif stype == "bool" then + sval = minetest.setting_getbool(sname) + elseif stype == "number" then + sval = tonumber(minetest.setting_get(sname)) + end + if sval ~= nil then + if valid_values ~= nil then + local valid = false + for i=1,#valid_values do + if sval == valid_values[i] then + valid = true + end + end + if not valid then + minetest.log("error", "[hudbars] Invalid value for "..sname.."! Using default value ("..tostring(defaultval)..").") + return defaultval + else + return sval + end + else + return sval + end + else + return defaultval + end +end + +-- (hardcoded) default settings +hb.settings.max_bar_length = 160 +hb.settings.statbar_length = 20 + +-- statbar positions +hb.settings.pos_left = {} +hb.settings.pos_right = {} +hb.settings.start_offset_left = {} +hb.settings.start_offset_right= {} +hb.settings.pos_left.x = hb.load_setting("hudbars_pos_left_x", "number", 0.5) +hb.settings.pos_left.y = hb.load_setting("hudbars_pos_left_y", "number", 1) +hb.settings.pos_right.x = hb.load_setting("hudbars_pos_right_x", "number", 0.5) +hb.settings.pos_right.y = hb.load_setting("hudbars_pos_right_y", "number", 1) +hb.settings.bar_type = hb.load_setting("hudbars_bar_type", "string", "statbar_modern", {"progress_bar", "statbar_classic", "statbar_modern"}) +if hb.settings.bar_type == "progress_bar" then + hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_offset_left_x", "number", -175) + hb.settings.start_offset_left.y = hb.load_setting("hudbars_start_offset_left_y", "number", -86) + hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_offset_right_x", "number", 15) + hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_offset_right_y", "number", -86) +else + hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_statbar_offset_left_x", "number", -265) + hb.settings.start_offset_left.y = hb.load_setting("hudbars_start_statbar_offset_left_y", "number", -90) + hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_statbar_offset_right_x", "number", 25) + hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_statbar_offset_right_y", "number", -90) +end +hb.settings.vmargin = hb.load_setting("hudbars_vmargin", "number", 32) +hb.settings.tick = hb.load_setting("hudbars_tick", "number", 0.1) + +-- experimental setting: Changing this setting is not officially supported, do NOT rely on it! +hb.settings.forceload_default_hudbars = hb.load_setting("hudbars_forceload_default_hudbars", "bool", true) + +-- Misc. settings +hb.settings.alignment_pattern = hb.load_setting("hudbars_alignment_pattern", "string", "zigzag", {"zigzag", "stack_up", "stack_down"}) +hb.settings.autohide_breath = hb.load_setting("hudbars_autohide_breath", "bool", true) + +local sorting = minetest.setting_get("hudbars_sorting") +if sorting ~= nil then + hb.settings.sorting = {} + for k,v in string.gmatch(sorting, "(%w+)=(%w+)") do + hb.settings.sorting[k] = tonumber(v) + end +else + sorting = "" + hb.settings.sorting = { ["health"] = 0, ["hunger"] = 1, ["armor"] = 2, ["breath"] = 3 } +end +hb.settings.sorting_reverse = {} +for k,v in string.gmatch(sorting, "(%w+)=(%w+)") do + hb.settings.sorting_reverse[tonumber(v)] = k +end + +local function player_exists(player) + return player ~= nil and player:is_player() +end + +-- Table which contains all players with active default HUD bars (only for internal use) +hb.players = {} + +function hb.value_to_barlength(value, max) + if max == 0 then + return 0 + else + if hb.settings.bar_type == "progress_bar" then + local x + if value < 0 then x=-0.5 else x = 0.5 end + local ret = math.modf((value/max) * hb.settings.max_bar_length + x) + return ret + else + local x + if value < 0 then x=-0.5 else x = 0.5 end + local ret = math.modf((value/max) * hb.settings.statbar_length + x) + return ret + end + end +end + +function hb.get_hudtable(identifier) + return hb.hudtables[identifier] +end + +function hb.get_hudbar_position_index(identifier) + if hb.settings.sorting[identifier] ~= nil then + return hb.settings.sorting[identifier] + else + local i = 0 + while true do + if hb.registered_slots[i] ~= true and hb.settings.sorting_reverse[i] == nil then + return i + end + i = i + 1 + end + end +end + +function hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string) + minetest.log("action", "hb.register_hudbar: "..tostring(identifier)) + local hudtable = {} + local pos, offset + local index = math.floor(hb.get_hudbar_position_index(identifier)) + hb.registered_slots[index] = true + if hb.settings.alignment_pattern == "stack_up" then + pos = hb.settings.pos_left + offset = { + x = hb.settings.start_offset_left.x, + y = hb.settings.start_offset_left.y - hb.settings.vmargin * index + } + elseif hb.settings.alignment_pattern == "stack_down" then + pos = hb.settings.pos_left + offset = { + x = hb.settings.start_offset_left.x, + y = hb.settings.start_offset_left.y + hb.settings.vmargin * index + } + else + if index % 2 == 0 then + pos = hb.settings.pos_left + offset = { + x = hb.settings.start_offset_left.x, + y = hb.settings.start_offset_left.y - hb.settings.vmargin * (index/2) + } + else + pos = hb.settings.pos_right + offset = { + x = hb.settings.start_offset_right.x, + y = hb.settings.start_offset_right.y - hb.settings.vmargin * ((index-1)/2) + } + end + end + if format_string == nil then + format_string = S("%s: %d/%d") + end + + hudtable.add_all = function(player, hudtable, start_value, start_max, start_hidden) + if start_value == nil then start_value = hudtable.default_start_value end + if start_max == nil then start_max = hudtable.default_start_max end + if start_hidden == nil then start_hidden = hudtable.default_start_hidden end + local ids = {} + local state = {} + local name = player:get_player_name() + local bgscale, iconscale, text, barnumber, bgiconnumber + if start_max == 0 or start_hidden then + bgscale = { x=0, y=0 } + else + bgscale = { x=1, y=1 } + end + if start_hidden then + iconscale = { x=0, y=0 } + barnumber = 0 + bgiconnumber = 0 + text = "" + else + iconscale = { x=1, y=1 } + barnumber = hb.value_to_barlength(start_value, start_max) + bgiconnumber = hb.settings.statbar_length + text = string.format(format_string, label, start_value, start_max) + end + if hb.settings.bar_type == "progress_bar" then + ids.bg = player:hud_add({ + hud_elem_type = "image", + position = pos, + scale = bgscale, + text = "hudbars_bar_background.png", + alignment = {x=1,y=1}, + offset = { x = offset.x - 1, y = offset.y - 1 }, + }) + if textures.icon ~= nil then + ids.icon = player:hud_add({ + hud_elem_type = "image", + position = pos, + scale = iconscale, + text = textures.icon, + alignment = {x=-1,y=1}, + offset = { x = offset.x - 3, y = offset.y }, + }) + end + elseif hb.settings.bar_type == "statbar_modern" then + if textures.bgicon ~= nil then + ids.bg = player:hud_add({ + hud_elem_type = "statbar", + position = pos, + text = textures.bgicon, + number = bgiconnumber, + alignment = {x=-1,y=-1}, + offset = { x = offset.x, y = offset.y }, + direction = 0, + size = {x=24, y=24}, + }) + end + end + local bar_image, bar_size + if hb.settings.bar_type == "progress_bar" then + bar_image = textures.bar + bar_size = nil + elseif hb.settings.bar_type == "statbar_classic" or hb.settings.bar_type == "statbar_modern" then + bar_image = textures.icon + bar_size = {x=24, y=24} + end + ids.bar = player:hud_add({ + hud_elem_type = "statbar", + position = pos, + text = bar_image, + number = barnumber, + alignment = {x=-1,y=-1}, + offset = offset, + direction = 0, + size = bar_size, + }) + if hb.settings.bar_type == "progress_bar" then + ids.text = player:hud_add({ + hud_elem_type = "text", + position = pos, + text = text, + alignment = {x=1,y=1}, + number = text_color, + direction = 0, + offset = { x = offset.x + 2, y = offset.y - 1}, + }) + end + -- Do not forget to update hb.get_hudbar_state if you add new fields to the state table + state.hidden = start_hidden + state.value = start_value + state.max = start_max + state.text = text + state.barlength = hb.value_to_barlength(start_value, start_max) + + local main_error_text = + "[hudbars] Bad initial values of HUD bar identifier “"..tostring(identifier).."” for player "..name..". " + + if start_max < start_value then + minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than start_value ("..start_value..")!") + end + if start_max < 0 then + minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than 0!") + end + if start_value < 0 then + minetest.log("error", main_error_text.."start_value ("..start_value..") is smaller than 0!") + end + + hb.hudtables[identifier].hudids[name] = ids + hb.hudtables[identifier].hudstate[name] = state + end + + hudtable.identifier = identifier + hudtable.format_string = format_string + hudtable.label = label + hudtable.hudids = {} + hudtable.hudstate = {} + hudtable.default_start_hidden = default_start_hidden + hudtable.default_start_value = default_start_value + hudtable.default_start_max = default_start_max + + hb.hudbars_count= hb.hudbars_count + 1 + + hb.hudtables[identifier] = hudtable +end + +function hb.init_hudbar(player, identifier, start_value, start_max, start_hidden) + if not player_exists(player) then return false end + local hudtable = hb.get_hudtable(identifier) + hb.hudtables[identifier].add_all(player, hudtable, start_value, start_max, start_hidden) + return true +end + +function hb.change_hudbar(player, identifier, new_value, new_max_value, new_icon, new_bgicon, new_bar, new_label, new_text_color) + if new_value == nil and new_max_value == nil and new_icon == nil and new_bgicon == nil and new_bar == nil and new_label == nil and new_text_color == nil then + return true + end + if not player_exists(player) then + return false + end + + local name = player:get_player_name() + local hudtable = hb.get_hudtable(identifier) + local value_changed, max_changed = false, false + + if new_value ~= nil then + if new_value ~= hudtable.hudstate[name].value then + hudtable.hudstate[name].value = new_value + value_changed = true + end + else + new_value = hudtable.hudstate[name].value + end + if new_max_value ~= nil then + if new_max_value ~= hudtable.hudstate[name].max then + hudtable.hudstate[name].max = new_max_value + max_changed = true + end + else + new_max_value = hudtable.hudstate[name].max + end + + if hb.settings.bar_type == "progress_bar" then + if new_icon ~= nil and hudtable.hudids[name].icon ~= nil then + player:hud_change(hudtable.hudids[name].icon, "text", new_icon) + end + if new_bgicon ~= nil and hudtable.hudids[name].bgicon ~= nil then + player:hud_change(hudtable.hudids[name].bgicon, "text", new_bgicon) + end + if new_bar ~= nil then + player:hud_change(hudtable.hudids[name].bar , "text", new_bar) + end + if new_label ~= nil then + hudtable.label = new_label + local new_text = string.format(hudtable.format_string, new_label, hudtable.hudstate[name].value, hudtable.hudstate[name].max) + player:hud_change(hudtable.hudids[name].text, "text", new_text) + end + if new_text_color ~= nil then + player:hud_change(hudtable.hudids[name].text, "number", new_text_color) + end + else + if new_icon ~= nil and hudtable.hudids[name].bar ~= nil then + player:hud_change(hudtable.hudids[name].bar, "text", new_icon) + end + if new_bgicon ~= nil and hudtable.hudids[name].bg ~= nil then + player:hud_change(hudtable.hudids[name].bg, "text", new_bgicon) + end + end + + local main_error_text = + "[hudbars] Bad call to hb.change_hudbar, identifier: “"..tostring(identifier).."”, player name: “"..name.."”. " + if new_max_value < new_value then + minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than new_value ("..new_value..")!") + end + if new_max_value < 0 then + minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than 0!") + end + if new_value < 0 then + minetest.log("error", main_error_text.."new_value ("..new_value..") is smaller than 0!") + end + + if hudtable.hudstate[name].hidden == false then + if max_changed and hb.settings.bar_type == "progress_bar" then + if hudtable.hudstate[name].max == 0 then + player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0}) + else + player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1}) + end + end + + if value_changed or max_changed then + local new_barlength = hb.value_to_barlength(new_value, new_max_value) + if new_barlength ~= hudtable.hudstate[name].barlength then + player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(new_value, new_max_value)) + hudtable.hudstate[name].barlength = new_barlength + end + + if hb.settings.bar_type == "progress_bar" then + local new_text = string.format(hudtable.format_string, hudtable.label, new_value, new_max_value) + if new_text ~= hudtable.hudstate[name].text then + player:hud_change(hudtable.hudids[name].text, "text", new_text) + hudtable.hudstate[name].text = new_text + end + end + end + end + return true +end + +function hb.hide_hudbar(player, identifier) + if not player_exists(player) then return false end + local name = player:get_player_name() + local hudtable = hb.get_hudtable(identifier) + if hudtable == nil then return false end + if(hudtable.hudstate[name].hidden == false) then + if hb.settings.bar_type == "progress_bar" then + if hudtable.hudids[name].icon ~= nil then + player:hud_change(hudtable.hudids[name].icon, "scale", {x=0,y=0}) + end + player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0}) + player:hud_change(hudtable.hudids[name].text, "text", "") + elseif hb.settings.bar_type == "statbar_modern" then + player:hud_change(hudtable.hudids[name].bg, "number", 0) + end + player:hud_change(hudtable.hudids[name].bar, "number", 0) + hudtable.hudstate[name].hidden = true + end + return true +end + +function hb.unhide_hudbar(player, identifier) + if not player_exists(player) then return false end + local name = player:get_player_name() + local hudtable = hb.get_hudtable(identifier) + if hudtable == nil then return false end + if(hudtable.hudstate[name].hidden) then + local value = hudtable.hudstate[name].value + local max = hudtable.hudstate[name].max + if hb.settings.bar_type == "progress_bar" then + if hudtable.hudids[name].icon ~= nil then + player:hud_change(hudtable.hudids[name].icon, "scale", {x=1,y=1}) + end + if hudtable.hudstate[name].max ~= 0 then + player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1}) + end + player:hud_change(hudtable.hudids[name].text, "text", tostring(string.format(hudtable.format_string, hudtable.label, value, max))) + elseif hb.settings.bar_type == "statbar_modern" then + player:hud_change(hudtable.hudids[name].bg, "number", hb.settings.statbar_length) + end + player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(value, max)) + hudtable.hudstate[name].hidden = false + end + return true +end + +function hb.get_hudbar_state(player, identifier) + if not player_exists(player) then return nil end + local ref = hb.get_hudtable(identifier).hudstate[player:get_player_name()] + -- Do not forget to update this chunk of code in case the state changes + local copy = { + hidden = ref.hidden, + value = ref.value, + max = ref.max, + text = ref.text, + barlength = ref.barlength, + } + return copy +end + +--register built-in HUD bars +if minetest.setting_getbool("enable_damage") or hb.settings.forceload_default_hudbars then + hb.register_hudbar("health", 0xFFFFFF, S("Health"), { bar = "hudbars_bar_health.png", icon = "hudbars_icon_health.png", bgicon = "hudbars_bgicon_health.png" }, 20, 20, false) + hb.register_hudbar("breath", 0xFFFFFF, S("Breath"), { bar = "hudbars_bar_breath.png", icon = "hudbars_icon_breath.png", bgicon = "hudbars_bgicon_breath.png" }, 10, 10, true) +end + +local function hide_builtin(player) + local flags = player:hud_get_flags() + flags.healthbar = false + flags.breathbar = false + player:hud_set_flags(flags) +end + + +local function custom_hud(player) + if minetest.setting_getbool("enable_damage") or hb.settings.forceload_default_hudbars then + local hide + if minetest.setting_getbool("enable_damage") then + hide = false + else + hide = true + end + hb.init_hudbar(player, "health", player:get_hp(), nil, hide) + local breath = player:get_breath() + local hide_breath + if breath == 11 and hb.settings.autohide_breath == true then hide_breath = true else hide_breath = false end + hb.init_hudbar(player, "breath", math.min(breath, 10), nil, hide_breath or hide) + end +end + +local function update_health(player) + hb.change_hudbar(player, "health", player:get_hp()) +end + +-- update built-in HUD bars +local function update_hud(player) + if not player_exists(player) then return end + if minetest.setting_getbool("enable_damage") then + if hb.settings.forceload_default_hudbars then + hb.unhide_hudbar(player, "health") + end + --air + local breath = player:get_breath() + + if breath == 11 and hb.settings.autohide_breath == true then + hb.hide_hudbar(player, "breath") + else + hb.unhide_hudbar(player, "breath") + hb.change_hudbar(player, "breath", math.min(breath, 10)) + end + --health + update_health(player) + elseif hb.settings.forceload_default_hudbars then + hb.hide_hudbar(player, "health") + hb.hide_hudbar(player, "breath") + end +end + +minetest.register_on_player_hpchange(update_health) + +minetest.register_on_respawnplayer(function(player) + update_health(player) + hb.hide_hudbar(player, "breath") +end) + +minetest.register_on_joinplayer(function(player) + hide_builtin(player) + custom_hud(player) + hb.players[player:get_player_name()] = player +end) + +minetest.register_on_leaveplayer(function(player) + hb.players[player:get_player_name()] = nil +end) + +local main_timer = 0 +local timer = 0 +minetest.register_globalstep(function(dtime) + main_timer = main_timer + dtime + timer = timer + dtime + if main_timer > hb.settings.tick or timer > 4 then + if main_timer > hb.settings.tick then main_timer = 0 end + -- only proceed if damage is enabled + if minetest.setting_getbool("enable_damage") or hb.settings.forceload_default_hudbars then + for _, player in pairs(hb.players) do + -- update all hud elements + update_hud(player) + end + end + end + if timer > 4 then timer = 0 end +end) diff --git a/mods/hudbars/locale/de.txt b/mods/hudbars/locale/de.txt new file mode 100644 index 000000000..578764ea4 --- /dev/null +++ b/mods/hudbars/locale/de.txt @@ -0,0 +1,3 @@ +Health = Leben +Breath = Atem +%s: %d/%d = %s: %d/%d diff --git a/mods/hudbars/locale/pt.txt b/mods/hudbars/locale/pt.txt new file mode 100644 index 000000000..2de62650d --- /dev/null +++ b/mods/hudbars/locale/pt.txt @@ -0,0 +1,5 @@ +Health = Saude +Breath = Folego + +# Formato de string padrão para progresso bar-style de barras do HUD, por exemplo “Saude 5/20” +%s: %d/%d diff --git a/mods/hudbars/locale/template.txt b/mods/hudbars/locale/template.txt new file mode 100644 index 000000000..0a26b8fe8 --- /dev/null +++ b/mods/hudbars/locale/template.txt @@ -0,0 +1,5 @@ +Health +Breath + +# Default format string for progress bar-style HUD bars, e.g. “Health 5/20” +%s: %d/%d diff --git a/mods/hudbars/mod.conf b/mods/hudbars/mod.conf new file mode 100644 index 000000000..add28e651 --- /dev/null +++ b/mods/hudbars/mod.conf @@ -0,0 +1 @@ +name = hudbars diff --git a/mods/hudbars/screenshot.png b/mods/hudbars/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..88ee3238dbaac6e7d3769e212c0ccd4eed023b96 GIT binary patch literal 9556 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