forked from Desour/helicopter
-
Notifications
You must be signed in to change notification settings - Fork 6
/
heli_control.lua
executable file
·189 lines (162 loc) · 6.19 KB
/
heli_control.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
--global constants
helicopter.tilting_speed = 1
helicopter.tilting_max = 0.20
helicopter.power_max = 15
helicopter.power_min = 0.2 -- if negative, the helicopter can actively fly downwards
helicopter.wanted_vert_speed = 5
helicopter.vector_up = vector.new(0, 1, 0)
helicopter.vector_forward = vector.new(0, 0, 1)
helicopter.last_time_command = 0
function helicopter.vector_length_sq(v)
return v.x * v.x + v.y * v.y + v.z * v.z
end
if not minetest.global_exists("matrix3") then
dofile(minetest.get_modpath("nss_helicopter") .. DIR_DELIM .. "matrix.lua")
end
function helicopter.check_node_below(obj)
local pos_below = obj:get_pos()
pos_below.y = pos_below.y - 0.1
local node_below = minetest.get_node(pos_below).name
local nodedef = minetest.registered_nodes[node_below]
local touching_ground = not nodedef or -- unknown nodes are solid
nodedef.walkable or false
local liquid_below = not touching_ground and nodedef.liquidtype ~= "none"
return touching_ground, liquid_below
end
function helicopter.heli_control(self, dtime, touching_ground, liquid_below, vel_before)
helicopter.last_time_command = helicopter.last_time_command + dtime
if helicopter.last_time_command > 1 then helicopter.last_time_command = 1 end
if self.driver_name == nil then
return
end
local driver = minetest.get_player_by_name(self.driver_name)
if not driver then
-- there is no driver (eg. because driver left)
self.driver_name = nil
-- gravity
self.object:set_acceleration(vector.multiply(helicopter.vector_up, -helicopter.gravity))
return
end
local ctrl = driver:get_player_control()
if ctrl.aux1 and helicopter.last_time_command > 0.3 then
helicopter.last_time_command = 0
if self._by_mouse == true then
self._by_mouse = false
else
self._by_mouse = true
end
end
local rot = self.object:get_rotation()
local position = self.object:get_pos()
local max_height = 1500
local vert_vel_goal = 0
if not liquid_below then
if ctrl.jump then
local compensated_vert_speed = helicopter.wanted_vert_speed
local curr_percent_height = (100 - ((position.y * 100) / max_height))/100
compensated_vert_speed = compensated_vert_speed * curr_percent_height
vert_vel_goal = vert_vel_goal + compensated_vert_speed
end
if ctrl.sneak then
vert_vel_goal = vert_vel_goal - helicopter.wanted_vert_speed
end
else
vert_vel_goal = helicopter.wanted_vert_speed
end
-- rotation
if not touching_ground then
local rotation = self.object:get_rotation()
local yaw = rotation.y
local tilting_goal = vector.new()
if ctrl.up then
tilting_goal.z = tilting_goal.z + 4
end
if ctrl.down then
tilting_goal.z = tilting_goal.z - 4
end
if self._by_mouse == true then
if ctrl.right then
tilting_goal.x = tilting_goal.x + 4
end
if ctrl.left then
tilting_goal.x = tilting_goal.x - 4
end
else
if ctrl.right then
yaw = yaw - 0.02
tilting_goal.x = tilting_goal.x + 0.2
end
if ctrl.left then
yaw = yaw + 0.02
tilting_goal.x = tilting_goal.x - 0.2
end
end
tilting_goal = vector.multiply(vector.normalize(tilting_goal), helicopter.tilting_max)
-- tilting
if helicopter.vector_length_sq(vector.subtract(tilting_goal, self.tilting)) > (dtime * helicopter.tilting_speed)^2 then
self.tilting = vector.add(self.tilting,
vector.multiply(vector.direction(self.tilting, tilting_goal), dtime * helicopter.tilting_speed))
else
self.tilting = tilting_goal
end
if helicopter.vector_length_sq(self.tilting) > helicopter.tilting_max^2 then
self.tilting = vector.multiply(vector.normalize(self.tilting), helicopter.tilting_max)
end
local new_up = vector.new(self.tilting)
new_up.y = 1
new_up = vector.normalize(new_up) -- this is what vector_up should be after the rotation
local new_right = vector.cross(new_up, helicopter.vector_forward)
local new_forward = vector.cross(new_right, new_up)
local rot_mat = matrix3.new(
new_right.x, new_up.x, new_forward.x,
new_right.y, new_up.y, new_forward.y,
new_right.z, new_up.z, new_forward.z
)
rot = matrix3.to_pitch_yaw_roll(rot_mat)
if self._by_mouse == true then
rot.y = driver:get_look_horizontal()
else
rot.y = yaw
end
else
rot.x = 0
rot.z = 0
self.tilting.x = 0
self.tilting.z = 0
end
self.object:set_rotation(rot)
-- calculate how strong the heli should accelerate towards rotated up
local power = vert_vel_goal - vel_before.y + helicopter.gravity * dtime
power = math.min(math.max(power, helicopter.power_min * dtime), helicopter.power_max * dtime)
-- calculate energy consumption --
----------------------------------
if self.energy > 0 and touching_ground == false then
local consumed_power = (power/1500)
self.energy = self.energy - consumed_power;
local energy_indicator_angle = ((self.energy * 18) - 90) * -1
if self.pointer:get_luaentity() then
self.pointer:set_attach(self.object,'',{x=0,y=11.26,z=9.37},{x=0,y=0,z=energy_indicator_angle})
else
--in case it have lost the entity by some conflict
self.pointer=minetest.add_entity({x=0,y=11.26,z=9.37},"nss_helicopter:pointer")
self.pointer:set_attach(self.object,'',{x=0,y=11.26,z=9.37},{x=0,y=0,z=energy_indicator_angle})
end
end
if self.energy <= 0 then
power = 0.2
if touching_ground or liquid_below then
--criar uma fucao pra isso pois ela repete na linha 268
-- sound and animation
if self.sound_handle then minetest.sound_stop(self.sound_handle) end
self.object:set_animation_frame_speed(0)
-- gravity
self.object:set_acceleration(vector.multiply(helicopter.vector_up, -helicopter.gravity))
end
end
----------------------------
-- end energy consumption --
local rotated_up = matrix3.multiply(matrix3.from_pitch_yaw_roll(rot), helicopter.vector_up)
local added_vel = vector.multiply(rotated_up, power)
added_vel = vector.add(added_vel, vector.multiply(helicopter.vector_up, -helicopter.gravity * dtime))
return vector.add(vel_before, added_vel)
end