Starsector API
Loading...
Searching...
No Matches
PirateHostileActivityFactor.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.events;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.Collections;
6import java.util.Comparator;
7import java.util.List;
8import java.util.Random;
9
10import org.lwjgl.util.vector.Vector2f;
11
12import com.fs.starfarer.api.Global;
13import com.fs.starfarer.api.campaign.CampaignFleetAPI;
14import com.fs.starfarer.api.campaign.StarSystemAPI;
15import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin;
16import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin.ListInfoMode;
17import com.fs.starfarer.api.campaign.econ.MarketAPI;
18import com.fs.starfarer.api.impl.campaign.ids.Factions;
19import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseIntel;
20import com.fs.starfarer.api.impl.campaign.intel.events.BaseEventIntel.EventStageData;
21import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.HAERandomEventData;
22import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel.Stage;
23import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel;
24import com.fs.starfarer.api.impl.campaign.intel.group.FleetGroupIntel.FGIEventListener;
25import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI;
26import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI.GenericRaidParams;
27import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission;
28import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission.FleetStyle;
29import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator;
30import com.fs.starfarer.api.impl.campaign.rulecmd.KantaCMD;
31import com.fs.starfarer.api.ui.TooltipMakerAPI;
32import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
33import com.fs.starfarer.api.util.Misc;
34import com.fs.starfarer.api.util.WeightedRandomPicker;
35
36public class PirateHostileActivityFactor extends BaseHostileActivityFactor implements FGIEventListener {
37
38// public static class HARaidEventData {
39// public SectorEntityToken source;
40// public StarSystemAPI target;
41// }
42
43 public static String RAID_KEY = "$PirateRaid_ref";
44 public static String SMALL_RAID_KEY = "$SmallPirateRaid_ref";
45
46 public static final String DEFEATED_LARGE_PIRATE_RAID = "$defeatedLargePirateRaid";
47
48 public static boolean isDefeatedLargePirateRaid() {
49 //if (true) return true;
50 return Global.getSector().getPlayerMemoryWithoutUpdate().getBoolean(DEFEATED_LARGE_PIRATE_RAID);
51 }
52 public static void setDefeatedLargePirateRaid(boolean value) {
53 Global.getSector().getPlayerMemoryWithoutUpdate().set(DEFEATED_LARGE_PIRATE_RAID, value);
54 }
55
56
60
62 return "";
63 }
64
65 @Override
67 if (PiracyRespiteScript.get() != null) {
68 return 0;
69 }
70 return super.getProgress(intel);
71 }
72
73 public String getDesc(BaseEventIntel intel) {
74 return "Pirate activity";
75 }
76
77 public String getNameForThreatList(boolean first) {
78 if (first) return "Pirates";
79 return "Pirates";
80 }
81
82
84 if (getProgress(intel) <= 0) {
85 return Misc.getGrayColor();
86 }
87 return Global.getSector().getFaction(Factions.PIRATES).getBaseUIColor();
88 }
89
90 public TooltipCreator getMainRowTooltip(BaseEventIntel intel) {
91 return new BaseFactorTooltip() {
92 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
93 float opad = 10f;
94 tooltip.addPara("Piracy follows interstellar civilization almost without exception.", 0f);
95 if (KantaCMD.playerHasProtection()) {
96 tooltip.addPara("However, you have %s, which is enough dissuade most pirates from attacking your interests.",
97 opad, Misc.getPositiveHighlightColor(), "Kanta's protection");
98 } else {
99 if (KantaCMD.playerEverHadProtection()) {
100 tooltip.addPara("You've %s, and it's not the sort of thing you can do over.",
101 opad, Misc.getNegativeHighlightColor(), "lost Kanta's protection");
102 } else {
103 tooltip.addPara("Having %s, however, should be enough dissuade most pirates from attacking your interests.",
104 opad, Misc.getHighlightColor(), "Kanta's protection");
105 }
106 }
107 }
108 };
109 }
110
112 return getProgress(intel) > 0 || KantaCMD.playerHasProtection();
113 }
114
115 @Override
117 return Global.getSector().getFaction(Factions.PIRATES).getBaseUIColor();
118 }
119
120 public Color getNameColor(float mag) {
121 if (mag <= 0f) {
122 return Misc.getGrayColor();
123 }
124 return Global.getSector().getFaction(Factions.PIRATES).getBaseUIColor();
125 }
126
127 @Override
128 public int getMaxNumFleets(StarSystemAPI system) {
129 if (getProgress(intel) <= 0) {
130 return 1;
131 }
132 return super.getMaxNumFleets(system);
133 }
134
135 public CampaignFleetAPI createFleet(StarSystemAPI system, Random random) {
136
137 float f = 0f;
138 f += getEffectMagnitude(system);
139
140 if (f > 1f) f = 1f;
141
142 int difficulty = 0;
143 difficulty += (int) Math.round(f * 7f);
144
145// int size = 0;
146// for (MarketAPI market : Misc.getMarketsInLocation(system, Factions.PLAYER)) {
147// size = Math.max(market.getSize(), size);
148// }
149// int minDiff = Math.max(0, size - 2);
150
151 float mult = 1f;
152 if (getProgress(intel) <= 0) {
153 mult = 0.5f;
154 }
155
156 int minDiff = Math.round(intel.getMarketPresenceFactor(system) * 6f * mult);
157
158 if (difficulty < minDiff) difficulty = minDiff;
159
160 difficulty += random.nextInt(4);
161
162 FleetCreatorMission m = new FleetCreatorMission(random);
163 m.beginFleet();
164
165 Vector2f loc = system.getLocation();
166 String factionId = Factions.PIRATES;
167
168 m.createStandardFleet(difficulty, factionId, loc);
169 m.triggerSetPirateFleet();
170 m.triggerMakeLowRepImpact();
171 //m.triggerFleetAllowLongPursuit();
172
173 CampaignFleetAPI fleet = m.createFleet();
174
175 return fleet;
176 }
177
178
179
180
181 public void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info,
182 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) {
183 info.addPara("Rumors of pirate raid", tc, initPad);
184// Color c = Global.getSector().getFaction(Factions.PIRATES).getBaseUIColor();
185// info.addPara("Rumors of pirate raid", initPad, tc, c, "pirate raid");
186 }
187
188 public void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info,
189 ListInfoMode mode, boolean isUpdate, Color tc, float initPad) {
190 info.addPara("Pirate raid averted", tc, initPad);
191 }
192
193 public void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info) {
194 float small = 0f;
195 float opad = 10f;
196
197 small = 8f;
198// info.addPara("There are rumors that a pirate raid targeting your colonies "
199// + "may be organized in the near future.", opad);
200//
201// info.addPara(BaseIntelPlugin.BULLET + "If the raid is successful, the targeted colonies will suffer from reduced stability.", opad,
202// Misc.getNegativeHighlightColor(), "reduced stability");
203//
204// info.addPara(BaseIntelPlugin.BULLET + "If the raid is defeated, your colonies will gain "
205// + "increased accessibility for several cycles.",
206// 0f, Misc.getPositiveHighlightColor(), "increased accessibility");
207
208 info.addPara("There are rumors that a pirate raid targeting your colonies "
209 + "may be organized in the near future. If the raid is successful, the targeted colonies will "
210 + "suffer from reduced stability.", small,
211 Misc.getNegativeHighlightColor(), "reduced stability");
212
213 if (stage.id == Stage.HA_EVENT) {
215 info.addPara("If the raid is defeated, your colonies will "
216 + "permanently gain increased accessibility.",
217 opad, Misc.getPositiveHighlightColor(), "increased accessibility");
218 } else {
219 info.addPara("If the raid is defeated, your colonies will gain "
220 + "increased accessibility for several cycles.",
221 opad, Misc.getPositiveHighlightColor(), "increased accessibility");
222 }
223 }
224
225 //if (stage.id == Stage.MINOR_EVENT) {
226 stage.addResetReq(info, false, "crisis", -1, -1, opad);
227// } else {
228// stage.beginResetReqList(info, true, "crisis", opad);
229 // want to keep this less prominent, actually, so: just the above
230// info.addPara("An agreement is reached with Kanta, the pirate queen",
231// 0f, Global.getSector().getFaction(Factions.LUDDIC_PATH).getBaseUIColor(), "Luddic Path");
232// stage.endResetReqList(info, false, "crisis", -1, -1);
233// }
234
235
236
237 addBorder(info, Global.getSector().getFaction(Factions.PIRATES).getBaseUIColor());
238
239
240// Color c = Global.getSector().getFaction(Factions.PIRATES).getBaseUIColor();
241// UIComponentAPI rect = info.createRect(c, 2f);
242// info.addCustomDoNotSetPosition(rect).getPosition().inTL(-small, 0).setSize(
243// info.getWidthSoFar() + small * 2f, Math.max(64f, info.getHeightSoFar() + small));
244 }
245
246
247 public String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage) {
248 return Global.getSector().getFaction(Factions.PIRATES).getCrest();
249 }
250
251 public TooltipCreator getStageTooltipImpl(final HostileActivityEventIntel intel, final EventStageData stage) {
252 if (stage.id == Stage.HA_EVENT || stage.id == Stage.MINOR_EVENT) {
253 if (stage.id == Stage.MINOR_EVENT) {
254 return new BaseFactorTooltip() {
255 @Override
256 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
257 float opad = 10f;
258 tooltip.addTitle("Pirate raid");
259 tooltip.addPara("A pirate raid will be launched against one of your "
260 + "star systems.", opad);
261 }
262 };
263 }
264 return getDefaultEventTooltip("Pirate raid", intel, stage);
265// return new BaseFactorTooltip() {
266// @Override
267// public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
268// float opad = 10f;
269// tooltip.addTitle("Pirate raid");
270// tooltip.addPara("A pirate raid will be launched against one of your "
271// + "star systems.", opad);
275// stage.addResetReq(tooltip, true, "crisis", HostileActivityEventIntel.RESET_MIN, HostileActivityEventIntel.RESET_MAX, opad);
276// }
277// };
278 }
279 return null;
280 }
281
282
283 public float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage) {
284 if (KantaCMD.playerHasProtection()) return 0f;
285
286 if (PiracyRespiteScript.get() != null) return 0f;
287
288 if (stage.id == Stage.HA_EVENT || stage.id == Stage.MINOR_EVENT) {
289 StarSystemAPI target = findRaidTarget(intel, stage);
290 MarketAPI source = findRaidSource(intel, stage, target);
291 if (target != null && source != null) {
292 return 10f;
293 }
294 }
295 return 0f;
296 }
297
298
299// public void resetEvent(HostileActivityEventIntel intel, EventStageData stage) {
300// super.resetEvent(intel, stage);
301// }
302
303 public void rollEvent(HostileActivityEventIntel intel, EventStageData stage) {
304// if (true) return;
305 HAERandomEventData data = new HAERandomEventData(this, stage);
306 stage.rollData = data;
308 }
309
310 public boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage) {
311 StarSystemAPI target = findRaidTarget(intel, stage);
312 MarketAPI source = findRaidSource(intel, stage, target);
313 if (source == null || target == null) {
314 return false;
315 }
316
317 stage.rollData = null;
318 return startRaid(source, target, stage, getRandomizedStageRandom(5));
319 }
320
321 public StarSystemAPI findRaidTarget(HostileActivityEventIntel intel, EventStageData stage) {
322 WeightedRandomPicker<StarSystemAPI> picker = new WeightedRandomPicker<StarSystemAPI>(getRandomizedStageRandom(3));
323
324 for (StarSystemAPI system : Misc.getPlayerSystems(false)) {
325 float mag = getEffectMagnitude(system);
326 if (mag < 0.1f && stage.id != Stage.MINOR_EVENT) {
327 //if (mag < 0.2f) {
328 continue;
329 }
330 picker.add(system, mag * mag);
331 }
332
333 return picker.pick();
334 }
335
336 public MarketAPI findRaidSource(HostileActivityEventIntel intel, EventStageData stage, final StarSystemAPI target) {
337 if (target == null) return null;
338
339 List<MarketAPI> list = new ArrayList<MarketAPI>();
340 float maxDist = Global.getSettings().getFloat("sectorWidth") * 0.5f;
341
342 for (IntelInfoPlugin curr : Global.getSector().getIntelManager().getIntel(PirateBaseIntel.class)) {
343 PirateBaseIntel base = (PirateBaseIntel) curr;
344 if (base.playerHasDealWithBaseCommander()) continue;
345
346 float dist = Misc.getDistance(target.getLocation(), base.getMarket().getLocationInHyperspace());
347 if (dist > maxDist) continue;
348
349 list.add(base.getMarket());
350 }
351
352 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
353 if (Factions.PIRATES.equals(market.getFaction().getId())) {
354 for (MarketAPI other : Misc.getMarketsInLocation(market.getContainingLocation())) {
355 if (other == market) continue;
356 if (!other.getFaction().isHostileTo(market.getFaction())) continue;
357 if (other.getSize() <= market.getSize() - 2) continue;
358
359 float dist = Misc.getDistance(market.getPrimaryEntity().getLocation(), other.getPrimaryEntity().getLocation());
360 if (dist < 8000) continue;
361
362 list.add(market);
363 }
364 }
365 }
366
367 Collections.sort(list, new Comparator<MarketAPI>() {
368 public int compare(MarketAPI m1, MarketAPI m2) {
369 float d1 = Misc.getDistance(target.getLocation(), m1.getLocationInHyperspace());
370 float d2 = Misc.getDistance(target.getLocation(), m2.getLocationInHyperspace());
371 return (int) Math.signum(d1 - d2);
372 }
373 });
374
375 WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>(getRandomizedStageRandom());
376 for (int i = 0; i < list.size() && i < 4; i++) {
377 MarketAPI market = list.get(i);
378 float dist = Misc.getDistance(target.getLocation(), market.getLocationInHyperspace());
379 float w = 100000f / (dist * dist);
380 picker.add(market, w);
381 }
382
383 return picker.pick();
384 }
385
386 public static void avertOrAbortRaid() {
387 if (GenericRaidFGI.get(SMALL_RAID_KEY) != null) {
388 GenericRaidFGI.get(SMALL_RAID_KEY).finish(false);
389 }
390
391 if (GenericRaidFGI.get(RAID_KEY) != null) {
392 GenericRaidFGI.get(RAID_KEY).finish(false);
393 }
394
396 if (intel == null) return;
397
398 HAERandomEventData data = intel.getRollDataForEvent();
399 if (data != null && data.factor instanceof PirateHostileActivityFactor) {
401 }
402 }
403
404
405 public boolean startRaid(MarketAPI source, StarSystemAPI target, EventStageData stage, Random random) {
406 GenericRaidParams params = new GenericRaidParams(new Random(random.nextLong()), true);
407 params.factionId = source.getFactionId();
408 params.source = source;
409
410 params.prepDays = 7f + random.nextFloat() * 14f;
411 params.payloadDays = 27f + 7f * random.nextFloat();
412
413 params.raidParams.where = target;
414 for (MarketAPI market : Misc.getMarketsInLocation(target)) {
415 if (market.getFaction().isHostileTo(source.getFaction()) || market.getFaction().isPlayerFaction()) {
416 params.raidParams.allowedTargets.add(market);
417 }
418 }
419 if (params.raidParams.allowedTargets.isEmpty()) return false;
420 params.raidParams.allowNonHostileTargets = true;
421
422 params.style = FleetStyle.STANDARD;
423
424 if (stage.id == Stage.MINOR_EVENT) {
425 params.fleetSizes.add(5);
426 params.fleetSizes.add(3);
427 params.memoryKey = SMALL_RAID_KEY;
428 } else {
429 params.memoryKey = RAID_KEY;
430
431 float mag1 = getEffectMagnitude(target);
432 if (mag1 > 1f) mag1 = 1f;
433 float mag2 = intel.getMarketPresenceFactor(target);
434 float totalDifficulty = (0.25f + mag1 * 0.25f + mag2 * 0.5f) * 100f;
435
436 Random r = getRandomizedStageRandom(7);
437 if (r.nextFloat() < 0.33f) {
438 params.style = FleetStyle.QUANTITY;
439 }
440
441 while (totalDifficulty > 0) {
442 float max = Math.min(10f, totalDifficulty * 0.5f);
443 float min = Math.max(2, max - 2);
444 if (max < min) max = min;
445
446 int diff = Math.round(StarSystemGenerator.getNormalRandom(r, min, max));
447
448 params.fleetSizes.add(diff);
449 totalDifficulty -= diff;
450 }
451 }
452
453 PirateBaseIntel base = PirateBaseIntel.getIntelFor(source);
454 if (base != null) {
455 if (Misc.isHiddenBase(source) && !base.isPlayerVisible()) {
456 base.makeKnown();
457 base.sendUpdateIfPlayerHasIntel(PirateBaseIntel.DISCOVERED_PARAM, false);
458 }
459 }
460
461 GenericRaidFGI raid = new GenericRaidFGI(params);
462 if (stage.id == Stage.HA_EVENT) { // don't want piracy respite from the minor raid
463 raid.setListener(this);
464 }
465 Global.getSector().getIntelManager().addIntel(raid);
466
467 return true;
468 }
469
470 public void reportFGIAborted(FleetGroupIntel intel) {
473 }
474
475
476
477 public static void main(String[] args) {
478 Random r = new Random();
479 int [] counts = new int[11];
480 for (int i = 0; i < 10000; i++) {
481 int x = Math.round(getNormalRandom(r, 7, 10));
482 counts[x]++;
483 }
484 for (int i = 0; i < counts.length; i++) {
485 System.out.println(i + ": " + counts[i]);
486 }
487 }
488
489 public static float getNormalRandom(Random random, float min, float max) {
490 double r = random.nextGaussian();
491 r *= 0.2f;
492 r += 0.5f;
493 if (r < 0) r = 0;
494 if (r > 1) r = 1;
495
496 // 70% chance 0.3 < r < .7
497 // 95% chance 0.1 < r < .7
498 // 99% chance 0 < r < 1
499 return min + (float) r * (max - min);
500 }
501
502}
503
504
505
506
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
void sendUpdateIfPlayerHasIntel(Object listInfoParam, TextPanelAPI textPanel)
TooltipCreator getDefaultEventTooltip(final String title, final HostileActivityEventIntel intel, final EventStageData stage)
float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage)
boolean startRaid(MarketAPI source, StarSystemAPI target, EventStageData stage, Random random)
boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage)
MarketAPI findRaidSource(HostileActivityEventIntel intel, EventStageData stage, final StarSystemAPI target)
StarSystemAPI findRaidTarget(HostileActivityEventIntel intel, EventStageData stage)
String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage)
void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
TooltipCreator getStageTooltipImpl(final HostileActivityEventIntel intel, final EventStageData stage)
void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info)