Skip to content

Commit ee1d8c9

Browse files
committed
Added 'parachute2' resource (Experimental SA-replicating parachute behavior, refer to #parachute on MTA dev Discord)
Additional project notes are commented in meta.xml & client.lua
1 parent a44a1bc commit ee1d8c9

File tree

2 files changed

+381
-0
lines changed

2 files changed

+381
-0
lines changed

[gameplay]/parachute2/client.lua

+368
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,368 @@
1+
--[[
2+
-- This resource is not finished. Make sure to read the below notes, as well as always use the latest code version from https://github.com/multitheftauto/mtasa-resources/tree/master/%5Bgameplay%5D/parachute2
3+
-- If you are willing to collaborate finishing this resource, or with testing/feedback
4+
-- Then please visit the #parachute channel in MTA Development Discord ( invite link: https://discord.gg/GNN6PRtTnu )
5+
-- Specifically, the posts around this point are relevant,as they are regarding this resource: https://discord.com/channels/801330706252038164/801411291024457778/1361397061123051832
6+
-- Use on production servers is still discouraged, unless you're satisfied with what you see and think it's already better than MTA's parachuting up until now
7+
-- Special thanks to -ffs-Plasma (initial version, written from scratch, and his research on original SA behavior/Parachute SCM)
8+
--]]
9+
10+
local strParachuteState = "NONE";
11+
local strPlayerState = "GROUND";
12+
local strPlayerAction = "NONE";
13+
local bHasParachute = false;
14+
local uParachuteSound = nil;
15+
local uParachuteObject = nil;
16+
local uParachuteCollision = nil;
17+
local iParachuteAnim = false;
18+
local fParachuteX = 0;
19+
local fParachuteY = 0;
20+
local fParachuteZ = 0;
21+
local fParachuteYaw = 0;
22+
local fParachuteRoll = 0;
23+
local fParachutePitch = 0;
24+
local fRotationX, fRotationY, fRotationZ = 0, 0, 0;
25+
local fEasingProgress = 0;
26+
local fEasingProgress2 = 0;
27+
local fEasingProgress3 = 0;
28+
29+
local fAccelerate = 0.1;
30+
31+
local function handleParachuteLogic()
32+
if (getElementHealth(localPlayer) > 0) then
33+
-- get pos/rot/vel/ground from localPlayer
34+
local fPX, fPY, fPZ = getElementPosition(localPlayer);
35+
local fRX, fRY, fRZ = getElementRotation(localPlayer);
36+
local fVX, fVY, fVZ = getElementVelocity(localPlayer);
37+
local fGroundPosition = getGroundPosition(fPX, fPY, fPZ);
38+
39+
-- get player input
40+
local fControlForwards = getPedAnalogControlState(localPlayer, "forwards");
41+
local fControlBackwards = getPedAnalogControlState(localPlayer, "backwards");
42+
local fControlLeft = getPedAnalogControlState(localPlayer, "left");
43+
local fControlRight = getPedAnalogControlState(localPlayer, "right");
44+
45+
-- movement/direction velocity
46+
local fMVX, fMVY, fMVZ, fMRZ = 0, 0, 0, 0;
47+
48+
-- check if player got parachute
49+
if (getPedWeapon(localPlayer, 11) ~= 0) then
50+
if (getPedTotalAmmo(localPlayer, 11) > 0) then
51+
bHasParachute = true;
52+
end
53+
end
54+
55+
-- if we do anything with parachute, disable weapon switching
56+
if (strParachuteState ~= "NONE") then
57+
toggleControl("next_weapon", false);
58+
toggleControl("previous_weapon", false);
59+
end
60+
61+
-- can we go to freefall/skydive
62+
if (strPlayerState == "GROUND" and bHasParachute) then
63+
fRotationX, fRotationY, fRotationZ = getElementRotation(localPlayer);
64+
65+
if (not isPedOnGround(localPlayer) and not getPedContactElement(localPlayer)) then
66+
if (fVZ < -0.1) then
67+
if ((fPZ - fGroundPosition) > 20) then
68+
if (isElement(uParachuteSound)) then destroyElement(uParachuteSound) end
69+
setPedWeaponSlot(localPlayer, 11);
70+
setPedAnimation(localPlayer, "parachute", "fall_skydive", -1, true, true, false, false);
71+
uParachuteSound = playSFX("genrl", 137, 20, true);
72+
strParachuteState = "READY";
73+
strPlayerState = "FREEFALL";
74+
end
75+
end
76+
end
77+
end
78+
79+
-- player is in freefall aka. skydive
80+
if (strPlayerState == "FREEFALL") then
81+
if (fControlForwards ~= 0) then
82+
if (strPlayerAction ~= "FORWARDS") then
83+
setPedAnimation(localPlayer, "parachute", "fall_skydive_accel", -2, true, true, false, false);
84+
end
85+
86+
if (fControlLeft ~= 0) then
87+
fRotationZ = fRotationZ - 1;
88+
elseif (fControlRight ~= 0) then
89+
fRotationZ = fRotationZ + 1;
90+
end
91+
92+
if (fRotationZ < 0) then
93+
fRotationZ = fRotationZ + 360;
94+
elseif (fRotationZ > 360) then
95+
fRotationZ = fRotationZ - 360;
96+
end
97+
98+
local fPitch = interpolateBetween(0, 0, 0, 50, 0, 0, fEasingProgress, "Linear");
99+
100+
fEasingProgress = fEasingProgress + 0.01
101+
102+
if (fEasingProgress > 1) then
103+
fEasingProgress = 1;
104+
end
105+
106+
setElementRotation(localPlayer, fPitch, 0, fRotationZ);
107+
108+
strPlayerAction = "FORWARDS";
109+
elseif (fControlBackwards ~= 0) then
110+
if (strPlayerAction ~= "BACKWARDS") then
111+
setPedAnimation(localPlayer, "parachute", "fall_skydive", -2, true, true, false, false);
112+
end
113+
114+
if (fControlLeft ~= 0) then
115+
fRotationZ = fRotationZ - 1;
116+
elseif (fControlRight ~= 0) then
117+
fRotationZ = fRotationZ + 1;
118+
end
119+
120+
if (fRotationZ < 0) then
121+
fRotationZ = fRotationZ + 360;
122+
elseif (fRotationZ > 360) then
123+
fRotationZ = fRotationZ - 360;
124+
end
125+
126+
local fPitch = interpolateBetween(0, 0, 0, 50, 0, 0, fEasingProgress2, "Linear");
127+
128+
fEasingProgress2 = fEasingProgress2 + 0.01;
129+
130+
if (fEasingProgress2 > 1) then
131+
fEasingProgress2 = 1;
132+
end
133+
134+
setElementRotation(localPlayer, fPitch * -1, 0, fRotationZ);
135+
136+
strPlayerAction = "BACKWARDS";
137+
else
138+
if (fControlLeft ~= 0) then
139+
if (strPlayerAction ~= "LEFT") then
140+
setPedAnimation(localPlayer, "parachute", "fall_skydive_l", -2, true, true, false, false);
141+
end
142+
143+
fRotationZ = fRotationZ - 1;
144+
145+
if (fRotationZ < 0) then
146+
fRotationZ = fRotationZ + 360;
147+
end
148+
149+
setElementRotation(localPlayer, 0, 0, fRotationZ);
150+
151+
strPlayerAction = "LEFT";
152+
elseif (fControlRight ~= 0) then
153+
if (strPlayerAction ~= "RIGHT") then
154+
setPedAnimation(localPlayer, "parachute", "fall_skydive_r", -2, true, true, false, false);
155+
end
156+
157+
fRotationZ = fRotationZ + 1;
158+
159+
if (fRotationZ > 360) then
160+
fRotationZ = fRotationZ - 360;
161+
end
162+
163+
setElementRotation(localPlayer, 0, 0, fRotationZ);
164+
165+
strPlayerAction = "RIGHT";
166+
else
167+
if (strPlayerAction ~= "NONE") then
168+
setPedAnimation(localPlayer, "parachute", "fall_skydive", -2, true, true, false, false);
169+
end
170+
171+
strPlayerAction = "NONE";
172+
end
173+
174+
if (fEasingProgress > 0) then
175+
local fPitch = interpolateBetween(0, 0, 0, 50, 0, 0, fEasingProgress, "Linear");
176+
177+
fEasingProgress = fEasingProgress - 0.01;
178+
179+
if (fEasingProgress < 0) then
180+
fEasingProgress = 0;
181+
end
182+
183+
setElementRotation(localPlayer, fPitch, 0, fRotationZ);
184+
end
185+
186+
if (fEasingProgress2 > 0) then
187+
local fPitch = interpolateBetween(0, 0, 0, 50, 0, 0, fEasingProgress2, "Linear");
188+
189+
fEasingProgress2 = fEasingProgress2 - 0.01;
190+
191+
if (fEasingProgress2 < 0) then
192+
fEasingProgress2 = 0;
193+
end
194+
195+
setElementRotation(localPlayer, fPitch * -1, 0, fRotationZ);
196+
end
197+
end
198+
199+
-- Handle player velocity/rotation (Not sure how yet, block commented out)
200+
201+
--[[
202+
203+
-- X
204+
fParachuteX = fParachuteX / 4.267;
205+
fParachuteX = fParachuteX - fParachuteRoll;
206+
fParachuteX = fParachuteX / 20;
207+
--fParachuteX = fParachuteX * para_time_step;
208+
fParachuteRoll = fParachuteRoll + fParachuteX;
209+
210+
fParachuteX = fParachuteRoll / 5;
211+
--fParachuteX = fParachuteX * para_time_step;
212+
fParachuteYaw = fParachuteX;
213+
214+
if(fParachuteYaw > 180) then
215+
fParachuteYaw = fParachuteYaw - 360;
216+
end
217+
218+
if(fParachuteYaw < -180) then
219+
fParachuteYaw = fParachuteYaw + 360;
220+
end
221+
222+
-- Y
223+
fParachuteX = fParachuteX / 4.267;
224+
fParachuteX = fParachuteX - fParachutePitch;
225+
fParachuteX = fParachuteX / 20;
226+
--fParachuteX = fParachuteX * para_time_step;
227+
fParachutePitch = fParachutePitch + fParachuteX;
228+
--]]
229+
230+
-- player opening parachute
231+
if (getControlState(localPlayer, "fire") and strParachuteState == "READY") then
232+
strPlayerState = "ACTION";
233+
setPedAnimation(localPlayer, "parachute", "para_open", -2, false, false, false, true);
234+
setPedAnimationSpeed(localPlayer, "para_open", 8);
235+
236+
if (isElement(uParachuteSound)) then destroyElement(uParachuteSound) end
237+
uParachuteSound = playSFX("genrl", 137, 21, true);
238+
239+
setTimer(function()
240+
if (isElement(uParachuteSound)) then destroyElement(uParachuteSound) end
241+
uParachuteSound = playSFX("genrl", 137, 66, false);
242+
end, 1100, 1);
243+
end
244+
245+
-- player hit the ground without opening parachute
246+
if ((fPZ - fGroundPosition) < 2) then
247+
strPlayerState = "HITGROUND";
248+
strParachuteState = "NOTREADY";
249+
setPedAnimation(localPlayer, "parachute", "fall_skydive_die", -1, false, false, false, false);
250+
setTimer(cleanupParachute, 2000, 1);
251+
end
252+
end
253+
254+
-- player opening parachute
255+
if (strPlayerState == "ACTION") then
256+
-- is it too late?
257+
if ((fPZ - fGroundPosition) < 2) then
258+
strPlayerState = "HITGROUND";
259+
strParachuteState = "NOTREADY";
260+
setPedAnimation(localPlayer, "parachute", "fall_skydive_die", -1, false, false, false, false);
261+
setTimer(cleanupParachute, 2000, 1);
262+
else
263+
if (strParachuteState ~= "OPENING") then
264+
strParachuteState = "OPENING";
265+
266+
-- prepare parachute opening animation
267+
uParachuteObject = createObject(1310, 0, 0, 0);
268+
attachElements(uParachuteObject, localPlayer);
269+
setObjectScale(uParachuteObject, 0);
270+
-- SCM: PLAY_OBJECT_ANIM parac para_open_o PARACHUTE 1000.0 0 1
271+
iParachuteAnim = getTickCount();
272+
273+
setTimer(function()
274+
strPlayerState = "GLIDING";
275+
strParachuteState = "OPENED";
276+
end, 1000, 1);
277+
end
278+
end
279+
end
280+
281+
-- do parachute opening animation
282+
if (iParachuteAnim) then
283+
if ((getTickCount() - iParachuteAnim) < 500) then
284+
setObjectScale(uParachuteObject, (getTickCount() - iParachuteAnim) / 500);
285+
else
286+
setObjectScale(uParachuteObject, 1);
287+
iParachuteAnim = false;
288+
289+
-- create parachute collision
290+
uParachuteCollision = createObject(3060, 0, 0, 0);
291+
setElementAlpha(uParachuteCollision, 0);
292+
attachElements(uParachuteCollision, uParachuteObject);
293+
-- SCM: SET_OBJECT_DYNAMIC para_col TRUE
294+
-- SCM: SET_OBJECT_RECORDS_COLLISIONS para_col TRUE
295+
end
296+
end
297+
298+
-- player is gliding with parachute
299+
if (strPlayerState == "GLIDING") then
300+
setPedAnimation(localPlayer, "parachute", "para_float", -2, true, false, false, true);
301+
-- SCM: PLAY_OBJECT_ANIM parac para_float_o PARACHUTE 1.0 1 1
302+
303+
if (fControlForwards ~= 0 and strPlayerAction ~= "FORWARDS") then
304+
strPlayerAction = "FORWARDS";
305+
setPedAnimation(localPlayer, "parachute", "para_float", -2, true, false, false, true);
306+
-- SCM: PLAY_OBJECT_ANIM parac para_float_o PARACHUTE 1.0 1 1
307+
elseif (fControlBackwards ~= 0 and strPlayerAction ~= "BACKWARDS") then
308+
strPlayerAction = "BACKWARDS";
309+
setPedAnimation(localPlayer, "parachute", "para_decel", -2, true, false, false, true);
310+
-- SCM: PLAY_OBJECT_ANIM parac para_decel_o PARACHUTE 1.0 1 1
311+
elseif (fControlLeft ~= 0 and strPlayerAction ~= "LEFT") then
312+
strPlayerAction = "LEFT";
313+
setPedAnimation(localPlayer, "parachute", "para_steerl", -2, true, false, false, true);
314+
-- SCM: PLAY_OBJECT_ANIM parac para_steerL_o PARACHUTE 1.0 1 1
315+
elseif (fControlRight ~= 0 and strPlayerAction ~= "RIGHT") then
316+
strPlayerAction = "RIGHT";
317+
setPedAnimation(localPlayer, "parachute", "para_steerr", -2, true, false, false, true);
318+
-- SCM: PLAY_OBJECT_ANIM parac para_steerR_o PARACHUTE 1.0 1 1
319+
else
320+
if (strPlayerAction ~= "NONE") then
321+
setPedAnimation(localPlayer, "parachute", "para_float", -2, true, false, false, true);
322+
-- SCM: PLAY_OBJECT_ANIM parac para_float_o PARACHUTE 1.0 1 1
323+
end
324+
325+
strPlayerAction = "NONE";
326+
end
327+
328+
-- SCM:
329+
-- IF HAS_OBJECT_COLLIDED_WITH_ANYTHING para_col
330+
-- PLAY_OBJECT_ANIM parac para_rip_loop_o PARACHUTE 8.0 1 1
331+
332+
--[[setElementVelocity(localPlayer, x, y, z);
333+
setElementRotation(localPlayer, 0, 0, yaw);
334+
335+
-- player landed
336+
if (fVZ > -0.1) then
337+
strPlayerState = "LANDED";
338+
strParachuteState = "CLOSING";
339+
end--]]
340+
end
341+
342+
-- player landed
343+
if (strPlayerState == "LANDED") then
344+
345+
end
346+
end
347+
end
348+
addEventHandler("onClientRender", root, handleParachuteLogic);
349+
350+
function cleanupParachute(bLandedGood)
351+
iParachuteAnim = false;
352+
bHasParachute = false;
353+
strParachuteState = "NONE";
354+
strPlayerState = "GROUND";
355+
strPlayerAction = "NONE";
356+
357+
if (isElement(uParachuteCollision)) then destroyElement(uParachuteCollision) end;
358+
if (isElement(uParachuteObject)) then destroyElement(uParachuteObject) end;
359+
if (isElement(uParachuteSound)) then destroyElement(uParachuteSound) end;
360+
361+
toggleControl("next_weapon", true);
362+
toggleControl("previous_weapon", true);
363+
364+
if (not bLandedGood) then
365+
-- todo: remove weapon from player via server
366+
-- takeWeapon(client, 46);
367+
end
368+
end

[gameplay]/parachute2/meta.xml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<meta>
2+
<info author="MTA contributors (github.com/multitheftauto/mtasa-resources)" version="2.0" name="Parachutes script v2" description="Experimental parachute resource, still in development and rough around the edges. Aims to replicate GTA SA's parachuting experience more closely, and eventually entirely" type="script"/>
3+
4+
<!-- This resource is not finished. Make sure to read the below notes, as well as always use the latest code version from https://github.com/multitheftauto/mtasa-resources/tree/master/%5Bgameplay%5D/parachute2 -->
5+
<!-- If you are willing to collaborate finishing this resource, or with testing/feedback -->
6+
<!-- Then please visit the #parachute channel in MTA Development Discord ( invite link: https://discord.gg/GNN6PRtTnu ) -->
7+
<!-- Specifically, the posts around this point are relevant,as they are regarding this resource: https://discord.com/channels/801330706252038164/801411291024457778/1361397061123051832 -->
8+
<!-- Use on production servers is still discouraged, unless you're satisfied with what you see and think it's already better than MTA's parachuting up until now -->
9+
10+
<!-- Special thanks to -ffs-Plasma (initial version, written from scratch, and his research on original SA behavior/Parachute SCM) -->
11+
12+
<script src="client.lua" type="client" />
13+
</meta>

0 commit comments

Comments
 (0)