]> git.lizzy.rs Git - Crafter.git/blob - mods/player_api/init.lua
Added Seasons
[Crafter.git] / mods / player_api / init.lua
1 local minetest,math = minetest,math
2 local pool = {}
3
4 -- player physical data constant
5 local player_constant = {
6         visual               = "mesh"       ,
7         mesh                 = "player.b3d" ,
8         animation_speed      = 24           ,
9         visual_size          = {x = 1, y = 1, z = 1},
10         textures             = {
11                                                         "player.png"    ,
12                                                         "blank_skin.png",
13                                                    },
14         current_animation    = "stand",
15         swimming             = false,
16         collisionbox         = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
17         old_controls         = {},
18         stepheight           = 0.6  ,
19         eye_height           = 1.47 ,
20         attached             = false,
21         wield_item           = nil  ,
22 }
23
24 -- set player wield item
25 local name
26 local temp_pool
27 local item
28 local object
29 local entity
30 local object_string
31 local update_wield_item = function(player)
32         name = player:get_player_name()
33         temp_pool = pool[name]
34
35         object = temp_pool.wield_item
36
37         item = player:get_wielded_item():get_name()
38
39         if not object or (object and not object:get_luaentity()) then
40                 
41                 object = minetest.add_entity(player:get_pos(),"player_api:item")
42
43                 entity = object:get_luaentity()
44
45                 if entity then
46
47                         entity.set_item(entity,item)
48                         
49                         entity.wielder = name
50                         
51                         object:set_attach(player, "Right_Hand", vector.new(0,0,0), vector.new(0, 0, 0))
52                         
53                         temp_pool.wield_item = object
54                 end
55
56                 return -- catch it
57         end
58         
59         entity = object:get_luaentity()
60         object_string = entity.itemstring
61
62         if object_string ~= item then
63                 entity.itemstring = item
64                 entity.set_item(entity,item)
65         end
66 end
67
68 -- easy way to allocate new players
69 local data
70 local name
71 local temp_pool
72
73 local set_all_properties = function(player)
74         name = player:get_player_name()
75         pool[name] = {}
76         temp_pool = pool[name]
77         data = {}
78
79         temp_pool.visual       = player_constant.visual
80         temp_pool.mesh         = player_constant.mesh
81         temp_pool.textures     = player_constant.textures
82         temp_pool.collisionbox = player_constant.collisionbox
83         temp_pool.eye_height   = player_constant.eye_height
84         temp_pool.stepheight   = player_constant.stepheight
85         temp_pool.visual_size  = player_constant.visual_size
86         temp_pool.attached     = false
87         temp_pool.sleeping     = false
88         player:set_properties(temp_pool)
89 end
90
91 -- easy way to set textures
92 local set_textures = function(player, textures)
93         player:set_properties({textures = textures})
94 end
95
96
97 local animation_list = {
98         stand            = { x = 5  , y = 5   },
99         lay              = { x = 162, y = 162 },
100         walk             = { x = 168, y = 187 },
101         mine             = { x = 189, y = 198 },
102         walk_mine        = { x = 200, y = 219 },
103         sit              = { x = 81 , y = 160 },
104         sneak            = { x = 60 , y = 60  },
105         sneak_mine_stand = { x = 20 , y = 30  },
106         sneak_walk       = { x = 60 , y = 80  },
107         sneak_mine_walk  = { x = 40 , y = 59  },
108         swim             = { x = 221, y = 241 },
109         swim_still       = { x = 226, y = 226 },
110         die              = { x = 242, y = 253 },
111 }
112
113 -- easy way to set animation
114 local name
115 local temp_pool
116 local current_animation
117
118 local set_animation = function(player, animation_name, speed, loop)
119         name = player:get_player_name()
120         temp_pool = pool[name]
121         current_animation = temp_pool.animation
122
123         if current_animation == animation_name then
124                 return
125         end
126         temp_pool.animation = animation_name
127         player:set_animation(animation_list[animation_name], speed, 0, loop)
128 end
129
130 -- allows mods to force update animation
131 local name
132 force_update_animation = function(player)
133         name = player:get_player_name()
134         pool[name].force_update = true
135 end
136
137 -- force updates the player
138 local name
139 local create_force_update = function(player)
140         name = player:get_player_name()
141         pool[name].force_update = true
142 end
143
144 -- allows other mods to set animations per player
145 set_player_animation = function(player,animation,speed,loop)
146         set_animation(player, animation, speed, loop)
147 end
148
149 local name
150 player_is_attached = function(player,truth)
151         name = player:get_player_name()
152         pool[name].attached = truth
153 end
154
155 local name
156 get_if_player_attached = function(player)
157         name = player:get_player_name()
158         return(pool[name].attached)
159 end
160
161
162 local name
163 player_is_sleeping = function(player,truth)
164         name = player:get_player_name()
165         pool[name].sleeping = truth
166 end
167
168 local name
169 get_if_player_sleeping = function(player)
170         name = player:get_player_name()
171         return(pool[name].sleeping)
172 end
173
174
175 -- toggles nametag visibility
176 local opacity
177 local show_nametag = function(player,boolean)
178         if boolean then
179                 opacity = 255
180         else
181                 opacity = 0
182         end
183         
184         player:set_nametag_attributes({
185                 color = {
186                         r = 255,
187                         b = 255,
188                         a = opacity,
189                         g = 255
190                 }
191         })
192 end
193
194 -- remove all player data
195 local name
196 minetest.register_on_leaveplayer(function(player)
197         name = player:get_player_name()
198         pool[name] = nil
199 end)
200
201
202 -- converts yaw to degrees
203 local degrees = function(yaw)
204         return(yaw*180.0/math.pi)
205 end
206
207 -- controls head bone
208 local state
209 local swimming
210 local pitch
211 local pitch_look = function(player,sneak)
212         state = get_player_state(player)
213         swimming = is_player_swimming(player)
214         pitch = degrees(player:get_look_vertical()) * -1
215         if swimming then
216                 pitch = pitch + 90
217         elseif sneak then
218                 pitch = pitch + 15
219         end
220
221         player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,0,0))
222 end
223
224 -- checks if the player has done anything with their keyboard/mouse
225 local name
226 local temp_pool
227 local old_control
228
229 local control_check = function(player,control_table)
230         name = player:get_player_name()
231         temp_pool = pool[name]
232
233         if not temp_pool.old_controls then
234                 temp_pool.old_controls = control_table
235                 return(true)
236         end
237
238         if temp_pool.force_update then
239                 temp_pool.old_controls = control_table
240                 return(true)
241         end
242
243         for i,k in pairs(temp_pool.old_controls) do
244                 if control_table[i] ~= k then
245                         temp_pool.old_controls = control_table
246                         return(true)
247                 end
248         end
249
250         temp_pool.old_controls = control_table
251         return(false)
252 end
253
254 -- movement to animation translations
255 local translation_table = {
256         ["walk"] = {
257                 ["keys"]    = { -- required keys
258                         up      = true,
259                         down    = true,
260                         left    = true,
261                         right   = true,
262                 },
263                 ["states" ] = { -- states
264                         [false] = { -- mouse input
265                                 [0] = {animation = "walk", speed = 24},
266                                 [1] = {animation = "walk", speed = 36},
267                                 [2] = {animation = "walk", speed = 42},
268                         },
269                         [true ] = {
270                                 [0] = {animation = "walk_mine", speed = 24},
271                                 [1] = {animation = "walk_mine", speed = 36},
272                                 [2] = {animation = "walk_mine", speed = 42},
273                         }
274                 }
275         },
276
277         ["sneak"] = {
278                 ["keys"]    = {
279                         up      = true,
280                         down    = true,
281                         left    = true,
282                         right   = true,
283                 },
284                 ["states" ] = {
285                         [true ] = { -- moving
286                                 --mouse input
287                                 [false] = {animation = "sneak_walk"     , speed = 24},
288                                 [true ] = {animation = "sneak_mine_walk", speed = 24},
289                         },
290                         [false] = { -- moving
291                                 --mouse input
292                                 [false] = {animation = "sneak"           , speed = 0 },
293                                 [true ] = {animation = "sneak_mine_stand", speed = 24},
294                         }
295                 }
296         },
297         
298         ["stand"]   = {
299                 [true ] = {animation = "mine" , speed = 24},
300                 [false] = {animation = "stand", speed = 0 },
301         },
302
303         ["swim"] = {
304                 ["keys"]    = { -- required keys
305                         up      = true,
306                         down    = true,
307                         left    = true,
308                         right   = true,
309                 },
310                 ["states"]  = {
311                         [true ] = {animation = "swim"      , speed = 24},
312                         [false] = {animation = "swim_still", speed = 0 },
313                 }
314         }
315 }
316
317 -- translate input and combine with state
318 local name
319 local temp_pool
320 local state
321 --local swimming
322 local mouse
323 local translated
324 local control_translation = function(player,control)
325         name = player:get_player_name()
326         temp_pool = pool[name]
327
328         state = get_player_state(player)
329         swimming = is_player_swimming(player)
330
331         mouse = (control.LMB or control.RMB)
332         if swimming then
333                 for k,i in pairs(control) do
334                         if i and translation_table.swim.keys[k] then
335                                 translated = translation_table.swim.states[true]
336                                 set_animation(player, translated.animation, translated.speed)
337                                 return
338                         end
339                 end
340                 translated = translation_table.swim.states[false]
341                 set_animation(player, translated.animation, translated.speed)
342                 return
343         else
344                 if control.sneak then
345                         for k,i in pairs(control) do
346                                 if i and translation_table.sneak.keys[k] then
347                                         translated = translation_table.sneak.states[true][mouse]
348                                         set_animation(player, translated.animation, translated.speed)
349                                         return
350                                 end
351                         end
352                         translated = translation_table.sneak.states[false][mouse]
353                         set_animation(player, translated.animation, translated.speed)
354                         return
355                 else
356                         for k,i in pairs(control) do
357                                 if i and translation_table.walk.keys[k] then
358                                         translated = translation_table.walk.states[mouse][state]
359                                         if translated then
360                                                 set_animation(player, translated.animation, translated.speed)
361                                                 return
362                                         end
363                                 end
364                         end
365                 end
366
367                 translated = translation_table.stand[mouse]
368                 set_animation(player, translated.animation, translated.speed)
369         end
370 end
371
372 -- translates player movement to animation
373 local control_table
374 local update
375 local name
376 local temp_pool
377 local do_animations = function(player)
378         name = player:get_player_name()
379         temp_pool = pool[name]
380
381         control_table = player:get_player_control()
382         pitch_look(player,control_table.sneak)
383
384         if player:get_hp() <= 0 then
385                 set_animation(player,"die",40,false)
386         elseif not temp_pool.sleeping and (not temp_pool.attached or not player:get_attach()) then
387                 temp_pool.attached = false
388                 update = control_check(player,control_table)
389                 update_wield_item(player)
390                 if update and player:get_hp() > 0 then
391                         control_translation(player,control_table)
392                 end
393         end
394 end
395
396
397
398 -- Update appearance when the player joins
399 minetest.register_on_joinplayer(function(player)
400         set_all_properties(player)
401 end)
402
403 minetest.register_on_respawnplayer(function(player)
404         create_force_update(player)
405 end)
406
407 -- inject into global loop
408 minetest.register_globalstep(function()
409         for _,player in ipairs(minetest.get_connected_players()) do
410                 do_animations(player)
411         end
412 end)
413
414
415 local stack
416 local itemname
417 local def
418 local set_item = function(self, item)
419         stack = ItemStack(item or self.itemstring)
420         self.itemstring = stack:to_string()
421
422         itemname = stack:is_known() and stack:get_name() or "unknown"
423
424         def = minetest.registered_nodes[itemname]
425         local tooldef = minetest.registered_tools[itemname]
426
427         self.object:set_properties({
428                 textures = {itemname},
429                 wield_item = self.itemstring,
430                 glow = def and def.light_source,
431         })
432         
433         local parent, bone, offset, rotation, forced_visible = self.object:get_attach()
434         
435         if not parent then
436                 return
437         end
438         
439         if tooldef then
440                 rotation = vector.new(90, 45, 90)
441         else
442                 rotation = vector.new(0, 0, 0)
443         end
444         
445         self.object:set_attach(parent, bone, offset, rotation, forced_visible)
446 end
447
448 minetest.register_entity("player_api:item", {
449         initial_properties = {
450                 hp_max           = 1,
451                 visual           = "wielditem",
452                 physical         = false,
453                 textures         = {""},
454                 automatic_rotate = 1.5,
455                 is_visible       = true,
456                 pointable        = false,
457
458                 collide_with_objects = false,
459                 collisionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
460                 selectionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
461                 visual_size  = {x = 0.21, y = 0.21},
462         },
463
464         itemstring = "",
465
466         set_item = set_item,
467
468         on_step = function(self, dtime)
469                 if not self.wielder or (self.wielder and not minetest.get_player_by_name(self.wielder)) then
470                         self.object:remove()
471                 end
472         end,
473 })