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, its 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 thats the price for having so many features.
For competent scriptors, I doubt that the Airlift code will present too much of a challenge: its not so much advanced as complicated. However, since Id like to make the scripts accessible to as many people as I can, Ive written what virtually amounts to a full tutorial anyway... ... bloody hell, its 4am! Ten pages ought to be enough, though.
Before we start looking at the actual scripts, its 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.
Dont 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?
Well 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 Ive 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 its best to place them on isolated mountaintops or in the sea. Thats one of the reasons I will be reworking this section for V3, when you wont need triggers and you can set waypoint-marker order in a global array named Orbit. I couldnt 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 its not being used. (If the chute hits the ground it crumples and youre 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, youll see this is basically the same as OrbitHelo (honest!) - if Descending is true, eg the chutes in use, then dont move it, otherwise keep it in the air. This is the same principle as Running in OrbitHelo.sqs, which stops the choppers 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 its
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 its time to detail the airlift itself. Firstly, a look at the interface:
This is all thats 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 wouldnt 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 triggers 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 were 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 were 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 its low, or B) Parachute to the ground - if its 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 doesnt have any prerequisites, so you can just set Attached = true in a units Init field if you so desire. Actually its a teeny bit more complex than that, but Ill explain later.
So, weve explained virtually every script, now for the main one. It runs in chronological order, and since weve covered all the subscripts the internal commentry ought to make things crystal clear...
Heres 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. Thats it. Not!
Hold on, a quick look at Init.sqs is last of all:
; Init.sqs
; Schisms 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 youre old enough, go to the pub and drink an ice cold pint. Ahhh...
If youre not, go have some soda pop or something, OK? Thats 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 lets face it youll 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, youll 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 cant easily be broken into midflow. In fact, the radio makes this pretty hard. Youd 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. Youll 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 cant be arsed itll be in Airlift V2.5, OK?)
So, thats Airlift V2. Any questions at all, please dont 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 youll 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.