001package com.fs.starfarer.api.impl.campaign.intel.events; 002 003import java.awt.Color; 004import java.util.Random; 005 006import com.fs.starfarer.api.Global; 007import com.fs.starfarer.api.campaign.CampaignFleetAPI; 008import com.fs.starfarer.api.campaign.StarSystemAPI; 009import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin.ListInfoMode; 010import com.fs.starfarer.api.campaign.econ.MarketAPI; 011import com.fs.starfarer.api.impl.campaign.ids.Factions; 012import com.fs.starfarer.api.impl.campaign.ids.Stats; 013import com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.EventStageData; 014import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.HAERandomEventData; 015import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.Stage; 016import com.fs.starfarer.api.impl.campaign.intel.group.FGRaidAction.FGRaidType; 017import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel; 018import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel.FGIEventListener; 019import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI; 020import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI.GenericRaidParams; 021import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission.FleetStyle; 022import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.ComplicationRepImpact; 023import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.BombardType; 024import com.fs.starfarer.api.ui.LabelAPI; 025import com.fs.starfarer.api.ui.TooltipMakerAPI; 026import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator; 027import com.fs.starfarer.api.util.Misc; 028import com.fs.starfarer.api.util.WeightedRandomPicker; 029 030public class RemnantHostileActivityFactor extends BaseHostileActivityFactor 031 implements FGIEventListener { 032 033 public RemnantHostileActivityFactor(HostileActivityEventIntel intel) { 034 super(intel); 035 036 //Global.getSector().getListenerManager().addListener(this); 037 } 038 039 public String getProgressStr(BaseEventIntel intel) { 040 return ""; 041 } 042 043 public String getDesc(BaseEventIntel intel) { 044 return "Remnant"; 045 } 046 047 public String getNameForThreatList(boolean first) { 048 return "Remnant"; 049 } 050 051 052 public Color getDescColor(BaseEventIntel intel) { 053 if (getProgress(intel) <= 0) { 054 return Misc.getGrayColor(); 055 } 056 return Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor(); 057 } 058 059 public TooltipCreator getMainRowTooltip(BaseEventIntel intel) { 060 return new BaseFactorTooltip() { 061 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) { 062 float opad = 10f; 063 tooltip.addPara("Remnant fleets have been sighted in your space.", opad); 064 } 065 }; 066 } 067 068 public boolean shouldShow(BaseEventIntel intel) { 069 return getProgress(intel) > 0; 070 } 071 072 @Override 073 public int getProgress(BaseEventIntel intel) { 074 return super.getProgress(intel); 075 } 076 077 public Color getNameColor(float mag) { 078 if (mag <= 0f) { 079 return Misc.getGrayColor(); 080 } 081 return Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor(); 082 } 083 084 085 @Override 086 public int getMaxNumFleets(StarSystemAPI system) { 087 return 0; // being spawned normally already 088 } 089 090 public CampaignFleetAPI createFleet(StarSystemAPI system, Random random) { 091 092// float f = intel.getMarketPresenceFactor(system); 093// 094// int difficulty = 4 + (int) Math.round(f * 4f); 095// 096// FleetCreatorMission m = new FleetCreatorMission(random); 097// m.beginFleet(); 098// 099// Vector2f loc = system.getLocation(); 100// String factionId = Factions.REMNANTS; 101// 102// m.createQualityFleet(difficulty, factionId, loc); 103// 104// m.triggerSetFleetType(FleetTypes.RAIDER); 105// 106// m.triggerSetPirateFleet(); 107// m.triggerMakeHostile(); 108// m.triggerMakeNonHostileToFaction(Factions.REMNANTS); 109// m.triggerMakeHostileToAllTradeFleets(); 110// m.triggerMakeNonHostileToFaction(Factions.PIRATES); 111// m.triggerMakeLowRepImpact(); 112// m.triggerFleetAllowLongPursuit(); 113// 114// m.triggerSetFleetFlag(RAIDER_FLEET); 115// 116// m.triggerFleetMakeFaster(true, 0, true); 117// 118// //m.triggerSetFleetMaxShipSize(3); 119// 120// 121// CampaignFleetAPI fleet = m.createFleet(); 122// 123// return fleet; 124 125 return null; 126 } 127 128 129 130 131 public void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, 132 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) { 133 Color c = Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor(); 134 info.addPara("Impending Remnant attack", initPad, tc, c, "Remnant"); 135 } 136 137 public void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, 138 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) { 139 info.addPara("Remnant attack averted", tc, initPad); 140 } 141 142 public void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info) { 143 float small = 0f; 144 float opad = 10f; 145 146 small = 8f; 147 148 Color c = Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor(); 149 150 if (!(stage.rollData instanceof HAERandomEventData)) return; 151 HAERandomEventData data = (HAERandomEventData) stage.rollData; 152 if (!(data.custom instanceof MarketAPI)) return; 153 154 MarketAPI target = (MarketAPI) data.custom; 155 156 Color h = Misc.getHighlightColor(); 157 info.addPara("There are signs of activity at a Remnant Nexus in your system. Intel evaluates " 158 + "a high probability of an attack fleet being assembled to saturation-bombard " + 159 target.getName() + ".", 160 small, Misc.getNegativeHighlightColor(), "saturation-bombard"); 161 162 LabelAPI label = info.addPara("Defeating the attack fleet would only put off the problem, " 163 + "but destroying the Remnant Nexus will end the threat for good.", 164 opad); 165 label.setHighlight("Remnant Nexus", "end the threat"); 166 label.setHighlightColors( 167 Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor(), 168 Misc.getPositiveHighlightColor()); 169 170 c = Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor(); 171 stage.beginResetReqList(info, true, "crisis", opad); 172 info.addPara("The %s is destroyed", 0f, c, "Remnant Nexus"); 173 stage.endResetReqList(info, false, "crisis", -1, -1); 174 175 addBorder(info, Global.getSector().getFaction(Factions.REMNANTS).getBaseUIColor()); 176 } 177 178 179 public String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage) { 180 return Global.getSector().getFaction(Factions.REMNANTS).getCrest(); 181 } 182 183 public TooltipCreator getStageTooltipImpl(final HostileActivityEventIntel intel, final EventStageData stage) { 184 if (stage.id == Stage.HA_EVENT) { 185 return getDefaultEventTooltip("Remnant attack", intel, stage); 186 } 187 return null; 188 } 189 190 public static CampaignFleetAPI getRemnantNexus(StarSystemAPI system) { 191 if (system == null) return null; 192// if (!system.hasTag(Tags.THEME_REMNANT_MAIN)) return null; 193// if (system.hasTag(Tags.THEME_REMNANT_DESTROYED)) return null; 194 195 for (CampaignFleetAPI fleet : system.getFleets()) { 196 if (!fleet.isStationMode()) continue; 197 if (!Factions.REMNANTS.equals(fleet.getFaction().getId())) continue; 198 199 return fleet; 200 } 201 return null; 202 } 203 204 205 public float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage) { 206 if (stage.id == Stage.HA_EVENT) { 207 208 MarketAPI target = findAttackTarget(intel, stage); 209 if (target == null || target.getStarSystem() == null) return 0f; 210 211 CampaignFleetAPI nexus = getRemnantNexus(target.getStarSystem()); 212 if (nexus == null) return 0f; 213 214 return 10f; 215 } 216 return 0f; 217 } 218 219 220 public void rollEvent(HostileActivityEventIntel intel, EventStageData stage) { 221 MarketAPI target = findAttackTarget(intel, stage); 222 if (target == null) return; 223 224 HAERandomEventData data = new HAERandomEventData(this, stage); 225 data.custom = target; 226 stage.rollData = data; 227 intel.sendUpdateIfPlayerHasIntel(data, false); 228 } 229 230 public boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage) { 231 MarketAPI target = findAttackTarget(intel, stage); 232 if (target == null || target.getStarSystem() == null) return false; 233 234 CampaignFleetAPI nexus = getRemnantNexus(target.getStarSystem()); 235 if (nexus == null) return false; 236 237 stage.rollData = null; 238 return startAttack(nexus, target, target.getStarSystem(), stage, getRandomizedStageRandom(3)); 239 } 240 241 242 public MarketAPI findAttackTarget(HostileActivityEventIntel intel, EventStageData stage) { 243 WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>(getRandomizedStageRandom(3)); 244 245 for (StarSystemAPI system : Misc.getPlayerSystems(false)) { 246 CampaignFleetAPI nexus = getRemnantNexus(system); 247 if (nexus != null) { 248 for (MarketAPI curr : Misc.getMarketsInLocation(system, Factions.PLAYER)) { 249 picker.add(curr, curr.getSize() * curr.getSize() * curr.getSize()); 250 } 251 } 252 } 253 return picker.pick(); 254 } 255 256 257 258 @Override 259 public void notifyFactorRemoved() { 260 //Global.getSector().getListenerManager().removeListener(this); 261 } 262 263 public void notifyEventEnding() { 264 notifyFactorRemoved(); 265 } 266 267 @Override 268 public void advance(float amount) { 269 super.advance(amount); 270 271 EventStageData stage = intel.getDataFor(Stage.HA_EVENT); 272 if (stage != null && stage.rollData instanceof HAERandomEventData && 273 ((HAERandomEventData)stage.rollData).factor == this) { 274 275 HAERandomEventData data = (HAERandomEventData) stage.rollData; 276 if (data.custom instanceof MarketAPI) { 277 MarketAPI target = (MarketAPI) data.custom; 278 if (getRemnantNexus(target.getStarSystem()) == null) { 279 intel.resetHA_EVENT(); 280 } 281 } 282 } 283 284 } 285 286 287 288 public boolean startAttack(CampaignFleetAPI nexus, MarketAPI target, StarSystemAPI system, EventStageData stage, Random random) { 289 //System.out.println("RANDOM: " + random.nextLong()); 290 291 GenericRaidParams params = new GenericRaidParams(new Random(random.nextLong()), true); 292 293 params.makeFleetsHostile = true; 294 params.remnant = true; 295 296 params.factionId = nexus.getFaction().getId(); 297 298 MarketAPI fake = Global.getFactory().createMarket(nexus.getId(), nexus.getName(), 3); 299 fake.setPrimaryEntity(nexus); 300 fake.setFactionId(params.factionId); 301 fake.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).modifyFlat( 302 "nexus_" + nexus.getId(), 1f); 303 304 //nexus.setMarket(fake); // can actually trade etc then, no good 305 306 params.source = fake; 307 308 params.prepDays = 0f; 309 params.payloadDays = 27f + 7f * random.nextFloat(); 310 311 params.raidParams.where = system; 312 params.raidParams.type = FGRaidType.SEQUENTIAL; 313 params.raidParams.tryToCaptureObjectives = false; 314 params.raidParams.allowedTargets.add(target); 315 params.raidParams.allowNonHostileTargets = true; 316 params.raidParams.setBombardment(BombardType.SATURATION); 317 params.forcesNoun = "remnant forces"; 318 319 params.style = FleetStyle.STANDARD; 320 params.repImpact = ComplicationRepImpact.FULL; 321 322 323 // standard Askonia fleet size multiplier with no shortages/issues is a bit over 230% 324 float fleetSizeMult = 1f; 325 boolean damaged = nexus.getMemoryWithoutUpdate().getBoolean("$damagedStation"); 326 if (damaged) { 327 fleetSizeMult = 0.5f; 328 } 329 330 float totalDifficulty = fleetSizeMult * 50f; 331 332 totalDifficulty -= 10; 333 params.fleetSizes.add(10); 334 335 while (totalDifficulty > 0) { 336 int min = 6; 337 int max = 10; 338 339 int diff = min + random.nextInt(max - min + 1); 340 341 params.fleetSizes.add(diff); 342 totalDifficulty -= diff; 343 } 344 345 346// SindrianDiktatPunitiveExpedition punex = new SindrianDiktatPunitiveExpedition(params); 347// punex.setListener(this); 348// Global.getSector().getIntelManager().addIntel(punex); 349 350 GenericRaidFGI raid = new GenericRaidFGI(params); 351 raid.setListener(this); 352 Global.getSector().getIntelManager().addIntel(raid); 353 354 return true; 355 } 356 357 public void reportFGIAborted(FleetGroupIntel intel) { 358 // TODO: anything? Nothing happens if you defeat it, it's purely avoiding a bombardment 359 } 360 361} 362 363 364 365