Airlift Scripts By Schism
The scripts on this page provide you with a powerful resource whenever you want to incorperate some form of vehicle transport/unload operation by helicopter.

This page contains a number of version's Schism work, ordered from newest version at the top down to the older versions. Read this entire page thoroughly to make sure you understand what you require in your mission. The scripts on this page are considered advanced, so hit the forums if you feel you need help.

Airlift Version 2
By Schism

Well, it’s taken a while but finally Airlift V2 is finished. Unfortunately it ended up a lot more complex than I would have liked, but I guess that’s the price for having so many features.

For competent scriptors, I doubt that the Airlift code will present too much of a challenge: it’s not so much advanced as complicated. However, since I’d like to make the scripts accessible to as many people as I can, I’ve written what virtually amounts to a full tutorial anyway... ... bloody hell, it’s 4am! Ten pages ought to be enough, though.

Before we start looking at the actual scripts, it’s probably worth taking a step back to get the ‘big picture’. The aim of Airlift V2 is to provide the basis for dynamic vehicle transportation in Flashpoint missions.

Don’t be put off, but you have to appreciate that these scripts cannot really be cut-and-pasted into your missions. As with all complex scripts, a certain amount of customisation will probably be necessary.

So, what makes Airlift V2 tick? There are ten files, composed of eight separate scripts as well as the description.ext and stringtable.csv data files. In addition to this, you will require three basic triggers plus a single trigger for every orbit-marker you wish the chopper to follow.

Confused already, huh?

We’ll start with the OrbitHelo script and its related items. The purpose of this script is to make the chopper follow a series of marker-waypoints when it is not being used in an airlift.

For example, the chopper flies the player in, drops him off, then follows an orbit (guess where the script name comes from!) around the target area until the mission is finished. Then, when the player radios for extraction, the chopper breaks orbit and zooms into the combat zone to pick him up.

Yes, really! The code for OrbitHelo is as follows:

; OrbitHelo.sqs
; By Schism
; Background Script - called from Init.sqs

; The name of the airlift chopper
_helo = _this select 0

; Default waypoint is WP1
Counter = 1

#loop
~1

; If the main airlift scripts are running, skip.
? Running : goto "loop"

; Send the chopper to the appropriate waypoint
? (Counter == 1) : _Helo CommandMove GetMarkerPos "WP1"
? (Counter == 2) : _Helo CommandMove GetMarkerPos "WP2"
? (Counter == 3) : _Helo CommandMove GetMarkerPos "WP3"
? (Counter == 4) : _Helo CommandMove GetMarkerPos "WP1"

; Keep going round
goto "loop"

exit

It could be a lot smarter, but that has to wait until V3. If I tried to make it perfect the scripts would never be released!

Basically, the loop runs constantly and sends the chopper to a waypoint depending on the contents of global variable Counter. Being global, you can adjust Counter from within the editor (for example, triggers) - and this is exactly what I’ve done:


Here you see the four waypoints (named WP1 - WP4), and the accompanying triggers. Each one is a repeating West Present trigger, which sets the Counter variable to the next waypoint.

So the trigger over WP1 has the On Activation: ‘Counter = 2’, sending the chopper off to WP2.

If you want more (or less) than 4 waypoint-markers, or want to change the names, you must remember to change the OrbitHelo script as well. Common sense ought to get you by!

Be aware that any West units passing through the triggers will adjust the Counter variable - so it’s best to place them on isolated mountaintops or in the sea. That’s one of the reasons I will be reworking this section for V3, when you won’t need triggers and you can set waypoint-marker order in a global array named Orbit. I couldn’t get this working in time for V2, sorry!

The last thing you need to remember is that OrbitHelo is called from Init.sqs and takes the chopper name as an argument. I.e. [Helo1] exec “OrbitHelo.sqs”.

If you set up a mission with four markers named WP1, WP2, WP3, WP4, four triggers as described, and a chopper named Helo with Running = false; [this] exec “OrbitHelo.sqs” the chopper would start orbiting round and round and round and...

Now, the second easy script is ChuteHeight - which keeps the chute in the air when it’s not being used. (If the chute hits the ground it crumples and you’re stuffed).

The code for this is as follows:

; ChuteHeight.sqs
; By Schism

; Name of the chute
_chute = _this select 0

; Loop indefinately
#loop
~0.2

; If the chute's in use, skip this!
?(Descending) : goto "skip"

; Fling the chute up high
_chute SetPos [0,0,2000]

#skip

; Is the airlift script done? If so, quit
? Finished : goto "end"

goto "loop"

exit

Now, you’ll see this is basically the same as OrbitHelo (honest!) - if Descending is true, eg the chute’s in use, then don’t move it, otherwise keep it in the air. This is the same principle as Running in OrbitHelo.sqs, which stops the chopper’s orders when the Airlift is underway.

Like OrbitHelo, this script is called from Init.sqs, and takes one argument, the name of the chute. (I normally call it... chute!)

There are two more scripts before we get to the airlift itself - usermarker and gotomarker. UserMarker was written by Snypir (thanks mate - very useful!) and has been documented elsewhere. Basically it tells you when and where the user creates runtime markers. Anybody who wants to use runtime markers, I advise you to save a lot of hassle and do it with usermarker, rather than write your own handler. I would have, but saw sense eventually (at about 2am!).

Gotomarker is basically another infinate loop script, as follows:

; GotoMarker.sqs
; By Schism

; The name of the user's vehicle and the chopper.
_vehicle = _this select 0
_helo = _this select 1

; loop around
#loop
~2

; Wait for the next marker
userMarkerSet = false
@userMarkerSet

; Check it’s permitted
? (!Running) : goto "loop"

;radio the orders
_vehicle SideRadio "MOVE"

; Order the chopper out.
_helo CommandMove UserMarkerPos

; Radio reply.
_helo SideRadio "MOVE_REPLY"

goto "loop"

exit

It waits for a runtime marker to be generated, then (provided Running is true - ie the airlift is in progress) it will order the chopper to that location, with all the custom radio polish included.

Worth noting - if you decide NOT to use OrbitHelo style marker-waypoints, disable the ?(!Running): line and you can order the chopper about even when unattached. Note that if you are using OrbitHelo a runtime marker command will be overridden by the waypoint marker instructions.

Right, so having dealt with the preliminary scripts it’s time to detail the airlift itself. Firstly, a look at the interface:


This is all that’s required for an airlift mission, as well as the marker-waypoints mentioned earlier. There are three triggers and three units.

The first two triggers must be repeating radio triggers (i.e. they have Radio Alpha / Radio Bravo as the condition and are set to repeating). In the On Activation of each, AlphaPressed (or BravoPressed) is set to true. This allows the background airlift scripts to detect a radio command, and decide what to do with it.

The third trigger is just as simple - it takes AlphaPressed && !Running as its condition, and [Jeep, Helo, Chute] exec "Airlift.sqs" as its On Activation.

What this does is run the airlift script if the player uses Alpha radio and the scripts are not already running. Obviously this could not be done in a script because they wouldn’t be running at the time...

The three units are an empty parachute (Named Chute), a jeep with machinegun (Named Jeep), and a UH-60 (Named Helo). These are the three units mentioned in the third trigger’s On Activation field, above.

So, when the user hits Alpha Radio for the first time they will call Airlift.sqs. However, this is pretty complex stuff so we’re going to look at ActionMonitor.sqs, the first subscript that is called from the main script. This is another relatively simple background loop script, which controls what radio commands and actions are available to the player. The code is as follows:

; ActionMonitor.sqs
; By Schism

; Initialise variables - no commands available by default.
_hasaction = false
_hasaction2 = false

; Passed parameters
_vehicle = _this select 0
_helo = _this select 1
_chute = _this select 2

; Loop for ever
#loop
~0.1

Available = false
_dist = _Helo Distance _Vehicle

; If not attached and close to the chopper
; Make Bravo Channel read "Attach" and set Available to true
?(_dist < 7 && !attached) : Available = true; 2 SetRadioMsg "Attach"

; If attached and doesn't have the action already
; Make Bravo channel read "Detach"
?(Attached && !_hasaction) : 2 SetRadioMsg "Detatch"

; If distance is greater than 10, blank Bravo Channel out.
; It doesn't matter if attached, available, or anything!
?(_dist > 10) : 2 SetRadioMsg " "

; Keep doing the last section until Bravoradio is pressed:
?(!BravoPressed) : goto "loop"

; Then, reset the variable (to detect the next bravopress)
BravoPressed = false

; If not attached and the command is available,
; Then run Attach.sqs, make Attached true and go back to the top loop.
?(!Attached && Available) : [_vehicle, _helo, _chute] exec "Attach.sqs";
Attached = true; goto "loop"

; If attached, the user must have pressed Detatch.
; Set everything to detatch mode and finish.
; (ALL scripts close when Finished = true)
?(Attached) : Release = true; finished = true; 2 setradiomsg " "

; If finished, shut this script.
; Otherwise, back up to the top.
?Finished : goto "end"

goto "loop"

#end
exit

The important parts are from #loop down to ?(BravoPressed), and from ?(BravoPressed) down to goto “loop”. Basically, the top part loops indefinately, checking to see whether the vehicle is close enough to get the Attach command, attached enough to get the Detach command, or nothing at all if neither is true. This goes on until the user presses Bravo Radio channel, setting BravoRadio to true. Then the lower half of the script determines (by looking at what command was available) what to do, and does it.

Worth noting is that the Detatch result causes global variable Finished to be set true, closing the script. ALL the other airlift scripts have a check too, so they will close as well. Basically, when you detach, Airlift is over.

Now we’re going to look at Attach.sqs, the script which does the physical airlifting. You saw where this was called above, and the code is as follows:

; Attach.sqs
; By Schism

; Variables passed in
_vehicle = _this select 0
_helo = _this select 1
_chute = _this select 2

#loop
~0.02

; loop until we are attached
?(!Attached):goto "loop"

; Find the chopper
HeloCoords = getPos _helo

; Hang the vehicle and make it face the right way
_vehicle setPos [HeloCoords select 0, HeloCoords select 1, (HeloCoords select 2)-4.5]
_vehicle setDir (getDir _helo)

; Has global Release been set? If not, go to loop again.
? (!release) : goto "loop"

; So now Release is set, we are detatching.

; Some radio gubbins
_vehicle SideRadio "DETACH"
; Move the chopper up to 50m
_helo FlyInHeight 50
_helo CommandMove GetPos _helo

; More radio gubbins
_helo SideRadio "ASCENDING"

; reset the variables - it's neater.
release = false
attached = false

; What height is the vehicle at?
_z = GetPos _vehicle select 2

; If he's lower than 5m don't bother with a chute, just drop.
?(_z < 5): goto "end"

; So this is for the chute.

; We are now descending. (Stops the ChuteHeight script, for example)
Descending = true

; Move the chute to the vehicle
_chute setPos getPos _vehicle
_chute setDir (getDir _vehicle)

; Do some more radio
_helo SideRadio "DETACH_REPLY"

; Now loop until we hit the ground
#Paraloop
; Get the chute's position
_x = (getPos _chute) select 0
_y = (getPos _chute) select 1
_z = (getPos _chute) select 2

; Re-hang vehicle
_vehicle setPos [_x, _y-1.5, _z-2]
_vehicle setDir (getDir _chute)

~0.01
?(_z > 6) : goto "Paraloop"

; We've come down to 6m, fling the chute up and reset Descending.
_chute SetPos [GetPos _chute select 0, GetPos _chute select 1, 2000]
Descending = false

; Clear up loose ends
#end

; Radio gubbins
_helo SideRadio "DETACH_REPLY"

; We're now finished. Everybody quit.
Finished = true

exit

OK, so what does it all mean? Basically the script waits until something sets the variable Attached to true, then starts looping round and round very fast, keeping the vehicle just underneath the chopper.

This goes on until something sets Release to true, at which point the vehicle will either a) drop to the ground - if it’s low, or B) Parachute to the ground - if it’s high enough.

Parachuting is the same as the airlift - just loop round but put the vehicle under a chute, instead of a chopper. Also, note that Main Battle Tanks are a wee bit too heavy for parachuting: I advise descending before release! (More later)

Agile minds will have noticed that the attach script doesn’t have any prerequisites, so you can just set Attached = true in a unit’s Init field if you so desire. Actually it’s a teeny bit more complex than that, but I’ll explain later.

So, we’ve explained virtually every script, now for the main one. It runs in chronological order, and since we’ve covered all the subscripts the internal commentry ought to make things crystal clear...

Here’s the code:

; AirLift.sqs
; By Schism

; Passed Parameters
_vehicle = _this select 0
_helo = _this select 1
_chute = _this select 2

; Initialising Variables
Running = true
state = "none"
AlphaPressed = false
BravoPressed = false
Descending = false
InProgress = false
Attached = false
Release = false

; Start the action monitor, pronto.
[_vehicle, _helo, _chute] exec "ActionMonitor.sqs"

; Keep it slow. Aim at the vehicle and then head over there.
_helo SetSpeedMode "LIMITED"
_helo DoWatch _vehicle
_helo CommandMove Getpos _vehicle

; We're now in progress, stops calls.
InProgress = true

; Do some dramatic radio.
_vehicle SideRadio "REQUEST_AIRLIFT"
~5
_helo SideRadio "REQUEST_REPLY"
~4
InProgress = false

; If the chopper is too close, miss this section
?(_helo Distance _vehicle) < 100) : goto "skip"

; Set Alpha to request status report.
1 SetRadioMsg "Status Report"

; We wait for speed to build.
@(Speed _helo > 15)

AlphaPressed = false

; Now loop, checking for status requests
#StatusLoop
~0.05

; Have they pressed the radio? If so, do the stuff.
?(!AlphaPressed) : goto "skipstatus"

InProgress = true
AlphaPressed = false
_vehicle SideRadio "STATUS_CHECK"
~4
_helo SideRadio "STATUS_REPORT"
~4
InProgress = false

#skipstatus

?(Speed _helo > 5 ): Goto "StatusLoop"

; OK, the chopper's speed has dropped below 5 or it was too close initially.
#skip

; Send the chopper to the vehicle again - it may have overshot and this will fix that.
_helo CommandMove GetPos _vehicle

; Are we close yet? This MIGHT cause a problem, but the player will probably drive
; towards the chopper anyway, and trigger this!
@_helo Distance _vehicle < 100
InProgress = true

; Do some radio
_helo SideRadio "DESCENDING"
~4
_vehicle SideRadio "ROGER_HAWK"

; Set the chopper to go to 7m
_helo FlyInHeight 7
_helo CommandMove GetPos _helo
~4

; LOOP around until chopper has descended!
#descendcheck
~0.05

_z = GetPos _helo select 2

? (_z > 8) : goto "descendcheck"

; Do some radio gubbins
_helo SideRadio "BOTTOM"
~4
_vehicle SideRadio "ROGER_HAWK"
~4
InProgress = false

; Radio Alpha now reads 'ascend'
1 SetRadioMsg "Ascend"

; First time - we skip the section below!!
goto "skipcheck"

; If he's unattached refuse to budge!
#attachcheck

InProgress = true
_helo SideRadio "UNATTACHED"
~4
CutText ["","PLAIN DOWN",2]
InProgress = false

; Wait for the Ascend command
#skipcheck
AlphaPressed = false
@AlphaPressed
AlphaPressed = false

; Is he attached (Remember, this is monitored in ActionMonitor.sqs && Attach.sqs!)
?(!Attached) : goto "attachcheck"

; OK, we must be attached!
; Send the chopper up to manouvering height.
; And say some radio gubbins.

InProgress = true
_helo FlyInHeight 50
_helo CommandMove GetPos _helo
_vehicle SideRadio "ASCENDING"

; STATE IS NOW UP. This means that Alpharadio will read 'descend' - which is right!!
state = "up"
InProgress = false

; But we'll force it to read descend anyway.
1 SetRadioMsg "Descend"

; Now, keep on checking!
#tag
~0.02
; Is he unattached? If so, goto end and quit the airlift!
?(!Attached): goto "end"

; Check finished too, in case the bad designers have messed around...
?(Finished): goto "end"

; If he presses Radio Alpha and the chopper is UP
; Make it descend with plenty of radio gubbins
?(AlphaPressed && state == "up") : 1 SetRadioMsg "Ascend"; AlphaPressed = false; state = "down"; _helo SideRadio "DESCENDING"; _helo FlyInHeight 7; _helo CommandMove GetPos _helo; _vehicle SideRadio "ROGER_HAWK"

; If he presses Radio Alpha and the chopper is DOWN
; Make it ascend with plenty of radio gubbins
?(AlphaPressed && state == "down") : 1 SetRadioMsg "Descend"; AlphaPressed = false; state = "up"; _helo SideRadio "ASCENDING"; _helo FlyInHeight 50; _helo CommandMove GetPos _helo; _vehicle SideRadio "ROGER_HAWK"
; While we're attached, keep looping.
?(Attached): goto "tag"

; OK, this is the end.
#end

; Set the radio to 'Request Airlift' again.
1 setradiomsg "Request Airlift"

; And we're no longer running. Aw.
Running = false

exit

Gasp. Wow. That’s it. Not!

Hold on, a quick look at Init.sqs is last of all:

; Init.sqs
; Schism’s Airlift Version!

; Initialise variables
AlphaPressed = false
BravoPressed = false
Descending = false
InProgress = false
Attached = false
Release = false
first = true
Finished = false
LockVar = true
running = false

; Set the initial radio messages
1 SetRadioMsg "Request airlift"
2 SetRadioMsg " "

; run OrbitHelo and Chuteheight.
; CUSTOMISING REQUIRES THAT YOU UPDATE THE VEHICLE NAMES!!!!!
[helo] exec "OrbitHelo.sqs"
[chute] exec "ChuteHeight.sqs"

; Usermarker - ADDING MARKERS REQUIRES THAT YOU UPDATE THE NUMBER!!!!!
; (4 is basic - we have 4 four marker-waypoints)
[4] exec "usermarker.sqs"
[jeep, helo] exec "gotomarker.sqs"

exit

There! Yeeehhhaaa!

So, you should now pretty much understand the airlift scripts. If you’re old enough, go to the pub and drink an ice cold pint. Ahhh...

If you’re not, go have some soda pop or something, OK? That’s better. Now, how to transfer my lovely, stable Airlift scripts from the safety of the example into one of your shoogly missions... ;)

What I advise you to do is make a copy of the entire sample mission directory, including the folder, then rename it Temp (.Eden for Everon, .Abel for Malden, .Cain for Kolgugev). This means that all the scripts and items will be moved unchanged into a mission file for a different map. Load it up and all the stuff will be there, just positioned funny.

First, you need to update the four markers named WP1, WP2, WP3 and WP4. Put them circling the mission zone (but well away from any shilkas or hinds!) and move the four triggers onto them. Next you need to move the three special triggers, put them nearby the WP1 marker or something.

Now all you need to do is relocate the jeep and the chopper, and you can start making a mission with Airlift at the foundations!!

Remember that if you add some of your own markers - and let’s face it you’ll want to - then you need to go to Init and update the number being sent to UserMarker.sqs. Also, if you change the chopper, chute or vehicle names, you’ll need to check the scripts to make sure they correspond. Init.sqs in particular, but possibly others too. My advice? Keep those names even if you make it a tank, not a jeep.

The only other thing you might want to do is start with the vehicle already hanging beneath the chopper, right? This is a little more complicated, because the scripts can’t easily be ‘broken into’ midflow. In fact, the radio makes this pretty hard. You’d need to artificially run through the necessary steps but somehow disable the radio transmissions.

OK, an update for airbourne starts will be released in a couple of days. Just suffer until then.

(What you need to do is run a script which triggers the variables - AlphaPressed, BravoPressed, Attached, Ascend - in a certain order to whizz through and start in the air. You’ll also need to install a one-time switch over the radio transmissions, and set up a false CommandMove to get the chopper moving without the presence of a runtime variable... Clever folks feel free to hack in, but if you can’t be arsed it’ll be in Airlift V2.5, OK?)

So, that’s Airlift V2. Any questions at all, please don’t hesitate to post a question on the OFP Editing Center forums or mail me direct at David@allmac.force9.co.uk.

This documentation is actually a small part of the upcoming Helicopter FAQ, (exclusive to OFP Editing Center), so you’ll be seeing the updated version sometime in the future, along with many more helicopter goodies!

In the meantime, keep drinking, editing and...

Cheers,

Schism

Download the script files and sample mission for version 2 here.