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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 z 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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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 TgAVF{e>kZqXo9QcEI$7~BOnZ3 literal 0 HcmV?d00001 diff --git a/mods/hudbars/settingtypes.txt b/mods/hudbars/settingtypes.txt new file mode 100644 index 000000000..3e4390e20 --- /dev/null +++ b/mods/hudbars/settingtypes.txt @@ -0,0 +1,119 @@ +[Appearance] +# Specifies how the value indicators (i.e. health, breah, etc.) look. There are 3 styles +# available. You can choose between the default progress-bar-like bars and the good +# old statbars like you know from vanilla Minetest. +# These values are possible: +# - progress_bar: A horizontal progress-bar-like bar with a label, showing numerical value +# (current, maximum), and an icon. These bars usually convey the most +# information. This is the default and recommended value. +# - statbar_classic: Classic statbar, like in vanilla Minetest. Made out of up to 20 +# half-symbols. Those bars represent the vague ratio between +# the current value and the maximum value. 1 half-symbol stands for +# approximately 5% of the maximum value. +# - statbar_modern: Like the classic statbar, but also supports background images, this +# kind of statbar may be considered to be more user-friendly than the +# classic statbar. This bar type closely resembles the mod +# “Better HUD” [hud] by BlockMen. +hudbars_bar_type (HUD bars style) enum progress_bar progress_bar,statbar_classic,statbar_modern + + +# If enabled (default), the breath indicators in the HUD will be automatically hidden shortly +# after the breath has been filled up. Otherwise, the breath will always be displayed. +hudbars_autohide_breath (Automatically hide breath indicators) bool true + +# This setting changes the way the HUD bars are ordered on the display. You can choose +# between a zig-zag pattern (default) or a vertically stacked pattern. +# The following values are allowed: +# - zigzag: Starting from the left bottom, the next is right from the first, +# the next is above the first, the next is right of the third, etc. +# - stack_up: The HUD bars are stacked vertically, going upwards. +# - stack_down: The HUD bars are stacked vertically, going downwards. +hudbars_alignment_pattern (HUD bars alignment pattern) enum zigzag zigzag,stack_up,stack_down + +# This setting allows you to specify the order of the HUD bars explicitly. If left empty +# (the default), the health and breath indicators come first, additional indicators +# may appear in any order. This setting is quite technical and normal users probably do not +# need to worry about it. +# +# Syntax: +# The setting has to be specified as a comma-seperated list of key=value pairs, where a key +# refers to the identifier of a HUD bar and the value refers to the slot number of where the +# HUD bar should be placed. The slot number must be an integer greater of equal to 0. Where +# the HUD bars will be displayed exactly depends on the alignment pattern being used. +# All HUD bars to which no order value has been applied will fill in all slots which have +# not been occupied by the HUD bars specified in this setting, the slots will be filled in +# from the lowest slot number. +# Note that the order of those remaining HUD bars is not fixed, it basically just boils +# down on which mod “came” first. Don't worry, the mod will still work perfectly fine, this +# setting is entirely optional. +# The identifier for the health bar is “health” and the identifier for the breath bar is +# “breath”. For other HUD bars, you have to learn it from the mod which is supplying them. +# +# Be careful not to use slot indices twice, or else different HUD bars will be drawn over +# each other! +# +# Example: “breath=0, health=1” +# This makes the breath bar first and the health bar second, which is the opposite order +# of the default one. +hudbars_sorting (HUD bars order) string + +[Positions and offsets] +# Horizontal (x) main position of the HUD bars over the entire screen. +# 0.0 is left-most, 1.0 is right-most. +# For the zig-zag alignment pattern, this is for the left HUD bars. +hudbars_pos_left_x (Left HUD bar screen x position) float 0.5 0.0 1.0 +# Vertical (y) main position of the HUD bars over the entire screen. +# 0.0 is top, 1.0 is bottom. +# For the zig-zag alignment pattern, this is for the left HUD bars. +hudbars_pos_left_y (Left HUD bar screen y position) float 1.0 0.0 1.0 +# Horizontal (x) main position of the right HUD bars over the entire screen. +# 0.0 is left-most, 1.0 is right-most. +# Only used for the zig-zag alignment pattern. +hudbars_pos_right_x (Right HUD bar screen x position) float 0.5 0.0 1.0 +# Vertical main position (y) of the right HUD bars over the entire screen. +# 0.0 is top, 1.0 is bottom. +# Only used for the zig-zag alignment pattern. +hudbars_pos_right_y (Right HUD bar screen y position) float 1.0 0.0 1.0 + +# Precise x offset in pixels from the basic screen x position of the HUD bars. +# For the zig-zag alignment pattern, this is for the left HUD bars. +# This setting is used for the progress bar HUD bar style. +hudbars_start_offset_left_x (Left HUD bar x offset) int -175 +# Precise y offset in pixels from the basic screen y position of the HUD bars. +# For the zig-zag alignment pattern, this is for the left HUD bars. +# This setting is used for the progress bar HUD bar style. +hudbars_start_offset_left_y (Left HUD bar y offset) int -86 +# Precise x offset in pixels from the basic screen x position of the right HUD bars. +# Only used for the zig-zag alignment pattern. +# This setting is used for the progress bar HUD bar style. +hudbars_start_offset_right_x (Right HUD bar x offset) int 15 +# Precise y offset in pixels from the basic screen y position of the right HUD bars. +# Only used for the zig-zag alignment pattern. +# This setting is used for the progress bar HUD bar style. +hudbars_start_offset_right_y (Right HUD bar y offset) int -86 + +# Precise x offset in pixels from the basic screen x position of the HUD statbars. +# For the zig-zag alignment pattern, this is for the left HUD statbars. +# This setting is used for the classic and modern statbar styles. +hudbars_start_statbar_offset_left_x (Left HUD statbar x offset) int -265 +# Precise y offset in pixels from the basic screen y position of the HUD statbars. +# For the zig-zag alignment pattern, this is for the left HUD statbars. +# This setting is used for the classic and modern statbar styles. +hudbars_start_statbar_offset_left_y (Left HUD statbar y offset) int -90 +# Precise x offset in pixels from the basic screen x position of the right HUD statbars. +# Only used for the zig-zag alignment pattern. +# This setting is used for the classic and modern statbar styles. +hudbars_start_statbar_offset_right_x (Right HUD statbar x offset) int 25 +# Precise y offset in pixels from the basic screen y position of the right HUD statbars. +# Only used for the zig-zag alignment pattern. +# This setting is used for the classic and modern statbar styles. +hudbars_start_statbar_offset_right_y (Right HUD statbar y offset) int -90 + +# The vertical distance between two HUD bars, in pixels. +hudbars_vmargin (Vertical distance between HUD bars) int 24 0 + +[Performance] +# The of seconds which need to pass before the server updates the default HUD bars +# (health and breath). Increase this number if you have a slow server or a slow network +# connection and experience performance problems. +hudbars_tick (Default HUD bars update interval) float 0.1 0.0 4.0 diff --git a/mods/hudbars/textures/hudbars_bar_background.png b/mods/hudbars/textures/hudbars_bar_background.png new file mode 100644 index 0000000000000000000000000000000000000000..cbc6c3f519956fab4bbe266ef26428e4ed8bb66c GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^i-1^&gAGXDuwcytQo)`sjv*QM-rh14JYXQe>}V;R zkoYBH-o%+lW$xTKs>gD6s+8xy1Bv;QLawHB`MrGib4H^yhoEAUfS?ivb!eU7@d&*Q Z3=a;oDeIOTssb9%;OXk;vd$@?2>|+XD)|5a literal 0 HcmV?d00001 diff --git a/mods/hudbars/textures/hudbars_bar_breath.png b/mods/hudbars/textures/hudbars_bar_breath.png new file mode 100644 index 0000000000000000000000000000000000000000..7d19a5752472cdbc05b2a331e2e7097f91a790fd GIT binary patch literal 80 zcmeAS@N?(olHy`uVBq!ia0vp^Oh7Ea!3HF4R;=3sq{Ka4978y+C(qgcqTZGn2!xqM ccyyQ<`izFVdQ&MBb@0B0K!`v3p{ literal 0 HcmV?d00001 diff --git a/mods/hudbars/textures/hudbars_bar_health.png b/mods/hudbars/textures/hudbars_bar_health.png new file mode 100644 index 0000000000000000000000000000000000000000..653091603ac377f93c7f98ae1f6a97f07268014d GIT binary patch literal 80 zcmeAS@N?(olHy`uVBq!ia0vp^Oh7Ea!3HF4R;=3sq{Ka4978y+C+|6Y;KTezAn0V| dVw=Xu!2g}`H{Xu=SAj|xJYD@<);T3K0RYvF74QH6 literal 0 HcmV?d00001 diff --git a/mods/hudbars/textures/hudbars_bgicon_breath.png b/mods/hudbars/textures/hudbars_bgicon_breath.png new file mode 100644 index 0000000000000000000000000000000000000000..fe7800ffe5f26f70c50a88a83b6b1ee8734a5f8b GIT binary patch literal 237 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|#^NA%Cx&(BWL^R}Y)RhkE)4&H zECyrsn$JLrv%n*=n1O*?7=#%aX3dcR3bL1Y`ns||WE9{tSGeo6F%Bq{>*?YcVsZNF zlt8Wn3OvrMm!JIWKlyfwy*AJFt~{#