001package com.fs.starfarer.api.impl.campaign.intel.events; 002 003import java.util.List; 004import java.util.Random; 005 006import java.awt.Color; 007 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.StarSystemAPI; 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.ids.Conditions; 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.Stats; 021import com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.EventStageData; 022import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.HAERandomEventData; 023import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.Stage; 024import com.fs.starfarer.api.impl.campaign.intel.events.TriTachyonStandardActivityCause.CompetitorData; 025import com.fs.starfarer.api.impl.campaign.intel.group.FGRaidAction.FGRaidType; 026import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel; 027import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel.FGIEventListener; 028import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI.GenericRaidParams; 029import com.fs.starfarer.api.impl.campaign.intel.group.SindrianDiktatPunitiveExpedition; 030import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission; 031import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission.FleetStyle; 032import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.BombardType; 033import com.fs.starfarer.api.ui.LabelAPI; 034import com.fs.starfarer.api.ui.TooltipMakerAPI; 035import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator; 036import com.fs.starfarer.api.util.CountingMap; 037import com.fs.starfarer.api.util.Misc; 038 039public class SindrianDiktatHostileActivityFactor extends BaseHostileActivityFactor 040 implements FGIEventListener { 041 042 public static String DEFEATED_DIKTAT_ATTACK = "$defeatedDiktatAttack"; 043 public static String MADE_DIKTAT_DEAL = "$makeDiktatDeal"; 044 public static String BROKE_DIKTAT_DEAL = "$brokeDiktatDeal"; 045 046 public static String RAIDER_FLEET = "$diktatRaider"; 047 048 public static boolean isMadeDeal() { 049 return Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(MADE_DIKTAT_DEAL); 050 } 051 public static void setMadeDeal(boolean value) { 052 Global.getSector().getPlayerMemoryWithoutUpdate().set(MADE_DIKTAT_DEAL, value); 053 } 054 055 public static boolean brokeDeal() { 056 return Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(BROKE_DIKTAT_DEAL); 057 } 058 public static void setBrokeDeal(boolean broke) { 059 Global.getSector().getPlayerMemoryWithoutUpdate().set(BROKE_DIKTAT_DEAL, broke); 060 } 061 062 public static boolean isPlayerDefeatedDiktatAttack() { 063 return Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(DEFEATED_DIKTAT_ATTACK); 064 } 065 public static void setPlayerDefeatedDiktatAttack() { 066 Global.getSector().getPlayerMemoryWithoutUpdate().set(DEFEATED_DIKTAT_ATTACK, true); 067 } 068 069 public SindrianDiktatHostileActivityFactor(HostileActivityEventIntel intel) { 070 super(intel); 071 072 //Global.getSector().getListenerManager().addListener(this); 073 } 074 075 public String getProgressStr(BaseEventIntel intel) { 076 return ""; 077 } 078 079 public String getDesc(BaseEventIntel intel) { 080 return "Sindrian Diktat"; 081 } 082 083 public String getNameForThreatList(boolean first) { 084 return "Sindrian Diktat"; 085 } 086 087 088 public Color getDescColor(BaseEventIntel intel) { 089 if (getProgress(intel) <= 0) { 090 return Misc.getGrayColor(); 091 } 092 return Global.getSector().getFaction(Factions.DIKTAT).getBaseUIColor(); 093 } 094 095 public TooltipCreator getMainRowTooltip(BaseEventIntel intel) { 096 return new BaseFactorTooltip() { 097 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) { 098 float opad = 10f; 099 tooltip.addPara("You've attracted the attention of the Sindrian Diktat.", 0f); 100 101 tooltip.addPara("Sindrian raider fleets have been sighted in your space, " 102 + "attacking trade fleets regardless of their factional allegiance.", opad); 103 } 104 }; 105 } 106 107 public boolean shouldShow(BaseEventIntel intel) { 108 return getProgress(intel) > 0; 109 } 110 111 @Override 112 public int getProgress(BaseEventIntel intel) { 113 if (!checkFactionExists(Factions.DIKTAT, true)) { 114 return 0; 115 } 116 return super.getProgress(intel); 117 } 118 119 public Color getNameColor(float mag) { 120 if (mag <= 0f) { 121 return Misc.getGrayColor(); 122 } 123 return Global.getSector().getFaction(Factions.DIKTAT).getBaseUIColor(); 124 } 125 126 127 @Override 128 public int getMaxNumFleets(StarSystemAPI system) { 129 return Global.getSettings().getInt("diktatMaxFleets"); 130 } 131 132 public CampaignFleetAPI createFleet(StarSystemAPI system, Random random) { 133 134 float f = intel.getMarketPresenceFactor(system); 135 136 int difficulty = 4 + (int) Math.round(f * 4f); 137 138 FleetCreatorMission m = new FleetCreatorMission(random); 139 m.beginFleet(); 140 141 Vector2f loc = system.getLocation(); 142 String factionId = Factions.DIKTAT; 143 144 m.createQualityFleet(difficulty, factionId, loc); 145 146 m.triggerSetFleetType(FleetTypes.RAIDER); 147 148 m.triggerSetPirateFleet(); 149 m.triggerMakeHostile(); 150 m.triggerMakeNonHostileToFaction(Factions.DIKTAT); 151 m.triggerMakeNonHostileToFaction(Factions.PIRATES); 152 m.triggerMakeLowRepImpact(); 153 m.triggerFleetAllowLongPursuit(); 154 m.triggerMakeHostileToAllTradeFleets(); 155 m.triggerMakeEveryoneJoinBattleAgainst(); 156 157 m.triggerSetFleetFlag(RAIDER_FLEET); 158 159 m.triggerFleetMakeFaster(true, 0, true); 160 161 //m.triggerSetFleetMaxShipSize(3); 162 163 164 CampaignFleetAPI fleet = m.createFleet(); 165 166 return fleet; 167 } 168 169 170 171 172 public void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, 173 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) { 174 Color c = Global.getSector().getFaction(Factions.DIKTAT).getBaseUIColor(); 175 info.addPara("Impending Sindrian Diktat attack", initPad, tc, c, "Sindrian Diktat"); 176 } 177 178 public void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, 179 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) { 180 info.addPara("Sindrian Diktat attack averted", tc, initPad); 181 } 182 183 public void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info) { 184 float small = 0f; 185 float opad = 10f; 186 187 small = 8f; 188 189 Color c = Global.getSector().getFaction(Factions.DIKTAT).getBaseUIColor(); 190 191 Color h = Misc.getHighlightColor(); 192 info.addPara("You've received intel that the Sindrian Diktat is planning an attack to " 193 + "saturation-bombard your fuel production facilities.", 194 small, Misc.getNegativeHighlightColor(), "saturation-bombard"); 195 196// LabelAPI label = info.addPara("If the attack is defeated, your standing with the Hegemony " 197// + "and the independents will increase substantially, and the Diktat will likely abandon " 198// + "further efforts against you. In addition, your ability to export fuel will be improved.", 199// opad); 200// label.setHighlight("Hegemony", "independents", "increase substantially", "Diktat", 201// "ability to export fuel will be improved"); 202// label.setHighlightColors(Global.getSector().getFaction(Factions.HEGEMONY).getBaseUIColor(), 203// Global.getSector().getFaction(Factions.INDEPENDENT).getBaseUIColor(), 204// Misc.getPositiveHighlightColor(), 205// Global.getSector().getFaction(Factions.DIKTAT).getBaseUIColor(), 206// Misc.getPositiveHighlightColor()); 207 208 LabelAPI label = info.addPara("If the attack is defeated the Diktat will likely abandon " 209 + "further efforts against you, and your ability to export fuel will be improved.", 210 opad); 211 label.setHighlight("Diktat", 212 "export fuel", "improved"); 213 label.setHighlightColors( 214 Global.getSector().getFaction(Factions.DIKTAT).getBaseUIColor(), 215 Misc.getPositiveHighlightColor(), 216 Misc.getPositiveHighlightColor()); 217 218 c = Global.getSector().getFaction(Factions.DIKTAT).getBaseUIColor(); 219 stage.beginResetReqList(info, true, "crisis", opad); 220 info.addPara("You go to %s and make an agreement with the Diktat", 0f, c, "Sindria"); 221 info.addPara("%s is tactically bombarded", 0f, c, "Sindria"); 222 info.addPara("Fuel production on %s is significantly disrupted", 0f, c, "Sindria"); 223 stage.endResetReqList(info, false, "crisis", -1, -1); 224 225 addBorder(info, Global.getSector().getFaction(Factions.DIKTAT).getBaseUIColor()); 226 } 227 228 229 public String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage) { 230 return Global.getSector().getFaction(Factions.DIKTAT).getCrest(); 231 } 232 233 public TooltipCreator getStageTooltipImpl(final HostileActivityEventIntel intel, final EventStageData stage) { 234 if (stage.id == Stage.HA_EVENT) { 235 return getDefaultEventTooltip("Sindrian Diktat attack", intel, stage); 236 } 237 return null; 238 } 239 240 public static Industry getSindrianFuelProd() { 241 MarketAPI sindria = getSindria(false); 242 if (sindria == null) return null; 243 244 Industry prod = sindria.getIndustry(Industries.FUELPROD); 245 return prod; 246 } 247 248 public static MarketAPI getSindria(boolean requireMilitaryBase) { 249 MarketAPI sindria = Global.getSector().getEconomy().getMarket("sindria"); 250 if (sindria == null || sindria.hasCondition(Conditions.DECIVILIZED) || 251 !sindria.getFactionId().equals(Factions.DIKTAT)) { 252 return null; 253 } 254 if (requireMilitaryBase) { 255 Industry b = sindria.getIndustry(Industries.MILITARYBASE); 256 if (b == null) b = sindria.getIndustry(Industries.HIGHCOMMAND); 257 if (b == null || b.isDisrupted() || !b.isFunctional()) { 258 return null; 259 } 260 } 261 return sindria; 262 } 263 264 265 public float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage) { 266 if (stage.id == Stage.HA_EVENT) { 267 268 if (isPlayerDefeatedDiktatAttack() || getSindria(true) == null) { 269 return 0f; 270 } 271 272 if (isMadeDeal()) return 0f; 273 274 if (SindrianDiktatPunitiveExpedition.get() != null) { 275 return 0f; 276 } 277 278 MarketAPI target = findExpeditionTarget(intel, stage); 279 MarketAPI source = getSindria(true); 280 if (target != null && source != null) { 281 return 10f; 282 } 283 } 284 return 0; 285 } 286 287 288 public void rollEvent(HostileActivityEventIntel intel, EventStageData stage) { 289 HAERandomEventData data = new HAERandomEventData(this, stage); 290 stage.rollData = data; 291 intel.sendUpdateIfPlayerHasIntel(data, false); 292 } 293 294 public boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage) { 295 MarketAPI target = findExpeditionTarget(intel, stage); 296 MarketAPI source = getSindria(true); 297 298 if (source == null || target == null) { 299 return false; 300 } 301 302 stage.rollData = null; 303 return startAttack(source, target, target.getStarSystem(), stage, getRandomizedStageRandom(3)); 304 } 305 306 307 public static MarketAPI findExpeditionTarget(HostileActivityEventIntel intel, EventStageData stage) { 308 List<CompetitorData> data = SindrianDiktatStandardActivityCause.computePlayerCompetitionData(); 309 CountingMap<MarketAPI> counts = new CountingMap<MarketAPI>(); 310 311 for (CompetitorData curr : data) { 312 for (MarketAPI market : curr.competitorProducers) { 313 StarSystemAPI system = market.getStarSystem(); 314 if (system == null) continue; 315 int weight = market.getCommodityData(curr.commodityId).getMaxSupply(); 316 counts.add(market, weight); 317 } 318 } 319 320 return counts.getLargest(); 321 } 322 323 324 public void reportFGIAborted(FleetGroupIntel intel) { 325 setPlayerDefeatedDiktatAttack(); 326 327 DiktatFuelBonusScript.grantBonus(); 328 } 329 330 331 @Override 332 public void notifyFactorRemoved() { 333 //Global.getSector().getListenerManager().removeListener(this); 334 } 335 336 public void notifyEventEnding() { 337 notifyFactorRemoved(); 338 } 339 340 341 @Override 342 public void advance(float amount) { 343 super.advance(amount); 344 345// float days = Misc.getDays(amount); 346 347// if (!Global.getSector().getListenerManager().hasListener(this)) { 348// Global.getSector().getListenerManager().addListener(this); 349// } 350 351// String key = "$wdfwefwe"; 352// if (!Global.getSector().getMemoryWithoutUpdate().getBoolean(key)) { 353// MarketAPI target = findExpeditionTarget(intel, null); 354// MarketAPI source = getSindria(true); 355// startAttack(source, target, target.getStarSystem(), null, new Random()); 356// Global.getSector().getMemoryWithoutUpdate().set(key, true); 357// } 358 359 EventStageData stage = intel.getDataFor(Stage.HA_EVENT); 360 if (stage != null && stage.rollData instanceof HAERandomEventData && 361 ((HAERandomEventData)stage.rollData).factor == this) { 362 363 Industry prod = getSindrianFuelProd(); 364 boolean prodOk = prod != null && prod.getSpecialItem() != null && !prod.isDisrupted(); 365 if (getSindria(true) == null || !prodOk) { 366 intel.resetHA_EVENT(); 367 } 368 } 369 370 } 371 372 373 374 public boolean startAttack(MarketAPI source, MarketAPI target, StarSystemAPI system, EventStageData stage, Random random) { 375 GenericRaidParams params = new GenericRaidParams(new Random(random.nextLong()), true); 376 377 params.makeFleetsHostile = false; // will be made hostile when they arrive, not before 378 379 params.factionId = source.getFactionId(); 380 params.source = source; 381 382 params.prepDays = 14f + random.nextFloat() * 14f; 383 params.payloadDays = 27f + 7f * random.nextFloat(); 384 385 params.raidParams.where = system; 386 params.raidParams.type = FGRaidType.SEQUENTIAL; 387 params.raidParams.tryToCaptureObjectives = false; 388 params.raidParams.allowedTargets.add(target); 389 params.raidParams.allowNonHostileTargets = true; 390 params.raidParams.setBombardment(BombardType.SATURATION); 391 392 params.style = FleetStyle.STANDARD; 393 394 395 // standard Askonia fleet size multiplier with no shortages/issues is a bit over 230% 396 float fleetSizeMult = source.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).computeEffective(0f); 397 398 float f = intel.getMarketPresenceFactor(system); 399 400 float totalDifficulty = fleetSizeMult * 15f * (0.6f + 0.4f * f); 401 402 if (totalDifficulty < 15) { 403 return false; 404 } 405 if (totalDifficulty > 100) { 406 totalDifficulty = 100; 407 } 408 409 totalDifficulty -= 10; 410 411 params.fleetSizes.add(10); 412 413 while (totalDifficulty > 0) { 414 int min = 6; 415 int max = 10; 416 417 //int diff = Math.round(StarSystemGenerator.getNormalRandom(random, min, max)); 418 int diff = min + random.nextInt(max - min + 1); 419 420 params.fleetSizes.add(diff); 421 totalDifficulty -= diff; 422 } 423 424 425 SindrianDiktatPunitiveExpedition punex = new SindrianDiktatPunitiveExpedition(params); 426 punex.setListener(this); 427 Global.getSector().getIntelManager().addIntel(punex); 428 429// GenericRaidFGI raid = new GenericRaidFGI(params); 430// raid.setListener(this); 431// Global.getSector().getIntelManager().addIntel(raid); 432 433 return true; 434 } 435 436} 437 438 439 440