]> git.lizzy.rs Git - Crafter.git/blob - mods/player_mechanics/player_mechanics.lua
Remove third person sneaking eye offset
[Crafter.git] / mods / player_mechanics / player_mechanics.lua
1 local minetest,math,vector,ipairs,tonumber = minetest,math,vector,ipairs,tonumber
2
3 local state_channels = {} -- holds every player's channel
4 local pool           = {}
5
6 -- creates specific channels for players
7 local name
8 local temp_pool
9 minetest.register_on_joinplayer(function(player)
10         name = player:get_player_name()
11
12         state_channels[name] = minetest.mod_channel_join(name..":player_movement_state")
13         player:set_physics_override({
14                         jump   = 1.25,
15                         gravity= 1.25
16         })
17
18         pool[name] = {}
19         temp_pool = pool[name]
20         temp_pool.state        = 0
21         temp_pool.old_state    = 0
22         temp_pool.was_in_water = false
23         temp_pool.swimming     = false
24         temp_pool.swim_bumped  = false
25 end)
26
27 -- resets the player's state on death
28 local name
29 minetest.register_on_respawnplayer(function(player)
30         name = player:get_player_name()
31         pool[name].state = 0
32         pool[name].was_in_water = false
33         pool[name].swim_bumped = false
34         send_running_cancellation(player,false)
35 end)
36
37
38 -- delete data on player leaving
39 local name
40 minetest.register_on_leaveplayer(function(player)
41         name = player:get_player_name()
42         pool[name] = nil
43 end)
44
45 -- tells the client to stop sending running/bunnyhop data
46 local name
47 send_running_cancellation = function(player,sneaking)
48         name = player:get_player_name()
49         state_channels[name]:send_all(
50                 minetest.serialize({
51                         stop_running=true,
52                         state=sneaking
53                 }
54         ))
55 end
56
57 -- intercept incoming data messages
58 local channel_decyphered
59 local state
60 minetest.register_on_modchannel_message(function(channel_name, sender, message)
61         channel_decyphered = channel_name:gsub(sender,"")
62         if sender ~= "" and channel_decyphered == ":player_movement_state" then
63                 state = tonumber(message)
64                 if type(state) == "number" then
65                         pool[sender].state = state
66                 end
67         end
68 end)
69
70
71
72
73 -- allows other mods to retrieve data for the game to use
74 local name
75 get_player_state = function(player)
76         name = player:get_player_name()
77         return(pool[name].state)
78 end
79 local name
80 is_player_swimming = function(player)
81         name = player:get_player_name()
82         return(pool[name].swimming)
83 end
84
85 -- controls player states
86 local hunger
87 local name
88 local temp_pool
89 local head
90 local legs
91 local in_water
92 local swim_unlock
93 local swim_bump
94 local control_state = function(player)
95         hunger    = get_player_hunger(player)
96         name      = player:get_player_name()
97         temp_pool = pool[name]
98
99         -- water movement data
100         head = minetest.get_item_group(get_player_head_env(player),"water") > 0
101         legs = minetest.get_item_group(get_player_legs_env(player),"water") > 0
102
103         --check if in water
104         if head then
105                 in_water = true
106                 temp_pool.swimming = true
107         elseif temp_pool.swimming == true then
108                 swim_unlock = player_swim_under_check(player)
109                 swim_bump = player_swim_check(player)
110                 if swim_unlock then
111                         in_water = false
112                         temp_pool.swimming = false
113                 elseif swim_bump then
114                         if player:get_player_velocity().y <= 0 then
115                                 player:add_player_velocity(vector.new(0,9,0))
116                         end
117                 end
118         end
119         
120         if (in_water ~= temp_pool.was_in_water) or 
121         (temp_pool.state ~= temp_pool.old_state) or 
122         ((temp_pool.state == 1 or temp_pool.state == 2) and hunger <= 6) then
123
124                 if (not in_water and temp_pool.was_in_water) then
125                         player:set_physics_override({
126                                 sneak   = true,
127                         })
128
129                         force_update_animation(player)
130
131                         player:set_properties({
132                                 collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
133                         })
134                 elseif in_water and not temp_pool.was_in_water then
135                         
136                         player:set_physics_override({
137                                 sneak   = false,
138                         })
139
140                         force_update_animation(player)
141
142                         player:set_properties({
143                                 collisionbox = {-0.3, 0.8, -0.3, 0.3, 1.6, 0.3},
144                         })
145                         player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
146                 end
147
148                 -- running/swimming fov modifier
149                 if hunger > 6 and (temp_pool.state == 1 or temp_pool.state == 2) then
150                         player:set_fov(1.25, true, 0.15)
151
152                         if temp_pool.state == 2 then
153                                 player:set_physics_override({speed=1.75})
154                         elseif temp_pool.state == 1 then
155                                 player:set_physics_override({speed=1.5})
156                         end
157
158                 elseif (not in_water and temp_pool.state ~= 1 and temp_pool.state ~= 2 and 
159                 (temp_pool.old_state == 1 or temp_pool.old_state == 2)) or 
160                 (in_water and temp_pool.state ~= 1 and temp_pool.state ~= 2 and temp_pool.state ~= 3 and 
161                 (temp_pool.old_state == 1 or temp_pool.old_state == 2 or temp_pool.old_state == 3))then
162
163                         player:set_fov(1, true,0.15)
164                         player:set_physics_override({speed=1})
165
166                         send_running_cancellation(player,temp_pool.state==3) --preserve network data
167                         
168                 elseif (temp_pool.state == 1 or temp_pool.state == 2) and hunger <= 6 then
169                         player:set_fov(1, true,0.15)
170                         player:set_physics_override({speed=1})                          
171                         send_running_cancellation(player,false) --preserve network data
172                 end
173
174                 --sneaking
175                 if temp_pool.state == 3 and in_water then
176                         send_running_cancellation(player,false)
177                 elseif not in_water and temp_pool.state == 3 and temp_pool.old_state ~= 3 then
178                         player:set_eye_offset({x=0,y=-1,z=0},{x=0,y=0,z=0})
179                 elseif not in_water and temp_pool.old_state == 3 and temp_pool.state ~= 3 then
180                         player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
181                 end
182
183                 temp_pool.old_state    = state
184                 temp_pool.was_in_water = in_water
185         
186         -- water movement
187         elseif in_water then
188                 if not temp_pool.was_in_water then
189                         player:set_physics_override({
190                                 sneak   = false ,
191                         })
192                 end
193                 temp_pool.old_state    = temp_pool.old_state
194                 temp_pool.was_in_water = in_water
195         end
196 end
197
198 minetest.register_globalstep(function(dtime)
199         for _,player in ipairs(minetest.get_connected_players()) do
200                 control_state(player)
201         end
202 end)