1 local minetest,math = minetest,math
4 -- player physical data constant
5 local player_constant = {
9 visual_size = {x = 1, y = 1, z = 1},
14 current_animation = "stand",
16 collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
24 -- set player wield item
31 local update_wield_item = function(player)
32 name = player:get_player_name()
33 temp_pool = pool[name]
35 object = temp_pool.wield_item
37 item = player:get_wielded_item():get_name()
39 if not object or (object and not object:get_luaentity()) then
41 object = minetest.add_entity(player:get_pos(),"player_api:item")
43 entity = object:get_luaentity()
47 entity.set_item(entity,item)
51 object:set_attach(player, "Right_Hand", vector.new(0,0,0), vector.new(0,0,0))
53 temp_pool.wield_item = object
59 entity = object:get_luaentity()
60 object_string = entity.itemstring
62 if object_string ~= item then
63 entity.itemstring = item
64 entity.set_item(entity,item)
68 -- easy way to allocate new players
73 local set_all_properties = function(player)
74 name = player:get_player_name()
76 temp_pool = pool[name]
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)
91 -- easy way to set textures
92 local set_textures = function(player, textures)
93 player:set_properties({textures = textures})
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 },
113 -- easy way to set animation
116 local current_animation
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
123 if current_animation == animation_name then
126 temp_pool.animation = animation_name
127 player:set_animation(animation_list[animation_name], speed, 0, loop)
130 -- allows mods to force update animation
132 force_update_animation = function(player)
133 name = player:get_player_name()
134 pool[name].force_update = true
137 -- force updates the player
139 local create_force_update = function(player)
140 name = player:get_player_name()
141 pool[name].force_update = true
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)
150 player_is_attached = function(player,truth)
151 name = player:get_player_name()
152 pool[name].attached = truth
156 player_is_sleeping = function(player,truth)
157 name = player:get_player_name()
158 pool[name].sleeping = truth
162 get_if_player_sleeping = function(player)
163 name = player:get_player_name()
164 return(pool[name].sleeping)
168 -- toggles nametag visibility
170 local show_nametag = function(player,boolean)
177 player:set_nametag_attributes({
187 -- remove all player data
189 minetest.register_on_leaveplayer(function(player)
190 name = player:get_player_name()
195 -- converts yaw to degrees
196 local degrees = function(yaw)
197 return(yaw*180.0/math.pi)
200 -- controls head bone
204 local pitch_look = function(player,sneak)
205 state = get_player_state(player)
206 swimming = is_player_swimming(player)
207 pitch = degrees(player:get_look_vertical()) * -1
214 player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,0,0))
217 -- checks if the player has done anything with their keyboard/mouse
222 local control_check = function(player,control_table)
223 name = player:get_player_name()
224 temp_pool = pool[name]
226 if not temp_pool.old_controls then
227 temp_pool.old_controls = control_table
231 if temp_pool.force_update then
232 temp_pool.old_controls = control_table
236 for i,k in pairs(temp_pool.old_controls) do
237 if control_table[i] ~= k then
238 temp_pool.old_controls = control_table
243 temp_pool.old_controls = control_table
247 -- movement to animation translations
248 local translation_table = {
250 ["keys"] = { -- required keys
256 ["states" ] = { -- states
257 [false] = { -- mouse input
258 [0] = {animation = "walk", speed = 24},
259 [1] = {animation = "walk", speed = 36},
260 [2] = {animation = "walk", speed = 42},
263 [0] = {animation = "walk_mine", speed = 24},
264 [1] = {animation = "walk_mine", speed = 36},
265 [2] = {animation = "walk_mine", speed = 42},
278 [true ] = { -- moving
280 [false] = {animation = "sneak_walk" , speed = 24},
281 [true ] = {animation = "sneak_mine_walk", speed = 24},
283 [false] = { -- moving
285 [false] = {animation = "sneak" , speed = 0 },
286 [true ] = {animation = "sneak_mine_stand", speed = 24},
292 [true ] = {animation = "mine" , speed = 24},
293 [false] = {animation = "stand", speed = 0 },
297 ["keys"] = { -- required keys
304 [true ] = {animation = "swim" , speed = 24},
305 [false] = {animation = "swim_still", speed = 0 },
310 -- translate input and combine with state
317 local control_translation = function(player,control)
318 name = player:get_player_name()
319 temp_pool = pool[name]
321 state = get_player_state(player)
322 swimming = is_player_swimming(player)
324 mouse = (control.LMB or control.RMB)
326 for k,i in pairs(control) do
327 if i and translation_table.swim.keys[k] then
328 translated = translation_table.swim.states[true]
329 set_animation(player, translated.animation, translated.speed)
333 translated = translation_table.swim.states[false]
334 set_animation(player, translated.animation, translated.speed)
337 if control.sneak then
338 for k,i in pairs(control) do
339 if i and translation_table.sneak.keys[k] then
340 translated = translation_table.sneak.states[true][mouse]
341 set_animation(player, translated.animation, translated.speed)
345 translated = translation_table.sneak.states[false][mouse]
346 set_animation(player, translated.animation, translated.speed)
349 for k,i in pairs(control) do
350 if i and translation_table.walk.keys[k] then
351 translated = translation_table.walk.states[mouse][state]
353 set_animation(player, translated.animation, translated.speed)
360 translated = translation_table.stand[mouse]
361 set_animation(player, translated.animation, translated.speed)
365 -- translates player movement to animation
370 local do_animations = function(player)
371 name = player:get_player_name()
372 temp_pool = pool[name]
374 control_table = player:get_player_control()
375 pitch_look(player,control_table.sneak)
377 if player:get_hp() <= 0 then
378 set_animation(player,"die",40,false)
379 elseif not temp_pool.sleeping and (not temp_pool.attached or not player:get_attach()) then
380 temp_pool.attached = false
381 update = control_check(player,control_table)
382 update_wield_item(player)
383 if update and player:get_hp() > 0 then
384 control_translation(player,control_table)
391 -- Update appearance when the player joins
392 minetest.register_on_joinplayer(function(player)
393 set_all_properties(player)
396 minetest.register_on_respawnplayer(function(player)
397 create_force_update(player)
400 -- inject into global loop
401 minetest.register_globalstep(function()
402 for _,player in ipairs(minetest.get_connected_players()) do
403 do_animations(player)
411 local set_item = function(self, item)
412 stack = ItemStack(item or self.itemstring)
413 self.itemstring = stack:to_string()
415 itemname = stack:is_known() and stack:get_name() or "unknown"
417 def = minetest.registered_nodes[itemname]
419 self.object:set_properties({
420 textures = {itemname},
421 wield_item = self.itemstring,
422 glow = def and def.light_source,
426 minetest.register_entity("player_api:item", {
427 initial_properties = {
429 visual = "wielditem",
432 automatic_rotate = 1.5,
436 collide_with_objects = false,
437 collisionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
438 selectionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
439 visual_size = {x = 0.21, y = 0.21},
446 on_step = function(self, dtime)
447 if not self.wielder or (self.wielder and not minetest.get_player_by_name(self.wielder)) then