]> git.lizzy.rs Git - Crafter.git/blob - mods/player/player_interaction.lua
Implement armor defense and make mobs more powerful
[Crafter.git] / mods / player / player_interaction.lua
1 --hurt sound and disable fall damage group handling
2 minetest.register_on_player_hpchange(function(player, hp_change, reason)
3         if reason.type == "fall" then
4                 if minetest.get_item_group(minetest.get_node(player:get_pos()).name, "disable_fall_damage") > 0 then
5                         return(0)
6                 else
7                         minetest.sound_play("hurt", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
8                 end
9         elseif hp_change < 0 then
10                 local hp_modifier = math.ceil(calculate_armor_absorbtion(player)/2)
11                 damage_armor(player,math.abs(hp_change))
12                 hp_change = hp_change + hp_modifier
13                 minetest.sound_play("hurt", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
14
15                 if hp_change >= 0 then
16                         hp_change = -1
17                 end
18         end
19         return(hp_change)
20 end, true)
21
22 --throw all items on death
23 minetest.register_on_dieplayer(function(player, reason)
24         local pos = player:get_pos()
25         local inv = player:get_inventory()
26         
27         for i = 1,inv:get_size("main") do
28                 local stack = inv:get_stack("main", i)
29                 local name = stack:get_name()
30                 local count = stack:get_count()
31                 if name ~= "" then
32                         local obj = minetest.add_item(pos, name.." "..count)
33                         if obj then
34                                 obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
35                         end
36                         inv:set_stack("main", i, ItemStack(""))
37                 else
38                         inv:set_stack("main", i, ItemStack(""))
39                 end
40         end
41
42         local stack = inv:get_stack("armor_head", 1)
43         local name = stack:get_name()
44         if name ~= "" then
45                 local obj = minetest.add_item(pos, name)
46                 if obj then
47                         obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
48                 end
49                 inv:set_stack("armor_head", 1, ItemStack(""))
50         end
51
52         stack = inv:get_stack("armor_torso", 1)
53         name = stack:get_name()
54         if name ~= "" then
55                 local obj = minetest.add_item(pos, name)
56                 if obj then
57                         obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
58                 end
59                 inv:set_stack("armor_torso", 1, ItemStack(""))
60         end
61
62         stack = inv:get_stack("armor_legs", 1)
63         name = stack:get_name()
64         if name ~= "" then
65                 local obj = minetest.add_item(pos, name)
66                 if obj then
67                         obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
68                 end
69                 inv:set_stack("armor_legs", 1, ItemStack(""))
70         end
71
72
73         stack = inv:get_stack("armor_feet", 1)
74         name = stack:get_name()
75         if name ~= "" then
76                 local obj = minetest.add_item(pos, name)
77                 if obj then
78                         obj:set_velocity(vector.new(math.random(-3,3),math.random(4,8),math.random(-3,3)))
79                 end
80                 inv:set_stack("armor_feet", 1, ItemStack(""))
81         end
82
83
84         recalculate_armor(player)
85 end)
86
87
88 --this dumps the players crafting table on closing the inventory
89 dump_craft = function(player)
90         local inv = player:get_inventory()
91         local pos = player:get_pos()
92         pos.y = pos.y + player:get_properties().eye_height
93         for i = 1,inv:get_size("craft") do
94                 local item = inv:get_stack("craft", i)
95                 local obj = minetest.add_item(pos, item)
96                 if obj then
97                         local x=math.random(-2,2)*math.random()
98                         local y=math.random(2,5)
99                         local z=math.random(-2,2)*math.random()
100                         obj:set_velocity({x=x, y=y, z=z})
101                 end
102                 inv:set_stack("craft", i, nil)
103         end
104 end
105
106
107 --play sound to keep up with player's placing vs inconsistent client placing sound 
108 minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
109         local node = minetest.registered_nodes[newnode.name]
110         local sound = node.sounds
111         local placing = ""
112         if sound then
113                 placing = sound.placing
114         end
115         --only play the sound when is defined
116         if type(placing) == "table" then
117                 minetest.sound_play(placing.name, {
118                           pos = pos,
119                           gain = placing.gain,
120                           --pitch = math.random(60,100)/100
121                 })
122         end
123 end)
124
125 --replace stack when empty (building)
126 minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
127         local old = itemstack:get_name()
128         --pass through to check
129         minetest.after(0,function(pos, newnode, placer, oldnode, itemstack, pointed_thing,old)
130                 if not placer then
131                         return
132                 end
133                 local new = placer:get_wielded_item():get_name()
134                 if old ~= new and new == "" then
135                         local inv = placer:get_inventory()
136                         --check if another stack
137                         if inv:contains_item("main", old) then
138                                 --print("moving stack")
139                                 --run through inventory
140                                 for i = 1,inv:get_size("main") do
141                                         --if found set wielded item and remove old stack
142                                         if inv:get_stack("main", i):get_name() == old then
143                                                 local count = inv:get_stack("main", i):get_count()
144                                                 placer:set_wielded_item(old.." "..count)
145                                                 inv:set_stack("main",i,ItemStack(""))   
146                                                 minetest.sound_play("pickup", {
147                                                           to_player = player,
148                                                           gain = 0.7,
149                                                           pitch = math.random(60,100)/100
150                                                 })
151                                                 return                          
152                                         end
153                                 end
154                         end
155                 end
156         end,pos, newnode, placer, oldnode, itemstack, pointed_thing,old)
157 end)
158
159 local do_critical_particles = function(pos)
160         minetest.add_particlespawner({
161                 amount = 40,
162                 time = 0.001,
163                 minpos = pos,
164                 maxpos = pos,
165                 minvel = vector.new(-2,-2,-2),
166                 maxvel = vector.new(2,8,2),
167                 minacc = {x=0, y=4, z=0},
168                 maxacc = {x=0, y=12, z=0},
169                 minexptime = 1.1,
170                 maxexptime = 1.5,
171                 minsize = 1,
172                 maxsize = 2,
173                 collisiondetection = false,
174                 vertical = false,
175                 texture = "critical.png",
176         })
177 end
178
179 --we need to do this to override the default damage mechanics
180 local punch_timers = {}
181 minetest.register_on_joinplayer(function(player)
182         local name = player:get_player_name()
183         punch_timers[name] = 0
184 end)
185
186 minetest.register_globalstep(function(dtime)
187         for _,player in ipairs(minetest.get_connected_players()) do
188                 local name = player:get_player_name()
189                 --limit this so the game engine isn't calculating huge floats
190                 if punch_timers[name] and punch_timers[name] <= 10 then
191                         punch_timers[name] = punch_timers[name] + dtime
192                 end
193         end
194 end)
195
196 --this throws the player when they're punched and activates the custom damage mechanics
197 minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
198         local name = player:get_player_name()
199         local hurt = tool_capabilities.damage_groups.damage
200         local hp = player:get_hp()
201         if punch_timers[name] > 0.8 and hp > 0 then
202                 if hitter:is_player() then
203                         local puncher_vel = hitter:get_player_velocity().y
204                         if puncher_vel < 0 then
205                                 hurt = hurt * 1.5
206                                 critical = true
207                                 do_critical_particles(player:get_pos())
208                                 minetest.sound_play("critical", {pos=player:get_pos(), gain = 0.1, max_hear_distance = 16,pitch = math.random(80,100)/100})
209                         end
210                 end
211
212                 dir = vector.multiply(dir,10)
213                 local vel = player:get_player_velocity()
214                 dir.y = 0
215                 if vel.y <= 0 then
216                         dir.y = 7
217                 end
218                 punch_timers[name] = 0
219                 player:add_player_velocity(dir)
220                 player:set_hp(hp-hurt)
221         end
222 end)
223
224