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