Newgrf Airports Documentation
This is a proposed spec only
This is a proposal for a newgrf airports spec. Whereas the current spec being worked on includes a full state machine, this one attempts to cut as much "hard code" out as possible, leaving a lightweight callback system which is, hopefully, both flexible and powerful, while being as simple as possible to implement.
In many ways, you could see this as my attempt to contribute to newgrf airports, since I can't/don't write OTTD patches, but I do write newgrfs. By moving as much codewriting into newgrf as possible, hopefully we can see newgrf airports included sooner than they otherwise would be.
Premise
This spec treats airports in a similar way to industries; it divides them into "airport tiles", which are the graphical component, and an "airport", which contains the logic. The state machine consists of a list of node positions held in the airport, and a callback that is run when an aircraft interacts with them.
Contents |
Airport Tiles
Airport tiles are the graphical component of the airport. They have no direct interaction or effect on the state machine on or aircraft.
Action 0 Airport Tiles
- 08 (b) Substitute tile type. Default airport tile to use when this newgrf is no longer available. Valid values are 0-8F.
- 0D (b) Land shape flags
- 0E (b) Callback flags Bits 2 and 3 for property 0E are not valid.
- 0F (w) Animation information
- 10 (b) Animation speed
as per Properties for industry tiles 0D, 0E, 0F and 10.
- 13 (b) Hangar #, from 01 to 0F: Clicking on this tile will open the hangar window or create a hangar order. 00 = no hangar.
- 14 (w) Tile Subname string (ie, clicking ? on this tile will give you "AirportName (TileSubname)").
Action 2 Airport Tiles
as per Action 2 for houses and industry tiles
Var Action 2 Airport Tiles
- 41 (B) Ground type, the same as variable 81 for canals
- 43 (D) Relative position
- 44 (B) Animation frame. Like house variable 46 but can contain anything 0..FF.
- 60 (D) Land info of nearby tiles
- 61 (D) Animation stage of nearby tiles
- 62 (D) Get airport tile ID at offset (not yet implemented)
see Variational Action 2 Variables for Industry Tiles for better descriptions, except of course "industry" -> "airport".
Callbacks for Airport Tiles
The related object for airport tiles is the airport.
- Next animation frame (153, like 1A/26/141)
- Animation control (152, like 1B/25/140) not yet implemented
- Length of animation frame (154, like 20/27/142)
- Custom shape check (158, like 2F)
- Decide drawing default foundations (150, like 30)
- Disable autosloping for industry tiles (151, like 3C)
Airports
Airports are the logical component of the airport. The airport contains the state machine.
Action 0 Airports
- 08-09 (2xw) - Years available (start and end year. 0000 and FFFF are forever respectively)
- 0A (data) Tile array similar to Industry Property 0A. Important difference: you have to specify a rotation (b) for every layout. It's the first byte (just before the first tile) and can have the following values: 0 (= not rotation), 2 (= rotated 90 east), 4 (= rotated 180), 6 (=rotated 270 east = 90 west).
- 0B (data) Node array. Each node has an x,y,z position, and a flag byte (hangar, entry point, loading bay) used for overbuilding, buying/selling aircraft in the hangar and, in the case of the entry point(s), aircraft interception from outside the state machine.
- Format: 0B <num nodes> <xx xx yy yy zz zz dd ff> <xx xx yy yy zz zz dd ff> <xx xx yy yy zz zz dd fh> ...
- f values: 1 = loading bay. h = hangar number.
- 0F (b) Small/Large/Helipad/Oilrig (note: for backwards compatibility with vehicle var 44)
- 10 (b) Catchment area radius.
- 11 (w) Noise level
- 12 (w) Name
- 13 (w) Text string to show in the build list
- 14 (b) Max airstrip length. 0 if only helicopters can land (will probably be removed after a callback can replace this)
- 15 (b) Can helicopters land at this airport (1=yes, 0=no) (will probably be removed after a callback can replace this)
- 18 (4xb) Entry point nodes, for planes flying NE, SE, SW, NW.
Not implemented yet:
- 16 (b) Cost multiplier per new tile when building
- 17 (b) Cost multiplier per overbuilt tile when building
- 19 (b) Yearly facility maintanance cost multiplier (possibly ?)
- 20-23 (w) Station name: four text IDs to use as station names if available, otherwise defaults to the old "x Airport" or "x Anystationname".
Action 4 Airports
- Name
- Class (?)
Action 2 Airports
The icon to show in the build list.
Var Action 2 Airports
- 40 (B) layout number
- 48 (D) Bitmask of accepted cargos (see varaction 2 stations)
- 60 (D) Amount of cargo waiting (see varaction 2 stations)
- 61 (D) Time since the cargo was last picked up (see varaction 2 stations)
- 62 (D) Rating of the cargo (see varaction 2 stations)
- 63 (D) Time spent en-route (see varaction 2 stations)
- 64 (W) Information about the last vehicle picking this cargo up (see varaction 2 stations)
- 65 (B) Amount of cargo acceptance (see varaction 2 stations)
- F0 (B) Bit mask of facilities attached to station (see varaction 2 stations)
- FA (W) Date when station was built in days since 1920 (see varaction 2 stations)
- Variable 7C, 16 4-byte slots of persistent data
Not implemented yet:
- Airport type ID
- Year built
- Days since an aircraft last arrived or was loading at any node
- Days since an aircraft last arrived or was loading at a specific node (60+)
- Quantity of passengers waiting at the airport
- Quantity of mail waiting at the airport
- Quantity and ID of most common other cargo waiting at the airport
Callbacks for Airports
The related object is the aircraft that is moving.
state machine callback (157)
The state machine callback is called when an aircraft wants to leave a node. It returns 15 bits, with the 3rd nibble containing the following flags:
- 0 = fly/taxi to the node specified in the low byte
- 1 = change the movement state to the value specified in the low byte and reiterate
- 2 = hold while taxiing. turn to the heading specified in the low byte. The aircraft will wait (16 ticks?) before rerunning the callback.
- 3 = do not allow heading for the hangar (ie, no hangars at this airport are useable by this aircraft) and reiterate. Aircraft which have recieved this return will not attempt to look for a hangar again until they leave the airport or have loaded/unloaded. (not yet implemented)
- 4 = enter the hangar specified in the low byte
- 8 = begin loading/unloading. turn to the heading specified in the low byte
- 9 = service the aircraft and reiterate (allows servicing outside hangars)
- A = play the sound effect specified in the low byte and reiterate (not yet implemented)
- C = throw the alert message specified in the low byte, change plan to "heading for a hangar" and reiterate (not yet implemented)
- D = throw the alert message specified in the low byte, skip to next order, change plan to "heading for an exit" and reiterate (not yet implemented)
- E = throw the alert message specified in the low byte and stop the aircraft (if it's on the ground) or leave the state machine and move to the next order (if it's in the air) (not yet implemented)
- F = leave the state machine. Skip to next order if plan was not "heading for an exit"
Notes:
- stopping the aircraft is probably not a good idea unless the aircraft is in a hangar.
Var 10 contains the number of the node that was triggered. Var 18 contains information on the aircraft's current plan:
- 0 = heading for a bay
- 1 = heading for a hangar
- 2 = heading for a hangar (for servicing only)
- 3 = heading for an exit
- high nibble of var 18 contains the reiteration count.
Type 82 within the callback gets the variables of the aircraft which triggered the callback. This callback + Variable 7C completely replaces the hardcoded state machine!!
Layout name (156)
The return value is the "xx" of a D0xx text ID. It's shown in the build airport window. Use var 40 contains the layout number.
Allowed Aircraft callback (159)
This callback is used to decide which aircraft may be built in hangars and which aircraft can land here. It is also used during overbuilding to decide which aircraft may be moved to the hangar.
When this callback is run, each aircraft which would normally appear in the build list is gone through in turn. The callback should return 0 to allow or 1 to disallow an aircraft. Type 82 within the callback gets the properties of the aircraft. Var 10:
- 0 = populating the buy list, var 18 = hangar num
- 1 = aircraft is flying and want to land on this airport
- 2 = overbuilding.
Aircraft
Aircraft gain an additional property/variable to provide information to the airport state machine. (not implemented)
Action 0 Aircraft
Basic aircraft information
- prop 1C/var 4A: Format xxxxxxsL
- L = runway length required (0-15)
- s = bitmap of valid landing options. It's valid for a vehicle to have none of these bits set if more landing options are added in the (now reserved) extra bits.
Bit Meaning 0 Aircraft can land on normal runway 1 Aircraft can land on water runway 2 Aircraft can land on heliport 3 Aircraft can load at zeppelin pylon
- xxxxxx = the other bytes are reserved.
Aircraft movement states
per [1]00: entering hangar 01: going to hangar entrance point 02..04: going to pad 1..3, respectively 05: going to pad 2 / pad 3 common entry point 06: going to pad 2 / pad 3 / hangar common entry point (large airports only) 07: going to airport's junction point (this is the location where helicopters land and take off) 08: leaving runway 09: going to the in way 0A: entering runway 0B: going to the out way 0C: airplane waiting for take-off clearance (?) 0D: airplane taking off 0E: airplane preparing to take-off 0F: airplane climbing after take-off 10..14: in flight 10 - final approach before landing or going for another round 12 - heading for tower contact point (where airplanes initiate their approach) 14 - heading for the final approach entry point 15: airplane landing (descent) 16: airplane braking after touchdown 17: helicopter taking off from airport 18: helicopter preparing to land at airport 19: helicopter landing at airport 1A: helicopter taking off from heliport 1B: helicopter preparing to land at heliport 1C: helicopter landing at heliport
Clearly, all these states are not necessary any more, however, a few values will result in special behaviors.
- If the aircraft's state changes to 16, the touchdown sound will be played and the aircraft will decelerate to taxi speed.
- If the aircraft's state changes to 0D, 17 or 1A, the takeoff sound will be played.
- If the aircraft's state is 0C or below, its speed will be clamped to taxi speed.
The other states (such as 0F, 10, 12, 15) can still be used to let aircraft grfs know about when they should change speeds, graphics, etc.
Overbuilding (not yet implemented)
Airports can be overbuilt like stations, even if aircraft are currently on the airport. Building a new airport tile over an existing airport tile can have a different cost from building one on empty ground (see airport action 0s above). When an airport is overbuilt, the airport's persistent data variables are reset, and the following happens to the aircraft on the airport:
- All aircraft currently loading will abort loading, have their plan changed to "heading for a bay", will be placed in the same bay number of the new airport (if it exists) or in a random bay (if their current bay doesn't exist), and will then run the state machine callback to lock themselves in. Loading aircraft that don't fit will be moved to the first defined hangar.
- All other aircraft on the ground will be moved to the airport's first defined hangar.
- All aircraft in the air will move to the first defined entry point.
If the airport wants to move aircraft to a hangar but doesn't have one, the overbuilding will fail.
Example Airports
Dusty Airpark
This is an early 2x4 small airport. It has 0x13 nodes defined in the airport action 0, including 3 entry points (0 2 5), four bays (C D E F) and one hangar (11). For the number of available bays it is quite compact, although there are no seperate taxiways so congestion is possible with too many aircraft.Airships can land, depart, and load/unload at (B). They do not fit in the hangar. This is not really a suitable airport for airships.
Simple logic description
Landing and taxing in
Aircraft will intercept the airport at the closest entry point. They will then change to the approach pattern state (10) and fly the pattern (1 2 3 4 6) until a landing runway becomes available. Only aircraft with a runway requirement of 4 or less can land.
Aircraft which have landed on Rwy L will taxi via (D F) in order of preference, or (F D) for helicopters. If (D F) are both blocked, aircraft will wait at their current node (8 or 7).
Aircraft which have landed on the Rwy R and want to go to a bay will taxi to bay (C E) in order of preference, or (E C) for helicopters. If they want the hangar, they will taxi directly via (B 10).
From the bay
Aircraft in bay (C) which want to depart will taxi directly onto Rwy R (A 9). If they want the hangar they can taxi directly (A B 10). Aircraft in bay (D) which want to depart or visit the hangar will taxi via (C) if it is clear, or else via Rwy L (8 7 (F)) if there are not too many aircraft waiting to land. Aircraft in bay (E) which want to depart will taxi directly onto Rwy R (9). If they want the hangar they can taxi directly (9 B 10). Aircraft in bay (F) which want to depart will taxi directly onto Rwy R (E 9) if (E) is clear, or else onto Rwy L (7). If they want the hangar they will taxi via (E 9 B 10).
Helicopters can take off from any runway (7 8 9 A B), but will prefer Rwy R (9 A B) if they can get to it.
From the hangar
Aircraft who want to move from the hangar to a bay will taxi to (E C) in order of preference via (B). Aircraft which want to take off from the hangar will taxi directly via (B 9).
Example NFO
WARNING: Since this is obviously impossible to test at the moment, the code below almost certainly contain numerous errors both logical and typographical. However, I think this is a worthwhile demonstration that a callback-based state machine can work. Please ask questions on the talk page or on the forums.
1 * 1 02 0D FF <build menu graphics> // state machine callback ================================================================================ // Use airport 7C 01 to for the statemachine. Bit values: // 01 0 = Left runway occupied // 02 1 = Right runway occupied // 04 2 = Aircraft waiting to move from D or F // 08 3 = Aircraft waiting to move from C or E // 10 4 = Bay C occupied // 20 5 = Bay D occupied // 40 6 = Bay E occupied // 80 7 = Bay F occupied // 00 01 8 = 01 - 0F = count of aircraft in holding pattern // 00 02 9 = 01 - 0F = count of aircraft in holding pattern // 00 04 a = 01 - 0F = count of aircraft in holding pattern // 00 08 b = 01 - 0F = count of aircraft in holding pattern // 00 10 c = Aircraft from hangar is heading for C // 00 20 d = Aircraft from hangar is heading for E // 00 40 e = Aircraft from D is heading for hangar via Rwy L // 00 80 f = Hangar approach occupied // 00 00 01 = // 00 00 02 = // 00 00 04 = // 00 00 08 = // 00 00 10 = // 00 00 20 = // 00 00 40 = // 00 00 80 = // 00 00 00 01 = // 00 00 00 02 = // 00 00 00 04 = // 00 00 00 08 = // 00 00 00 10 = // 00 00 00 20 = // 00 00 00 40 = // 00 00 00 80 = // hangar nodes ========================================= // node 11 ========== Hangar // Aircraft will only leave the hangar if both the hangar approach // and Rwy R is clear. Additionally, aircraft which want to go to // a bay will only exit the hangar if they can also lock either bay // E or C. They also set the appropriate flag to tell the nodes on // the runway where they are headed for. 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 0B 80 // set movement state to taxi (07) and target to node 0B. 1 * 1 02 0D A4 85 7C 01 60 FD FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, 1 * 1 02 0D EE 81 7C 01 60 BF DF 40 20 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock E, set H->E, 1 * 1 02 0D CC 81 7C 01 60 EF EF 10 10 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock C, set H->C, // vv C+ vv E+ 1 * 1 02 0D 10 81 7C 01 00 50 02 CC 00 40 40 EE 00 10 50 03 82 // heading for a bay, Are bays C or E available? 1 * 1 02 0D 11 81 11 00 FF 02 A4 00 01 02 A4 00 03 03 10 00 // plan is hangar? plan is takeoff? 1 * 1 02 0D 11 85 7C 01 00 02 80 01 01 11 00 00 00 00 00 03 82 // if Rwy R and hangar approach are available, // node 10 ========== Hangar Entry // The function of this node is simply to unlock the hangar approach // when the aircraft arrives at the hangar. The aircraft is then // moved into the hangar proper. 1 * 1 02 0D 01 85 7C 01 60 FF 7F 10 00 \w1 \2sto 1A 00 \w1 01 11 80 00 00 00 00 11 80 // unlock hangar approach and move to hangar node 11 // end hangar nodes ===================================== // bay nodes ============================================ // node 0F ========== Bay 0F // Aircraft from bay 0F will taxi to either runway to take off, // although they will prefer Rwy R if it's available, and will // not use Rwy L if there are more than 3 aircraft waiting to land. // Aircraft from this bay taxi to the hangar via bay 0E, and // will move across into that bay if they're heading for the // hangar, and 0E is clear. 1 * 1 02 0D A5 85 7C 01 60 FB FF 04 00 \w1 \2sto 1A 00 \w1 01 03 82 00 00 00 00 03 82 // else set waiting at D, turn to heading 3 and wait. 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 0E 80 // set movement state to taxi (07) and target to node 0E. 1 * 1 02 0D B4 85 7C 01 60 33 FF 48 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock E, unlock F, unlock aircraft waiting, lock aircraft waiting and 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 09 80 // set movement state to taxi (07) and target to node 09. 1 * 1 02 0D A4 85 7C 01 60 79 FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, unlock F, unlock aircraft waiting and vv +RC vv+E 1 * 1 02 0D 03 81 7C 01 00 42 02 A4 00 00 00 B4 00 02 02 A5 00 // taxi to hangar: if Rwy R and C is available, 1 * 1 02 0D A5 85 7C 01 60 FB FF 04 00 \w1 \2sto 1A 00 \w1 01 01 82 00 00 00 00 01 82 // else set waiting at D, turn to heading 1 and wait. 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 07 80 // set movement state to taxi (07) and target to node 07. 1 * 1 02 0D A4 85 7C 01 60 7A FF 01 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, unlock F, unlock aircraft waiting and 1 * 1 02 0D A5 81 7C 01 08 0F 01 A4 00 00 02 A5 00 // there are 2 or fewer aircraft in the holding pattern, 1 * 1 02 0D A5 81 7C 01 00 01 01 A4 00 00 00 A5 00 // else if Rwy L is available, and 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 09 80 // set movement state to taxi (07) and target to node 09. 1 * 1 02 0D A4 85 7C 01 60 79 FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, unlock F, unlock aircraft waiting and 1 * 1 02 0D 03 81 7C 01 00 42 01 A4 00 00 00 A5 00 // taxi to takeoff: if Rwy R and E is available, 1 * 1 02 0D 0F 81 11 00 FF 02 01 00 01 02 03 00 03 03 01 88 // plan is hangar? plan is takeoff? // node 0E ========== Bay 0E // Aircraft from bay 0E will taxi to either runway to take off, // although they will prefer Rwy R if it's available, and will // not use Rwy L if there is more than 1 aircraft waiting to land. 1 * 1 02 0D A5 85 7C 01 60 F7 FF 08 00 \w1 \2sto 1A 00 \w1 01 03 82 00 00 00 00 03 82 // else set waiting at C, turn to heading 3 and wait. 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 09 80 // set movement state to taxi (07) and target to node 09. 1 * 1 02 0D A4 85 7C 01 60 B5 FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, unlock E, unlock aircraft waiting and 1 * 1 02 0D 01 81 7C 01 01 01 01 A4 00 00 00 A5 00 // taxi to hangar: if Rwy R is available, 1 * 1 02 0D A5 85 7C 01 60 F7 FF 08 00 \w1 \2sto 1A 00 \w1 01 01 82 00 00 00 00 01 82 // else set waiting at C, turn to heading 1 and wait. 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 07 80 // set movement state to taxi (07) and target to node 07. 1 * 1 02 0D A4 85 7C 01 60 B6 FF 01 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy L, unlock E, unlock aircraft waiting, and 1 * 1 02 0D A5 81 7C 01 08 0F 01 A4 00 00 01 A5 00 // there are 1 or fewer aircraft in the holding pattern, 1 * 1 02 0D A5 81 7C 01 00 81 01 A4 00 00 00 A5 00 // else if F and Rwy L are available, and 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 09 80 // set movement state to taxi (07) and target to node 09. 1 * 1 02 0D A4 85 7C 01 60 B5 FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, unlock E, unlock aircraft waiting and 1 * 1 02 0D 03 81 7C 01 01 01 01 A4 00 00 00 A5 00 // taxi to takeoff: if Rwy R is available, 1 * 1 02 0D 0E 81 11 00 FF 02 01 00 01 02 03 00 03 03 01 88 // plan is hangar? plan is takeoff? // node 0D ========== Bay 0D // Aircraft from bay 0D will taxi to either runway to take off, // although they will prefer Rwy R if it's available, and will // not use Rwy L if there is more than 3 aircraft waiting to land. // If they want to take off or go to the hangar and bay C is // unoccupied, they will move across into that bay. If they want // to get to the hangar, but bay C is occupied, they can drive the // long way around via Rwy L and bay F, providing the airport is // not very busy. 1 * 1 02 0D A5 85 7C 01 60 FB FF 04 00 \w1 \2sto 1A 00 \w1 01 05 82 00 00 00 00 05 82 // else set waiting at D, turn to heading 5 and wait. 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 08 80 // set movement state to taxi (07) and target to node 08. 1 * 1 02 0D A4 85 7C 01 60 5A DF 81 40 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy L, lock F, set D->F, unlock D, unlock aircraft waiting and 1 * 1 02 0D A5 81 7C 01 08 0F 01 A4 00 00 01 A5 00 // there is 1 or fewer aircraft in the holding pattern, 1 * 1 02 0D A5 81 7C 01 00 81 01 A4 00 00 00 A5 00 // else if Rwy L and F are available, and 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 0C 80 // set movement state to taxi (07) and target to node 0C. 1 * 1 02 0D B4 85 7C 01 60 C3 FF 18 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock C, unlock D, unlock aircraft waiting, lock aircraft waiting and 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 0A 80 // set movement state to taxi (07) and target to node 0A. 1 * 1 02 0D A4 85 7C 01 60 D9 FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, unlock D, unlock aircraft waiting and vv +RC vv+C 1 * 1 02 0D 01 81 7C 01 00 12 02 A4 00 00 00 B4 00 02 02 A5 00 // taxi to hangar: if Rwy R and C is available, 1 * 1 02 0D A5 85 7C 01 60 FB FF 04 00 \w1 \2sto 1A 00 \w1 01 05 82 00 00 00 00 05 82 // else set waiting at D, turn to heading 5 and wait. 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 08 80 // set movement state to taxi (07) and target to node 08. 1 * 1 02 0D A4 85 7C 01 60 DA FF 01 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy L, unlock D, unlock aircraft waiting, and 1 * 1 02 0D A5 81 7C 01 08 0F 01 A4 00 00 03 A5 00 // there are 3 or fewer aircraft in the holding pattern, 1 * 1 02 0D A5 81 7C 01 00 01 01 A4 00 00 00 A5 00 // else if Rwy L is available, and 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 0A 80 // set movement state to taxi (07) and target to node 0A. 1 * 1 02 0D A4 85 7C 01 60 D9 FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, unlock D, unlock aircraft waiting and vv +RC vv+C 1 * 1 02 0D 03 81 7C 01 00 12 02 A4 00 00 00 B4 02 02 A5 00 // taxi to takeoff: if Rwy R and C is available, 1 * 1 02 0D 0D 81 11 00 FF 02 01 00 01 02 03 00 03 03 05 88 // plan is hangar? plan is takeoff? // node 0C ========== Bay 0C // Aircraft from bay 0C will taxi to either runway to take off, // although they will prefer Rwy R if it's available, and will // not use Rwy L if there is more than 1 aircraft waiting to land. 1 * 1 02 0D A5 85 7C 01 60 F7 FF 08 00 \w1 \2sto 1A 00 \w1 01 03 82 00 00 00 00 03 82 // else set waiting at C, turn to heading 3 and wait 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 0A 80 // set movement state to taxi (07) and target to node 0A. 1 * 1 02 0D A4 85 7C 01 60 E5 FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, unlock C, unlock aircraft waiting and 1 * 1 02 0D 01 81 7C 01 01 01 01 A4 00 00 00 A5 00 // taxi to hangar: if Rwy R is available, 1 * 1 02 0D A5 85 7C 01 60 F7 FF 08 00 \w1 \2sto 1A 00 \w1 01 05 82 00 00 00 00 05 82 // else set waiting at C, turn to heading 5 and wait. 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 08 80 // set movement state to taxi (07) and target to node 08. 1 * 1 02 0D A4 85 7C 01 60 E6 FF 01 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy L, unlock C, unlock aircraft waiting, and 1 * 1 02 0D A5 81 7C 01 08 0F 01 A4 00 00 01 A5 00 // there are 1 or fewer aircraft in the holding pattern, 1 * 1 02 0D A5 81 7C 01 00 21 01 A4 00 00 00 A5 00 // else if D and Rwy L are available, and 1 * 1 02 0D A4 81 11 00 F0 01 07 81 00 00 0A 80 // set movement state to taxi (07) and target to node 0A. 1 * 1 02 0D A4 85 7C 01 60 E5 FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, unlock C, unlock aircraft waiting and 1 * 1 02 0D 03 81 7C 01 01 01 01 A4 00 00 00 A5 00 // taxi to takeoff: if Rwy R is available, 1 * 1 02 0D 0C 81 11 00 FF 02 01 00 01 02 03 00 03 03 05 88 // plan is hangar? plan is takeoff? // end bay nodes ======================================== // runway nodes ========================================= // node 0B ========== Hangar Junction Rwy R // Aircraft which have landed on Rwy R but cannot find an available // bay will be sent to the depot from this node. As well as being // the connection to the hangar, this node serves as the loading and // unloading point for airships. // airship 1 * 1 02 0D 01 85 7C 01 60 FD FF 10 00 \w1 \2sto 1A 00 \w1 01 01 00 00 00 00 00 01 00 // unlock Rwy R 1 * 1 02 0D 03 81 11 00 F0 01 17 81 00 00 12 80 // set movement state to htakeoff (17) and target to node 11 1 * 1 02 0D 03 85 7C 01 60 FD FF 10 00 \w1 \2sto 1A 00 \w1 01 03 00 00 00 00 00 03 00 // unlock Rwy R 1 * 1 02 0D 1B 81 11 00 FF 02 00 83 01 02 03 00 03 03 02 88 // taxiing: plan is hangar? (disallow) plan is takeoff? Else, load right here! // non-airship 1 * 1 02 0D 01 85 7C 01 60 FD 7F 10 00 \w1 \2sto 1A 00 \w1 01 10 80 00 00 00 00 10 80 // taxiing into hangar: unlock Rwy R, lock hangar approach, head for node 10 1 * 1 02 0D 07 81 11 00 F0 01 07 81 00 00 09 80 // set movement state to taxi (07) and target to node 09. 1 * 1 02 0D 8F 85 7C 01 60 4F DF 80 00 \w1 \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // taxiing to E: lock 0E, set H->E // vv E+ vvB+ 1 * 1 02 0D 07 81 7C 01 00 40 01 8F 00 00 00 01 00 // taxiing: check availability of node 0E, else wait in hangar vv C+ vv E+ 1 * 1 02 0D 07 81 7C 01 08 30 02 0A 80 10 10 8F 00 20 30 09 80 // taxiing: we are H->C or H->E? Else, 1 * 1 02 0D 0B 81 11 00 FF 02 01 00 01 02 09 80 03 03 07 00 // taxiing: plan is hangar? plan is takeoff? 1 * 1 02 0D 0B 82 42 10 10 01 1B 00 10 10 0B 00 // airship? // node 0A ========== end Rwy R 1 * 1 02 0D 07 81 11 00 F0 01 07 81 00 00 09 80 // set movement state to taxi (07) and target to node 09. 1 * 1 02 0D 8F 85 7C 01 60 4F FF 80 00 \w1 \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // taxiing to E: lock 0E 1 * 1 02 0D 07 81 11 00 F0 01 07 81 00 00 0C 80 // set movement state to taxi (07) and target to node 0C. 1 * 1 02 0D 8D 85 7C 01 60 ED EF 10 00 \w1 \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // taxiing to C: unlock Rwy R, clear hangar->c, lock 0C // helo: 1 * 1 02 0D A7 81 11 00 F0 01 17 81 00 00 13 80 // set movement state to htakeoff (17) and target to node 13. 1 * 1 02 0D A7 85 7C 01 20 FD FF \2sto 1A 00 \w1 01 A7 00 00 00 00 00 A7 00 // taking off: unlock Rwy R, // vvC+ vv wait 1 * 1 02 0D B7 81 7C 01 00 10 01 8D 00 00 00 03 82 // taxiing: check availability of node (0C) 1 * 1 02 0D B7 81 11 00 FF 01 A7 00 03 03 B7 00 // plan is takeoff? // aircraft: // vv E+C- vvC+ vvB+ 1 * 1 02 0D 07 81 7C 01 00 50 02 8F 00 10 10 8D 00 40 50 0B 80 // taxiing: check availability of nodes (0C) and (0E), else go to (0B) 1 * 1 02 0D 07 81 11 00 FF 01 09 80 03 03 07 00 // taxiing: plan is takeoff? target to node 9. 1 * 1 02 0D A7 81 11 00 F0 01 07 81 00 00 07 82 // rollout: change mode to taxi, turn to heading 07 1 * 1 02 0D A8 81 11 00 F0 01 0F 81 00 00 13 80 // set movement state to climb (0F) and target to node 13. 1 * 1 02 0D A8 85 7C 01 20 FD FF \2sto 1A 00 \w1 01 A8 00 00 00 00 00 A8 00 // taking off: unlock Rwy R, 1 * 1 02 0D 07 82 E2 00 FF 02 A7 00 16 16 A8 00 0D 0D 07 00 // check movementstate (rollout 16 or taking off 0D or taxiing), and 1 * 1 02 0D 0A 82 81 00 FF 01 B7 00 00 00 07 00 // aircraft or helicopter? 1 * 1 02 0D 0A 81 7C 01 08 10 01 8D 00 10 10 0A 00 // taxiing: are we H->C? // node 09 ========== threshold Rwy R // helo: 1 * 1 02 0D 07 81 11 00 F0 01 17 81 00 00 13 80 // set movement state to htakeoff (17) and target to node 13. 1 * 1 02 0D A7 85 7C 01 20 FD FF \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // taking off: unlock Rwy R, 1 * 1 02 0D B7 81 11 00 F0 01 07 81 00 00 0A 80 // set movement state to taxi (07) and target to node 0A. 1 * 1 02 0D 07 81 11 00 F0 01 07 81 00 00 0E 80 // set movement state to taxi (07) and target to node 0E. 1 * 1 02 0D 07 85 7C 01 60 BD FF 40 00 \w1 \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // lock Bay E, unlock Rwy R, 1 * 1 02 0D B7 81 7C 01 06 01 01 07 00 00 00 B7 00 // if Bay E is available, 1 * 1 02 0D B7 81 11 00 FF 02 A7 00 03 03 0B 80 01 02 B7 00 // plan is takeoff? hangar (taxi to 0B if so)? // aircraft: 1 * 1 02 0D 07 81 11 00 F0 01 07 81 00 00 0F 80 // set movement state to taxi (07) and target to node 0E. 1 * 1 02 0D 8D 85 7C 01 20 FD DF \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // taxiing: unlock Rwy R, clear hangar->e 1 * 1 02 0D A7 81 11 00 F0 01 0D 81 00 00 0A 80 // set movement state to takeoff (0D) and target to node 0A. 1 * 1 02 0D 07 81 11 00 FF 02 A7 00 03 03 0B 80 01 02 8D 00 // plan is takeoff? hangar (taxi to 0B if so)? 1 * 1 02 0D A7 81 11 00 F0 02 16 81 00 00 <sfx> 8A 10 10 0A 80 // landing: rollout (16), play landing sound, set target to node 0A 1 * 1 02 0D 07 82 E2 00 FF 01 A7 00 15 15 07 00 // check movementstate (landing 15 or taxiing), and 1 * 1 02 0D 09 82 81 00 FF 01 B7 00 00 00 07 00 // aircraft or helicopter? 1 * 1 02 0D 09 81 7C 01 08 20 01 8D 00 20 20 09 00 // taxiing: are we H->E // node 08 ========== end Rwy L 1 * 1 02 0D 07 81 11 00 F0 01 07 81 00 00 07 80 // set movement state to taxi (07) and target to node 07. 1 * 1 02 0D 8F 85 7C 01 60 7F FF 80 00 \w1 \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // taxiing to F: lock 0F 1 * 1 02 0D 07 81 11 00 F0 01 07 81 00 00 0D 80 // set movement state to taxi (07) and target to node 0D. 1 * 1 02 0D 8D 85 7C 01 60 DE FF 20 00 \w1 \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // taxiing to D: unlock Rwy L, lock 0D // helo: 1 * 1 02 0D A7 81 11 00 F0 01 17 81 00 00 12 80 // set movement state to htakeoff (17) and target to node 12. 1 * 1 02 0D A7 85 7C 01 20 FE FF \2sto 1A 00 \w1 01 A7 00 00 00 00 00 A7 00 // taking off: unlock Rwy L, // vvD+ vv wait 1 * 1 02 0D B7 81 7C 01 00 20 01 8D 00 00 00 03 82 // taxiing: check availability of node (0D) 1 * 1 02 0D B7 81 11 00 FF 01 A7 00 03 03 B7 00 // plan is takeoff? // aircraft: // vv F+D- vvD+ vv wait 1 * 1 02 0D 07 81 7C 01 00 A0 02 8F 00 20 20 8D 00 80 A0 03 82 // taxiing: check availability of nodes (0D) and (0F) 1 * 1 02 0D 07 81 11 00 FF 01 07 80 03 03 07 00 // taxiing: plan is takeoff? target to node 7. 1 * 1 02 0D A7 81 11 00 F0 01 07 81 00 00 03 82 // rollout: change mode to taxi, turn to heading 03 1 * 1 02 0D A8 81 11 00 F0 01 0F 81 00 00 12 80 // set movement state to climb (0F) and target to node 12. 1 * 1 02 0D A8 85 7C 01 20 FE FF \2sto 1A 00 \w1 01 A8 00 00 00 00 00 A8 00 // taking off: unlock Rwy L, 1 * 1 02 0D 07 82 E2 00 FF 02 A7 00 16 16 A8 00 0D 0D 07 00 // check movementstate (rollout 16 or taking off 0D or taxiing), and 1 * 1 02 0D 08 82 81 00 FF 01 B7 00 00 00 07 00 // aircraft or helicopter? 1 * 1 02 0D 08 81 7C 01 0E 01 01 08 00 00 00 07 80 // if D->F, target to node 7. // node 07 ========== threshold Rwy L // helo: 1 * 1 02 0D A7 81 11 00 F0 01 17 81 00 00 11 80 // set movement state to htakeoff (17) and target to node 11. 1 * 1 02 0D A7 85 7C 01 20 FE FF \2sto 1A 00 01 \w1 A7 00 00 00 A7 00 // taking off: unlock Rwy L, 1 * 1 02 0D B7 81 11 00 F0 01 07 81 00 00 08 80 // set movement state to taxi (07) and target to node 08. 1 * 1 02 0D 07 81 11 00 F0 01 07 81 00 00 0F 80 // set movement state to taxi (07) and target to node 0F. 1 * 1 02 0D 07 85 7C 01 60 7E FF 80 00 \w1 \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // lock Bay F, unlock Rwy L, 1 * 1 02 0D B7 81 7C 01 07 01 01 07 00 00 00 B7 00 // if Bay F is available, 1 * 1 02 0D B7 81 11 00 FF 01 A7 00 03 03 B7 00 // plan is takeoff? // aircraft: 1 * 1 02 0D 07 81 11 00 F0 01 07 81 00 00 0F 80 // set movement state to taxi (07) and target to node 0F. 1 * 1 02 0D 07 85 7C 01 20 FE BF \2sto 1A 00 \w1 01 07 00 00 00 00 00 07 00 // taxiing: unlock Rwy L, cancel D->F, 1 * 1 02 0D A7 81 11 00 F0 01 0D 81 00 00 08 80 // set movement state to takeoff (0D) and target to node 8. 1 * 1 02 0D 07 81 11 00 FF 01 A7 00 03 03 07 00 // plan is takeoff? 1 * 1 02 0D A7 81 11 00 F0 02 16 81 00 00 <sfx> 8A 10 10 08 80 // landing: rollout (16), play landing sound, set target to node 08 1 * 1 02 0D 07 82 E2 00 FF 01 A7 00 15 15 07 00 // check movementstate (landing 15 or taxiing), and 1 * 1 02 0D 07 82 81 00 FF 01 B7 00 00 00 07 00 // aircraft or helicopter? // end runway nodes ===================================== // approach nodes ======================================= // node 04 ========== final turn Rwy R // aircraft which can't make Rwy R either will be sent around back to node 06. Airships will be targeted from here to the center of Rwy R (node 0B). 1 * 1 02 0D A4 81 11 00 F0 01 15 81 00 00 0B 80 // set state to landing (15) and set target to 0B for airship 1 * 1 02 0D 04 81 11 00 F0 01 15 81 00 00 09 80 // set state to landing (15) and set target to 09, or 1 * 1 02 0D A4 82 42 10 10 01 A4 00 10 10 04 00 // check if airship, and 1 * 1 02 0D 04 85 7C 01 20 FF FF \2- 1A 20 00 \b1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // -1 to the circuit count 1 * 1 02 0A A4 85 7C 01 00 00 0F 01 A4 00 00 00 00 00 04 00 // if circuit count > 0, 1 * 1 02 0D A4 85 7C 01 60 FD FF 02 00 \w1 \2sto 1A 00 \w1 01 A4 00 00 00 00 00 A4 00 // lock Rwy R, and 1 * 1 02 0D 04 81 7C 01 01 01 01 A4 00 00 00 06 80 // if Rwy R is available, // node 03 ========== final turn Rwy L // this is where decisions happen. Firstly, checks are done to see if this aircraft is an // airship (in which case it will have to head for Rwy R) or if it is a large aircraft (in // which case it cannot land at all, and will be skipped on to its next order). All other // aircraft will land on Rwy L if available, or will either go around to node 06 or head for // node 04 and Rwy R, depending on the state of aircraft on the ground and the count of // aircraft in the circuit. // -- runway is too short 1 * 1 02 0D A3 81 11 00 F0 01 <runway too short to land> 8D 00 00 13 80 // throw error and set target to 13 1 * 1 02 0D 03 85 7C 01 20 FF FF \2- 1A 20 00 \b1 \2sto 1A 00 \w1 01 A3 00 00 00 00 00 A3 00 // -1 to the circuit count 1 * 1 02 0A A3 85 7C 01 00 00 0F 01 A3 00 00 00 00 00 03 00 // if circuit count > 0, // -- 1 * 1 02 0D 03 81 7C 01 03 01 01 04 80 00 00 06 80 // if there are no aircraft waiting at C or E, try our luck at node 4, otherwise, go around to node 6 1 * 1 02 0D 03 81 7C 01 08 0F 01 04 80 04 0F 03 00 // if there are four or more planes in the holding pattern, or 1 * 1 02 0D A3 81 11 00 F0 01 15 81 00 00 07 80 // set state to landing (15) and set target to 07 1 * 1 02 0D 03 85 7C 01 20 FF FF \2- 1A 20 00 \b1 \2sto 1A 00 \w1 01 A3 00 00 00 00 00 A3 00 // -1 to the circuit count 1 * 1 02 0A A3 85 7C 01 00 00 0F 01 A3 00 00 00 00 00 03 00 // if circuit count > 0, 1 * 1 02 0D A3 85 7C 01 60 FE FF 01 00 \w1 \2sto 1A 00 \w1 01 A3 00 00 00 00 00 A3 00 // lock Rwy L, and 1 * 1 02 0D 03 81 7C 01 00 01 01 A3 00 00 00 03 00 // if Rwy L is available, 1 * 1 02 0D A3 82 42 10 10 01 B3 00 10 10 03 00 // no runway req, check if "large", else you land at your own risk! 1 * 1 02 0D 03 82 42 10 0F 02 A3 00 00 00 03 00 01 04 B3 00 // runway length check before landing 1 * 1 02 0D A3 82 42 10 10 01 04 80 10 10 03 00 // head for node 4 if an airship 1 * 1 02 0D 03 82 81 00 FF 01 A3 00 00 00 03 00 // helicopter? // node 02 ========== base leg holding pattern // this is the point where aircraft change state to (10) and slow down for the holding pattern. // if the aircraft has just arrived (which we can tell by checking if it's state is already (10), // we add + to the aircraft hold counter - this counter will be used to help try and streamline // aircraft movements. 1 * 1 02 0D 02 81 11 00 F0 01 10 81 00 00 03 80 // set state to holding pattern (10) and target to node 03 1 * 1 02 0D A2 85 7C 01 20 FF FF \2+ 1A 20 00 \b1 \2sto 1A 00 \w1 01 02 00 00 00 00 00 02 00 // +1 to the circuit count 1 * 1 02 0A A2 85 7C 01 00 00 0F 01 A2 00 00 00 00 0E 02 00 // if circuit count < E, then 1 * 1 02 0D 02 82 E2 00 FF 01 02 00 10 10 A2 00 // if the aircraft is not already holding (E2 movementstate = 10), and // end approach nodes =================================== 1 * 1 02 0D AA 81 10 00 FF 12 // which node is triggered? 00 00 01 80 // node 00 = north contact point, head for node 01 01 00 02 80 // node 01 = downwind leg holding pattern, head for node 02 02 00 02 02 03 00 03 03 04 00 04 04 05 00 01 80 // node 05 = east contact point, head for node 01 06 00 01 80 // node 06 = crosswind leg holding pattern, head for node 01 07 00 07 07 08 00 08 08 09 00 09 09 0A 00 0A 0A 0B 00 0B 0B 0C 00 0C 0C 0D 00 0D 0D 0E 00 0E 0E 0F 00 0F 0F 10 00 10 10 11 00 11 11 00 8F // leave the state machine and fly to next destination 1 * 1 02 0D AA 85 0C 00 FF FF 01 AA 00 <callback #> FF 00 // statemachine callback // end state machine callback ============================================================================ 1 * 1 03 0D 01 04 01 FF FF 00 AA 00
Test grf: Av8ports testing