1 local minetest,armor_class,math = minetest,armor_class,math
3 --hurt sound and disable fall damage group handling
4 minetest.register_on_player_hpchange(function(player, hp_change, reason)
5 if reason.type == "fall" then
6 if minetest.get_item_group(minetest.get_node(player:get_pos()).name, "disable_fall_damage") > 0 then
9 --boots absorb fall damage
10 local fall_damage = math.floor(player:get_player_velocity().y+0.5)+13
11 --print("fall damage:",fall_damage)
12 local inv = player:get_inventory()
13 local stack = inv:get_stack("armor_feet", 1)
14 local name = stack:get_name()
18 absorption = minetest.get_item_group(name,"armor_level")*2
19 --print("absorbtion:",absorption)
20 local wear_level = ((9-minetest.get_item_group(name,"armor_level"))*8)*(5-minetest.get_item_group(name,"armor_type"))*math.abs(fall_damage)
22 stack:add_wear(wear_level)
24 inv:set_stack("armor_feet", 1, stack)
26 local new_stack = inv:get_stack("armor_feet",1):get_name()
28 if new_stack == "" then
29 minetest.sound_play("armor_break",{to_player=player:get_player_name(),gain=1,pitch=math.random(80,100)/100})
30 armor_class.recalculate_armor(player)
31 armor_class.set_armor_gui(player)
33 elseif minetest.get_item_group(new_stack,"boots") > 0 then
34 local pos = player:get_pos()
35 minetest.add_particlespawner({
38 minpos = {x=pos.x-0.5, y=pos.y+0.1, z=pos.z-0.5},
39 maxpos = {x=pos.x+0.5, y=pos.y+0.1, z=pos.z+0.5},
40 minvel = vector.new(-0.5,1,-0.5),
41 maxvel = vector.new(0.5 ,2 ,0.5),
42 minacc = {x=0, y=-9.81, z=1},
43 maxacc = {x=0, y=-9.81, z=1},
49 collisiondetection = true,
50 collision_removal = true,
52 node = {name= name.."particletexture"},
53 --texture = "eat_particles_1.png"
55 minetest.sound_play("armor_fall_damage", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
58 fall_damage = fall_damage + absorption
60 if fall_damage >= 0 then
63 minetest.sound_play("hurt", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
66 minetest.sound_play("hurt", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
68 --print("returned fall damage",fall_damage)
71 elseif hp_change < 0 then
72 minetest.sound_play("hurt", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
77 --throw all items on death
78 minetest.register_on_dieplayer(function(player, reason)
79 local pos = player:get_pos()
80 local inv = player:get_inventory()
82 for i = 1,inv:get_size("main") do
83 local stack = inv:get_stack("main", i)
84 local name = stack:get_name()
85 local count = stack:get_count()
87 local obj = minetest.add_item(pos, stack)
89 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
91 inv:set_stack("main", i, ItemStack(""))
93 inv:set_stack("main", i, ItemStack(""))
97 local stack = inv:get_stack("armor_head", 1)
98 local name = stack:get_name()
100 local obj = minetest.add_item(pos, stack)
102 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
104 inv:set_stack("armor_head", 1, ItemStack(""))
107 stack = inv:get_stack("armor_torso", 1)
108 name = stack:get_name()
110 local obj = minetest.add_item(pos, stack)
112 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
114 inv:set_stack("armor_torso", 1, ItemStack(""))
117 stack = inv:get_stack("armor_legs", 1)
118 name = stack:get_name()
120 local obj = minetest.add_item(pos, stack)
122 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
124 inv:set_stack("armor_legs", 1, ItemStack(""))
128 stack = inv:get_stack("armor_feet", 1)
129 name = stack:get_name()
131 local obj = minetest.add_item(pos, stack)
133 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
135 inv:set_stack("armor_feet", 1, ItemStack(""))
139 armor_class.recalculate_armor(player)
143 --this dumps the players crafting table on closing the inventory
144 dump_craft = function(player)
145 local inv = player:get_inventory()
146 local pos = player:get_pos()
147 pos.y = pos.y + player:get_properties().eye_height
148 for i = 1,inv:get_size("craft") do
149 local item = inv:get_stack("craft", i)
150 local obj = minetest.add_item(pos, item)
152 local x=math.random(-2,2)*math.random()
153 local y=math.random(2,5)
154 local z=math.random(-2,2)*math.random()
155 obj:set_velocity({x=x, y=y, z=z})
157 inv:set_stack("craft", i, nil)
162 --play sound to keep up with player's placing vs inconsistent client placing sound
163 minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
164 local node = minetest.registered_nodes[newnode.name]
165 local sound = node.sounds
168 placing = sound.placing
170 --only play the sound when is defined
171 if type(placing) == "table" then
172 minetest.sound_play(placing.name, {
175 --pitch = math.random(60,100)/100
180 --replace stack when empty (building)
181 minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
182 local old = itemstack:get_name()
183 --pass through to check
184 minetest.after(0,function(pos, newnode, placer, oldnode, itemstack, pointed_thing,old)
188 local new = placer:get_wielded_item():get_name()
189 if old ~= new and new == "" then
190 local inv = placer:get_inventory()
191 --check if another stack
192 if inv:contains_item("main", old) then
193 --print("moving stack")
194 --run through inventory
195 for i = 1,inv:get_size("main") do
196 --if found set wielded item and remove old stack
197 if inv:get_stack("main", i):get_name() == old then
198 local count = inv:get_stack("main", i):get_count()
199 placer:set_wielded_item(old.." "..count)
200 inv:set_stack("main",i,ItemStack(""))
201 minetest.sound_play("pickup", {
204 pitch = math.random(60,100)/100
211 end,pos, newnode, placer, oldnode, itemstack, pointed_thing,old)
214 local do_critical_particles = function(pos)
215 minetest.add_particlespawner({
220 minvel = vector.new(-2,-2,-2),
221 maxvel = vector.new(2,8,2),
222 minacc = {x=0, y=4, z=0},
223 maxacc = {x=0, y=12, z=0},
228 collisiondetection = false,
230 texture = "critical.png",
234 --we need to do this to override the default damage mechanics
235 minetest.register_on_joinplayer(function(player)
236 local meta = player:get_meta()
237 meta:set_float("player_punch_timer",0)
240 minetest.register_globalstep(function(dtime)
241 for _,player in ipairs(minetest.get_connected_players()) do
242 local meta = player:get_meta()
243 local punch_timer = meta:get_float("player_punch_timer")
245 --limit this so the game engine isn't calculating huge floats
246 if punch_timer > 0 then
247 punch_timer = punch_timer - dtime
248 if punch_timer < 0 then punch_timer = 0 end
249 meta:set_float("player_punch_timer",punch_timer)
254 --this throws the player when they're punched and activates the custom damage mechanics
255 minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
256 local meta = player:get_meta()
257 local punch_timer = meta:get_float("player_punch_timer")
258 local hurt = tool_capabilities.damage_groups.damage
259 local hp = player:get_hp()
260 if punch_timer <= 0 and hp > 0 then
261 meta:set_float("player_punch_timer",0.25)
262 if hitter:is_player() and hitter ~= player then
263 local puncher_vel = hitter:get_player_velocity().y
264 if puncher_vel < 0 then
267 do_critical_particles(player:get_pos())
268 minetest.sound_play("critical", {pos=player:get_pos(), gain = 0.1, max_hear_distance = 16,pitch = math.random(80,100)/100})
272 dir = vector.multiply(dir,10)
273 local vel = player:get_player_velocity()
279 local hp_modifier = math.ceil(armor_class.calculate_armor_absorbtion(player)/3)
280 --print("hp_modifier:",hp_modifier)
281 armor_class.damage_armor(player,math.abs(hurt))
283 --print("hurt:",hurt,"|","hp_modifier:",hp_modifier)
284 local modify_output = (hurt == 0)
286 hurt = hurt - hp_modifier
288 if modify_output == false and hurt <= 0 then
290 elseif modify_output == true then
293 player:add_player_velocity(dir)
294 player:set_hp(hp-hurt)