1 local get_group = minetest.get_item_group
3 local get_node = minetest.get_node
4 --add nodes that hurt the player into the touch hurt table
6 minetest.register_on_mods_loaded(function()
7 for _,def in pairs(minetest.registered_nodes) do
8 if get_group(def.name, "touch_hurt") > 0 then
9 table.insert(hurt_nodes,def.name)
12 registered_nodes = minetest.registered_nodes
15 --handle nodes around, inside, and above
16 local player_surroundings_index_table = {}
18 --add the player to the index table when they join and remove when they leave
19 minetest.register_on_joinplayer(function(player)
20 local name = player:get_player_name()
21 player_surroundings_index_table[name] = {}
24 minetest.register_on_leaveplayer(function(player)
25 local name = player:get_player_name()
26 player_surroundings_index_table[name] = nil
28 --reset their drowning settings
29 --minetest.register_on_dieplayer(function(ObjectRef, reason))
32 --handle touching hurt
48 local subval = vector.subtract
50 local abs_it = math.abs
51 local floor_it = math.floor
55 local function handle_hurt(player)
56 if player:get_hp() > 0 then
57 player_pos = player:get_pos()
58 name = player:get_player_name()
59 temp_hurt = player_surroundings_index_table[name].hurt
62 x1 = floor_it(abs_it(player_pos.x-c_pos.x)*100)
63 y1 = floor_it(abs_it(player_pos.y-c_pos.y)*100)
64 z1 = floor_it(abs_it(player_pos.z-c_pos.z)*100)
65 --we will assume the player cbox is equal as x=0.8,y=0.5,z=0.8
66 if x1 <= 80 and z1 <= 80 and y1 <= 50 then
67 heart = player:get_hp()
68 player:set_hp(heart - player_surroundings_index_table[name].hurt.hurt_amount)
83 local function handle_hurt_inside(player)
84 if player:get_hp() > 0 then
85 player_pos = player:get_pos()
86 name = player:get_player_name()
87 legs = player_surroundings_index_table[name].legs
88 head = player_surroundings_index_table[name].head
90 hurt_more = get_group(legs, "hurt_inside")
91 if get_group(head, "hurt_inside") > hurt_more then
92 hurt_more = get_group(head, "hurt_inside")
95 heart = player:get_hp()
96 player:set_hp(heart - hurt_more)
103 --handle player suffocating inside solid node
112 local function handle_player_suffocation(player)
113 if player:get_hp() > 0 then
114 player_pos = player:get_pos()
115 name = player:get_player_name()
116 head = player_surroundings_index_table[name].head
118 if head and registered_nodes[head] then
120 drawy = registered_nodes[head].drawtype
122 if drawy == "normal" then
123 legs = player_surroundings_index_table[name].legs
124 if legs ~= "aether:portal" and legs ~= "nether:portal" then
125 heart = player:get_hp()
126 player:set_hp(heart - 1)
136 --index specific things in area
137 --declare here for ultra extreme efficiency
138 local get_node = minetest.get_node
146 local v_add = vector.add
147 local v_sub = vector.subtract
148 local get_number = table.getn
151 local function index_players_surroundings()
152 for _,player in ipairs(minetest.get_connected_players()) do
153 if player:get_hp() > 0 then
154 --if not dead begin index
155 name = player:get_player_name()
156 pos = player:get_pos()
158 --under player position (useful for walking on hot stuff)
160 player_surroundings_index_table[name].under = get_node(pos).name
162 --at legs position (useful for pushing a player up)
164 player_surroundings_index_table[name].legs = get_node(pos).name
166 --at camera/head position (useful for drowning/being trapped inside node)
168 pos.y = pos.y + 0.940
169 player_surroundings_index_table[name].head = get_node(pos).name
171 handle_player_suffocation(player)
172 handle_hurt_inside(player)
174 --used for finding a damage node next to the player (centered at player's waist)
178 damage_pos = minetest.find_nodes_in_area(a_min, a_max, hurt_nodes)
180 if get_number(damage_pos) > 0 then
181 for _,found_location in ipairs(damage_pos) do
182 gotten_node = get_node(found_location).name
183 collisionbox = registered_nodes[gotten_node].collision_box
184 hurt_amount = get_group(gotten_node, "touch_hurt")
186 if not collisionbox then
187 collisionbox = {-0.5,-0.5,-0.5,0.5,0.5,0.5}
189 player_surroundings_index_table[name].hurt = {pos=found_location,collisionbox=collisionbox,hurt_amount=hurt_amount}
190 --stop doing damage on player if they got hurt
191 if handle_hurt(player) == true then
197 player_surroundings_index_table[name].hurt = nil
202 --4 times a second server tick
203 minetest.after(0.25, function()
204 index_players_surroundings()
207 minetest.register_on_mods_loaded(function()
208 minetest.after(0,function()
209 index_players_surroundings() --begin
214 --completely destroy the breath bar
215 minetest.hud_replace_builtin("breath",{
216 hud_elem_type = "statbar",
217 position = {x = 0.5, y = 1},
218 text = "nothing.png",
221 size = {x = 24, y = 24},
222 offset = {x = 25, y= -(48 + 24 + 16)},
225 minetest.register_on_joinplayer(function(player)
226 player:hud_set_flags({breathbar=false})
228 local meta = player:get_meta()
229 --give players new breath when they join
230 meta:set_int("breath", 10)
232 hud_elem_type = "statbar",
233 position = {x = 0.5, y = 1},
234 text = "bubble_bg.png",
237 size = {x = 24, y = 24},
238 offset = {x = 24*10, y= -(48 + 24 + 39)},
240 local bubble_id = player:hud_add({
241 hud_elem_type = "statbar",
242 position = {x = 0.5, y = 1},
246 size = {x = 24, y = 24},
247 offset = {x = 24*10, y= -(48 + 24 + 39)},
249 meta:set_int("breathbar", bubble_id)
252 --begin custom breathbar
255 --handle the breath bar
256 local function fix_breath_hack()
257 for _,player in ipairs(minetest.get_connected_players()) do
258 player:set_breath(50000)
259 name = player:get_player_name()
260 indexer = player_surroundings_index_table[name].head
261 local meta = player:get_meta()
262 local breath = meta:get_int("breath")
263 local breathbar = meta:get_int("breathbar")
265 if indexer == "main:water" or indexer == "main:waterflow" then
266 local ticker = meta:get_int("breath_ticker")
269 if ticker > 5 then ticker = 0 end
271 meta:set_int("breath_ticker", ticker)
273 if breath > 0 and ticker >= 5 then
275 meta:set_int("breath", breath)
276 player:hud_change(breathbar, "number", breath*2)
277 elseif breath <= 0 and ticker >= 5 then
278 local hp = player:get_hp()
279 meta:set_int("drowning", 1)
281 player:punch(player, 2,
283 full_punch_interval=1.5,
284 damage_groups = {fleshy=2},
288 elseif breath < 10 then --reset the bar
291 meta:set_int("breath", breath)
292 meta:set_int("drowning", 0)
293 meta:set_int("breath_ticker", 0)
294 player:hud_change(breathbar, "number", breath*2)
297 print(meta:get_int("drowning"))
300 minetest.after(0.25, function()
304 minetest.register_on_mods_loaded(function()
305 minetest.after(0,function()