Player_api: Integrate settable player collisionbox
[oweals/minetest_game.git] / mods / player_api / api.lua
1 -- Minetest 0.4 mod: player
2 -- See README.txt for licensing and other information.
3
4 player_api = {}
5
6 -- Player animation blending
7 -- Note: This is currently broken due to a bug in Irrlicht, leave at 0
8 local animation_blend = 0
9
10 player_api.registered_models = { }
11
12 -- Local for speed.
13 local models = player_api.registered_models
14
15 function player_api.register_model(name, def)
16         models[name] = def
17 end
18
19 -- Player stats and animations
20 local player_model = {}
21 local player_textures = {}
22 local player_anim = {}
23 local player_sneak = {}
24 player_api.player_attached = {}
25
26 function player_api.get_animation(player)
27         local name = player:get_player_name()
28         return {
29                 model = player_model[name],
30                 textures = player_textures[name],
31                 animation = player_anim[name],
32         }
33 end
34
35 -- Called when a player's appearance needs to be updated
36 function player_api.set_model(player, model_name)
37         local name = player:get_player_name()
38         local model = models[model_name]
39         if model then
40                 if player_model[name] == model_name then
41                         return
42                 end
43                 player:set_properties({
44                         mesh = model_name,
45                         textures = player_textures[name] or model.textures,
46                         visual = "mesh",
47                         visual_size = model.visual_size or {x=1, y=1},
48                         collisionbox = model.collisionbox or {-0.3, 0.0, -0.3, 0.3, 1.77, 0.3},
49                 })
50                 player_api.set_animation(player, "stand")
51         else
52                 player:set_properties({
53                         textures = { "player.png", "player_back.png", },
54                         visual = "upright_sprite",
55                         collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.75, 0.3},
56                 })
57         end
58         player_model[name] = model_name
59 end
60
61 function player_api.set_textures(player, textures)
62         local name = player:get_player_name()
63         local model = models[player_model[name]]
64         local model_textures = model and model.textures or nil
65         player_textures[name] = textures or model_textures
66         player:set_properties({textures = textures or model_textures,})
67 end
68
69 function player_api.set_animation(player, anim_name, speed)
70         local name = player:get_player_name()
71         if player_anim[name] == anim_name then
72                 return
73         end
74         local model = player_model[name] and models[player_model[name]]
75         if not (model and model.animations[anim_name]) then
76                 return
77         end
78         local anim = model.animations[anim_name]
79         player_anim[name] = anim_name
80         player:set_animation(anim, speed or model.animation_speed, animation_blend)
81 end
82
83 minetest.register_on_leaveplayer(function(player)
84         local name = player:get_player_name()
85         player_model[name] = nil
86         player_anim[name] = nil
87         player_textures[name] = nil
88 end)
89
90 -- Localize for better performance.
91 local player_set_animation = player_api.set_animation
92 local player_attached = player_api.player_attached
93
94 -- Check each player and apply animations
95 minetest.register_globalstep(function(dtime)
96         for _, player in pairs(minetest.get_connected_players()) do
97                 local name = player:get_player_name()
98                 local model_name = player_model[name]
99                 local model = model_name and models[model_name]
100                 if model and not player_attached[name] then
101                         local controls = player:get_player_control()
102                         local walking = false
103                         local animation_speed_mod = model.animation_speed or 30
104
105                         -- Determine if the player is walking
106                         if controls.up or controls.down or controls.left or controls.right then
107                                 walking = true
108                         end
109
110                         -- Determine if the player is sneaking, and reduce animation speed if so
111                         if controls.sneak then
112                                 animation_speed_mod = animation_speed_mod / 2
113                         end
114
115                         -- Apply animations based on what the player is doing
116                         if player:get_hp() == 0 then
117                                 player_set_animation(player, "lay")
118                         elseif walking then
119                                 if player_sneak[name] ~= controls.sneak then
120                                         player_anim[name] = nil
121                                         player_sneak[name] = controls.sneak
122                                 end
123                                 if controls.LMB then
124                                         player_set_animation(player, "walk_mine", animation_speed_mod)
125                                 else
126                                         player_set_animation(player, "walk", animation_speed_mod)
127                                 end
128                         elseif controls.LMB then
129                                 player_set_animation(player, "mine")
130                         else
131                                 player_set_animation(player, "stand", animation_speed_mod)
132                         end
133                 end
134         end
135 end)