1package com.fs.starfarer.api.impl.campaign;
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.Comparator;
6import java.util.HashMap;
7import java.util.HashSet;
8import java.util.Iterator;
9import java.util.LinkedHashMap;
12import java.util.Random;
15import com.fs.starfarer.api.Global;
16import com.fs.starfarer.api.campaign.BattleAPI;
17import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
18import com.fs.starfarer.api.campaign.CampaignFleetAPI;
19import com.fs.starfarer.api.campaign.CargoAPI;
20import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
21import com.fs.starfarer.api.campaign.CargoStackAPI;
22import com.fs.starfarer.api.campaign.CombatDamageData;
23import com.fs.starfarer.api.campaign.CombatDamageData.DamageToFleetMember;
24import com.fs.starfarer.api.campaign.CombatDamageData.DealtByFleetMember;
25import com.fs.starfarer.api.campaign.EngagementResultForFleetAPI;
26import com.fs.starfarer.api.campaign.FactionAPI;
27import com.fs.starfarer.api.campaign.FleetAssignment;
28import com.fs.starfarer.api.campaign.FleetDataAPI;
29import com.fs.starfarer.api.campaign.FleetEncounterContextPlugin;
30import com.fs.starfarer.api.campaign.FleetEncounterContextPlugin.DataForEncounterSide.OfficerEngagementData;
31import com.fs.starfarer.api.campaign.InteractionDialogAPI;
32import com.fs.starfarer.api.campaign.TextPanelAPI;
33import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI.PursuitOption;
34import com.fs.starfarer.api.campaign.ai.ModularFleetAIAPI;
35import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
36import com.fs.starfarer.api.campaign.listeners.ListenerUtil;
37import com.fs.starfarer.api.campaign.rules.MemoryAPI;
38import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
39import com.fs.starfarer.api.characters.OfficerDataAPI;
40import com.fs.starfarer.api.characters.PersonAPI;
41import com.fs.starfarer.api.combat.DeployedFleetMemberAPI;
42import com.fs.starfarer.api.combat.EngagementResultAPI;
43import com.fs.starfarer.api.combat.FighterLaunchBayAPI;
44import com.fs.starfarer.api.combat.ShipAPI;
45import com.fs.starfarer.api.combat.ShipVariantAPI;
46import com.fs.starfarer.api.combat.WeaponAPI;
47import com.fs.starfarer.api.combat.WeaponAPI.WeaponType;
48import com.fs.starfarer.api.fleet.CrewCompositionAPI;
49import com.fs.starfarer.api.fleet.FleetGoal;
50import com.fs.starfarer.api.fleet.FleetMemberAPI;
51import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
52import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
53import com.fs.starfarer.api.impl.campaign.ids.Commodities;
54import com.fs.starfarer.api.impl.campaign.ids.Factions;
55import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
56import com.fs.starfarer.api.impl.campaign.ids.Stats;
57import com.fs.starfarer.api.impl.campaign.ids.Tags;
58import com.fs.starfarer.api.impl.campaign.intel.PromoteOfficerIntel;
59import com.fs.starfarer.api.impl.campaign.procgen.SalvageEntityGenDataSpec.DropData;
60import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.SalvageEntity;
61import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.BaseSalvageSpecial;
62import com.fs.starfarer.api.impl.campaign.tutorial.TutorialMissionIntel;
63import com.fs.starfarer.api.loading.FighterWingSpecAPI;
64import com.fs.starfarer.api.loading.HullModSpecAPI;
65import com.fs.starfarer.api.loading.VariantSource;
66import com.fs.starfarer.api.loading.WeaponGroupSpec;
67import com.fs.starfarer.api.loading.WeaponSlotAPI;
68import com.fs.starfarer.api.loading.WeaponSpecAPI;
69import com.fs.starfarer.api.util.Misc;
70import com.fs.starfarer.api.util.WeightedRandomPicker;
74 protected List<DataForEncounterSide>
sideData =
new ArrayList<DataForEncounterSide>();
113 if (combined ==
null) {
114 return new DataForEncounterSide(participantOrCombined);
117 for (DataForEncounterSide curr :
sideData) {
118 if (curr.getFleet() == combined)
return curr;
120 DataForEncounterSide dfes =
new DataForEncounterSide(combined);
127 for (DataForEncounterSide curr :
sideData) {
128 if (!curr.disengaged()) {
136 for (DataForEncounterSide curr :
sideData) {
137 if (curr.disengaged()) {
162 data.getMemberToDeployedMap().clear();
165 if (deployed !=
null && !deployed.isEmpty()) {
167 if (dfm.getMember() !=
null) {
169 data.getMemberToDeployedMap().put(member, dfm);
171 if (dfm !=
null && dfm.getShip() !=
null && dfm.getShip().getOriginalCaptain() !=
null &&
172 !dfm.getShip().getOriginalCaptain().isDefault()) {
173 data.getMembersWithOfficerOrPlayerAsOrigCaptain().add(member);
186 Iterator<FleetMemberAPI> iter = result.
getDeployed().iterator();
187 while (iter.hasNext()) {
194 while (iter.hasNext()) {
201 while (iter.hasNext()) {
208 while (iter.hasNext()) {
215 while (iter.hasNext()) {
245 if (currDamageData !=
null) {
282 winnerData.setWonLastEngagement(
true);
285 loserData.setWonLastEngagement(
false);
289 winnerData.setDidEnoughToDisengage(
true);
290 float damageInFP = 0f;
292 damageInFP += member.getFleetPointCost();
295 damageInFP += member.getFleetPointCost();
298 damageInFP += member.getFleetPointCost();
309 winnerData.setLastGoal(winnerResult.
getGoal());
310 loserData.setLastGoal(loserResult.
getGoal());
312 winnerData.getDeployedInLastEngagement().clear();
313 winnerData.getRetreatedFromLastEngagement().clear();
314 winnerData.getInReserveDuringLastEngagement().clear();
315 winnerData.getDisabledInLastEngagement().clear();
316 winnerData.getDestroyedInLastEngagement().clear();
317 winnerData.getDeployedInLastEngagement().addAll(winnerResult.
getDeployed());
318 winnerData.getRetreatedFromLastEngagement().addAll(winnerResult.
getRetreated());
319 winnerData.getInReserveDuringLastEngagement().addAll(winnerResult.
getReserves());
320 winnerData.getDisabledInLastEngagement().addAll(winnerResult.
getDisabled());
321 winnerData.getDestroyedInLastEngagement().addAll(winnerResult.
getDestroyed());
323 loserData.getDeployedInLastEngagement().clear();
324 loserData.getRetreatedFromLastEngagement().clear();
325 loserData.getInReserveDuringLastEngagement().clear();
326 loserData.getDisabledInLastEngagement().clear();
327 loserData.getDestroyedInLastEngagement().clear();
328 loserData.getDeployedInLastEngagement().addAll(loserResult.
getDeployed());
329 loserData.getRetreatedFromLastEngagement().addAll(loserResult.
getRetreated());
330 loserData.getInReserveDuringLastEngagement().addAll(loserResult.
getReserves());
331 loserData.getDisabledInLastEngagement().addAll(loserResult.
getDisabled());
332 loserData.getDestroyedInLastEngagement().addAll(loserResult.
getDestroyed());
335 loserData.addOwn(member, Status.DESTROYED);
339 loserData.addOwn(member, Status.DISABLED);
343 winnerData.addOwn(member, Status.DESTROYED);
347 winnerData.addOwn(member, Status.DISABLED);
369 loserData.addEnemy(member, Status.DESTROYED);
372 loserData.addEnemy(member, Status.DISABLED);
376 winnerData.addEnemy(member, Status.DESTROYED);
379 winnerData.addEnemy(member, Status.DISABLED);
392 playerGoal = winnerGoal;
393 otherGoal = loserGoal;
395 playerGoal = loserGoal;
396 otherGoal = winnerGoal;
401 lastOutcome = EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_WIN;
403 lastOutcome = EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_LOSS;
407 lastOutcome = EngagementOutcome.PURSUIT_PLAYER_OUT_FIRST_WIN;
409 lastOutcome = EngagementOutcome.PURSUIT_PLAYER_OUT_FIRST_LOSS;
414 lastOutcome = EngagementOutcome.ESCAPE_PLAYER_OUT_FIRST_WIN;
416 lastOutcome = EngagementOutcome.ESCAPE_PLAYER_OUT_FIRST_LOSS;
421 lastOutcome = EngagementOutcome.MUTUAL_DESTRUCTION;
426 lastOutcome = EngagementOutcome.BATTLE_PLAYER_WIN_TOTAL;
432 lastOutcome = EngagementOutcome.ESCAPE_PLAYER_WIN_TOTAL;
438 lastOutcome = EngagementOutcome.ESCAPE_ENEMY_LOSS_TOTAL;
440 lastOutcome = EngagementOutcome.ESCAPE_ENEMY_SUCCESS;
446 lastOutcome = EngagementOutcome.BATTLE_ENEMY_WIN_TOTAL;
452 lastOutcome = EngagementOutcome.ESCAPE_ENEMY_WIN_TOTAL;
458 lastOutcome = EngagementOutcome.ESCAPE_PLAYER_LOSS_TOTAL;
460 lastOutcome = EngagementOutcome.ESCAPE_PLAYER_SUCCESS;
475 float time = dfm.getShip().getFullTimeDeployed();
477 if (time > maxTime) {
481 time -= dfm.getShip().getTimeDeployedUnderPlayerControl();
482 if (time <= 0)
continue;
484 PersonAPI person = dfm.getMember().getCaptain();
486 if (source ==
null)
continue;
490 OfficerEngagementData oed = data.getFleetMemberDeploymentData().get(dfm.getMember());
492 oed =
new OfficerEngagementData(source);
494 data.getFleetMemberDeploymentData().put(dfm.getMember(), oed);
496 time += dfm.getShip().getTimeDeployedUnderPlayerControl();
497 oed.timeDeployed += time;
501 OfficerEngagementData oed = data.getOfficerData().get(person);
503 oed =
new OfficerEngagementData(source);
505 data.getOfficerData().put(person, oed);
507 oed.timeDeployed += time;
509 data.setMaxTimeDeployed(data.getMaxTimeDeployed() + maxTime);
513 DataForEncounterSide otherData =
getDataFor(otherFleet);
515 if (otherData.isWonLastEngagement())
return PursueAvailability.LOST_LAST_ENGAGEMENT;
518 if (otherData.isDidEnoughToDisengage())
return PursueAvailability.TOOK_SERIOUS_LOSSES;
519 return PursueAvailability.AVAILABLE;
523 DataForEncounterSide otherData =
getDataFor(otherFleet);
524 if (otherData.isWonLastEngagement())
return DisengageHarryAvailability.LOST_LAST_ENGAGEMENT;
527 return DisengageHarryAvailability.AVAILABLE;
557 boolean printedAdjustmentText =
false;
569 RepActions action =
null;
582 if (knowsWhoPlayerIs && !lowImpact) {
583 action = RepActions.COMBAT_AGGRESSIVE;
585 action = RepActions.COMBAT_AGGRESSIVE_TOFF;
587 }
else if (playerWasAggressive) {
588 if (knowsWhoPlayerIs && !lowImpact) {
589 action = RepActions.COMBAT_NORMAL;
591 action = RepActions.COMBAT_NORMAL_TOFF;
599 if (!okToAdjustEnemy) action =
null;
601 Set<String> seen =
new HashSet<String>();
602 if (action !=
null) {
605 String factionId = enemy.getFaction().getId();
606 if (seen.contains(factionId))
continue;
609 printedAdjustmentText =
true;
614 action = RepActions.COMBAT_HELP_MINOR;
620 if (fleet.isPlayerFleet()) {
621 playerFP += member.getFleetPointCost();
623 allyFP += member.getFleetPointCost();
629 enemyFP += member.getFleetPointCost();
632 if (allyFP > enemyFP || !playerWon) {
633 action = RepActions.COMBAT_HELP_MINOR;
634 }
else if (allyFP < enemyFP * 0.5f) {
635 action = RepActions.COMBAT_HELP_CRITICAL;
637 action = RepActions.COMBAT_HELP_MAJOR;
648 }
else if (f < 0.1f) {
649 action = RepActions.COMBAT_HELP_MINOR;
652 if (action !=
null) {
655 action = RepActions.COMBAT_HELP_MINOR;
656 }
else if (totalDam < 20 && action == RepActions.COMBAT_HELP_CRITICAL) {
657 action = RepActions.COMBAT_HELP_MAJOR;
666 if (!okToAdjustAlly) action =
null;
674 if (ally.isPlayerFleet())
continue;
676 String factionId = ally.getFaction().getId();
677 if (seen.contains(factionId))
continue;
681 float threshold = 2f;
682 if (action == RepActions.COMBAT_HELP_MAJOR) {
684 }
else if (action == RepActions.COMBAT_HELP_CRITICAL) {
687 if (friendlyFPHull !=
null && friendlyFPHull > threshold) {
690 }
else if (action !=
null && playerSide.contains(ally)) {
693 printedAdjustmentText =
true;
699 if (okToAdjustAlly) {
700 boolean first =
true;
703 if (ally.isPlayerFleet())
continue;
705 String factionId = ally.getFaction().getId();
707 if (seen.contains(factionId))
continue;
711 float threshold = 2f;
712 if (action == RepActions.COMBAT_HELP_MAJOR) {
714 }
else if (action == RepActions.COMBAT_HELP_CRITICAL) {
717 if (friendlyFPHull !=
null && friendlyFPHull > threshold) {
718 if (first && ffText !=
null) {
724 printedAdjustmentText =
true;
725 }
else if (action !=
null && playerSide.contains(ally)) {
732 return printedAdjustmentText;
759 member.getStatus().resetAmmoState();
765 if (fleet.
getAI() !=
null &&
785 if (winners ==
null || losers ==
null)
return;
789 member.getStatus().resetAmmoState();
792 loser.getVelocity().set(0, 0);
793 if (loser.isPlayerFleet())
continue;
794 if (loser.isPlayerFleet()) loser.setNoEngaging(3f);
799 member.getStatus().resetAmmoState();
802 winner.getVelocity().set(0, 0);
803 if (winner.isPlayerFleet())
continue;
804 if (winner.isPlayerFleet()) winner.setNoEngaging(3f);
810 if (fleet.isPlayerFleet())
continue;
825 if (loser.getFleetData().getMembersListCopy().isEmpty()) {
827 loser.despawn(FleetDespawnReason.DESTROYED_BY_BATTLE,
battle);
832 if (winner.getFleetData().getMembersListCopy().isEmpty()) {
834 winner.despawn(FleetDespawnReason.DESTROYED_BY_BATTLE,
battle);
870 float loserDepDestroyed = 0f;
871 float loserDepLeft = 0f;
873 for (
FleetMemberAPI member : loserData.getRetreatedFromLastEngagement()) {
874 loserDepLeft += member.getDeploymentPointsCost();
876 for (
FleetMemberAPI member : loserData.getInReserveDuringLastEngagement()) {
877 loserDepLeft += member.getDeploymentPointsCost();
880 for (
FleetMemberAPI member : loserData.getDestroyedInLastEngagement()) {
881 loserDepDestroyed += member.getDeploymentPointsCost();
883 for (
FleetMemberAPI member : loserData.getDisabledInLastEngagement()) {
884 loserDepDestroyed += member.getDeploymentPointsCost();
886 for (
FleetMemberAPI member : loserData.getRetreatedFromLastEngagement()) {
887 if (member.isFighterWing()) {
889 if (dfm !=
null && dfm.
getMember() == member) {
891 float finalCR = deploymentCR;
893 if (deploymentCR > finalCR) {
895 float extraCraftLost = (deploymentCR - finalCR) / crPer;
897 if (extraCraftLost >= 1) {
898 loserDepDestroyed += Math.min(1f, extraCraftLost / wingSize) * member.getDeploymentPointsCost();
905 float totalRecovery = 0f;
907 for (
FleetMemberAPI member : winnerData.getDeployedInLastEngagement()) {
908 float dp = member.getDeploymentPointsCost();
909 float recoveryFraction = Math.max(0, (dp * 1.25f - loserDepDestroyed)) / dp;
912 if (loserDepDestroyed > loserDepLeft * 2f) {
913 recoveryFraction = Math.max(0, (dp * 0.75f - loserDepDestroyed)) / dp;
915 if (recoveryFraction > 1f) recoveryFraction = 1f;
916 if (loserDepDestroyed <= 0) recoveryFraction = 1f;
921 if (prevCR < deployCost) {
926 float recoveryAmount = Math.round(deployCost * recoveryFraction * 100f) / 100f;
928 recoveryAmount = member.getRepairTracker().getMaxCR() - member.getRepairTracker().getCR();
931 totalRecovery += recoveryAmount;
934 if (recoveryAmount <= 0)
continue;
937 member.getRepairTracker().applyCREvent(recoveryAmount,
"Post engagement recovery");
940 if (count <= 0)
return 0;
942 return Math.round(totalRecovery / count * 100f) / 100f;
953 DataForEncounterSide pursuer =
getDataFor(pursuingFleet);
954 DataForEncounterSide other =
getDataFor(otherFleet);
956 if (pursuitOption == PursuitOption.HARRY) {
960 float harryCost = deployCost * 1f;
961 member.getRepairTracker().applyCREvent(-harryCost,
"harried while disengaging");
977 lastOutcome != EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_WIN &&
978 lastOutcome != EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_LOSS &&
979 lastOutcome != EngagementOutcome.BATTLE_ENEMY_WIN &&
980 lastOutcome != EngagementOutcome.BATTLE_PLAYER_WIN;
987 lastOutcome != EngagementOutcome.BATTLE_ENEMY_WIN &&
988 lastOutcome != EngagementOutcome.BATTLE_PLAYER_WIN;
992 return lastOutcome == EngagementOutcome.BATTLE_PLAYER_WIN ||
993 lastOutcome == EngagementOutcome.BATTLE_PLAYER_WIN_TOTAL ||
994 lastOutcome == EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_WIN ||
995 lastOutcome == EngagementOutcome.PURSUIT_PLAYER_OUT_FIRST_WIN ||
996 lastOutcome == EngagementOutcome.ESCAPE_PLAYER_OUT_FIRST_WIN ||
997 lastOutcome == EngagementOutcome.ESCAPE_ENEMY_LOSS_TOTAL ||
998 lastOutcome == EngagementOutcome.ESCAPE_ENEMY_SUCCESS ||
999 lastOutcome == EngagementOutcome.ESCAPE_PLAYER_WIN ||
1000 lastOutcome == EngagementOutcome.ESCAPE_PLAYER_WIN_TOTAL;
1028 return lastOutcome == EngagementOutcome.BATTLE_PLAYER_WIN_TOTAL ||
1030 lastOutcome == EngagementOutcome.ESCAPE_ENEMY_LOSS_TOTAL ||
1031 lastOutcome == EngagementOutcome.ESCAPE_ENEMY_SUCCESS ||
1032 lastOutcome == EngagementOutcome.ESCAPE_PLAYER_WIN ||
1033 lastOutcome == EngagementOutcome.ESCAPE_PLAYER_WIN_TOTAL;
1088 public static enum EngageBoardableOutcome {
1097 float r = (float) Math.random();
1107 DataForEncounterSide attackerSide =
getDataFor(attackingFleet);
1108 attackerSide.changeEnemy(toBoard, Status.DISABLED);
1110 return EngageBoardableOutcome.DISABLED;
1112 DataForEncounterSide attackerSide =
getDataFor(attackingFleet);
1113 attackerSide.changeEnemy(toBoard, Status.DESTROYED);
1115 return EngageBoardableOutcome.DESTROYED;
1120 public static enum BoardingAttackType {
1122 LAUNCH_FROM_DISTANCE,
1124 public static enum BoardingOutcome {
1127 SUCCESS_TOO_DAMAGED,
1132 public static class BoardingResult {
1133 private BoardingOutcome outcome;
1137 private List<FleetMemberAPI> lostInSelfDestruct =
new ArrayList<FleetMemberAPI>();
1139 public BoardingOutcome getOutcome() {
1142 public List<FleetMemberAPI> getLostInSelfDestruct() {
1143 return lostInSelfDestruct;
1145 public void setOutcome(BoardingOutcome outcome) {
1146 this.outcome = outcome;
1148 public CrewCompositionAPI getAttackerLosses() {
1149 return attackerLosses;
1151 public void setAttackerLosses(CrewCompositionAPI attackerLosses) {
1152 this.attackerLosses = attackerLosses;
1154 public CrewCompositionAPI getDefenderLosses() {
1155 return defenderLosses;
1157 public void setDefenderLosses(CrewCompositionAPI defenderLosses) {
1158 this.defenderLosses = defenderLosses;
1160 public FleetMemberAPI getMember() {
1163 public void setMember(FleetMemberAPI member) {
1164 this.member = member;
1186 DataForEncounterSide attackerSide =
getDataFor(attacker);
1187 DataForEncounterSide defenderSide =
getDataFor(defender);
1192 float crewMult = 2f;
1193 float marineMult = 7f;
1197 attackerStr *= attackerMarineMult;
1200 float defenderStr = defenderCrew.
getCrew() * crewMult + defenderCrew.
getMarines() * marineMult;
1201 defenderStr *= defenderMarineMult;
1206 attackerStr *= 0.75f + 0.25f * rand.nextFloat();
1207 defenderStr *= 0.75f + 0.25f * rand.nextFloat();
1209 boolean attackerWin = attackerStr > defenderStr;
1210 boolean defenderWin = !attackerWin;
1212 BoardingResult result =
new BoardingResult();
1213 result.setMember(member);
1216 BoardingOutcome outcome = BoardingOutcome.SUCCESS;
1218 outcome = BoardingOutcome.SHIP_ESCAPED;
1224 result.setOutcome(outcome);
1228 result.getAttackerLosses().removeFromCargo(attacker.
getCargo());
1235 result.getAttackerLosses().removeFromCargo(attacker.
getCargo());
1245 attackerSide.changeEnemy(member, Status.CAPTURED);
1246 defenderSide.changeOwn(member, Status.CAPTURED);
1248 attackerSide.getInReserveDuringLastEngagement().add(member);
1249 defenderSide.getDestroyedInLastEngagement().remove(member);
1250 defenderSide.getDisabledInLastEngagement().remove(member);
1261 DataForEncounterSide attackerSide =
getDataFor(attacker);
1262 DataForEncounterSide defenderSide =
getDataFor(defender);
1266 float crewMult = 2f;
1267 float marineMult = 7f;
1269 Random rand =
new Random();
1274 for (
int i = 0; i < 100; i++) {
1276 attackerStr *= attackerMarineMult;
1279 float defenderStr = defenderCrew.
getCrew() * crewMult + defenderCrew.
getMarines() * marineMult;
1280 defenderStr *= defenderMarineMult;
1284 attackerStr *= 0.75f + 0.25f * rand.nextFloat();
1285 defenderStr *= 0.75f + 0.25f * rand.nextFloat();
1287 boolean attackerWin = attackerStr > defenderStr;
1288 if (attackerWin) wins++;
1297 result.getAttackerLosses().addAll(boardingParty);
1298 result.getAttackerLosses().multiplyBy((
float) Math.random() * 0.2f);
1303 float attackerStr,
float defenderStr) {
1305 if (attackerStr < 1) attackerStr = 1;
1306 if (defenderStr < 1) defenderStr = 1;
1308 float attackerExtraStr = 0f;
1309 if (attackerStr > defenderStr * cap) {
1310 attackerExtraStr = attackerStr - defenderStr * cap;
1311 attackerStr = defenderStr * cap;
1313 if (defenderStr > attackerStr * cap) {
1314 defenderStr = attackerStr * cap;
1317 float attackerLosses = defenderStr / (attackerStr + defenderStr);
1318 float defenderLosses = attackerStr / (attackerStr + defenderStr);
1320 if (attackerStr > defenderStr) {
1321 result.getAttackerLosses().addAll(boardingParty);
1322 result.getAttackerLosses().multiplyBy(attackerLosses * attackerStr / (attackerExtraStr + attackerStr));
1324 result.getDefenderLosses().multiplyBy(defenderLosses);
1326 result.getAttackerLosses().addAll(boardingParty);
1327 result.getAttackerLosses().multiplyBy(attackerLosses);
1329 result.getDefenderLosses().multiplyBy(defenderLosses);
1337 List<FleetMemberAPI> boardingTaskForce,
1339 BoardingResult result) {
1341 DataForEncounterSide attackerSide =
getDataFor(attacker);
1342 DataForEncounterSide defenderSide =
getDataFor(defender);
1344 attackerSide.changeEnemy(member, Status.DESTROYED);
1345 defenderSide.changeOwn(member, Status.DESTROYED);
1350 if (attackType == BoardingAttackType.SHIP_TO_SHIP) {
1353 float hull = fm.getStatus().getHullFraction();
1354 float hullDamageFactor = 0f;
1355 fm.getStatus().applyDamage(damage);
1356 if (fm.getStatus().getHullFraction() <= 0) {
1357 fm.getStatus().disable();
1359 attackerSide.addOwn(fm, Status.DESTROYED);
1362 attackerSide.getRetreatedFromLastEngagement().remove(fm);
1363 attackerSide.getInReserveDuringLastEngagement().remove(fm);
1364 attackerSide.getDeployedInLastEngagement().remove(fm);
1365 attackerSide.getDestroyedInLastEngagement().add(fm);
1367 result.getLostInSelfDestruct().add(fm);
1369 hullDamageFactor = 1f;
1371 float newHull = fm.getStatus().getHullFraction();
1372 float diff = hull - newHull;
1373 if (diff < 0) diff = 0;
1374 hullDamageFactor = diff;
1377 temp.
addAll(fm.getCrewComposition());
1378 float lossFraction =
computeLossFraction(fm,
null, fm.getStatus().getHullFraction(), hullDamageFactor);
1393 result.getAttackerLosses().addAll(total);
1398 DataForEncounterSide attackerSide =
getDataFor(attackingFleet);
1399 attackerSide.removeEnemyCasualty(toBoard);
1401 DataForEncounterSide defenderSide =
getDataFor(fleetItBelongsTo);
1402 defenderSide.removeOwnCasualty(toBoard);
1405 defenderSide.getDestroyedInLastEngagement().remove(toBoard);
1406 defenderSide.getDisabledInLastEngagement().remove(toBoard);
1407 defenderSide.getRetreatedFromLastEngagement().add(toBoard);
1432 List<FleetMemberAPI> result =
new ArrayList<FleetMemberAPI>();
1443 DataForEncounterSide winnerData =
getDataFor(winningFleet);
1444 DataForEncounterSide loserData =
getDataFor(otherFleet);
1447 List<FleetMemberData> enemyCasualties = winnerData.getEnemyCasualties();
1448 List<FleetMemberData> ownCasualties = winnerData.getOwnCasualties();
1449 List<FleetMemberData> all =
new ArrayList<FleetMemberData>();
1450 all.addAll(ownCasualties);
1451 Collections.sort(all,
new Comparator<FleetMemberData>() {
1452 public int compare(FleetMemberData o1, FleetMemberData o2) {
1471 List<FleetMemberData> enemy =
new ArrayList<FleetMemberData>(enemyCasualties);
1472 Collections.sort(enemy,
new Comparator<FleetMemberData>() {
1473 public int compare(FleetMemberData o1, FleetMemberData o2) {
1474 int result = o2.getMember().
getId().hashCode() - o1.getMember().
getId().hashCode();
1479 for (FleetMemberData curr : enemy) {
1481 switch (curr.getMember().getHullSpec().getHullSize()) {
1482 case CAPITAL_SHIP: base = 40f;
break;
1483 case CRUISER: base = 20f;
break;
1484 case DESTROYER: base = 10f;
break;
1485 case FRIGATE: base = 5f;
break;
1487 float w = curr.getMember().getUnmodifiedDeploymentPointsCost() / base;
1489 enemyPicker.
add(curr, w);
1491 List<FleetMemberData> sortedEnemy =
new ArrayList<FleetMemberData>();
1492 while (!enemyPicker.
isEmpty()) {
1497 all.addAll(sortedEnemy);
1505 int maxRecoverablePerType = 24;
1511 for (FleetMemberData data : all) {
1517 if (data.getStatus() != Status.DISABLED && data.getStatus() != Status.DESTROYED)
continue;
1519 boolean own = ownCasualties.contains(data);
1520 if (own && data.getMember().isAlly())
continue;
1527 if (data.getStatus() == Status.DESTROYED) mult = 0.5f;
1528 if (!own) mult *= playerContribMult;
1531 boolean useOfficerRecovery =
false;
1533 useOfficerRecovery = winnerData.getMembersWithOfficerOrPlayerAsOrigCaptain().contains(data.getMember());
1534 if (useOfficerRecovery) {
1539 boolean noRecovery =
false;
1551 boolean normalRecovery = !noRecovery &&
1553 boolean storyRecovery = !noRecovery && !normalRecovery;
1558 if (!own && !alwaysRec && (storyRecovery || normalRecovery) && shipRecProb < 1f) {
1564 float assumedAddedDmods = 3f;
1566 assumedAddedDmods = Math.min(assumedAddedDmods, 5 - dmods);
1568 float recoveredSoFar = 0f;
1570 else recoveredSoFar = result.size();
1572 if (random.nextFloat() < Math.min(max, (dmods + assumedAddedDmods) * per) + recoveredSoFar * perAlready) {
1579 if (!noRecovery && (normalRecovery || storyRecovery)) {
1583 String aiCoreId =
null;
1584 if (own && data.getMember().getCaptain() !=
null &&
1585 data.getMember().getCaptain().isAICore()) {
1586 aiCoreId = data.getMember().getCaptain().getAICoreId();
1593 boolean keepCaptain =
false;
1601 if (aiCoreId !=
null) {
1603 data.getMember().getCaptain().getMemoryWithoutUpdate().set(
1604 "$aiCoreIdForRecovery", aiCoreId);
1605 }
else if (!own && data.getMember().getCaptain() !=
null &&
1606 data.getMember().getCaptain().isAICore()) {
1607 aiCoreId = data.getMember().getCaptain().getAICoreId();
1609 data.getMember().getCaptain().getMemoryWithoutUpdate().set(
1610 "$aiCoreIdForPossibleRecovery", aiCoreId);
1617 variant = variant.
clone();
1624 data.getMember().setVariant(variant,
false,
true);
1626 boolean lessDmods =
false;
1627 if (!own && data.getStatus() != Status.DESTROYED && random.nextFloat() < probLessDModsOnNext) {
1629 probLessDModsOnNext *= lessDmodsOnNextMult;
1636 DModManager.reduceNextDmodsBy = 3;
1639 float probAvoidDmods =
1640 data.getMember().getStats().getDynamic().getMod(
1643 float probAcquireDmods =
1644 data.getMember().getStats().getDynamic().getMod(
1647 if (dModRandom.nextFloat() >= probAvoidDmods && dModRandom.nextFloat() < probAcquireDmods) {
1665 prepareShipForRecovery(data.getMember(), own,
true, !own && !retain, weaponProb, wingProb, salvageRandom);
1667 if (normalRecovery) {
1668 if (result.size() < maxRecoverablePerType) {
1669 result.add(data.getMember());
1671 }
else if (storyRecovery) {
1704 DataForEncounterSide winnerData =
null;
1705 DataForEncounterSide loserData =
null;
1707 if (context !=
null) {
1708 winnerData = context.
getDataFor(winningFleet);
1718 if (member.getStatus().getNumStatuses() <= 1) {
1719 member.getStatus().repairDisabledABit();
1738 float hull = (float) Math.random() * (maxHull - minHull) + minHull;
1739 if (hull < 0.01f) hull = 0.01f;
1740 if (hull > 1f) hull = 1f;
1741 member.getStatus().setHullFraction(hull);
1743 float cr = (float) Math.random() * (maxCR - minCR) + minCR;
1744 if (cr < 0 || member.isMothballed()) cr = 0;
1745 float max = member.getRepairTracker() ==
null ? 1f : member.getRepairTracker().getMaxCR();
1746 if (cr > max) cr = max;
1747 member.getRepairTracker().setCR(cr);
1749 if (winnerData !=
null) winnerData.getInReserveDuringLastEngagement().add(member);
1751 if (context !=
null) {
1757 member.setFleetCommanderForStats(
null,
null);
1769 if (winnerData !=
null) {
1770 winnerData.changeEnemy(member, Status.REPAIRED);
1771 winnerData.changeOwn(member, Status.REPAIRED);
1773 winnerData.getDestroyedInLastEngagement().remove(member);
1774 winnerData.getDisabledInLastEngagement().remove(member);
1777 if (loserData !=
null) {
1778 loserData.changeEnemy(member, Status.REPAIRED);
1779 loserData.changeOwn(member, Status.REPAIRED);
1781 loserData.getDestroyedInLastEngagement().remove(member);
1782 loserData.getDisabledInLastEngagement().remove(member);
1791 boolean retainAllHullmods,
boolean retainKnownHullmods,
boolean clearSMods,
1792 float weaponRetainProb,
float wingRetainProb, Random salvageRandom) {
1795 if (retainAllHullmods) {
1797 }
else if (retainKnownHullmods) {
1798 for (String modId :
new ArrayList<String>(variant.
getHullMods())) {
1810 for (String
id :
new ArrayList<String>(variant.
getSMods())) {
1817 List<String>
remove =
new ArrayList<String>();
1825 Random random =
new Random();
1826 if (salvageRandom !=
null) random = salvageRandom;
1830 if (random.nextFloat() > weaponRetainProb) {
1834 for (String slotId :
remove) {
1840 if (random.nextFloat() > wingRetainProb) {
1849 retainAllHullmods, retainKnownHullmods, clearSMods, weaponRetainProb, wingRetainProb, salvageRandom);
1853 for (
int i = 1; i < member.
getStatus().getNumStatuses(); i++) {
1854 if (random.nextFloat() > 0.5f) {
1861 for (
int i = 0; i < 10; i++) {
1872 boolean retainAllHullmods,
boolean retainKnownHullmods,
boolean clearSMods,
1873 float weaponRetainProb,
float wingRetainProb, Random salvageRandom) {
1876 if (moduleCurrent ==
null)
return;
1878 moduleCurrent = moduleCurrent.
clone();
1880 if (retainAllHullmods) {
1882 }
else if (retainKnownHullmods) {
1883 for (String modId :
new ArrayList<String>(moduleCurrent.
getHullMods())) {
1895 for (String
id :
new ArrayList<String>(moduleCurrent.
getSMods())) {
1903 List<String>
remove =
new ArrayList<String>();
1906 if (salvageRandom !=
null) random = salvageRandom;
1909 if (random.nextFloat() > weaponRetainProb) {
1913 for (String slotId :
remove) {
1919 if (random.nextFloat() > wingRetainProb) {
1931 DataForEncounterSide sideOne =
sideData.get(0);
1932 DataForEncounterSide sideTwo =
sideData.get(1);
1934 gainXP(sideOne, sideTwo);
1936 gainXP(sideTwo, sideOne);
1941 float max = data.getMaxTimeDeployed();
1942 if (max < 1) max = 1;
1943 float num = data.getOfficerData().size();
1944 if (num < 1) num = 1;
1945 for (
PersonAPI person : data.getOfficerData().keySet()) {
1946 OfficerEngagementData oed = data.getOfficerData().get(person);
1947 if (oed.sourceFleet ==
null || !oed.sourceFleet.
isPlayerFleet())
continue;
1950 if (od ==
null)
continue;
1952 float f = oed.timeDeployed / max;
1989 if (member.getOwner() != 0)
continue;
1996 DamageToFleetMember damage = dealt.getDamageTo(target);
1997 float maxHull = target.getStats().getHullBonus().computeEffective(target.getHullSpec().getHitpoints());
1998 if (maxHull <= 0)
continue;
1999 if (target.isFighterWing()) {
2000 maxHull *= target.getNumFightersInWing();
2003 float currDam = Math.min(damage.hullDamage, maxHull) / maxHull * (float) target.getFleetPointCost();
2004 if (target.getOwner() == 1) {
2006 boolean ally = member.isAlly();
2007 if (ally && fleet !=
null &&
2016 }
else if (!member.isAlly() && target.isAlly() && !target.isFighterWing()) {
2019 if (fleet !=
null) {
2020 float curr = currDam;
2042 if (
battle ==
null)
return 1f;
2047 boolean hasAllies =
false;
2048 boolean startedWithAllies =
false;
2053 if (startedWithAllies) {
2062 protected void gainXP(DataForEncounterSide side, DataForEncounterSide otherSide) {
2065 for (FleetMemberData data : side.getOwnCasualties()) {
2066 if (data.getStatus() == Status.DISABLED ||
2067 data.getStatus() == Status.DESTROYED) {
2070 bonusXP += bonus[1] * bonus[0];
2073 if (bonusXP > 0 && points > 0) {
2085 for (FleetMemberData data : otherSide.getOwnCasualties()) {
2086 float fp = data.getMember().getFleetPointCost();
2097 fp *= 1f + data.getMember().getCaptain().getStats().getLevel() / 5f;
2101 float xp = (float) fpTotal * 250;
2104 float difficultyMult = Math.max(1f,
difficulty);
2105 xp *= difficultyMult;
2133 DataForEncounterSide sideOne =
sideData.get(0);
2134 DataForEncounterSide sideTwo =
sideData.get(1);
2136 DataForEncounterSide player = sideOne;
2137 DataForEncounterSide enemy = sideTwo;
2143 float fpDestroyed = 0;
2144 for (FleetMemberData data : enemy.getOwnCasualties()) {
2145 float fp = data.getMember().getFleetPointCost();
2146 fp *= 1f + data.getMember().getCaptain().getStats().getLevel() / 5f;
2150 for (FleetMemberData data : player.getOwnCasualties()) {
2151 if (data.getMember().isAlly())
continue;
2152 float fp = data.getMember().getFleetPointCost();
2153 fp *= 1f + data.getMember().getCaptain().getStats().getLevel() / 5f;
2157 float fpInFleet = 0f;
2159 float fp = member.getFleetPointCost();
2160 fp *= 1f + member.getCaptain().getStats().getLevel() / 5f;
2170 float prob = fpDestroyed / (Math.max(1f, fpInFleet));
2174 if (curr >= max) prob *= 0.5f;
2175 if (prob > maxProb) prob = maxProb;
2178 if (salvageRandom !=
null) {
2179 random = salvageRandom;
2186 if (random.nextFloat() < prob) {
2195 public void generateLoot(List<FleetMemberAPI> recoveredShips,
boolean withCredits) {
2207 private Random salvageRandom =
null;
2209 return salvageRandom;
2212 this.salvageRandom = salvageRandom;
2222 if (winner ==
null || loser ==
null)
return;
2224 float adjustedFPSalvage = 0;
2227 Random origSalvageRandom = salvageRandom;
2228 long extraSeed = 1340234324325L;
2229 if (origSalvageRandom !=
null) extraSeed = origSalvageRandom.nextLong();
2231 for (FleetMemberData data : winner.getEnemyCasualties()) {
2232 if (data.getStatus() == Status.REPAIRED) {
2240 if (origSalvageRandom !=
null) {
2241 String sig = data.getMember().getHullId();
2242 if (data.getMember().getVariant() !=
null) {
2243 for (
WeaponGroupSpec spec : data.getMember().getVariant().getWeaponGroups()) {
2244 for (String slotId : spec.getSlots()) {
2245 String w = data.getMember().getVariant().getWeaponId(slotId);
2246 if (w !=
null) sig += w;
2250 if (loser !=
null && loser.getFleet() !=
null && loser.getFleet().
getFleetData() !=
null) {
2252 if (members !=
null) {
2253 int index = members.indexOf(data.getMember());
2259 long seed = sig.hashCode() * 143234234234L * extraSeed;
2260 salvageRandom =
new Random(seed);
2264 float mult =
getSalvageMult(data.getStatus()) * playerContribMult;
2265 lootWeapons(data.getMember(), data.getMember().getVariant(),
false, mult,
false);
2266 lootHullMods(data.getMember(), data.getMember().getVariant(), mult);
2267 lootWings(data.getMember(), data.getMember().getVariant(),
false, mult);
2268 adjustedFPSalvage += (float) data.getMember().getFleetPointCost() * mult;
2271 for (FleetMemberData data : winner.getOwnCasualties()) {
2272 if (data.getMember().isAlly())
continue;
2274 if (data.getStatus() == Status.CAPTURED || data.getStatus() == Status.REPAIRED) {
2288 lootWeapons(data.getMember(), data.getMember().getVariant(),
true, mult,
false);
2289 lootWings(data.getMember(), data.getMember().getVariant(),
true, mult);
2291 adjustedFPSalvage += (float) data.getMember().getFleetPointCost() * mult;
2294 if (recoveredShips !=
null) {
2297 adjustedFPSalvage += (float) member.getFleetPointCost() * mult;
2301 salvageRandom = origSalvageRandom;
2304 Random resetSalvageRandomTo =
null;
2305 Random forRandomDrops =
null;
2306 Random forCargoDrops =
null;
2309 if (salvageRandom !=
null) {
2310 random = salvageRandom;
2311 resetSalvageRandomTo =
Misc.
getRandom(random.nextLong(), 11);
2326 float creditsFraction = minCreditsFraction + (maxCreditsFraction - minCreditsFraction) * random.nextFloat();
2327 creditsFraction *= playerContribMult;
2339 maxSalvageValue *= valueMultFleet + valueModShips;
2341 creditsLooted = Math.round(maxSalvageValue * creditsFraction);
2345 float salvageValue = 0f;
2352 while (salvageValue < maxSalvageValue) {
2353 String commodityId = lootPicker.
pick();
2354 if (commodityId ==
null)
break;
2365 if (fuelMult > 1f) {
2366 loot.
addFuel((
int) Math.round(fuel * (fuelMult - 1f)));
2369 if (
getBattle().getSnapshotSideFor(loser.getFleet()) ==
null)
return;
2371 List<DropData> dropRandom =
new ArrayList<DropData>();
2372 List<DropData> dropValue =
new ArrayList<DropData>();
2375 dropRandom.addAll(other.getDropRandom());
2376 dropValue.addAll(other.getDropValue());
2377 other.getDropRandom().clear();
2378 other.getDropValue().clear();
2389 if (forRandomDrops !=
null) {
2390 random = forRandomDrops;
2397 if (forCargoDrops !=
null) {
2398 salvageRandom = forCargoDrops;
2402 if (resetSalvageRandomTo !=
null) {
2403 salvageRandom = resetSalvageRandomTo;
2425 protected static class LootableCargoStack {
2429 this.source = source;
2434 protected static class LossFraction {
2435 public float maxCargo;
2436 public float maxFuel;
2437 public float lostCargo;
2438 public float lostFuel;
2446 if (winner ==
null || loser ==
null)
return;
2454 if (salvageRandom !=
null) random = salvageRandom;
2458 Map<CargoAPI, LossFraction> fractions =
new HashMap<CargoAPI, LossFraction>();
2460 float lostCargo = 0f;
2461 float lostFuel = 0f;
2463 float totalLoss = 0f;
2464 for (FleetMemberData data : winner.getEnemyCasualties()) {
2474 if (orig !=
null) source = orig;
2476 if (source !=
null) {
2478 LossFraction loss = fractions.get(c);
2480 loss =
new LossFraction();
2483 fractions.put(c, loss);
2486 loss.lostCargo += data.getMember().getCargoCapacity();
2487 loss.lostFuel += data.getMember().getFuelCapacity();
2489 loss.maxCargo += data.getMember().getCargoCapacity();
2490 loss.maxFuel += data.getMember().getFuelCapacity();
2492 totalLoss += loss.maxCargo + loss.maxFuel;
2494 lostCargo += data.getMember().getCargoCapacity();
2495 lostFuel += data.getMember().getFuelCapacity();
2497 maxCargo += data.getMember().getCargoCapacity();
2498 maxFuel += data.getMember().getFuelCapacity();
2500 totalLoss += maxCargo + maxFuel;
2506 if (totalLoss <= 0) {
2510 if (maxCargo < 1) maxCargo = 1;
2511 if (maxFuel < 1) maxFuel = 1;
2517 recoveryFraction *= playerContribMult;
2520 float cargoFractionLost = lostCargo / maxCargo;
2521 float fuelFractionLost = lostFuel / maxFuel;
2522 if (lostCargo > maxCargo) cargoFractionLost = 1f;
2523 if (lostFuel > maxFuel) fuelFractionLost = 1f;
2527 if (losers ==
null)
return;
2529 List<LootableCargoStack> stacks =
new ArrayList<LootableCargoStack>();
2532 stacks.add(
new LootableCargoStack(curr.getCargo(), stack));
2536 for (LootableCargoStack stack : stacks) {
2537 if (stack.stack.isNull())
continue;
2538 if (stack.stack.isPersonnelStack())
continue;
2539 if (stack.stack.getSize() < 1)
continue;
2541 float actualCargoFractionLost = cargoFractionLost;
2542 float actualFuelFractionLost = fuelFractionLost;
2543 LossFraction loss = fractions.get(stack.source);
2545 actualCargoFractionLost = loss.lostCargo / loss.maxCargo;
2546 actualFuelFractionLost = loss.lostFuel / loss.maxFuel;
2547 if (loss.lostCargo > loss.maxCargo) actualCargoFractionLost = 1f;
2548 if (loss.lostFuel > loss.maxFuel) actualFuelFractionLost = 1f;
2552 if (takingFromPlayer) {
2553 if (stack.stack.isSpecialStack())
continue;
2554 if (stack.stack.isCommodityStack()) {
2564 if (stack.stack.isFuelStack()) {
2565 numLost = actualFuelFractionLost * stack.stack.getSize();
2566 numTaken = Math.round(numLost * (0.5f + random.nextFloat() * 0.5f));
2568 numLost = actualCargoFractionLost * stack.stack.getSize();
2569 numTaken = Math.round(numLost * (0.5f + random.nextFloat() * 0.5f));
2573 if (random.nextFloat() < numLost) {
2581 if (numLost <= 0)
continue;
2583 stack.stack.add(-numLost);
2584 if (numTaken * recoveryFraction >= 1) {
2585 loot.
addItems(stack.stack.getType(), stack.stack.getData(), numTaken * recoveryFraction);
2590 if (fleet.isPlayerFleet()) {
2591 fleet.getCargo().sort();
2603 if (variant ==
null)
return;
2606 if (salvageRandom !=
null) random = salvageRandom;
2613 if (random.nextFloat() < pItem && random.nextFloat() < mult) {
2617 boolean addToLoot =
true;
2635 if (random.nextFloat() < p && random.nextFloat() < mult) {
2651 if (module ==
null)
continue;
2658 if (variant ==
null)
return;
2661 if (salvageRandom !=
null) random = salvageRandom;
2674 if (!alreadyStripped) {
2675 if (random.nextFloat() > mult)
continue;
2676 if (random.nextFloat() > p)
continue;
2688 if (module ==
null)
continue;
2695 if (variant ==
null)
return;
2702 if (own && !lootingModule && member.
getCaptain() !=
null &&
2717 if (salvageRandom !=
null) random = salvageRandom;
2719 String coreIdOverride =
null;
2724 if (!own && !lootingModule &&
2728 if (coreIdOverride !=
null) {
2729 cid = coreIdOverride;
2746 if (prob > 0 && random.nextFloat() < prob) {
2764 Set<String>
remove =
new HashSet<String>();
2770 if (weaponId ==
null)
continue;
2782 if (
remove.contains(slotId))
continue;
2784 if (!alreadyStripped) {
2785 if (random.nextFloat() > mult)
continue;
2786 if (random.nextFloat() > p)
continue;
2802 if (module ==
null)
continue;
2817 if (winner ==
null || loser ==
null)
return;
2822 picker.
add(curr, curr.getFleetPoints());
2825 if (stack.isNull() || stack.isFuelStack())
continue;
2828 if (pick ==
null)
break;
2832 if (spaceLeft <= 0) {
2837 float spacePerUnit = stack.getCargoSpacePerUnit();
2838 float maxUnits = (int) (spaceLeft / spacePerUnit);
2839 if (maxUnits > stack.getSize()) maxUnits = stack.getSize();
2840 maxUnits = Math.round(maxUnits * (Math.random() * 0.5f + 0.5f));
2841 winnerCargo.
addItems(stack.getType(), stack.getData(), maxUnits);
2846 picker.
add(curr, curr.getFleetPoints());
2849 if (stack.isNull() || !stack.isFuelStack())
continue;
2852 if (pick ==
null)
break;
2856 if (spaceLeft <= 0) {
2861 float spacePerUnit = stack.getCargoSpacePerUnit();
2862 float maxUnits = (int) (spaceLeft / spacePerUnit);
2863 if (maxUnits > stack.getSize()) maxUnits = stack.getSize();
2864 maxUnits = Math.round(maxUnits * (Math.random() * 0.5f + 0.5f));
2865 winnerCargo.
addItems(stack.getType(), stack.getData(), maxUnits);
2895 Set<CampaignFleetAPI> fleetsWithDecks =
new HashSet<CampaignFleetAPI>();
2898 if (curr.isMothballed())
continue;
2899 if (curr.getNumFlightDecks() > 0) {
2905 if (curr.isMothballed())
continue;
2906 if (curr.getNumFlightDecks() > 0) {
2912 if (curr.isMothballed())
continue;
2913 if (curr.getNumFlightDecks() > 0) {
2918 List<FleetMemberAPI> saved =
new ArrayList<FleetMemberAPI>();
2922 if (curr.isFighterWing()) {
2931 List<FleetMemberAPI> toRepair =
new ArrayList<FleetMemberAPI>();
2936 if (curr.isFighterWing()) {
2938 curr.getStatus().repairFully();
2940 curr.getStatus().repairFullyNoNewFighters();
2973 boolean wonBattle = result.
isWinner();
2981 List<FleetMemberAPI> applyDeployCostTo =
new ArrayList<FleetMemberAPI>(result.
getDeployed());
2988 member.getRepairTracker().applyCREvent(-1f * mult,
"disabled in combat");
2991 applyDeployCostTo.add(member);
3001 member.getRepairTracker().applyCREvent(-1f * mult,
"disabled in combat");
3004 applyDeployCostTo.add(member);
3010 if (member.isFighterWing()) {
3011 member.getRepairTracker().applyCREvent(-deployCost,
"wing deployed in combat");
3013 member.getRepairTracker().applyCREvent(-deployCost,
"deployed in combat");
3023 if (member.isFighterWing()) {
3024 member.getRepairTracker().applyCREvent(-deployCost,
"wing deployed in combat");
3026 member.getRepairTracker().applyCREvent(-deployCost,
"deployed in combat");
3032 float retreatCost = deployCost * retreatLossMult;
3033 if (retreatCost > 0) {
3034 member.getRepairTracker().applyCREvent(-retreatCost,
"retreated from lost engagement");
3064 if (dfm ==
null)
return;
3086 if (cr > endOfCombatCR) {
3098 float hullDamageCRLoss = hullDamageFraction * hMult;
3100 if (hullDamageCRLoss > 0) {
3108 if (instaRepairFraction > 0) {
3117 float totalDisabled = 0f;
3120 if (maxOP <= 1) maxOP = 1;
3126 totalDisabled += maxOP * eMult;
3129 float damageBasedCRLoss = Math.min(1f, totalDisabled / maxOP);
3130 if (damageBasedCRLoss > 0) {
3134 float missileReloadOP = 0f;
3136 if (w.getType() == WeaponType.MISSILE && w.usesAmmo()) {
3137 missileReloadOP += (1f - (float) w.getAmmo() / (
float) w.getMaxAmmo()) * w.getSpec().getOrdnancePointCost(stats, ship.
getVariant().
getStatsForOpCosts()) * mMult;
3141 float missileReloadLoss = Math.min(1f, missileReloadOP / maxOP);
3142 if (missileReloadLoss > 0) {
3179 if (member ==
null && hullFraction == 0) {
3180 return (0.75f + (
float) Math.random() * 0.25f);
3186 float extraLossMult = hullDamage;
3188 if (dfm !=
null && dfm.
getMember() == member) {
3194 float extraCraftLost = (cr - finalCR) / crPer;
3196 if (extraCraftLost >= 1) {
3197 extraLossMult = hullDamage + extraCraftLost / wingSize;
3205 float extraFromFighters = 0f;
3208 if (dfm !=
null && dfm.
getMember() == member) {
3209 float craftCrewLoss = 0;
3211 if (bay.getWing() ==
null || bay.getWing().getLeader() ==
null)
continue;
3212 float baseCrew = bay.getWing().getLeader().getHullSpec().getMinCrew();
3213 float perCraft = bay.getWing().getLeader().getMutableStats().getMinCrewMod().computeEffective(baseCrew);
3215 craftCrewLoss += perCraft * bay.getNumLost();
3219 craftCrewLoss *= baseLossFraction;
3222 if (memberCrew > 0) {
3223 float threshold = memberCrew * 0.33f;
3225 float actualLost = 0f;
3228 float curr = Math.min(craftCrewLoss, threshold);
3229 craftCrewLoss -= curr;
3235 }
while (craftCrewLoss > 0);
3237 extraFromFighters = actualLost / memberCrew;
3243 if (hullFraction == 0) {
3258 boolean wonBattle = result.
isWinner();
3264 List<FleetMemberAPI> all =
new ArrayList<FleetMemberAPI>();
3272 member.getStatus().resetDamageTaken();
3283 float playerCapacityLost = 0f;
3289 float hullDamage = member.getStatus().getHullDamageTaken();
3290 float hullFraction = member.getStatus().getHullFraction();
3291 member.getStatus().resetDamageTaken();
3306 if (playerInvolved &&
3315 playerCapacityLost += member.getMaxCrew();
3331 float lost = c.
getCrew() * f1;
3337 playerCapacityLost += member.getMaxCrew() * f1;
3353 if (playerFleet !=
null) {
3363 float total = totalCrew + marines + recoverableTotal;
3364 if (maxCrew + playerCapacityLost > 0) {
3365 total *= playerCapacityLost / (maxCrew + playerCapacityLost);
3372 if (total > maxCrew) {
3374 float toLose = total - maxCrew;
3377 recoverable.
transfer(Math.min(recoverableTotal, toLose),
null);
3378 toLose -= recoverableTotal;
3379 total -= recoverableTotal;
3381 if (toLose > 0 && total > 0) {
3385 crewLosses.
addCrew((
int)Math.ceil(crew / total * toLose));
3386 crewLosses.
addMarines((
int)Math.ceil(marines / total * toLose));
3403 DataForEncounterSide data =
getDataFor(fleet);
3444 float scorePlayer = 0f;
3445 float scoreEnemy = 0f;
3447 float officerBase = 30;
3448 float officerPerLevel = 15;
3450 float baseMult = 2f;
3451 float dModMult = 0.9f;
3454 if (member.isMothballed())
continue;
3455 float mult = baseMult;
3456 if (member.isStation()) mult *= 1f;
3457 else if (member.isCivilian()) mult *= 0.25f;
3458 if (member.getCaptain() !=
null && !member.getCaptain().isDefault()) {
3459 scoreEnemy += officerBase + officerPerLevel * Math.max(1f, member.getCaptain().getStats().getLevel());
3462 for (
int i = 0; i < dMods; i++) {
3474 scoreEnemy += member.getFleetPointCost() * mult;
3478 float maxPlayserShipScore = 0f;
3480 officerBase *= 0.5f;
3481 officerPerLevel *= 0.5f;
3482 Set<PersonAPI> seenOfficers =
new HashSet<PersonAPI>();
3483 int unofficeredShips = 0;
3485 if (member.isMothballed())
continue;
3486 float mult = baseMult;
3487 if (member.isStation()) mult *= 1f;
3488 else if (member.isCivilian()) mult *= 0.25f;
3489 if (member.getCaptain() !=
null && !member.getCaptain().isDefault()) {
3490 scorePlayer += officerBase + officerPerLevel * Math.max(1f, member.getCaptain().getStats().getLevel());
3491 seenOfficers.add(member.getCaptain());
3492 }
else if (!member.isCivilian()) {
3496 for (
int i = 0; i < dMods; i++) {
3500 float currShipBaseScore = member.getFleetPointCost() * mult;
3501 scorePlayer += currShipBaseScore;
3503 maxPlayserShipScore = Math.max(maxPlayserShipScore, currShipBaseScore);
3511 if (seenOfficers.contains(od.getPerson()))
continue;
3512 if (od.getPerson().isPlayer())
continue;
3513 if (unofficeredShips <= 0)
break;
3515 scorePlayer += officerBase + officerPerLevel * Math.max(1f, od.getPerson().getStats().getLevel());
3518 scorePlayer = Math.max(scorePlayer, Math.min(scoreEnemy * 0.5f, maxPlayserShipScore * 6f));
3520 if (scorePlayer < 1) scorePlayer = 1;
3521 if (scoreEnemy < 1) scoreEnemy = 1;
static SettingsAPI getSettings()
static FactoryAPI getFactory()
static SectorAPI getSector()
Map< FleetMemberAPI, DealtByFleetMember > getDealt()
void add(CombatDamageData other)
static void reportExtraSalvageShown(SectorEntityToken entity)
float computeEffective(float baseValue)
static void addDMods(FleetMemberData data, boolean own, CampaignFleetAPI recoverer, Random random)
static boolean setDHull(ShipVariantAPI variant)
static int getNumDMods(ShipVariantAPI variant)
static boolean ALLOW_KNOWN_HULLMOD_DROPS
List< FleetMemberAPI > getRecoverableShips(BattleAPI battle, CampaignFleetAPI winningFleet, CampaignFleetAPI otherFleet)
boolean playerOnlyRetreated
void lootWings(FleetMemberAPI member, ShipVariantAPI variant, boolean own, float mult)
float computeLossFraction(FleetMemberAPI member, EngagementResultForFleetAPI result, float hullFraction, float hullDamage)
float performPostVictoryRecovery(EngagementResultForFleetAPI winnerResult, EngagementResultForFleetAPI loserResult)
void generateLoot(List< FleetMemberAPI > recoveredShips, boolean withCredits)
void addPotentialOfficer()
boolean engagedInActualBattle
boolean didPlayerWinMostRecentBattleOfEncounter()
float getSalvageMult(Status status)
void applyShipLosses(EngagementResultAPI result)
void tallyOfficerTime(DataForEncounterSide data, EngagementResultForFleetAPI result)
void setNoHarryBecauseOfStation(boolean noHarryBecauseOfStation)
void applyCREffect(EngagementResultForFleetAPI result)
void gainOfficerXP(DataForEncounterSide data, float xp)
void setAllyFPHullDamageToEnemies(float allyFPHullDamageToEnemies)
void setSalvageRandom(Random salvageRandom)
static final float ENGAGE_DISABLE_CHANCE
void setTextPanelForXPGain(TextPanelAPI textPanelForXPGain)
DataForEncounterSide getLoserData()
void lootHullMods(FleetMemberAPI member, ShipVariantAPI variant, float mult)
boolean adjustPlayerReputation(InteractionDialogAPI dialog, String ffText)
boolean wasLastEngagementEscape()
List< FleetMemberAPI > recoverableShips
float getCargoLootMult(Status status)
float playerFPHullDamageToEnemies
Map< FleetMemberAPI, CampaignFleetAPI > origSourceForRecoveredShips
void setDifficulty(float difficulty)
void applyPursuitOption(CampaignFleetAPI pursuingFleet, CampaignFleetAPI otherFleet, PursuitOption pursuitOption)
static final float ENGAGE_DESTROY_CHANCE
Map< FactionAPI, Float > playerFPHullDamageToAlliesByFaction
void applyAfterBattleEffectsIfThereWasABattle()
float getAllyFPHullDamageToEnemies()
boolean isOtherFleetHarriedPlayer()
float computePlayerContribFraction()
boolean isNoHarryBecauseOfStation()
CampaignFleetAPI getWinner()
boolean isEngagedInActualBattle()
void gainXP(DataForEncounterSide side, DataForEncounterSide otherSide)
static final float DOCK_SUCCESS_CHANCE
boolean playerDidSeriousDamage
float performPostEngagementRecoveryBoth(EngagementResultAPI result)
boolean didPlayerWinEncounterOutright()
boolean otherFleetHarriedPlayer
BoardingResult boardShip(FleetMemberAPI member, CampaignFleetAPI attacker, CampaignFleetAPI defender)
static void prepareModuleForRecovery(FleetMemberAPI member, String moduleSlotId, boolean retainAllHullmods, boolean retainKnownHullmods, boolean clearSMods, float weaponRetainProb, float wingRetainProb, Random salvageRandom)
void setOtherFleetHarriedPlayer(boolean otherFleetHarriedPlayer)
void setComputedDifficulty(boolean computedDifficulty)
void updateDeployedMap(EngagementResultForFleetAPI result)
List< FleetMemberAPI > getStoryRecoverableShips()
void recoverCrew(CampaignFleetAPI fleet)
float computeBattleDifficulty()
float getBoardingSuccessPercent(FleetMemberAPI member, CampaignFleetAPI attacker, CampaignFleetAPI defender)
static final float ENGAGE_ESCAPE_CHANCE
static void prepareShipForRecovery(FleetMemberAPI member, boolean retainAllHullmods, boolean retainKnownHullmods, boolean clearSMods, float weaponRetainProb, float wingRetainProb, Random salvageRandom)
boolean alreadyAdjustedRep
DataForEncounterSide getDataFor(CampaignFleetAPI participantOrCombined)
EngagementOutcome lastOutcome
static final float CIV_SELF_DESTRUCT_CHANCE
static void recoverShips(List< FleetMemberAPI > ships, FleetEncounterContext context, CampaignFleetAPI winningFleet, CampaignFleetAPI otherFleet)
Random getSalvageRandom()
void computeMissedLaunchLosses(BoardingResult result, CrewCompositionAPI boardingParty)
Map< FleetMemberAPI, Float > preEngagementCRForWinner
float getSalvageValueModPlayerShips()
PursueAvailability getPursuitAvailability(CampaignFleetAPI fleet, CampaignFleetAPI otherFleet)
void clearNoSourceMembers(EngagementResultForFleetAPI result)
void computeCrewLossFromBoarding(BoardingResult result, FleetMemberAPI member, CrewCompositionAPI boardingParty, float attackerStr, float defenderStr)
float performPostVictoryRecovery(EngagementResultAPI result)
void handleCargoLooting(List< FleetMemberAPI > recoveredShips, boolean takingFromPlayer)
void setAutoresolve(boolean isAutoresolve)
void applyShipLosses(EngagementResultForFleetAPI result)
TextPanelAPI textPanelForXPGain
boolean hasWinnerAndLoser()
static final float LAUNCH_SUCCESS_CHANCE
boolean canOutrunOtherFleet(CampaignFleetAPI fleet, CampaignFleetAPI other)
void applyBoardingSelfDestruct(FleetMemberAPI member, CrewCompositionAPI boardingParty, BoardingAttackType attackType, List< FleetMemberAPI > boardingTaskForce, CampaignFleetAPI attacker, CampaignFleetAPI defender, BoardingResult result)
void applyExtendedCRLossIfNeeded(EngagementResultForFleetAPI result, FleetMemberAPI member)
void applyCrewLosses(EngagementResultAPI result)
boolean isEngagedInHostilities()
EngageBoardableOutcome engageBoardableShip(FleetMemberAPI toBoard, CampaignFleetAPI fleetItBelongsTo, CampaignFleetAPI attackingFleet)
void setEngagedInActualBattle(boolean engagedInActualBattle)
void computeFPHullDamage()
boolean isComputedDifficulty()
void setPlayerFPHullDamageToEnemies(float playerFPHullDamageToEnemies)
float playerFPHullDamageToAllies
CombatDamageData runningDamageTotal
boolean engagedInHostilities
boolean computedDifficulty
void applyResultToFleets(EngagementResultAPI result)
boolean noHarryBecauseOfStation
CampaignFleetAPI getLoser()
List< DataForEncounterSide > sideData
TextPanelAPI getTextPanelForXPGain()
boolean adjustPlayerReputation(InteractionDialogAPI dialog, String ffText, boolean okToAdjustAlly, boolean okToAdjustEnemy)
static final float SELF_DESTRUCT_CHANCE
List< FleetMemberAPI > storyRecoverableShips
DataForEncounterSide getWinnerData()
EngagementOutcome getLastEngagementOutcome()
DisengageHarryAvailability getDisengageHarryAvailability(CampaignFleetAPI fleet, CampaignFleetAPI otherFleet)
float getPlayerFPHullDamageToEnemies()
void fixFighters(EngagementResultForFleetAPI result)
float getDeployCost(FleetMemberAPI member)
void generatePlayerLoot(List< FleetMemberAPI > recoveredShips, boolean withCredits)
float allyFPHullDamageToEnemies
void calculateAndApplyCrewLosses(EngagementResultForFleetAPI result, boolean playerInvolved)
static final float LAUNCH_CLEAN_ESCAPE_CHANCE
void lootWeapons(FleetMemberAPI member, ShipVariantAPI variant, boolean own, float mult, boolean lootingModule)
void setBattle(BattleAPI battle)
boolean didPlayerWinLastEngagement()
void processEngagementResults(EngagementResultAPI result)
void letBoardableGo(FleetMemberAPI toBoard, CampaignFleetAPI fleetItBelongsTo, CampaignFleetAPI attackingFleet)
void setEngagedInHostilities(boolean engagedInHostilities)
float computeRecoverableFraction(FleetMemberAPI member, EngagementResultForFleetAPI result, float hullFraction, float hullDamage)
static HullModItemManager getInstance()
void giveBackAllItems(FleetMemberAPI member)
static float getAdjustedGantryModifierForPostCombatSalvage(CampaignFleetAPI fleet)
static final String TAG_NO_LOSS_FROM_COMBAT
static final String HEAVY_MACHINERY
static final String SUPPLIES
static final String METALS
static final String PLAYER
static final String MEMORY_KEY_NO_SHIP_RECOVERY
static final String SALVAGE_SEED
static final String MEMORY_KEY_LOW_REP_IMPACT
static final String MEMORY_KEY_NO_REP_IMPACT
static final String ENEMY_WING_RECOVERY_MOD
static final String INDIVIDUAL_SHIP_RECOVERY_MOD
static final String RECOVERED_HULL_MIN
static final String FUEL_SALVAGE_VALUE_MULT_FLEET
static final String RECOVERED_HULL_MAX
static final String RECOVERED_CR_MAX
static final String OWN_WING_RECOVERY_MOD
static final String DMOD_AVOID_PROB_MOD
static final String INSTA_REPAIR_FRACTION
static final String OWN_WEAPON_RECOVERY_MOD
static final String SHIP_DMOD_REDUCTION
static final String DMOD_ACQUIRE_PROB_MOD
static final String BATTLE_SALVAGE_MULT_FLEET
static final String FIGHTER_CREW_LOSS_MULT
static final String RECOVERED_CR_MIN
static final String HULL_DAMAGE_CR_LOSS
static final String ENEMY_WEAPON_RECOVERY_MOD
static CargoAPI generateSalvage(Random random, float valueMult, float overallMult, float fuelMult, List< DropData > dropValue, List< DropData > dropRandom)
static CargoAPI getCombinedExtraSalvage(Map< String, MemoryAPI > memoryMap)
static void clearExtraSalvage(Map< String, MemoryAPI > memoryMap)
static boolean isTutorialInProgress()
static int getMaxOfficers(CampaignFleetAPI fleet)
static Random getRandom(long seed, int level)
static float[] getBonusXPForScuttling(FleetMemberAPI member)
static boolean isShipRecoverable(FleetMemberAPI member, CampaignFleetAPI recoverer, boolean own, boolean useOfficerRecovery, float chanceMult)
static void forgetAboutTransponder(CampaignFleetAPI fleet)
static boolean isPlayerOrCombinedContainingPlayer(CampaignFleetAPI fleet)
static boolean isUnremovable(PersonAPI person)
static int getNumNonMercOfficers(CampaignFleetAPI fleet)
static boolean isPlayerOrCombinedPlayerPrimary(CampaignFleetAPI fleet)
static boolean isUnboardable(FleetMemberAPI member)
static void makeLowRepImpact(CampaignFleetAPI fleet, String reason)
CargoAPI createCargo(boolean unlimitedStacks)
CrewCompositionAPI createCrewComposition()
HullModSpecAPI getHullModSpec(String modId)
CommoditySpecAPI getCommoditySpec(String commodityId)
float getFloat(String key)
FighterWingSpecAPI getFighterWingSpec(String wingId)
WeaponSpecAPI getWeaponSpec(String weaponId)
boolean isPlayerInvolvedAtStart()
List< CampaignFleetAPI > getPlayerSideSnapshot()
List< CampaignFleetAPI > getSnapshotSideFor(CampaignFleetAPI participantOrCombined)
CampaignFleetAPI getCombinedFor(CampaignFleetAPI participantOrCombined)
CampaignFleetAPI getPrimary(List< CampaignFleetAPI > side)
CampaignFleetAPI getNonPlayerCombined()
List< CampaignFleetAPI > getSideFor(CampaignFleetAPI participantOrCombined)
void setPlayerInvolvementFraction(float playerInvolvementFraction)
List< CampaignFleetAPI > getSnapshotFor(List< CampaignFleetAPI > side)
CampaignFleetAPI getSourceFleet(FleetMemberAPI member)
CampaignFleetAPI getPlayerCombined()
boolean knowsWhoPlayerIs(List< CampaignFleetAPI > side)
boolean isPlayerInvolved()
List< CampaignFleetAPI > getBothSides()
List< CampaignFleetAPI > getNonPlayerSide()
Map< FleetMemberAPI, CampaignFleetAPI > getMemberSourceMap()
boolean isPlayerSide(EngagementResultForFleetAPI side)
List< CampaignFleetAPI > getPlayerSide()
CampaignFleetAIAPI getAI()
void setNoEngaging(float seconds)
void removeFleetMemberWithDestructionFlash(FleetMemberAPI member)
void setMoveDestination(float x, float y)
FleetDataAPI getFleetData()
MutableFleetStatsAPI getStats()
MutableCharacterStatsAPI getCommanderStats()
boolean isValidPlayerFleet()
void addHullmods(String id, int count)
void addFromStack(CargoStackAPI stack)
void removeMarines(int quantity)
void addWeapons(String id, int count)
boolean removeItems(CargoAPI.CargoItemType itemType, Object data, float quantity)
int getNumWeapons(String id)
void addMarines(int quantity)
void addAll(CargoAPI other)
List< CargoStackAPI > getStacksCopy()
void addFuel(float quantity)
void addItems(CargoAPI.CargoItemType itemType, Object data, float quantity)
void addCommodity(String commodityId, float quantity)
void removeCrew(int quantity)
SpecialItemSpecAPI getSpecialItemSpecIfSpecial()
FighterWingSpecAPI getFighterWingSpecIfWing()
CargoAPI.CargoItemType getType()
CommoditySpecAPI getResourceIfResource()
WeaponSpecAPI getWeaponSpecIfWeapon()
List< DeployedFleetMemberAPI > getAllEverDeployedCopy()
List< FleetMemberAPI > getDestroyed()
List< FleetMemberAPI > getDeployed()
List< FleetMemberAPI > getDisabled()
boolean enemyCanCleanDisengage()
CampaignFleetAPI getFleet()
List< FleetMemberAPI > getReserves()
List< FleetMemberAPI > getRetreated()
void resetAllEverDeployed()
boolean knowsHullMod(String modId)
boolean isPlayerFaction()
OfficerDataAPI getOfficerData(PersonAPI person)
ArrayList< FleetMemberAPI > getSnapshot()
List< OfficerDataAPI > getOfficersCopy()
void addFleetMember(FleetMemberAPI member)
void removeFleetMember(FleetMemberAPI member)
void updateCargoCapacities()
List< FleetMemberAPI > getCombatReadyMembersListCopy()
List< FleetMemberAPI > getMembersListCopy()
TextPanelAPI getTextPanel()
CampaignFleetAPI getPlayerFleet()
void reportPlayerEngagement(EngagementResultAPI result)
ReputationAdjustmentResult adjustPlayerReputation(Object action, String factionId)
CampaignClockAPI getClock()
long getPlayerBattleSeed()
FactionAPI getPlayerFaction()
IntelManagerAPI getIntelManager()
void reportBattleOccurred(CampaignFleetAPI primaryWinner, BattleAPI battle)
MutableCharacterStatsAPI getPlayerStats()
void reportBattleFinished(CampaignFleetAPI primaryWinner, BattleAPI battle)
MemoryAPI getMemoryWithoutUpdate()
boolean hasTag(String tag)
LabelAPI addParagraph(String text)
boolean isCurrentAssignment(FleetAssignment assignment)
void addAssignmentAtStart(FleetAssignment assignment, SectorEntityToken target, float maxDurationInDays, Script onCompletion)
TacticalModulePlugin getTacticalModule()
void addIntel(IntelInfoPlugin plugin)
boolean hasTag(String tag)
CommoditySpecAPI getCommoditySpec(String commodityId)
String getString(String key)
boolean contains(String key)
boolean getBoolean(String key)
void setBonusXPGainReason(String bonusXPGainReason)
void addXP(long xp, TextPanelAPI textPanel, boolean withMessage, boolean allowBonusXP, boolean withLevelUp)
void setOnlyAddBonusXPDoNotSpendStoryPoints(boolean onlyAddBonusXPDoNotSpendStoryPoints)
void spendStoryPoints(int points, boolean withMessage, TextPanelAPI textPanel, boolean topScreenMessage, String logText)
MutableStat getMarineEffectivnessMult()
MutableCharacterStatsAPI getStats()
MemoryAPI getMemoryWithoutUpdate()
FleetMemberAPI getMember()
EngagementResultForFleetAPI getLoserResult()
EngagementResultForFleetAPI getWinnerResult()
CombatDamageData getLastCombatDamageData()
boolean isPlayerOutBeforeEnd()
default CargoStackAPI getRequiredItem()
MutableStat getCrewLossMult()
DynamicStatsAPI getDynamic()
StatBonus getCRPerDeploymentPercent()
MutableStat getFluxCapacity()
Set< WeaponAPI > getDisabledWeapons()
MutableShipStatsAPI getMutableStats()
float getLowestHullLevelReached()
float getHullLevelAtDeployment()
float getWingCRAtDeployment()
List< WeaponAPI > getAllWeapons()
ShipVariantAPI getVariant()
List< FighterLaunchBayAPI > getLaunchBaysCopy()
boolean isBuiltInMod(String modId)
int getOrdnancePoints(MutableCharacterStatsAPI stats)
Collection< String > getHullMods()
boolean hasTag(String tag)
String getWeaponId(String slotId)
MutableShipStatsAPI getStatsForOpCosts()
List< String > getModuleSlots()
List< String > getFittedWings()
LinkedHashSet< String > getSMods()
void removePermaMod(String modId)
Map< String, String > getStationModules()
void clearSlot(String slotId)
void setWingId(int index, String wingId)
ShipVariantAPI getModuleVariant(String slotId)
void setOriginalVariant(String targetVariant)
List< String > getNonBuiltInWings()
ShipHullSpecAPI getHullSpec()
void setNumFluxVents(int vents)
void setModuleVariant(String slotId, ShipVariantAPI variant)
List< String > getNonBuiltInWeaponSlots()
void setSource(VariantSource source)
void setNumFluxCapacitors(int capacitors)
void removeMod(String modId)
WeaponSlotAPI getSlot(String slotId)
void removeAll(CrewCompositionAPI other)
void setMarines(float marines)
void addToCargo(CargoAPI cargo)
void addAll(CrewCompositionAPI other)
void addCrew(float quantity)
void multiplyBy(float mult)
void addMarines(float marines)
void transfer(float quantity, CrewCompositionAPI dest)
void setCrew(float quantity)
BuffManagerAPI getBuffManager()
PersonAPI getFleetCommander()
ShipVariantAPI getVariant()
FleetDataAPI getFleetData()
void setCaptain(PersonAPI commander)
CrewCompositionAPI getCrewComposition()
FleetMemberStatusAPI getStatus()
RepairTrackerAPI getRepairTracker()
int getNumFightersInWing()
ShipHullSpecAPI getHullSpec()
void setVariant(ShipVariantAPI variant, boolean withRefit, boolean withStatsUpdate)
MutableShipStatsAPI getStats()
void setDetached(int index, Boolean detached)
float getArmorDamageTaken()
float getHullDamageTaken()
void repairHullFraction(float fraction)
void setHullFraction(float fraction)
void repairArmorAllCells(float fraction)
DynamicStatsAPI getDynamic()
void setMothballed(boolean mothballed)
void applyCREvent(float crChange, String description)
boolean hasTag(String tag)
boolean hasTag(String tag)
boolean isHiddenEverywhere()
HullModEffect getEffect()
boolean isStationModule()
boolean hasTag(String tag)
float getValue(String id)