Howto:Adding Bombable to FlightGear Aircraft
Bombable |
---|
a FlightGear addon |
|
Related |
How to make a FlightGear aircraft work with Bombable.
When you follow these instructions, you will add the following properties to your aircraft:
- AI aircraft can fly, maneuver, dodge, and attack the main aircraft. They can avoid the ground (aircraft) or stay on the ground (ships, vehicles) while maneuvering.
- AI and MP aircraft can be damaged by the main aircraft and will stop functioning, crash, catch fire, explode, etc., appropriately when hit by weapons or bombs. MP aircraft will report damage back over MP to the main aircraft, making multiplayer dogfights possible.
- MP aircraft will display weapons shooting whenever the remote MP aircraft is shooting, and report damage back to the main aircraft if the remote MP aircraft shoots or damages your aircraft.
- AI and MP aircraft can have smoke, contrails, and damaged engine smoke
- AI aircraft can automatically follow the main aircraft and attack it with weapons, which will be visible.
- You can design and customize the features per aircraft--to make, for instance, a maneuverable twisty dogfighter, light and easily damaged, or a fast, heavily armored energy fighter with lower maneuverability.
To make FlightGear aircraft work with Bombable--as the main aircraft, an AI aircraft, and via Multiplayer (MP)--you need three things:
- Weapons submodels that report impacts properly
- A snippet of code added to the aircraft's -set.xml file to allow communication of Bombable information over Multiplayer
- A section of code in the load/unload section of the Aircraft's XML files that allow Bombable to initialize and give it information about the aircraft needed to operate as an AI or Multiplayer model
There are several decisions you will have to make about where to put your file and what to name it (see "Where your aircraft files are" below for more info).
For our example, we'll mod the F-15E model from FGUK to become Bombable. We'll assume:
- You have Bombable installed already
- You have the aircraft installed in FGDATA/aircraft/F-15E
- We will add the files/mods needed for AI aircraft to the FGDATA/aircraft/F-15E directories (rather than creating a new, separate FGDATA/AI/Aircraft version of the F-15E)
- We're just going to mod the existing F-15E directories and aircraft without changing and aircraft or file names (rather than creating a separate, new, differently named F-15E-Bombable aircraft)
Preliminaries
Helpful/Needed files
- Bombable download
- F-15E model with the mods as described in this article (finished and working version, though still un-polished, as described below, but with several updates and fixes beyond those mentioned in the article)
- Note that this zip file includes an AI directory with two AI scenarios you can use to fly against the F-15E AI aircraft. You can also use these two scenarios with the current F-15E model linked just below.
- Current F-15E model from FGUK - which now includes the Bombable mods as well as a large number of tweaks and updates to the base F-15E model that have been added since 2011.
Note: The original FGUK F-15E, without the Bombable mods, is no longer available.
The mods described below were added to the base FGUK F-15E aircraft in about 2011. Since then, FGUK has incorporated the Bombable mods in the F-15E aircraft and then continued to make further enhancements to the F-15E since that time.
So, unfortunately, you will not be able to download the original F-15E files and then follow the steps below to make your own modded F-15E version.
Still, you can:
- Download the F-15E model with the mods as described in this article (2011) to see the end result of the mods, and then read the steps below to see what changes were made to arrive at the Bombable-compatible mod.
- Download the current F-15E model from FGUK, which also include the Bombable mods, and see how the mods look in a somewhat more current/updated aircraft model.
Either way, by looking at either of those aircraft and following the instructions below, you should be able to get good idea about how the original files were modded to become compatible with Bombable.
Here is the step-by-step guide to modding the F-15E to become Bombable-compatible:
Step 1: Check the weapons models for impact reporting
Most FG aircraft that have weapons already work with Bombable at a basic level, right out of the box. That is because FG has a way for aircraft weapons to report their impacts, and most FG aircraft with weapons already use the impact reporting system.
First, find the XML file that defines the weapons submodels. Typically this is in the aircraft's Models directory (or a subdirectory). It may be named submodels.xml, or F-15-submodels.xml, or guns.xml, or something similar.
When you open the correct file (FGDATA\Aircraft\F-15E\Models\Effects\guns\submodels.xml, in this case), it will look something like this:
<PropertyList> <submodel> <name>left</name> <model>Aircraft/F-15E/Models/Effects/guns/apibullet-tracer.xml</model> <trigger>controls/armament/trigger</trigger> <speed>2460.0</speed> <repeat>true</repeat> . . .
A complete description of these files is here.
For each <submodel></submodel> section, the areas of interest are the <name> and the <collision> and <impact> areas.
Submodel name
For the submodel name, in FG 2.4.0 we are working around a little FG bug, and Bombable identifies munitions and weapons by their name.
So it is very important that the name of each weapons submodel include one of the following keywords:
gun, tracer, bullet, round, cannon, bomb, heavy-bomb, rocket, missile, MK-81, MK-82, MK-83, MK-84, 5 pound, 25 pound, 100 pound, 150 pound, 250 pound, 500 pound, 1000 pound, 2000 pound
The name simply needs to include the appropriate keyword in some way--so if you have another name you prefer, just include the keyword at the end, like "MKFD Special Munition (250 pound)".
In this case, it is a 20 mm gatling gun, so more into cannon range, with projectiles weighing in at about .25 lb. So we simply add "cannon" to each of the submodel names:
<submodel> <name>left cannon</name>
<submodel> <name>right cannon</name>
Collision and impact reporting
The collision and impact areas of this file look like this:
<collision>true</collision> <collision-report>sim/ai/aircraft/collision/gun</collision-report> <impact>true</impact> <impact-report>sim/ai/aircraft/impact/bullet</impact-report>
[IMPORTANT!] Both <collision> and <impact> should be set to true.
[IMPORTANT!] <impact-report> should be one of these--the first one is the default, but any is fine:
ai/models/model-impact sim/armament/weapons/impact sim/ai/aircraft/impact/bullet sim/ai/aircraft/impact/gun sim/ai/aircraft/impact/cannon sim/ai/aircraft/impact/bomb
According to the FG documentation, the <collision-report> setting is no longer used, so you can safely delete it (though it does no harm to leave it be).
For the F-15E, this section of each <submodel> looks fine, so we just leave it alone.
We save the file with the changes to the <name> sections.
STEP 2: Adding code needed for MultiPlayer to the -set.xml file
In the aircraft's -set.XML file, we need to add a <multiplay> section in the <PropertyList><sim> section.
This gets a bit confusing for two reasons:
- -set.xml files may (or may not!) load other files, so the <sim> section where we need to add our code may be in the -set.xml file OR in one of the other .xml files the -set.xml file loads
- There may be existing code in <sim><multiplayer> and so we can simply add our code to that rather than creating a new/different <multiplayer> section.
In the case of the F-15E, we open FGDATA\Aircraft\F-15E\F-15E_StrikeEagle-set.xml and find:
<?xml version="1.0"?> <PropertyList> <sim> <description>F-15E_Strike_Eagle</description> <author>Flying Toaster 3DM, StuartC</author> <status>Alpha 2.01</status> . . .
Find out more about the -set.xml file here.
The <sim> section is what we are looking for.
We search for <multiplayer> and don't find any existing <multiplayer> section. So we can add our needed <multiplayer> section in any convenient place. Let's place it between the <submodels> and <panel> sections. The added code is in between those two:
<submodels> <serviceable type="bool">true</serviceable> <path>Aircraft/F-15E/Models/Effects/guns/submodels.xml</path> <path>Aircraft/F-15E/Models/weapons/loads.xml</path> </submodels> <multiplay> <generic> <string n="9" type="string"/> <int n="10" alias="controls/armament/trigger" /> </generic> </multiplay> <panel> <visibility archive="y">false</visibility> </panel>
You'll notice we have customized one line: <int n="10" alias="controls/armament/trigger" />
The alias, controls/armament/trigger, refers to the submodel <trigger> which we observed in Step 1.
If the aircraft has more than one trigger (for more than one weapon, for example), we can make several triggers like this:
<int n="10" alias="controls/armament/trigger" /> <int n="11" alias="controls/armament/trigger1" /> <int n="12" alias="controls/armament/trigger2" /> <int n="13" alias="controls/armament/trigger3" /> <int n="14" alias="controls/armament/trigger4" />
Each alias should correspond to a different <trigger> property in the submodel.xml definitions.
Save the -set.xml file with the changes.
STEP 3: Add the Bombable Nasal code to the Model XML file
Bombable needs to have certain code run when the AI or MP aircraft initializes. The code is in Nasal, FlightGear's scripting language. The code gives Bombable needed information about the aircraft (dimensions, vulnerabilities, weapons, etc) and also the code tells Bombable which systems to initialize for this aircraft.
The simplest way to create this code is to start with a similar aircraft in the Bombable download, then copy and mod the Bombable code as needed.
There are two steps in this process:
- Create the -bombableinclude.xml file
- Link the -bombableinclude.xml file to the aircraft's existing model XML file
Create the -bombableinclude.xml file
In the Bombable distribution, the include files are named [aircraftname]-bombableinclude.xml and are generally found in FGDATA/AI/Aircraft/[aircraftname]/Models.
In this case, the most similar aircraft in the Bombable distribution is the A-10. If Bombable is installed, the needed file is in:
FGDATA\AI\Aircraft\A-10-Bombable\Models\A-10-bombableinclude.xml
Open the file with a text editor and save it with a new name in your F-15E directory. The new name & directory should be something like:
FGDATA\Aircraft\F-15E\Models\F-15E_StrikeEagle-bombableinclude.xml
Now you can open and edit this file. Most changes are quite obvious--change the name, change the dimensions, etc.
When done, we end up with a file like this:
<?xml version="1.0"?> <PropertyList> <nasal> <load> <![CDATA[ print("Loading F-15E ", cmdarg().getPath()); var nodeName = cmdarg().getPath(); ##checks whether it has been initialized already; if so, just return if ( bombable.check_overall_initialized (nodeName) ) return; ############################################ #FUNCTION object_init, INITIALIZER var object_init = func() { # Datas of this object are under: cmdarg().getPath() var thisNodeName = cmdarg().getPath(); var thisNode = props.globals.getNode(thisNodeName); # Add some useful nodes ######################################################################## ######################################################################## # INITIALIZE BOMBABLE # # Initialize constants and main routines for maintaining altitude # relative to ground-level, relocating after file/reset, and # creating bombable/shootable objects. # # These routines are found in FG/nasal/bombable.nas # ######################################################################## # INITIALIZE BOMBABLE Object # This object will be slurped in the object's node as a child # node named "bombable". # All distances are specified in meters. # All altitudes are relative to current ground level at the object's # location # thisNodeName = cmdarg().getPath(); var bombableObject = { objectNodeName : thisNodeName, objectNode : props.globals.getNode(thisNodeName), updateTime_s : 1/3, #time, in seconds, between the updates that #keep the object at its AGL. Tradeoff is high-speed updates look more #realistic but slow down the framerate/cause jerkiness. Faster-moving #objects will need more frequent updates to look realistic. #update time faster than about 1/3 seems to have a noticeable effect #on frame rate ######################################### # ALTITUDE DEFINITIONS # altitudes : { wheelsOnGroundAGL_m : 1 , #altitude correction to add to your aircraft or ship that is needed to put wheels on ground (or, for a ship, make it float in the water at the correct level). For most objects this is 0 but some models need a small correction to place them exactly at ground level minimumAGL_m : 300, #minimum altitude above ground level this object is allowed to fly maximumAGL_m : 50000, #maximum altitude AGL this object is allowed to fly, ie, operational ceiling crashedAGL_m : 0.6, #altitude AGL when crashed. Ships will sink to this level, aircraft or vehicles will sink into the ground as landing gear collapses or tires deflate. Should be negative, even just -0.001. }, # ######################################### # VELOCITIES DEFINITIONS # velocities : { maxSpeedReduce_percent : 0.5, #max % to reduce speed, per step, when damaged minSpeed_kt : 112, #minimum speed to reduce to when damaged. Ground vehicles and ships might stop completely when damaged but aircraft will need a minimum speed so they keep moving until they hit the ground. cruiseSpeed_kt : 550, #cruising speed, typical/optimal cruising speed, V C for aircraft attackSpeed_kt : 900, #typical/optimal speed when aggressively attacking or evading, in #level flight for aircraft maxSpeed_kt : 1400 , #Maximum possible speed under dive or downhill conditions, V NE for aircraft damagedAltitudeChangeMaxRate_meterspersecond : 30, #max rate to sink or fly downwards when damaged, in meters/second #The terminal velocities are calculated by opening the 'real' AC #in FG, level flight, full throttle, then putting #the AC at different angles of attack with the autopilot, #and noting the terminal airspeed & vertical speed velocities. #For best results, do it near sea level, under 5000 feet altitude. #One or two each of climb & dive velocities are probably sufficient. #However if you do more we may be able to use the more precise #data in the future. # #Note that these are intended to be true airspeed whereas FG's #/velocities/airspeed-kt reports indicated airspeed, so some #conversion or reference to groundspeed-kt is needed. # #In FG /velocities/groundspeed-kt is equal (or close #to equal, except for wind . . .) true airspeed when pitch=0 #but as pitch increases or decreases that will change. # diveTerminalVelocities: { point1: { airspeed_kt : 1060, vertical_speed_fps : - 337}, point2: { airspeed_kt : 1230, vertical_speed_fps : - 755}, }, climbTerminalVelocities: { point1: { airspeed_kt : 468, vertical_speed_fps : 236}, point2: { airspeed_kt : 843, vertical_speed_fps : 251}, #point3: { airspeed_kt : 1100, vertical_speed_fps : 161}, }, }, # ######################################### # EVASION DEFINITIONS # # The evasion system makes the AI aircraft dodge when they come under # fire. evasions : { dodgeDelayMax_sec : 15, #max time to delay/wait between dodges dodgeDelayMin_sec : 5, #minimum time to delay/wait between dodges dodgeMax_deg : 88, #Max amount to turn when dodging #90 degrees = instant turn, unrealistic #up to 80 is usually OK, somewhere in 80-85 starts to be unrealistically fast #>85 is usually very unrealistic. You must test this in your scenario, however. dodgeMin_deg : 83, #minimum amount to turn when dodging rollRateMax_degpersec : 300, #you can figure this out by rolling the corresponding FG aircraft and timing a 180 or 360 deg roll dodgeROverLPreference_percent : 50, # Preference for right turns vs. left when dodging. 90% means 90% right turns, 50% means 50% right turns. dodgeAltMin_m : -8000, #Aircraft will begin to move up or down dodgeAltMax_m : 8000, #Max & Min are relative to current alt dodgeVertSpeedClimb_mps : 1500, #Max speed to climb when evading dodgeVertSpeedDive_mps : 1500, #Max speed to dive when evading }, # ######################################### # ATTACK DEFINITIONS # # The attack system makes the AI aircraft turn and fly towards # other aircraft attacks : { maxDistance_m : 30000, #max distance to turn & attack main aircraft minDistance_m : 4000, #min distance to turn & attack main aircraft, ie, fly away this far before turning to attack again continueAttackAngle_deg : 80, #when within minDistance_m, the aircraft will continue to turn towards the main aircraft and attack *if* if the angle is less than this amount from dead ahead altitudeHigherCutoff_m : 30000, # will attack the main aircraft unless this amount higher than it or more altitudeLowerCutoff_m : 30000, # will attack the main aircraft unless this amount lower than it or more climbPower : 8000, # How powerful the aircraft is when climbing during an attack; 4000 would be typical for, say a Zero--scale accordingly for others; higher is stronger divePower : 10000, # How powerful the aircraft is when diving during and attack; 6000 typical of a Zero--could be much more than climbPower if the aircraft is a weak climber but a strong diver rollMin_deg : 82, #when turning on attack, roll to this angle min #for sedate, Cessna-like manuevers make rollMin low. If you want an aggressive, #attacking, aiming fighter keep it close to rollMax, or even almost equal to rollMax rollMax_deg : 87, #when turning on attack, roll to this angle max #90 degrees = instant turn, unrealistic #up to 80 might be OK, depending on aircraft & speed; somewhere in 80-85 starts to be unrealistically fast #>85 is usually very unrealistic. You must test this in your scenario, however. rollRateMax_degpersec : 120, #you can figure this out by rolling the corresponding FG aircraft and timing a 180 or 360 deg roll attackCheckTime_sec : 10, # check for need to attack/correct course this often attackCheckTimeEngaged_sec : 0.5, # once engaged with enemy, check/update course this frequently }, # ######################################### # WEAPONS DEFINITIONS # # The weapons system makes the AI aircraft fire on the main aircraft # You can define any number of weapons--just enclose each in curly brackets # and separate with commas (,). weapons : { front_gun : #internal name - this can be any name you want; must be a valid nasal variable name { name : "Machine Gun", # name presented to users, ie in on-screen messages maxDamage_percent : 5, # maximum percentage damage one hit from the aircraft's main weapon/machine guns will do to an opponent maxDamageDistance_m : 2000, # maximum distance at which the aircrafts main weapon/maching guns will be able to damage an opponent weaponAngle_deg : { heading: 0, elevation: 0 }, # direction the aircraft's main weapon is aimed. # 0,0 = straight ahead, 90,0=directly right, 0,90=directly up, 0,180=directly back, etc. weaponOffset_m : {x:2, y:0, z:0}, # Offset of the weapon from the main aircraft center weaponSize_m : {start:.1, end:.1}, # Visual size of the weapon's projectile, in meters, at start & end of its path }, sidewinder_missile : #internal name - this can be any name you want; must be a valid nasal variable name { name : "Sidewinder guided missile", # name presented to users, ie in on-screen messages maxDamage_percent : 40, # maximum percentage damage one hit from the aircraft's main weapon/machine guns will do to an opponent maxDamageDistance_m : 6000, # maximum distance at which the aircrafts main weapon/machine guns will be able to damage an opponent weaponAngle_deg : { heading: 0, elevation: 0 }, # direction the aircraft's main weapon is aimed. # 0,0 = straight ahead, 90,0=directly right, 0,90=directly up, 0,180=directly back, etc. weaponOffset_m : {x:2, y:0, z:0}, # Offset of the weapon from the main aircraft center weaponSize_m : {start:1, end:1}, # Visual size of the weapon's projectile, in meters, at start & end of its path }, }, # ######################################### # DIMENSION DEFINITIONS # # All dimensions are in meters # # dimensions : { width_m : 17.53, #width of your object, ie, for aircraft, wingspan length_m : 16.26, #length of your object, ie, for aircraft, distance nose to tail height_m : 4.47, #height of your object, ie, for aircraft ground to highest point when sitting on runway damageRadius_m : 8, #typically 1/2 the longest dimension of the object. Hits within this distance of the #center of object have some possibility of damage vitalDamageRadius_m : 2, #typically the radius of the fuselage or cockpit or other most # vital area at the center of the object. Always smaller than damageRadius_m crashRadius_m : 6, #It's a crash if the main aircraft hits in this area. }, # ######################################### # VULNERABILITIES DEFINITIONS # vulnerabilities : { damageVulnerability : 9, #Vulnerability to damage from armament, 1=normal M1 tank; higher to make objects easier to kill and lower to make them more difficult. This is a multiplier, so 5 means 5X easier to kill than an M1, 1/5 means 5X harder to kill. engineDamageVulnerability_percent : 6, #Chance that a small-caliber machine-gun round will damage the engine. fireVulnerability_percent : 5, #Vulnerability to catching on fire. 100% means even the slightest impact will set it on fire; 20% means quite difficult to set on fire; 0% means set on fire only when completely damaged; -1% means never set on fire. fireDamageRate_percentpersecond : .1, #Amount of damage to add, per second, when on fire. 100%=completely damaged. Warthog is relatively damage-resistant. fireExtinguishMaxTime_seconds : 80, #Once a fire starts, for this many seconds there is a chance to put out the fire; fires lasting longer than this won't be put out until the object burns out. fireExtinguishSuccess_percentage : 45, #Chance of the crew putting out the fire within the MaxTime above. Warthoge is relatively damage-resistant. explosiveMass_kg : 27772 , #mass of the object in KG, but give at least a 2-10X bonus to anything carrying flammables or high explosives. }, # ######################################### # LIVERY DEFINITIONS # # Path to livery files to use at different damage levels. # Path is relative to the AI aircraft's directory. # The object will start with the first livery listed and # change to succeeding liveries as the damage # level increases. The final livery should indicate full damage/ # object destroyed. # # If you don't want to specify any special liveries simply set # damageLivery : nil and the object's normal livery will be used. # damageLiveries : { damageLivery : [ ] }, }; ######################################### # INITIALIZE ROUTINES # # OVERALL INITIALIZER: Needed to make all the others work bombable.initialize ( bombableObject ); # # LOCATION: Relocate object to maintain its position after file/reset # (best not used for airplanes) # bombable.location_init ( thisNodeName ); # # GROUND: Keep object at altitude relative to ground level bombable.ground_init ( thisNodeName ); # # ATTACK: Make the object attack the main aircraft bombable.attack_init ( thisNodeName ); # # WEAPONS: Make the object shoot the main aircraft bombable.weapons_init ( thisNodeName ); # # BOMBABLE: Make the object bombable/damageable bombable.bombable_init ( thisNodeName ); # # SMOKE/CONTRAIL: Start a flare, contrail, smoke trail, or exhaust # trail for the object. # Smoke types available: flare, jetcontrail, pistonexhaust, smoketrail, # damagedengine bombable.startSmoke("jetcontrail", thisNodeName ); #F-15E already has contrails, we're leaving this out # # END INITIALIZE BOMBABLE ######################################################################## ######################################################################## } object_init(); ]]> </load> <unload> <![CDATA[ print("Unload F-15E."); var nodeName= cmdarg().getPath(); bombable.de_overall_initialize( nodeName ); bombable.initialize_del( nodeName ); bombable.ground_del( nodeName ); bombable.location_del (nodeName); bombable.bombable_del( nodeName ); bombable.attack_del( nodeName ); bombable.weapons_del (nodeName); # </unload> ]]> </unload> </nasal> </PropertyList>
Save this file with the name you have chosen ( FGDATA\Aircraft\F-15E\Models\F-15E_StrikeEagle-bombableinclude.xml).
Link the -bombableinclude.xml file to the existing F-15 model file
Now that we have created the -bombableinclude.xml file, we need to set up the aircraft to load the file on startup.
AI scenarios (and MP aircraft) load the aircraft's model file. So we need to locate that file and include the new -bombableinclude.xml file in it.
Where is the model file? Look in the aircraft's -set.xml file. In that file will be a section called <model>. For the F-15E it looks like this:
<model> <path>Aircraft/F-15E/Models/F-15E_StrikeEagle.xml</path> </model>
So Aircraft/F-15E/Models/F-15E_StrikeEagle.xml is our model file.
Load Aircraft/F-15E/Models/F-15E_StrikeEagle.xml in a text editor. At the beginning of that file you will find this:
<?xml version="1.0"?> <PropertyList>
Change it to this:
<?xml version="1.0"?> <PropertyList include="F-15E_StrikeEagle-bombableinclude.xml">
Save the file.
Notes
- The statement include="F-15E_StrikeEagle-bombableinclude.xml" indicates that F-15E_StrikeEagle-bombableinclude.xml will be in the same directory as F-15E_StrikeEagle.xml. That directory is Aircraft/F-15E/Models -- so make sure that the -bombableinclude.xml file is indeed in that directory!
- Model files can have only ONE Nasal <load> section and one <unload> section. Ramifications:
If you have more than one, the second and subsequent <load>/<unload> sections are ignored.
The problem? Your aircraft may already have a <load> or <unload> section. When you add the Bombable code, one of the two <load> sections (the pre-existing one or Bombable's) will be ignored.
The solution is to combine the two <load> sections into one, and the same with the <unload> sections. You'll need to know a little about Nasal programming to do anything complicated, but as a rule you can just copy/paste whatever is in the aircraft's <load> section to the end of Bombable's <load> section, and the same with <unload>.
- One trick here is to post the existing Nasal code at the END of the section, AFTER the Bombable code - both for the <load> and <unload> sections. This is a bit of a kludge, but it allows you to use the same model file for both regular and AI aircraft. Often the existing nasal in the model file is needed only for regular/piloted aircraft and not for the AI version. Because of this, the code will thrown an error when run as an AI aircraft. If you simply place the existing Nasal code AFTER the Bombable code, the Bombable code will run (it works and is needed for both regular and AI aircraft). Then if the existing Nasal code runs as a regular aircraft, it will run fine as well. If it is an AI aircraft, it will give a runtime error and stop. But it won't hurt anything because the Bombable code has already run.
- The proper way to address this issue is to make separate model files for regular and AI aircraft. The AI aircraft can generally be stripped way down, no console and other details are needed, and much less nasal code for subsystems is needed. How to handle all of that properly is a whole topic of its own.
- You'll notice the Nasal code starts with <![CDATA[ and ends with ]]>. That is needed to make Nasal code work within XML files. CDATA usage is explained here.
STEP 4. Add to an AI Scenario
Now we can add the F-15E to an AI scenario.
Create a file named F-15E-demo.xml and save it in your FGDATA/AI directory.
Most of the entries in the scenario file are self-explanatory. For the <model> entry you'll need the path of the same model file for the F-15 that we located in Step 3--which is Aircraft/F-15E/Models/F-15E_StrikeEagle.xml.
Here is how the file should look when you are done:
<?xml version="1.0"?> <PropertyList> <scenario> <description>My new F-15E scenario. Starts at KSFO! </description> <entry> <type>aircraft</type> <callsign>Jones</callsign> <name>F15E Leader</name> <model type="string">Aircraft/F-15E/Models/F-15E_StrikeEagle.xml</model> <latitude type="double">37.608720</latitude> <longitude type="double">-122.3076</longitude> <altitude type="double">309</altitude> <speed>280.0</speed> <heading type="double">192</heading> </entry> <entry> <type>aircraft</type> <callsign>Cooper</callsign> <name>F15E Wingman</name> <model type="string">Aircraft/F-15E/Models/F-15E_StrikeEagle.xml</model> <latitude type="double">37.608200</latitude> <longitude type="double">-122.2988</longitude> <altitude type="double">309</altitude> <speed>270.0</speed> <heading type="double">192</heading> </entry> </scenario> </PropertyList>
Again, save as FGDATA/AI/F-15E-demo.xml. When you start FGRun next time, F-15E-demo will be listed as one of the scenario file options. (You may need to quit and re-start FGRun.)
If the scenario doesn't appear, check [fgfs.log] for any errors related to the scenario file. Here is a typical error message:
0.53 [WARN]:ai C:\Jenkins\workspace\Windows-release\flightgear\src\AIModel\AIManager.cxx:257: Skipping malformed scenario file:Path "e:/FlightGear 2020.3/data/AI/F-15E-demo.xml"
0.53 [WARN]:general C:\Jenkins\workspace\Windows-release\simgear\simgear\debug\ErrorReportingCallback.cxx:82: Error:bad data from sceanrio load::The scenario couldn't be loaded:mismatched tag
at e:/FlightGear 2020.3/data/AI/F-15E-demo.xml,
line 31, column 2
e:/FlightGear 2020.3/data/AI/F-15E-demo.xml,
line 31, column 2
- The path given in this line can vary: <model type="string">Aircraft/F-15E/Models/F-15E_StrikeEagle.xml</model>
- If you are placing the scenario file in the AI subdirectory and the aircraft is in AI/Aircraft/F-15E - then the above line will work as is.
- However, a common situation is to place the aircraft file in data/Aircraft/F-15E (as we described above - that is the normal place for regular/piloted aircraft, and if we are NOT making a special AI version of the aircraft, then the aircraft will ilve in data/Aircraft/F-15E or a similar place. In that case, perhaps the AI folder is in data/AI and the F-15E folder is in data/Aircraft/F-15E. In that case, we need a correct relative directory from wherever the scenario .xml file is to wherever the F-15E model file is, for example:
- <model type="string">../Aircraft/F-15E/Models/F-15E_StrikeEagle.xml</model>
- Here ".." means go to the parent directory, so "../Aircraft" means go to the parent directoy of AI, then go to the Aircraft subdirectory from there.
- Regardless of the details, the point is: In order for the scenario file to work properly, you must have a proper, complete, accurate path leading from the location of the AI scenario file to the location of the F-15E_StrikeEagle.xml file.
- More details about this below in the section Where your aircraft files are.
- <model type="string">../Aircraft/F-15E/Models/F-15E_StrikeEagle.xml</model>
STEP 5. Troubleshooting
OK, we're done. Time to fly our new aircraft in our new scenario!
Oh, yeah . . . we just followed a very complicated process with numerous steps that could go wrong. Maybe we'd better test a bit first.
Start Flightgear. Using FGRun:
1. Choose UFO bombable as the main aircraft (best for testing . . . ) 2. Airport KSFO 3. Scenario F-15-demo (which we just created--if saved correctly in the FGDATA/AI directory, it will show up in the scenario list of FGRun) 4. Click "Run" 5. Closely watch the command console as FG starts. You may pick up important errors in XML files and/or Nasal code. 6. You should see
* Bombable (ver. 4.4) loaded . . . * loading scenario "f-15-demo"
Uh-oh. There is our first error. f-15-demo.xml, line 31, column 2, I have "<scenario>" rather than "</scenario>".
I fix, save the fixed file, and re-start. Now I get:
* Bombable (ver. 4.4) loaded . . . * loading scenario "f-15-demo" * Failed to load XML: . . . F-15E-StrikeEagle-bombableinclude.xml
OK, this is typical. There is a typo or stray character on the .xml file . . . or something.
After a few minutes of trying different things, I discover I've made a typo:
- In \Aircraft\F-15E\Models\F-15E_StrikeEagle.xml is this line:
<PropertyList include="F-15E_StrikeEagle-bombableinclude.xml">
- But I've saved the file as
FGDATA/Aircraft/F-15E/F-15-StrikeEagle-bombableinclude.xml
OK, that one little "E" after F-15 made all the difference. Plus, in one place it has "-" before StrikeEagle, and in the other one it has "_". I change the filename to match what's in the -set.xml file and try again.
And finally:
* Bombable (ver. 4.4) loaded . . . * loading scenario "f-15-demo" * Loading F-15E /ai/models/aircraft * Loading F-15E /ai/models/aircraft[1] * A bunch of other Bombable messages showing the aircraft initializing (I have Bombable menu/Debug turned on, which is helpful at this stage) * A bunch of error messages showing various animations and systems not load (ahhh . . . that's why we create stripped-down versions of aircraft in the AI/Aircraft directory--a completely separate and even longer article).
I open Equipment/Maps, click "traffic", see the two aircraft "Jones" and "Cooper", track them down with the UFO, they show proper smoke trails, I shoot at them, I shoot them down. It works!
Success!
Well, except . . . are they flying realistically? Climbing, turning, diving, shooting? Are they taking damage realistically? Does it work properly under Multiplayer?
Here is where you spend hours researching real F-15s, flying against the AI models with the UFO and other aircraft, tweaking parameters in the -bombableinclude.xml file, and so on and on.
You're just getting started.
Good luck!
Testing/parsing XML files
One final tip: XML files are extremely persnickety. Just one wrong character can make an entire file fail to load.
The best/easiest way to test XML files is load them in Internet Explorer. It will parse the XML file and display any errors it finds. (If you don't have access to IE there are other XML parsers available.) This is far easier and faster than starting and re-starting FG repeatedly, and IE gives better, more informative error messages as well.
IMPORTANT POSTSCRIPT: Where your aircraft files are
An important detail in getting Bombable to work with aircraft over AI and MP is the directories you store the files in and the names you choose to use for them.
FlightGear stores aircraft and AI aircraft files in at least two different places.
In a typical FG installation, in your FGDATA folder, you will find
* FGDATA/Aircraft * FGDATA/AI/Aircraft
FGDATA/Aircraft holds files for the main aircraft whereas FGDATA/AI/Aircraft holds files for AI and MP aircraft.
AI/MP aircraft don't have all the features of main aircraft, so you might find the very same aircraft in FGDATA/Aircraft and in FGDATA/AI/Aircraft--but the one in FGDATA/AI/Aircraft will be very stripped down, fewer files, smaller, and less complex.
When building a FlightGear AI scenario, you can specify the exact path and filename of the file FlightGear looks for. You can specify a file in the FGDATA/Aircraft directory, or in the FGDATA/AI/Aircraft, or really anywhere within the FGDATA directory that you like. Examples:
<model type="string">AI/Aircraft/sopwithCamel-Bombable/Models/sopwithCamel-model.xml</model>
OR
<model type="string">Aircraft/sopwithCamel-Bombable/Models/sopwithCamel-model.xml</model>
When loading an MP aircraft, FlightGear first looks for the (typically smaller/simpler) aircraft file in FGDATA/AI/Aircraft.
If it doesn't find the aircraft there, it then searches FGDATA/Aircraft.
How FG matches Multiplayer Aircraft with your local AI aircraft models
As of version 2.4.0, when FG is looking for the local AI aircraft model to display for a remote aircraft over Multiplayer, FG searches first the AI Aircraft directories, then the Aircraft directories.
It searches for a match by looking for the file with a name exactly matching the MP aircraft's model (this is typically in the aircraft's Models subdirectory and ends with .ac, though this may vary) and if that fails, FG looks for a matching -set.xml file.
The important points for making AI models that will work over MP with Bombable:
- Make sure the main aircraft and the AI version of the aircraft have the exact same names for the aircraft's model file and the aircraft's -set.xml
- If you're modding an existing but non-bombable-compatible aircraft, you need to decide whether you're going to leave all the directories, model XML file names, and -set.xml file names the same as the standard flightgear aircraft (leading to possible frustration as your version overwrites existing aircraft files on users hard drivers) OR rename the aircraft's directory, -set.xml file name, and model file name (which means you're going to have to do a bit of work on the aircraft's XML files to make sure everything still works with all those name changes.
- You can create a separate, stripped down AI version of the aircraft in the FGDATA/AI/Aircraft directory and add the Bombable additions to it (more work for you but smaller/quicker download and easier on the memory and framerate in FG) OR you can simply add all the Bombable additions to the main aircraft directory in FGDATA/Aircraft.
Bombable will work with any of those options--so it is really up to you.
EXTRA: Making livery change with damage
Once you have Bombable working with your aircraft there is a bonus: bombable.nas will handle setting the livery colors and automatically changing them as the object becomes damaged.
For an example of how this works and looks, take a look at the Bombable scenarios involving the M1 tank and the Jeep.
For this to work your model must have different liveries available and then animate the liveries so that the texture used is the one shown in this path: /ai/model/model[X]/bombable/texture-corps-path. The /ai/model/model[X]/ part is assumed for AI craft so you need to add <texture-prop>bombable/texture-corps-path</texture-prop> in the right place of your XML file.
Example from Jeep.xml in the jeep-bombable directory:
<animation> <type>material</type> <object-name>jeep-body</object-name> <object-name>roof1</object-name> <object-name>roof2</object-name> <object-name>softroof</object-name> <object-name>chassis</object-name> <object-name>chassis.002</object-name> <object-name>Plane</object-name> <object-name>hinge</object-name> <object-name>screen</object-name> <object-name>wiper.L</object-name> <object-name>wiper.R</object-name> <object-name>seat.L</object-name> <object-name>seat.R</object-name> <texture-prop>bombable/texture-corps-path</texture-prop> <transparency> <alpha>1.0</alpha> </transparency> </animation>
Additionally, if you want to change your object's the livery color programmatically (for instance, if you include a menu item to select different liveries) you can use the following code in the -bombableinclude.xml file (see above) to change all liveries, including damage liveries, that the object uses:
Example:
liveries = [ "Models/livery_nodamage.png", "Models/livery_slightdamage.png", "Models/livery_highdamage.png"); ]; bombable.set_livery (cmdarg().getPath(), liveries);
You can include liveries for as many different levels of damage (ie, fine gradations of change from undamaged to completely damaged) as you like. For instance:
Example:
liveries = [ "Models/livery_nodamage.png", "Models/livery_barelydamaged.png", "Models/livery_justslightlydamaged.png", "Models/livery_alittlemoredamage.png", "Models/livery_fairlydamaged.png", "Models/livery_kindadamaged.png", "Models/livery_prettydamaged.png", "Models/livery_whoawereintroublenow.png", "Models/livery_finishedoff.png"); ]; bombable.set_livery (cmdarg().getPath(), liveries);