Starsector API
Loading...
Searching...
No Matches
FleetFactory.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.fleets;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import org.apache.log4j.Logger;
7
8import com.fs.starfarer.api.FactoryAPI;
9import com.fs.starfarer.api.Global;
10import com.fs.starfarer.api.campaign.CampaignFleetAPI;
11import com.fs.starfarer.api.campaign.FactionAPI;
12import com.fs.starfarer.api.campaign.FactionAPI.ShipPickParams;
13import com.fs.starfarer.api.campaign.econ.MarketAPI;
14import com.fs.starfarer.api.fleet.FleetMemberAPI;
15import com.fs.starfarer.api.fleet.FleetMemberType;
16import com.fs.starfarer.api.impl.campaign.ids.Factions;
17import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
18import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
19import com.fs.starfarer.api.impl.campaign.ids.ShipRoles;
20import com.fs.starfarer.api.loading.AbilitySpecAPI;
21import com.fs.starfarer.api.util.WeightedRandomPicker;
22
23public class FleetFactory {
24
25 public static Logger log = Global.getLogger(FleetFactory.class);
26
27 public static enum PatrolType {
28 FAST(FleetTypes.PATROL_SMALL),
29 COMBAT(FleetTypes.PATROL_MEDIUM),
30 HEAVY(FleetTypes.PATROL_LARGE);
31
32 private String fleetType;
33 private PatrolType(String fleetType) {
34 this.fleetType = fleetType;
35 }
36 public String getFleetType() {
37 return fleetType;
38 }
39 }
40
41 public static CampaignFleetAPI createPatrol(MarketAPI market, PatrolType type) {
42 float stability = market.getStabilityValue();
43 String factionId = market.getFactionId();
44 FactionAPI faction = Global.getSector().getFaction(factionId);
45 float qf = market.getShipQualityFactor();
46 return createPatrol(type, faction, stability, qf, market);
47
48 }
49
50 public static CampaignFleetAPI createPatrol(PatrolType type, FactionAPI faction, float stability, float qf, MarketAPI market) {
51 String fleetType = FleetTypes.PATROL_SMALL;
52 switch (type) {
53 case FAST:
54 fleetType = FleetTypes.PATROL_SMALL;
55 break;
56 case COMBAT:
57 fleetType = FleetTypes.PATROL_MEDIUM;
58 break;
59 case HEAVY:
60 fleetType = FleetTypes.PATROL_LARGE;
61 break;
62 }
63 CampaignFleetAPI fleet = createEmptyFleet(faction.getId(), fleetType, market);
64
65 switch (type) {
66 case FAST:
67 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
68 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
69 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
70 if (stability > (float) Math.random() * 20f) {
71 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
72 }
73 if (stability > (float) Math.random() * 20f) {
74 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
75 }
76 break;
77 case COMBAT:
78 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
79 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
80
81 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
82 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
83 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
84
85 if (stability > (float) Math.random() * 20f) {
86 faction.pickShipAndAddToFleet(ShipRoles.FREIGHTER_SMALL, ShipPickParams.all(), fleet);
87 }
88 if (stability > (float) Math.random() * 20f) {
89 faction.pickShipAndAddToFleet(ShipRoles.TANKER_SMALL, ShipPickParams.all(), fleet);
90 }
91 if (stability > (float) Math.random() * 20f) {
92 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
93 }
94 if (stability > (float) Math.random() * 20f) {
95 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
96 }
97 if (stability > (float) Math.random() * 20f) {
98 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
99 }
100 break;
101 case HEAVY:
102 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
103
104 if ((float) Math.random() > 0.5f) {
105 faction.pickShipAndAddToFleet(ShipRoles.CARRIER_MEDIUM, ShipPickParams.all(), fleet);
106 } else {
107 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
108 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_LARGE, ShipPickParams.all(), fleet);
109 }
110
111 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
112 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
113 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_LARGE, ShipPickParams.all(), fleet);
114
115 faction.pickShipAndAddToFleet(ShipRoles.FREIGHTER_MEDIUM, ShipPickParams.all(), fleet);
116 faction.pickShipAndAddToFleet(ShipRoles.TANKER_MEDIUM, ShipPickParams.all(), fleet);
117
118 if (stability > (float) Math.random() * 20f) {
119 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
120 }
121 if (stability > (float) Math.random() * 20f) {
122 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
123 }
124 if (stability > (float) Math.random() * 20f) {
125 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_LARGE, ShipPickParams.all(), fleet);
126 }
127 break;
128 }
129
130 setAIMode(fleet, true);
131
132 return fleet;
133 }
134
135
136
137
138 public static enum MercType {
139 SCOUT(FleetTypes.MERC_SCOUT),
140 BOUNTY_HUNTER(FleetTypes.MERC_BOUNTY_HUNTER),
141 PRIVATEER(FleetTypes.MERC_PRIVATEER),
142 PATROL(FleetTypes.MERC_PATROL),
143 ARMADA(FleetTypes.MERC_ARMADA);
144
145 public String fleetType;
146 private MercType(String fleetType) {
147 this.fleetType = fleetType;
148 }
149
150 }
151
152 public static CampaignFleetAPI createMerc(MarketAPI market, float qf, MercType type, String factionIdForShipPicking) {
153 float stability = market.getStabilityValue();
154
155 String factionId = Factions.INDEPENDENT;
156 FactionAPI faction = Global.getSector().getFaction(factionIdForShipPicking);
157// FactionAPI factionForInitialName = Global.getSector().getFaction(factionId);
158// //float qf = market.getShipQualityFactor();
159// String fleetName = factionForInitialName.getFleetTypeName(type.fleetType);
160// CampaignFleetAPI fleet = Global.getFactory().createEmptyFleet(factionId, fleetName, true);
161 //CampaignFleetAPI fleet = createEmptyFleet(factionId, type.fleetType);
162 CampaignFleetAPI fleet = createEmptyFleet(factionIdForShipPicking, type.fleetType, market);
163 switch (type) {
164 case SCOUT:
165 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
166 if ((float) Math.random() > 0.5f) {
167 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
168 }
169 if (stability < (float) Math.random() * 20f) {
170 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
171 }
172 break;
173 case PRIVATEER:
174 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
175 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
176 if (stability < (float) Math.random() * 20f) {
177 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
178 }
179 if (stability < (float) Math.random() * 20f) {
180 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
181 }
182 if (stability < (float) Math.random() * 20f) {
183 if ((float) Math.random() > 0.5f) {
184 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_FREIGHTER_MEDIUM, ShipPickParams.all(), fleet);
185 } else {
186 faction.pickShipAndAddToFleet(ShipRoles.FREIGHTER_MEDIUM, ShipPickParams.all(), fleet);
187 }
188 }
189 break;
190 case BOUNTY_HUNTER:
191 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
192 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
193 if ((float) Math.random() > 0.5f) {
194 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
195 }
196 if (stability < (float) Math.random() * 20f) {
197 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
198 }
199 if (stability < (float) Math.random() * 20f) {
200 faction.pickShipAndAddToFleet(ShipRoles.FAST_ATTACK, ShipPickParams.all(), fleet);
201 }
202 if (stability < (float) Math.random() * 20f) {
203 faction.pickShipAndAddToFleet(ShipRoles.TANKER_SMALL, ShipPickParams.all(), fleet);
204 }
205 break;
206 case PATROL:
207 if ((float) Math.random() > 0.33f) {
208 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
209 faction.pickShipAndAddToFleet(ShipRoles.ESCORT_SMALL, ShipPickParams.all(), fleet);
210 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
211 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
212 } else {
213 faction.pickShipAndAddToFleet(ShipRoles.CARRIER_SMALL, ShipPickParams.all(), fleet);
214 if (stability < (float) Math.random() * 20f) {
215 faction.pickShipAndAddToFleet(ShipRoles.CARRIER_SMALL, ShipPickParams.all(), fleet);
216 }
217 }
218 if (stability < (float) Math.random() * 20f) {
219 faction.pickShipAndAddToFleet(ShipRoles.ESCORT_SMALL, ShipPickParams.all(), fleet);
220 }
221 if (stability < (float) Math.random() * 20f) {
222 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
223 }
224 if (stability < (float) Math.random() * 20f) {
225 faction.pickShipAndAddToFleet(ShipRoles.ESCORT_SMALL, ShipPickParams.all(), fleet);
226 }
227 if (stability < (float) Math.random() * 20f) {
228 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
229 }
230 if (stability < (float) Math.random() * 20f) {
231 faction.pickShipAndAddToFleet(ShipRoles.FREIGHTER_MEDIUM, ShipPickParams.all(), fleet);
232 }
233 if (stability < (float) Math.random() * 20f) {
234 faction.pickShipAndAddToFleet(ShipRoles.TANKER_SMALL, ShipPickParams.all(), fleet);
235 }
236 break;
237 case ARMADA:
238 if ((float) Math.random() > 0.33f) {
239 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
240 faction.pickShipAndAddToFleet(ShipRoles.ESCORT_SMALL, ShipPickParams.all(), fleet);
241 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
242 faction.pickShipAndAddToFleet(ShipRoles.ESCORT_MEDIUM, ShipPickParams.all(), fleet);
243 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_LARGE, ShipPickParams.all(), fleet);
244 } else {
245 faction.pickShipAndAddToFleet(ShipRoles.CARRIER_MEDIUM, ShipPickParams.all(), fleet);
246 if (stability < (float) Math.random() * 20f) {
247 faction.pickShipAndAddToFleet(ShipRoles.CARRIER_SMALL, ShipPickParams.all(), fleet);
248 }
249 }
250 if (stability < (float) Math.random() * 20f) {
251 faction.pickShipAndAddToFleet(ShipRoles.ESCORT_MEDIUM, ShipPickParams.all(), fleet);
252 }
253 if (stability < (float) Math.random() * 20f) {
254 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_LARGE, ShipPickParams.all(), fleet);
255 }
256 if (stability < (float) Math.random() * 20f) {
257 faction.pickShipAndAddToFleet(ShipRoles.ESCORT_SMALL, ShipPickParams.all(), fleet);
258 }
259 if (stability < (float) Math.random() * 20f) {
260 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_MEDIUM, ShipPickParams.all(), fleet);
261 }
262 if (stability < (float) Math.random() * 20f) {
263 faction.pickShipAndAddToFleet(ShipRoles.FREIGHTER_MEDIUM, ShipPickParams.all(), fleet);
264 }
265 if (stability < (float) Math.random() * 20f) {
266 faction.pickShipAndAddToFleet(ShipRoles.TANKER_MEDIUM, ShipPickParams.all(), fleet);
267 }
268 break;
269 }
270
271 setAIMode(fleet, true);
272 return fleet;
273 }
274
275 private static List<String> startingAbilities = null;
276 public static CampaignFleetAPI createEmptyFleet(String factionId, String fleetType, MarketAPI market) {
277 FactionAPI faction = Global.getSector().getFaction(factionId);
278 String fleetName = null;
279 if (fleetType != null) fleetName = faction.getFleetTypeName(fleetType);
280 CampaignFleetAPI fleet = Global.getFactory().createEmptyFleet(factionId, fleetName, true);
281 if (fleetType != null) {
282 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_FLEET_TYPE, fleetType);
283 }
284
285 if (market != null) {
286 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_SOURCE_MARKET, market.getId());
287 }
288
289 if (startingAbilities == null) {
290 startingAbilities = new ArrayList<String>();
291 for (String id : Global.getSettings().getSortedAbilityIds()) {
292 AbilitySpecAPI spec = Global.getSettings().getAbilitySpec(id);
293 if (spec.isAIDefault()) {
294 startingAbilities.add(id);
295 }
296 }
297 }
298
299 for (String id : startingAbilities) {
300 fleet.addAbility(id);
301 }
302
303 return fleet;
304 }
305
306
307// public static final float SUPPLIES_FRACTION = 0.15f;
308// public static final float FUEL_FRACTION = 0.5f;
309 public static final float SUPPLIES_FRACTION = 0;
310 public static final float FUEL_FRACTION = 0;
311 public static void finishAndSync(CampaignFleetAPI fleet) {
312 setAIMode(fleet, false);
313 }
314 private static void setAIMode(CampaignFleetAPI fleet, boolean addSuppliesAndFuel) {
315// for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
316// //member.setCrewXPLevel(CrewXPLevel.REGULAR);
317// member.setCrewXPLevel(member.getCrewXPLevel());
318// }
319// fleet.setAIMode(true);
320// if (addSuppliesAndFuel) {
321// float maxCargo = fleet.getCargo().getMaxCapacity();
322// float maxFuel = fleet.getCargo().getMaxFuel();
323// fleet.getCargo().clear();
324// fleet.getCargo().addItems(CargoItemType.RESOURCES, Commodities.SUPPLIES, maxCargo * SUPPLIES_FRACTION);
325// fleet.getCargo().addItems(CargoItemType.RESOURCES, Commodities.FUEL, maxFuel * FUEL_FRACTION);
326// }
327 fleet.forceSync();
328 }
329
330
331 public static CampaignFleetAPI createGenericFleet(String factionId, String name, float qualityFactor, int maxFP) {
332 FactionAPI faction = Global.getSector().getFaction(factionId);
333 CampaignFleetAPI fleet = Global.getFactory().createEmptyFleet(factionId, name, true);
334
335 WeightedRandomPicker<String> main = new WeightedRandomPicker<String>();
336
337 main.add(ShipRoles.COMBAT_SMALL, 5);
338 main.add(ShipRoles.COMBAT_SMALL, 5);
339
340 main.add(ShipRoles.ESCORT_SMALL, 6);
341 main.add(ShipRoles.COMBAT_SMALL, 20);
342 main.add(ShipRoles.FAST_ATTACK, 10);
343
344 if (maxFP >= 20) {
345 main.add(ShipRoles.COMBAT_MEDIUM, 10);
346 main.add(ShipRoles.ESCORT_MEDIUM, 10);
347 }
348 if (maxFP >= 40) {
349 main.add(ShipRoles.COMBAT_LARGE, 5);
350 main.add(ShipRoles.COMBAT_SMALL, 5);
351 }
352 if (maxFP >= 60) {
353 main.add(ShipRoles.COMBAT_LARGE, 5);
354 main.add(ShipRoles.COMBAT_CAPITAL, 3);
355 }
356
357 // add ships and/or fighters, leave some headroom for carriers
358 int failCount = 0;
359 while (fleet.getFleetPoints() < maxFP * 0.75f) {
360 String role = main.pick();
361 boolean added = faction.pickShipAndAddToFleet(role, ShipPickParams.all(), fleet) > 0;
362 if (added) {
363 failCount = 0;
364 } else {
365 failCount++;
366 if (failCount >= 10) break;
367 }
368 }
369
370 // add a flagship if all we'd added before this were fighters
371 if (fleet.getFlagship() == null) {
372 faction.pickShipAndAddToFleet(ShipRoles.COMBAT_SMALL, ShipPickParams.all(), fleet);
373 if (fleet.getFlagship() == null) {
375 FleetMemberAPI flagship = f.createFleetMember(FleetMemberType.SHIP, "tempest_Attack");
376 fleet.getFleetData().addFleetMember(flagship);
377 }
378 }
379
380 int fighterFP = 0;
381 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
382 if (member.isFighterWing()) {
383 fighterFP += member.getFleetPointCost();
384 }
385 }
386
387 float pointsLeft = maxFP - fleet.getFleetPoints();
388 float carrierPoints = Math.min(pointsLeft, fighterFP * 0.33f);
389
390 WeightedRandomPicker<String> carriers = new WeightedRandomPicker<String>();
391 if (fighterFP >= 10) {
392 carriers.add(ShipRoles.CARRIER_SMALL, 5);
393 }
394 if (fighterFP >= 30) {
395 carriers.add(ShipRoles.CARRIER_MEDIUM, 5);
396 }
397 if (fighterFP >= 50) {
398 carriers.add(ShipRoles.CARRIER_LARGE, 5);
399 }
400
401 // add carriers, if needed
402 failCount = 0;
403 int startingFP = fleet.getFleetPoints();
404 while (fleet.getFleetPoints() < startingFP + carrierPoints) {
405 String role = carriers.pick();
406 boolean added = faction.pickShipAndAddToFleet(role, ShipPickParams.all(), fleet) > 0;
407 if (added) {
408 failCount = 0;
409 } else {
410 failCount++;
411 if (failCount >= 10) break;
412 }
413 }
414
415 // finish out by adding more ships with any leftover points
416 failCount = 0;
417 while (fleet.getFleetPoints() < maxFP) {
418 String role = main.pick();
419 boolean added = faction.pickShipAndAddToFleet(role, ShipPickParams.all(), fleet) > 0;
420 if (added) {
421 failCount = 0;
422 } else {
423 failCount++;
424 if (failCount >= 10) break;
425 }
426 }
427
428 finishAndSync(fleet);
429
430 return fleet;
431 }
432
433
434 public static void addGenericCombatShips(CampaignFleetAPI fleet, FactionAPI faction, MarketAPI market, int extraFP) {
435 float qualityFactor = market.getShipQualityFactor();
436
437 WeightedRandomPicker<String> main = new WeightedRandomPicker<String>();
438
439 main.add(ShipRoles.COMBAT_SMALL, 5);
440 main.add(ShipRoles.COMBAT_SMALL, 5);
441
442 main.add(ShipRoles.ESCORT_SMALL, 6);
443 main.add(ShipRoles.COMBAT_SMALL, 20);
444 main.add(ShipRoles.FAST_ATTACK, 10);
445
446 if (extraFP >= 20) {
447 main.add(ShipRoles.COMBAT_MEDIUM, 10);
448 main.add(ShipRoles.ESCORT_MEDIUM, 10);
449 }
450 if (extraFP >= 40) {
451 main.add(ShipRoles.COMBAT_LARGE, 5);
452 main.add(ShipRoles.COMBAT_SMALL, 5);
453 }
454 if (extraFP >= 60) {
455 main.add(ShipRoles.COMBAT_LARGE, 5);
456 main.add(ShipRoles.COMBAT_CAPITAL, 3);
457 }
458
459 // add ships and/or fighters, leave some headroom for carriers
460 int failCount = 0;
461 int starting = fleet.getFleetPoints();
462 while (fleet.getFleetPoints() < starting + extraFP) {
463 String role = main.pick();
464 boolean added = faction.pickShipAndAddToFleet(role, ShipPickParams.all(), fleet) > 0;
465 if (added) {
466 failCount = 0;
467 } else {
468 failCount++;
469 if (failCount >= 10) break;
470 }
471 }
472 }
473}
474
475
476
477
478
479
480
481
482
483
484
485
486
487
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static Logger getLogger(Class c)
Definition Global.java:26
static SectorAPI getSector()
Definition Global.java:59
static CampaignFleetAPI createPatrol(MarketAPI market, PatrolType type)
static void finishAndSync(CampaignFleetAPI fleet)
static CampaignFleetAPI createMerc(MarketAPI market, float qf, MercType type, String factionIdForShipPicking)
static CampaignFleetAPI createGenericFleet(String factionId, String name, float qualityFactor, int maxFP)
static CampaignFleetAPI createPatrol(PatrolType type, FactionAPI faction, float stability, float qf, MarketAPI market)
static CampaignFleetAPI createEmptyFleet(String factionId, String fleetType, MarketAPI market)
static void addGenericCombatShips(CampaignFleetAPI fleet, FactionAPI faction, MarketAPI market, int extraFP)
CampaignFleetAPI createEmptyFleet(String factionId, String name, boolean aiMode)
FleetMemberAPI createFleetMember(FleetMemberType type, String variantOrWingId)
AbilitySpecAPI getAbilitySpec(String abilityId)
List< String > getSortedAbilityIds()