64 float startingCR = ship.getCRAtDeployment();
65 float cr = ship.getCurrentCR();
67 List<CRStatusItemData> list =
new ArrayList<CRStatusItemData>();
80 String title =
"Combat Readiness " + Math.round(cr * 100f) +
"%";
82 String malfStr = getMalfunctionString(ship.getMutableStats(), cr);
85 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[9], icon, title,
86 "Shields offline",
true);
91 boolean hasWings =
false;
92 for (FighterLaunchBayAPI bay : ship.getLaunchBaysCopy()) {
93 if (bay.getWing() !=
null) {
99 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[10], icon, title,
100 "Fighter bays offline",
true);
106 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[8], icon, title,
107 ship.getPhaseCloak().getDisplayName() +
" offline",
true);
112 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[7], icon, title,
113 ship.getSystem().getDisplayName() +
" offline",
true);
118 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[0], icon, title,
119 "malfunction risk: " + malfStr,
true);
123 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[2], icon, title,
124 "missiles not fully loaded",
true);
129 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[3], icon, title,
130 "degraded performance",
true);
133 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[4], icon, title,
134 "improved performance",
false);
137 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[8], icon, title,
138 "standard performance",
false);
142 if (ship.losesCRDuringCombat() && cr > 0) {
144 float noLossTime = ship.getMutableStats().getPeakCRDuration().computeEffective(ship.getHullSpec().getNoCRLossTime());
145 if (noLossTime > ship.getTimeDeployedForCRReduction()) {
146 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[5], icon,
"peak active performance",
147 "remaining time: " + (
int) (noLossTime - ship.getTimeDeployedForCRReduction()) +
" sec",
false);
150 CRStatusItemData itemData =
new CRStatusItemData(
statusKeys[6], icon,
"combat stresses",
151 "degrading readiness",
true);
253 public void applyCRToStats(
float cr, MutableShipStatsAPI stats, HullSize hullSize) {
254 String
id =
"cr_effect";
256 boolean fighter = hullSize == HullSize.FIGHTER;
265 stats.getWeaponMalfunctionChance().modifyFlat(
id, 0.01f * getWeaponMalfuctionPercent(stats, cr));
266 stats.getEngineMalfunctionChance().modifyFlat(
id, 0.01f * getEngineMalfuctionPercent(stats, cr));
268 stats.getWeaponMalfunctionChance().unmodify(
id);
269 stats.getEngineMalfunctionChance().unmodify(
id);
275 stats.getCriticalMalfunctionChance().modifyFlat(
id, 0.01f * getCriticalMalfuctionPercent(stats, cr));
277 stats.getCriticalMalfunctionChance().unmodify(
id);
283 stats.getShieldMalfunctionChance().modifyFlat(
id, 0.01f * getShieldMalfuctionPercent(stats, cr));
284 stats.getShieldMalfunctionFluxLevel().modifyFlat(
id, 0.75f);
286 stats.getShieldMalfunctionChance().unmodify(
id);
287 stats.getShieldMalfunctionFluxLevel().unmodify(
id);
292 if (stats.getEntity() instanceof ShipAPI) {
293 ShipAPI ship = (ShipAPI)stats.getEntity();
295 ship.setShipSystemDisabled(
true);
296 ship.setDefenseDisabled(
true);
298 ship.setShipSystemDisabled(
false);
299 ship.setDefenseDisabled(
false);
304 float movementChange = getMovementChangePercent(stats, cr);
305 float damageTakenChange = getDamageTakenChangePercent(stats, cr);
306 float damageChange = getDamageChangePercent(stats, cr);
307 float refitTimeChange = getRefitTimeChangePercent(stats, cr);
309 if (refitTimeChange != 0) {
310 stats.getFighterRefitTimeMult().modifyPercent(
id, refitTimeChange);
312 stats.getFighterRefitTimeMult().unmodify(
id);
315 if (movementChange != 0) {
316 stats.getMaxSpeed().modifyPercent(
id, movementChange);
317 stats.getAcceleration().modifyPercent(
id, movementChange);
318 stats.getDeceleration().modifyPercent(
id, movementChange);
319 stats.getTurnAcceleration().modifyPercent(
id, movementChange);
320 stats.getMaxTurnRate().modifyPercent(
id, movementChange);
322 stats.getMaxSpeed().unmodify(
id);
323 stats.getAcceleration().unmodify(
id);
324 stats.getDeceleration().unmodify(
id);
325 stats.getTurnAcceleration().unmodify(
id);
326 stats.getMaxTurnRate().unmodify(
id);
329 if (damageTakenChange != 0) {
330 stats.getArmorDamageTakenMult().modifyPercent(
id, damageTakenChange);
331 stats.getHullDamageTakenMult().modifyPercent(
id, damageTakenChange);
332 stats.getShieldDamageTakenMult().modifyPercent(
id, damageTakenChange);
334 stats.getArmorDamageTakenMult().unmodify(
id);
335 stats.getHullDamageTakenMult().unmodify(
id);
336 stats.getShieldDamageTakenMult().unmodify(
id);
339 if (damageChange != 0) {
340 stats.getBallisticWeaponDamageMult().modifyPercent(
id, damageChange);
341 stats.getEnergyWeaponDamageMult().modifyPercent(
id, damageChange);
342 stats.getMissileWeaponDamageMult().modifyPercent(
id, damageChange);
344 stats.getBallisticWeaponDamageMult().unmodify(
id);
345 stats.getEnergyWeaponDamageMult().unmodify(
id);
346 stats.getMissileWeaponDamageMult().unmodify(
id);
349 float aimAccuracy = getAimAccuracy(cr);
350 stats.getAutofireAimAccuracy().modifyFlat(
id, aimAccuracy);
355 for (WeaponAPI weapon : ship.getAllWeapons()) {
356 if (weapon.getType() == WeaponType.MISSILE) {
358 if (ammo < 0) ammo = 0;
359 weapon.setAmmo(Math.round(ammo));
363 ship.setCRAtDeployment(cr);
366 if (cr < c && !ship.controlsLocked() && !ship.isFighter()) {
367 float severity = (c - cr) / (c);
370 float criticalMult = 1f;
371 for (StatMod mod : ship.getMutableStats().getCriticalMalfunctionChance().getMultMods().values()) {
372 criticalMult *= mod.getValue();
374 severity *= criticalMult;
432 CREffectDescriptionForTooltip result =
new CREffectDescriptionForTooltip();
435 boolean hasPositive =
false;
436 boolean hasNegative =
false;
437 for (CREffectDetail detail : details) {
438 if (detail.getType() == CREffectDetailType.BONUS) hasPositive =
true;
439 if (detail.getType() == CREffectDetailType.PENALTY) hasNegative =
true;
443 String crStr = (int)(cr * 100f) +
"%";
446 str = String.format(
"The %s is not ready for combat and can not be deployed in battle.", shipOrWing);
448 str = String.format(
"The %s suffers from degraded performance and runs the risk of permanent and damaging malfunctions if deployed.", shipOrWing);
450 str = String.format(
"The %s suffers from degraded performance and runs the risk of weapon and engine malfunctions during combat.", shipOrWing);
452 str = String.format(
"The %s suffers from degraded performance during combat.", shipOrWing);
454 str = String.format(
"The %s has standard combat performance.", shipOrWing);
456 str = String.format(
"The %s benefits from improved combat performance.", shipOrWing);
462 if (member.isFighterWing()) {
463 boolean canReplaceFighters =
false;
464 FleetDataAPI data = member.getFleetData();
466 for (FleetMemberAPI curr : data.getMembersListCopy()) {
467 if (curr.isMothballed())
continue;
468 if (curr.getNumFlightDecks() > 0) {
469 canReplaceFighters =
true;
474 if (canReplaceFighters) {
475 details.add(
new CREffectDetail(
"",
"", CREffectDetailType.NEUTRAL));
476 float costPer = member.getStats().getCRPerDeploymentPercent().computeEffective(member.getVariant().getHullSpec().getCRToDeploy()) / 100f;
477 String numStr =
"" + (int) Math.ceil((
float)((int) (cr * 100f)) / (costPer * 100f));
479 str +=
" " + numStr +
" fighter chassis are ready to replace combat losses.";
480 result.getHighlights().add(numStr);
483 details.add(
new CREffectDetail(
"Replacement chassis",
"None", CREffectDetailType.PENALTY));
484 str +=
" " +
"Fighter losses can not be replaced due to the lack of a ship with proper facilities (i.e. a flight deck).";
489 result.setString(str);
507 List<CREffectDetail> result =
new ArrayList<CREffectDetail>();
509 int engine = (int) getEngineMalfuctionPercent(member.getStats(), cr);
510 int weapon = (int) getWeaponMalfuctionPercent(member.getStats(), cr);
512 int speed = (int) Math.round(getMovementChangePercent(member.getStats(), cr));
513 int damage = (int) Math.round(getDamageTakenChangePercent(member.getStats(), cr));
514 int damageDealt = (int) Math.round(getDamageChangePercent(member.getStats(), cr));
515 int refit = (int) Math.round(getRefitTimeChangePercent(member.getStats(), cr));
517 float acc = getAimAccuracy(cr);
519 String malfStr = getMalfunctionString(member.getStats(), cr);
522 CREffectDetailType accType;
524 accString =
"Very poor";
525 accType = CREffectDetailType.PENALTY;
526 }
else if (acc < 0.25f) {
528 accType = CREffectDetailType.PENALTY;
529 }
else if (acc < 0.67) {
530 accString =
"Standard";
531 accType = CREffectDetailType.NEUTRAL;
533 accString =
"Excellent";
534 accType = CREffectDetailType.BONUS;
537 String speedStr = speed +
"%";
539 speedStr =
"+" + speedStr;
541 String damageStr = damage +
"%";
543 damageStr =
"+" + damageStr;
545 String rofStr = damageDealt +
"%";
546 if (damageDealt >= 0) {
547 rofStr =
"+" + rofStr;
550 String refitStr = refit +
"%";
552 refitStr =
"+" + refitStr;
555 result.add(
new CREffectDetail(
"Speed & maneuverability", speedStr, getTypeFor(speed,
false)));
556 result.add(
new CREffectDetail(
"Damage taken", damageStr, getTypeFor(damage,
true)));
557 result.add(
new CREffectDetail(
"Damage dealt", rofStr, getTypeFor(damageDealt,
false)));
559 if (member.getNumFlightDecks() > 0) {
560 result.add(
new CREffectDetail(
"Fighter refit time", refitStr, getTypeFor(refit,
true)));
563 result.add(
new CREffectDetail(
"Autofire accuracy", accString, accType));
567 CREffectDetailType malfType = CREffectDetailType.NEUTRAL;
568 if (getWeaponMalfuctionPercent(member.getStats(), cr) > 0) {
569 malfType = CREffectDetailType.PENALTY;
572 result.add(
new CREffectDetail(
"Malfunction risk", malfStr, malfType));
574 Collection<String> slots = member.getVariant().getFittedWeaponSlots();
575 boolean hasMissiles =
false;
576 for (String slotId : slots) {
577 WeaponSpecAPI w = member.getVariant().getWeaponSpec(slotId);
578 if (w.getType() == WeaponType.MISSILE) {
585 if (missileFraction < 0) missileFraction = 0;
586 String missileStr = (int)(missileFraction * 100f) +
"%";
588 if (missileFraction < 1f) {
589 result.add(
new CREffectDetail(
"Missile magazines", missileStr, missileFraction < 1 ? CREffectDetailType.PENALTY : CREffectDetailType.NEUTRAL));
634 if (module instanceof ShipEngineAPI) {
635 float fractionIfDisabled = ((ShipEngineAPI) module).getContribution() + ship.getEngineFractionPermanentlyDisabled();
636 if (fractionIfDisabled > 0.66f) {
643 if (module instanceof WeaponAPI) {
644 WeaponType type = ((WeaponAPI)module).getType();
645 if (type == WeaponType.DECORATIVE || type == WeaponType.LAUNCH_BAY || type == WeaponType.SYSTEM) {
649 if (ship.getCurrentCR() <= 0) {
653 List<Object> usableWeapons =
new ArrayList<Object>();
654 for (WeaponAPI weapon : ship.getAllWeapons()) {
655 if (weapon.isPermanentlyDisabled())
continue;
656 if (weapon.isDecorative())
continue;
657 if (weapon.getSlot().isSystemSlot())
continue;
658 if (weapon.getSlot().isDecorative())
continue;
659 if (weapon.getSlot().isStationModule())
continue;
660 if (weapon.getAmmo() > 0 && (weapon.getMaxAmmo() > 20 || weapon.getSpec().getAmmoPerSecond() > 0)) {
661 usableWeapons.add(weapon);
664 usableWeapons.remove(module);
666 return usableWeapons.size() >= 1;