1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-05-28 14:19:19 +03:00

Add 3.1 ships and modules

This commit is contained in:
Jonathan Harris 2018-07-08 01:04:04 +01:00
parent 9947e9a919
commit 9ced79f077
7 changed files with 5895 additions and 7432 deletions

View File

@ -62,6 +62,7 @@ ship_map = {
'hauler' : 'Hauler',
'independant_trader' : 'Keelback',
'independent_fighter' : 'Taipan Fighter',
'krait_mkii' : 'Krait MkII',
'orca' : 'Orca',
'python' : 'Python',
'scout' : 'Taipan Fighter',
@ -72,6 +73,7 @@ ship_map = {
'type9' : 'Type-9 Heavy',
'type9_military' : 'Type-10 Defender',
'typex' : 'Alliance Chieftain',
'typex_3' : 'Alliance Challenger',
'viper' : 'Viper MkIII',
'viper_mkiv' : 'Viper MkIV',
'vulture' : 'Vulture',

@ -1 +1 @@
Subproject commit 44d57f26a8099cfa8d91815f453c7bba303a63ec
Subproject commit 35473b30d391975dc4a00e0ab2dc0e8611cce268

View File

@ -16,32 +16,6 @@ import companion
if __name__ == "__main__":
data = json.load(open('coriolis-data/dist/index.json'))
bulkheads = outfitting.armour_map.values()
# Modules that have a name as well as a group
fixup_map = {}
fixup_map.update({ x[0] : ('Scanner', x[0]) for x in outfitting.misc_internal_map.values() })
fixup_map.update({ x[0] : ('Countermeasure', x[0]) for x in outfitting.countermeasure_map.values() })
fixup_map.update({
'Advanced Plasma Accelerator' : ('Plasma Accelerator', 'Advanced Plasma Accelerator'),
'Corrosion Resistant Cargo Rack': ('Cargo Rack', 'Corrosion Resistant'),
'Cytoscrambler Burst Laser' : ('Burst Laser', 'Cytoscrambler'),
'Enforcer Cannon' : ('Multi-cannon', 'Enforcer'),
'Enhanced Performance Thrusters': ('Thrusters', 'Enhanced Performance'),
'Imperial Hammer Rail Gun' : ('Rail Gun', 'Imperial Hammer'),
'Luxury Class Passenger Cabin' : ('Luxury Passenger Cabin', None),
'Mining Lance Beam Laser' : ('Mining Laser', 'Mining Lance'),
'Multi-Cannon' : ('Multi-cannon', None),
'Pacifier Frag-Cannon' : ('Fragment Cannon', 'Pacifier'),
'Pack-Hound Missile Rack' : ('Missile Rack', 'Pack-Hound'),
'Pulse Disruptor Laser' : ('Pulse Laser', 'Disruptor'),
'Retributor Beam Laser' : ('Beam Laser', 'Retributor'),
'Rocket Propelled FSD Disruptor': ('Missile Rack', 'Rocket Propelled FSD Disruptor'),
'Shock Mine Launcher' : ('Mine Launcher', 'Shock Mine Launcher'),
'Standard Docking Computer' : ('Docking Computer', 'Standard Docking Computer'),
})
specials = { v:k for k,v in fixup_map.items() }
# Map Coriolis's names to names displayed in the in-game shipyard
coriolis_ship_map = {
'Cobra Mk III' : 'Cobra MkIII',
@ -50,73 +24,10 @@ if __name__ == "__main__":
'Viper Mk IV' : 'Viper MkIV',
}
# From https://github.com/EDCD/coriolis/blob/master/src/app/shipyard/Constants.js
ModuleGroupToName = {
# Standard
'pp' : 'Power Plant',
't' : 'Thrusters',
'fsd' : 'Frame Shift Drive',
'ls' : 'Life Support',
'pd' : 'Power Distributor',
's' : 'Sensors',
'ft' : 'Fuel Tank',
'pas' : 'Planetary Approach Suite',
# Symbolic name from in-game name
reverse_ship_map = {v: k for k, v in companion.ship_map.iteritems()}
# Internal
'fs' : 'Fuel Scoop',
'sc' : 'Scanner',
'am' : 'Auto Field-Maintenance Unit',
'bsg' : 'Bi-Weave Shield Generator',
'cr' : 'Cargo Rack',
'fh' : 'Fighter Hangar',
'fi' : 'Frame Shift Drive Interdictor',
'hb' : 'Hatch Breaker Limpet Controller',
'hr' : 'Hull Reinforcement Package',
'rf' : 'Refinery',
'scb' : 'Shield Cell Bank',
'sg' : 'Shield Generator',
'pv' : 'Planetary Vehicle Hangar',
'psg' : 'Prismatic Shield Generator',
'dc' : 'Docking Computer',
'fx' : 'Fuel Transfer Limpet Controller',
'mrp' : 'Module Reinforcement Package',
'pc' : 'Prospector Limpet Controller',
'pce' : 'Economy Class Passenger Cabin',
'pci' : 'Business Class Passenger Cabin',
'pcm' : 'First Class Passenger Cabin',
'pcq' : 'Luxury Passenger Cabin',
'cc' : 'Collector Limpet Controller',
'rpl' : 'Repair Limpet Controller',
'ss' : 'Detailed Surface Scanner',
# Hard Points
'bl' : 'Beam Laser',
'ul' : 'Burst Laser',
'c' : 'Cannon',
'ch' : 'Chaff Launcher',
'cs' : 'Cargo Scanner',
'cm' : 'Countermeasure',
'ec' : 'Electronic Countermeasure',
'fc' : 'Fragment Cannon',
'rfl' : 'Remote Release Flak Launcher',
'hs' : 'Heat Sink Launcher',
'ws' : 'Frame Shift Wake Scanner',
'kw' : 'Kill Warrant Scanner',
'nl' : 'Mine Launcher',
'ml' : 'Mining Laser',
'mr' : 'Missile Rack',
'axmr': 'AX Missile Rack',
'pa' : 'Plasma Accelerator',
'po' : 'Point Defence',
'mc' : 'Multi-cannon',
'axmc': 'AX Multi-Cannon',
'pl' : 'Pulse Laser',
'rg' : 'Rail Gun',
'sb' : 'Shield Booster',
'tp' : 'Torpedo Pylon',
'sfn' : 'Shutdown Field Neutraliser',
'xs' : 'Xeno Scanner',
};
bulkheads = outfitting.armour_map.keys()
ships = {}
modules = {}
@ -124,9 +35,10 @@ if __name__ == "__main__":
# Ship and armour masses
for m in data['Ships'].values():
name = coriolis_ship_map.get(m['properties']['name'], str(m['properties']['name']))
assert name in reverse_ship_map, name
ships[name] = { 'hullMass' : m['properties']['hullMass'] }
for i in range(len(bulkheads)):
modules[(bulkheads[i], name, '1', 'I')] = { 'mass': m['bulkheads'][i]['mass'] }
modules['_'.join([reverse_ship_map[name], 'armour', bulkheads[i]])] = { 'mass': m['bulkheads'][i]['mass'] }
ships = OrderedDict([(k,ships[k]) for k in sorted(ships)]) # sort for easier diffing
cPickle.dump(ships, open('ships.p', 'wb'))
@ -135,14 +47,9 @@ if __name__ == "__main__":
for cat in data['Modules'].values():
for grp, mlist in cat.iteritems():
for m in mlist:
key = (specials.get((ModuleGroupToName[grp], m.get('name'))) or ModuleGroupToName[grp],
None,
str(m['class']),
str(m['rating']))
if key in modules:
# Test our assumption that mount and guidance don't affect mass
assert modules[key]['mass'] == m.get('mass', 0), '%s !=\n%s' % (key, m)
elif grp == 'fsd':
assert 'symbol' in m, m
key = str(m['symbol'].lower())
if grp == 'fsd':
modules[key] = {
'mass' : m['mass'],
'optmass' : m['optmass'],
@ -150,32 +57,42 @@ if __name__ == "__main__":
'fuelmul' : m['fuelmul'],
'fuelpower' : m['fuelpower'],
}
elif grp == 'gfsb':
modules[key] = {
'mass' : m['mass'],
'jumpboost' : m['jumpboost'],
}
else:
modules[key] = { 'mass': m.get('mass', 0) } # Some modules don't have mass
# 3.0 additions not yet present in coriolis-data
# 3.0 / 3.1 additions not yet present in coriolis-data
for k in modules.keys():
if k[0] == 'Module Reinforcement Package':
modules[('Meta Alloy Hull Reinforcement',) + k[1:]] = modules[k]
modules[('Decontamination Limpet Controller', None, '1', 'E')] = {'mass': 1.3}
modules[('Decontamination Limpet Controller', None, '3', 'E')] = {'mass': 2}
modules[('Decontamination Limpet Controller', None, '5', 'E')] = {'mass': 20}
modules[('Decontamination Limpet Controller', None, '7', 'E')] = {'mass': 128}
modules[('Recon Limpet Controller', None, '1', 'E')] = {'mass': 1.3}
modules[('Recon Limpet Controller', None, '3', 'E')] = {'mass': 2}
modules[('Recon Limpet Controller', None, '5', 'E')] = {'mass': 20}
modules[('Recon Limpet Controller', None, '7', 'E')] = {'mass': 128}
modules[('Research Limpet Controller', None, '1', 'E')] = {'mass': 1.3}
modules[('Guardian Power Plant', None, '2', 'A')] = {'mass': 1.5}
modules[('Guardian Power Plant', None, '3', 'A')] = {'mass': 2.9}
modules[('Guardian Power Plant', None, '4', 'A')] = {'mass': 5.9}
modules[('Guardian Power Plant', None, '5', 'A')] = {'mass': 11.7}
modules[('Guardian Power Plant', None, '6', 'A')] = {'mass': 23.4}
modules[('Guardian Power Plant', None, '7', 'A')] = {'mass': 46.8}
modules[('Guardian Power Plant', None, '8', 'A')] = {'mass': 93.6}
modules[('Bi-Weave Shield Generator', None, '8', 'C')] = {'mass': 160}
modules[('Enzyme Missile Rack', None, '2', 'B')] = {'mass': 4}
modules[('Remote Release Flechette Launcher', None, '2', 'B')] = {'mass': 4}
if k.startswith('int_hullreinforcement_'):
modules['int_guardianhullreinforcement_' + k[22:]] = modules[k]
modules['int_metaalloyhullreinforcement_' + k[22:]] = modules[k]
modules['int_guardianmodulereinforcement_' + k[22:]] = modules[k]
modules['hpt_causticmissile_fixed_medium'] = {'mass': 4}
modules['hpt_flechettelauncher_fixed_medium'] = {'mass': 4}
modules['hpt_flechettelauncher_turret_medium'] = {'mass': 4}
modules['hpt_guardian_plasmalauncher_fixed_medium'] = {'mass': 4}
modules['hpt_guardian_plasmalauncher_fixed_large'] = {'mass': 8}
modules['hpt_guardian_plasmalauncher_turret_medium'] = {'mass': 4}
modules['hpt_guardian_plasmalauncher_turret_large'] = {'mass': 8}
modules['hpt_guardian_shardcannon_fixed_medium'] = {'mass': 4}
modules['hpt_guardian_shardcannon_fixed_large'] = {'mass': 8}
modules['hpt_guardian_shardcannon_turret_medium'] = {'mass': 4}
modules['hpt_guardian_shardcannon_turret_large'] = {'mass': 8}
modules['hpt_plasmashockcannon_fixed_medium'] = {'mass': 4}
modules['hpt_plasmashockcannon_fixed_large'] = {'mass': 8} # ???
modules['hpt_plasmashockcannon_gimbal_medium'] = {'mass': 4}
modules['hpt_plasmashockcannon_gimbal_large'] = {'mass': 8} # ???
modules['hpt_plasmashockcannon_turret_medium'] = {'mass': 4}
modules['hpt_plasmashockcannon_turret_large'] = {'mass': 8} # ???
modules['int_dronecontrol_decontamination_size1_class1'] = {'mass': 1.3}
modules['int_dronecontrol_decontamination_size3_class1'] = {'mass': 2}
modules['int_dronecontrol_decontamination_size5_class1'] = {'mass': 20}
modules['int_dronecontrol_decontamination_size7_class1'] = {'mass': 128}
modules['int_dronecontrol_unkvesselresearch'] = {'mass': 1.3}
modules = OrderedDict([(k,modules[k]) for k in sorted(modules)]) # sort for easier diffing
cPickle.dump(modules, open('modules.p', 'wb'))

View File

@ -63,6 +63,7 @@ def export(data, filename=None):
fuel = 0
cargo = 0
fsd = None
jumpboost = 0
for slot in sorted(data['ship']['modules']):
@ -96,7 +97,7 @@ def export(data, filename=None):
fsd['optmass'] *= mods['OutfittingFieldType_FSDOptimalMass']['value']
if mods.get('OutfittingFieldType_MaxFuelPerJump'):
fsd['maxfuel'] *= mods['OutfittingFieldType_MaxFuelPerJump']['value']
jumpboost += module.get('jumpboost', 0)
for s in slot_map:
if slot.lower().startswith(s):
@ -134,8 +135,8 @@ def export(data, filename=None):
string += 'Mass : %.2f T empty\n %.2f T full\n' % (mass, mass + fuel + cargo)
multiplier = pow(min(fuel, fsd['maxfuel']) / fsd['fuelmul'], 1.0 / fsd['fuelpower']) * fsd['optmass']
string += 'Range : %.2f LY unladen\n %.2f LY laden\n' % (
multiplier / (mass + fuel),
multiplier / (mass + fuel + cargo))
multiplier / (mass + fuel) + jumpboost,
multiplier / (mass + fuel + cargo) + jumpboost)
except:
if __debug__: raise

12948
modules.p

File diff suppressed because it is too large Load Diff

View File

@ -31,8 +31,9 @@ weapon_map = {
('dumbfiremissilerack', 'lasso') : 'Rocket Propelled FSD Disruptor',
'flakmortar' : 'Remote Release Flak Launcher',
'flechettelauncher' : 'Remote Release Flechette Launcher',
('guardian', 'gausscannon') : 'Guardian Gauss Cannon',
('guardian', 'plasmalauncher') : 'Guardian Plasma Charger',
'guardian_gausscannon' : 'Guardian Gauss Cannon',
'guardian_plasmalauncher' : 'Guardian Plasma Charger',
'guardian_shardcannon' : 'Guardian Shard Cannon',
'minelauncher' : 'Mine Launcher',
('minelauncher','impulse') : 'Shock Mine Launcher',
'mininglaser' : 'Mining Laser',
@ -41,6 +42,7 @@ weapon_map = {
('multicannon','strong') : 'Enforcer Cannon',
'plasmaaccelerator' : 'Plasma Accelerator',
('plasmaaccelerator','advanced') : 'Advanced Plasma Accelerator',
'plasmashockcannon' : 'Shock Cannon',
'pulselaser' : 'Pulse Laser',
('pulselaser','disruptor') : 'Pulse Disruptor Laser',
'pulselaserburst' : 'Burst Laser',
@ -119,9 +121,15 @@ weaponrating_map = {
'hpt_flakmortar_turret_medium': 'B',
'hpt_flechettelauncher_fixed_medium': 'B',
'hpt_flechettelauncher_turret_medium': 'B',
'hpt_guardian_gausscannon_fixed_medium': 'A', # guess
'hpt_guardian_plasmalauncher_fixed_medium': 'A', # guess
'hpt_guardian_plasmalauncher_turret_medium': 'A', # guess
'hpt_guardian_gausscannon_fixed_medium': 'B', # guess
'hpt_guardian_plasmalauncher_fixed_medium': 'B',
'hpt_guardian_plasmalauncher_fixed_large': 'C',
'hpt_guardian_plasmalauncher_turret_medium': 'E',
'hpt_guardian_plasmalauncher_turret_large': 'D',
'hpt_guardian_shardcannon_fixed_medium': 'A',
'hpt_guardian_shardcannon_fixed_large': 'C',
'hpt_guardian_shardcannon_turret_medium': 'D',
'hpt_guardian_shardcannon_turret_large': 'D',
'hpt_minelauncher_fixed_small': 'I',
'hpt_minelauncher_fixed_medium': 'I',
'hpt_mininglaser_fixed_small': 'D',
@ -141,6 +149,12 @@ weaponrating_map = {
'hpt_plasmaaccelerator_fixed_medium': 'C',
'hpt_plasmaaccelerator_fixed_large': 'B',
'hpt_plasmaaccelerator_fixed_huge': 'A',
'hpt_plasmashockcannon_fixed_medium': 'D',
'hpt_plasmashockcannon_fixed_large': 'C',
'hpt_plasmashockcannon_gimbal_medium': 'D',
'hpt_plasmashockcannon_gimbal_large': 'C',
'hpt_plasmashockcannon_turret_medium': 'E',
'hpt_plasmashockcannon_turret_large': 'D',
'hpt_pulselaser_fixed_small': 'F',
'hpt_pulselaser_fixed_smallfree': 'F',
'hpt_pulselaser_fixed_medium': 'E',
@ -244,17 +258,18 @@ misc_internal_map = {
}
standard_map = {
# 'armour' : handled separately
'engine' : 'Thrusters',
('engine','fast') : 'Enhanced Performance Thrusters',
'fueltank' : 'Fuel Tank',
'guardianpowerplant' : 'Guardian Power Plant',
'hyperdrive' : 'Frame Shift Drive',
'lifesupport' : 'Life Support',
# 'planetapproachsuite' : handled separately
'powerdistributor' : 'Power Distributor',
'powerplant' : 'Power Plant',
'sensors' : 'Sensors',
# 'armour' : handled separately
'engine' : 'Thrusters',
('engine','fast') : 'Enhanced Performance Thrusters',
'fueltank' : 'Fuel Tank',
'guardianpowerdistributor' : 'Guardian Hybrid Power Distributor',
'guardianpowerplant' : 'Guardian Hybrid Power Plant',
'hyperdrive' : 'Frame Shift Drive',
'lifesupport' : 'Life Support',
# 'planetapproachsuite' : handled separately
'powerdistributor' : 'Power Distributor',
'powerplant' : 'Power Plant',
'sensors' : 'Sensors',
}
internal_map = {
@ -267,6 +282,10 @@ internal_map = {
'fsdinterdictor' : 'Frame Shift Drive Interdictor',
'fuelscoop' : 'Fuel Scoop',
'fueltransfer' : 'Fuel Transfer Limpet Controller',
'guardianfsdbooster' : 'Guardian FSD Booster',
'guardianhullreinforcement' : 'Guardian Hull Reinforcement',
'guardianmodulereinforcement': 'Guardian Module Reinforcement',
'guardianshieldreinforcement': 'Guardian Shield Reinforcement',
'hullreinforcement' : 'Hull Reinforcement Package',
'metaalloyhullreinforcement' : 'Meta Alloy Hull Reinforcement',
'modulereinforcement' : 'Module Reinforcement Package',
@ -304,6 +323,11 @@ def lookup(module, ship_map, entitled=False):
name = module['name'].lower().split('_')
new = { 'id': module['id'], 'symbol': module['name'] }
# Hack 'Guardian used as a prefix'
if name[1] == 'guardian':
name.pop(1)
name[1] = 'guardian_%s' % name[1]
# Armour - e.g. Federation_Dropship_Armour_Grade2
if name[-2] == 'armour':
name = module['name'].lower().rsplit('_', 2) # Armour is ship-specific, and ship names can have underscores
@ -405,8 +429,10 @@ def lookup(module, ship_map, entitled=False):
if len(name) < 4 and name[1] == 'unkvesselresearch': # Hack! No size or class.
(new['class'], new['rating']) = ('1', 'E')
elif len(name) < 4 and name[1] == 'guardianpowerplant': # Hack! No class.
elif len(name) < 4 and name[1] in ['guardianpowerdistributor', 'guardianpowerplant']: # Hack! No class.
(new['class'], new['rating']) = (str(name[2][4:]), 'A')
elif len(name) < 4 and name[1] in ['guardianfsdbooster']: # Hack! No class.
(new['class'], new['rating']) = (str(name[2][4:]), 'H')
else:
if not name[2].startswith('size') or not name[3].startswith('class'): raise AssertionError('%s: Unknown class/rating "%s/%s"' % (module['id'], name[2], name[3]))
new['class'] = str(name[2][4:])
@ -429,16 +455,19 @@ def lookup(module, ship_map, entitled=False):
new['entitlement'] = 'horizons'
# Extra module data
key = (new['name'], 'ship' in new and companion.ship_map.get(name[0]) or None, new['class'], new['rating'])
if module['name'].endswith('_free'):
key = module['name'][:-5].lower() # starter modules - treated like vanilla modules
else:
key = module['name'].lower()
if __debug__:
m = moduledata.get(key, {})
if not m:
print 'No data for module %s' % str(key)
print 'No data for module %s' % key
elif new['name'] == 'Frame Shift Drive':
assert 'mass' in m and 'optmass' in m and 'maxfuel' in m and 'fuelmul' in m and 'fuelpower' in m, m
else:
assert 'mass' in m, m
new.update(moduledata.get(key, {}))
new.update(moduledata.get(module['name'].lower(), {}))
# check we've filled out mandatory fields
for thing in ['id', 'symbol', 'category', 'name', 'class', 'rating']: # Don't consider mass etc as mandatory

136
ships.p
View File

@ -10,196 +10,208 @@ S'hullMass'
p6
I35
saa(lp7
S'Alliance Chieftain'
S'Alliance Challenger'
p8
a(dp9
g6
I420
I450
saa(lp10
S'Anaconda'
S'Alliance Chieftain'
p11
a(dp12
g6
I400
saa(lp13
S'Asp Explorer'
S'Anaconda'
p14
a(dp15
g6
I280
I400
saa(lp16
S'Asp Scout'
S'Asp Explorer'
p17
a(dp18
g6
I150
I280
saa(lp19
S'Beluga Liner'
S'Asp Scout'
p20
a(dp21
g6
I950
I150
saa(lp22
S'Cobra MkIII'
S'Beluga Liner'
p23
a(dp24
g6
I180
I950
saa(lp25
S'Cobra MkIV'
S'Cobra MkIII'
p26
a(dp27
g6
I210
I180
saa(lp28
S'Diamondback Explorer'
S'Cobra MkIV'
p29
a(dp30
g6
I260
I210
saa(lp31
S'Diamondback Scout'
S'Diamondback Explorer'
p32
a(dp33
g6
I170
I260
saa(lp34
S'Dolphin'
S'Diamondback Scout'
p35
a(dp36
g6
I140
I170
saa(lp37
S'Eagle'
S'Dolphin'
p38
a(dp39
g6
I50
I140
saa(lp40
S'Federal Assault Ship'
S'Eagle'
p41
a(dp42
g6
I480
I50
saa(lp43
S'Federal Corvette'
S'Federal Assault Ship'
p44
a(dp45
g6
I900
I480
saa(lp46
S'Federal Dropship'
S'Federal Corvette'
p47
a(dp48
g6
I580
I900
saa(lp49
S'Federal Gunship'
S'Federal Dropship'
p50
a(dp51
g6
I580
saa(lp52
S'Fer-de-Lance'
S'Federal Gunship'
p53
a(dp54
g6
I250
I580
saa(lp55
S'Hauler'
S'Fer-de-Lance'
p56
a(dp57
g6
I14
I250
saa(lp58
S'Imperial Clipper'
S'Hauler'
p59
a(dp60
g6
I400
I14
saa(lp61
S'Imperial Courier'
S'Imperial Clipper'
p62
a(dp63
g6
I35
I400
saa(lp64
S'Imperial Cutter'
S'Imperial Courier'
p65
a(dp66
g6
I1100
I35
saa(lp67
S'Imperial Eagle'
S'Imperial Cutter'
p68
a(dp69
g6
I50
I1100
saa(lp70
S'Keelback'
S'Imperial Eagle'
p71
a(dp72
g6
I180
I50
saa(lp73
S'Orca'
S'Keelback'
p74
a(dp75
g6
I290
I180
saa(lp76
S'Python'
S'Krait MkII'
p77
a(dp78
g6
I350
I320
saa(lp79
S'Sidewinder'
S'Orca'
p80
a(dp81
g6
I25
I290
saa(lp82
S'Type-10 Defender'
S'Python'
p83
a(dp84
g6
I1200
I350
saa(lp85
S'Type-6 Transporter'
S'Sidewinder'
p86
a(dp87
g6
I155
I25
saa(lp88
S'Type-7 Transporter'
S'Type-10 Defender'
p89
a(dp90
g6
I420
I1200
saa(lp91
S'Type-9 Heavy'
S'Type-6 Transporter'
p92
a(dp93
g6
I850
I155
saa(lp94
S'Viper MkIII'
S'Type-7 Transporter'
p95
a(dp96
g6
I50
I350
saa(lp97
S'Viper MkIV'
S'Type-9 Heavy'
p98
a(dp99
g6
I190
I850
saa(lp100
S'Vulture'
S'Viper MkIII'
p101
a(dp102
g6
I50
saa(lp103
S'Viper MkIV'
p104
a(dp105
g6
I190
saa(lp106
S'Vulture'
p107
a(dp108
g6
I230
saatRp103
saatRp109
.