1 local minetest,armor_class,math,pairs,ipairs = minetest,armor_class,math,pairs,ipairs
10 local cancel_fall_damage = function(player)
11 name = player:get_player_name()
12 if player:get_hp() <= 0 then
15 -- used for finding a damage node from the center of the player
16 -- rudementary collision detection
17 pos = player:get_pos()
18 minetest.chat_send_player(name,dump(pos))
19 pos.y = pos.y + (player:get_properties().collisionbox[5]/2)
30 _,saving_nodes = minetest.find_nodes_in_area( a_min, a_max, {"group:disable_fall_damage"})
32 for node_data,_ in pairs(saving_nodes) do
33 if saving_nodes[node_data] > 0 then
34 table.insert(real_nodes,node_data)
37 -- find the highest damage node
38 if table.getn(real_nodes) > 0 then
50 --hurt sound and disable fall damage group handling
51 minetest.register_on_player_hpchange(function(player, hp_change, reason)
52 if reason.type == "fall" then
53 if cancel_fall_damage(player) then
56 --boots absorb fall damage
57 local fall_damage = math.floor(player:get_player_velocity().y+0.5)+13
58 --print("fall damage:",fall_damage)
59 local inv = player:get_inventory()
60 local stack = inv:get_stack("armor_feet", 1)
61 local name = stack:get_name()
65 absorption = minetest.get_item_group(name,"armor_level")*2
66 --print("absorbtion:",absorption)
67 local wear_level = ((9-minetest.get_item_group(name,"armor_level"))*8)*(5-minetest.get_item_group(name,"armor_type"))*math.abs(fall_damage)
69 stack:add_wear(wear_level)
71 inv:set_stack("armor_feet", 1, stack)
73 local new_stack = inv:get_stack("armor_feet",1):get_name()
75 if new_stack == "" then
76 minetest.sound_play("armor_break",{to_player=player:get_player_name(),gain=1,pitch=math.random(80,100)/100})
77 armor_class.recalculate_armor(player)
78 armor_class.set_armor_gui(player)
80 elseif minetest.get_item_group(new_stack,"boots") > 0 then
81 local pos = player:get_pos()
82 minetest.add_particlespawner({
85 minpos = {x=pos.x-0.5, y=pos.y+0.1, z=pos.z-0.5},
86 maxpos = {x=pos.x+0.5, y=pos.y+0.1, z=pos.z+0.5},
87 minvel = vector.new(-0.5,1,-0.5),
88 maxvel = vector.new(0.5 ,2 ,0.5),
89 minacc = {x=0, y=-9.81, z=1},
90 maxacc = {x=0, y=-9.81, z=1},
96 collisiondetection = true,
97 collision_removal = true,
99 node = {name= name.."particletexture"},
100 --texture = "eat_particles_1.png"
102 minetest.sound_play("armor_fall_damage", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
105 fall_damage = fall_damage + absorption
107 if fall_damage >= 0 then
110 minetest.sound_play("hurt", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
113 minetest.sound_play("hurt", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
115 --print("returned fall damage",fall_damage)
118 elseif hp_change < 0 then
119 minetest.sound_play("hurt", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
124 --throw all items on death
125 minetest.register_on_dieplayer(function(player, reason)
126 local pos = player:get_pos()
127 local inv = player:get_inventory()
129 for i = 1,inv:get_size("main") do
130 local stack = inv:get_stack("main", i)
131 local name = stack:get_name()
132 local count = stack:get_count()
134 local obj = minetest.add_item(pos, stack)
136 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
138 inv:set_stack("main", i, ItemStack(""))
140 inv:set_stack("main", i, ItemStack(""))
144 local stack = inv:get_stack("armor_head", 1)
145 local name = stack:get_name()
147 local obj = minetest.add_item(pos, stack)
149 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
151 inv:set_stack("armor_head", 1, ItemStack(""))
154 stack = inv:get_stack("armor_torso", 1)
155 name = stack:get_name()
157 local obj = minetest.add_item(pos, stack)
159 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
161 inv:set_stack("armor_torso", 1, ItemStack(""))
164 stack = inv:get_stack("armor_legs", 1)
165 name = stack:get_name()
167 local obj = minetest.add_item(pos, stack)
169 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
171 inv:set_stack("armor_legs", 1, ItemStack(""))
175 stack = inv:get_stack("armor_feet", 1)
176 name = stack:get_name()
178 local obj = minetest.add_item(pos, stack)
180 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
182 inv:set_stack("armor_feet", 1, ItemStack(""))
186 armor_class.recalculate_armor(player)
190 --this dumps the players crafting table on closing the inventory
191 dump_craft = function(player)
192 local inv = player:get_inventory()
193 local pos = player:get_pos()
194 pos.y = pos.y + player:get_properties().eye_height
195 for i = 1,inv:get_size("craft") do
196 local item = inv:get_stack("craft", i)
197 local obj = minetest.add_item(pos, item)
199 local x=math.random(-2,2)*math.random()
200 local y=math.random(2,5)
201 local z=math.random(-2,2)*math.random()
202 obj:set_velocity({x=x, y=y, z=z})
204 inv:set_stack("craft", i, nil)
209 --play sound to keep up with player's placing vs inconsistent client placing sound
210 minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
211 local node = minetest.registered_nodes[newnode.name]
212 local sound = node.sounds
215 placing = sound.placing
217 --only play the sound when is defined
218 if type(placing) == "table" then
219 minetest.sound_play(placing.name, {
222 --pitch = math.random(60,100)/100
227 --replace stack when empty (building)
228 minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
229 local old = itemstack:get_name()
230 --pass through to check
231 minetest.after(0,function(pos, newnode, placer, oldnode, itemstack, pointed_thing,old)
235 local new = placer:get_wielded_item():get_name()
236 if old ~= new and new == "" then
237 local inv = placer:get_inventory()
238 --check if another stack
239 if inv:contains_item("main", old) then
240 --print("moving stack")
241 --run through inventory
242 for i = 1,inv:get_size("main") do
243 --if found set wielded item and remove old stack
244 if inv:get_stack("main", i):get_name() == old then
245 local count = inv:get_stack("main", i):get_count()
246 placer:set_wielded_item(old.." "..count)
247 inv:set_stack("main",i,ItemStack(""))
248 minetest.sound_play("pickup", {
251 pitch = math.random(60,100)/100
258 end,pos, newnode, placer, oldnode, itemstack, pointed_thing,old)
261 local do_critical_particles = function(pos)
262 minetest.add_particlespawner({
267 minvel = vector.new(-2,-2,-2),
268 maxvel = vector.new(2,8,2),
269 minacc = {x=0, y=4, z=0},
270 maxacc = {x=0, y=12, z=0},
275 collisiondetection = false,
277 texture = "critical.png",
281 --we need to do this to override the default damage mechanics
282 minetest.register_on_joinplayer(function(player)
283 local meta = player:get_meta()
284 meta:set_float("player_punch_timer",0)
287 minetest.register_globalstep(function(dtime)
288 for _,player in ipairs(minetest.get_connected_players()) do
289 local meta = player:get_meta()
290 local punch_timer = meta:get_float("player_punch_timer")
292 --limit this so the game engine isn't calculating huge floats
293 if punch_timer > 0 then
294 punch_timer = punch_timer - dtime
295 if punch_timer < 0 then punch_timer = 0 end
296 meta:set_float("player_punch_timer",punch_timer)
301 --this throws the player when they're punched and activates the custom damage mechanics
302 minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
303 local meta = player:get_meta()
304 local punch_timer = meta:get_float("player_punch_timer")
305 local hurt = tool_capabilities.damage_groups.damage
306 local hp = player:get_hp()
307 if punch_timer <= 0 and hp > 0 then
308 meta:set_float("player_punch_timer",0.25)
309 if hitter:is_player() and hitter ~= player then
310 local puncher_vel = hitter:get_player_velocity().y
311 if puncher_vel < 0 then
314 do_critical_particles(player:get_pos())
315 minetest.sound_play("critical", {pos=player:get_pos(), gain = 0.1, max_hear_distance = 16,pitch = math.random(80,100)/100})
319 dir = vector.multiply(dir,10)
320 local vel = player:get_player_velocity()
326 local hp_modifier = math.ceil(armor_class.calculate_armor_absorbtion(player)/3)
327 --print("hp_modifier:",hp_modifier)
328 armor_class.damage_armor(player,math.abs(hurt))
330 --print("hurt:",hurt,"|","hp_modifier:",hp_modifier)
331 local modify_output = (hurt == 0)
333 hurt = hurt - hp_modifier
335 if modify_output == false and hurt <= 0 then
337 elseif modify_output == true then
340 player:add_player_velocity(dir)
341 player:set_hp(hp-hurt)