001package com.fs.starfarer.api.impl.campaign.intel.punitive; 002 003import java.awt.Color; 004import java.util.Random; 005import java.util.Set; 006 007import org.lwjgl.input.Keyboard; 008import org.lwjgl.util.vector.Vector2f; 009 010import com.fs.starfarer.api.Global; 011import com.fs.starfarer.api.campaign.CampaignFleetAPI; 012import com.fs.starfarer.api.campaign.FactionAPI; 013import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin.ReputationAdjustmentResult; 014import com.fs.starfarer.api.campaign.SectorEntityToken; 015import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI; 016import com.fs.starfarer.api.campaign.econ.Industry; 017import com.fs.starfarer.api.campaign.econ.MarketAPI; 018import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin; 019import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact; 020import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope; 021import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions; 022import com.fs.starfarer.api.impl.campaign.DebugFlags; 023import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3; 024import com.fs.starfarer.api.impl.campaign.fleets.FleetParamsV3; 025import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator; 026import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData; 027import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData; 028import com.fs.starfarer.api.impl.campaign.ids.Factions; 029import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 030import com.fs.starfarer.api.impl.campaign.ids.Ranks; 031import com.fs.starfarer.api.impl.campaign.ids.Tags; 032import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExData; 033import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExGoal; 034import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExReason; 035import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExType; 036import com.fs.starfarer.api.impl.campaign.intel.raid.RaidAssignmentAI; 037import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel; 038import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel.RaidDelegate; 039import com.fs.starfarer.api.impl.campaign.procgen.themes.RouteFleetAssignmentAI; 040import com.fs.starfarer.api.ui.Alignment; 041import com.fs.starfarer.api.ui.ButtonAPI; 042import com.fs.starfarer.api.ui.IntelUIAPI; 043import com.fs.starfarer.api.ui.LabelAPI; 044import com.fs.starfarer.api.ui.SectorMapAPI; 045import com.fs.starfarer.api.ui.TooltipMakerAPI; 046import com.fs.starfarer.api.util.Misc; 047 048public class PunitiveExpeditionIntel extends RaidIntel implements RaidDelegate { 049 050 public static final String BUTTON_AVERT = "BUTTON_CHANGE_ORDERS"; 051 public static float REP_PENALTY = 0.05f; 052 053 public static enum PunExOutcome { 054 TASK_FORCE_DEFEATED, 055 COLONY_NO_LONGER_EXISTS, 056 SUCCESS, 057 BOMBARD_FAIL, 058 RAID_FAIL, 059 AVERTED, 060 } 061 062 public static final Object ENTERED_SYSTEM_UPDATE = new Object(); 063 public static final Object OUTCOME_UPDATE = new Object(); 064 065 protected PEActionStage action; 066 protected PunExGoal goal; 067 protected MarketAPI target; 068 protected MarketAPI from; 069 protected PunExOutcome outcome; 070 071 protected Random random = new Random(); 072 073 protected PunExReason bestReason; 074 protected Industry targetIndustry; 075 protected FactionAPI targetFaction; 076 077 public PunitiveExpeditionIntel(FactionAPI faction, MarketAPI from, MarketAPI target, 078 float expeditionFP, float organizeDuration, 079 PunExGoal goal, Industry targetIndustry, PunExReason bestReason) { 080 super(target.getStarSystem(), faction, null); 081 this.goal = goal; 082 this.targetIndustry = targetIndustry; 083 this.bestReason = bestReason; 084 this.delegate = this; 085 this.from = from; 086 this.target = target; 087 targetFaction = target.getFaction(); 088 089 SectorEntityToken gather = from.getPrimaryEntity(); 090 SectorEntityToken raidJump = RouteLocationCalculator.findJumpPointToUse(getFactionForUIColors(), target.getPrimaryEntity()); 091 092 if (gather == null || raidJump == null) { 093 endImmediately(); 094 return; 095 } 096 097 098 float orgDur = organizeDuration; 099 if (DebugFlags.PUNITIVE_EXPEDITION_DEBUG || DebugFlags.FAST_RAIDS) orgDur = 0.5f; 100 101 addStage(new PEOrganizeStage(this, from, orgDur)); 102 103 float successMult = 0.5f; 104 PEAssembleStage assemble = new PEAssembleStage(this, gather); 105 assemble.addSource(from); 106 assemble.setSpawnFP(expeditionFP); 107 assemble.setAbortFP(expeditionFP * successMult); 108 addStage(assemble); 109 110 111 PETravelStage travel = new PETravelStage(this, gather, raidJump, false); 112 travel.setAbortFP(expeditionFP * successMult); 113 addStage(travel); 114 115 action = new PEActionStage(this, target); 116 action.setAbortFP(expeditionFP * successMult); 117 addStage(action); 118 119 addStage(new PEReturnStage(this)); 120 121 setImportant(true); 122 123 //applyRepPenalty(); 124 Global.getSector().getIntelManager().addIntel(this); 125 126 //repResult = null; 127 } 128 129 protected transient ReputationAdjustmentResult repResult = null; 130 public void applyRepPenalty() { 131 CustomRepImpact impact = new CustomRepImpact(); 132 impact.delta = -REP_PENALTY; 133 repResult = Global.getSector().adjustPlayerReputation( 134 new RepActionEnvelope(RepActions.CUSTOM, 135 impact, null, null, false, false), 136 getFaction().getId()); 137 } 138 139 140 public Random getRandom() { 141 return random; 142 } 143 144 public MarketAPI getTarget() { 145 return target; 146 } 147 148 public FactionAPI getTargetFaction() { 149 return targetFaction; 150 } 151 152 public MarketAPI getFrom() { 153 return from; 154 } 155 156 public RouteFleetAssignmentAI createAssignmentAI(CampaignFleetAPI fleet, RouteData route) { 157 RaidAssignmentAI raidAI = new RaidAssignmentAI(fleet, route, action); 158 //raidAI.setDelegate(action); 159 return raidAI; 160 } 161 162 protected transient String targetOwner = null; 163 @Override 164 protected void advanceImpl(float amount) { 165 super.advanceImpl(amount); 166 if (target != null && targetOwner == null) targetOwner = target.getFactionId(); 167 if (failStage < 0 && targetOwner != null && target != null && !targetOwner.equals(target.getFactionId())) { 168 forceFail(false); 169 } 170 } 171 172 public void sendOutcomeUpdate() { 173 sendUpdateIfPlayerHasIntel(OUTCOME_UPDATE, false); 174 } 175 176 public void sendEnteredSystemUpdate() { 177 //applyRepPenalty(); 178 sendUpdateIfPlayerHasIntel(ENTERED_SYSTEM_UPDATE, false); 179 //repResult = null; 180 } 181 182 @Override 183 public String getName() { 184 String base = Misc.ucFirst(faction.getPersonNamePrefix()) + " Expedition"; 185 if (isEnding()) { 186 if (outcome == PunExOutcome.AVERTED) { 187 return base + " - Averted"; 188 } 189 if (isSendingUpdate() && isFailed()) { 190 return base + " - Failed"; 191 } 192 if (isSucceeded() || outcome == PunExOutcome.SUCCESS) { 193 return base + " - Successful"; 194 } 195 if (outcome == PunExOutcome.RAID_FAIL || 196 outcome == PunExOutcome.BOMBARD_FAIL || 197 outcome == PunExOutcome.COLONY_NO_LONGER_EXISTS || 198 outcome == PunExOutcome.TASK_FORCE_DEFEATED) { 199 return base + " - Failed"; 200 } 201 } 202 return base; 203 } 204 205 206 @Override 207 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) { 208 //super.addBulletPoints(info, mode); 209 210 Color h = Misc.getHighlightColor(); 211 Color g = Misc.getGrayColor(); 212 float pad = 3f; 213 float opad = 10f; 214 215 float initPad = pad; 216 if (mode == ListInfoMode.IN_DESC) initPad = opad; 217 218 Color tc = getBulletColorForMode(mode); 219 220 bullet(info); 221 boolean isUpdate = getListInfoParam() != null; 222 223 if (getListInfoParam() == OUTCOME_UPDATE) { 224// if (isSucceeded()) { 225// info.addPara("Succeeded", initPad, tc); 226// } else { 227// 228// } 229// return; 230 } 231 232 if (getListInfoParam() == ENTERED_SYSTEM_UPDATE) { 233 FactionAPI other = target.getFaction(); 234 info.addPara("Target: %s", initPad, tc, 235 other.getBaseUIColor(), target.getName()); 236 initPad = 0f; 237 info.addPara("Arrived in-system", tc, initPad); 238// info.addPara("" + faction.getDisplayName() + " forces arrive in-system", initPad, tc, 239// faction.getBaseUIColor(), faction.getDisplayName()); 240 if (repResult != null) { 241 initPad = 0f; 242 CoreReputationPlugin.addAdjustmentMessage(repResult.delta, faction, null, 243 null, null, info, tc, isUpdate, initPad); 244 } 245 return; 246 } 247 248 249 FactionAPI other = targetFaction; 250 if (outcome != null) { 251 if (outcome == PunExOutcome.TASK_FORCE_DEFEATED) { 252 info.addPara("Expeditionary force defeated", tc, initPad); 253 } else if (outcome == PunExOutcome.COLONY_NO_LONGER_EXISTS) { 254 info.addPara("Expedition aborted", tc, initPad); 255 } else if (outcome == PunExOutcome.AVERTED) { 256 info.addPara("Expedition planning disrupted", initPad, tc, other.getBaseUIColor(), target.getName()); 257 } else if (outcome == PunExOutcome.BOMBARD_FAIL) { 258 info.addPara("Bombardment of %s failed", initPad, tc, other.getBaseUIColor(), target.getName()); 259 } else if (outcome == PunExOutcome.RAID_FAIL) { 260 info.addPara("Raid of %s failed", initPad, tc, other.getBaseUIColor(), target.getName()); 261 } else if (outcome == PunExOutcome.SUCCESS) { 262 if (goal == PunExGoal.BOMBARD) { 263 if (!target.isInEconomy()) { 264 info.addPara("%s destroyed by bombardment", initPad, tc, other.getBaseUIColor(), target.getName()); 265 } else { 266 info.addPara("Bombardment of %s successful", initPad, tc, other.getBaseUIColor(), target.getName()); 267 } 268 } else if (targetIndustry != null && targetIndustry.getDisruptedDays() >= 2) { 269 info.addPara(targetIndustry.getCurrentName() + " disrupted for %s days", 270 initPad, tc, h, "" + (int)Math.round(targetIndustry.getDisruptedDays())); 271 } 272 } 273 274 if (repResult != null) { 275 initPad = 0f; 276 CoreReputationPlugin.addAdjustmentMessage(repResult.delta, faction, null, 277 null, null, info, tc, isUpdate, initPad); 278 } 279 280 return; 281 } 282 283 info.addPara("Target: %s", initPad, tc, 284 other.getBaseUIColor(), target.getName()); 285 initPad = 0f; 286 287 if (goal == PunExGoal.BOMBARD) { 288 String goalStr = "saturation bombardment"; 289 info.addPara("Goal: %s", initPad, tc, Misc.getNegativeHighlightColor(), goalStr); 290 } 291 292 float eta = getETA(); 293 if (eta > 1 && !isEnding()) { 294 String days = getDaysString(eta); 295 info.addPara("Estimated %s " + days + " until arrival", 296 initPad, tc, h, "" + (int)Math.round(eta)); 297 initPad = 0f; 298 } else if (!isEnding() && action.getElapsed() > 0) { 299 info.addPara("Currently in-system", tc, initPad); 300 initPad = 0f; 301 } 302 303 if (repResult != null) { 304 initPad = 0f; 305 CoreReputationPlugin.addAdjustmentMessage(repResult.delta, faction, null, 306 null, null, info, tc, isUpdate, initPad); 307 } 308 309 unindent(info); 310 } 311 312 public PEActionStage getActionStage() { 313 for (RaidStage stage : stages) { 314 if (stage instanceof PEActionStage) { 315 return (PEActionStage) stage; 316 } 317 } 318 return null; 319 //return (PEActionStage) stages.get(2); 320 } 321 322 @Override 323 public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) { 324 super.createIntelInfo(info, mode); 325 } 326 327 328 public void addInitialDescSection(TooltipMakerAPI info, float initPad) { 329 Color h = Misc.getHighlightColor(); 330 float opad = 10f; 331 332 FactionAPI faction = getFaction(); 333 String is = faction.getDisplayNameIsOrAre(); 334 335 String goalDesc = ""; 336 String goalHL = ""; 337 Color goalColor = Misc.getTextColor(); 338 switch (goal) { 339 case RAID_PRODUCTION: 340 goalDesc = "disrupting the colony's " + targetIndustry.getCurrentName(); 341 break; 342 case RAID_SPACEPORT: 343 goalDesc = "raiding the colony's " + targetIndustry.getCurrentName() + " to disrupt its operations"; 344 break; 345 case BOMBARD: 346 goalDesc = "a saturation bombardment of the colony"; 347 goalHL = "saturation bombardment of the colony"; 348 goalColor = Misc.getNegativeHighlightColor(); 349 break; 350 } 351 352 String strDesc = getRaidStrDesc(); 353 int numFleets = (int) getOrigNumFleets(); 354 String fleets = "fleets"; 355 if (numFleets == 1) fleets = "fleet"; 356 357 if (outcome == null) { 358 LabelAPI label = info.addPara(Misc.ucFirst(faction.getDisplayNameWithArticle()) + " " + is + 359 " targeting %s with a " + strDesc + " expeditionary force, projected to be comprised of " + 360 numFleets + " " + fleets + ". " + 361 "Its likely goal is " + goalDesc + ".", 362 initPad, faction.getBaseUIColor(), target.getName()); 363 label.setHighlight(faction.getDisplayNameWithArticleWithoutArticle(), target.getName(), strDesc, "" + numFleets, goalHL); 364 label.setHighlightColors(faction.getBaseUIColor(), targetFaction.getBaseUIColor(), h, h, goalColor); 365 } else { 366 LabelAPI label = info.addPara(Misc.ucFirst(faction.getDisplayNameWithArticle()) + " " + is + 367 " targeting %s with an expeditionary force. " + 368 "Its likely goal is " + goalDesc + ".", 369 initPad, faction.getBaseUIColor(), target.getName()); 370 label.setHighlight(faction.getDisplayNameWithArticleWithoutArticle(), target.getName(), goalHL); 371 label.setHighlightColors(faction.getBaseUIColor(), targetFaction.getBaseUIColor(), goalColor); 372 } 373 } 374 375 @Override 376 public void createSmallDescription(TooltipMakerAPI info, float width, float height) { 377 //super.createSmallDescription(info, width, height); 378 379 Color h = Misc.getHighlightColor(); 380 Color g = Misc.getGrayColor(); 381 Color tc = Misc.getTextColor(); 382 float pad = 3f; 383 float opad = 10f; 384 385 info.addImage(getFactionForUIColors().getLogo(), width, 128, opad); 386 387 FactionAPI faction = getFaction(); 388 String has = faction.getDisplayNameHasOrHave(); 389 String is = faction.getDisplayNameIsOrAre(); 390 391 addInitialDescSection(info, opad); 392 393 if (bestReason.type == PunExType.ANTI_COMPETITION && bestReason.commodityId != null) { 394 CommoditySpecAPI spec = Global.getSettings().getCommoditySpec(bestReason.commodityId); 395 info.addPara("The primary reason for the expedition is the colony's market share " + 396 "in the exports of " + spec.getName() + ".", opad); 397 } else if (bestReason.type == PunExType.ANTI_FREE_PORT) { 398 info.addPara("The primary reason for the expedition is the colony's \"free port\" " + 399 "status, and the concomitant export of illegal goods alongside it being a haven for " + 400 "various undesirables.", opad); 401 } else if (bestReason.type == PunExType.TERRITORIAL) { 402 info.addPara("The primary reason for the expedition is the colony being established in " + 403 "space claimed by " + faction.getDisplayNameWithArticle() + ".", opad); 404 } 405 406 if (outcome == null) { 407 addStandardStrengthComparisons(info, target, targetFaction, goal != PunExGoal.BOMBARD, goal == PunExGoal.BOMBARD, 408 "expedition", "expedition's"); 409 } 410 411 info.addSectionHeading("Status", 412 faction.getBaseUIColor(), faction.getDarkUIColor(), Alignment.MID, opad); 413 414 for (RaidStage stage : stages) { 415 stage.showStageInfo(info); 416 if (getStageIndex(stage) == failStage) break; 417 } 418 419 if (getCurrentStage() == 0 && !isFailed()) { 420 FactionAPI pf = Global.getSector().getPlayerFaction(); 421 ButtonAPI button = info.addButton("Avert", BUTTON_AVERT, 422 pf.getBaseUIColor(), pf.getDarkUIColor(), 423 (int)(width), 20f, opad * 2f); 424 button.setShortcut(Keyboard.KEY_T, true); 425 } 426 427 428 if (!from.getFaction().isHostileTo(targetFaction) && !isFailed()) { 429// LabelAPI label = info.addPara("This operation is being carried " + 430// "without an open declaration of war. Fighting the " + 431// "expeditionary force will not result in " + faction.getDisplayNameWithArticle() + 432// " immediately becoming hostile, unless the relationship is already strained.", Misc.getGrayColor(), 433// opad); 434// LabelAPI label = info.addPara("This operation is being carried " + 435// "without an open declaration of war. Fighting the " + 436// "expeditionary force will not result in reputation changes with " + faction.getDisplayNameWithArticle() + 437// ".", Misc.getGrayColor(), 438// opad); 439 LabelAPI label = info.addPara("This operation is being carried " + 440 "without an open declaration of war. Defeating the " + 441 "expeditionary force will only result in a small reputation reduction with " + faction.getDisplayNameWithArticle() + 442 ".", Misc.getGrayColor(), 443 opad); 444 label.setHighlight(faction.getDisplayNameWithArticleWithoutArticle()); 445 label.setHighlightColors(faction.getBaseUIColor()); 446 } 447 } 448 449 450 451 @Override 452 public void sendUpdateIfPlayerHasIntel(Object listInfoParam, boolean onlyIfImportant, boolean sendIfHidden) { 453 454 if (listInfoParam == UPDATE_RETURNING) { 455 // we're using sendOutcomeUpdate() to send an end-of-event update instead 456 return; 457 } 458 459 if (listInfoParam == UPDATE_FAILED) { 460 applyRepPenalty(); 461 } 462 463 super.sendUpdateIfPlayerHasIntel(listInfoParam, onlyIfImportant, sendIfHidden); 464 } 465 466 @Override 467 public Set<String> getIntelTags(SectorMapAPI map) { 468 //return super.getIntelTags(map); 469 470 Set<String> tags = super.getIntelTags(map); 471 tags.add(Tags.INTEL_MILITARY); 472 tags.add(Tags.INTEL_COLONIES); 473 tags.add(getFaction().getId()); 474 return tags; 475 } 476 477 478 public void notifyRaidEnded(RaidIntel raid, RaidStageStatus status) { 479 if (outcome == null && failStage >= 0) { 480 if (!target.isInEconomy() || !target.isPlayerOwned()) { 481 outcome = PunExOutcome.COLONY_NO_LONGER_EXISTS; 482 } else { 483 outcome = PunExOutcome.TASK_FORCE_DEFEATED; 484 } 485 } 486 487 PunExData data = PunitiveExpeditionManager.getInstance().getDataFor(faction); 488 if (data != null) { 489 if (outcome == PunExOutcome.SUCCESS) { 490 data.numSuccesses++; 491 } 492 } 493 } 494 495 496 @Override 497 public String getIcon() { 498 return faction.getCrest(); 499 } 500 501 public PunExGoal getGoal() { 502 return goal; 503 } 504 505 public Industry getTargetIndustry() { 506 return targetIndustry; 507 } 508 509 public PunExOutcome getOutcome() { 510 return outcome; 511 } 512 513 public void setOutcome(PunExOutcome outcome) { 514 this.outcome = outcome; 515 } 516 517 518 public CampaignFleetAPI spawnFleet(RouteData route) { 519 Random random = route.getRandom(); 520 521 MarketAPI market = route.getMarket(); 522 CampaignFleetAPI fleet = createFleet(market.getFactionId(), route, market, null, random); 523 524 if (fleet == null || fleet.isEmpty()) return null; 525 526 //fleet.addEventListener(this); 527 528 market.getContainingLocation().addEntity(fleet); 529 fleet.setFacing((float) Math.random() * 360f); 530 // this will get overridden by the patrol assignment AI, depending on route-time elapsed etc 531 fleet.setLocation(market.getPrimaryEntity().getLocation().x, market.getPrimaryEntity().getLocation().x); 532 533 fleet.addScript(createAssignmentAI(fleet, route)); 534 535 return fleet; 536 } 537 538 public CampaignFleetAPI createFleet(String factionId, RouteData route, MarketAPI market, Vector2f locInHyper, Random random) { 539 if (random == null) random = new Random(); 540 541 OptionalFleetData extra = route.getExtra(); 542 543 float combat = extra.fp; 544 float tanker = extra.fp * (0.1f + random.nextFloat() * 0.05f); 545 float transport = extra.fp * (0.1f + random.nextFloat() * 0.05f); 546 float freighter = 0f; 547 548 if (goal == PunExGoal.BOMBARD) { 549 tanker += transport; 550 } else { 551 transport += tanker / 2f; 552 tanker *= 0.5f; 553 } 554 555 combat -= tanker; 556 combat -= transport; 557 558 559 FleetParamsV3 params = new FleetParamsV3( 560 market, 561 locInHyper, 562 factionId, 563 route == null ? null : route.getQualityOverride(), 564 extra.fleetType, 565 combat, // combatPts 566 freighter, // freighterPts 567 tanker, // tankerPts 568 transport, // transportPts 569 0f, // linerPts 570 0f, // utilityPts 571 0f // qualityMod, won't get used since routes mostly have quality override set 572 ); 573 //params.ignoreMarketFleetSizeMult = true; // already accounted for in extra.fp 574 575 if (route != null) { 576 params.timestamp = route.getTimestamp(); 577 } 578 params.random = random; 579 CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params); 580 581 if (fleet == null || fleet.isEmpty()) return null; 582 583 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_WAR_FLEET, true); 584 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_RAIDER, true); 585 586 if (fleet.getFaction().getCustomBoolean(Factions.CUSTOM_PIRATE_BEHAVIOR)) { 587 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_PIRATE, true); 588 } 589 590 String postId = Ranks.POST_PATROL_COMMANDER; 591 String rankId = Ranks.SPACE_COMMANDER; 592 593 fleet.getCommander().setPostId(postId); 594 fleet.getCommander().setRankId(rankId); 595 596 Misc.makeNoRepImpact(fleet, "punex"); 597 Misc.makeHostile(fleet); 598 599 return fleet; 600 } 601 602 603 public void buttonPressConfirmed(Object buttonId, IntelUIAPI ui) { 604 if (buttonId == BUTTON_AVERT) { 605 ui.showDialog(null, new PEAvertInteractionDialogPluginImpl(this, ui)); 606 } 607 } 608 609 public PunExReason getBestReason() { 610 return bestReason; 611 } 612 613 public boolean isTerritorial() { 614 return bestReason != null && bestReason.type == PunExType.TERRITORIAL; 615 } 616 617 @Override 618 public SectorEntityToken getMapLocation(SectorMapAPI map) { 619 if (target != null && target.isInEconomy() && target.getPrimaryEntity() != null) { 620 return target.getPrimaryEntity(); 621 } 622 return super.getMapLocation(map); 623 } 624 625// @Override 626// public List<ArrowData> getArrowData(SectorMapAPI map) { 627// 628// } 629} 630 631 632 633 634 635