Starsector API
Loading...
Searching...
No Matches
NearbyEventsEvent.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.events.nearby;
2
3import java.awt.Color;
4import java.text.DecimalFormat;
5import java.text.ParseException;
6import java.util.HashSet;
7import java.util.List;
8import java.util.Locale;
9import java.util.Map;
10import java.util.Random;
11import java.util.Set;
12
13import org.lwjgl.util.vector.Vector2f;
14
15import com.fs.starfarer.api.Global;
16import com.fs.starfarer.api.campaign.CampaignFleetAPI;
17import com.fs.starfarer.api.campaign.CargoAPI;
18import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
19import com.fs.starfarer.api.campaign.FactionAPI;
20import com.fs.starfarer.api.campaign.InteractionDialogAPI;
21import com.fs.starfarer.api.campaign.LocationAPI;
22import com.fs.starfarer.api.campaign.RepLevel;
23import com.fs.starfarer.api.campaign.SectorEntityToken;
24import com.fs.starfarer.api.campaign.StarSystemAPI;
25import com.fs.starfarer.api.campaign.TextPanelAPI;
26import com.fs.starfarer.api.campaign.econ.MarketAPI;
27import com.fs.starfarer.api.campaign.events.CampaignEventTarget;
28import com.fs.starfarer.api.campaign.rules.MemoryAPI;
29import com.fs.starfarer.api.characters.PersonAPI;
30import com.fs.starfarer.api.combat.ShipVariantAPI;
31import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact;
32import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
33import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
34import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin;
35import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictShipData;
36import com.fs.starfarer.api.impl.campaign.events.BaseEventPlugin;
37import com.fs.starfarer.api.impl.campaign.fleets.PirateFleetManager;
38import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
39import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
40import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
41import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteFleetSpawner;
42import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
43import com.fs.starfarer.api.impl.campaign.ids.Abilities;
44import com.fs.starfarer.api.impl.campaign.ids.Commodities;
45import com.fs.starfarer.api.impl.campaign.ids.Entities;
46import com.fs.starfarer.api.impl.campaign.ids.Factions;
47import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
48import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
49import com.fs.starfarer.api.impl.campaign.ids.Tags;
50import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseManager;
51import com.fs.starfarer.api.impl.campaign.intel.misc.DistressCallIntel;
52import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator;
53import com.fs.starfarer.api.impl.campaign.procgen.themes.RuinsFleetRouteManager;
54import com.fs.starfarer.api.impl.campaign.procgen.themes.SalvageSpecialAssigner;
55import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
56import com.fs.starfarer.api.impl.campaign.rulecmd.BaseCommandPlugin;
57import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.TransmitterTrapSpecial.TransmitterTrapSpecialData;
58import com.fs.starfarer.api.util.IntervalUtil;
59import com.fs.starfarer.api.util.Misc;
60import com.fs.starfarer.api.util.Misc.Token;
61import com.fs.starfarer.api.util.TimeoutTracker;
62import com.fs.starfarer.api.util.WeightedRandomPicker;
63
70public class NearbyEventsEvent extends BaseEventPlugin implements RouteFleetSpawner {
71
72 public static enum DistressEventType {
73 NORMAL,
74 PIRATE_AMBUSH,
75 PIRATE_AMBUSH_TRAP,
76 DERELICT_SHIP,
77 }
78
79 public static float DISTRESS_REPEAT_TIMEOUT = 90f;
80 public static float DISTRESS_ALREADY_WAS_NEARBY_TIMEOUT = 30f;
81 public static float DISTRESS_MIN_SINCE_PLAYER_IN_SYSTEM = 90f;
82 public static float DISTRESS_MIN_CHECK_INTERVAL = 5f;
83 public static float DISTRESS_MAX_CHECK_INTERVAL = 15f;
84 public static float DISTRESS_PROB_PER_SYSTEM = 0.2f;
85 public static float DISTRESS_MAX_PROB = 0.6f;
86
87 public static float DERELICT_SKIP_PROB = 0.5f;
88 public static float DERELICT_SKIP_PROB_ABYSS = 0.85f;
89
90 protected IntervalUtil derelictShipInterval = new IntervalUtil(1f, 10f);
92 protected TimeoutTracker<String> skipForDistressCalls = new TimeoutTracker<String>();
93
94 public static boolean TEST_MODE = false;
95
96 public void init(String type, CampaignEventTarget eventTarget) {
97 super.init(type, eventTarget);
98 readResolve();
99 }
100
101 Object readResolve() {
102 if (skipForDistressCalls == null) {
103 skipForDistressCalls = new TimeoutTracker<String>();
104 }
105 if (distressCallInterval == null) {
107 }
108 return this;
109 }
110
111 public void startEvent() {
112 super.startEvent();
113 }
114
115 public void advance(float amount) {
116 //if (true) return;
117
118 if (!isEventStarted()) return;
119 if (isDone()) return;
120
121 if (Global.getSector().isInFastAdvance()) return;
122 if (Global.getSector().getPlayerFleet() == null) return;
123
124
125 float days = Global.getSector().getClock().convertToDays(amount);
126
127 derelictShipInterval.advance(days);
128 if (derelictShipInterval.intervalElapsed()) {
130 }
131
132 skipForDistressCalls.advance(days);
133
134 distressCallInterval.advance(days);
135 //TEST_MODE = true;
136 if (distressCallInterval.intervalElapsed() || TEST_MODE) {
138 }
139 }
140
141 protected void maybeSpawnDerelictShip() {
142 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
143 if (!playerFleet.isInHyperspace()) return;
144
145 float skipProb = DERELICT_SKIP_PROB;
146 if (Misc.isInAbyss(playerFleet)) {
147 skipProb = DERELICT_SKIP_PROB_ABYSS;
148 }
149
150 if ((float) Math.random() < skipProb) return;
151
152 WeightedRandomPicker<String> factions = SalvageSpecialAssigner.getNearbyFactions(null, playerFleet,
153 15f, 5f, 5f);
154
155 DerelictShipData params = DerelictShipEntityPlugin.createRandom(factions.pick(), null, null, 0f);
156 if (params != null) {
157 ShipVariantAPI variant = Global.getSettings().getVariant(params.ship.variantId);
158 params.durationDays = DerelictShipEntityPlugin.getBaseDuration(variant.getHullSize());
159
160 CustomCampaignEntityAPI entity = (CustomCampaignEntityAPI) BaseThemeGenerator.addSalvageEntity(
161 Global.getSector().getHyperspace(),
162 Entities.WRECK, Factions.NEUTRAL, params);
163 entity.addTag(Tags.EXPIRES);
164 entity.setDiscoverable(false);
165 SalvageSpecialAssigner.assignSpecials(entity, false);
166
167
168 float distFromPlayer = 3000f + (float) Math.random() * 2000f;
169 Vector2f loc = Misc.getPointAtRadius(playerFleet.getLocationInHyperspace(), distFromPlayer, new Random());
170
171 entity.getLocation().x = loc.x;
172 entity.getLocation().y = loc.y;
173
174
175 float angle = Misc.getAngleInDegrees(loc, playerFleet.getLocation());
176 float arc = 90f;
177 angle = angle - arc /2f + arc * (float) Math.random();
178 float speed = 10f + 10f * (float) Math.random();
179
180 float depth = Misc.getAbyssalDepth(loc);
181 speed *= (0.5f + 0.5f * (1f - depth));
182
183 Vector2f vel = Misc.getUnitVectorAtDegreeAngle(angle);
184 vel.scale(speed);
185 entity.getVelocity().set(vel);
186
187 }
188 }
189
190
191 public static Set<String> distressCallAllowedThemes = new HashSet<String>();
192 static {
193 distressCallAllowedThemes.add(Tags.THEME_MISC);
194 distressCallAllowedThemes.add(Tags.THEME_MISC_SKIP);
195 distressCallAllowedThemes.add(Tags.THEME_RUINS);
196 distressCallAllowedThemes.add(Tags.THEME_REMNANT_SUPPRESSED);
197 distressCallAllowedThemes.add(Tags.THEME_REMNANT_DESTROYED);
198 distressCallAllowedThemes.add(Tags.THEME_REMNANT_NO_FLEETS);
199 distressCallAllowedThemes.add(Tags.THEME_DERELICT);
200 }
201
202 public static class NESpawnData {
203 public DistressEventType type;
204 public LocationAPI location;
205 public SectorEntityToken jumpPoint;
206 }
207
208 protected void maybeSpawnDistressCall() {
209 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
210 if (!playerFleet.isInHyperspace()) return;
211 if (playerFleet.isInHyperspaceTransition()) return;
212
213 WeightedRandomPicker<StarSystemAPI> systems = new WeightedRandomPicker<StarSystemAPI>();
214 OUTER: for (StarSystemAPI system : Misc.getNearbyStarSystems(playerFleet, Global.getSettings().getFloat("distressCallEventRangeLY"))) {
215
216 if (skipForDistressCalls.contains(system.getId())) continue;
217
218 if (system.hasPulsar()) continue;
219 if (system.hasTag(Tags.SYSTEM_CUT_OFF_FROM_HYPER)) continue;
220 if (system.hasTag(Tags.THEME_HIDDEN)) continue;
221 //if (system.hasTag(Tags.THEME_SPECIAL)) continue;
222
223 float sincePlayerVisit = system.getDaysSinceLastPlayerVisit();
224 if (sincePlayerVisit < DISTRESS_MIN_SINCE_PLAYER_IN_SYSTEM) {
225 continue;
226 }
227
228 boolean validTheme = false;
229 for (String tag : system.getTags()) {
230 if (distressCallAllowedThemes.contains(tag)) {
231 validTheme = true;
232 break;
233 }
234 }
235 if (!validTheme) continue;
236
237 for (CampaignFleetAPI fleet : system.getFleets()) {
238 if (!fleet.getFaction().isHostileTo(Factions.INDEPENDENT)) continue OUTER;
239 }
240
241 if (!Misc.getMarketsInLocation(system).isEmpty()) continue;
242
244 systems.add(system);
245 }
246
247 float p = systems.getItems().size() * DISTRESS_PROB_PER_SYSTEM;
249 if ((float) Math.random() >= p && !TEST_MODE) return;
250
251
252 StarSystemAPI system = systems.pick();
253 if (system == null) return;
254
256
257
258 WeightedRandomPicker<DistressEventType> picker = new WeightedRandomPicker<DistressEventType>();
259 picker.add(DistressEventType.NORMAL, 10f);
260 picker.add(DistressEventType.PIRATE_AMBUSH, 10f);
261 picker.add(DistressEventType.PIRATE_AMBUSH_TRAP, 10f);
262 picker.add(DistressEventType.DERELICT_SHIP, 10f);
263
264 DistressEventType type = picker.pick();
265 if (TEST_MODE) type = DistressEventType.PIRATE_AMBUSH;
266
267 if (type == DistressEventType.NORMAL) {
269 } else if (type == DistressEventType.PIRATE_AMBUSH) {
271 } else if (type == DistressEventType.PIRATE_AMBUSH_TRAP || TEST_MODE) {
273 } else if (type == DistressEventType.DERELICT_SHIP) {
275 }
276
277// CommMessageAPI message = FleetLog.beginEntry("Distress Call", system.getCenter());
278// message.setSmallIcon(Global.getSettings().getSpriteName("intel_categories", "events"));
279// message.getSection1().addPara("You receive a distress call from the nearby " + system.getNameWithLowercaseType());
280// message.getSection1().addPara("There's no additional information, but that's not surprising - a typical fleet doesn't carry the equipment to broadcast a full-fledged data stream into hyperspace.");
281// FleetLog.addToLog(message, null);
282
283 DistressCallIntel intel = new DistressCallIntel(system);
284 Global.getSector().getIntelManager().addIntel(intel);
285 }
286
287 protected void generateDistressDerelictShip(StarSystemAPI system) {
288 SectorEntityToken jumpPoint = Misc.getDistressJumpPoint(system);
289 if (jumpPoint == null) return;
290
291
292 WeightedRandomPicker<String> factions = SalvageSpecialAssigner.getNearbyFactions(null, system.getLocation(),
293 15f, 5f, 5f);
294 DerelictShipData params = DerelictShipEntityPlugin.createRandom(factions.pick(), null, null, DerelictShipEntityPlugin.getDefaultSModProb());
295 if (params == null) return;
296
297 params.durationDays = 60f;
298 CustomCampaignEntityAPI derelict = (CustomCampaignEntityAPI) BaseThemeGenerator.addSalvageEntity(
299 system, Entities.WRECK, Factions.NEUTRAL, params);
300 derelict.addTag(Tags.EXPIRES);
301
302 float radius = 400f + 400f * (float) Math.random();
303 float maxRadius = Math.max(300, jumpPoint.getCircularOrbitRadius() * 0.33f);
304 if (radius > maxRadius) radius = maxRadius;
305
306 float orbitDays = radius / (5f + Misc.random.nextFloat() * 20f);
307 float angle = (float) Math.random() * 360f;
308 derelict.setCircularOrbit(jumpPoint, angle, radius, orbitDays);
309
310 SalvageSpecialAssigner.assignSpecialForDistressDerelict(derelict);
311 }
312
313 protected void generateDistressCallAmbushTrap(StarSystemAPI system) {
314 SectorEntityToken jumpPoint = Misc.getDistressJumpPoint(system);
315 if (jumpPoint == null) return;
316
317
318 WeightedRandomPicker<String> factions = SalvageSpecialAssigner.getNearbyFactions(null, system.getLocation(),
319 15f, 5f, 5f);
320 DerelictShipData params = DerelictShipEntityPlugin.createRandom(factions.pick(), null, null, DerelictShipEntityPlugin.getDefaultSModProb());
321 if (params == null) return;
322
323 params.durationDays = 60f;
324 CustomCampaignEntityAPI derelict = (CustomCampaignEntityAPI) BaseThemeGenerator.addSalvageEntity(
325 system, Entities.WRECK, Factions.NEUTRAL, params);
326 derelict.addTag(Tags.EXPIRES);
327
328 float radius = 400f + 400f * (float) Math.random();
329 float maxRadius = Math.max(300, jumpPoint.getCircularOrbitRadius() * 0.33f);
330 if (radius > maxRadius) radius = maxRadius;
331
332 float orbitDays = radius / (5f + Misc.random.nextFloat() * 20f);
333 float angle = (float) Math.random() * 360f;
334 derelict.setCircularOrbit(jumpPoint, angle, radius, orbitDays);
335
336
337 TransmitterTrapSpecialData data = new TransmitterTrapSpecialData();
338 data.prob = 1f;
339 data.maxRange = 20000f;
340 data.nearbyFleetFaction = Factions.PIRATES;
341 data.useAllFleetsInRange = true;
342 Misc.setSalvageSpecial(derelict, data);
343
344 int numPirates = new Random().nextInt(3) + 1;
345 for (int i = 0; i < numPirates; i++) {
346
347 NESpawnData dcd = new NESpawnData();
348 dcd.type = DistressEventType.PIRATE_AMBUSH_TRAP;
349 dcd.location = system;
350 dcd.jumpPoint = jumpPoint;
351
352 OptionalFleetData extra = new OptionalFleetData();
353 extra.factionId = Factions.PIRATES;
354
355 RouteData route = RouteManager.getInstance().addRoute("dcd_" + getId(), null,
356 Misc.genRandomSeed(), extra, this, dcd);
357 float waitDays = 30f + (float) Math.random() * 10f;
358 route.addSegment(new RouteSegment(waitDays, jumpPoint));
359
360//
361// int points = 5 + new Random().nextInt(20);
362//
363// CampaignFleetAPI fleet = PirateFleetManager.createPirateFleet(points, null, system.getLocation());
364// if (fleet != null) {
365// system.addEntity(fleet);
366// Vector2f loc = Misc.getPointAtRadius(jumpPoint.getLocation(), 500f + (float) Math.random() * 200f);
367// fleet.setLocation(loc.x, loc.y);
368// fleet.addScript(new DistressCallPirateAmbushTrapAssignmentAI(fleet, system, jumpPoint));
369// }
370 }
371
372 }
373
374
375 protected void generateDistressCallAmbush(StarSystemAPI system) {
376 SectorEntityToken jumpPoint = Misc.getDistressJumpPoint(system);
377 if (jumpPoint == null) return;
378
379 int numPirates = new Random().nextInt(3) + 1;
380
381
382 for (int i = 0; i < numPirates; i++) {
383 NESpawnData dcd = new NESpawnData();
384 dcd.type = DistressEventType.PIRATE_AMBUSH;
385 dcd.location = system;
386 dcd.jumpPoint = jumpPoint;
387
388 OptionalFleetData extra = new OptionalFleetData();
389 extra.factionId = Factions.PIRATES;
390
391 RouteData route = RouteManager.getInstance().addRoute("dcd_" + getId(), null,
392 Misc.genRandomSeed(), extra, this, dcd);
393 float waitDays = 30f + (float) Math.random() * 10f;
394 route.addSegment(new RouteSegment(waitDays, jumpPoint));
395
396// int points = 5 + new Random().nextInt(20);
397//
398// CampaignFleetAPI fleet = PirateFleetManager.createPirateFleet(points, null, system.getLocation());
399// if (fleet != null) {
400// system.addEntity(fleet);
401// Vector2f loc = Misc.getPointAtRadius(jumpPoint.getLocation(), 500f + (float) Math.random() * 200f);
402// fleet.setLocation(loc.x, loc.y);
403// fleet.addScript(new DistressCallPirateAmbushAssignmentAI(fleet, system, jumpPoint));
404// }
405 }
406
407 }
408
409
410 protected void generateDistressCallNormal(StarSystemAPI system) {
411 SectorEntityToken jumpPoint = Misc.getDistressJumpPoint(system);
412 if (jumpPoint == null) return;
413
414 NESpawnData dcd = new NESpawnData();
415 dcd.type = DistressEventType.NORMAL;
416 dcd.location = system;
417 dcd.jumpPoint = jumpPoint;
418
419 OptionalFleetData extra = new OptionalFleetData();
420 extra.factionId = Factions.INDEPENDENT;
421
422 RouteData route = RouteManager.getInstance().addRoute("dcd_" + getId(), null,
423 Misc.genRandomSeed(), extra, this, dcd);
424 float waitDays = 30f + (float) Math.random() * 10f;
425 route.addSegment(new RouteSegment(waitDays, jumpPoint));
426
427
428// WeightedRandomPicker<String> typePicker = new WeightedRandomPicker<String>();
429// typePicker.add(FleetTypes.SCAVENGER_SMALL, 10f);
430// typePicker.add(FleetTypes.SCAVENGER_MEDIUM, 10f);
431// typePicker.add(FleetTypes.SCAVENGER_LARGE, 10f);
432// String type = typePicker.pick();
433// type = FleetTypes.SCAVENGER_SMALL;
434// boolean pirate = (float) Math.random() < 0.5f;
435// if (TEST_MODE) pirate = true;
436// CampaignFleetAPI fleet = RuinsFleetRouteManager.createScavenger(
437// type, system.getLocation(),
438// null, pirate, null);
439// if (fleet == null) return;
440// if (Misc.getSourceMarket(fleet) == null) return;
441//
442// system.addEntity(fleet);
443//
444// fleet.removeAbility(Abilities.EMERGENCY_BURN);
445//
446// //fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_LOW_REP_IMPACT, true);
447// fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_NO_JUMP, true);
448// //fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_MAKE_AGGRESSIVE, true);
449// Misc.setFlagWithReason(fleet.getMemoryWithoutUpdate(), MemFlags.ENTITY_MISSION_IMPORTANT,
450// "distress", true, 1000f);
451// fleet.getMemoryWithoutUpdate().set("$ne_eventRef", this);
452// fleet.getMemoryWithoutUpdate().set("$distress", true);
453//
454// if (pirate) {
455// fleet.getMemoryWithoutUpdate().set("$distressTurnHostile", true);
456// }
457//
458// //SectorEntityToken jumpPoint = jpLoc.orbit.getFocus();
459// Vector2f loc = Misc.getPointAtRadius(jumpPoint.getLocation(), 400f + (float) Math.random() * 200f);
460// fleet.setLocation(loc.x, loc.y);
461//
462// fleet.addScript(new DistressCallNormalAssignmentAI(fleet, system, jumpPoint));
463
464 }
465
466 public void reportAboutToBeDespawnedByRouteManager(RouteData route) {
467 route.expire();
468 }
469
470 public boolean shouldCancelRouteAfterDelayCheck(RouteData route) {
471 return false;
472 }
473
474 public boolean shouldRepeat(RouteData route) {
475 return false;
476 }
477
478 public CampaignFleetAPI spawnFleet(RouteData route) {
479
480 NESpawnData data = (NESpawnData) route.getCustom();
481
482 if (data.type == DistressEventType.PIRATE_AMBUSH_TRAP) {
483 float tf = PirateBaseManager.getInstance().getStandardTimeFactor();
484 int points = (int) (10 + new Random().nextInt(20) * tf);
485
486 CampaignFleetAPI fleet = PirateFleetManager.createPirateFleet(points, null, data.location.getLocation());
487 if (fleet != null) {
488 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_LOW_REP_IMPACT, true);
489 data.location.addEntity(fleet);
490 Vector2f loc = Misc.getPointAtRadius(data.jumpPoint.getLocation(), 500f + (float) Math.random() * 200f);
491 fleet.setLocation(loc.x, loc.y);
492 fleet.addScript(new DistressCallPirateAmbushTrapAssignmentAI(fleet, (StarSystemAPI) data.location, data.jumpPoint));
493 Misc.makeHostile(fleet);
494 }
495 return fleet;
496 } else if (data.type == DistressEventType.PIRATE_AMBUSH) {
497 float tf = PirateBaseManager.getInstance().getStandardTimeFactor();
498 int points = (int) (10 + new Random().nextInt(20) * tf);
499
500 CampaignFleetAPI fleet = PirateFleetManager.createPirateFleet(points, null, data.location.getLocation());
501 if (fleet != null) {
502 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_LOW_REP_IMPACT, true);
503 data.location.addEntity(fleet);
504 Vector2f loc = Misc.getPointAtRadius(data.jumpPoint.getLocation(), 500f + (float) Math.random() * 200f);
505 fleet.setLocation(loc.x, loc.y);
506 fleet.addScript(new DistressCallPirateAmbushAssignmentAI(fleet, (StarSystemAPI) data.location, data.jumpPoint));
507 Misc.makeHostile(fleet);
508 }
509 return fleet;
510 } else if (data.type == DistressEventType.NORMAL) {
511
512 WeightedRandomPicker<String> typePicker = new WeightedRandomPicker<String>();
513 typePicker.add(FleetTypes.SCAVENGER_SMALL, 10f);
514 typePicker.add(FleetTypes.SCAVENGER_MEDIUM, 10f);
515 typePicker.add(FleetTypes.SCAVENGER_LARGE, 10f);
516 String type = typePicker.pick();
517 type = FleetTypes.SCAVENGER_SMALL;
518 boolean pirate = (float) Math.random() < 0.5f;
519 if (TEST_MODE) pirate = true;
520 CampaignFleetAPI fleet = RuinsFleetRouteManager.createScavenger(
521 type, data.location.getLocation(),
522 null, pirate, null);
523 if (fleet == null) return null;
524 if (Misc.getSourceMarket(fleet) == null) return null;
525
526 data.location.addEntity(fleet);
527
528 fleet.removeAbility(Abilities.EMERGENCY_BURN);
529
530 //fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_LOW_REP_IMPACT, true);
531 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_NO_JUMP, true);
532 //fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_MAKE_AGGRESSIVE, true);
533 Misc.setFlagWithReason(fleet.getMemoryWithoutUpdate(), MemFlags.ENTITY_MISSION_IMPORTANT,
534 "distress", true, 1000f);
535 fleet.getMemoryWithoutUpdate().set("$ne_eventRef", this);
536 fleet.getMemoryWithoutUpdate().set("$distress", true);
537
538 if (pirate) {
539 fleet.getMemoryWithoutUpdate().set("$distressTurnHostile", true);
540 }
541
542 //SectorEntityToken jumpPoint = jpLoc.orbit.getFocus();
543 Vector2f loc = Misc.getPointAtRadius(data.jumpPoint.getLocation(), 400f + (float) Math.random() * 200f);
544 fleet.setLocation(loc.x, loc.y);
545
546 fleet.addScript(new DistressCallNormalAssignmentAI(fleet, (StarSystemAPI) data.location, data.jumpPoint));
547
548 return fleet;
549 }
550
551 return null;
552 }
553
554
555 @Override
556 public boolean callEvent(String ruleId, InteractionDialogAPI dialog, List<Token> params, Map<String, MemoryAPI> memoryMap) {
557 String action = params.get(0).getString(memoryMap);
558
559 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
560 CargoAPI cargo = playerFleet.getCargo();
561
562 FactionAPI playerFaction = playerFleet.getFaction();
563 Color color = playerFaction.getColor();
564 Color bad = Misc.getNegativeHighlightColor();
565 Color highlight = Misc.getHighlightColor();
566
567 TextPanelAPI text = dialog.getTextPanel();
568
569 MemoryAPI memory = BaseCommandPlugin.getEntityMemory(memoryMap);
570
571 boolean tookCrew = memory.getBoolean("$playerTookDistressCrewRecently");
572 if (action.equals("initDistress")) {
573
574 CampaignFleetAPI fleet = (CampaignFleetAPI) dialog.getInteractionTarget();
575 MarketAPI source = Misc.getSourceMarket(fleet);
576
577 float returnDistLY = 0;
578 if (source != null) {
579 returnDistLY = Misc.getDistanceLY(fleet.getLocationInHyperspace(), source.getLocationInHyperspace());
580 } else {
581 returnDistLY = Misc.getDistanceLY(fleet.getLocationInHyperspace(), new Vector2f());
582 }
583
584 int fuel = (int) (returnDistLY * Math.max(1, fleet.getLogistics().getFuelCostPerLightYear()));
585 fuel *= 0.5f;
586 if (fuel < 10) fuel = 10;
587 fuel = (int) (Math.ceil(fuel / 10f) * 10);
588 //fuel = 10;
589
590 int credits = fuel * (int) Global.getSettings().getFloat("distressCallFuelCost");
591
592 int crew = (int) (fleet.getFleetData().getMinCrew() * 0.33f);
593 int takeOnCrew = Math.min(crew, cargo.getFreeCrewSpace());
594
595 memory.set("$distressFuel", fuel, 0f);
596 //memory.set("$distressCredits", credits, 0f);
597 memory.set("$distressCredits", Misc.getWithDGS(credits), 0f);
598 memory.set("$distressCrewTakeOn", takeOnCrew, 0f);
599 memory.set("$distressCrew", crew, 0f);
600
601 if (memory.getBoolean("$distressTurnHostile")) {
602 memory.set("$distressFuelHostileThreshold", fuel, 0f);
603 }
604
605 } else if (action.equals("takeDistressCrew")) {
606 int crew = (int) memory.getFloat("$distressCrewTakeOn");
607 int needed = (int) memory.getFloat("$distressCrew");
608
609 boolean enough = crew >= needed;
610
611 cargo.addCrew(crew);
612 AddRemoveCommodity.addCommodityGainText(Commodities.CREW, crew, text);
613
614 float repChange = (int) (crew / 20);
615 if (repChange < 1) repChange = 1;
616 if (repChange > 5) repChange = 5;
617 adjustRep(repChange, null, dialog.getInteractionTarget().getActivePerson().getFaction(),
618 dialog.getInteractionTarget().getActivePerson(), text);
619 //memory.set("$playerTookDistressCrewRecently", true); -- this is set in rules.csv with an expiration
620
621 if (enough) {
622 DistressCallNormalAssignmentAI.undistress(dialog.getInteractionTarget());
623
624 CampaignFleetAPI fleet = (CampaignFleetAPI) dialog.getInteractionTarget();
626 }
627
628 } else if (action.equals("sellDistressFuel")) {
629 int fuel = (int) memory.getFloat("$distressFuel");
630 int credits = (int) memory.getFloat("$distressCredits");
631
632 cargo.removeFuel(fuel);
633 cargo.getCredits().add(credits);
634
635 AddRemoveCommodity.addCommodityLossText(Commodities.FUEL, fuel, text);
636 AddRemoveCommodity.addCreditsGainText(credits, text);
637
638 DistressCallNormalAssignmentAI.undistress(dialog.getInteractionTarget());
639
640 if (tookCrew) {
641 int crew = (int) memory.getFloat("$distressCrewTakeOn");
642 float repChange = (int) (crew / 20);
643 if (repChange < 1) repChange = 1;
644 if (repChange > 5) repChange = 5;
645 adjustRep(-repChange, RepLevel.INHOSPITABLE, dialog.getInteractionTarget().getActivePerson().getFaction(),
646 dialog.getInteractionTarget().getActivePerson(), text);
647 }
648
649 } else if (action.equals("scaredDistressFuel")) {
650 int fuel = (int) memory.getFloat("$distressFuel");
651 //int credits = (int) memory.getFloat("$distressCredits");
652
653 cargo.removeFuel(fuel);
654 //cargo.getCredits().add(credits);
655
656 AddRemoveCommodity.addCommodityLossText(Commodities.FUEL, fuel, text);
657 //AddRemoveCommodity.addCreditsGainText(credits, text);
658
659 DistressCallNormalAssignmentAI.undistress(dialog.getInteractionTarget());
660
661 } else if (action.equals("giveDistressFuel")) {
662 int fuel = (int) memory.getFloat("$distressFuel");
663 int credits = (int) memory.getFloat("$distressCredits");
664
665 cargo.removeFuel(fuel);
666 //cargo.getCredits().add(credits);
667
668 AddRemoveCommodity.addCommodityLossText(Commodities.FUEL, fuel, text);
669 //AddRemoveCommodity.addCreditsGainText(credits, text);
670
671 if (!tookCrew) {
672 float repChange = (int) (credits / 1000);
673 if (repChange > 10) repChange = 10;
674 adjustRep(repChange, null, dialog.getInteractionTarget().getActivePerson().getFaction(),
675 dialog.getInteractionTarget().getActivePerson(), text);
676 }
677
678 DistressCallNormalAssignmentAI.undistress(dialog.getInteractionTarget());
679
680 }
681
682
683// else if (action.equals("showDistressResources")) {
684// ResourceCostPanelAPI cost = text.addCostPanel("Required crew & machinery", SalvageEntity.COST_HEIGHT,
685// color, playerFaction.getDarkUIColor());
686// cost.setNumberOnlyMode(true);
687// cost.setWithBorder(false);
688// cost.setAlignment(Alignment.LMID);
689// cost.addCost(Commodities.FUEL, 10, color);
690// cost.setSecondTitle(" Available crew & machinery");
691// cost.addCost(Commodities.FUEL, 10, color);
692// cost.update();
693// }
694
695 return true;
696 }
697
698
699 protected void adjustRep(float repChangePercent, RepLevel limit, FactionAPI faction, PersonAPI person, TextPanelAPI text) {
700 if (repChangePercent != 0) {
701 CustomRepImpact impact = new CustomRepImpact();
702 impact.delta = repChangePercent * 0.01f;
703 impact.limit = limit;
704 Global.getSector().adjustPlayerReputation(
705 new RepActionEnvelope(RepActions.CUSTOM, impact,
706 null, text, true),
707 faction.getId());
708
709 if (person != null) {
710 impact.delta *= 2f;
711 Global.getSector().adjustPlayerReputation(
712 new RepActionEnvelope(RepActions.CUSTOM, impact,
713 null, text, true), person);
714 }
715 }
716 }
717
718
719 public Map<String, String> getTokenReplacements() {
720 Map<String, String> map = super.getTokenReplacements();
721 return map;
722 }
723
724 @Override
725 public String[] getHighlights(String stageId) {
726 return null;
727 }
728
729 @Override
730 public Color[] getHighlightColors(String stageId) {
731 return super.getHighlightColors(stageId);
732 }
733
734
735 @Override
736 public CampaignEventTarget getEventTarget() {
737 return super.getEventTarget();
738 }
739
740 public boolean isDone() {
741 return false;
742 }
743
744 @Override
745 public CampaignEventCategory getEventCategory() {
746 return CampaignEventCategory.DO_NOT_SHOW_IN_MESSAGE_FILTER;
747 }
748
749 public boolean showAllMessagesIfOngoing() {
750 return false;
751 }
752
753 public static void main(String[] args) throws ParseException {
754 Locale.setDefault(Locale.GERMAN);
755
756// DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.getDefault());
757// symbols.setDecimalSeparator('.');
758// symbols.setGroupingSeparator(',');
759// DecimalFormat format = new DecimalFormat("###,###,###,###,###", symbols);
760 DecimalFormat format = new DecimalFormat("###,###,###,###,###");
761 System.out.println(format.parse("25,000").floatValue());
762 }
763
764
765}
766
767
768
769
770
771
772
773
774
775
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
static DerelictShipData createRandom(String factionId, DerelictType type, Random random)
void adjustRep(float repChangePercent, RepLevel limit, FactionAPI faction, PersonAPI person, TextPanelAPI text)
void init(String type, CampaignEventTarget eventTarget)
boolean callEvent(String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
ShipVariantAPI getVariant(String variantId)