001package com.fs.starfarer.api.impl.campaign.intel.events; 002 003import java.awt.Color; 004import java.util.LinkedHashSet; 005import java.util.List; 006import java.util.Random; 007import java.util.Set; 008 009import org.lwjgl.util.vector.Vector2f; 010 011import com.fs.starfarer.api.Global; 012import com.fs.starfarer.api.campaign.BattleAPI; 013import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason; 014import com.fs.starfarer.api.campaign.CampaignFleetAPI; 015import com.fs.starfarer.api.campaign.CargoAPI; 016import com.fs.starfarer.api.campaign.InteractionDialogAPI; 017import com.fs.starfarer.api.campaign.StarSystemAPI; 018import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin.ListInfoMode; 019import com.fs.starfarer.api.campaign.econ.Industry; 020import com.fs.starfarer.api.campaign.econ.MarketAPI; 021import com.fs.starfarer.api.campaign.listeners.ColonyPlayerHostileActListener; 022import com.fs.starfarer.api.campaign.listeners.FleetEventListener; 023import com.fs.starfarer.api.fleet.FleetMemberAPI; 024import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetAssignmentAI.EconomyRouteData; 025import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetRouteManager; 026import com.fs.starfarer.api.impl.campaign.fleets.RouteManager; 027import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData; 028import com.fs.starfarer.api.impl.campaign.ids.Conditions; 029import com.fs.starfarer.api.impl.campaign.ids.Factions; 030import com.fs.starfarer.api.impl.campaign.ids.FleetTypes; 031import com.fs.starfarer.api.impl.campaign.ids.Industries; 032import com.fs.starfarer.api.impl.campaign.ids.Skills; 033import com.fs.starfarer.api.impl.campaign.ids.Strings; 034import com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.EventStageData; 035import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.HAERandomEventData; 036import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.Stage; 037import com.fs.starfarer.api.impl.campaign.intel.events.TriTachyonStandardActivityCause.CompetitorData; 038import com.fs.starfarer.api.impl.campaign.intel.events.ttcr.TTCRCommerceRaidersDestroyedFactor; 039import com.fs.starfarer.api.impl.campaign.intel.events.ttcr.TTCRIndustryDisruptedFactor; 040import com.fs.starfarer.api.impl.campaign.intel.events.ttcr.TTCRMercenariesDefeatedFactor; 041import com.fs.starfarer.api.impl.campaign.intel.events.ttcr.TTCRPoints; 042import com.fs.starfarer.api.impl.campaign.intel.events.ttcr.TTCRTradeFleetsDestroyedFactor; 043import com.fs.starfarer.api.impl.campaign.intel.events.ttcr.TriTachyonCommerceRaiding; 044import com.fs.starfarer.api.impl.campaign.intel.group.FGRaidAction.FGRaidType; 045import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel; 046import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel.FGIEventListener; 047import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI.GenericRaidParams; 048import com.fs.starfarer.api.impl.campaign.intel.group.TTMercenaryAttack; 049import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission; 050import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission.FleetStyle; 051import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.ComplicationRepImpact; 052import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.FleetQuality; 053import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.TempData; 054import com.fs.starfarer.api.ui.TooltipMakerAPI; 055import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator; 056import com.fs.starfarer.api.util.CountingMap; 057import com.fs.starfarer.api.util.Misc; 058import com.fs.starfarer.api.util.TimeoutTracker; 059 060public class TriTachyonHostileActivityFactor extends BaseHostileActivityFactor 061 implements FGIEventListener, FleetEventListener, ColonyPlayerHostileActListener { 062 063 public static String COUNTER_RAIDED_TRITACH = "$counterRaidedTriTach"; 064 public static String DEFEATED_MERC_ATTACK = "$defeatedTTMercAttack"; 065 public static String BRIBED_MERC_ATTACK = "$bribedTTMercAttack"; 066 067 public static String COMMERCE_RAIDER_FLEET = "$triTachCommerceRaider"; 068 069 public static float DEALT_WITH_MERC_PROGRESS_MULT = 0.25f; 070 071 public static boolean isPlayerCounterRaidedTriTach() { 072 return Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(COUNTER_RAIDED_TRITACH); 073 } 074 public static void setPlayerCounterRaidedTriTach() { 075 Global.getSector().getPlayerMemoryWithoutUpdate().set(COUNTER_RAIDED_TRITACH, true); 076 } 077 078 public static boolean isPlayerDefeatedMercAttack() { 079 return Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(DEFEATED_MERC_ATTACK); 080 } 081 public static void setPlayerDefeatedMercAttack() { 082 Global.getSector().getPlayerMemoryWithoutUpdate().set(DEFEATED_MERC_ATTACK, true); 083 } 084 085 public static boolean isDealtWithMercAttack() { 086 return isPlayerDefeatedMercAttack() || isPlayerBribedMercAttack(); 087 } 088 089 /** 090 * This is actually set in rules, so: method never called 091 */ 092 public static boolean isPlayerBribedMercAttack() { 093 return Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(BRIBED_MERC_ATTACK); 094 } 095 public static void setPlayerBribedMercAttack() { 096 Global.getSector().getPlayerMemoryWithoutUpdate().set(BRIBED_MERC_ATTACK, true); 097 } 098 099 100 101 protected TimeoutTracker<Industry> recentlyDisrupted = new TimeoutTracker<Industry>(); 102 103 104 public TriTachyonHostileActivityFactor(HostileActivityEventIntel intel) { 105 super(intel); 106 107 Global.getSector().getListenerManager().addListener(this); 108 } 109 110 protected Object readResolve() { 111 if (recentlyDisrupted == null) { 112 recentlyDisrupted = new TimeoutTracker<Industry>(); 113 } 114 return this; 115 } 116 117 public String getProgressStr(BaseEventIntel intel) { 118 return ""; 119 } 120 121 @Override 122 public int getProgress(BaseEventIntel intel) { 123 if (!checkFactionExists(Factions.TRITACHYON, true)) { 124 return 0; 125 } 126 return super.getProgress(intel); 127 } 128 129 public String getDesc(BaseEventIntel intel) { 130 return "Tri-Tachyon Corporation"; 131 } 132 133 public String getNameForThreatList(boolean first) { 134 return "Tri-Tachyon"; 135 } 136 137 138 public Color getDescColor(BaseEventIntel intel) { 139 if (getProgress(intel) <= 0) { 140 return Misc.getGrayColor(); 141 } 142 return Global.getSector().getFaction(Factions.TRITACHYON).getBaseUIColor(); 143 } 144 145 public TooltipCreator getMainRowTooltip(BaseEventIntel intel) { 146 return new BaseFactorTooltip() { 147 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) { 148 float opad = 10f; 149 tooltip.addPara("Your independent polity has become enough of a presence in the Sector to " 150 + "start cutting into the profit margins of the Tri-Tachyon Corporation.", 0f); 151 152 tooltip.addPara("Independent-flagged commerce raiders - little more than sanctioned pirates - " 153 + "have been sighted in your space, " 154 + "attacking trade fleets regardless of their factional allegiance.", opad); 155 156 addDealtSectionToTooltip(tooltip, opad); 157 } 158 }; 159 } 160 161 public static void addDealtSectionToTooltip(TooltipMakerAPI tooltip, float opad) { 162 if (isDealtWithMercAttack()) { 163 tooltip.addPara("You've dealt with the mercenary attack sent against you, and " + 164 "this has considerably cooled the enthusiasm for continued aggression. " + 165 "Commerce-raiding continues, but the event progress value is reduced by %s, " 166 + "and no further large-scale attacks are likely to be mounted.", opad, 167 Misc.getHighlightColor(), Strings.X + DEALT_WITH_MERC_PROGRESS_MULT); 168 } 169 } 170 171 public boolean shouldShow(BaseEventIntel intel) { 172 return getProgress(intel) > 0; 173 } 174 175 176 public Color getNameColor(float mag) { 177 if (mag <= 0f) { 178 return Misc.getGrayColor(); 179 } 180 return Global.getSector().getFaction(Factions.TRITACHYON).getBaseUIColor(); 181 } 182 183 184 @Override 185 public int getMaxNumFleets(StarSystemAPI system) { 186 return Global.getSettings().getInt("triTachyonMaxFleets"); 187 } 188 189 public CampaignFleetAPI createFleet(StarSystemAPI system, Random random) { 190 191 float f = intel.getMarketPresenceFactor(system); 192 193 // even if magnitude is not factored in, if it's 0 fleets won't spawn 194 // and its value affects the likelihood of tritach fleets spawning 195 //getEffectMagnitude(system); 196 197 int difficulty = 4 + (int) Math.round(f * 4f); 198 199 FleetCreatorMission m = new FleetCreatorMission(random); 200 m.beginFleet(); 201 202 Vector2f loc = system.getLocation(); 203 String factionId = Factions.TRITACHYON; 204 if (random.nextFloat() < 0.5f) { 205 factionId = Factions.MERCENARY; 206 } 207 208 m.createQualityFleet(difficulty, factionId, loc); 209 210 if (difficulty <= 5) { 211 m.triggerSetFleetQuality(FleetQuality.SMOD_1); 212 } else if (difficulty <= 7) { 213 m.triggerSetFleetQuality(FleetQuality.SMOD_2); 214 } else { 215 m.triggerSetFleetQuality(FleetQuality.SMOD_3); 216 } 217 218 m.triggerSetFleetFaction(Factions.INDEPENDENT); 219 m.triggerSetFleetType(FleetTypes.COMMERCE_RAIDERS); 220 221 m.triggerSetPirateFleet(); 222 //m.triggerMakeHostile(); 223 m.triggerMakeNonHostileToFaction(Factions.TRITACHYON); 224 m.triggerMakeHostileToAllTradeFleets(); 225 m.triggerMakeEveryoneJoinBattleAgainst(); 226 227 m.triggerMakeNonHostileToFaction(Factions.PIRATES); 228 m.triggerMakeNoRepImpact(); 229 m.triggerFleetAllowLongPursuit(); 230 231 m.triggerFleetAddCommanderSkill(Skills.COORDINATED_MANEUVERS, 1); 232 m.triggerFleetAddCommanderSkill(Skills.ELECTRONIC_WARFARE, 1); 233// m.triggerFleetAddCommanderSkill(Skills.FLUX_REGULATION, 1); 234// m.triggerFleetAddCommanderSkill(Skills.PHASE_CORPS, 1); 235// m.triggerFleetAddCommanderSkill(Skills.CARRIER_GROUP, 1); 236 237 m.triggerSetFleetFlag(COMMERCE_RAIDER_FLEET); 238 239 int tugs = 0; 240 if (Factions.MERCENARY.equals(factionId)) { 241 tugs = random.nextInt(3); 242 } 243 244 m.triggerFleetMakeFaster(true, tugs, true); 245 m.triggerSetFleetMaxShipSize(3); 246 247 248 CampaignFleetAPI fleet = m.createFleet(); 249 250 return fleet; 251 } 252 253 254 255 256 public void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, 257 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) { 258 Color c = Global.getSector().getFaction(Factions.TRITACHYON).getBaseUIColor(); 259 info.addPara("Impending Tri-Tachyon mercenary attack", initPad, tc, c, "Tri-Tachyon"); 260 } 261 262 public void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, 263 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) { 264 info.addPara("Tri-Tachyon mercenary attack averted", tc, initPad); 265 } 266 267 public void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info) { 268 float small = 0f; 269 float opad = 10f; 270 271 small = 8f; 272 273 Color c = Global.getSector().getFaction(Factions.TRITACHYON).getBaseUIColor(); 274 275 Color h = Misc.getHighlightColor(); 276 info.addPara("You've received intel that the Tri-Tachyon Corporation is allocating funds to hire and " 277 + "equip a mercenary company to raid and disrupt your industrial base.", 278 small, Misc.getNegativeHighlightColor(), "raid and disrupt your industrial base"); 279 280 info.addPara("If the mercenary attack is defeated, it will go a long way towards convincing " 281 + "the Tri-Tachyon Corporation to abandon its anti-competitive efforts.", 282 //opad, tri, "Tri-Tachyon Corporation"); 283 opad, h, "abandon its anti-competitive efforts"); 284 285 stage.beginResetReqList(info, true, "crisis", opad); 286 info.addPara("The %s is convinced that its efforts are unprofitable", 0f, c, "Tri-Tachyon Corporation"); 287 stage.endResetReqList(info, false, "crisis", -1, -1); 288 289 addBorder(info, Global.getSector().getFaction(Factions.TRITACHYON).getBaseUIColor()); 290 } 291 292 293 public String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage) { 294 return Global.getSector().getFaction(Factions.TRITACHYON).getCrest(); 295 } 296 297 public TooltipCreator getStageTooltipImpl(final HostileActivityEventIntel intel, final EventStageData stage) { 298 if (stage.id == Stage.HA_EVENT) { 299 return getDefaultEventTooltip("Tri-Tachyon mercenary attack", intel, stage); 300 } 301 return null; 302 } 303 304 305 public float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage) { 306 if (stage.id == Stage.HA_EVENT) { 307 308 if (isPlayerCounterRaidedTriTach() || getPrimaryTriTachyonSystem() == null) { 309 return 0f; 310 } 311 312 if (isPlayerDefeatedMercAttack() || isPlayerBribedMercAttack()) { 313 return 0f; 314 } 315 316 StarSystemAPI target = findExpeditionTarget(intel, stage); 317 MarketAPI source = findExpeditionSource(intel, stage, target); 318 if (target != null && source != null) { 319 return 10f; 320 } 321 } 322 return 0; 323 } 324 325 326 public void rollEvent(HostileActivityEventIntel intel, EventStageData stage) { 327 HAERandomEventData data = new HAERandomEventData(this, stage); 328 stage.rollData = data; 329 intel.sendUpdateIfPlayerHasIntel(data, false); 330 } 331 332 public boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage) { 333 StarSystemAPI target = findExpeditionTarget(intel, stage); 334 MarketAPI source = findExpeditionSource(intel, stage, target); 335 336 if (source == null || target == null) { 337 return false; 338 } 339 340 stage.rollData = null; 341 return startMercenaryAttack(source, target, stage, intel, getRandomizedStageRandom(3)); 342 } 343 344 345 public static StarSystemAPI findExpeditionTarget(HostileActivityEventIntel intel, EventStageData stage) { 346 List<CompetitorData> data = TriTachyonStandardActivityCause.computePlayerCompetitionData(); 347 CountingMap<StarSystemAPI> counts = new CountingMap<StarSystemAPI>(); 348 349 for (CompetitorData curr : data) { 350 for (MarketAPI market : curr.competitorProducers) { 351 StarSystemAPI system = market.getStarSystem(); 352 if (system == null) continue; 353 int weight = market.getCommodityData(curr.commodityId).getMaxSupply(); 354 counts.add(system, weight); 355 } 356 } 357 358 return counts.getLargest(); 359 } 360 361 public static MarketAPI findExpeditionSource(HostileActivityEventIntel intel, EventStageData stage, StarSystemAPI target) { 362 if (getNortia() != null) return getNortia(); 363 364 365 CountingMap<MarketAPI> scores = new CountingMap<MarketAPI>(); 366 for (MarketAPI market : Misc.getFactionMarkets(Factions.TRITACHYON)) { 367 int size = market.getSize(); 368 int weight = size; 369 if (!Misc.isMilitary(market)) weight += size * 10; 370 if (market.hasIndustry(Industries.ORBITALWORKS)) weight += size; 371 if (market.hasIndustry(Industries.HEAVYINDUSTRY)) weight += size; 372 373 scores.add(market, weight); 374 } 375 376 return scores.getLargest(); 377 } 378 379 public static MarketAPI getNortia() { 380 MarketAPI nortia = Global.getSector().getEconomy().getMarket("nortia"); 381 if (nortia == null || nortia.hasCondition(Conditions.DECIVILIZED) || 382 !nortia.getFactionId().equals(Factions.INDEPENDENT)) { 383 return null; 384 } 385 return nortia; 386 } 387 388 389 390 391 public void reportFGIAborted(FleetGroupIntel intel) { 392 setPlayerDefeatedMercAttack(); 393 TriTachyonCommerceRaiding.addFactorCreateIfNecessary(new TTCRMercenariesDefeatedFactor(), null); 394 } 395 396 397 398 @Override 399 public void notifyFactorRemoved() { 400 Global.getSector().getListenerManager().removeListener(this); 401 } 402 403 public void notifyEventEnding() { 404 notifyFactorRemoved(); 405 } 406 407 408 @Override 409 public void advance(float amount) { 410 super.advance(amount); 411 412 float days = Misc.getDays(amount); 413 recentlyDisrupted.advance(days); 414 415// if (!Global.getSector().getListenerManager().hasListener(this)) { 416// Global.getSector().getListenerManager().addListener(this); 417// } 418 419// System.out.println("LISTENERS:"); 420// for (Object o : Global.getSector().getListenerManager().getListeners(Object.class)) { 421// System.out.println("Listener: " + o.getClass().getSimpleName() + " [" + o.hashCode() + "]"); 422// } 423// System.out.println("-----"); 424// System.out.println("-----"); 425// System.out.println("-----"); 426// System.out.println("-----"); 427 428 EventStageData stage = intel.getDataFor(Stage.HA_EVENT); 429 if (stage != null && stage.rollData instanceof HAERandomEventData && 430 ((HAERandomEventData)stage.rollData).factor == this) { 431 if (isPlayerCounterRaidedTriTach()) { 432 intel.resetHA_EVENT(); 433 } 434 } 435 if (isPlayerCounterRaidedTriTach() && TTMercenaryAttack.get() != null) { 436 TTMercenaryAttack.get().finish(false); 437 } 438 } 439 440 441 public static StarSystemAPI getPrimaryTriTachyonSystem() { 442 CountingMap<StarSystemAPI> counts = new CountingMap<StarSystemAPI>(); 443 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) { 444 if (!Factions.TRITACHYON.equals(market.getFactionId())) continue; 445 StarSystemAPI system = market.getStarSystem(); 446 if (system == null) continue; 447 int size = market.getSize(); 448 int weight = size; 449 if (Misc.isMilitary(market)) weight += size; 450 if (market.hasIndustry(Industries.ORBITALWORKS)) weight += size; 451 if (market.hasIndustry(Industries.HEAVYINDUSTRY)) weight += size; 452 453 counts.add(system, weight); 454 } 455 return counts.getLargest(); 456 } 457 458 459 public boolean startMercenaryAttack(MarketAPI source, StarSystemAPI target, 460 EventStageData stage, HostileActivityEventIntel intel, Random random) { 461 if (isPlayerCounterRaidedTriTach()) return false; 462 if (source == null || target == null) return false; 463 464 GenericRaidParams params = new GenericRaidParams(new Random(random.nextLong()), true); 465 params.makeFleetsHostile = false; // will be made hostile when they arrive, not before 466 params.source = source; 467 468 params.prepDays = 21f + random.nextFloat() * 7f; 469 params.payloadDays = 27f + 7f * random.nextFloat(); 470 471 params.raidParams.where = target; 472 params.raidParams.type = FGRaidType.SEQUENTIAL; 473 474 Set<String> disrupt = new LinkedHashSet<String>(); 475 for (MarketAPI market : Misc.getMarketsInLocation(target, Factions.PLAYER)) { 476 params.raidParams.allowedTargets.add(market); 477 params.raidParams.allowNonHostileTargets = true; 478 for (Industry ind : market.getIndustries()) { 479 if (ind.getSpec().hasTag(Industries.TAG_UNRAIDABLE)) continue; 480 disrupt.add(ind.getId()); 481 482 } 483 } 484 485 params.raidParams.disrupt.addAll(disrupt); 486 params.raidParams.raidsPerColony = Math.min(disrupt.size(), 4); 487 if (disrupt.isEmpty()) { 488 params.raidParams.raidsPerColony = 2; 489 } 490 491 if (params.raidParams.allowedTargets.isEmpty()) { 492 return false; 493 } 494 495 params.factionId = Factions.INDEPENDENT; 496 params.style = FleetStyle.QUALITY; 497 params.repImpact = ComplicationRepImpact.NONE; 498 499 500 float fleetSizeMult = 1f; 501 502 float f = intel.getMarketPresenceFactor(target); 503 504 float totalDifficulty = fleetSizeMult * 50f * (0.5f + 0.5f * f); 505 506 totalDifficulty -= 10; 507 params.fleetSizes.add(10); // first size 10 pick becomes the Operational Command 508 509 while (totalDifficulty > 0) { 510 int min = 3; 511 int max = 8; 512 513 //int diff = Math.round(StarSystemGenerator.getNormalRandom(random, min, max)); 514 int diff = min + random.nextInt(max - min + 1); 515 516 params.fleetSizes.add(diff); 517 totalDifficulty -= diff; 518 } 519 520 TTMercenaryAttack attack = new TTMercenaryAttack(params); 521 attack.setListener(this); 522 //attack.setPreFleetDeploymentDelay(30f + random.nextFloat() * 60f); 523 //attack.setPreFleetDeploymentDelay(1f); 524 Global.getSector().getIntelManager().addIntel(attack, false); 525 526 return true; 527 } 528 529 530 531 public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) { 532 533 } 534 public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) { 535 if (isPlayerCounterRaidedTriTach()) return; 536 537 if (!battle.isPlayerInvolved()) return; 538 539 if (getProgress(null) <= 0 && TriTachyonCommerceRaiding.get() == null) return; 540 541 int traderFP = 0; 542 int raiderFP = 0; 543 for (CampaignFleetAPI otherFleet : battle.getNonPlayerSideSnapshot()) { 544 //if (!Global.getSector().getPlayerFaction().isHostileTo(otherFleet.getFaction())) continue; 545 boolean trader = isTraderServingATTColony(otherFleet); 546 boolean raider = isCommerceRaider(otherFleet); 547 548 if (!trader && !raider) continue; 549 550 int mult = 1; 551 if (trader) mult = TTCRPoints.TRADE_FLEET_FP_MULT; 552 553 for (FleetMemberAPI loss : Misc.getSnapshotMembersLost(otherFleet)) { 554 int fp = loss.getFleetPointCost() * mult; 555 if (trader) { 556 traderFP += fp; 557 } else if (raider) { 558 raiderFP += fp; 559 } 560 } 561 } 562 563 if (traderFP > 0) { 564 int points = computeTTCRProgressPoints(traderFP); 565 if (points > 0) { 566 TTCRTradeFleetsDestroyedFactor factor = new TTCRTradeFleetsDestroyedFactor(points); 567 TriTachyonCommerceRaiding.addFactorCreateIfNecessary(factor, null); 568 } 569 } 570 if (raiderFP > 0) { 571 int points = computeTTCRProgressPoints(raiderFP); 572 if (points > 0) { 573 TTCRCommerceRaidersDestroyedFactor factor = new TTCRCommerceRaidersDestroyedFactor(points); 574 TriTachyonCommerceRaiding.addFactorCreateIfNecessary(factor, null); 575 } 576 } 577 } 578 579 public static boolean isCommerceRaider(CampaignFleetAPI fleet) { 580 return fleet.getMemoryWithoutUpdate().getBoolean(TriTachyonHostileActivityFactor.COMMERCE_RAIDER_FLEET); 581 } 582 public static boolean isTraderServingATTColony(CampaignFleetAPI fleet) { 583 boolean trader = Misc.isTrader(fleet); 584 boolean smuggler = Misc.isSmuggler(fleet); 585 586 if (!trader && !smuggler) return false; 587 588 RouteData route = RouteManager.getInstance().getRoute(EconomyFleetRouteManager.SOURCE_ID, fleet); 589 if (route == null) return false; 590 591 EconomyRouteData data = (EconomyRouteData) route.getCustom(); 592 if (data == null) return false; 593 594 if (data.from != null && Factions.TRITACHYON.equals(data.from.getFactionId())) { 595 return true; 596 } 597 if (data.to != null && Factions.TRITACHYON.equals(data.to.getFactionId())) { 598 return true; 599 } 600 601 return false; 602 } 603 604 public static int computeTTCRProgressPoints(float fleetPointsDestroyed) { 605 if (fleetPointsDestroyed <= 0) return 0; 606 607 int points = Math.round(fleetPointsDestroyed / (float) TTCRPoints.FP_PER_POINT); 608 if (points < 1) points = 1; 609 return points; 610 } 611 612 public static int computeIndustryDisruptPoints(Industry ind) { 613 float base = ind.getSpec().getDisruptDanger().disruptionDays; 614 float per = TTCRPoints.BASE_POINTS_FOR_INDUSTRY_DISRUPT; 615 616 float days = ind.getDisruptedDays(); 617 618 int points = (int) Math.round(days / base * per); 619 if (points > TTCRPoints.MAX_POINTS_FOR_INDUSTRY_DISRUPT) { 620 points = TTCRPoints.MAX_POINTS_FOR_INDUSTRY_DISRUPT; 621 } 622 return points; 623 } 624 625 public void reportRaidForValuablesFinishedBeforeCargoShown(InteractionDialogAPI dialog, MarketAPI market, 626 TempData actionData, CargoAPI cargo) { 627 628 } 629 public void reportRaidToDisruptFinished(InteractionDialogAPI dialog, MarketAPI market, TempData actionData, 630 Industry industry) { 631 if (isPlayerCounterRaidedTriTach()) return; 632 if (getProgress(null) <= 0 && TriTachyonCommerceRaiding.get() == null) return; 633 634 if (market != null && Factions.TRITACHYON.equals(market.getFactionId())) { 635 applyIndustryDisruptionToTTCR(industry, dialog); 636 } 637 } 638 public void reportTacticalBombardmentFinished(InteractionDialogAPI dialog, MarketAPI market, TempData actionData) { 639 if (isPlayerCounterRaidedTriTach()) return; 640 if (getProgress(null) <= 0 && TriTachyonCommerceRaiding.get() == null) return; 641 642 if (market != null && Factions.TRITACHYON.equals(market.getFactionId())) { 643 applyMassIndustryDisruptionToTTCR(market, dialog); 644 } 645 } 646 public void reportSaturationBombardmentFinished(InteractionDialogAPI dialog, MarketAPI market, 647 TempData actionData) { 648 if (isPlayerCounterRaidedTriTach()) return; 649 if (getProgress(null) <= 0 && TriTachyonCommerceRaiding.get() == null) return; 650 651 if (market != null && Factions.TRITACHYON.equals(market.getFactionId())) { 652 applyMassIndustryDisruptionToTTCR(market, dialog); 653 } 654 } 655 656 public void applyMassIndustryDisruptionToTTCR(MarketAPI market, InteractionDialogAPI dialog) { 657 if (isPlayerCounterRaidedTriTach()) return; 658 if (getProgress(null) <= 0 && TriTachyonCommerceRaiding.get() == null) return; 659 660 int points = 0; 661 for (Industry industry : market.getIndustries()) { 662 if (recentlyDisrupted.contains(industry)) continue; 663 if (industry.getSpec().hasTag(Industries.TAG_UNRAIDABLE)) continue; 664 665 int curr = computeIndustryDisruptPoints(industry); 666 if (curr > 0) { 667 points += curr; 668 recentlyDisrupted.add(industry, industry.getDisruptedDays()); 669 } 670 } 671 672 if (points > 0) { 673 TTCRIndustryDisruptedFactor factor = new TTCRIndustryDisruptedFactor( 674 "Disrupted industries " + market.getOnOrAt() + " " + market.getName(), points); 675 TriTachyonCommerceRaiding.addFactorCreateIfNecessary(factor, dialog); 676 } 677 } 678 public void applyIndustryDisruptionToTTCR(Industry industry, InteractionDialogAPI dialog) { 679 if (isPlayerCounterRaidedTriTach()) return; 680 if (getProgress(null) <= 0 && TriTachyonCommerceRaiding.get() == null) return; 681 682 if (!recentlyDisrupted.contains(industry)) { 683 if (industry.getSpec().hasTag(Industries.TAG_UNRAIDABLE)) return; 684 MarketAPI market = industry.getMarket(); 685 if (market == null) return; 686 687 int points = computeIndustryDisruptPoints(industry); 688 if (points > 0) { 689 TTCRIndustryDisruptedFactor factor = new TTCRIndustryDisruptedFactor( 690 industry.getCurrentName() + " " + market.getOnOrAt() + " " + market.getName() + 691 " disrupted", points); 692 TriTachyonCommerceRaiding.addFactorCreateIfNecessary(factor, dialog); 693 recentlyDisrupted.add(industry, industry.getDisruptedDays()); 694 } 695 } 696 } 697 @Override 698 public Color getNameColorForThreatList() { 699 return super.getNameColorForThreatList(); 700 } 701 702 703} 704 705 706 707