001package com.fs.starfarer.api.impl.campaign.intel.events; 002 003import java.util.Random; 004 005import java.awt.Color; 006 007import org.lwjgl.util.vector.Vector2f; 008 009import com.fs.starfarer.api.Global; 010import com.fs.starfarer.api.campaign.CampaignFleetAPI; 011import com.fs.starfarer.api.campaign.StarSystemAPI; 012import com.fs.starfarer.api.campaign.comm.CommMessageAPI.MessageClickAction; 013import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin.ListInfoMode; 014import com.fs.starfarer.api.campaign.econ.Industry; 015import com.fs.starfarer.api.campaign.econ.MarketAPI; 016import com.fs.starfarer.api.impl.campaign.NPCHassler; 017import com.fs.starfarer.api.impl.campaign.ids.Factions; 018import com.fs.starfarer.api.impl.campaign.ids.FleetTypes; 019import com.fs.starfarer.api.impl.campaign.ids.Industries; 020import com.fs.starfarer.api.impl.campaign.ids.Sounds; 021import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin; 022import com.fs.starfarer.api.impl.campaign.intel.MessageIntel; 023import com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.EventStageData; 024import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.HAERandomEventData; 025import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.Stage; 026import com.fs.starfarer.api.impl.campaign.intel.inspection.HegemonyInspectionIntel; 027import com.fs.starfarer.api.impl.campaign.intel.inspection.HegemonyInspectionIntel.HegemonyInspectionOutcome; 028import com.fs.starfarer.api.impl.campaign.intel.inspection.HegemonyInspectionIntel.InspectionEndedListener; 029import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission; 030import com.fs.starfarer.api.ui.LabelAPI; 031import com.fs.starfarer.api.ui.TooltipMakerAPI; 032import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator; 033import com.fs.starfarer.api.util.DelayedActionScript; 034import com.fs.starfarer.api.util.Misc; 035import com.fs.starfarer.api.util.WeightedRandomPicker; 036 037public class HegemonyHostileActivityFactor extends BaseHostileActivityFactor implements InspectionEndedListener { 038 039 public static final String HASSLE_REASON = "hegemonyInvestigator"; 040 041 public static String DEFEATED_HEGEMONY = "$defeatedHegemony"; 042 043 public static String INSPECTION_ATTEMPTS = "$hegemonyInspectionAttempts"; 044 public static String INSPECTIONS_DEFEATED = "$hegemonyInspectionsDefeated"; 045 046 public static int INSPECTIONS_TO_DEFEAT = 3; 047 048 public static float INSPECTION_STRENGTH_FIRST = 150; 049 public static float INSPECTION_STRENGTH_SECOND = 600; 050 public static float INSPECTION_STRENGTH_FINAL = 1400; 051 052 public static boolean isPlayerDefeatedHegemony() { 053 return Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(DEFEATED_HEGEMONY); 054 } 055 public static void setPlayerDefeatedHegemony() { 056 Global.getSector().getPlayerMemoryWithoutUpdate().set(DEFEATED_HEGEMONY, true); 057 } 058 059 public static int getInspectionAttempts() { 060 return Global.getSector().getPlayerMemoryWithoutUpdate().getInt(INSPECTION_ATTEMPTS); 061 } 062 public static void incrInspectionAttempts() { 063 Global.getSector().getPlayerMemoryWithoutUpdate().set(INSPECTION_ATTEMPTS, getInspectionAttempts() + 1); 064 } 065 066 public static int getInspectionsDefeated() { 067 return Global.getSector().getPlayerMemoryWithoutUpdate().getInt(INSPECTIONS_DEFEATED); 068 } 069 public static void incrInspectionsDefeated() { 070 Global.getSector().getPlayerMemoryWithoutUpdate().set(INSPECTIONS_DEFEATED, getInspectionsDefeated() + 1); 071 } 072 073 074 public HegemonyHostileActivityFactor(HostileActivityEventIntel intel) { 075 super(intel); 076 077 //Global.getSector().getListenerManager().addListener(this); 078 } 079 080 public String getProgressStr(BaseEventIntel intel) { 081 return ""; 082 } 083 084 @Override 085 public int getProgress(BaseEventIntel intel) { 086 if (!checkFactionExists(Factions.HEGEMONY, true)) { 087 return 0; 088 } 089 return super.getProgress(intel); 090 } 091 092 public float getEffectMagnitude(StarSystemAPI system) {//, boolean adjustByEventProgress) { 093 if (!checkFactionExists(Factions.HEGEMONY, true)) { 094 return 0; 095 } 096 return super.getEffectMagnitude(system); 097 } 098 099 public String getDesc(BaseEventIntel intel) { 100 return "Hegemony"; 101 } 102 103 public String getNameForThreatList(boolean first) { 104 return "Hegemony"; 105 } 106 107 108 public Color getDescColor(BaseEventIntel intel) { 109 if (getProgress(intel) <= 0) { 110 return Misc.getGrayColor(); 111 } 112 return Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor(); 113 } 114 115 public TooltipCreator getMainRowTooltip(BaseEventIntel intel) { 116 return new BaseFactorTooltip() { 117 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) { 118 float opad = 10f; 119 120 tooltip.addPara("The Hegemony considers the use of AI cores illegal and will not tolerate it " 121 + "even outside the volume of the core worlds.", 0f); 122 tooltip.addPara("Fleets investigating your AI core use can sometimes be found in your space, not overtly " 123 + "hostile, but harassing your shipping and generally acting in a high-handed way.", opad); 124 } 125 }; 126 } 127 128 public boolean shouldShow(BaseEventIntel intel) { 129 boolean shouldShowDueToCause = false; 130 for (HostileActivityCause2 cause : getCauses()) { 131 shouldShowDueToCause |= cause.shouldShow(); 132 } 133 return getProgress(intel) > 0 || shouldShowDueToCause; 134 } 135 136 137 138 @Override 139 public int getMaxNumFleets(StarSystemAPI system) { 140 return Global.getSettings().getInt("hegemonyMaxFleets"); 141 } 142 143 public CampaignFleetAPI createFleet(StarSystemAPI system, Random random) { 144 145 float f = 0f; 146 //f += getEffectMagnitude(system); 147 f += intel.getMarketPresenceFactor(system); 148 149 if (f > 1f) f = 1f; 150 151// float fInvestigators = Global.getSettings().getFloat("hegemonyInvestigatorsFreq"); 152// float fRecon = Global.getSettings().getFloat("hegemonyReconFreq"); 153// 154// WeightedRandomPicker<Integer> picker = new WeightedRandomPicker<Integer>(random); 155// picker.add(1, fInvestigators); 156// picker.add(2, fRecon); 157// 158// int pick = picker.pick(); 159// boolean recon = pick == 2; 160 boolean recon = false; 161 162 int difficulty = 0; 163 164 if (recon) { 165 difficulty = 1 + random.nextInt(2); 166 } else { 167 difficulty = 3; 168 difficulty += (int) Math.round(f * 5f); 169 difficulty += random.nextInt(4); 170 } 171 172 173 FleetCreatorMission m = new FleetCreatorMission(random); 174 m.beginFleet(); 175 176 Vector2f loc = system.getLocation(); 177 String factionId = Factions.HEGEMONY; 178 179 if (recon) { 180 m.createStandardFleet(difficulty, factionId, loc); 181 } else { 182 m.createStandardFleet(difficulty, factionId, loc); 183 } 184 185 m.triggerSetFleetType(FleetTypes.INVESTIGATORS); 186 m.triggerSetPatrol(); 187 188 if (!recon) { 189 m.triggerSetFleetHasslePlayer(HASSLE_REASON); 190 m.triggerSetFleetFlag("$hegemonyInvestigator"); 191 m.triggerFleetAllowLongPursuit(); 192 } 193 194 m.triggerMakeLowRepImpact(); 195 196 CampaignFleetAPI fleet = m.createFleet(); 197 198 if (fleet != null && !recon) { 199 fleet.addScript(new NPCHassler(fleet, system)); 200 } 201 202 return fleet; 203 } 204 205 206 @Override 207 public void notifyFactorRemoved() { 208 //Global.getSector().getListenerManager().removeListener(this); 209 } 210 211 public void notifyEventEnding() { 212 notifyFactorRemoved(); 213 } 214 215 216 public void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, 217 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) { 218 219 if (!(stage.rollData instanceof HAERandomEventData)) return; 220 HAERandomEventData data = (HAERandomEventData) stage.rollData; 221 MarketAPI target = (MarketAPI) data.custom; 222 223 //MarketAPI target = pickTargetMarket(); 224 if (target == null) return; 225 226 MarketAPI from = pickSourceMarket(); 227 if (from == null) return; 228 229 Color c = Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor(); 230 231 LabelAPI label = info.addPara("Upcoming Hegemony AI inspection targeting %s", 232 initPad, tc, tc, target.getName()); 233 label.setHighlight("Hegemony", target.getName()); 234 label.setHighlightColors(c, Misc.getBasePlayerColor()); 235 } 236 237 public void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, 238 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) { 239 info.addPara("Hegemony AI inspection averted", tc, initPad); 240 } 241 242 public void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info) { 243 if (!(stage.rollData instanceof HAERandomEventData)) return; 244 HAERandomEventData data = (HAERandomEventData) stage.rollData; 245 MarketAPI target = (MarketAPI) data.custom; 246 247 //MarketAPI target = pickTargetMarket(); 248 if (target == null) return; 249 250 MarketAPI from = pickSourceMarket(); 251 if (from == null) return; 252 253 Color c = Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor(); 254 255 float small = 0f; 256 float opad = 10f; 257 258 small = 8f; 259 260 LabelAPI label = info.addPara("You've received intel that the Hegemony is planning " 261 + "an AI insprection targeting %s. If the inspection arrives at your colony, " 262 + "your options would include open hostilities with the Hegemony, or the loss of " 263 + "at least some of your AI cores.", 264 small, c, target.getName()); 265 label.setHighlight(target.getName(), "open hostilities", "loss of at least some of your AI cores"); 266 label.setHighlightColors(Misc.getBasePlayerColor(), Misc.getNegativeHighlightColor(), Misc.getNegativeHighlightColor()); 267 268 int defeated = getInspectionsDefeated(); 269 if (defeated < INSPECTIONS_TO_DEFEAT - 1) { 270 label = info.addPara("If this inspection is defeated by military means, the Hegemony is likely to " 271 + "escalate the conflict, although only up to a point.", 272 opad, Misc.getNegativeHighlightColor(), "escalate the conflict"); 273 label.setHighlight("escalate the conflict", "up to a point"); 274 label.setHighlightColors(Misc.getNegativeHighlightColor(), Misc.getPositiveHighlightColor()); 275 } else { 276 info.addPara("If this massive inspection force - a declaration of war in all but name - is defeated," 277 + " the Hegemony is likely to reconsider the viability of their approach.", 278 opad, Misc.getPositiveHighlightColor(), "reconsider"); 279 } 280 281 282 stage.beginResetReqList(info, true, "crisis", opad); 283 info.addPara("The %s has no functional military bases", 0f, c, "Hegemony"); 284 stage.endResetReqList(info, false, "crisis", -1, -1); 285 286 addBorder(info, Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor()); 287 } 288 289 290 public String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage) { 291 return Global.getSector().getFaction(Factions.HEGEMONY).getCrest(); 292 } 293 294 public TooltipCreator getStageTooltipImpl(final HostileActivityEventIntel intel, final EventStageData stage) { 295 if (stage.id == Stage.HA_EVENT) { 296 return getDefaultEventTooltip("Hegemony AI inspection", intel, stage); 297 } 298 return null; 299 } 300 301 302 public float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage) { 303 if (stage.id == Stage.HA_EVENT) { 304 if (pickTargetMarket() != null && pickSourceMarket() != null) { 305 return 10f; 306 } 307 } 308 return 0; 309 } 310 311 public MarketAPI pickTargetMarket() { 312 WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>(getRandomizedStageRandom()); 313 314 float alpha = Global.getSettings().getFloat("hegemonyPointsAlpha"); 315 float beta = Global.getSettings().getFloat("hegemonyPointsBeta"); 316 float gamma = Global.getSettings().getFloat("hegemonyPointsGamma"); 317 318 float threshold = alpha + beta + gamma; 319 for (MarketAPI market : Misc.getPlayerMarkets(false)) { 320 // to put a damper on shenanigans with establishing and abandoning a colony 321 // with an Alpha Core admin to bait an attack 322 if (market.getDaysInExistence() < 180f && !Global.getSettings().isDevMode()) continue; 323 324 float w = HegemonyAICoresActivityCause.getAICorePoints(market); 325 if (w <= threshold) continue; 326 picker.add(market, w * w); 327 } 328 return picker.pick(); 329 } 330 331 public MarketAPI pickSourceMarket() { 332 WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>(getRandomizedStageRandom(7)); 333 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) { 334 if (market.getFactionId().equals(Factions.HEGEMONY)) { 335 Industry b = market.getIndustry(Industries.MILITARYBASE); 336 if (b == null) b = market.getIndustry(Industries.HIGHCOMMAND); 337 if (b == null || b.isDisrupted() || !b.isFunctional()) { 338 continue; 339 } 340 picker.add(market, market.getSize()); 341 } 342 } 343 MarketAPI from = picker.pick(); 344 return from; 345 } 346 347 348 public void rollEvent(HostileActivityEventIntel intel, EventStageData stage) { 349// if (true) return; 350 351 if (isPlayerDefeatedHegemony()) return; 352 353 MarketAPI market = pickTargetMarket(); 354 if (market == null) return; 355 356 MarketAPI from = pickSourceMarket(); 357 if (from == null) return; 358 359 HAERandomEventData data = new HAERandomEventData(this, stage); 360 data.custom = market; 361 stage.rollData = data; 362 intel.sendUpdateIfPlayerHasIntel(data, false); 363 } 364 365 public boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage) { 366 //if (true) return false; 367 368 if (isPlayerDefeatedHegemony()) return false; 369 370 //MarketAPI market = pickTargetMarket(); 371 if (!(stage.rollData instanceof HAERandomEventData)) return false; 372 HAERandomEventData data = (HAERandomEventData) stage.rollData; 373 MarketAPI market = (MarketAPI) data.custom; 374 375 if (market == null) return false; 376 if (!market.isInEconomy()) return false; 377 378 MarketAPI from = pickSourceMarket(); 379 if (from == null) return false; 380 381 StarSystemAPI system = market.getStarSystem(); 382 if (system == null) return false; 383 384 return createInspection(market, null); 385 } 386 387 388 public boolean createInspection(MarketAPI target, Integer fpOverride) { 389 390// MarketAPI target = pickTargetMarket(); 391// if (target == null) return false; 392 393 MarketAPI from = pickSourceMarket(); 394 if (from == null) return false; 395 396 397 float fp; 398 int defeated = getInspectionsDefeated(); 399 //defeated = 2; 400 401 if (defeated <= 0) { 402 fp = INSPECTION_STRENGTH_FIRST; 403 } else if (defeated == 1) { 404 fp = INSPECTION_STRENGTH_SECOND; 405 } else { 406 fp = INSPECTION_STRENGTH_FINAL; 407 } 408 409 //fp = 500; 410 if (fpOverride != null) { 411 fp = fpOverride; 412 } 413 HegemonyInspectionIntel inspection = new HegemonyInspectionIntel(from, target, fp); 414 if (inspection.isDone()) { 415 inspection = null; 416 return false; 417 } 418 419 inspection.setListener(this); 420 421 incrInspectionAttempts(); 422 423 return true; 424 } 425 426 427 @Override 428 public void advance(float amount) { 429 super.advance(amount); 430 431 EventStageData stage = intel.getDataFor(Stage.HA_EVENT); 432 if (stage != null && stage.rollData instanceof HAERandomEventData && 433 ((HAERandomEventData)stage.rollData).factor == this) { 434 if (pickSourceMarket() == null) { 435 intel.resetHA_EVENT(); 436 } 437 } 438 } 439 440 public static void avertInspectionIfNotInProgress() { 441 HostileActivityEventIntel intel = HostileActivityEventIntel.get(); 442 if (intel == null) return; 443 444 HAERandomEventData data = intel.getRollDataForEvent(); 445 if (data != null && data.factor instanceof HegemonyHostileActivityFactor) { 446 intel.resetHA_EVENT(); 447 } 448 } 449 450 451 public void notifyInspectionEnded(HegemonyInspectionOutcome outcome) { 452 // also called when aborted from military base being destroyed, with same outcome enum 453 if (outcome == HegemonyInspectionOutcome.TASK_FORCE_DESTROYED) { 454 incrInspectionsDefeated(); 455 int defeated = getInspectionsDefeated(); 456 if (defeated >= INSPECTIONS_TO_DEFEAT) { 457 setPlayerDefeatedHegemony(); 458 459 Global.getSector().addScript(new DelayedActionScript(0.1f) { 460 @Override 461 public void doAction() { 462 MessageIntel msg = new MessageIntel(); 463 msg.addLine("Major Hegemony defeat!", Misc.getBasePlayerColor()); 464 msg.addLine(BaseIntelPlugin.BULLET + 465 "You may be able to discuss the situation with the High Hegemon on Chicomoztoc"); 466 msg.setIcon(Global.getSector().getFaction(Factions.HEGEMONY).getCrest()); 467 msg.setSound(Sounds.REP_GAIN); 468 Global.getSector().getCampaignUI().addMessage(msg, MessageClickAction.NOTHING); 469 } 470 }); 471 } 472 } 473 } 474 475} 476 477 478 479