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 get_if_player_attached = function(player)
157 name = player:get_player_name()
158 return(pool[name].attached)
163 player_is_sleeping = function(player,truth)
164 name = player:get_player_name()
165 pool[name].sleeping = truth
169 get_if_player_sleeping = function(player)
170 name = player:get_player_name()
171 return(pool[name].sleeping)
175 -- toggles nametag visibility
177 local show_nametag = function(player,boolean)
184 player:set_nametag_attributes({
194 -- remove all player data
196 minetest.register_on_leaveplayer(function(player)
197 name = player:get_player_name()
202 -- converts yaw to degrees
203 local degrees = function(yaw)
204 return(yaw*180.0/math.pi)
207 -- controls head bone
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
221 player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,0,0))
224 -- checks if the player has done anything with their keyboard/mouse
229 local control_check = function(player,control_table)
230 name = player:get_player_name()
231 temp_pool = pool[name]
233 if not temp_pool.old_controls then
234 temp_pool.old_controls = control_table
238 if temp_pool.force_update then
239 temp_pool.old_controls = control_table
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
250 temp_pool.old_controls = control_table
254 -- movement to animation translations
255 local translation_table = {
257 ["keys"] = { -- required keys
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},
270 [0] = {animation = "walk_mine", speed = 24},
271 [1] = {animation = "walk_mine", speed = 36},
272 [2] = {animation = "walk_mine", speed = 42},
285 [true ] = { -- moving
287 [false] = {animation = "sneak_walk" , speed = 24},
288 [true ] = {animation = "sneak_mine_walk", speed = 24},
290 [false] = { -- moving
292 [false] = {animation = "sneak" , speed = 0 },
293 [true ] = {animation = "sneak_mine_stand", speed = 24},
299 [true ] = {animation = "mine" , speed = 24},
300 [false] = {animation = "stand", speed = 0 },
304 ["keys"] = { -- required keys
311 [true ] = {animation = "swim" , speed = 24},
312 [false] = {animation = "swim_still", speed = 0 },
317 -- translate input and combine with state
324 local control_translation = function(player,control)
325 name = player:get_player_name()
326 temp_pool = pool[name]
328 state = get_player_state(player)
329 swimming = is_player_swimming(player)
331 mouse = (control.LMB or control.RMB)
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)
340 translated = translation_table.swim.states[false]
341 set_animation(player, translated.animation, translated.speed)
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)
352 translated = translation_table.sneak.states[false][mouse]
353 set_animation(player, translated.animation, translated.speed)
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]
360 set_animation(player, translated.animation, translated.speed)
367 translated = translation_table.stand[mouse]
368 set_animation(player, translated.animation, translated.speed)
372 -- translates player movement to animation
377 local do_animations = function(player)
378 name = player:get_player_name()
379 temp_pool = pool[name]
381 control_table = player:get_player_control()
382 pitch_look(player,control_table.sneak)
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)
398 -- Update appearance when the player joins
399 minetest.register_on_joinplayer(function(player)
400 set_all_properties(player)
403 minetest.register_on_respawnplayer(function(player)
404 create_force_update(player)
407 -- inject into global loop
408 minetest.register_globalstep(function()
409 for _,player in ipairs(minetest.get_connected_players()) do
410 do_animations(player)
418 local set_item = function(self, item)
419 stack = ItemStack(item or self.itemstring)
420 self.itemstring = stack:to_string()
422 itemname = stack:is_known() and stack:get_name() or "unknown"
424 def = minetest.registered_nodes[itemname]
425 tooldef = minetest.registered_tools[itemname]
427 self.object:set_properties({
428 textures = {itemname},
429 wield_item = self.itemstring,
430 glow = def and def.light_source,
433 local parent, bone, offset, rotation, forced_visible = self.object:get_attach()
440 rotation = vector.new(90, 45, 90)
442 rotation = vector.new(0, 0, 0)
445 self.object:set_attach(parent, bone, offset, rotation, forced_visible)
448 minetest.register_entity("player_api:item", {
449 initial_properties = {
451 visual = "wielditem",
454 automatic_rotate = 1.5,
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},
468 on_step = function(self, dtime)
469 if not self.wielder or (self.wielder and not minetest.get_player_by_name(self.wielder)) then