]> git.lizzy.rs Git - Crafter.git/blob - mods/new_functions/init.lua
Overhaul drowning
[Crafter.git] / mods / new_functions / init.lua
1 local get_group = minetest.get_item_group
2 local registered_nodes
3 local get_node = minetest.get_node
4 --add nodes that hurt the player into the touch hurt table
5 local hurt_nodes = {}
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)
10                 end
11         end
12         registered_nodes = minetest.registered_nodes
13 end)
14
15 --handle nodes around, inside, and above
16 local player_surroundings_index_table = {}
17
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] = {}
22 end)
23
24 minetest.register_on_leaveplayer(function(player)
25         local name = player:get_player_name()
26         player_surroundings_index_table[name] = nil
27 end)
28 --reset their drowning settings
29 --minetest.register_on_dieplayer(function(ObjectRef, reason))
30
31
32 --handle touching hurt
33 local player_pos
34
35 local c_pos
36
37 local temp_hurt
38 local x1
39 local y1
40 local z1
41
42 local xcompare
43 local ycompare
44 local zcompare
45
46 local c_player
47
48 local subval = vector.subtract
49
50 local abs_it = math.abs
51 local floor_it = math.floor
52
53 local heart
54
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
60                 if temp_hurt then
61                         c_pos = temp_hurt.pos
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)
69                                 return(true)
70                         end
71                 end
72         end
73         return(false)
74 end
75
76 --handle inside hurt
77 local c_player
78 local heart
79 local legs
80 local head
81 local hurt_more
82 local name = ""
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
89                 if legs and head then
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")
93                         end
94                         
95                         heart = player:get_hp()
96                         player:set_hp(heart - hurt_more)
97                         return(true)
98                 end
99         end
100         return(false)
101 end
102
103 --handle player suffocating inside solid node
104 local c_player
105 local heart
106 local legs
107 local head
108 local hurt_more
109 local drawy
110 local legs
111 local name = ""
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
117                 
118                 if head and registered_nodes[head] then
119             
120                         drawy = registered_nodes[head].drawtype
121
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)
127                                         return(true)
128                                 end
129                         end
130                 end
131         end
132         return(false)
133 end
134
135
136 --index specific things in area
137 --declare here for ultra extreme efficiency
138 local get_node = minetest.get_node
139 local pos
140 local node
141 local name = ""
142 local damage_pos
143 local collisionbox
144 local a_min
145 local a_max
146 local v_add = vector.add
147 local v_sub = vector.subtract
148 local get_number = table.getn
149 local hurt_amount
150 local gotten_node
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()
157                         
158                         --under player position (useful for walking on hot stuff)
159                         pos.y = pos.y - 0.1
160                         player_surroundings_index_table[name].under = get_node(pos).name
161                         
162                         --at legs position (useful for pushing a player up)
163                         pos.y = pos.y + 0.6
164                         player_surroundings_index_table[name].legs = get_node(pos).name
165                         
166                         --at camera/head position (useful for drowning/being trapped inside node)
167                         
168                         pos.y = pos.y + 0.940
169                         player_surroundings_index_table[name].head = get_node(pos).name
170                         
171                         handle_player_suffocation(player)
172                         handle_hurt_inside(player)
173
174                         --used for finding a damage node next to the player (centered at player's waist)
175                         pos.y = pos.y - 0.74
176                         a_min = v_sub(pos,1)
177                         a_max = v_add(pos,1)
178                         damage_pos = minetest.find_nodes_in_area(a_min, a_max, hurt_nodes)
179                         
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")
185                                         
186                                         if not collisionbox then
187                                                 collisionbox = {-0.5,-0.5,-0.5,0.5,0.5,0.5}
188                                         end
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
192                                                 break
193                                         end
194                                 end
195                         else
196                                 collisionbox = nil
197                                 player_surroundings_index_table[name].hurt = nil
198                         end
199                                 
200                 end
201         end
202         --4 times a second server tick
203         minetest.after(0.25, function()
204                 index_players_surroundings()
205         end)
206 end
207 minetest.register_on_mods_loaded(function()
208         minetest.after(0,function()
209                 index_players_surroundings() --begin
210         end)
211 end)
212
213
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",
219         number = 50000,
220         direction = 0,
221         size = {x = 24, y = 24},
222         offset = {x = 25, y= -(48 + 24 + 16)},
223 })
224
225 minetest.register_on_joinplayer(function(player)
226         player:hud_set_flags({breathbar=false})
227         
228         local meta = player:get_meta()
229         --give players new breath when they join
230         meta:set_int("breath", 10)
231         player:hud_add({
232                 hud_elem_type = "statbar",
233                 position = {x = 0.5, y = 1},
234                 text = "bubble_bg.png",
235                 number = 20,
236                 direction = 1,
237                 size = {x = 24, y = 24},
238                 offset = {x = 24*10, y= -(48 + 24 + 39)},
239         })
240         local bubble_id = player:hud_add({
241                 hud_elem_type = "statbar",
242                 position = {x = 0.5, y = 1},
243                 text = "bubble.png",
244                 number = 20,
245                 direction = 1,
246                 size = {x = 24, y = 24},
247                 offset = {x = 24*10, y= -(48 + 24 + 39)},
248         })
249         meta:set_int("breathbar", bubble_id)
250 end)
251
252 --begin custom breathbar
253 local name
254 local indexer
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")
264                 
265                 if indexer == "main:water" or indexer == "main:waterflow" then
266                         local ticker = meta:get_int("breath_ticker")
267                 
268                         ticker = ticker + 1
269                         if ticker > 5 then ticker = 0 end
270
271                         meta:set_int("breath_ticker", ticker)
272                                                 
273                         if breath > 0 and ticker >= 5 then
274                                 breath = breath - 1
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)
280                                 if hp > 0 then
281                                         player:punch(player, 2, 
282                                                 {
283                                                 full_punch_interval=1.5,
284                                                 damage_groups = {fleshy=2},
285                                                 })
286                                 end
287                         end
288                 elseif breath < 10 then --reset the bar
289                         
290                         breath = breath + 1
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)
295                 end
296
297                 print(meta:get_int("drowning"))
298         end
299         
300         minetest.after(0.25, function()
301                 fix_breath_hack()
302         end)
303 end
304 minetest.register_on_mods_loaded(function()
305         minetest.after(0,function()
306                 fix_breath_hack()
307         end)
308 end)