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 00000000..680f9c44 --- /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 00000000..32c22245 --- /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 00000000..02a8a34f --- /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 00000000..fb697e72 --- /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 00000000..5a6bacdc --- /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 00000000..d898abe4 --- /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 00000000..47352c19 --- /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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%0DhsoDmqo;Om zF@1Pq>IC&W{S!)F&f1q8*QWGbrAItfAST#QQ@3;KW#=6W`PEnC9cA59a!1Vd+=SfC zy;B;0eqOZFIU?b}bz?o|{l?PPrKyf=sSG)Rx}Rbu&yH?+@odAaAgA0@3R_*d1@=q} z3xBjlr&&ZKgtIu-Lec+^#w&qmjJx=EhpHr&r5NNp8Qm)3(EQTv6hD2IRg24pDHmJM zD8I08-22R<;>C_B3nC@YNJocko^UZ(KiNUlU5;s@;R8>%*ALXzPiDDu+Fms$s;s3* z?Y-gi`>(jK$f&B7&)9MMc#im*rzx+aS@(37SN{2UJk#`S@}0WhZ&`o8DS5`t>bh>K zLAd$8^sSt=|nfGy4 z_PU#!QoX&sx!11$#eACYz8g-Z z<-6}5?~`RV`}Oyq%=VO~f}c;Pcjtyk{9x8`dinX;+0`pnR6LpJp10?tTf(jH`@Y+L zxw_!x;dcJ^_Frf7>pp)t%+Ksv91PR%$oXeSM{hi9_GIdEzqz|=e}DV-t!%~L{r~^ImzI(W z_;tSS+vcyYulvt76q``_>P+h<-ggyN8RQ3DxaU5YyEJQu$oWB@3-6Y_kImCc&@kWh0=*XFBbRT zD?V@g_*ifE9d8xI48aQz8rkI{wq#tqwKaSFjz?XN>)A9F_Rp{TmFZMDYxeAi(HfyO zNui;lHB9ptGB|h`I9gjQ|mY0_o7JfWAS-tW6 zhqs$jPxHy!*`%HlIl-31(Zh6I?_t)0uJ8Bj|1WT5T6gH`qu@1R+7_!nqy%_OVPa{k zW<1E|+s>By=Eg=|g)uviABtmy$MK(272w5+bEuRi)#$ z`1<3I)qDRXTwtH?;J9A=kM?%$yH$z{RrZ*BsyQqhI--u+JZXdaaWQRW{$g9kLc%vqn?@dxgyco&{Y2 zri~LE4s|qC*kn2_4zRAAxBu<7+cR#=iwIc0+ny?!6p zEA~16AItye`1WmM^6>*XbuX7rUvQ(qF+=TM<#X8$$)6{wFAVP1FZ`6T?Cf(cHm8@% z^;cc>@7Ub*;NW8S#>RxNj=Jq^a#JoOZFQ3MRlg&{uEJve(!c)Ki4XzQ*M|Vc%9*^>R~9;tm%_9cJpF<{NeTb{d`Abf-k*&FW}JlQ1}Xu#JR2&YuBWdSzn{A#% z`mfn3XIKAwak+Pon}EaSlOZudkBThb)qi|tlJ0ny^=`%Iv*rhv^epG~aF30RjhL3y z9DU=`C8lrp+IXcM3eH)*)|qgm^z}8-&bb;NJw#Gla=1TnESK*Y&Sk<;q3LLYVYrFZ+E}hboxNfH8Vx^Y1IkUB%<;FF%c~Apib8*_WYC^PW9R`(SX; zvgH=P$W$wy2m1paADq+t_}aB=d#k@UZEWAy^eZ+plJgbU@w)x>=jYkZojdn|YSX%= z`=LQWO@96RZ@s&_Tb9qgC@1anv$N|OKdJ;6@6eCo)#EeUTFW zS<)d4S5DRZ`}sU!MYDmEl}+8h(08}<_y290?f&q$QP+=_zi*3Ejl-8f5~qHFXsnf2S${Mj}qbW0`8&XGD(v_d<5(X2K1L+6#dPv^h7 z&a&%A?zWQ~weH?!+}~}nVZvG7VBKdrS8dAm?=DqlmOK+&@vC{|4Aqve8<@T>ug_b$ zKj~ibFMIywUNa{0oU-WlVEcaAYu0s(wGH#<9@Em$Fj>|Td3dUJ-;^$PTb|Fi76}#< zoSYxM+ObRWnRDAuH=mPy$A0{M8y^4m&;9?s{xWy(*MFK8Eu+7G&7;-pSFgUkfB(`w zHX_?~7+e=>Ctk}5On4y5v-w2c{(bxY$sh0CojJMS?yG;6JfEFCMEDfP{%QX{O%Hk$FOjDIO_XQ({J70krOwsAU+mi_IKL(- zH>YRc{Y6R|5r4Pe?|b)B^4~%BWjjvFU-Q;0%)R?-$>D>O=6gGyz39Uzbt7TBacSwB z8yl6?eIyLa-h`Hx7Qgvs^zpW_qv+*%_YN6IPZHwq+H#U5;Pn2~8FM%Of8;Ni)_Y8F zw%N|=>iP4nzM5~{I{W(C)itlz3NLm)96nV$OhU~!>h6snyW859_1kI1@7`u@rg-7f zjf#}RZGvvewm)}@RJAO(w_xGiEIFxj!J3|xtCFOoW_)}sEiKh{urP9_OJFfu|Echh zki8$A{!Ua*j?oM7@QmmQUd9u@zpf-b-KAh#j-l^-x%z8gmZ`m7I=$}s!uE9*l}6v3 za?b?eda z*suTe>k1Rz-}A1na=TY9|M=^+xa!=LElS5D_4ieL|MgWlb&mH!nI~VFH+OY~=S>m# zb6~N|@rboNCT|}f-~55|_{LOjV;9qka#7LM=j{LQTea$Y*t#`U&*uu4PW*U3R6ES# z_U-vn#?S8Ex;1xq+0?y%%dE>^ecT>j;P}0f`Mpl;ulG}@p6}2Uzf*SmVEVksu+Xo+ z=9W*pTmRo&Sbfo)TAt6Z4p_G_Gyb1vTmQZ+p2baV!}e8O<`PwW@@4aD%{pFA%e|fE zIGfpv`_``7>bqxVCOn;W-m*RM=3MKt9wqzfO7_ggk<$)d7wffne)pfCp7`y{hig9b zGS5HWZ@h8l%lXDW)weFI$Jg8bQC(K|uhQk6n%|Z)^Y+#pVmbcsF!zI<^J+HLUtDz0 zwOi-=-SU!OU;YcGew(lO_hx!`-KWX^ZvFcn9bkOPbaWBZ{No0fkNmIu`0KTN{+$ZN z!&mIS%WTex{Jq3eG`{xeor1${BE6EA3a=%sh}*fT{_n5a+2-f>KWs~=uh$S*(V5C! zRuW=jk|UaX@g2V%N4wM20A=Z=ic2C-8$QK`un$AE?&H=zh}dvHt9#f?`~{7+`ERm(DK0SZ|{2R z*B_oedw_LOi zmm>~^hMKMpZ?E0={NF?QS1yN|8zk9pN#|I+5n61tJA9pts?mfmcWPSKT1Bm$T)zCs z+Nio%zI5@F(+O=iwq+bSXD`oUn8MO%S?1#v&(3qi;_rL5NsM2XaBp;t(J9G{oVj~@ zdBf@Oc>9{WyB?pn-=FsJ(c!mmw-r8qmy_4`=ibVEMx#)xfY+D$PZ|5oi`kv#dw-Ux zcHJjoGl3s=PxAA{-;^2X&%80~QBCU7-Fxq*Y;JVlmHqHg;FIT#}tAfqdrC>5gA z?xIrWq4!VcG)K*sEn5%#-?q*B@xEB?f3iC&r{pw#d*5r}tGxg7+?}({j?U(Gy}WFr z*y-T%yQa(5zxUc;kbdUC%CkRA?^$GC`oM3OQTw1Vwf@K9jDXmWcPq-@G+Ym{E>2sq zQuEUpn|!To_yS zug{a4deZbSJO8(Rzu)oy`)of~SbdY*;?#S4cK!YBdwCh_k+=VjottmJddH5mgG{%l z9&ky!abx4h&1r}9!ZV$jrJ(ngvb7bZ!T5x68kN8d- z7p5O!$9P;`L~U8IerM&QXJ>hBZAJU->po0$pLcWT=MU-gW%vI7CvW%n%Z+PcuT8J# z?0>hbIs4k5A78Kc-v7U^B)uk94ha6M49}!rVQraW z>hG?0&)PgMkgc&5$Aj&@ zSnGL7?#|~ir*E%4moV*S>Z~-~wO)h`DVtf~N7MN-VS_PhZ(0?}5 zq4VOQ3Y!Ao)mOVdE%@Z&I?3q$olVB`+U?kREyXl=($2l-6x3e$=B1yO;f7VKvc9~y zc=f8F;g_n#*>)^UjGJ$s=@wvNEELLh=8b1Gx3ac=sPOAa5?cbF)rJV20zDZE89v9B zBdSv*8J_RDn^(g6LqA4l>G$v7oh6t2UH6bHfMG|%lf5&~G75gsmC3)kNi~vRlS`)N z?-rpwH=2FshkuOiZD>?gRV~{s>%laIfzxQFPr&K9e(DnzZr!?d_3G14iyV91ot}UG z>7>-4zQCiyn_~jg%!fK2>}J1Q8m?_zRLXFlY3>7IJtoZwYuB#j&A4;<^5wgCd9OFR z94Y(48ShxBAYIdTII*OB2e;6@z{PI9GmTg;_5YZaEH}&N_q_<6&5k_mn{6Y*?s4gD z%2&7krBE$fHEnX`>3}nO6G zYx>iXGofis@QKF)f@{qUrA75RiVl@dP~@sq5R}|9fiH?Z+_{V0{OyYlFBugpSBKXO zGHt>O=kW6Kwr!cbM1$*wx=*+9@w02RR-2x<8{%^>E$ZdR`ue{T6WQlj9TB^rI>BxM z}puq z3&fUqA9aZLT&L#c-lvh`{D?>LneT3;Eai%nZQq{>*?qnie(2=9$7k8MtE%`(8ZX|o z#q8XiiQ2bZz4ChZ6h4pU)C@j;ZiUY3voV}czjgB5)0`A@?#F%Gn|xmGhmO6pU$Ii+ z=k9iSlM`EAAMf>F8Xzd`#ywr z(?YGXKcP>ltnrRwrAy@m2`8l&(obA!+*lhfUu1o#_d#^h@!+<75=$D_FPXjQ%kyb_ zC4Nh$?30=7>nWrcTO|JBt$w|1K)zb~J-Z0m`#M7I5p`}6+=I{lqz@=Rvs z93Qs7Et|earLsS+EwXHEy!2kKb~WRq13k+mG$MOCm{(kCuD`J*`|!2g=v3(!pQ??5 z|Cbr3ohkYD_4?F#eNGl0x~fdsEsY|U+{ZZP9C42Qw$y1WTWr^@v_%V7yu5z)^NKAe zx|V(Qw{3AYIy&KTWMz^BU;E7-_QgDoPB)o1U7384QLp_XN1Dnj-77j1JbRKhfBdG! z+S)f&;Alugqk_?a1G8pHsWm4Qib-^&Ot@y&^+!>0(?<)xnUxWo*N&W9mLb1aecRi^ zYbw)%+6|`4dn+t74%m^l}wc~1HywS4>=f(oCB3wmEbHwQee&Df zet8!){`yLNtIj1wH(snrVO@NCsc7VSM|Nwo^-k>1&ulxvY1}d4Nz^xvm4_O4Mtn#) zI`7gJAu*08zB%ft3ST)jJ3Lo(&lOvG^W99B)J;iS+YW71$a=QRcjELDCuDlJI|=^N z%bToR^XKi{@8F_wL%KBrARmN{P5K=ZpUa*3D&0u1lV|vs?Mw)uRlW%iSfXB+2d4P@gr+!+EjD zDvd2*kmx#$6s*tO)k;^cB!I0Ob=+U9s>=n82>@7Ld7S`}$=A+;pru`oyQ#0d+F zH9v_M&G9riazXy^rYc!$DZbb1xBEur8s5IQU#{v^^FPK`liO@7XHE+`7-y^?k*D=c zxF~H?sgqha|B-6*JrjK+()fZd?XYKBsk>@{Xjk%dKCUerSfh;DbU&?J;B4`Ici`;L zU&F60Zhm<6VqHzUwiNf@Q@LseW{-{)EazAI%JXKSSkH2hB)jiba@cY)|h5PYYP-Xe?5>x~2KnqFd{4?qXOWFK|A^ z=;EqrvJz|e#C@9cuHeTUaV;er=rGDXsMDuV!|?$eAf;JUD}Nt|WEcdOq)p-KLZyd3(Np$`F!0tbFrN zqk;a381eSUPuDL!|I&|b@>{Dd$D5V-7D_o(JEaQQa{b6yV}Ji_AlFuD?gWJ>?a+8T z#kZOlg*hj$z3@QY`HU;qFQ;SN`F<9%m-Srj6mNM8^cf4zGzoh#ufhDYd9&Cd#%9Sm z&LZb(-yO@S*u2Taa7A?Nyi281)?E0s#MQwq)P3#K?)u$qvU`4ZdtY>%b#R4W`5McB zbPk2nK}CtP7w^2-e&&t#6Ru44X(ly zWPV+jdU469l0ingt9$FhrcPtNoPP?cXW7!Ny8GPN;$CmC^FAGPvan(6UHgSWAKBho z7SH)ox^>6n;5(E5u2X3~6t!&g-tsTETorj|9sJI-(D3v!QK=6tHSZMC9|zb!T$yxa zTfyg_iqxRxQJ=_&DHiOGAXe*qc-Uh`&YF3INE6p|ORlUd2+ zUsqsYte&{6qu0V7At{~ZIrf#xu9q49H%+qa68^Qn;K_!Nuou($%Ecs399f(Du;16~ z*Yv5gg^kSr*;!@(yIMbY`iIc)e3KtfzNy*e_}70qwbawwX-m24ts9d>e=Yw1kJ~C@ zR|?xw$GnMG>x`GW1ul4(|6tzbmnFOJM!jR~|IU`#GsTHf=-BB5KE|zWpH;m6_S~~-&YR}c+Raa~wJSZ# z`r^U;Fw=$2rsXk0rzLG&xx^!NFUG%`^}lP@#Mkfo{LbWCKJ&VnAtfYz_TkjDsF$A` zTXt@Bow#I2j9zTdVHex485WL*K8Z!K%Qmic6v{dx=KF2^mN(f8r!hq?vAlC>ijp_) z^fl|8_Lf~+e1IqFw2mle^ljOV%xb^GGK@q8f6WOpxI81FHSS+T$*(`g-06#(pZ{02 zdVlhOduwK8j@p!#+4KK%$nGhuPHtLSm9;O3XOiKcL;KyHKYqXP%1P4#W@E`y3pQ;& zeWC4Z#@)b%RgC>Si;XTgEZ~$c+dbDWbH>EZ2_3yH78jB|f`Wf9acr!81!1 zw#?e(>MuI?@qsg!e|&0B(5l`W_rqnE?^FYBk9pyaQv;r|2VB-TdqL4;My1-bbxzfe zk}JHTZEh&FT0U8L@f3Tl;{O8^B$h0>S>RbJv}*eU{!Olz{Zmh^)#Y+nRgZ6MLs#3H~OS;7G{c9^RhlIp7C@>gY^;d&mY&a3C~|;!5rL-qH)+__ckFBfkCn@Uzs`YI+e;RRE%7iq(Q$jK;xQ)X$9qjZ8iOCLWVQVL`}f5M z{wgzicD%Bi6B-lKlhGM6z4Pno!{Htkip7C}g1f{|^|(z~cmH3SS(8(M-|m`r`3%Vq zX(0`7bb2SQs#`X5)jZaS)9fGn&E8dMr#DJYbuwaD@vHjVo6O8iN6mnv3y(FkY8Y~b za7fO~(B|ljHJhz_u-C=*{J2Z^`L+)zRhgI>1jec2+*? z_J5DM^$+m8d+{P+)1##HLk?WJtZ7EwIjgozc09Ugov^fIii4ADyHvjl$HikWOXg`c zSe)j}6nx^sJ}G5k>>AZ`9x2XmTwh-L5TcfM)Z~KImEY=teCwENy3-Z@n2Rv)s;I8E z&N9-uToRybG{uqYsmF}qB^zA*KN>8&&HIA!NC*E+21V6Jo_=>Vr)MU(@1NpmrFyk< z0;BJeNn8^yxEp2ED|l?V{dSv=wc~3USEhgRYWL^eyUbnw3$&!u)78&qol`;+0Id*= AMgRZ+ literal 0 HcmV?d00001 diff --git a/mods/hbarmor/settingtypes.txt b/mods/hbarmor/settingtypes.txt new file mode 100644 index 00000000..067d5045 --- /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 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 Mr>mdKI;Vst04!Be_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 00000000..fa245da8 --- /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 00000000..a56dbcb8 --- /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 00000000..6bd271b3 --- /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 00000000..77e6159d --- /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 00000000..dce52c06 --- /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 00000000..0a9a7222 --- /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 00000000..3a06d93f --- /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 00000000..44fe4521 --- /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 00000000..37a578dc --- /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 00000000..dc67cd6e --- /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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 LS3j3^P6Z3)sPo9gJX|U^a*V z>11SJVE7a8H%rj|KPm`jhM1(!z`ziZS&*UUUzDzplbI9-HebP0!N|bS#K6$VNI@f{ zw5T94`|y&Y!%MO(s@)OxySGrj8HI15oKUtVQA3c>|6ZIGwYmXx`cXP(E`g% zKa1rG>|KEmEIAK-RZGrWwq;p%-Z@QG4&F#s1_mYu2M@(oksuI})S=iWk<_8sE>m}?sVx8A5ijo|dc!oZ+7H*H#01Bda1L~yWx0$O4rhcgevCKd*Uj)hMYW?h)| z`K%@1tfvcBip;)zurp+~`p%UzW`koe=bYr@ImPERPt82KVCIEc#pgVEW-W!VDurgV zuU&a*R`EH>=X3auNhZ!IK9_lE7W>MZ5wnZWMP8WoY{gEI*~RBNr_5I0x-$e~9@x<0 zb1UQKoI7awa8B{L&ResycXGzgDL(fzWzM^^oFFmu;`F;@I3Kh1x#0BoW1B zij(C^`uQd=Fg&5TM6S2b&1+?IK#-*R(vl{y&lMOLS_HtU7)F4TG9(o*nbf6qN@MdG zqtiMdV$I=mR^NQD5dSox%dM!$O>69QZ&86V*17#3} zlnIV(lHg3zHlyg2=JEwiT#(>|MBE3J^MbM$kfkLVmjdX*JZ9_vs!^?6b zrS$H)w0x^+ft*q*G6sw zVb@veT|R-PiL>Utn5lNTBy`!zRWXs% z6nD>4pQUy=BzD=#RVm@q6i+iSFzEOj`_4-1GC6C~xhV6HiSAir-&tz2U|ie45RhJ< z;Lx4xULPv8y%-X@Xyqyxmyv0fww`$poRX&$PXD(V5 z6nnk(b=9JkyL^H}JD0603ccR?nu&qog3ra$&PA(*Ttic5t>e0S)#Y+&=b~3&?ket3 z(a_+snaf@q`CebTY904YQQxamq1;{TxWn1NceONj$GVJF zFmCwN*d6N_7#bMa85$UbPdO}9)MjkZU|{He>@g{|QttRf74OeBeafD*o>i)x++^Y_ zk{CHlt?Poxd12R#S4zg>s+KU zYuTz@dM3V~T>?dXgF|D*p(?5>$g>hvCr~iCkWqswQ2InyOPcoIF-8nd0f8yY-rphUV65QL0O~ghicNvgBG& z_RJ|)qO#XAFl=CEXV}2Zy%6j#IR=L22|=L7f~$w-F^S?nr6nTCJ(li*L0yK==PaJ0 zbyTAGT%gy~q#n!X8cV$lkIg8a5_C)=`HZF4$|*gD&t#T@xjjK%n#nzeY77i34lpt( z9B`X>meZ|?i#L*!VF?q1h0O6yCcc+#{6$ocZ`3&tE{skW>YN4##N^b>S&(o%eF+o? zmqS9Ay#$Bgt6d>iL7^Rb6)99086I%*F*vZAt?4TWG7*c&IN`;hz|7EK$flUW<8(rz z1=Or)5fEZvFnGYgAduiBsbP|$$}oY8!9ilNNb)&P&y_}Qn$H!cT#8Da5OmH_W9im3 z&82giCk17n4f3*7S6zB-mZoHLfS1==)2T*m3#Uwp%0AaA;N-RT=#4qTiY-&3x;I*? zCu?eMl}Il3I~Ej_Wq9n_oZxj^#gfl@YA%h*);$)*&ESwxz`$U=A+fY&@}i9goSeg$ z7%CYUCIoqbT4g?(OF>PuWm7=mJ|oym6C9q)MUs0ApUnX`+=|bE)b&_C2dO(Y2f{rE z;Xa>J++%ob1_Q$aCQt&Gb~RI%;M4;7QGkzuLE`X~;&YA~s#CcXk13RZd=biF$fnp5 z6qKc#bt59w;H9a$^jcJjZb^`r=gO@Ti>D~HObGH?yH#SY zuwu)kpe)^E&*tKn7@nw1Fi+7J;-uYy-1EwgotWErMuMZ4q+PfHWUkKoSs(z|IhI;#kPQuz(p9 zpUPUgNBoS}*)X|_82LD~wyj}dxWvT3;Jjw*wW#d1Ac8jt##+18O%oypmRJdr1+xZ- z@CNx5=6g`cLA*;8i}41lG+)C-VKIRjp?zd>~lvYlv_4z-6oZN*7SN(kKr*6`Q$ZQuiYsIJ)HbU}A#w>p^@bCP;VPfgfxI1E{+WlJ&1*l@@3G z|KAGKVfP0S|Ba5F2h(8;yOOKl{be+FWPC1n`}K?X0td$D#kTeT{_I+py<)4FLwR}Z z_5S0JKfb8@^X>lYQ$C=^%HUeWxJHV5JL>}*2|rB+ zhK~7ff_Cx5Zqq$k5#OlwGl50%;&ZM3*;CaFt(?DfbnIL7sKVwPU-b9iy8=GHxm9z% zFZ#=wm6Km>X+H8Tg`1J%>F?|N#J9y3oYZSOoqPAw>z_}{RyTjFs&(F_U4H)G|H}ct z>n`cUt#5ty)j-7g?j#Pg=t%-j(@d-OuD|~J_1=yL+w->HUVBvWRf57XiP=|cuV!$+ zJeir%Ey(LD6}0ZE7GM7PN^jG^sdxVFe$V!5R}qKe^8yPQpG3U_75~cQ9L@IH+1qp9 zUGZA${$kVI=sSD2yl*z#S$=+|Pjr+qPy6?SDuU|oPgS`zC*F(_EhyenYy)$iZ+zY{)w{k!fd z-|WxdXBU_4Uc71*!}qOs7#Cct+FRD%diL3$yWcy`oQYX`^!M}Pl5+NrX{xgizkdDt zckTZB*S#~6T^}8@R<}Hr`Z0KJ{r~!3s}&7rp6S!K|NH8V@Q&{eo9?xpzvaQ~HtqSV zuYF!>lTTLh?+H5oS-5nn{c7(M>HD|X$n~43CTrZUtILyQ2)K6t{`Z3dPi-onik@aX zy`AT|(Sp}^L(6yeoc!$h|7B>ZO8%SgJF~N&WteQ*Hf`gXTeoiAiemd7!(i7^{Wf^= zL_P+VhjPbbj4y?=iT-$hx_qVVl`GeF+GVW>ak{ho&7+D^Tgwcyoy)}dIIcX^o%T8W z)M=fi;n%0yoHJ;;?Yq6?rqJd4K}A}b`dydperNjpRoeS~jm6dmhDNK*>@+XyRqL-F zo*8=7wSR`f=DA!mr&=DWY!@h>l-JUzmccmTT=t5sb-6Pib#(YGk+xErW1|(j#G_v3 zWUzLCw&L8?%>j-lxkL_^#7gh2pLV1BwyIqJz3jeQ#cz6FzPH`%995O?5WG6=k;Tl{ za)EzJc~3=lb(Dx(^1H8HbzMbWj!}NvYPLA>86rFcIyhx*aM6#HZH!;HSflnbp^j> z44mM)*72G4ETMvoMupg9u2ojDTf>5;Zz`34#vv2sWW2esVA;~J-l+CSvrh-By>ryG zKHgKDsp{gS-8rN8iei$z}_`44 z>(!li)$*^tuKBc5#bm)9`z6{ zYWPjJ;P1cNc|H&S-2W$}viy!@u=w+z4B=_d7j1~#dHbuu+^>0`9%{PUEq*rloorG^ z0B3S2+hM&_>p$gh-p=|N^6S>KZ>HMW${c5R`sxW^fBE8IRKz|xv$dh0(Dt^0T+=gy9G+sX4b}(YH`m-^==y`X31WVmio^u;6%Jo+N*yDM$Xxgpp+mBx8{_D7;vu`n{zyBT8o3px%MCR^1 z)EpJC>P+k>Upcjn+Mdl<^O*8Fzs|WiclW!rXJyl(UMV^E_CLR5*RiWe^Y%woyMN0B zHZ|7B9re{S{1owuiRZ9BbSgN~R{f9|>izi*n_ud{q}Ibmw_zo}X~rak(2apxkJ zl}R6FKRR3c``PYufj$S{GG4EEr?+R#h4b3Vbu;_9m5LNwS@&t) zT%US=_v9Lbwa<&bJGtJQ@ix3#VxC%`K-5N7+uomg`p-1Nul%*0UmLV9T>JOw)w>xF zJoqvTHKC_RswGZEM=?<7#^@1CdOl0&-M2E+ z54OvsQs?IB{oeb1$KB^|=hUX}H0+t&r}u41Pk-zx`FVen;>x9COpLB8eOK7#CLMkA zhk$9)ihN71ouwW1p^Im&mx)bIIeo+Lr)1sXHz$9^`6#_yskrsg_4k(3+l;TCx#0fK z;^WU(`$MbL1WyVcEB%>YX&dL;oSXi7&9a|+ePM7;;c>Y^k>YX{qq<->a#6x-!Bp}%B8oeHCV8N^TC0K3>FM3g&b$^sv9uR5|uCTW8CxOK*Vavu+885 zWD{%NeOq08Pu%RS<>OUPHzuoSz2?~&WAI7;LH+f67gYbnU%YQ&x>5W5&DHatJ=Nj+ z%lm6DcfQ!;jT-em|82KLnf?{;pT6Gc`J?}TxRxBS_ZaKX*?8pE6 z&%Z3WRGn@9zL%r?VQ|c!QSUi+%s)*RMHeuxafdnYHebKNfxxwcQgf zzVu<{x?OgLp;oiz+=G==jk9?`z zmU(yDcQ-q!jH}D*rY&B&OZ%_g@8at-6MfDfeI>+s{khFOHK+WRImaF>k8OIp&Z)j^ zZ+)rr1M{WRYI@rL1ba1SxGR5Ic7?Cr=i=+U(mrJ)&pp5M+i$Hr=4W~9sM_i?+jhMX z<^Jr_bSu`XOZvEGt<}=+doJvqk{v5}ojv+&@1l)IRoE|RE=`-*`uY*4LRXGW@wa~W z@0T8Km}!!caq3R?!3Xp2*I%`IoBnq5{>f}8U%i&& zd+QSA3KPHR&D^Js+Wy+d$arwN-e=#B9sgb4y-Pa&`RJb+;T^kI*Uvoo@Z*Hu7o}-m5ymXu4ZOb0rBd1IG%HvlDrQSZ&v}$VPR0Fl8e3k18?RWC;?2V8u zuP|-CX1tnn)y6RY%ep%b?ead;+hKo;J8MSh@fxS3b5~yNRjA&wPu)&r)7$TryZ>eW ztNK&6{_AJar6(8v`ThRK{W^}yLU5m@*{VLYlmOmaiMIz%;|Y? z+m61>-LY!Z3>~f%J$VL|lOb2!GYbzYxw8r1mppxMN~Lu}qM?p=PlS2y+LxVYZ{%JH zvkkU?bGM3l+p7NFv;3!d-?rb%yZGh8=5;%krS7Y}sOr*FWb%8%lwG+sm9A4o3h!8k z2Cto_XsZ99e)UZk7u&5{_Ltt@<8;{eaN(WpJL>k9zS#aP=C=6$)+)LB80&u%<$}GI z?=$}U^yD&er`tE9Pk-G0vwb(;+Ig3%&wI60M_iKF#U1qfUe>E;ZT}u5c?*g7?tXnK z^z-R(>t6Mn?+WsS3La^gxt!cI>3j1BW#`jUl9OiceHyakbQweUthT^(`;TjbR@Lvg z*5ULm;HGj|+A~+nW51uxKfj{f_OZv*sh8fb>z!KUZ+^A(cWTEk*|lFb=FGYs^lQbM zdw>7T_*!|*fRnZ9cX8ts<##3X4%OVTT%~ZbaQ|=R+CTO&)>`Kuo2u(b-`=0N`+P^r zbNzMZ@z3PW|2(M6Z1+2Bj$)-&O~muKHw$8aO-L}f?DB5jOSy}0Kgrm2Dzq+Hv{&!k zwd$|l%XX)j1-0CJ{CTIu+r@vM{64F@bIty1tVX7{-J4H7$=@!%;;Go#U+*UH?@wmj zQO>}yX7QT$hVy5iuKsnqf8*sZ$7kPkeZDu~N?U8dw8)Mb>4}n&9ZFAU{Po?ZC^B$k6MLvN7b$otDk?E@4EDFjs4<_$e|#KhV6*dZ1w8=CueTOrit#k>L}t~dnv=;OQ6p8s8Eu` z*3he-<|cd3?KGLgw)S+%z5g?B`WJF|*Bs}qFW&7YI&lh1?{_v^BVVVUb?fk zU2gcfX5Md`IhJjfNi)=sWfoq0vSi7MM;7Yp>x@qa+21L9eO%RBj$8M{Vh*KH4WZ89 zCB}{{yrR1EtRDCOe(c)vsN_B0an(|eW(keBO1mFNQ!ew!tACp@oLshd?!U_mbgO=y znYMoY8RylNVQ^&8ei7r$ImE`77!B1=$Uj-#K)GjZiF%cf0i zZ(UyLWmoozKf+HZ@w}|5?UeA4&ohqb-^&&7e7$ryU0KhK?Pr@Um%iJbAG!PN-kIlqRoDhy zUUysEGP}9!XY&0@i`Z>PTmpZ;one|@G(CIr1%)~bfrTuWZE{ZapSp8={`A{lMV@Kx z&8+4&3C~_{C8K!p?SF;Xney#Hrrlq|#Gd%cHt#&>|M`)ANoeWr{gEZVlMc7LC-QY$ zbu=mQ70$aadVTWbyWbl2y|8*GSF=Ut%e!yOem5rXxU)Y(TtY_eu3Av@^V91VUz_y# zuTwhb+|&Hu`j5_w42bxD>YlTLsQ%Hal(Rpp-X1o*)W6$wTYu)e9Y^l!?YcgBO&ZG# znKkEX8*-1-a8 zi~r{b#@K(Je!1@JuXvun)PzY(&L#8r87>6&%OC+ z*SB9DSI%$uEqyBxc35()?&;+HcQ0?<8q?Z+xaQpV*|+BHd$vE!(xdRhb%DJmB z{(5%J`^kUn)gpCnb~~rpRj;1EsoVeP=N#MRch0RkY(8a6Xx1&)gXda5)Fz)6Ut78F ziUem&%Y^;AHeJ2G^#0O|`mwz1@oR5?FIx9yL$_J-@3ltXuWx%Ilgt|T_`b=k^rPbQ z_gGx{bieeth_1K#;w?`nev4L-_6Mz4VQ7#-3}i7gFfjC={I4y1?aH0|k8fSPdhhnD z2M;b@dhqbx!<2(+I{m#T)4h`ge1vxS=ggU!!M=@I;@fMnX&da4G+B4gTIOob9sT>7 z?Z(6RW!&UTXWGq6Y>$6j8L+mmL$Ne;`_oI>`}yta@~-7w-SuP1)n7r!zAgK=PQU+W zVY0`Xt{dU1-+ZIqt&;v8^`xWY#@Va$9ClrOFLzdO^^ZC~eqa8-SyFSa#>*K@KBTkV zSK#ZvzgHjGN?Pu}F3!LIx%P_ZQGAsP)Gc;YFZnfd&`1f!B z<7oM}<;QMKYtEjM^H@3eW9H?gRY%V^zbgueyt4h3zwYV1HIt{gz7&|(-~LyjYWa%Z zw^^yq^X{*j{qyeGV+Ma~@9&!*x@pQK%@-vR`-C_>UsYOt6?lB2dv=M?*CS^y-06Kg zQ{aN~x+fxPe+^C6ZEbSywkersSR`EJjaaJvYPHK!%3r#PJ7e|Y=;4VzC`v9auBIux9| zCH&&7CDU0CJg^ekE_>k1&*#sN@2|Go7gcNKc1x=H;f&o^!sj0~s_;vBsW*GqV#&JC zN1xg0-e0rBZm0CpX`gMYoBwOX?)A7F5Vo-{+Fgt%izoM9Y<~LeqvemTt0ymb{Cm0h)V29j@>1l*FMr~fy1iiU zxm^v@)ap{ZzgI{6Onb+D_wDP~{}W#R`kYV^YoV1qr(CP#$Wf2YhY$Yz)xf?lRQu-E zCkNj~9Wj_}r7rn>=izmA6LsfG-uo=}rTW(@)g}9OS1$edZ&6^y)Mq=ovs`O+L-wW= zR33e!JAd-`mq%sYXRcV2%YH*b^675Ar_b!}8s7VAdNbmWU3ITz{d}>%FP;?z?>7tT z(_O!C&%M>(dLRCsbM~P}a?Nj5wm!M~N9M{l$O7j=xX6^7Y#ZFWahB zp_^a1$8K5i+`c&RwxGx5eg7wyhh3bpQ|R-qUmb~@1^E)TrN^e;%V@c|=)UiTtywAt zA?yA;6m1Gzbw4pISGs_&syOIYm{I4-R`){Akl(N^ppDp?AWY1HF0B#5E9)D|o_R!hw%eL?*)CezI zxJzCH~kt<=?-yz+d@O{)u(( zKYB08@YL63-{Q>WUhi7>tgXNFh{@T5GJMD7?s;$czt>#wR#teIT)5oaV6CF=BYg)a z-(Ol;vgI)UgO2pc4@lc_N2GHVHa~#MSrfJuh_|a zqj#mx{PgM#ch`H|HTblBdFG9!PfWrWyQc-dsFXZowqf1ES+{M@TzKwKy5hU#oyhX) zw(BM}n^R9E?>7B=&#mSCnSyzJ;+!2Pe?`4}x$6`cyWRdw<4b>1%%%rFJvLoGBjzr5 z{^1-=)*mc)kIIGGYtLcjOzm}>DYt3L@B2zh9eW}VulZAOeIJ8;_+?X{Zp+;4z{^Qe zW{an9nzHNR%?S6Ln()IVwTr$azp+ian31x1QWRg^+12~k+HOlWIePDwlx>jM`&*wP zzb(A7^ZB2By2ZORk1zIqv;XUBj$nDEo=49Z%KbmSJ32{p>#Mk$eKW&l_x$B6+W7v< z{eL@!Ggl~nQ|Qa$y)!lZePzl6?`!Sr-UMI#`~KaJ<^H`D>t^U|UG8}BNqAne!oAQ} z6OYXbTAuSfvJMB|8@#aXw&`yg9~Uc%MQw4{w zuRZ%JY;ElJ4f?VZH+_7$weUsAyL(!jSLwX>m06lwXrIi{C?Fg>UXOWoc5@A9s9O}n?=;SWxm?3(`g?e{zHPjC2r zGu}c*EBdKCQ_fbVWBXo)?78I6tz35Ad}@zxHoHWsr~i|mH*$No-P`*iI`wy_dU$tC z?(w$QQDK+u_fA|``Z9iwWlwja!|Bw0g~w)A?=;<#H`iO<|L?zT%g#@FeQj5EZF_Cm|R?Z@PILYp%6Ia02xt6to)@A&iz@sbHI1Z`aO)hfE*fB$}R z?I(-<<>7Z*vg*%-yYJpTpKDvO#g%`rPkmCC{Z)NCZOTTaM|Zotd^tK;lw5UWmo+b# zrx}|A|d4F6n+K{I4~?`^4;9=l0ngyKS^9XM6PT-PaFWuCq@%eAQ^% z%>czyA206j`*^FMJ^%FeX+0-Q+V9P~@hewXUhbHI{wb5iwr7PtU;SJC-(|h-NoJo}jYgwra5W#?Dw zhri^?wC$4rQ~$$c`SAee#Mh@=FCG3}azQSG%gsyVgV*t?Q{Uc8uCuIprBb!AZtj-s z>JV+I=8Fffu1=E>x4-&vo7SndtZTN47z@VOTAXJ5w&hZy!ip6U9NFw2a(`@^@-HdJ z{GalpFv*>bfs1FSnfjf-cFo`SvdOt`8&|D0JuP!;kIlY$v%4h34hQ9I=?^^Kw|V8c ze_NxTo{h}$^PHR%Gw*c4m566=Zo7Vev)5yW@2uB9-~YaLLh0cG2AZ3nV%G3GIBJ$l^a+f1F(JsV~nQ>bf--H>xx%;s?UEW75p zNnev!3f|k%9Di!M^7Ck}+vVFU?B@CJPM#&ieEo%4eZjQmyQ#O|>h9cDWyq7VVUnYt zz%0SzPYUkvAO9lwzfINnQIFzJgHL+!+Za+&HX9vyKJKP&xu_&lWw}5zo(ggHRJnc{fBF_|9jXKo_n>;^aSr>Htmg8 zao3$PykkWcE{c8=d*ovc-(&Tvd1}GWx1C><&#>jE$+>Cg7ERcl=)B)#%Tj>}-`_H1 zg$DcH&r#2`pB15#)pN+i_w}ph^ybT8D z558J;et8D#{Y}4hq*iZ~tGgC^Mz_A@3eP9gYJ2YYMme8^wV$sDOFh87L^9CprnfG; zckkZSOQvtS?d@h=@s^>iE3+fh_*2ddv)rz9$-OzeMIX6Dwj>ubkuJNxZ#^Y!0$O2tLk`WVJ8ZTdH7u_E^$?b)99 zDvs6nyx$dg+NLe@=N`@9A3AKV+RZ<I@a*w6z#b2%W zN%8$zHEW9E-Uj_;JAAY1?VkxsY>CbFaya+6T4&ok)yuDctgjcE9zWOp{fwHLL%ZuU z?LF$5jvN&V{vLbKIi~!?Q`Jj$(p6{fY>47FP}BHQR1vfESH!p6{}X-9^M5Fo)_+#M z`03=TmYaoP|6lEs(7egN`srHxXR5a8}?q; zO@7x2Z!?UXa%l2*i6+nA0nG%cOSO4CQ4@kA&rxNUTat7CmouYSYQ3E2n+g*tTA)md#Lx=XP@Fsp)GX z_vXA#h_9M$@b+)qVvW=8dZ#Z-Uwi-Uca~R$^N#7sk)J=PF3&0FUGT~B_ZJcMdi(B{ zPce5g>?i3jnX!Ar{H14u_??sL?Z0l+w>hzQ=f!24rt!x#eYpFfcb}-gK5L49Y-Qy6 z!VSM1zv|Y+)oow6OgPQpmSz3I3kk|q`Kic_nG#yhJww@th9?wf6UJ4;LX-_CbWWr`;InkYvjD?^arupI{xV6 zHN|IFuRdp(K69z}-s?5IRxUH{9*mE6OnLf?ZS~m;wbkd1)BauEywm2Xj)UZ)f2Akn zwM|#vH~f&?GxNsO>`=qEFV|OF<;}>^2}{svu6i1?F2ClUx8{P6f3`e7X(g+-q~A^Y zUHFFQk1B6Vp0Kx%Z-4!6_m7&-i<8nHbC&N(dT(*0eudpKzQ?+2Hi{Uyuk;aaI1{#3 z!^2!NRFdfy;}wCep^NWqUiHwsX3esP=4S)1Zko6(`^VRu)jz7k=5Me*-#^JzY_Xo? z1UZq}r@t8Hzc}q-Z}aiHd3*LYo6pVq|BCW5x-&}u@7ws~_N7Os%&(tRn}74PV%P0$ z#wT>LLQ|X8$gVrRe#-qY^QRxw=DfM5yj_uxjoHu5awk9APglK#_m*{^(%t%Kdtvq} zbydS(&+opS{^O_oj{BwU7mDnc{*eFeJMZt#n)sgNXOV@?{ z%(IR?Y2soxQ~&u!zmWHJ*|0q?Du}TM(2AUuBGE^L-#)s3^U}R*m#;s$e*4kQE0?c7 zxtFrGr0Qwnk*|eHcYC9Lc0N?hd^?9Thke5=wPpQR%T}*^_4syHTI8%{nXixUUH80H zr~b#=y*JsFuRW}iklc9r+{DwXmhD`4rrEyY@Q%d2r@RlJ(E0Fx+yBd-Hs85?W0LAb z(eDx^L5I#S;UmQTI$U+}o-k^RbVxqo@ieDLCB{)Gj%-u9n9 ze)5}saFF4B37s?X=9<}i6kNUs*2GxZM!x!Tf4YG6{rSl@HlHpY)3f3?`(t-m)-TgJ0@V>Dmt-3>Xrx5Z!I==?*kTS`7f^xVa>8`j74Z4{b!_+NR= zi{-Ned#3XR7WcoN@~uP1CC^JF;h%xW>UT?0ivR81wCnS0*(-H3F0Zaya#%Llx8&gd ztGdf_{;ap$miBpLvDtK?-yOO^w_d)Szv0xLXS)_9O;av;{r>w#&D~<(>EWQVoN(}KSY^xWU_zQ zIHN7XroMhkw5#q?!z8VajzePI5A)B6)&Dn|9l6=yx}&bLQQpc;o3nQPmJ51*DW>N3 z?9!FLi=G*IuihNDcH_08`MXwUh}^O)?fuesO-VMOg1Mu|blQW}jRhB#WcI92;aFz9TQ+@wOy}EQp z?bhn*hm#hZ>6*z?x_qnY@2o?DH>=lh{?*oWer7QD{pp$=Un}dT)aC}vdw<4uSO0yD ztl4W==WMmu*pT>0BU!g;t*@%px@+=Lhu=KSy_iI=*%KU8SzRQ8{v-YC}QcERVvN*SIoK+`r!`Xzr0vy zw&TxSn|*(Nod3)A=hM+i;u2>fGgn``;?C@&+r6>vaGVTdX4bn0Zkr_f8XLaNPczcG z^{x10w6E#ewS7NU#=84#-t|qa{_y($VbM!2f8JR9W#I+s4ZP>C#1rqs;njU&yA9eODNx? z|Jy2F^JHV5&vg4DQHOgw3cF*k?z%O7&Fa$r+aEt0{CINtXP@(O(GuNSk>5||eLs4s zc>RplEuRYdcRZ1M8~RK1b%#!fm}FLk*y`usZ`93L+TS(*SLe&y`+RREZQXb)L^8ix zKHlzM*v`Bii=*AP96PqruvGTud-n*o!o3^k?M+|#JYd~C>t{yG_P($CSG9aa;;wTm z#o3E8Hn;Si{oGcYU`}T%6S*+h*RUVZ%oz26(UG_l0<*cn=Yr^s+Huib^ z_#}LNx|y|vXYE=N9oyzBj0A#3aEFZW+x3p@XeH}TD?3E%SV zmnQ$-zO(K5vb3p;TlXClJQHJS-ubfXl&yR4_dCfeDF(0|GgF+84?+FWsyYPzOS33H-~yhcZceRxt`^Xo_*1L`_Ia%mgm>kwQUU- zUA=HwqUe>cG4nU&Y?HTZ%a1HCiaTAuU%ggXx?6qmx##^S-Q6ynHGh-j+fwtd_{(YA zEtfAep6s)o8RA|b`Rz-XS5~($%cR>0>uaPn-`_j-VdkXJ-hZFx&R$pV5S-lozuG7M zmX4I+z8QbNoNiyM<=U@qRP%e!lB1u_iA}nsH2eN9Gk^d0yDYrFztrlEf3JGgL?}m< zTkx>4`8h2%_?Y_5JcYoaOtgCu#-3`UI z_{--)QvrJf;m&o|$XXDjD6GisknpS;ujy0m*$=b3ueAM?_W+s~4{x;$^S>oWWL z^_L2NKJNeM^=A3u_P4p#4_IP;cG{Y|4I?tiZsU)^c)=k(dF`=523_n2jLNxMqXNo}9$?Q82Rc^=QZU3UIz zK=BiqPiNzt4S%j(cS<;A;j*{+heR_COJmOktU0gt&Un_(i|p_2Zn!DCyyj%`>aHo@ zX5arg{pnGI)agGa-JZ_HdFa8jyZ(2+Jb$)s{3O#+cJh-SFHbJ` z?I*J5dl9!}Z{6;}``1J6#W)UkBq3bCHQ>E`uUX}M^{;W&i z&+b2dt0;ZpyJz3zsLf9Q@$t9ikza4kFDw_|Z_N_(cF&@1+lyu@o^nvOTm5|bP2K{B`+N(+bpJ|u z|4KIheIY2XrMzlG(LN>fH@E$ECunD}-p`8oTO6~-OnKQti)5d)_^6(*;^&`s{_Y4h zcv@8bR?$EFa$M+PALfD`$Hf{$0_%`kTP*w8GQJ7cQ48TpU#VdY0rG&S1qo zYhp4S-k*|?)ITAs^j@j%yz9;>%P07Ft*Oa>mwvqIp!1UAl@GRl+7hI5ykPIP50+8! z=ZMiFl3JB4V5bOS1B(J)@E%E*7W5<#t&ONa9J}q`Q zX`{rCANQ8{N)<0Yy{SiR>#bYA>}rGWd1^k7jP+f8RmM>E`iJk+W6Vz(KW?6He?QnV zeV@(i6Qbug=?K2Ecx!a$UwGchwP$aKO}%;9_iI)Zuaoh|sIPMZzhC@y$8VDPXO^Us zhHH1N=K90CSTApC*1>;`TYFXS&eU9F*z6d?WW%&H;TySYSJ*#((<^Jpnj*SB*v)8jqgjp>Jz%e^1!BwV{9S^5`{U(cMY!B^UqcJ27Rg% z1&h1l-+LA$?C91KT^Hpm)wSwMsv7UVbK=tTHn#6KjjC5On|VKG+R}^*x5Dk$=C2ak z|N6nr1FxQaTvog?IqT;W**oX=O03y@YL>8Vgsz9;<$M41UZ>4IJ$dzOd4?3r?#@lA zC(kSDgr7-T)6>8i_rKDwXI-ICy=+YU;gGiduW#SIqLqDpt#o$g>#FICvoqTgEuKDe zbL;*6V_%zX=Hw}_ZU;@XEB$?!`}eo$m)zgawzG|}zk71B@7=SvYTrq%lRo#O=6TQN zuVUhh=AT-~q*K4pjG5nbThR8`Svy0&F7e?ybSdk^a2{T`LBl-*X#h%;z zlb^hubnoa{$Lm{*E=^r^S4v{bwd%N@=WiRM0u=W?=lpUizT~U-LiI> z`J$y)WpYEU)6U)J|NQm~%s(*k&y&?>r9Ra~Ok*+k4V}B$?P+azZ6}9u+AC|1s~o#l znl98SyQTU`PvQ5Hu4+%cEYBya58C;;oH)?+>bn22p8;=evs5q56L;&ge7!~D-@L1( zcJ=Aj)$#JBg@xiJ)!nn&=C3R>xndo~mlFDSMTpL8ZjFhnCy6Pstr0WjP~XP9VpaML zsdv+|dJbhp=$LKwm0sPOpZz|$u>DVq8D;xy zFLx$X_Is^%_1<@gdHdc)oh$2J9{OUr{La=LMl+AUnRelF zjm6eWOS3oFSW5><^KMO_3itwcBb@Il>|Ov%sF{VuxNg0 zvvA9%NY2H(IXfE47)-A!W&PN-s_)ce=huI-^A6lQr1o+j&+E9@!{wE=JLdN;f9LsA zaNU+DpVc>3^u@&G;=<3a zi|_tU_x-*r!$o7lXDy?&XZm_t@7=aLc72GKcKID1iOS6- z|MxX*b$zxuU{68byLJA0%jZd6Gq*i@=%v?J)27gWprt-p{b*7*50!PnnRPxuzmC~ zJxFeqkN9DJ!Ar}(l&p8}e#x|-Y3dOk{r6jD?tT~H^^0-Bx;u~GXJ~Zk zeErAIUzeI!oA3SbZI66rR6%V$^|^fq|hybon;n$2YFrefap+*~eENKe>D9%8iG29+zCKnbKl9d&;wkuG$ND zBepg+moeB2el^q;JKdZqJ#AW~`Fr(sce~yuz0dy<@V4V(&5CC0XaB-pFRb&vY~tJ9 zyXf)hQs3zLf^A=vCHjxPikQH z`4L|}RT)oTRU01b(bd~+zLPyB)_bOzl(qH^>;0>yx%Viu*?2^6VeZhJQK!0n`>!J& z(qSKkFK^G@_AZ%ob?=Q|U$?K8*w(f;eEDswpjB^g8TIj{p4)8{y)-J9XLVrSqFwW> z{#MNUW*7hd_HMzp*|t00*ZwpPH{+STqdrW1nbDt)mPtwm&yyY{rkrQ`of%vGwN6#V zyo>Wyx$9`o>&)4dQ{BD5ms|UCd0eQek^HaPBKdazw>nY(^=`XeF<g@qSfY=+qd3&Fgq!^ zZK>44h|}IbH*QG`v;MPoS*pjus#`rdlWs)U%50a4NsV0g>vTYja<%1anfr5==R7=h zUP?26mfL+l<0(B?B46|tbL>AkrDSs0ileXjtA74^v)xRj?7GUf3u}(gm{n`gvt#e7 zWA7xN+}(LodY_8vuJ4P^ZM(g5zvKFviCM*+;Vd#Xwa@!+{C8DcxApGi!yA7@NpI56 z_kGH#cKdSm;`O`F`_J*0IpPzy?f6c)sWTaEc6J4PQk>Ch;CN{@OX_z4S;w|A21DM} zGsG^NuR3btHr0w(>zmF?TeoLgdOcM<%hs1F@ISGBmfhRi(JQ){U(zr)l;^ik{`=%z zvwq+Fw*Aw*YVQYA-?_Pmu6FT}oXH`?@RNQad^txwD zUC(+MHkXs96m|-)(&AH$+?eE)lgDJXg;^pgRI=v#qO#i=)5796&-bef`qdGCcKX?% zyek^zt9owctS#ggO-aaE;X{#Mca^EjWhu-vgem4H<*Hfid=iHZ`m0I_3AN$Wa z>%yjA{~c;8!#B43}+YH&sY1nB+qYovQh80+w;8{UY~C8 zg}#6NvsoY}S@Cnsew{zlzMD3?d^@jy`2S%u?Y~#~>*RB%+pyN~nog88tB&+_lALl( zXZGH=VlUUrH=fYYl6omNdxQL%qZ^)^=iE-3B^GaYFVK7Obf?IUiPxmx+%Bz%lneYn zF|bZ;cK-jf*^z4($GY$O@;SQnD^vLVlP8v?8m2d!Y?TRLAG>CdwfD}_4bu_3 ze2zz5+i&hP&80VfM892QHcdyf`}3vLIko+oP5nP^ZT$5k+DAJv>t%kPShQb$f$Cnf zE34WT?&{{*6f^mS((FE~2e0E2ts51KT;}BI-4MCD_;2c-unSLbmzoFGJ$Z5Zi;Vcz zOOjV-+*vxoMP2vD%sqGar0+eEykcdvz`k0!D|~VnZS?{zOkbEBIel}(uRp@9H#&{# zR&`Fic+~FFL>0-GJgYhP$B6D-QOIDVuqJRP)7dF?7f$f zOI%%*?M|=Rc((lRrEr<7pmS=0HNiDMyB6ta?&0sy5t;h`+n;&TN40-&^G^M7+_WZ2 zZ1ch7M)|^A`6rM3ReVznyqD;4-<;g|Yj62Ou16P)^SAr#w6XiReEF|8_nsNF+58Y~ z=J#j$XlxOx^7waVo}+o?+zq>*yk54uyYk@D4|~_SKRjW2BK28xY$QSfse-CJV_fR z&)UnYUYi$^`q|pl$2z1;}7p#Tjsvr`r@tDUG4HE)2^A@*d2M$_WfVVwc5$g zuY|2!$@0icyF|V=d!I%<>DgQk!@CelF*>|JL;GW1;4&&A$dQ-t|J{67 zp1=5Q^7FF3HkU1YtUj*X0gsa}r15>y{;(>-L$iNL>hoD;3>yxcnEtJ))^U4zJKf;V zG`nkAE%AMMw{9)WOw$f1N&LR1xFnV9@b;HK%W6|Am*>yPyWjkI*}VnL51*(hC%>)V z_))^R&-HfB_xtB}n;$wIIsGJ~CYR_fM;AlRe1lh!7i?sOp0B+5zP{nZt+JU_X}gSK z&c6FxeEi00o51%g<>c<$zn>EGa?-X^0ZDO#^~V>#(6g-eJS!n~qFO$Afq zt#4WWy?E`N&Q0lm`O;-O46XbB?mln$d{=Q*&Z_y3?ku^fE!6v}_Qa%nj6FB^h;&Zr zOn7i+`QjbCm)0yW5%`^v_H5lYg?9%!)>?i^eD}BN^H$wWmH9_5zcbX9k%^y>xMhF; ze7-ep@$-2Nb=tC11+35Hn%_Qi?n~tQiD7%PH`V-F@@>(o{r9#U6Y9C?H?=BM;Q5M> zx0`d=Dz2#9YI1wCQtfPOW_0&$=UY$x;>3f>bhfxG6Rkch_Q58;pJ8uc!kUso6SI|$ z&n;cQnXtOPXYE(r!hU<=Y)PKBwdZqB^hL=o@!GD=_pp-hzonc0v_~hOeryk46F)`$ z!-p@e-gfV&?7wk;UfZlo``Yf_SafdR&3ZN&!Scl0=RB^=N*TkE z1Jk3<=w?N&4$aXG3tx3~OOEK}4N^;|ZI0miIK7D1{?fUutf;Lqy0Yu1zb=gXX5Rk( z?XPIdjI~FPZJ5&j`t(Da`OCIyNZ$UapXpqnaN&&$88h`HK(Mc{Yt;qKM0 zetX!H6L!>pIpE$_eRY!gnsrvIZ5G;0kJr4L@YfPk(unWV&i)|EHy5 zrn<{^?0f4zwK?Wp@~m?|JTi6PZivcJ{hs+T)!3*atCG`Mb>C;-m8N~G(@(F7Jzx8L zPoI9`qY0lI|456byGX9^zsC{gEV8YwIe6mh{dLdWs(#dc&Y2~<+w|h;Dc9$|_)+_J zw}jBv9eWhdEH1WpM`lYfwi;#nq_>u`(f3JxVd+?DZgc3CVQat@71h`($%?AMLjbf zolervl31N-s#_L)YqM<9#vjwGt&BR3vRxLjeq-QbepNE?_c7zO*JiohY0keTJHO}B z{WLDG@axx1RgXVYn6Tbyp}>9pnex>=0W;P=Sh)JM^Vzlh!q=I$&)OJl+I;-2OSS=D zu&y}YzoAa_nyS}{ruDN-yZhK7KyJOZ?yVYhT&DK0`8WH(C#nyYurwMCJ1JwO|PbVH`J|T7O z_?EvvH}i)~Svuoeoaq{!x*wN5Urs)}eXs0dukKF?KNjZRTD|}3qO{!d)qhWf&G;d! zdU%;~o2GZzSNV+_ziz!2cD?w1#5eDhBkxzN{kZ=7)em!?ZoRiIo&Ch$A4&3Yi`!DH zSGyS4|KGcJRn+2}FHYASdTMRHzv68Q`?J%#cR6^^o4p`mN|)u|Sy4s!`UH4?1;UI27y7PtbUxb+5zv%E4gI_d!_^7YDNk7co3niV1;NG54=o?QKmT`1(u_>S*P2ULiG43GkNd7uF0`l8 z{&(n=O%45dM#cxeoe*Vy%gDEKUhsyxs=5BB>?|{O9zVZZmc!3lQ9t(Y+8JL~E)M;B zdZT>s5AB6Hy3&Vg>ODv8v71b$2UWxiowB<=Si4Dp!Y@1~n^xeBR-->Kfmww_m>ODk-q~ zP~`WL`z2$&nsm(WeEl!`7yl5>ZS<6`wyWcxP@Oh`KdwF5@}0c(+b_$WuXnOI!8+Y@ z+M?qo=l|~yKKZCt+V=j{$9d0tgSp(l-_d_w7@w4?_GF4R-|3IvOrqy*JHFr4>i*tR zx$}B`HFx(oFfbITep%$;wYTXKpTf6&25Wx&5Zl`4VQ;v~Ab8`6y@p5oU%lqME#X|f zccE|2(%(z*BHGoO9x=>U(0Kc%O7bG%D`=>6oBZ~qYg{@>&1=>p+(i~eT*uy`U+ z#eHJF$p7zZ(*2K|ZU)_re!lle&vQMwqR)FSJrMk{HR#;_JP++sbH}Pyqc;yd4C_UC z($X`tubomXU%lA+*T)B!Zhbg*cxTLwhjR7&zwe&=zUB83*qR4(1~32}9Ky!Hz_5R5 z-45ZKmyTb%`tZivn>X*DyL$Kf!+Q_z#c0-w{Je2dMeXP`S=X-jWg1P{w;9)1-Do-* z`{&GxvMHH{K8vU9zWcfPSC3K6pFLJ}ayNF$E|&jhr~J(=pzGoKvX85mn>Y2(HLbl~ zwDpu-PEKY=dgU|aXrrmSU(P#vebVmYLrYhD5KftJSG4w>>gG4T*7gDm{(O#G)V*Ef z(<#lmC*Tnxbm&4^yk*8x&nI^T(jtVq30}New4-kbNrfRxoI!Yp6*)y zGtPbWf$y`W?mT<2cD{Jr^v%hSEOY{!oIE$7v^gQkCdH-Go{R~Kv-f492x&#dvd z>&hLKw)WFMol34@EO#h1@72nDsJb@1Yu4^n3K1K18xl(kG-9vj?U| zTKm~DS{EHvj)*&Z6>cz{{kJat$nkrsb^ixAMR^|uZyw*3{c}!D0YU0 zC)?MVyB7cb>hx=hvWaSU=ckM{oIzVMon#qVH8S2Zn14BPT%-Dmo2AFg%`;`^b??8L zcYfFHuxe|c_}YrXUC;e@|ClswZIDxxqSoRIwp;wS&iS0A>E7CxqIbK^t?EJLq{S(v zs@Ya+6+75dTk4HFbe=q(Tpn4<&s*?vbMgGm@3Mj>ys!6Kdi>Fp9hcvHdtCa?qTWF6 z>a{P9@4eXAt=HDR+bKC`o_g~=8>4G!d{-Zrt@54n|7pe4^qUWNS=s+|+qYG>w!2b% z$z;{yYa-9yZ4H-c+>&oDv&Lrjgr#5qC!Wk;7huluEL~yZ;k-7W{n!FIhM1GwNj26D zzk<5=OVz2ni%VPDuHL`*eQAnHdF*O^9?8^?Zanhkmw#qRe~dM(ot@XeqV{gum)!W- z9&623@87Xh%J{+KRqOS{^J9uU{CjsQY3(f7zw3lfi;Viu{pBAeOrNZ}U#(`q&DUzv zm(3e^ulD87iFs#_Z2ist^6lSE85d66n?7rn%MVx6n0Ij@pMSi{pV#-{eahGW7n!4Z ze?FgAC){@-et%!yzv-X2KYm%u|JpvJ+x`EYGuO8+nK}LO9*LiiQXI33WusVS3`?78 zwb?H2%o7*5Dze5+!6%dbhDz~gR9in^N~Y@jl=B=Q$Ej+3b3DY`T&a_VL!fRI`f@6AyVm zVYc6^xa`o4{4j6pDwB6z?&Zn1^mO~hOI#nfAN$mFXNJ++fOrM-}sA5&3UD*Ui!rTU{7#{wn zU10TjjqtxY!S#pV{>|;>SbcS4=3(S9#yl$@|rQ&0??3Z}_7OLY*v6=Bw-TfD4jc5ozOvNjl(F%)FNr^QZ2YxmTR`^?t2ouRz^AXh zGgld0FT1a4fBgCBYX7{+PHD`S&GgUj3ut^NXKNI6UH#?V^P1;Zwv;4A99M01%=Uh` zZN`<$F`0KV1ih@!|8aJ{_xkCv@8Lh)zkBUBx5<|~AGKZn{N{=tm)A!Rv+Ydp}_X6@xY)6VYMviz?ryCQV{we9bJ zS#7_)PiEa-+fbj2yJr0kIWF*j^XYaQoAV}jZ+9A>YxAfrc~rMrndL%&)EZM?%c^XzcW`gfa4m*s7rR}vq3H{km@uh{oj zG@0LR7jRa}yvY1LNoQA|oc5ockDk9@{V`qm*52fMvwKYZ=l@AptlMjs=2)`v@#eEE zqLUc;Uh@6E|2BJ$Y0|C3`Nm}*68X!FwS7Li-O2s`cgBJ@&wd|Uay#V3{*M}b=Zp78 z^fc$_*mheQFAy+Px;1IDfWhLBf)Bsy=iL*T8fkF#-j~!FwLdVnyQHpt{tj^=8jwyKhAQX?r*=DPlrVx7W_AveE0e z%&C?#(*M4U`@o{u8y5dWS4z)NT|RM}b1;#sKN-oPCYAfMC zeVhBp>{sI3JhvI=o;daDujAh~f#4_4UfNSHjE=UwgJi$!gaBorbSA?B@9zX!_=@p61gl>%`iNuOFPAlk2o5Pok*r zit>^9ww9$ovb4Wje>2KHHGN7^=FcjNJjqoBzGmCEd;bnM*(FeaR4RQ(TjYzC*N!gy zST-Zyc8aNgU%tKLv8mg54>Kp~G%tCweOAUZjq~fjos=pl!&^56THP4)Im^LZDq zw<*8(`>oMl?n$$Y_51FuEl(FctTKPyi7&6Ri>@zIkNNwDsq@MNL7~Z4v_(}mBqkZW zWq5VtSD0zew(kr1w*5<#TDo`T;vQWsiDj|1KW`pm|CSTc{&dRHEnB13CMajU+LpF5 z=|_@rd9ur`|9h4#U-nSGHE!AR&^_}maJOIYdvePnW7W2w)iXVby*=jdl0^dhyWOL9{CuQeD7<;;^ZRv) z{u)y*R9Ia9eA$Or^q}B5>2sis5vo5?53=2G$ebzK#Z1}hTdh?0G$+2&1eYlf;T$A~8Mn`gM(w1`pWk9_9Jn4bIn`8?xZ) zm7;Z8r`sRC5>}Tw9`J1Wt_789DYK21Ixl!jLG#?ya zqy0#{-s86S#Pf0cR~zo>oiwfPo!XlPiyv})duM)swe!Yn{pk|^zI*+(#Q4^{-~Y;V zrhc7z-n2J4iwl;Wt=oAvP~_U8M|ai=eqwQX%k@=(=bC0z$l3_zRf+BHeCkNh3djIpyBV)JOz8w#be>SX{v2Whf;F;@w$knXevbO8^BT2Vg z3A-hheav~h^K;D$t3^vUKaKa*>y7Z+AK{%Xb?MOK*)L|PamE_+9yajfQ*Xa-Cv^DM zhAVD=gI!g$zLb1vn;-VdzdJ?0=|Opx-L@UY^S4|R-14aYOxKTTJFe=zUH|`S<-+~x zg|ntM<)$9_G3ChBf@_E4R!`1d_vP&~o7yXC_w;L*E%;UbF`iTMp1QdEj&FX&3HL3j*u<_N( zF#8;D`wV&B<9b<}Z+RyMdf)DFZI@HM-4z<-Wm*$1f7ztnJ;~tR)7!mA|9@EDR9Sq> z>iFYny&4uuM;}(4V7A-0?u_pPmkn;>Wa4sXZ%{3VOLaVD}VJRqt%bUOQYvb zStT1MeeZg@W3-ojRc!Uwt?!;}{-RkCOOdYw!`;ml-=1fP;nn2VP*6T#yQz|!H)3&`^Hb>! zp&Mn-uDfy7-+y(c!tE%RzwSJj*T+6xT|Rf;uNhN|!cJYvTB2Ageg4w2qg%|cEE2nX z@7E>eh0|xe-TmSF?~K#Wie}`B!J^y6)dQasR?s{nyX`yOUG5@uU5#MW3~|UH&`$Xp*>x;Y_FZ zPLGNT3gU0v7y4PZ-gx`8Rd+hy?%lql=#Jub&))6lcKk1{JjxXAEAoJw+xC{f-WUI? z>$7`aJ-_I;mMKQ|uYkg~z7++cUzihK3M>-*weYddX`RlaN$n5$cJ&#(t;wnR`{&Ka zh0ATi1XY0KH3WSczQWZmxgZQpiT zRIfJi+Agkqr$gA*W5=Ve*Sp?56u4#iQR}kLX)}3&yr5!KY4xeolSR> z!_L~tzxYz~GehLj-{~J)4w^`pEseQoye|UdX*6eNVH@#;?PCWNq^3ARb<=eLYJ1uw4>~L`ZnEC$S?0vK5FR`A#dwO{L; znbl2DUK_hS@|SVdja-|Sv?WnH_j=xT;rBSL{2(gg+3$zbOa9Ef`;bf8IpBFk9kcU# ztrZ#X&i#sO{r-Hn)`xZ#w&pkw*}QK7f~Cxc&)0ao=sh2%(<&SPP5%F~-v-mS)<%{q zX}vZ$u;;Ffjw<(tUO|o%D?_~;FB}uR!uj%+#WS_dI?pThPicmCzvaEY;qa%D-~G?R z-6u<2-CWV#)D@PTeB}4t-SYc3c4caaeN0VGzPa`Gy<_+91!XOpWBI!FT)$5Jm9>?x zlP#5Ao~-g{@o*8a{hd2s!R~7oAJh2{XSPk8&^onB_;`o=d-u1iLk=4!-S}jG_@?2{ zNZEMd@0EGAve!=dYx>K~bd`x~P(RKg^!t@nv%-%ugj_t8dEo04mPhMqR80hS@$Opi z&0BkuKJL znzH6$`58y?6|vh&mPqNGOTV}D{MjOm2{de!s z8|wo+{ZB6O8?WST?&Qkv*E_v`+tJxK+U732`}x<(yMHDXq}0BCeLo^QhsF6**U!4@ zZC-}4GdArsGPFK>hfDl^=!!N?3)4o?BhF0!Csk^!@iEVud8Me@=-b_pZ{It*_g)ud zf3)Vxe}`=88K))-njGb-buiee%;CGqNuPnG;1=VWZHs;0w7Q=U%$%`!=C`-g7N>2# zvn7K2=APHv`@&ZJO1!ns@Y;0!BkHcTo$2p4uTsp~<92@6PyN%MRTsaxf4x6wT0~#= zzu)INQ}^BvmM!f4TGrA00lFTUE{zBNZH_uysL`iy%Q z0(3Vv|9evUzua8Td7@gp_~i*-?>TMD{_UIlcKJ@0`}^XqH}@wzdhEGW$?PO=#$BCN zx9{0zKe=7@WS-gI`VX3!eeUTC0_~r#YiSOPN~-?8YWs%gm;Qgyxn6e0?CSRaCL&k8 zY}iyR6&yKculnh#FeOPtCztWsnuu#jfyUnJFIR0XaMwv)S&{PcQrPlcbvrz^?l4;S zu;$%4yJK_GKb^Tbc~MEm&f`~$4a4uWKis)F?0)t7OTQ+c-1sW##p~9csvbWNDs?xW zj&SbVoSqr*e8T)4O?uyE?g~HGy~F&%(a&3Etl3@E(d3qW#q8$oOXaUczD|`tz4qPD zC6@L}gYsfT=FHo@r~pa1dHMBhBy$gTRgdkM%-b0vT&o=ZBtd+kesWl+@Lv{X4hH)LxmLTlYcV zeEZ3)7u#On&5D;6i*@0dZ)mk@-`X9&H{G^d8&>=+vp%nI=InNb==A09vo(4wlb-(E zvMw@oyKdCk#bKm1P23jMoy zY2B({s&d|XLT_@?mrq$*x9`wiiLm)o|DJ1FT5l5Z=a{|w=joH$e%+`_Tb?^5*zjZJ z{r%bh-mP>0t`bvoqN?ui-bnYIhgN13Us&3isQ>)TuJf`h^vo4bWor*_ zFko`|TT?Yn>C}?Lm)4w654?1TD<S@fapvpUnL*Z+TLc9;46SKOHs)dW(YA)x|~0_UIf= zSStTcWG7eZ#1*r`wr1&{XkHn>pLH{Z*Sg2oXX93$psv)d-=4kw*Y3AmDrr_yc8?Ly z%}on$FE2G+vrckz<^Gp4j{@)N=HI^CzG7ZW^{IJv%OA-|zy-2D?Z z2iFxp&Hb=xrPJL~BbEE7)MHNxFHM{tb=ylntNw#OJ zMZXY#?W#j@bEV>A>(zG~1)SYjck<%0zGa^~|B3GoS+{}d60gPc*LHtq^j`D)Fj=Sc zcaGut7soe?eC0B|V7p4_WTWg`F4GIWDHm=r@~plwaoNND)ruUgI;8274A$aIGyT0AC{_~}Id%NED zyz?LJ&%ZC<|K+sd^7&tHd9-||Gcc ze)XTfwfB)umw}G1*}9kAS7)r2ZL_zO&^-1UO;x2~v2p+bX`(xu2sUU6FH*ae`O$wa{PnZvA7b-0H|40k z&#SuVw!L^y#XHwOXSsPKy)~H|_)die=rcI5t(85X#%rp(^lU=1;o*0e)-PYTSAXrk zyKNW4R=+ksc~|>+f5$?tWf8hbA9pW%+dL)cZSJ;9clO;h5L2K3d2jw>oA+73~|nN({KoTX#M?Z~g80JiGYc^+DdJ-#Hdm6<&!g zydPD+ZN774zW+~|)=&D~dzW7q&pq?(wEo`Svz7`BGGG5l88a~*Svl8_U8P{c8up4M z^8^DwY&A)J((GGmaIGu!PPcvTMZ;fTQzN$XZ?#!8e;e1~;052Wq6))$kHa%Q zNOE4tSZ!7!o06@y$~)@JE*ZsjhNoKZ{HY4L{+(fuu<_;lD}8(KU(Wx!;!OSA^T%&j zEw6c-7C3h{vyU&gslf@|!&jDm`EfwOtKl|Z!m7lL6=8R`Zh3p+kvdz}l-VDWKWtqX zW@@$esz$9_>wVw&T=wgix)NlMs{v;r$n!1pLsN-T2ro$FSb_cZUgJabx*Y)T3&lE=)Ka%Bz4bgpU6k2<@~q} z&uHZcx`!BCeDZ5@#g=f@Ri`(*-Yv9!cve|>g8M`(4cmcH}Ad*Ibpr4p%fnr931jAmBp?_X}-zyE$(zUf<` z!zYd{o4sNizuMBd<^i=oCs$qh-@&_a>#o@;@72{-zEs|~eA+(!-+|lRtlhWO-kq~) z|Fgo}s64T6*>W8@p<%iQ7A}=bZQB}yw@B+BpMH63*qIv>f;g{dZJnlhT~YR0 z;h+!HpCmU;y`X#P?@E@GHSIf1ybQhv-hSNJ%0KzDrE6^5>Qhs^ zmTSztWiyZ0?9|lxVY^e8T5XOztGiIeeCqw6RZ9})S^n*MQnT~-Ztu^#A}&=*w3up2 zafIbBlH?9jYM3(B`9 zf4kSNKmFmT#Y1ny)km$qG@q?W{1wIiJFIwf>gMJCrt_q2zDxHNO2%Fd+oI0?@Iu^| z$DZ4bCw`f8^-l)Fm(O-73#VS{RxH=Ax*j@bReVjr&h2X>SKpJq)4l!pjOg2!KUP|v z?7vp`<@gNubq_?gcYY1~F8gi2MWo~9d@Z@IUGJRhZPw)mTs7spc#zRGt@7w4yEewz z+&`TAZTn?gmVAD>bp9QG$Y2A57hu{$qr zJl47TXHnw(w+zCQa$2_}Ubkg#Nlcz{BQz(M_j1zKi&qSPZSBiDrcwHg_1JXLzZY!+ z4cmR)pK93lecJasc)RYlvX8;irXg$EcD99h|F|COy}a~Jw40d!mC)uw`Remu3t#JM zzrV4@tuXEO^BD%&ul-j?-`c5>x^?Zwh}`Rz4_Ws}GcB4Ixk0XnKY;VMy^h6e`I9%4gmrgu*-Ecfw3zkgYUfRpx_#R`)<~7b9C24q{_y7NhuHzoSD9!m zzxF)kQk_%X&P~zV!)JbY7`N+ddV2ly|8wfw)}7^7P?%u zH+s$Ich6qbU49jRdhgD?Jx|wFOMm#WEm-yXA>Z4s0e@}SCcT?0cm8+SthE|%kN(Z! zX`2?jI;q_Lz?6ONTT~zS>D0CV3vE8?k=t%3Z}|4y8c9iWz0YqpUDB2NCu63$(4VvC z&bIfV!LfYvl*M10Y?pkW&a89uOWY+j-ab};$3S-L1(toe>;{{^qkVpBehkoFn^FEKaZ8+t(y+2C)(w7ZQmy7(Q zL>v0WMD}jG;x*U*lktY@^12_-F5uORd?_q=`0tiaoj+5>H=mwfT%^EXINkOO&zB2( zSdS@IN+~StZsT@6blE}h!v9}t=|?61EZMN)sPT(PEgtTp54ZXKE4%eND?;~LRG*N3 zO;2D{So^IXd6$Ex>xNF*xW4v#UFwwHwRa<9-_JW7TyGP9CNnIsTK=%eC4hqsv z=)6nH@R5mo{B&!`#a$NbEtj*H^8S`m?T=r*RaE}Y)zh$9y`={m7>b^hS-fHh^5VPaXz0Q;N{Pyds%!yG;w)vQ|eD{nj*~=rI z)-lPhd;eL>`Bze;tjn^Be{F43c=gYIR(-O~l$?uyGy={txGYam6)8B%;Bt$Rr`z?) zt6R&TJ}kN0`S$GhUn^h!%DsK``oDQ=Eth0!uRgoX<=WkCvlhS6%e^FH_$TaopZV6m z3AgUN+#LCmcb~fZGxKe4?Y9_SxfiuPf9F%Ld2>#hT76ySTKTLrb<4L!y9XnbN1?1 z<{i$PnjO%wp=@im{S56IZvT2-vxz6JBu_lPHUCpbf6x8dXKcHV5Us)5Cz1(Ksw3gD6IY%SCu1>1?z5dH|V;v{Gy(SkY8Vm7CKb<+3{f~%}i zTzTu_8TCyJ3|p9|%$j%fIRE^4r;M_v|GA;^HCb|+Z>_tY{p!WCW)si8;A-zF{V4kF z+rGacqE|z0^ABHpe#_h}^Yhg^5}GG_9ZznNI$pJQXVQ`6`k(o^dmmZN?>HO#GwF&F zlW75ei+0kU^Q}o~D)I3?a;rP)=FI&dbDsbF<{w`!D^Kq6Gxytn{l6URXYn~r2ZB=S zo0dzK>olL=a_>o5YILh~Oz&*=h+Kodl!65-Vts=DKd(6(|Mr)?&%Yhp?SFH=NHTt{ zTGBn~)~Z8=|9_kOt)KJ6a@)ymHm~&VukU7zx%$O~os}WlH1GijGsCY`!|pXx7ESxM zCh6-{_gvL0_C?}($9pt>ZRuJY>ihNk-{LL3r)!=R)qM<#I6cMesELpC`AyH4?SKEl zcHKg@$@Mc|?MlD>@99;E$OQ&_3g(qZ^1A-~KI3=Fbf$!FhhD{eI(Ct_uq1sB--{{R z&V>}eF1plLz5Lm}<{QTjL|9$i_@gAL>89}2%)J#c2cu^0t+~*D+|8`L?#|r2OS9+u zn@D^sFei->myKIZP{i>_<)Az&s{z^EP80waF zoz)POPj+5q_wBN@j=Ro{UqbTL-E+S!w|SJC|8V~0jAp~?(=Ts?eemg9y$H_$(*0_ zVv@J&Ee@>X-~1=}ZfBwObo+1HuYDAXX`OjGSLXjM86&5PdnwDd`)Vk@@25?{g>rjrBD=KQk>|px9PR`rp3f zbGG}Z?Gan``0n)?Ud5YU_^_wHOLEFfSSo+>)sLUnuQxuMdh$2VR(=MbgC%m2QD==^ zD<)OC3TFAcG5k9Jxu;q0%-y$H@AVc>Tc7ncH+y-e>0#-0y7l{~wh(N_;F-TP_V>l=4tW20wI-W-3l zhBteoQQk|d?Bvj67j#W{&Q7-xStYdToYG1jU;Eahm%S&q9FbWS8L(&L_vsIQp9q~Y z$7mUUNw$Y>)#AF=9}4k&ABDekFe5F|bmN+-L8|YsEe)9>)O|JP{;n*G>H7P(Z!P(k|FwHgx~q_2_fdIuiG_Q9 z-dbH`J>TOW+a2%1SfzEdp37anIp;FBR!w&I(r?qX@)eC^5*U|G`XPDk$@G@bW{;$H z@TV=D=DUCWx!u<#)B_&9QrWtpV}1T6-ukrhK7L$FeG~n^>|H-k^naYJ%1iIsI-r9d#;;zJMK9$#g50TsV-gkd5d7o#rO|B zi{*>BZ+)-teQ93Tb*?yWQ=?n8W!7w=$Q|cz&oL7!2-;zB_qplc86R$$9QVE~|10|P zccJGo2TK|P7#g%@$Q3X!++sBF-59}RUAy(hkNLC3cOQTMqI$_AcI&qxZ|=#N7e&4K z@HYLud-tWh`f9=RewXhpi(0$mj*V?q*o8Pu2 zzGVz*nd!~Z@!oB{Q&e4i`z!m^au!PB8)mJXfAy_x->cWj8&{t*mD$>r@xZC9ZGrk! zepWw;h%L-NR>b>k&3-3;weR7HjkD_vdyhQIU7U2QXVvs2l5Hn!>!hCBR@!t2>u5HPxElbIrJW>;JhmcDbt;R$A$6w*P!!QtIcdySw#h#l6X= zy)ORwqN{wU_}AR|vnqbGZ*8{Eum2%_gu?TW8xNJEB|X*r++xJl}E9)XS2<>Kl6Gs z_txAD&t5IfY_qd#1GhTwr?i;0H5a;#nRYV2Wtb6Wdgaa)6B+r#&c1z%R|S@ZhJu86SWTf0u$EZQrz zt*&q5?0*;Q+vER!51e$}>2*qF&AmXKU*{wx-9H#)W@KD&OzAJ*zcD7g`iEzHpIYkm z$IQFtH|`hxyQn<=>%OxyZ!ccGBU=CW+PUQxf44>M*?cy4#hqZ+Gj{mr303uL!oE_He`f7iq72m>~lc4Z(;33Qh(F z2A0CQ2;t{XpFO>E=kfE~4{zPMd++X}2aoUn*;1A~?G%R!FVD_X&f8Wn#4BuN&N-*A zBqrUhujGHtsx94ihW&1yqVBT{iP=%?tIuD)_PJCu(yXo5S9Z$y7CzKv;k}0gXYPsrKRR7G6%hw6CF7W)Wa$+CrnU7O0 z&lJqK`~POkge^v;H?&Mo6>XjR-siINjN4yx9!Sn$2sHoG3?{O@qzBE`C_e^%xT&$T@}X5Y-0K5Uux``%B5 zYxAG8Keg=%PVI`~;pEJnJMaGWc-=Tfll4z0PTKTz<+P|1v%c0(uBzkO^yABXn=py+ z+gn8JjAK_TdY-x+9Moyv-kVYswbg5)%PG^B-@Ym)_7w+ATjjZRiW{?CmamTi5XjAc`M()Rwjx30AQN!#1xuTO8@(p|PU zaqEoVuM4cKk_>+r7453kxg9;b_x;50`OOa>S554m(dpP?@x_p@rh`R%$@JMwOv-gof3z|4Pl1igYM{*}-B9=u}L^2*b4epg>d>PCWR2ZS!*NZ+;m&pa0sNp7?Ls{nIJccex_PWagEzX8o(5`uOhao9YQs zQ*zy}p4)j;eD`TJv5>7Li+ZFP0-j#V*2-Ef*|b1*LFxxXuhsL{ubds35`1`fWwy!t zD|bE!+RKXj-_AOjySqAMnpW<-_-$X>dRL11^OoH@vmty-52Cpb>E%r#0PiGS|G4n+w~^mTP!zR zS2@Xd$InWoTJP|gyzL6%>AipKB)zA{+unOR$;$ZmrQS;>zgc{?);O>;D0qglFfce+ zH$?FU>x$hpsqvDn6~3LESC{-*`f*a^QTJT;JA%$)|IZozl{b8Q{Lzi|`*>G}vYVD4 zE#)mXIbShzoy(WA<;jJg=bV{+dv2_8R``a9?{dYo2 z%hzs+&?VfZ*_V`4{#)!%HC=8p)3@WL?8Z5d0(+0Uyg0G+vHmNy`oFXPueX`c^zZ-o zl$Y#}Dqbpo+G4xpx!#?ekd~#B9(~MESl?Fh=kENppNCx}++Oe5amhvJNx$j7d-A`Z zzu#}`4_Yb7vf09e?}M(mtuj$Mb%! zZTnS{_{T2bLGp29>$#;7MV8xTOnWy(yIkFJYxd7iX0dDD&l0#F{4#m{W4nU=LD#!> zWXeob&)#%p^>3f;7wqc(RNlK(tm60k&P+vPmHLB$*KSlkSagR&bYA!FFCTqy@y7*!91PQO>;Gi;r!&Z}qI~%h`J~ zbCP+^KQmtwnLp?8GyPcMyWaDyFYK9~uE$z>Z2hDD+cl^BHg>=Bo}s7QbF$-HV&x45 z*O=)%uTxj;Ej%-2VHCfB<$_o9ei>YU^DpPXCYf^{vZjw_&&$7B^v=RVWYK%cfB%+t z7)rG5>eG?G9@Ku({mOIB`RaN0a)0j?N6!2AuWh%^QDa zuKeDg=K;4Wr)s^dI$b%(`Q_uP!cV2y3j+81pFdm>_2DOb(30tD&!3%m)&JOb?L<4% z7n*5nlC8Gr?3(g_3b$5O>ihdM>`n5%t$f`1X@g=I_xs0>7XCf0a{TGShlg8^${F83 z9&>oA)mKBG8~;^!^4?CBPczpl{Tu1G?nf~9`?@~q_ph2-m+LIez4dIGSZDp|dw<{F zWz5+rFrSr2^1@Q5uY9M>G+u;X@cLY2cVN53wX;{=r^f!hmAEeL>)*G(mi|6+;@t|t z|Gwtu)#fjr=KDNx=KG`5)1TkC#J~FJ7E_nIuDYcmk+(`Gm`=C2d-KBczfBzL<5G4V z-LGfcn)-PA)fL^Fy#<37ski>Tb7^k&+~}uo7fWAVWNW+ot-{x=02?uG!HCD%dU>V2 zJ3mgI`CGrB@8iuSx6ZF;ubSUpc<$WV)8BUgeK*fGtvG@u{U@u^zg-%y-(EMrd;FNs zL*eXCpY{Ed#peXgxw`dprq#U-MdJDbd$uiK9X|iTe}E@OjyTrIQUOu*3sqS6&{e{bR)NTC!edC%*L3O_S=RI7X zJ4GUB+nkbJ4;Qb!cfxYlV)4=o$tkO@r9OGIDyG?5=vi1)WJ!wUmz+(n?o?R)f9h$| zuwuu;e|a-F1nbT*Pvcl(aQN6i?hm!^R$Nu}zg@c|_Wp7uxs`nB`734DdA)VsCB7v4 z*#zx)_h--SUDKU1wrV>!F_|pG6n;$rvjIzCRcne17LiiR1&h%F`EjtY&BF zS@>nbZQhWbHX@o!H7ocIEsC-85?U4YjUn-GF56nyz$I%JE}0vad{`?iS9J4 z|C8AA=bumT&nb(X@!u_}X;Zdv#boXo%gXCFXo<2m&79a=VIwx{<${=+rDXw?CwK9R zeZN0_?kwT8Yv(Q6|DZgQPw36D>-YXX?z_BsSuB&zS}y^ET&@WRbf(Qe9aGl8_?F?- z^Pt6y?Vkqf8w7O)t`nr zf6nIVS$w_idw=^Y<2RqTlqrPf-oAbGOYYlU&kSD3fBo{uxWG3dY5T*_kIBU)S4}?bzA>Zh-NIwXu6<~<^s3o* z_w3wfkET_=+xBnP)T>6z&a)}CNzA?xe%Zi1X7QJK{nM*X&e;)DRe32YYYwORqMUcz zFKQ_y*1umkU;Wv%wAkr8B5m&Vt>p3ly<^*^dCKN`>6ab|9p80U#dPVV_YyN=&Y!gB ztN5gH?&b~keVTJD);wywZ~5Y5u=?9p#<_V8b{X4?pZ2e>?D?g8o_#`xq)lC^+)@79 zEIV(S{y$K+CFs;7&-VBT@5TFmZQuW{e}4InKXt$479X#y{kQh1$G^as{H1cCbmWh0;cBVSs9CnJzGpQ*b7+gmugE;P{(Ry2)QNFVKYJMG zcYVHbG?qDMZ-=|@H8V{KrpYl?yd3>~EDrmBRQ6;XD} zH6|%I%BMT^wrhLXv`rG$ZK+YmGxB%My1MHjZ>zuQ-}x^e{y(#4_t!IP9xu0?V{h?$ zQvR_#@6!*DXY(DEn_#Os&+SaCa*lFrPJH;E%fGtj%ak3qyc?shQu-$UZp&h=XZK8A zT%P-8B|~p)ho1N4?CC$2Sf5+raZ}sEPfgq8{7S3$(Xaj%?lJe0&b0a&c*4_i29F;5 ztoQyp`i44oIS$869_L>ule4+haysd04VR+s*TV${vtHa_t=TIO#VS+~@YKmPkI~2B z@xyugMMvaZG&lQBm*2Vf`Lp(<;Nn|H(z^H7_B^cE=NsRas^VTVb>g)ZJI^UUl1SQf z+cPsZTXSny|5bs?UapmF1-5IyPnZ17{_XWeuj8{O-JQiU-O~7UHa2|yTzl4z+BT4H19wJ+{dB)zM* zN^s7-wJRp+^KFIy>@g3&Xc((#Mhk4pk(-jkV94;6A?)k+o`jA0XNX3@N^n*53O+I`f%FsV>{R$hU9JR{6-5GRw!9+xY)Xwu?_sefdRlo#ql7 zdFi;dh3AzSu{L6 z6z}?L-dNuHeaZ89iQI@~9jrIBZ|ALC^Le{!?zI1J=ij#5f6`cY^8UY(C3^z|Ic{_F zEsNSR&*#uTHtAc8r!K}CdqpSvc3)loOJdujA3wfUPP^Zy_&4t9iL>|H_FkFtDe{Qb zwO2|{v)|9DjbA0ww)Xzn{N5F5hWyr67Vp};+kf@v$bLRjvqB@__p6Sqo5^i9Z;tlO zym(Ggd1ZUP)t}{WKUhZ{D}2Op{Oi1Zyj;qS%Q!FotthP6@Ty2q%zwJt>&nTIN%2eX zWyqL6>wmsY|ML0%`Z&L5M)yl9o%bBfxf0^8C3lKDn6K(a%oPFSN%yO)6x|lvX*~Bz z*wptZntSJuFWXMLm%o-@e$A2{uGF#V7Je_($?c@3up5BWRe-qKZmq`T~MCR&e|YXsSD%VmR-0_fnrldbZZS`Rkv3d(Ls{{e6@B z^7$WU91NWJyedMbKIxtC^UW`KjX&@Fedy^0AN6xqGkC1`AIlCC`B(TqQm;X1&q;e% zgWZ!X#TI`JoOmv6-O7^dZR;+-E{PDozDrVj>-%#IIVTl-r*BDRe6uN`!(q7rOG8;h z(Ocgivz2!~jCy--Ng+@6*67=tZ^ZF>cirzhxPJArjh3F9EmjBpN;w*E{lM3$-FuhD z#vgf5&zByyYR$1-EB|LbJFR@W_WHq0n^V*4N<7y-^GdYqda8QrUQp7mqeoWmP;I$c z)!NgRe(S6C4}+~e9m@4_wYFUx`@-f;@d`<8_&R5s&CIxs>efIMd*Xbq1ax2ZFzq+lv?#*-Qct7dn*3jHM0ctE zEB!g=aLvEkI?JEWO;-!JOs~CeRh={Q{`&{N=bT+#|9Gd|>FP|Im0NHBy|Q)U^O#*va6Tux6s@;-(t@1n(LoKvLb4@muYMD z+kaL{hM#E+VMFf>bo3+&)xvr3?GhwMKM#@Ma)rf8lA2Jap#o2HEPf zFO34$eKrW%eC6f#^M`7>7E76)ms)+*?9KIup{~Il|6lq#FJoHr$K7#nMvjb5Ia~0= z$Cr0$@pU`R@8)CovGu(!_on*52K&moTl#)`jQ1QkP^3Gh`t~{FhwGb@x3{`{NWa>; zCR*>taRK(GHp5mQ;V0K;c3Nucm7kyYWX~Vjk2m6$uZ!cqem1v!&y=NGKYn@76SB5M zs*@{n{=5Z-Vp?N-zGn`ho{SlGIC zOWuzg=cPQhRv-4c_@igrkCF35UQTG6j_y7v>!%hvN|EdP+Xsa!Ahc0$K?*6;C?pRL)<&HE_$rD1sC zwIBE1D4UtS|GkY@sJdcnXh!U%%WpkP{_YCbZeMvxA-Yg@?^7f9*A?fwj8)6e6m~k# zRo?fpXYcOxzehwu%C6>S>aR~0)pu52I?pS{)VpVo@x3749jV^)jm;nLU!6AP7UPv` zVLFR8x#qkL`K|lzha9K${=HXC46Z7LMT>@Ote>9k9=-bLvAT_4W0zIx#vl8UdiGMt za9z)x)YR|!s{w)a@4POt}tHm=-urlFD$#3r@r}Y>ij|az2J83ecP)AAAkLScQ5C5R#W~h zO_OT1ryZQ>A67aw{`PrG4SBJo>4lfI-+Zus$981zn?0WYcbD9fSb03<{Db)F9*%Uwo~W4_n?`E~s5>Fs;g8fMkk-!W2i%bfpox!G;~ zNu}#glpfpvK6=Z%%a(6%%q@Qs`&>YhfAW)!Dhd;CWgWg9oO=FbK(fu!H^m1xKRhUv za(36$e9c)|n}3$xy6b;ab^W4;LZAB8-$|@W{kBW$>$2yC@~8LKbJTV1o|d*j_UngD zRb5$Ee((5irTlG&^{0}vhnKv4FK|)ri}wE&ceB6#{*aYZ9sNx%W$%XYt<6$3F(q3U z_#OY?Ah$^Nf#-3B%#Vj(b-yhCP#E?6{MUzN^3k@{t2BLF}uSXZs^k; zdd1*!P~J+RxV2*QKZdVOoip#u^<~Ru@6s=f*j^=GWV2#Lz?`k27w5%Z4gIYCd?MfW z%c&*a_Ra6YU({tyd)}gTvGz{&)uVgvs_|^u@360SUQ~(l+2!H0bq_7Cn%~Jc4u#0cJz9Of94JTZSqF77U2T@~F=X?eu%)zRPtTezm9i#NOi7 ze1A4{xyV*D8(&-}x~f>Yv*nG#I@t%!fr%eKZY&f(yecW-aec&}+gTIWwjB+w{vZ0~ z%j#V#ucSS?Zo-;-DB}E~fZvD38X`iWfV*QC% zr%%6rwC0xo*0+n*UO(FQRVuPFxI}RBx7q2~?lk&fVdDq9f z_hK6#r?KxdwSM)jy`u7@+1FiLp0Bx)*MIxzEpotU0XI&Dy}n;PC&S&$}XC z@B3+)61k?^IS=OFQ0d-hMPRz`_Bc5WY#^KTv6~tlKp#O!RKF1`cY?Yw14~? z(r?e_ZE^mZbacM*)aHE$58i)&-B<3L%?usYiaj9-k5w#(PZm2bnINFV@xjDMxk2|9Af<*4l>o*C;&d*to-M`hioAPga)RH8TwR zJzr(53D-&{huu+%SBfX7i*sDO#mEz!^S8?I%hG~{XWz?zn11@hcgF(1 zXGcw0@%)YFP182ToxfuGq_Q^$ugaKltZns7e%qf?&uxpfvR15F6RNt%ZQd^Lv+G=r z*(m>)yC@$i(4U^ycE+RW>Y7i%yJwp6D$gcv}V?)9j`idKOFYqe=I-olTQBimlN-2#vc4{YyL|<af?`{T^>*Vp~N`Yyff?$6ED&$rsX=ZV=W@PLV7L9S@4Kr_>}h)nhm<;B8=VbwQp zsQ70^-nub&-{nn~{~xoNt#1ptoICqtx9w-y<1^wcbsmMA%~wpD`)HF<&zJwLAFKB{ zPx;=`d8E{%^7hT5>vIg}q^4f0wYwCO`@QYi4_?7_0ki%*lBg__dA9On)}DLe>bqL9 zb}nYTVSDcE+DkUw(O)w*Zms`Q^1A9m%gPwW=d*NIJ!D&6BIqtD^DN|Y*86`MyCxRZ7o2gR)eEU48vKKg+$@e9ZC+|I%Gim*39(wKdzd zNNY#W_A9+l|3BT}nzMl?KKR_B86HKSmRn7YblGpZ$p81h`?2dA4og}}SiWY_li5OC&?%8bhDl(`}@;`4@;Ki{Q3FzLWX4w* z?sxZYzVyX6Yt>{G(LF`)m+mRpx8Ps)JolaR(=2K~T=#qQKBu6gJ~idM^wme{Q@@Lb zKA56-{`1zrFJBK`J$|%TE>NcKiKUL6KJ%jOmh!8hnx57PMgPjf9W){>(6R#+`o2L z?7UG@$BA`mv3H%KBsXsN=#p1nT$dLyukKsG-E|Y6Guu77_i4&csYo$R;a=1DDWC4M zEpPjrS>gM2#;z)#o*#>TYhC&`=Y8bX_gylQeNWDmL_L>E3cj>xmdxMvZvDxvN)O|W zO?S^K<1$Hmb+^0emc^-iwM^{t54J^Y+wZaFk>o42T)y77Rz44-=KNe?@^ABAcGs)? zNAH=ue`gCe_nI@wN%@4_rgHu?ZQ8fd|#lq)9>P{ACE8SWIa6Eb+)1IMAqledFNw_ zY&D&iUEW;XW?UIna4-2|R)pT;$*(7G)7{WjP<+bt=_~1ZFN)vvyuLey&u62}4by#H z+#JnjqAHocx9|w$vTwL`Bg$u^l>ee*GZKGA^KSlYQ}cWo>;4^KTV>l`ISC&7{C|$s z6w@_=Mc3CqjW7>-YC2`rqT_PEr{;gF+x+U!-~T;xw)vclnzWUlYu(S8?eTk0uVmeL znBx`y^w00#NV=EUZ?*gvw|AlZ*J~b?YtwW+?ye3CT6a|_Y~}(7!<_gw_mjJyBwf37 z%I1)1y0gHf{&j6dccnkemVMsi!K}ah?5Fxaot@Ir3m5&!Z0{_LK6U8ZrfF-c*2`>v z#N7XGp}_o-=bPSq_4S{9`}O}m=xLV?X^24!ZUzR1Qw?V(3g3Ep@BaN8H?KcEfA`w; zd)IHixOvBBtAbXK^fH|lQQ_VTt!}R44!FghVEcc~)%l7fn3*p&`$VtVuU^ygj74!j z+4fxe{Py|w?NeHqkK6s_-nYacqV}usGM*3N8#}jt>t*};GE-UMSEBtqzom(Ca@`kg zrhPt9`d*uThGq8u|NVw}vv0gT^m*Ps`-f@a(j_aW9CuArpTwq^zjn>foq^L1aAsK_ zm^J;z@1y+pjrljO(0qC#M|}ECJ2UC6CaX=m&T6)W8}}^wQnc*P&a|x&Yn->n%(}g4 z>TUn8zqPm5f1UPJ-2cjo`^VE`)34q5*X;ThImRhlMV=nZ68>;0D)7t9q!^|>WenG)?}{Eie*5@_maDI( zib-z#C9?QrR>k6s>h8?5XFFG?P0=bX+7&S;dQ-2^adGv?tpE2mFFj?k{@$?-6+5l^ zeO05wm+L9dx?`V}>#nNqK3VC~U)lc89=%^G?(4fx7u@J^Pwx7ZAM5w2*oGcGad!6i zlwP}n4KsG$Fn?HMeE7=G-!je9SNvxa`TqXcha-OTTDgxc_Nr%zeLAg9mt~{V@9&Ye zqG^sPnhX9M{hD}3_UG4mlb2p$J$B0Gk9XK{t?9>Nw^v^O-{rpkvvT*nZl9E`3Lhs$ z+H{0#CVNV3I`Ja(R7)9y{OOLwsW&(6J+EK4`)vf<;d}h2?H)b5$GbZ0@D{_V9_jV} zE4E85ZD0OwL-{oEb=%iW+qqeg?%4e=SoibZ3YF~= zmVcxxce}Ohv@G7j*!^_%bb(o&JGDcPma4bZJYAP+&|3cc=ZO`mCtvIRowoeh`epkk zJQnpl7G1DkLv!xyHOT_klHa{w5xVJw&h5|t?#ibJ6mjVmNayA?_pRA=?r`4sqi6P6 zGhb_;c%g5>l;7KGcn{Zax6HGjY%9lDvUW$BV2ZefTF=rg8#FG)%H1eqIGy^{wn(B* z|M<4A(Jv$S1X|viboB4+xQD0fv+sRiE9^B|{3Gu7s{eBAx4C%IU!6-nxk={Soc&F4 z$G1eBN;PeNy?4r|DQjMK6=z+OdRkW$z12;;dXZ@R9x>Uc{m-nee|5FaI#yIQeeKpI zTaE_re;D8YO}q1}P>$pAr|YKWX@29BoRrd^{m~?1(KO}M4g3E#R`tsC7Tiu^%wm^6 z(!FHXc8{yEZ~nPT6;E!Ov-jht=)9>5-aZcc*6TdgJABQVg48W@O}~XbTm8O_@BT|J zo{f71IP@3}?TcW!C>-O$DVP&~fVZb7b&{v=eqEml%&u0s55oaAD7t$ zU+Z1^EHU!v)_Jz!6*uOtu{@xvnOzaIyF2{MjE8IHOj*@^`MFE?QQcEwY1i3*ZeJCB z^AD-{&t|ax_GLZ|xq9qndixYYhz7#XkD-Ei3F_Poawt!%aQ=6vm52 zUfTk0Jp5O`Wro>Pj|0VI+<_n&qXu4bKHyn*xS*3OHieWk42 z7wx2X)#RS6yB8Za{pZgUH|EaE*V!1ra$s}ggp#d11p$(sp|8*XZQp#tROVrDtbF}t zj{DmKYxx)V%Cx$U3dL@IkHzpaqqSA5)gzDK{|(xZJ*+c%f*I??lc z&fofbaTc}Vmy*8Eob&d8;oiA%nxea&)g883UGFjJLEoGCEB~ZiSbjDp&9U!t_RLW0 zJNtcpb|L(2PfOLWPf>-GQ4XD`)zR=@A&+~eYLCNUf5ga<5{)vRWG zRLM$V<~&a?>jV9lwvv*LIzk`~S_{`-q}m-}DllHnua>oG!EWAAWpv z-Qnx&?^yZtONAtz`Bt~|V(bmME8)uzt9@5@;WTbMaA?O`yMM{+JN}mj;7>Q7d@975=daQamh5MTE=~4&bM|Pl&C|`-f1iE*WRaMz>Gji7XHLnV zu46y>yZEiQ%b0!E3PjyyOkvofE6T*ez;KQEh{E-*Zwd1E|4rZf&{jItber9izDt`; z*0g5UpAc5MzArGZ{ap2qRIo$J#pSMxp3im_SFb#-N9dGPU% z6V@B`CEl~vx+%E#uIgkZk)wuu^2L^iB_%t5?d!Cz;tg7)bU3xd;Bn`l3r94aZmn8& z%K7ErR(XfgGv`fy%=^~3P3fYN#OiYopUkw+FJ9&bgO!dxJ7b~T=ExQ%*^{STg;kD^zvws;LyRat6F82p_=2YS574BQ^ z7%gR$i1hk9<*>Bk;v;uA>E+Mba?Nw=lGiE=zgE3?{Bs76uB-fSqo=#A+yvb^&WPC5 zO<#R8#8lt+FN0WJ?M|We{s5H?e`Npt6j51w_9EB(zQ|qGTF!k3mhD{saM9v(^A}m& z5l^}P=kdhX7xvx?cr@X2zU3X!91F7|uO~C&Kiz6&2>rJ1_EWBd3`b|a{eR1u<5*_T zwhB!)m7QN!*eEb7dfU(K_!Q{N8rrM1uZm|E=q5tf&7<|NkPJ<^QcM>nsfaZfdd<$qSN|C^TM#1i{JR-2zY#z%JVq8Xt&Z9IP+_TP?GnmC{3 z`&<1aW0}Au9@97UPdwq$EB$zF{Hc8kQ{rc`)+pXKwYNFK_Aalgq_%18EuWe5y>pI4 z=pPF%ZOFdhsr*J<9K{?Q4=t{eL2fC(m0}yff@1PxMRU>6Oc_o)D1V9)5E1=2HdruG8nA z`h0EO^)8?3XQr2gT=(F6vbDT&&;6{dbe8{V^Un)U5L4Q5YUZ{iiNo(XXElmQeahOj z#>k|6Vr=&Ly^kcr4X?LLPgoxs^|k0{;r93OSM1caARx34|$vBszXsyS-ZG+ z9sa8RcpYqcckw+@9%&`^qxYYEdm4Jvbn>cyt1b6sYajc)_{F9FiIdi*t^A!DvX$ZK zqN1BGosEudYLZucb3|-fS;Mv~f`{vleCWMw)m9YL{`uk?wwc+du0LHjH>caw*{!F; zbYoNGshv6h=Vxx8s#SO<==HxMKk>&Avv<~H&CglAaL4Hrx8vETSJasvG4cPTFlmug z)Yo6}wQ>BNwX;femp2~YCAXtMz-vd<=|7R1j;^{G6UQ%XW*%~N{=I9}&advWDa}=o zOPt8+74)$=)9jnv-ShHi94ux%I=OF~^o_RuuxTo4&!=CCvOBMRq%XRvEHixm>h89? z0^NDZ!Lv5*-+y*m=0=`xmuI}vZeDAq+PpOO)bfrM`=`vxl#05+P z#FZ%d-&13h`t)P|F`?aM*+IMX+Qr=@?)>x)tpC?nc=6sl=Bz5kRoutJ_SzdC-LcQ? zyrSK@f8F=(!fMt|x!0Sb*04G3O6A5kp^72584GenyVLJ}*}meXB-^%ShSyB@dY|FD zyJxGrH1F#Co*(m;{)oF8scX%SWrh0h{oIxP_eaU~sNSM)l7}v3x$=De zm%rA+C;#&6gRir%TvmD-m?1U)@8%_OF;8zAT-@!K(b=~4QTD{CMXlREw)?wCEUcSh z;_=|~&-pn9FK@_ik~e=>(Wf$F+UmQyuWg+V$Y#uEox!!F`^~e3vr~WXSn#%LO4+tI z8*a`o)?90RZ|1IrFY>2NeedY^&A3?d!>Xy=?K+7jC*WSDwGwfBpYdy~5s_-6fUm&v#$m z5YKjh-`>an?tS~~a%!!A==smr*3QpAU#)Y#J?HS%Ij42%(~Rrm{p_;V`T2zIEzRfL zb$jifsKbA^SY&+JRhKT;#eVwD)OWvbUyFYIm!nd;^n7F5=76qu&-0?=e{UCRefyd9 zho$y|dF5I0N8?sq-hFt|t8H_3#d6-;B4GdJ-ghmvbFybkwyZz*XyaEoZbhCi8_VA- z?>>I^V)czEjm>NJ9`-(Z?%Xa$pN$Oka;0&AlS~ z-nO=;jo-BG^|^ZA@5P^+{%I)vD6jo2@$1X;+jgd_<1?p;hJ4^)bx}{BKlk7ie;MW5 zm8-o@{lC?`$1CpWohtRK%l~HX&u&|LZ*z8kd2Qv6H~aUh+ud~!W+~Y^<%MiZ?9{1; z>()+rA>F$15a(Nlw%+(Vf%DA640RvzEz3>X_)#?V)wH7mn(^4;2((;o5T*__XRB4p%y1cHww-3XuQJ@L)zB@z=CzY#rWW zX29y7R2#V2C$c;C^@X4^_3Tso*FCQLvFTTBdTON375n7#+xcG0cvbEDJMaD0sk&RE ze6_Q>{{M?e?+a-@T224ZRyew9`Mx|8vyON>cx_IxFCipS<>!tLuv; zSHxH8m4>Z4ZMAP!alOFRwvg-5kuxhK*Kr-b8{GC}u55<1!ULN-iClU=}I>Bd7lrLZ_~JParY{Nx@v=j{qqx_R_2|% z6nn$`rRxVd%fDAR?%%22dbc9cd&>_0yQ{0> z-F9Pttiih@>eBs<6;JN_P3Ql8ZMDAq>Z5j__x#G=l(xbyXQM@!@Bz6yI@4S#J#&1e z^W*Wpj?iwym)%ZPCt57W}^NnfC*Ao$KZ0rcvfMS9aM2PPPa=@FuPO`y=JJI>wZZ z28)yh+4iVR<70A6JCM!3A?oV-#Hy!aAAL?&L|lDjzII+>o@|eiJHPj>owj*TP6)Dd z{VuAwwY|6Mr>An z3Fn4aQm>9YPCBb9_4j1;Y~{nJd|n=2zvs#7yQ&g)Q_@at>@mBmmb_MB$JXDne@z5e zChzq6SeJYC)b;sq>*m|$)W^H`Y}I*c?s1E8{pqCv<;F_P!PX9$%V$_U5{+g*znS;; zK|{A?g1>WX@96S6OV+p*9pOIYJCkpUe8ya(x}aNWqF);*S9zMeCc04_`S+)@6CSC?=M#RF8{n<)$e_? z)yv+uOV5@SduE@>J^K@nb==m?-J6oX-&n)9$=KPfw`8rtq9&OOttYQ^EoyusYNhm+ zVX@6dM*FJ6YHRFvpM9WQW-p&}dDGu*D_wtF+5PNYeD<^1zs_&jr}=sLy=C3jS*h{y zhrVx@`M>UUdg1+@|GJ<4t+6|ueBv_4*KfTNo9-r`C|N#hb4Bn~k>y#B=YO`3;a8Ga z$MeY|-#6x9lybg>{sX>uZU^taU@vFBx|Hp$=L@F)RkQ4@IP-j`pFD9;Kkm-_Gqyz+ z{Xfh)yS8t&t=}CT@Au7rn~%SK{dnWL zxO+>|f0zHUk@N4qy#Dz8)xF||Tz74jt-Qpc#Clll@K^Z{O2?MZt-sX$?{FlanOe)f z$4aN8&+XX9`af>6w66PRlV0tYVcoOuT5p@MGURILlJe>6|IhuTeT(}d^Pdx&k4EfY zxaE+o5;8YMy4*bDd1JD!X|5)jw<3M?T;E6_Yg~??sc*NY^tEjtIsdHHO6q&Iyma^VK(Tu3!)bC)r^T6? zc;Bv?_{q<^)AGia+^vyo+h)8uoU&$FcFdmZzbk+5ee-O`n(4FC=9K6k+n1%8BxiLj zFuWu-wEFn_%jcfEbIF{Z8=tiI-{CKRPr0*4ZD?-1dFq0j{nvvxC!FRo^?~=Xoon^8g!Uv6xi{Zp&Q$4vR2!Zh8q zyDr-kH%@sRHviS_JN8yORu${|_o{rz6nZ77wBzlME4`DlE6%3vNVz(>C+^3e_@A#g z&G+@}G5FteY2EC+c~UpqpFiD}K3D72_Dj0GPm`zq+kfNZF+~S0g+ogY-DeKsO-rr4 zohK-A_BLzX*HeL3<`w&mqL=pOrtC_dp=TSjz1}*0*1h>D*30FaWA9|kNpYT>w)t5` zy?#*WF8gP1&)Z3@Dd4<1wNQEXo^#WMBDEsSRG;M@X8g0G#N`Ali<80ALl;ujI2^1S z(lWQ}-#gl7xhsEv@;!I+<7ex_|$=9^VqY$Mp1+iLVyP zv^W2}TzTgC%`+J{KSxTfl~|a4?aaZvc~`bxQ5RWeDU-1^s(1aKORg>gU*DZCbF19# zHt}(i*JbCGTtB32Ji@#>s>$%8mDSx_| zZ+Le4jpppg=40BEKXg8Anx4Pt?9W{s|4#)eO?$$1_EKZ(VlBJRcelM>t)VsVv7z^- z)r>Y9GafN*Wa8*63cS$$V0qIez6bsNN0XvTQZqyRlTDfpzx7W32y47~e zvi~3dcE?IGvQN+Hm0j%rFdeDIli%Jsto2;~WlM2Vbjv=gM;m6?r``Llztwj7{*}Bp zTFWzvxpkiPOYPd#_qOm^@`XLN;Wm3dohq<9C+#6RMd+UNj@L;~!uMGOSKNH^(^xG1 zoL12J%6}JX9zXeSQ(N~nFY7X=&rXq7d7VsV-r?D!1lj zw;mOcmQG%?UN=5}X|z<1=k&FkO)@ujJuP`#bVTRsoV{B^ss+>@zkDOJ^jUhW^m7CI zw(zGvWQxBYE&2Vj=-0w_{?8Jwhco|0lo@?qy)tW0;p&_(zb*a;SlZTS?ti4YPVd_b z?|+JI%bQ&O%vw-omvlXDx8?C${VY9?lh=eSa&vziqi-!^YIW52q_f4cjAI#xd`}v0 z7gK+K)?@z6w|~yxDXRUxT|E8&t1UOnra!e|O^-{SoBQ?SpNdFkm#qe=N|hFt-!?@F z?dVymw?gqYUxJa9cbV^tdtZi`Yj6DazlQ?>8HD+o{tt;|5pHJXpW8Oh zdTO6_c-P*Ka$V(b!Ysa`gM`ohRmHE zaM`AlXXW^=)k-?6KU{Y6Z!_+nm4oZEDBs}Wb@|F-_n+(kNTm4%Y_->X|Ur#F~AeAk~<53jxWSm|i9f1YOS zvJy@A_N!AXe}1o6cB1ItulGeU)=51cZ)d$*@@01D#d+T^8*jBd`O9Me3r+VIKAiWS z|C-vl+-kYUn$kync1yoKG5*2BT3Ec!@7VL1n@`%Fe|GTrlDYBqI;ns5tlqhMSNN~} zw+nwpZe6oppFMn~Y1or)SDhJaKK}mm{LgCdN0HkmF8cj3`sI|P^7G2yum1L@>PzJF z^JzEcGpg(qkY4^Mi&5<)>zwT>Gc}UD^Y?y=)}J%qDEI2|RnrQ;3*PUFIIC;u{^#uu zw@PVqlldy!*B#Upf6w!H)h@T7iIX4SI4?8zdH77fqn24x*|vN3ox6N2C_nb8?aKa= zN2QfDnlAEsccfb$Ee^SV=3Z}>Xt&p+te!o$ zo{HDJ+tGix(md+DX|&O^Z8Pp~k4a`=*(s1TG0EDp)pIiUW|2Dr)>Yf>iOK6E0!G9&Hr807i}lA+$hF*-87wRo1UBA z&wM_0rRM3IuX95;Pv7%)=7UeKug0sYm~s)fdWd#-DC~`sV(r zE!X_LyhOe0mZz$i8mbkf6LH~!8MpDL{OvcB~6O_#@o)1OU=e7`Dek#F3`TXn`!Z|85S*FF0D^lj77 zeXBG6-sk(i^kjJyv(3gOZl04$6sEgu+;L)KSBZl9R^};YkMc8Sb@y5)o&ByKUJiWq_T_HAr~53Quidr!xOkQ1s)h4v zBmC=4d3}u84bQV*6mv;2Jb(O&*JiQj#_MJjgkNCX(rNqp@2&X%M)v#X#a0A1#GXG< zQ}H5Cd-mg>SBupimnU@d+Fg65{BM;E+bIRrQipW^UkjU6Bwm_-yZ5U(srrlb|KqFg z+Q@!?YgXHK&g-+bTCALW{kGLN*2n$Z^3(1)8+5#&3Nc>5%fP^JKUB9>SI=L( zcRW`ymjmJnIq>#_AUu*XVbl5b$EGPV3f0Rtll=`ZOk{i!}*>@%>OHPjU#&E z#oV&PAKu+7+crbl`ua5C$3jVBt2S{=oOXG6g!8(m57&LaRI>NANowu>$?etF*A|{} z&G@RcTvFrJssCE@S4%m&JvsGvw{5su-^C(n?I-EdOXGL~ncv$z{<}?Y`Am&d-;ZX+ z-8xh)Vx4ER;QXKMf7x8$omuziXvxll@oBRjzf6oy5Z|4YdAI0+UTKP%n76$h8>3Ba z(7C3UXZ$a(3!c1ZU5#(D`l|QV^Q(S z^4oj~>!Z6fKZpG1oiFD$|Lx z$|Vu6lXmzX-)*OnVR-eZ^v0@7Z{>nAx&=i=H)ZWR_EpiSJaJ{hia%R}0xS9d_B-#F z*%|Y}_KV%F)whH6+UI7UW=_n!Y*wb*eAPXB&CTEv`*oL#cWC_Ucxm!9*5J`%^R;iy zh5dFH`&@U|o$sZaH|6Q^BP%U8oBA(V{^sd~J5trzw;#WZoAJ@$&g6GhMGP`KHC`c%EVeyr?b6(dS=nFD#hK>)vT9L0h{T1u-Me+BC zKe_hxw^&TJ_S`#YknQ9#KPK$6x5wuEC2`gV)T#ro_RDQu*s6bi)9j?JzvPNPOJB?K z{B4_3a6RJw&l+2|vXxVV#JU%F`G&vse!KN`O!@b~W2XP^t(*2dQ)+YTC;9g>_tt8? z+OlWEuJiAd;&xt||NW=O#9e{M4j8Px@od-WV$+8b-S!vk1ibcI+t>cuy1Q+o)cdn5 z3?@5wU9C!7SJ7qne(J8wBCZ#@&z3|v7%%^NxU%Y{_+qDC!S^eYM7v9-_1$}Q-HH2k zcF%RQ&Kmol|ElZu=Uh%d`gA`>d#@S0&Bi6?CN(Kb?@&vE{wi_lJ6xkYj%k0h-Ykn0OeA%onFyGLi_V;6)s{J%Z`c3dx9xfU-hD^k_t{CZscfCW5wnWX^51e+lLbEO zC)C|${KHYbxWwFa+uA8&!M=y5?{{rK7~Z)w&{Rji?K1!3E8VthmTf*7u)27M>bJ={ zpFNIOME^Vc@_zl~iF1$d`Mde~bKUu>(OdL7X1rU>zg2J5Lf1z7&CZ59^uFF?UZQ)kq;@&q74{0Z-R26u zf7jm(S6X>a;7hRMjr@M~x{mV1N3+weB zrKH_1)qQ`I*Ss|D`d5`Q-_3`aT!JD)?+8>nzRSOHadPLJTTg8`ybq`z?e6Og|1{s` z{PN<}mJ2KPwMbcqnnu{!pVXVS*T0S5=64L!_T4Fa+3hz+cKMgs&)?p>kx~{Mv1an0wK zQP*2KtXfC9`{({czbvL~tk`#cA%{{|=(>Mr9L^|zjk>e>ebiLdWySk4Row1KEnRfw zed!g~P^GGT-pl?H+RjOh;sw?QgzsJXCdO z;?w>A_;2=n-rn@%Nn8B#>J#djtZSb=`J$Y*&4$S`U@h08_`rZF_wa`r*JodpE^2PR zw>e=aOUms2*_#yo_pgth)AB0%{9j;<@eXhldo_AL|SKmWaB7rS#x{N0vQc8eX7H_F9l!{;c<^Q#PzyD0#CG&atMD?fXo#NS+s^`uf&uzUPiXT0g zb9&a~kXX;(-c!%zdhyhrS!gO3>~d1E-Hg9FEbf6^mdoa2_d@bIFTY+~eE-g(?X1-` zJ8g=pdOHvPy|+d!S@&Lf5&wfov7VV%-2QgBU7xf1!1gdc)$qRR=X00J)*XNGJ@?)E z3$b^0N=>ib8RYx#*8Ssu(}jF?$ZmC8bZNsgk%JuvHit#-GQS)L^U*KSHJ3te;HvpDTxW@YKh z+OLWK4Jys2_4#CL1p6N`+@x3a>DIyb6Yq4ZZ<>F`_Q)}rbJ5Psddr>)JaqAD zO3~s=w)*dW{NBYO?WtR_tIO*{&DGDYX*zf2KMN2RoyES=X-kWj-q+&H>C61|wd{BG zs{ZadX_on{sy@6d(C+o00=xg^#Xr5bY0R%Fd2%9_YtD{85yzt*&N!6!vNcjGMpWlz9Uh8Yw7O^S=D z(wxKka-FO~txfgTsMF@#b8}}~o%;Nm@7481al39u&zWLXm(6#rEH{P!dW^W)_pO#Q zcHNt4`MoD%>6#yNoSqzry!%#XwO9Y@o6C1i=6jy%5_@9%W<}+OZPC%+4-5Wk7JnZ2 z#8y`E`<1XAFRq&_$?Rav*u6qF{U%q_+H;RTOxWJdNeC<`2oIm?4_qVOiGF`iETUfA;*=>nM%dUnT-@1MKjy9d74vDs- zNy&yfNhjPocC=aVYte4wP%K)zXU*1|b6OwG&|P*li#6)c_sZ-gJzq2~Z2i}J<^A?~ zrn9bPoS(WtYh{Pn@xRB__KVe2$uC^oKhMa?SVUa>WPr#zq3xl0`^3*3{eEdu-Mx8V zcvYu9_`cq`j3u2nO}E( zidD6cs`hE+plN+Qi{j#ZKHs0M_xrfH3)|85qai)o)$hvJOg*%+kweXwU;ciQYQNy- zzx`7aL{2aH>vcDV=XK)V$v3-C+P&qNsK2XyZ^O;y3!gFWGTa?)$6yf_Six#y;l6rz zPfVyq|I^B~CElSQzpP#@W^eIl`Wml0%qySE?AcIrWAA$o=ABbEX|=42Rds62sx;JD zO)Pu-re8h#$W5Dj;?E7HR7yVgFbz7qO!ZvQp@Tl(cV743TJ>Ry_ud*wBd3hNZ*uNs z&%OWe*3lD}-gjQy&$>BlwdVn$UseCz6wV7~>vf*EU;TQ!Y-K^IW8aRQZ!UGuF+OWy ztJ?k~&;I+TxWha8=l}O_`fsmay*YSwpW}iZ#nb<;od0{{{xz?jo66UBcGo zk;C^xGCAB^_LSWCt#ZWX$041kPaCgI7Wn+2Kd1g(ZMAVu;D!?#x2JsDY8|t0NmsAy zn!^%jr6c6Zubg&XdnZJ?x%Ube@p*6 zmND((t^Fd3I;9^qHeTso8x`~Up4aitS*d3>MD*%JT4vX4at5b8v3p!oU^egEroH7y ztK-g|-hAzyBsUvF~$_qI^dIxk+nG(faT_0%Tz&%)g|I)yW@R@}ecxb}}p>A{>$im!Th zZ967kY;N~0|M>O7{W~r^*^<%H*W~g*#nEH6zy@m$k?>6RfWulwL49{$oln^1vif2B zQNQj|>nr!)1lstr?*8%?7F@y z@AS6lqp9kWIqS17cp2VRGrF~ElcRdG^)ihrU!`-;jDmDNxBkqqi+h()I@SBe^H_~z zp=~SPwZ|;F|HLe`V*c@c8J&x~GUD%7pWk9Nd*RA&J@edl^3S|2*fA^c-|gzpM;52e zG@EGOE0P?$_4xIps&8|jUe>hyb-lXgt1x6p!J!2)q`=3(z)+%l>Z<7JqsK0uK5_Bn zsWaD(?LBz(=>Px!|6k?VI^*1-uDFd$E_j??&bazsR=ouGXs-nHhF?(c%s9 zX99C)WKNuT@#dTv*OJy;SrxnM{hD<*4#f#+ryj~P=Q+4UdCmLjI@4#0m0PTzS9tGx z>ZitiwNol*Md{hyYTI?mqW#e%{q%yV{(O?tPCMip&#PNHWvU!bKF_MYTYk7W z@N-+rnrk_lUpfCAWWD|9&X;$aZuw7n>~`0#vSzvE)d^b{I4h`#?owGO5P9`kd)eF< z?8{$Wx_R~c*U+>1zt%3STq>u0TW%fWl|3da^BQ>Wb)7!^gDqmg7Uqu3jFz|G_FA@6YCO?-YEpKEox=Bw%Zb*(EEMq%$-2{CE^-FWxmf{zG)XMf|q|FJo2wiwbis z-rrpRVf*aVN0t}T{CG>AseHQd){o|CPV?YrPcNvn%s= zT*#t}Z?eL7M>|(gOwG{gf{&^3V=`C89$@5usaz^D>tLnAq zy40h;TQ&N=`c`Oq!@RiXL~+FrtHaYTtlKbA@2sKi#+n1XNB->E6?et)#B^zm0ug8J$L7=!zo((emK3c zyLtU%NRgab?N{p__l5iBZ1Z`2Zsq1WRfZ=!0xlj|I!CccU$1u?L&=7>4ByJ4|MUi( zb#D{A{9*f#-_uuKo4By=|FXMQn{F0_7P4w?tNPe`<%bHZ$_ra zy5qlRz3V>uzvf$%ZD_GsTiR09{XbUjo7Pcr@J>$3lm7G1{?_kvuC+V+^KpEEbCvv@ znHuH1&n^e4|1T=LUb|z3yBC{0%QX3E`W0R~n(e+Vd}sBR>$>f(Q<5$clR|h;T~^qB zzWf+d`;4tNM*FvajQ=&iH%&S@+2HG|bI-T^vi0ix_fetqgh?6mnLPqW%$-`irOLeu zJ3CAr6qqf_Z}25->{{5CtG9Sl)SgSeyN_@A{pqFR+JDBFf1jA&t(>*~X>FOj`EPkiyB+^S_*{zQ>)3B`I~KkF z!z&eHSD27fczpZc^EF$ivzG5PIF;C@)OBCt@{vRPf7(ecPrhP){MfopQohOGCU4ne z_CvsK+5i2Uwmg_M*<$9^2K}FG-#(XLjN2S18-H5+Ec@fDOFNf*I3;^RY`W!|BO+cK zbLJQHiqCM`tFkG~VwG&d<+WcY{|&nJCi&EhSC1d(i++^M@806Jq;bJ#TxZ?Csm%;$``N?)__bKlx|&w*BSlOQ&tFyOhe) zv!SLcb<3I80x9~sbLBXSbbAV~@F{#_Qx1J|%ZA^%5Qt` z+5POBVrA%$1=EY~akT9C!zA#Av!kxJTkPthOM4YkelL#;Kep$`sk1E7!B_4^&1zfQ z+u0x8S2AVW$HVCnBK8<)MlD$#HEaCy`Dl^L=(ze-x& z3o6z5m+|V?>C*HX^S2vVg+6?I`c~@s-Y(B;)2yVM;uoEsUi|a!-~LD5KW0wJeer3_ za%H~H*O%U({_RKHs`G`0y#kCq2fBJBbY4qVZ46Ig4a*JcVy%tXyXouA6F(OuMCrC| zJG)`+j6n>qd{@M`Ek1Urya>8g}m2 zilyJ*s&0?>{-k&;=G-&m^&Ew}^gA+EA3XPZ)BP{0UGI;-((ip|tSS;W@ABl&vW)?s zeyrqLsrzlxw~nV7XD3WIvye=Gt9{4va;4d~172Q{VSeo0Y||IMn->24^5-X9{|%PT z$z8IQHT>)5Tmj8UFkUoj%4ue2+eV4cK7Yk5D!`#d}>9*TZZIY zSJKwVZ@L=vqerGRIs4`}-MZ;(_;YGaEDrrDiqricvpK5BZEo00W9{rCYwS1E4*n+0k7z4A6^e!r`*Y`*pUt^w_-j~PGv)4Aqi-*g zO?BP!?mSID7aV=Nqh_{V;HBdI>txPJOiS%swSK;I_R0~R z;$2H@6Fv%UJ`>{o?AODd-sJDGau(-5+pc*Yv#Gi=!uz+>zr|M*H|{+)<#e4?;)bwT zYx6}%Otx-VcWdplS)0BIeOcn?xK^-eoA{@nZ+bSEpR-+7`1nrny1J9>Q#Kcu_b+|T z`?+{uSX^pQ>AvIp)Xy)H)>`qXa8vhxtC|(IT317kL`ccc(0+3v+%+)EF>=xOrqkE{ zhpakxTzuM%e;m&~Jm2io^*=4ZC!|~d$-x0`v2wLGB*2!Wh{I41b7`~ z|k@GJedZ>K=#_UWU>94nV{QEb(ED)FACD@)8^|-t6ZHZsoIqB;!!}8 zlA4?K^b>~XH%C2sb4BqStHXTX?45UQC2lpRCKuQm+MeZp6UjdD=0~rHxf3|oY5Eu6 zUGi;4*aMcrY_6@h1h)P zT=PG=?Z(cXta|_cEeZ7cE&cfCti-ZgZSjY+a(;iiayD&Eo8Q@cFCNd_mR-+t%Xzlm zJ8u;Y-k!3&&(~~2W_w5+eEvxH{=c{TZ}jZ2`(~GHzNBmW4~b`+58mfdWN}w#Wsqd+Y?uDTbz7WWuBY~CstWZUx^YU*?{47sk`t$*y>C{tPLqi= zJRW2*J4?#!=oP{8qj?Wi) zQn}mRre1gM?@pPg|0N>y$OgUMV$Nl^4defx;`csiZoT^b|H!b}A=-k+kA@XJEBRU3 zEmtiXuw~CPtNxGgQ+o?bUSIWoJ+msZ(q`$AyZe{Cl-ph-cJt%&Irds%s;Z0!b`_^t z{tJ7yy?S4BQSmxfqsuRU+*o|?|Kz_4o7(Ol)0@~d%b&}7`GxE5;a5(IeTiQ6Y^p}( z?;R?Ip})TUXkMSFlIV6dJ^I@B6q5x7+*))RB-i^24u_n&({P4_sWX00@9vEgLq znPPALC~bKXUb(5noeS6!B zCH`!CK08KAWyK1buzl-@R!n}7M;*X73B zJ#Rg^EYWy9Jn@%$zkGhlVukXqFSmK8h3~N4Zt~mix^*k}v-3ZSu5UK{*?IZT#7{E% z_oo;5{;~aZV$ofpC1Twou6wuMU0G%JKL2^WrPZ5XdF+kX?=2~qZ~P+f!?t&md8IPC znzrYaPJPY#`#RIZyUz>4wU$+HxYjr^eU8oZ6yfvl3syLuR*d^Sad(pC&cCmIyog(U zeLl;(579a)!Yiv!R);xH>~gZ#?Z5q|)_nc@tLqI;sWlb9b^Q2Mf8CPh_RZeQW5hd; ztDjHJkMBDdzWCPM+w}YC164KYOD8X# z*vVO(d*N`v%}Gb*eLCb4_U%CLugfX(xBmNEb6n=bs;aO8tKW|L5g-3KuUz31*K}x! zNX4ax_bR351l{`HBb#+++Jkk{_w_6E-<@Ip9rg9;$Leo2^S6KA|5S9T;?^zS?U(<2 zm|An^(vr=HlezxLaN>0hP(TIS~OzQD7ZZ9+}R;s;YY)HSuH@2apKR?Z|5E z-8WxvdYwVo^>q`gd@ENcN-b`?o7n5>$}1XhIO}DYqeIEjtc_iZ_U8Sbu}(W`ePrNe z16L8p={NQ*JN?qi@Ge{JeO}R}#|>PsCT*YkrS|-{iNEc3<^8rRkG)>%nJd5H;`he2 z8!ngTmhW2kde^$ubJo4y^?pkH-S4&c%e$`z2*gHijnG|Ypnm%LaX0A&(Xo*{tB>Zb z;9C7Oyf-lLu!)zB+M)sQdEEc-=90|`F|gOe*gX5iSpM|zHYqu{o?o9`aR!&Sys6n`#9n9LZ+8xlb4ByNgeOX3ENsjeqA}s)z|H5vt!e?r6yT%Q?ky! zNl2Mm_M!a8)(;YD6Rw>PGEOTGQ0+g-w>2wfnR5EVbs2B+WM02_x_I*8j{a)l1q&(-E?w7Lyd+HCy~XHcim+ikyZH&moLs4sTbpgtj=a~LJawLjU4@l; z<9QG94^?ZwnSDMqKXmD$tK}Otw(a3EVLkcrZ_3vy>Gb{9i?^D-{1hcUH+b>R^AZ2F zuhoCQxL1;^w9GoW=H9+j>A|L*OP|~QuZyv}o_9=a*BbNx8;vvHct89mWRf2i+PgAo zhfnYsKfm3P>8jf`ecEQFe^1-@qC_=_$$b6&)^%k`(Z@{Jy}WXNd%ya%xxy|>=lzg~ z{rjc2`r6cFjrjM1Ck?QA~l(xInTbJwoj z`2NkCD>95*T~VEU+>EiL;WNRF|jtgNi< zw$#gaJ|=6|u65^XFffnGILl`3AJ6K>wL|Gu>w%2J9Me~Co_y`viK}}=<2tTp}2F(o5sjs`mdKI;Vst0I)9qgk!a;F^BWr*8#@`f*rqWuaII(j{8FOiH3I_!gQu&X%Q~loCIB1IBZvS1 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 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s77>k44ofy`glX=O&z`&N| z?e4-50)ocL2fs2fFmM)lL>4nJa0`PlBg3pY5)2Fs>?NMQuIvvuSa}5%_6E+1VqjqG z^K@|xu{eEnvSGfkqd@EaNbB@T!9|)H0Ro%>PP0TDUuH~v;2&@yV#ky40Hq(Q)83e| zx+X0YIO*G^Vdy0@M?$E%|MS_o<(hu!Nlz7Ax#G6&o;9;J|6Y&9^BtT#<}Q}@IqUX4 zJo<}0y@v5XTVK^`Er#>*d&|=Pe>^Jw^{VAXQp-!pH|5ryg6kJ_nw99hVfS$Ta5Q~o$@EC$_KJk| zZ&l*2)~<5d%b}!LqImbC;X>|>%>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 071bcf4f..00000000 --- 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 a0566d65..00000000 --- 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 00000000..124da82c --- /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 00000000..6571b775 --- /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 00000000..e2e6b560 --- /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 00000000..77e8d97c --- /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 00000000..9e10e894 --- /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 00000000..30a3491c --- /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 00000000..578764ea --- /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 00000000..2de62650 --- /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 00000000..0a26b8fe --- /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 00000000..add28e65 --- /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 zcmeAS@N?(olHy`uVBq!ia0y~yVANq?U^v0S#K6FCcds{yVk{1FcVbv~PUa;80|RG) zM`SSr1K$x4W}K?cC(XdXz+U3%>&pIsn^{bNan|fhHy9WgcrrsGN}Tg^b5rw57(igp zx=k|~7*x)Ax;TbZ+F7vz6!>@~*wNAcg7o@%e3 ze{avsxs~_7|Na-ZbobX6zNHLIQ4Sv&8Uv2FZ!0!76ryz%lB2%M^i-LfM6AP1Phl9d|77mx^EgbTU zi#|6ko7fV!=~=Fvfr1d%&mD{_O}hGXN_Sb=ZQ6QsZB0t{_RpVkeo93tOk0%TpI%9rQDE>pWf3L$(Kko6FEa0+rD z3`z88SROhL>_(7dC$w;2C{k=S^48&8aw;3-0RzVEZroleD@q#6gVSpC->M{bt&y7V zq~LV*TFdfPHn+pQHJ&VeCdyS27#cRacR9Px#1EUSXI;$ru*FMg?lp~Dp7C|}RO|WY zszabt@Y*tt7I|I8dL9?!jt?_ea~jO_IjHMC zv5})?yU5CP6&J-WhaZ=P776f{>2~=pZp`FiJ>lT8+*M&mYryR835{_k%|$zvCU~>0 zzZUJ#UAa3~?)amKGh6P@-{zr_k!mm8=x`uC^V#d4UaCg_@@6kTC>Ek%dQ;IV%Hv4T z1}&!#r+ndR8huPEmEZRMh)jXyNpo2NJ088p8T zQ2L>y_{~#6AU9;mB8Ak1j2Qh7aDSr&hdG-{pXL&7;+HvDQ)e9ZOh0FTm# zz18zu_9Z5qnBl1SO{OF)Ldq)GF^sR~u!Bi+$AT>_H`E&)ww#yXYU*grU=vh~WMDaX z=zsvTRZGW%&zu)|l$=5*mTft+P}1ecxugpv8UNNTNJ!}TdTz0p>-Gy*CDf~0Tv@>LC1xzg8w$QWUvWx?4P({v&rNK{Z1@uoPixmf4V2!={0fCPK%G?xw5EZ zfuiCpN0vkLRlcY)J74Ab^{G7Za>j~@0=WuI7dva5zOV_-duAl8Vd+pOu!`fF%X8KgkxAX0k$@Z7iOzYM#hB2e_^u~YRIXBv>c|6QE zmbf%^D}RInhXC86(=86(9cBWJ95$9+X#$NO_&EbRlmzyrv@o=4FkM{vRAZLodgU#% z-JIux-CjTG!go-%aoGOBit{3yQWJ+_SS|MlOC^DS>WW-}EQk6977FmHnp`(oHDUFS z-77ApeE6#`+O4{8|B8c0PAmOU+I;o;WKI?)Mv3_Q)z|jbr-!XRdOSSjlc$->ik~ef z99Rz7tB5>Um%z~?@7clQ!eW{t6gN%o+pROdyj|5lsJ7Y^Rr7tRns>BS-TG(n*Jq!^ zTq8W3rDAP7eJ*ba&{!gyuC)00+Rqp{=j&Ms9%L~Q`5HF;o&;iMH?G-omyIb; z-Ztx7@@K8yrb$}0z1M;w14ARj3Los=dNsW3Oxoi3TdQL~KFhwm|HmhXx`UPe{vuo% z=E)MGD`UPqvOWLjY4PHVZ&HPrnAL+q+M;s%dvvCHTv-<7Tw2QC^~yVNqJV#(sjE7l z`QgJ)Y^%?>x`wBpE$a0-dEQ*ky6o*l_gm$Q?+1qnx$^$}eLr{W)>*3F9#85uxmI=F z+4fZ7-8J2+k4ZN_JlqnK_v`ERSJUGz<=%f6VCt3n<#xXIr%x;oA0AV7*P35>tm2D? zrEB4F*$9WAT&cx)2pOas^ zW<__OXXfdhh8Gis)p<^x>k{{Fd75f^yG+LZ*XjHx0sZezK0i18{r%nh{x=vZZG3W& zJx|KU;P=kw`&XdWOr7SIp1%Ca zGqv<|e^2k-p=kIR2G zHC_GtTdk&H;rDI18}HXun;HxA9bFfr`R;1AbKJd0Jw3L&%UpBsM#(ygFsPnCy?aZt z`zDu3?|$x_dyU6$j)~#w@cm~veqQdc|8mOv^1b@+6R*e5-T1rxarOQimCw)KOir^G z6`QRjWNLjc_4c<~=XT!~|G0ZSPfv&UNnhTd{=H!Ro#?EhlHO&1PCa$n_MxKS-5$%u zXVWe(?%!)tcE>rs?(5mZo84C&o^wuj!|M|lFMEYf2~n&4vhcQs`?hb%?%S<+?3yLN z-=8u=;^TDIeE&Hn<=@}gewN$ayND-OX(98(i6JpEQztr>zMVCFq9F6b6CQnwHu2f; zC6<)jnPvKNx?bwbk_5$rlO|Mn&bRZty*)iFEbZDgwfA?mWsQz}U87k2P2=63;sdMK z`|T;~J#ymEp2LXW>=)#J>+tONSfVRB|HX_ej?Q)0SD%-? zYASeLD@#fFsOWV)r$1fgX}q$Rp0>7@+y7&4=M2zV%713Z&#C`sZ~D^9KCd<{=6jx} zpW-x;pT{dJ*YB;mFTLKk{#U2r%a?`%Kd%UvGe*nJD7^kE^jy)RfD`k6Tz;}WZa$;t z`xCDZ3$kr0+AY5`Mo4;f-1fY^%a-l)KKEe}_m-Gdwj8zVLwtAwrISt`^dAE6|0U~W*r z*7CPrhs|5GwfBBn_2}U4?!GwlnjedH?0A1|UGMEJFSDX%HQQ^4XPrJBo|5`k*Kp&5 z4-ZfDN}rC6I>2|grugg5;@M(46=r7NoYkH^Q=f11|6#lQk)ySy^>t59>(76CbMlfk zOIPSi#a+zXIKzMbzqxVzTPHBxkQP@L={6PDf5pz%GAsN2dHefEPUL9bxaQn`sg2i~ zIg^dQt!uA>z5UhC#n!q?hm=>Hxnw?l&2xztRa-vfWVT$f$|#VZ=)!Y!yXaMAQGV%L zrdnQqFZ=(jvfUGODreib*TTEMysbY!cl(DoFPZtz@AFj@xBqx0JNcOHpRd3E+k89W zG4VuV;=BF%6{V$b{~FJewJs|=_^_!x?cSQpS=01>|NAs`wf4Q}>fbMZ_sjj`n{?MY z_fFscXZ|zI>R;ZLZ{91)W#T89b7k(Iuj<#WFTVC|ZJmC+f4`~v@^-JKQib09tFO+B zFNj&b_M}ID<9x<&PX7Med%u@B9(?#B*KvyB5F4g7MTB>-SgA&WSWGURHB)(IiFZe`jahd@1n%|ra%29I6^>`-@2~lKb>CcT_kfT`t3t1^%TM|KO0@QqifQ(>KDAoWHZ8uBDq_di z$3}0jt$z6K?&9>bo335GsWXjb9q+D1N><8`6&Aa$uK#f`Z}U-O{;P|Nf0u*_%{ue! zbd>au#$HK|73;3u(kE)*~{G6S?gZqHvf`#(CoA8f}&2XyH@+{=RNM{ z{U-ZXhh~?ZpI3Q!)6&Baj(w?mJlp$!?boc(^Y{MlD)+Xle6{FoR`@EJJdd21wivl* zRg1h-jU{@*R)?-ET6Lmot)ZG))atd%R-CyO?Y@8A3J-lfzcd|lg9&yuGmc10OwV`i zUb|TR+M39l8xo(*{8RI2MOU$`t|tF{%g0f|YO?nKv|aC3UH0|=_jUcHeYLEDf&q7A z*E_1M&i$t)+S>ZTBDiy{v4o0|WJK1AO1JF`S{^?VGRxU8+h?_!uU9e$|N5{?0YVqb zcK2mYwcJ>iyUKg(wQt4N`MXy*By7EunCPqD!_Rcd?c&TpuhmEI?D606Kfk{EZeXPM z5lc(S^ZI|1-Hvhp|99%QGntlz2f+jTpiK8yZm@cq5! z$%zWetxgq|1;J&D5B}XcC1#h9=-efI{jCNbE-OP8UBAlIYP6ZnBr9vtbGx$Yqg!WH zzpsAwYU?J!?R?c`|B|crF5PtN-r{N_i;W9hWAhL5KB(bpRSG}tA8hj6aGTSiud!A4 zqe_^16jg-+r|ZYp`-p7a$h&??wX;!!?MkKZOUfq{I;Jeyw`^JC>FM+4ZOOeo_3G;F zHlI!${q$+WoH;*__gl*ae4fr=EPC<6wXJ(zcP%M@e?&JrYkN-Q&mWJs95s@=G<|ya zm8=QV172Ir6q8=9uRp!5wb8xmMt0M*XiUkwPYwS%qsv7aW$x~N&X8C%dBy6>r=JE*^mvgat*tF3GAYdJ_4cMe+S zPy0UszfNh(>qN7?{~Xq~<=CH^imRQ6+ire)Qz&7wFre%(ud4pO8OB*tem**CEUw4% z^-qlJi=s6%IZK_^om#)&bpgnTA>bHy9m?OEO_jUwt=H9Zk&pw}5-}A4^_xie~6)RrU|6yM9dR^)3UC*9Q&A-q0KK|{` zot<-U2wl5=ZB513$b~m=l>h0dYc5t&k`41-I7KgZGV>_w<~YeEf^Pj+UmLUZHWYsA%c&{`iVlCvOG{CQS^uplhCavHSay!qs|6Oz+okNpoBC`aRY4(I2<2dbLaaze%v{ zvI!n8&FpE7xqmYK4>r`@?VGDH$wM?KbF*lE?cRq0ju+?4)f@OYYKmU!OlCj${@#|< z-C8=k)=ry{q>*m%=FNQ;ws$fwS{sc*jnk#3>Al@qy*)(Fe7<#g-N{Myq9PV=-k#R? zul`@V(q+-_f4`lL)0V7_H2%GMy`Rs_LvtfO|NC7VU%mGHm6fV5U+O;bk8*!s+Q}%* zx-Ko~{yy({)$gh{@!Rb%E6=++$MVG+zWf7*Hlt zKL~%5xB7i^`tNJG78S=k*4Y2gT;#P>YhOj_!|wO5c#r8Bp1l6H&g-^^>9-G@vlLT` zIlcJi7swvq-EXufkeO3}`CYll?OmH^FVZv6i)S$wSS~JHKVi`UL6*Ps&fS>vR-|;| zqGJJ9#JYBMOFHv>Js5XP?Ci1?Q$nn-S&VG5!bZ~SIjtl}ot^8GA{p$593wK|gX|8T+Dyrqme}B7knJrKM zmb{BmA~e-7cGr*9Zoz5WBM*l6c%SI&ExmGXy0?G4?tTU)V;dVg-NolyKf7mTuS+eL z%rSedA8W(8YD510J<0Cdccnc&VY%49#OGG)XZNqaqQZr&mhM=%@5v?4+}f>I(^{nz z6}Nha_sSLdJdSR`I{ zZ<)gE|7q%ORm;621f+Oe6#g*ii&i*h7zmtIP^xG=Jzr5k(eco^95%rYzNY(nT~9P3 z3vByNhxKm{{jgrl^~ZhPHwB-2#651zkz`?e_Uu_(tEC&81W(@~-?q1%Hz&>yTYWWc z^TGLd3hX)zXP;G>mlUR5Xv@V|r1#{R8PkPRC7u&m(#rgruP&X><=1E<%EjvG{H}es zs$QX^qoZ|2hXczZRTj2mM~|kar5!tNeeJEG)ZER>b;P=T)P#)`K1VhPX-(~tVaf{$ z3oAN2%Y!L_kMqRSB8%xoJY8$W4Ik`q5n_H2vp3GasKH*bSSUU`oc+6lo=Z`KbOVp( z@s5g_t&B3QAMWj~p4iS2@3g|N>-#QA7Phwb_SILj6gUHzd?tiwwFa%bn$^g&bm`L2 z&`_(nd|oz&C2EsT9%HCr66-AJWJpploWuI@fSWM$hSHQS6&Y5mgXWRxVw0v$oyyp2 zD&<>RYWl=^+JaVwpKZ=m|LgPL#LFx0 z-e0Y5)#iBGdWnZ?T>665E-jn*d?tIS2rzsSILs>3P{eQ3C}Ci??vPN@104_l6KV)JR2BQC`VKk=I4Yk^5u9YX$S9j}I1!ii)1wq&+c1(%~(GOq=jS zJ7XiGBT47Yq#fEX{7-XH_>f+|H~h(qC5Df0)o${=T_R|+qgq{&-=efdH(~mLFO0kj zYtzbCE`%_E)>}1bU?S%q?s|5HTN~ImLlWAg@ z!}{?~?gZyKt34leDs!FeC~RYyeEW~j8?*QcABrk(Ha0PBKOxP=>(%8iFq3)pDq-Rim#AcGo5eX-i z8|EIKKYa2S{M026g+354?7yxZxNIUDU!l0_$85XI&&C_Kerwp<*vc)grmnW`{-p(X zcq9!9K0Z2H);!;LW5CS?Vig6?&hXwh-*MjY@NeC^uc2}84+cH|=<)Hsy~XF(`TrhE z6`#MmKYHt`xsxqj5@n0HTuQ3D`}Q8a$DVYyfqBV==K39fm&^0Z*+>Lj{k9?TaKo;< zn|Du8lS$HDn=Ai2|M|p<4h5zwOtKFXt!od3u`-BcZ}3*}X-RVUE$XDWGkVdYjUkG+ z8lSj7-+6RO-4D5Vl`kGm&JWonJ*&8x#ax6YZ;K4yEA`;RZZX%2<%w!Lkv1L9PcLOmp@SHcuXEIO27ju?m--eyG(vwtdxsz@;|F!o;3N(A=ZDw>^I*;-tLJ{G=FgJ z{al~Es#6XNWy|o>D3I^Oi!ghxv_D_F`lDm72On=qWZS2F9_CCKExz;z#-2sD&R)0 z3&*KI=g7@-E1rMe`u5zd+@~E5+gf7uU0-kSin_A;g-N(bYWn{wdeD z&8iMK!&8(y)iGJZBBOiW6aTYCQ4?9rrcRsWprq|Swb#v}EY~FT#HnqjA{(_g&-wG# zTO5a}_vYONr=w3z*U53b)}z>6!&Vad#Hj7|_g>E}8>YG%WiZxc zG`^@Z+I`^S3b)Ju;$si5UAEP{Z)33B)nmP(88`Ram3Dj1_*cFCi0+G^?V$y8CTcZW zL_HC^oZ`jAs%^J({-X51I?}&C@Awv^eLHSda+qt;l80L5W*a+VnXV^o?#%Jky>;DX z$=&2!H>-muFD-7ooapu2D)qeQOJOoI=eH#{#yw3^u+c^Nb> z;G`5kYxJb-n-Yw#xeJQ6%v*a(Hz#^U-{m>oEKmb!zLJ1WYXcF#hsuKsl9chzeE6^qFHa70_XYoeaA|#756T3Kb2)Y zOaHO(q`fSPGAG>HbXu63Bc7!^H{0Ec=u>`&B?$=T$fB_f4u%b>1g0dKHrp+1v)hx^QSq)>Gr(t``qZ` z6clV?`JCBWU0~1Yi%DxcrHx)4y%xBxhW%(&`yCgqn0ri&8kO~}(LIf^A3X(yotb8B zPM_O4NB7?JMT_Sy?YKHeEo^sDQOL}R4}BJ2x4s+_{@Y2Lt?sgY5x?N9B9k2lbiGAS zM44Qe<(6rgRhoa|q9^~ddACB&dSA==9N19ZwqT~Gz2Y=Bm*N{`ZzMSH+*mEn`6fAZ z#lu&j%N=~Zlo+|S?RMH#X=*3AzIpTe*P%n-BAgVix}Ofu@X|Ye^jOhEYxCSTiR=DC zmuGmJb*R5CV6V7r?{0rbidXPLQHa{qbw3{{3z=QZ-WmD%mBH7`=k2ul!;9y0x4N!t zy?sdGzmvv(tW;uY^E6XYJ)wB-8Vz4e^m9*r`;U}?pvUf*SH3bt+d@bdY; zqzf5YIV3_}mh2;jJ3$GZL@WxPN}Q{8j#)+Wc4d z?rNGE8_x|-^PXsAdsp(rDJ90-!i}4kZ2bFU-R{=13^7)Zvl}O?&-}`EYvbGQACpVx z`|qp1bocQwUE9xMGeqY4iHkfo@btHRD5sY%_+>$+mW0ZTyQ!WR`6e2es;2tfla;UE z)fQY>)Oshu!0g+4rkg^OW;JO9@ozKv`m{T3ooZk118xq{Eeu1aFWlu{^+U==+zrLNXclYac znwOWqzrDXd$$X9a>pmu?T?Y?msS4X&$ujjzb^38!XdCO__WK!^UcKQxUgmhxw&=}` zmds#XH{prJOpOj_-pz2FmC|%n*Tk6P#>6`&e4lu8g~G0GTwS(#b&r;c@1Ek$O)rnm z$}mvosx*EyM=gZs$<{MIYQlGx+|9fG`m0viLJyWjYj;g?R&IPX>)5?N&-DI;ZQwhs zA;$jWQ@g^{UN_|$;oZG|zjDYQ7S~dbaM8RXe!_tzpO5wKB$=mHuQk_BUw%(WSL#9V z%#M&_N9zUeiLc20&iV85B9YxUBNWaH6|Gg+kSX%8xhqq6Vn5nA2 zKj(;q;{rc;fsFxkZHNN`N}$;0%^ zt5W#3quu_5h4uMsK7M%cC%(_jPb}m7<-+;L@4Ww9R4IA?`^`HZa)B?Wp5FKK=8_I( z|E#PmkL?RP7_SyQ=GxTDv(e+j+5n9dBgw?HiVBMlGmTdXG)O2&WQHl;X{(qt<4I;h z`>VhldlpOCO{%-67rk{`_iWdeH(m}?XKc!T%HA(#qW7-z9MD{MrD;lOX=%y_b;B7Vn_t<@SsJvGL$~wl(i?S^7A`#cDq&hv zpG2t`N;>X(xce-ltJ8Jcs`cWt+_rpSX1~2*dDY`bavUl-Lel%5|J`f8liN1lPEoRj z)Aj$CmzR&85h(g0++{JPf_Jw%TVTIS%A~al7Gxr;6eHBW>;O?;W!-Ix@%pK&J# ztE`uep<|0#)Y@;qp3aQ)J0j-jCG@~Y?B>x~k9pk94#f$b=k;G26XwGl?OyfY;*_J^ z0rPOSL-WnVR6c+DRJ87tgF@5n78(A#yY4o~Iq+Op6IM`hw>h`+@q=p@&#ON0%Y5hJ z;h+{&X#U{Zo0}>13NteH#>J8E~H=gi);;kIW3R>ah>FVdQ&MBb@ E03#p_UH||9 literal 0 HcmV?d00001 diff --git a/mods/hudbars/settingtypes.txt b/mods/hudbars/settingtypes.txt new file mode 100644 index 00000000..3e4390e2 --- /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!ia0y~yU|7V!z#zoI#=yXE!-6%Bfq@~|)5S3)U|>t~ zc6VX;&%nUIV60yAnSp_Uv%n*=n1O*?7=#%aX3ddcU|?V`@$_|Nf5<4nXRdJ9X=5A% z14FK-i(`nz>8n!$xeh4sIImuQ@~{8o+bQp=fS?83{1ON(`P$B>T literal 0 HcmV?d00001 diff --git a/mods/hud/textures/hud_heart_bg.png b/mods/hudbars/textures/hudbars_bgicon_health.png similarity index 100% rename from mods/hud/textures/hud_heart_bg.png rename to mods/hudbars/textures/hudbars_bgicon_health.png diff --git a/mods/hud/textures/hud_air_fg.png b/mods/hudbars/textures/hudbars_icon_breath.png similarity index 100% rename from mods/hud/textures/hud_air_fg.png rename to mods/hudbars/textures/hudbars_icon_breath.png diff --git a/mods/hud/textures/hud_heart_fg.png b/mods/hudbars/textures/hudbars_icon_health.png similarity index 100% rename from mods/hud/textures/hud_heart_fg.png rename to mods/hudbars/textures/hudbars_icon_health.png