]> git.lizzy.rs Git - Crafter.git/blob - mods/player_mechanics/player_interaction.lua
e6901f3cf2ac916453bc42aaaf72ca87f76ca43d
[Crafter.git] / mods / player_mechanics / player_interaction.lua
1 local 
2 minetest,math,pairs,ipairs,type
3 =
4 minetest,math,pairs,ipairs,type
5
6 local add_item   = minetest.add_item
7 local random     = math.random
8 local play_sound = minetest.sound_play
9 local add_ps     = minetest.add_particlespawner
10 local abs        = math.abs
11 local ceil       = math.ceil
12 local new_vec    = vector.new
13 local multiply_vec = vector.multiply
14
15 --hurt sound and disable fall damage group handling
16 minetest.register_on_player_hpchange(function(player, hp_change, reason)
17         if reason.type == "fall" then
18                 --fall damage is handled on another globalstep calc
19                 return(0)
20         elseif hp_change < 0 and reason.reason ~= "correction" then
21                 play_sound("hurt", {object=player, gain = 1.0, max_hear_distance = 60,pitch = random(80,100)/100})
22         end
23         return(hp_change)
24 end, true)
25
26 --throw all items on death
27 local pos
28 local inv
29 local stack
30 local count
31 local obj
32 minetest.register_on_dieplayer(function(player, reason)
33         pos = player:get_pos()
34         inv = player:get_inventory()
35         
36         for i = 1,inv:get_size("main") do
37                 stack = inv:get_stack("main", i)
38                 name = stack:get_name()
39                 count = stack:get_count()
40                 if name ~= "" then
41                         obj = add_item(pos, stack)
42                         if obj then
43                                 obj:set_velocity(new_vec(random(-3,3),random(4,8),random(-3,3)))
44                         end
45                         inv:set_stack("main", i, ItemStack(""))
46                 end
47         end
48
49         stack = inv:get_stack("armor_head", 1)
50         name = stack:get_name()
51         if name ~= "" then
52                 obj = add_item(pos, stack)
53                 if obj then
54                         obj:set_velocity(new_vec(random(-3,3),random(4,8),random(-3,3)))
55                 end
56                 inv:set_stack("armor_head", 1, ItemStack(""))
57         end
58
59         stack = inv:get_stack("armor_torso", 1)
60         name = stack:get_name()
61         if name ~= "" then
62                 obj = add_item(pos, stack)
63                 if obj then
64                         obj:set_velocity(new_vec(random(-3,3),random(4,8),random(-3,3)))
65                 end
66                 inv:set_stack("armor_torso", 1, ItemStack(""))
67         end
68
69         stack = inv:get_stack("armor_legs", 1)
70         name = stack:get_name()
71         if name ~= "" then
72                 obj = add_item(pos, stack)
73                 if obj then
74                         obj:set_velocity(new_vec(random(-3,3),random(4,8),random(-3,3)))
75                 end
76                 inv:set_stack("armor_legs", 1, ItemStack(""))
77         end
78
79
80         stack = inv:get_stack("armor_feet", 1)
81         name = stack:get_name()
82         if name ~= "" then
83                 obj = add_item(pos, stack)
84                 if obj then
85                         obj:set_velocity(new_vec(random(-3,3),random(4,8),random(-3,3)))
86                 end
87                 inv:set_stack("armor_feet", 1, ItemStack(""))
88         end
89
90         dump_craft(player)
91
92         recalculate_armor(player)
93 end)
94
95
96 --this dumps the players crafting table on closing the inventory
97 dump_craft = function(player)
98         pos = player:get_pos()
99         inv = player:get_inventory()
100         for i = 1,inv:get_size("craft") do
101                 stack = inv:get_stack("craft", i)
102                 name = stack:get_name()
103                 count = stack:get_count()
104                 if name ~= "" then
105                         obj = add_item(pos, stack)
106                         if obj then
107                                 obj:set_velocity(new_vec(random(-3,3),random(4,8),random(-3,3)))
108                         end
109                         inv:set_stack("craft", i, ItemStack(""))
110                 end
111         end
112 end
113
114
115 local registered_nodes
116 minetest.register_on_mods_loaded(function()
117         registered_nodes = minetest.registered_nodes
118 end)
119
120 --play sound to keep up with player's placing vs inconsistent client placing sound 
121 local node
122 local sound
123 local placing
124 minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
125         node = registered_nodes[newnode.name]
126         sound = node.sounds
127         placing = ""
128         if sound then
129                 placing = sound.placing
130         end
131         --only play the sound when is defined
132         if type(placing) == "table" then
133                 play_sound(placing.name, {
134                           pos = pos,
135                           gain = placing.gain,
136                           max_hear_distance = 32,
137                           --pitch = random(60,100)/100
138                 })
139         end
140 end)
141
142 --replace stack when empty (building)
143 local new
144 local inv
145 local old
146 local count
147 minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
148         old = itemstack:get_name()
149         --pass through to check
150         minetest.after(0,function(pos, newnode, placer, oldnode, itemstack, pointed_thing,old)
151                 if not placer then
152                         return
153                 end
154                 new = placer:get_wielded_item():get_name()
155                 if old ~= new and new == "" then
156                         inv = placer:get_inventory()
157                         --check if another stack
158                         if inv:contains_item("main", old) then
159                                 --print("moving stack")
160                                 --run through inventory
161                                 for i = 1,inv:get_size("main") do
162                                         --if found set wielded item and remove old stack
163                                         if inv:get_stack("main", i):get_name() == old then
164                                                 count = inv:get_stack("main", i):get_count()
165                                                 placer:set_wielded_item(old.." "..count)
166                                                 inv:set_stack("main",i,ItemStack(""))   
167                                                 play_sound("pickup", {
168                                                           to_player = player,
169                                                           gain = 0.7,
170                                                           pitch = random(60,100)/100
171                                                 })
172                                                 return                          
173                                         end
174                                 end
175                         end
176                 end
177         end,pos, newnode, placer, oldnode, itemstack, pointed_thing,old)
178 end)
179
180 local do_critical_particles = function(pos)
181         add_ps({
182                 amount = 40,
183                 time = 0.001,
184                 minpos = pos,
185                 maxpos = pos,
186                 minvel = new_vec(-2,-2,-2),
187                 maxvel = new_vec(2,8,2),
188                 minacc = {x=0, y=4, z=0},
189                 maxacc = {x=0, y=12, z=0},
190                 minexptime = 1.1,
191                 maxexptime = 1.5,
192                 minsize = 1,
193                 maxsize = 2,
194                 collisiondetection = false,
195                 vertical = false,
196                 texture = "critical.png",
197         })
198 end
199
200 --we need to do this to override the default damage mechanics
201 local pool = {}
202
203 local name
204 minetest.register_on_joinplayer(function(player)
205         name = player:get_player_name()
206         pool[name] = minetest.get_us_time()/1000000
207 end)
208
209 local name
210 function player_can_be_punched(player)
211         name = player:get_player_name()
212         return((minetest.get_us_time()/1000000)-pool[name] >= 0.5)
213 end
214
215 --this throws the player when they're punched and activates the custom damage mechanics
216 local name
217 local temp_pool
218 local hurt
219 local punch_diff
220 local hurt
221 local hp
222 local puncher_vel
223 local vel
224 local hp_modifier
225 local modify_output
226 minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
227         name = player:get_player_name()
228         temp_pool = pool[name]
229
230         punch_diff = (minetest.get_us_time()/1000000)-temp_pool
231
232         hurt = tool_capabilities.damage_groups.damage
233         hp = player:get_hp()
234
235         if punch_diff >= 0.5 and hp > 0 then
236                 
237                 temp_pool = minetest.get_us_time()/1000000
238
239                 if hitter:is_player() and hitter ~= player then
240                         puncher_vel = hitter:get_player_velocity().y
241                         if puncher_vel < 0 then
242                                 hurt = hurt * 1.5
243                                 do_critical_particles(player:get_pos())
244                                 play_sound("critical", {pos=player:get_pos(), gain = 0.1, max_hear_distance = 16,pitch = random(80,100)/100})
245                         end
246                 end
247
248                 dir = multiply_vec(dir,10)
249                 vel = player:get_player_velocity()
250                 dir.y = 0
251                 if vel.y <= 0 then
252                         dir.y = 7
253                 end
254
255                 hp_modifier = ceil(calculate_armor_absorbtion(player)/3)
256                 --print("hp_modifier:",hp_modifier)
257                 damage_armor(player,abs(hurt))
258
259                 --print("hurt:",hurt,"|","hp_modifier:",hp_modifier)
260                 modify_output = (hurt == 0)
261                 
262                 hurt = hurt - hp_modifier
263
264                 if not modify_output and hurt <= 0 then
265                         hurt = 1
266                 elseif modify_output then
267                         hurt = 0
268                 end
269                 player:add_player_velocity(dir)
270                 player:set_hp(hp-hurt)
271         end
272 end)
273
274 local inv
275 minetest.register_on_respawnplayer(function(player)
276         player:add_player_velocity(multiply_vec(player:get_player_velocity(),-1))
277         inv = player:get_inventory()
278         inv:set_list("main", {})
279         inv:set_list("craft", {})
280     inv:set_list("craftpreview", {})
281     inv:set_list("armor_head", {})
282     inv:set_list("armor_torso", {})
283     inv:set_list("armor_legs", {})
284     inv:set_list("armor_feet", {})
285 end)