Starsector API
Loading...
Searching...
No Matches
BaseHubMission.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.missions.hub;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.Arrays;
6import java.util.HashSet;
7import java.util.Iterator;
8import java.util.LinkedHashMap;
9import java.util.LinkedHashSet;
10import java.util.List;
11import java.util.Map;
12import java.util.Random;
13import java.util.Set;
14
15import org.lwjgl.input.Keyboard;
16import org.lwjgl.util.vector.Vector2f;
17
18import com.fs.starfarer.api.Global;
19import com.fs.starfarer.api.campaign.CampaignFleetAPI;
20import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
21import com.fs.starfarer.api.campaign.CampaignTerrainPlugin;
22import com.fs.starfarer.api.campaign.CargoAPI;
23import com.fs.starfarer.api.campaign.CargoStackAPI;
24import com.fs.starfarer.api.campaign.CustomEntitySpecAPI;
25import com.fs.starfarer.api.campaign.FactionAPI;
26import com.fs.starfarer.api.campaign.InteractionDialogAPI;
27import com.fs.starfarer.api.campaign.LocationAPI;
28import com.fs.starfarer.api.campaign.PersonImportance;
29import com.fs.starfarer.api.campaign.PlanetAPI;
30import com.fs.starfarer.api.campaign.RepLevel;
31import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin.ReputationAdjustmentResult;
32import com.fs.starfarer.api.campaign.SectorEntityToken;
33import com.fs.starfarer.api.campaign.SpecialItemData;
34import com.fs.starfarer.api.campaign.StarSystemAPI;
35import com.fs.starfarer.api.campaign.TextPanelAPI;
36import com.fs.starfarer.api.campaign.econ.Industry;
37import com.fs.starfarer.api.campaign.econ.MarketAPI;
38import com.fs.starfarer.api.campaign.rules.HasMemory;
39import com.fs.starfarer.api.campaign.rules.MemKeys;
40import com.fs.starfarer.api.campaign.rules.MemoryAPI;
41import com.fs.starfarer.api.characters.FullName.Gender;
42import com.fs.starfarer.api.characters.ImportantPeopleAPI;
43import com.fs.starfarer.api.characters.ImportantPeopleAPI.PersonDataAPI;
44import com.fs.starfarer.api.characters.PersonAPI;
45import com.fs.starfarer.api.combat.StatBonus;
46import com.fs.starfarer.api.fleet.FleetMemberAPI;
47import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin;
48import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.MissionCompletionRep;
49import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
50import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
51import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepRewards;
52import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin;
53import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictShipData;
54import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictType;
55import com.fs.starfarer.api.impl.campaign.ids.Entities;
56import com.fs.starfarer.api.impl.campaign.ids.Factions;
57import com.fs.starfarer.api.impl.campaign.ids.Ranks;
58import com.fs.starfarer.api.impl.campaign.ids.Stats;
59import com.fs.starfarer.api.impl.campaign.ids.Tags;
60import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
61import com.fs.starfarer.api.impl.campaign.intel.contacts.ContactIntel;
62import com.fs.starfarer.api.impl.campaign.missions.CheapCommodityMission;
63import com.fs.starfarer.api.impl.campaign.missions.hub.MissionTrigger.TriggerAction;
64import com.fs.starfarer.api.impl.campaign.missions.hub.MissionTrigger.TriggerActionContext;
65import com.fs.starfarer.api.impl.campaign.plog.PlaythroughLog;
66import com.fs.starfarer.api.impl.campaign.procgen.Constellation;
67import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator;
68import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.AddedEntity;
69import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.EntityLocation;
70import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.LocationType;
71import com.fs.starfarer.api.impl.campaign.procgen.themes.SalvageSpecialAssigner;
72import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
73import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD;
74import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.RaidDangerLevel;
75import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.BaseSalvageSpecial;
76import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.BreadcrumbSpecial;
77import com.fs.starfarer.api.impl.campaign.terrain.BaseRingTerrain;
78import com.fs.starfarer.api.impl.campaign.terrain.BaseTiledTerrain;
79import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin.DebrisFieldParams;
80import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin.DebrisFieldSource;
81import com.fs.starfarer.api.ui.ButtonAPI;
82import com.fs.starfarer.api.ui.IntelUIAPI;
83import com.fs.starfarer.api.ui.LabelAPI;
84import com.fs.starfarer.api.ui.SectorMapAPI;
85import com.fs.starfarer.api.ui.TooltipMakerAPI;
86import com.fs.starfarer.api.util.IntervalUtil;
87import com.fs.starfarer.api.util.Misc;
88import com.fs.starfarer.api.util.Misc.Token;
89import com.fs.starfarer.api.util.Pair;
90import com.fs.starfarer.api.util.WeightedRandomPicker;
91
92public abstract class BaseHubMission extends BaseIntelPlugin implements HubMission {
93
94 public static float DEBRIS_SMALL = 200f;
95 public static float DEBRIS_MEDIUM = 350f;
96 public static float DEBRIS_LARGE = 500f;
97
98 public static float DEBRIS_SPARSE = 0.25f;
99 public static float DEBRIS_AVERAGE = 0.5f;
100 public static float DEBRIS_DENSE = 1f;
101
102 public static float GLOBAL_MISSION_REWARD_MULT = 1f;
103
104 public static int EXTRA_REWARD_PER_MARINE = 50;
105
106 public static enum CreditReward {
107 VERY_LOW(20000, 25000, 2000),
108 LOW(30000, 40000, 5000),
109 AVERAGE(50000, 60000, 10000),
110 HIGH(70000, 80000, 15000),
111 VERY_HIGH(90000, 100000, 20000),
112// VERY_LOW(10000, 15000, 2000),
113// LOW(20000, 25000, 5000),
114// AVERAGE(30000, 40000, 10000),
115// HIGH(50000, 60000, 15000),
116// VERY_HIGH(80000, 100000, 20000),
117 ;
118 public int min;
119 public int max;
120 public int perMarketSize;
121 private CreditReward(int min, int max, int perMarketSize) {
122 this.min = (int) (min * GLOBAL_MISSION_REWARD_MULT);
123 this.max = (int) (max * GLOBAL_MISSION_REWARD_MULT);
124 this.perMarketSize = (int) (perMarketSize * GLOBAL_MISSION_REWARD_MULT);
125 }
126 }
127
128
129
130 public static String BUTTON_ABANDON = "Abandon";
131
132// public static int MIN_LEVEL_TO_SCALE_XP_GAIN_AT = 1;
133// public static int MAX_LEVEL_TO_SCALE_XP_GAIN_AT = 5;
134// public static enum XPReward {
135// VERY_LOW(0.05f),
136// LOW(0.1f),
137// MEDIUM(0.15f),
138// HIGH(0.2f),
139// VERY_HIGH(0.3f),
140// ;
141//
142// float fractionOfLevel;
143// private XPReward(float fractionOfLevel) {
144// this.fractionOfLevel = fractionOfLevel;
145// }
146// public float getFractionOfLevel() {
147// return fractionOfLevel;
148// }
149// }
150
151 public static enum Abandon {
152 ABANDON
153 }
154
155 public static enum EntityLocationType {
156 HIDDEN,
157 HIDDEN_NOT_NEAR_STAR,
158 ORBITING_PLANET,
159 ORBITING_PLANET_OR_STAR,
160 UNCOMMON, /* similar to HIDDEN, but can also orbit jump-points */
161 ANY,
162 ORBITING_PARAM,
163 }
164
165 public static class LocData {
166 public CampaignTerrainAPI terrain;
167 public EntityLocation loc;
168 public EntityLocationType type;
169 public SectorEntityToken centerOn;
170 public LocationAPI system; // can be hyperspace when type is ORBITING_PARAM or EntityLocation is set
171 public boolean removeOnMissionOver;
172
176 public LocData(EntityLocation loc, LocationAPI system, boolean removeOnMissionOver) {
177 this.loc = loc;
178 this.removeOnMissionOver = removeOnMissionOver;
179 this.system = system;
180 }
181
185 public LocData(EntityLocationType type, SectorEntityToken centerOn, LocationAPI system,
186 boolean removeOnMissionOver) {
187 this.type = type;
188 this.centerOn = centerOn;
189 this.system = system;
190 this.removeOnMissionOver = removeOnMissionOver;
191 }
192
196 public LocData(SectorEntityToken centerOn, boolean removeOnMissionOver) {
197 if (centerOn instanceof CampaignTerrainAPI) {
198 this.centerOn = centerOn;
199 } else {
200 loc = new EntityLocation();
201 loc.type = LocationType.OUTER_SYSTEM;
202 loc.orbit = Global.getFactory().createCircularOrbit(centerOn, 0f, 0f, 1000f);
203 }
204 system = centerOn.getContainingLocation();
205 this.removeOnMissionOver = removeOnMissionOver;
206 }
207
211 public LocData(Vector2f loc, LocationAPI system, boolean removeOnMissionOver) {
212 this.loc = new EntityLocation();
213 this.loc.type = LocationType.OUTER_SYSTEM;
214 this.loc.location = loc;
215 this.system = system;
216 this.removeOnMissionOver = removeOnMissionOver;
217 }
218
222 public LocData(EntityLocation loc, LocationAPI system) {
223 this(loc, system, true);
224 }
225
229 public LocData(EntityLocationType type, SectorEntityToken centerOn, LocationAPI system) {
230 this(type, centerOn, system, true);
231 }
232
236 public LocData(SectorEntityToken centerOn) {
237 this(centerOn, true);
238 }
239
243 public LocData(Vector2f loc, LocationAPI system) {
244 this(loc, system, true);
245 }
246
247 public boolean updateLocIfNeeded(BaseHubMission mission, String entityId) {
248 if (centerOn instanceof CampaignTerrainAPI) {
249 CampaignTerrainAPI terrain = (CampaignTerrainAPI) centerOn;
250 loc = mission.generateLocationInsideTerrain(terrain);
251 if (loc == null) return false;
252 } else if (type != null) {
253 loc = mission.generateLocation(entityId, type, centerOn, system);
254 if (loc == null) return false;
255 }
256 return true;
257 }
258
259 public void placeEntity(SectorEntityToken entity) {
260 //if (!updateLocIfNeeded(mission, entity.getCustomEntityType())) return false;
261
262 if (loc.orbit != null) {
263 entity.setOrbit(loc.orbit);
264 loc.orbit.setEntity(entity);
265 } else {
266 entity.setOrbit(null);
267 entity.getLocation().set(loc.location);
268 }
269
270 if (removeOnMissionOver) {
271 entity.addTag(REMOVE_ON_MISSION_OVER);
272 }
273 }
274 }
275
276
277
278
279 public static class HubMissionResult {
280 public boolean success;
281 public int reward;
282 public int xp;
283 public ReputationAdjustmentResult repPerson;
284 public ReputationAdjustmentResult repFaction;
285 public Object custom;
286 }
287
288 public static enum MapLocationType {
289 NORMAL,
290 CONSTELLATION;
291 }
292 public static class ImportanceData {
293 public MemoryAPI memory;
294 public String flag;
295 public MapLocationType locType = null;
296 public SectorEntityToken entity;
297 public MarketAPI market;
298 public PersonAPI person;
299
300 public ImportanceData() {
301 }
302 }
303
304 public static class FlagData {
305 public MemoryAPI memory;
306 public String flag;
307 public LinkedHashSet<Object> stages = new LinkedHashSet<Object>();
308 }
309
310 public static class StageData {
311 public Object id;
312 public float elapsed = 0f;
313 //public LinkedHashMap<MemoryAPI, String> important = new LinkedHashMap<MemoryAPI, String>();
314 public List<ImportanceData> important = new ArrayList<ImportanceData>();
315 }
316
317 public static interface ConditionChecker {
318 boolean conditionsMet();
319 }
320
321 public static class GlobalBooleanChecker implements ConditionChecker {
322 public String flag;
323 public GlobalBooleanChecker(String flag) {
324 this.flag = flag;
325 }
326 public boolean conditionsMet() {
327 return Global.getSector().getMemoryWithoutUpdate().getBoolean(flag);
328 }
329 }
330
331 public static class MemoryBooleanChecker implements ConditionChecker {
332 public String flag;
333 public MemoryAPI memory;
334 public MemoryBooleanChecker(MemoryAPI memory, String flag) {
335 this.memory = memory;
336 this.flag = flag;
337 }
338 public boolean conditionsMet() {
339 return memory.getBoolean(flag);
340 }
341 }
342
343 public static class EntityNotAliveChecker implements ConditionChecker {
344 public SectorEntityToken entity;
345 public EntityNotAliveChecker(SectorEntityToken entity) {
346 this.entity = entity;
347 }
348 public boolean conditionsMet() {
349 return !entity.isAlive();
350 }
351 }
352
353 public static class MarketDecivChecker implements ConditionChecker {
354 public MarketAPI market;
355 public MarketDecivChecker(MarketAPI market) {
356 this.market = market;
357 }
358 public boolean conditionsMet() {
359 return market.isPlanetConditionMarketOnly() ||
360 (market.getPrimaryEntity() != null && !market.getPrimaryEntity().isAlive());
361 }
362 }
363
364 public static class HostilitiesEndedChecker implements ConditionChecker {
365 public PersonAPI person;
366 public MarketAPI market;
367 public HostilitiesEndedChecker(PersonAPI person, MarketAPI market) {
368 this.person = person;
369 this.market = market;
370 }
371 public boolean conditionsMet() {
372 return !person.getFaction().isHostileTo(market.getFaction());
373 }
374 }
375
376 public static class HostilitiesStartedChecker implements ConditionChecker {
377 public PersonAPI person;
378 public MarketAPI market;
379 public HostilitiesStartedChecker(PersonAPI person, MarketAPI market) {
380 this.person = person;
381 this.market = market;
382 }
383 public boolean conditionsMet() {
384 return person.getFaction().isHostileTo(market.getFaction());
385 }
386 }
387
388 public static class DaysElapsedChecker implements ConditionChecker {
389 public float days;
390 public StageData stage;
391 public BaseHubMission mission;
392 public DaysElapsedChecker(float days, StageData stage) {
393 this.days = days;
394 this.stage = stage;
395 }
396
397 public DaysElapsedChecker(float days, BaseHubMission mission) {
398 this.days = days;
399 this.mission = mission;
400 }
401
402 public boolean conditionsMet() {
403 if (mission != null) {
404 return mission.elapsed >= days;
405 }
406 return stage.elapsed >= days;
407 }
408 }
409
410 public static class InCommRelayRangeChecker implements ConditionChecker {
411 public boolean conditionsMet() {
412 return Global.getSector().getIntelManager().isPlayerInRangeOfCommRelay();
413 }
414 }
415
416 public static class InRangeOfEntityChecker implements ConditionChecker {
417 public SectorEntityToken entity;
418 public float range;
419 public InRangeOfEntityChecker(SectorEntityToken entity, float range) {
420 this.entity = entity;
421 this.range = range;
422 }
423 public boolean conditionsMet() {
424 return Global.getSector().getCurrentLocation() == entity.getContainingLocation() &&
425 Misc.getDistance(Global.getSector().getPlayerFleet(), entity) < range;
426 }
427 }
428
429 public static class InHyperRangeOfEntityChecker implements ConditionChecker {
430 public SectorEntityToken entity;
431 public float rangeLY;
432 public boolean requirePlayerInHyperspace;
433 public InHyperRangeOfEntityChecker(SectorEntityToken entity, float rangeLY, boolean requirePlayerInHyperspace) {
434 this.entity = entity;
435 this.rangeLY = rangeLY;
436 this.requirePlayerInHyperspace = requirePlayerInHyperspace;
437 }
438 public boolean conditionsMet() {
439 if (requirePlayerInHyperspace && !Global.getSector().getPlayerFleet().isInHyperspace()) return false;
440 return Misc.getDistanceLY(Global.getSector().getPlayerFleet(), entity) < rangeLY;
441 }
442 }
443
444 public static class EnteredLocationChecker implements ConditionChecker {
445 public LocationAPI location;
446 public EnteredLocationChecker(LocationAPI location) {
447 this.location = location;
448 }
449 public boolean conditionsMet() {
450 return Global.getSector().getCurrentLocation() == location;
451 }
452 }
453
454 public static class AlwaysTrueChecker implements ConditionChecker {
455 public boolean conditionsMet() {
456 return true;
457 }
458 }
459
460 public static class StageConnection {
461 public Object from;
462 public Object to;
463 public ConditionChecker checker;
464 public StageConnection(Object from, Object to, ConditionChecker checker) {
465 this.from = from;
466 this.to = to;
467 this.checker = checker;
468 }
469 }
470
471 public static class TimeLimitData {
472 public float days;
473 public Object failStage;
474 public LinkedHashSet<Object> endLimitStages = new LinkedHashSet<Object>();
475 public StarSystemAPI noLimitWhileInSystem;
476 }
477
478 public static interface Abortable {
479 void abort(HubMission mission, boolean missionOver);
480 }
481
482 public static class VariableSet implements Abortable {
483 public MemoryAPI memory;
484 public String key;
485 public boolean removeOnMissionOver;
486 public VariableSet(MemoryAPI memory, String key, boolean removeOnMissionOver) {
487 this.memory = memory;
488 this.key = key;
489 this.removeOnMissionOver = removeOnMissionOver;
490 }
491
492 public void abort(HubMission mission, boolean missionOver) {
493 if (!removeOnMissionOver && missionOver) return;
494 memory.unset(key);
495 }
496 }
497
498 public static class MadeImportant implements Abortable {
499 public MemoryAPI memory;
500 public String reason;
501 public MadeImportant(MemoryAPI memory, String reason) {
502 this.memory = memory;
503 this.reason = reason;
504 }
505 public void abort(HubMission mission, boolean missionOver) {
506 Misc.makeUnimportant(memory, reason);
507 }
508 }
509
510 public static class DefeatTriggerAdded implements Abortable {
511 protected CampaignFleetAPI fleet;
512 protected String trigger;
513 protected boolean permanent;
514 public DefeatTriggerAdded(CampaignFleetAPI fleet, String trigger, boolean permanent) {
515 this.fleet = fleet;
516 this.trigger = trigger;
517 this.permanent = permanent;
518 }
519 public void abort(HubMission mission, boolean missionOver) {
520 if (!(permanent && missionOver)) {
521 Misc.removeDefeatTrigger(fleet, trigger);
522 }
523 }
524 }
525
526 public static String REMOVE_ON_MISSION_OVER = "remove_on_mission_over";
527 public static class EntityAdded implements Abortable {
528 public SectorEntityToken entity;
529 public EntityAdded(SectorEntityToken entity) {
530 this.entity = entity;
531 }
532
533 public void abort(HubMission mission, boolean missionOver) {
534 if (missionOver) {
535 if (!entity.hasTag(REMOVE_ON_MISSION_OVER)) return;
536 if (entity.hasTag(Tags.FADING_OUT_AND_EXPIRING)) return;
537 }
538 if (entity.getContainingLocation() != null) {
539 entity.getContainingLocation().removeEntity(entity);
540 }
541 }
542 }
543
544 public static class PersonAdded implements Abortable {
545 public MarketAPI market;
546 public PersonAPI person;
547 public boolean wasOnlyAddedToCommDirectory;
548
549 public PersonAdded(MarketAPI market, PersonAPI person, boolean wasOnlyAddedToCommDirectory) {
550 this.market = market;
551 this.person = person;
552 this.wasOnlyAddedToCommDirectory = wasOnlyAddedToCommDirectory;
553 }
554
555 public void abort(HubMission mission, boolean missionOver) {
556 if (missionOver && !person.hasTag(REMOVE_ON_MISSION_OVER)) return;
557
558 if (mission instanceof BaseHubMission) {
559 BaseHubMission bhm = (BaseHubMission) mission;
560 if (Misc.setFlagWithReason(person.getMemoryWithoutUpdate(),
561 "$requiredForMissions", bhm.getReason(), false, -1f)) {
562 return;
563 }
564 }
565
566 if (!wasOnlyAddedToCommDirectory) {
567 if (market != null) market.removePerson(person);
568 Global.getSector().getImportantPeople().removePerson(person);
569 }
570 if (market != null) market.getCommDirectory().removePerson(person);
571 }
572 }
573
574 public static class PersonMadeRequired implements Abortable {
575 public PersonAPI person;
576
577 public PersonMadeRequired(PersonAPI person) {
578 this.person = person;
579 }
580
581 public void abort(HubMission mission, boolean missionOver) {
582 if (mission instanceof BaseHubMission) {
583 BaseHubMission bhm = (BaseHubMission) mission;
584 if (Misc.setFlagWithReason(person.getMemoryWithoutUpdate(),
585 "$requiredForMissions", bhm.getReason(), false, -1f)) {
586 return;
587 }
588 }
589 }
590 }
591
592 protected Object currentStage = null;
593 protected LinkedHashMap<Object, StageData> stages = new LinkedHashMap<Object, StageData>();
594 protected Boolean stageTransitionsRepeatable = null;
595 protected List<Object> successStages = new ArrayList<Object>();
596 protected List<Object> failStages = new ArrayList<Object>();
597 protected List<Object> noPenaltyFailStages = new ArrayList<Object>();
598 protected Object abandonStage = Abandon.ABANDON;
599 protected List<StageConnection> connections = new ArrayList<StageConnection>();
600 protected List<MissionTrigger> triggers = new ArrayList<MissionTrigger>();
601 protected List<Abortable> changes = new ArrayList<Abortable>();
602 protected List<FlagData> flags = new ArrayList<FlagData>();
603
604 protected transient Object startingStage;
605
606 protected transient CargoAPI cargoOnAccept = Global.getFactory().createCargo(true);
607 protected CargoAPI cargoOnSuccess = null;
608
609 protected float elapsed = 0f;
610 protected TimeLimitData timeLimit;
611 protected HubMissionResult result;
612
613
614 protected MissionHub hub;
615 protected PersonAPI personOverride = null;
617 protected Random genRandom = null;
618
619 protected IntervalUtil tracker = new IntervalUtil(0.09f, 0.11f);
620
621 protected Float repRewardPerson = null;
622 protected Float repPenaltyPerson = null;
623 protected Float repRewardFaction = null;
624 protected Float repPenaltyFaction = null;
625 protected Integer creditReward = null;
626 protected Integer xpReward = null;
627
628 protected String iconName;
629
630 protected RepLevel rewardLimitPerson = null;
631 protected RepLevel rewardLimitFaction = null;
632 protected RepLevel penaltyLimitPerson = null;
633 protected RepLevel penaltyLimitFaction = null;
634
635 protected String missionId;
636
637 protected float rewardMult = 1f;
638 protected float quality = 0f;
639
640 protected IntelSortTier sortTier = null;
641
642 public static class PotentialContactData {
643 public PersonAPI contact;
644 public float probability = -1f;
645 }
646
647 protected List<PotentialContactData> potentialContactsOnMissionSuccess = null;
649
650 public BaseHubMission() {
651 }
652
656
658 this.doNotAutoAddPotentialContactsOnSuccess = true;
659 }
660
664
665 public void setGiverIsPotentialContactOnSuccess(float probability) {
667 }
668
669 public void setPersonIsPotentialContactOnSuccess(PersonAPI person) {
671 }
672 public void setPersonIsPotentialContactOnSuccess(PersonAPI person, float probability) {
673 if (person == null) return;
675 potentialContactsOnMissionSuccess = new ArrayList<PotentialContactData>();
676 }
677 for (PotentialContactData data : potentialContactsOnMissionSuccess) {
678 if (data.contact == person) return;
679 }
680 PotentialContactData data = new PotentialContactData();
681 data.contact = person;
682 data.probability = probability;
684 }
685
686 public void setGenRandom(Random random) {
687 genRandom = random;
688 }
689
690 public void setMissionId(String missionId) {
691 this.missionId = missionId;
692 }
693 public String getMissionId() {
694 return missionId;
695 }
696
697 public boolean isBarEvent() {
698 return isBarEvent;
699 }
700
701 protected boolean isBarEvent = false;
702 public void createAndAbortIfFailed(MarketAPI market, boolean barEvent) {
703 isBarEvent = barEvent;
704 if (getPerson() != null) {
706 }
707 if (!create(market, barEvent)) {
708 abort();
709 }
710 }
711 protected abstract boolean create(MarketAPI createdAt, boolean barEvent);
712
713 protected String baseName = null;
714
715 public String getBaseName() {
716 if (baseName != null) {
717 return baseName;
718 }
719 return "Call setName(<name>) to set mission name";
720 }
721 public void setName(String name) {
722 baseName = name;
723 }
724
725 public String getBlurbText() {
726 return null;
727 }
728
729// public abstract boolean addNextStepText(TooltipMakerAPI info, Color tc, float pad);
730// public abstract void addDescriptionForCurrentStage(TooltipMakerAPI info, float width, float height);
731
732 public boolean addNextStepText(TooltipMakerAPI info, Color tc, float pad) {
733 String text = getNextStepText();
734 if (text != null) {
735 info.addPara(text, tc, pad);
736 return true;
737 }
738 return false;
739 }
740 public void addDescriptionForNonEndStage(TooltipMakerAPI info, float width, float height) {
741
742 }
743 public void addDescriptionForCurrentStage(TooltipMakerAPI info, float width, float height) {
744 float opad = 10f;
745 String text = getStageDescriptionText();
746 if (text != null) {
747 info.addPara(text, opad);
748 } else {
749 String noun = getMissionTypeNoun();
750 String verb = getMissionCompletionVerb();
751 if (isSucceeded()) {
752 info.addPara("You have successfully " + verb + " this " + noun + ".", opad);
753 } else if (isFailed()) {
754 info.addPara("You have failed this " + noun + ".", opad);
755 } else if (isAbandoned()) {
756 info.addPara("You have abandoned this " + noun + ".", opad);
757 } else {
758 addDescriptionForNonEndStage(info, width, height);
759 }
760 }
761 }
762 public String getStageDescriptionText() {
763 return null;
764 }
765 public String getNextStepText() {
766 return null;
767 }
768
769 @Override
770 protected void advanceImpl(float amount) {
771 float days = Global.getSector().getClock().convertToDays(amount);
772 StageData stage = getData(currentStage);
773 if (stage != null) {
774 stage.elapsed += days;
775 }
776
777 //elapsed += days * 100f;
778 elapsed += days;
779
780 //if (timeLimit != null) timeLimit.days = 240;
781 if (timeLimit != null && timeLimit.days < elapsed &&
782 (timeLimit.noLimitWhileInSystem == null ||
783 timeLimit.noLimitWhileInSystem != Global.getSector().getCurrentLocation())) {
784 setCurrentStage(timeLimit.failStage, null, null);
785 timeLimit = null;
786 runTriggers();
787 }
788
789 tracker.advance(days);
790 if (tracker.intervalElapsed()) {
792 }
793 }
794
796 StageData stage = getData(currentStage);
797 if (stage != null) {
798 return stage.elapsed;
799 }
800 return 0f;
801 }
802
803 @Override
804 protected void notifyEnded() {
805 super.notifyEnded();
806 Global.getSector().removeScript(this);
807 }
808
809 public void accept(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
810 setImportant(true);
811
812 if (startingStage == null) {
813 throw new RuntimeException("startingStage can not be null. Use setStartingStage()");
814 }
815
816 // don't pass in dialog/memoryMap so it doesn't add an update item to the textPanel
817 // might not anyway, but that depends on some future decisions...
818 setCurrentStage(startingStage, null, null); //dialog, memoryMap);
819
820 acceptImpl(dialog, memoryMap);
821
822 TextPanelAPI text = dialog != null ? dialog.getTextPanel() : null;
823
824 if (cargoOnAccept != null) {
825 cargoOnAccept.sort();
826 for (CargoStackAPI stack : cargoOnAccept.getStacksCopy()) {
827 Global.getSector().getPlayerFleet().getCargo().addItems(stack.getType(), stack.getData(), stack.getSize());
828 if (text != null) {
829 AddRemoveCommodity.addStackGainText(stack, text);
830 }
831 }
832 cargoOnAccept.clear();
833 }
834
835 Global.getSector().getIntelManager().addIntel(this, false, text);
836 Global.getSector().addScript(this);
837
838 startingStage = null;
839
840 runTriggers();
841 }
842
843 public void acceptImpl(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
844
845 }
846
847 protected transient boolean aborted = false;
848 public void abort() {
849 boolean missionWasAccepted = currentStage != null;
850 for (Abortable curr : changes) {
851 curr.abort(this, missionWasAccepted);
852 }
853 changes.clear();
854
855 //if (genRandom != null) {
856 if (!missionWasAccepted) {
857 aborted = true;
858 }
859
860 // is this needed? not if missions are reset every time in BaseMissionHub.updateOfferedMissions()
861 // and not saved
862// currentStage = null;
863// stages.clear();
864// successStages.clear();
865// failStages.clear();
866// connections.clear();
867//
868// genRandom = null;
869// startingStage = null;
870 }
871
872 public boolean isMissionCreationAborted() {
873 return aborted;
874 }
875
876
877 public String getTriggerPrefix() {
878 //return getClass().getSimpleName();
879 return getMissionId();
880 }
881
882 protected boolean callAction(String action, String ruleId, InteractionDialogAPI dialog, List<Token> params, Map<String, MemoryAPI> memoryMap) {
883 return false;
884 }
885
886 protected void addPotentialContacts(InteractionDialogAPI dialog) {
888 for (PotentialContactData curr : potentialContactsOnMissionSuccess) {
889 PersonAPI p = curr.contact;
890 MarketAPI m = curr.contact.getMarket();
891 if (m == null) m = getPerson().getMarket();
892 if (m != null) {
893 if (curr.probability < 0) {
894 ContactIntel.addPotentialContact(p, m, dialog != null ? dialog.getTextPanel() : null);
895 } else {
896 ContactIntel.addPotentialContact(curr.probability, p, m, dialog != null ? dialog.getTextPanel() : null);
897 }
898 }
899 }
901 }
902 }
903
904 @SuppressWarnings("rawtypes")
905 @Override
906 public boolean callEvent(String ruleId, InteractionDialogAPI dialog, List<Token> params, Map<String, MemoryAPI> memoryMap) {
907 String action = params.get(0).getString(memoryMap);
908
909 if ("endFailure".equals(action)) {
910 Object stage = null;
911 if (!failStages.isEmpty()) {
912 stage = failStages.get(0);
913 }
914 if (stage == null && !noPenaltyFailStages.isEmpty()) {
915 stage = noPenaltyFailStages.get(0);
916 }
917 if (stage != null) {
918 setCurrentStage(stage, dialog, memoryMap);
919 runTriggers();
920 }
921 return true;
922 }
923
924 if ("makeUnimportant".equals(action)) {
925 SectorEntityToken target = dialog.getInteractionTarget();
926 if (target != null) {
927 makeUnimportant(target, (Enum) currentStage);
928 if (target.getMarket() != null) {
929 makeUnimportant(target.getMarket(), (Enum) currentStage);
930 }
931 if (target.getActivePerson() != null) {
932 makeUnimportant(target.getActivePerson(), (Enum) currentStage);
933 }
934 }
935 return true;
936 }
937
938 if ("showMap".equals(action)) {
939 SectorEntityToken mapLoc = getMapLocation(null, startingStage);
940 if (mapLoc != null) {
941 String title = params.get(1).getStringWithTokenReplacement(ruleId, dialog, memoryMap);
942 String text = "";
943 Set<String> tags = getIntelTags(null);
944 tags.remove(Tags.INTEL_ACCEPTED);
945 String icon = getIcon();
946
947 Color color = getFactionForUIColors().getBaseUIColor();
948 //String factionId = getFactionForUIColors().getId();
949 if (mapLoc != null && mapLoc.getFaction() != null && !mapLoc.getFaction().isNeutralFaction()) {
950 color = mapLoc.getFaction().getBaseUIColor();
951 //factionId = mapLoc.getFaction().getId();
952 } else if (mapLoc instanceof PlanetAPI) {
953 PlanetAPI planet = (PlanetAPI) mapLoc;
954 if (planet.getStarSystem() != null && planet.getFaction().isNeutralFaction()) {
955 StarSystemAPI system = planet.getStarSystem();
956 if (system.getStar() == planet || system.getCenter() == planet) {
957 if (planet.getMarket() != null) {
958 color = planet.getMarket().getTextColorForFactionOrPlanet();
959 } else {
960 color = Misc.setAlpha(planet.getSpec().getIconColor(), 255);
961 color = Misc.setBrightness(color, 235);
962 }
963 } else {
964 color = Misc.setAlpha(planet.getSpec().getIconColor(), 255);
965 color = Misc.setBrightness(color, 235);
966 }
967 }
968 }
969 if (mapMarkerNameColor != null) {
970 color = mapMarkerNameColor;
971 }
972
973 dialog.getVisualPanel().showMapMarker(mapLoc,
974 title, color,
975 true, icon, text, tags);
976 }
977 return true;
978 }
979
980 if ("hideMap".equals(action)) {
981 dialog.getVisualPanel().removeMapMarkerFromPersonInfo();
982 return true;
983 }
984
985// if (action.equals("endSuccess")) {
986// doNotEndMission = true;
987// checkStageChangesAndTriggers();
988// doNotEndMission = false;
989// endSuccess(dialog, memoryMap);
990// } else if (action.equals("endFailure")) {
991// doNotEndMission = true;
992// checkStageChangesAndTriggers();
993// doNotEndMission = false;
994// endFailure(dialog, memoryMap);
995// } else
996 if (action.equals("updateStage")) {
997 checkStageChangesAndTriggers(dialog, memoryMap);
998 } else if (action.equals("updateData")) {
999 checkStageChangesAndTriggers(dialog, memoryMap);
1000 updateInteractionData(dialog, memoryMap);
1001 } else if (action.equals("addContacts")) {
1002 addPotentialContacts(dialog);
1003 } else if (action.equals("repSuccess")) {
1004 adjustRep(dialog.getTextPanel(), null, RepActions.MISSION_SUCCESS);
1005 } else if (action.equals("repFailure")) {
1006 adjustRep(dialog.getTextPanel(), null, RepActions.MISSION_FAILURE);
1007 } else {
1008 if (!callAction(action, ruleId, dialog, params, memoryMap)) {
1009 throw new RuntimeException("Unhandled action [" + action + "] in " + getClass().getSimpleName() +
1010 " for rule [" + ruleId + "], params:[" + params + "]");
1011 }
1012 }
1013 return true;
1014 }
1015
1016 protected void showPersonInfo(PersonAPI person, InteractionDialogAPI dialog, boolean withFaction, boolean withRelBar) {
1017 dialog.getInteractionTarget().setActivePerson(person);
1018 dialog.getVisualPanel().showPersonInfo(person, !withFaction, withRelBar);
1019 }
1020
1021 protected transient MemoryAPI interactionMemory = null;
1022 public void updateInteractionData(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
1023 interactionMemory = memoryMap.get(MemKeys.LOCAL);
1024 if (interactionMemory == null) {
1025 if (dialog.getInteractionTarget().getActivePerson() != null) {
1026 interactionMemory = dialog.getInteractionTarget().getActivePerson().getMemoryWithoutUpdate();
1027 } else {
1028 interactionMemory = dialog.getInteractionTarget().getMemoryWithoutUpdate();
1029 }
1030 }
1031
1032 // unless we're already talking to a person
1033 // actually, always do it; this happens in a bar event
1034 // don't always do it - if updateData is called when talking to *another* person
1035 // (i.e. not the mission giver) this would override their $HeOrShe etc tokens
1036 if (isBarEvent() || !memoryMap.containsKey(MemKeys.ENTITY)) {
1038 }
1039
1040 if (getCurrentStage() != null) {
1041 set("$" + getMissionId() + "_stage", ((Enum)getCurrentStage()).name());
1042 }
1043
1045 }
1046
1047
1048 protected void updateInteractionDataImpl() {
1049
1050 }
1051
1052 protected void setPersonTokens(MemoryAPI mem) {
1053 PersonAPI person = getPerson();
1054 if (person == null) return;
1055
1056 if (person.isMale()) {
1057 mem.set("$hisOrHer", "his", 0);
1058 mem.set("$HisOrHer", "His", 0);
1059 mem.set("$himOrHer", "him", 0);
1060 mem.set("$HimOrHer", "Him", 0);
1061 mem.set("$heOrShe", "he", 0);
1062 mem.set("$HeOrShe", "He", 0);
1063 mem.set("$himOrHerself", "himself", 0);
1064 mem.set("$HimOrHerself", "Himself", 0);
1065 mem.set("$manOrWoman", "man", 0);
1066 mem.set("$ManOrWoman", "Man", 0);
1067 } else {
1068 mem.set("$hisOrHer", "her", 0);
1069 mem.set("$HisOrHer", "Her", 0);
1070 mem.set("$himOrHer", "her", 0);
1071 mem.set("$HimOrHer", "Her", 0);
1072 mem.set("$heOrShe", "she", 0);
1073 mem.set("$HeOrShe", "She", 0);
1074 mem.set("$himOrHerself", "herself", 0);
1075 mem.set("$HimOrHerself", "Herself", 0);
1076 mem.set("$manOrWoman", "woman", 0);
1077 mem.set("$ManOrWoman", "Woman", 0);
1078 }
1079
1080 if (person.getRank() != null) {
1081 mem.set("$personRankAOrAn", person.getRankArticle(), 0);
1082 mem.set("$personRank", person.getRank().toLowerCase(), 0);
1083 mem.set("$PersonRank", Misc.ucFirst(person.getRank()), 0);
1084 }
1085
1086 if (person.getPost() != null) {
1087 mem.set("$personPostAOrAn", person.getPostArticle().toLowerCase(), 0);
1088 mem.set("$personPost", person.getPost().toLowerCase(), 0);
1089 mem.set("$PersonPost", Misc.ucFirst(person.getPost()), 0);
1090 }
1091
1092 mem.set("$PersonName", person.getName().getFullName(), 0);
1093 mem.set("$personName", person.getName().getFullName(), 0);
1094 mem.set("$personFirstName", person.getName().getFirst(), 0);
1095 mem.set("$personLastName", person.getName().getLast(), 0);
1096
1097 if (person.getVoice() != null) {
1098 mem.set("$voice", person.getVoice());
1099 }
1100 if (person.getImportance() != null) {
1101 mem.set("$importance", person.getImportance().name());
1102 }
1103
1104 }
1105
1106 public void set(String key, Object value) {
1107 if (value instanceof Enum) value = ((Enum)value).name();
1108 interactionMemory.set(key, value, 0f);
1109 }
1110
1111 public void unset(String key) {
1112 interactionMemory.unset(key);
1113 }
1114
1115
1116 public StageData getData(Object id) {
1117 if (id == null) return null;
1118 StageData data = stages.get(id);
1119 if (data == null) {
1120 data = new StageData();
1121 data.id = id;
1122 stages.put(id, data);
1123 }
1124 return data;
1125 }
1126
1127 protected boolean shouldSendUpdateForStage(Object id) {
1128 return true;
1129 }
1130
1131 public void checkStageChangesAndTriggers(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
1132 if (isEnding()) return;
1133 boolean changed = false;
1134 do {
1135 changed = false;
1136 for (StageConnection conn : connections) {
1137 if (conn.from != currentStage && conn.from != null) continue;
1138 if (conn.to == currentStage) continue;
1139
1140 if (conn.checker.conditionsMet()) {
1141 setCurrentStage(conn.to, dialog, memoryMap);
1142 changed = true;
1143
1145 connections.remove(conn);
1146 }
1147
1148 break;
1149 }
1150 }
1151 //runTriggers();
1152 } while (changed);
1153
1154 runTriggers();
1155 }
1156
1157 protected void runTriggers() {
1158 Iterator<MissionTrigger> iter = triggers.iterator();
1159 while (iter.hasNext()) {
1160 MissionTrigger trigger = iter.next();
1161 if (!trigger.getStages().contains(currentStage)) continue;
1162 if (trigger.getCondition().conditionsMet()) {
1163 TriggerActionContext context = new TriggerActionContext(this);
1164 for (TriggerAction curr : trigger.getActions()) {
1165 curr.doAction(context);
1166 }
1167 iter.remove();
1168 }
1169 }
1170 }
1171
1172 public List<CampaignFleetAPI> runStageTriggersReturnFleets(Object stage) {
1173 List<CampaignFleetAPI> result = new ArrayList<CampaignFleetAPI>();
1174 Iterator<MissionTrigger> iter = triggers.iterator();
1175 while (iter.hasNext()) {
1176 MissionTrigger trigger = iter.next();
1177 if (!trigger.getStages().contains(stage)) continue;
1178 if (trigger.getCondition().conditionsMet()) {
1179 TriggerActionContext context = new TriggerActionContext(this);
1180 for (TriggerAction curr : trigger.getActions()) {
1181 curr.doAction(context);
1182 }
1183 iter.remove();
1184 result.addAll(context.allFleets);
1185 }
1186 }
1187 return result;
1188 }
1189
1190 protected transient boolean doNotEndMission = false;
1191 public void setCurrentStage(Object next, InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
1192 if (currentStage == next) {
1193 return;
1194 }
1195
1196 if (currentStage != null) {
1197 StageData data = getData(currentStage);
1198 for (ImportanceData curr : data.important) {
1199 Misc.makeUnimportant(curr.memory, getReason());
1200 removeImportanceChanges(curr.memory);
1201
1202 if (curr.flag != null) {
1203 curr.memory.unset(curr.flag);
1204 removeMemoryFlagChanges(curr.memory, curr.flag);
1205 }
1206 }
1207 }
1208
1209 currentStage = next;
1210 if (timeLimit != null && timeLimit.endLimitStages != null &&
1211 timeLimit.endLimitStages.contains(currentStage)) {
1212 timeLimit = null;
1213 }
1214
1215 StageData data = getData(currentStage);
1216 data.elapsed = 0;
1217 for (ImportanceData curr : data.important) {
1218 //if (curr.market != null) curr.memory = curr.market.getMemoryWithoutUpdate();
1219
1220 Misc.makeImportant(curr.memory, getReason());
1221 changes.add(new MadeImportant(curr.memory, getReason()));
1222 if (curr.flag != null) {
1223 curr.memory.set(curr.flag, true);
1224 changes.add(new VariableSet(curr.memory, curr.flag, true));
1225 }
1226 }
1227
1228 for (FlagData fd : flags) {
1229 if (fd.stages.contains(currentStage)) {
1230 removeMemoryFlagChanges(fd.memory, fd.flag);
1231 fd.memory.set(fd.flag, true);
1232 changes.add(new VariableSet(fd.memory, fd.flag, true));
1233 } else {
1234 fd.memory.unset(fd.flag);
1235 removeMemoryFlagChanges(fd.memory, fd.flag);
1236 }
1237
1238 }
1239
1240
1241 if (!doNotEndMission) {
1242 if (successStages.contains(currentStage)) {
1243 endSuccess(dialog, memoryMap);
1244 } else if (failStages.contains(currentStage)) {
1245 endFailure(dialog, memoryMap);
1246 } else if (currentStage != null && currentStage == abandonStage) {
1247 endAbandon();
1249 sendUpdateForNextStep(NEXT_STEP_UPDATE, dialog == null ? null : dialog.getTextPanel());
1250 }
1251 }
1252
1253 runTriggers();
1254 }
1255
1256 protected void endSuccess(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
1257 setImportant(false);
1258
1259 result = new HubMissionResult();
1260 result.success = true;
1261
1262 TextPanelAPI textPanel = null;
1263 if (dialog != null) textPanel = dialog.getTextPanel();
1264
1265 int xp = getXPReward();
1266 if (xp > 0) {
1267 Global.getSector().getPlayerStats().addXP(xp, textPanel);
1268 }
1269
1270 int reward = getCreditsReward();
1271 if (reward > 0) {
1272 Global.getSector().getPlayerFleet().getCargo().getCredits().add(reward);
1273 }
1274
1275 if (textPanel != null && reward > 0) {
1276 AddRemoveCommodity.addCreditsGainText(reward, dialog.getTextPanel());
1277 }
1278
1279
1280 result.reward = reward;
1281 result.xp = xp;
1282
1283 adjustRep(textPanel, result, RepActions.MISSION_SUCCESS);
1284
1285
1286 endSuccessImpl(dialog, memoryMap);
1287
1288 if (cargoOnSuccess != null) {
1289 cargoOnSuccess.sort();
1290 for (CargoStackAPI stack : cargoOnSuccess.getStacksCopy()) {
1291 Global.getSector().getPlayerFleet().getCargo().addItems(stack.getType(), stack.getData(), stack.getSize());
1292 if (textPanel != null) {
1293 AddRemoveCommodity.addStackGainText(stack, textPanel);
1294 }
1295 }
1296 cargoOnSuccess.clear();
1297 }
1298
1299 endAfterDelay();
1300
1301// if (textPanel == null) { // if in dialog, already printed stuff to the text panel
1302// sendUpdateIfPlayerHasIntel(result, false);
1303// }
1304 sendUpdateForNextStep(END_MISSION_UPDATE, dialog == null ? null : dialog.getTextPanel());
1305
1306 if (creator != null) creator.incrCompleted();
1307
1308
1311 for (PotentialContactData curr : potentialContactsOnMissionSuccess) {
1312 PersonAPI p = curr.contact;
1313 MarketAPI m = curr.contact.getMarket();
1314 if (m == null) m = getPerson().getMarket();
1315 if (curr.probability < 0) {
1316 ContactIntel.addPotentialContact(p, m, dialog != null ? dialog.getTextPanel() : null);
1317 } else {
1318 ContactIntel.addPotentialContact(curr.probability, p, m, dialog != null ? dialog.getTextPanel() : null);
1319 }
1320 }
1323 }
1324 }
1325
1326 abort();
1327
1328 if (completedKey != null) {
1329 Global.getSector().getMemoryWithoutUpdate().set(completedKey, true);
1330 }
1331 }
1332
1333 protected void endFailure(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
1334 setImportant(false);
1335
1336 result = new HubMissionResult();
1337 result.success = false;
1338
1339 TextPanelAPI textPanel = null;
1340 if (dialog != null) textPanel = dialog.getTextPanel();
1341
1342 if (!noPenaltyFailStages.contains(currentStage)) {
1343 adjustRep(textPanel, result, RepActions.MISSION_FAILURE);
1344 }
1345
1346 endFailureImpl(dialog, memoryMap);
1347 endAfterDelay();
1348
1349// if (textPanel == null) {
1350// sendUpdateIfPlayerHasIntel(result, false);
1351// }
1352 sendUpdateForNextStep(END_MISSION_UPDATE, dialog == null ? null : dialog.getTextPanel());
1353
1354 if (creator != null) creator.incrFailed();
1355 abort();
1356 }
1357
1358 protected void endAbandon() {
1359 result = new HubMissionResult();
1360 result.success = false;
1361
1362 if (!canAbandonWithoutPenalty()) {
1363 adjustRep(null, result, RepActions.MISSION_FAILURE);
1364 if (creator != null) creator.incrFailed();
1365 }
1366
1368
1369 endAfterDelay();
1370 abort();
1371 }
1372
1373
1374
1375 protected void endSuccessImpl(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
1376 }
1377 protected void endFailureImpl(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
1378 }
1379 protected void endAbandonImpl() {
1380 }
1381
1382
1383 protected Boolean adjustedRep;
1384 protected void adjustRep(TextPanelAPI textPanel, HubMissionResult result, RepActions action) {
1385 if (adjustedRep != null) return;
1386 adjustedRep = true;
1387
1388 MissionCompletionRep completionRepPerson = new MissionCompletionRep(
1391 MissionCompletionRep completionRepFaction = new MissionCompletionRep(
1394
1395 boolean withMessage = textPanel != null;
1396
1397 boolean adjustPersonRep = (action == RepActions.MISSION_SUCCESS && completionRepPerson.successDelta != 0) ||
1398 (action == RepActions.MISSION_FAILURE && completionRepPerson.failureDelta != 0);
1399 if (adjustPersonRep && getPerson() != null) {
1400 ReputationAdjustmentResult rep = Global.getSector().adjustPlayerReputation(
1401 new RepActionEnvelope(action, completionRepPerson,
1402 textPanel, true, withMessage),
1403 getPerson());
1404 if (result != null) result.repPerson = rep;
1405 completionRepPerson.successDelta = 0;
1406 }
1407
1408 boolean adjustFactionRep = (action == RepActions.MISSION_SUCCESS && completionRepFaction.successDelta != 0) ||
1409 (action == RepActions.MISSION_FAILURE && completionRepFaction.failureDelta != 0);
1410 if (adjustFactionRep && getPerson() != null) {
1411 ReputationAdjustmentResult rep = Global.getSector().adjustPlayerReputation(
1412 new RepActionEnvelope(action, completionRepFaction,
1413 textPanel, true, withMessage),
1414 getPerson().getFaction().getId());
1415 if (result != null) result.repFaction = rep;
1416 completionRepFaction.successDelta = 0f;
1417 }
1418 }
1419
1420
1421 public void setSuccessStage(Object id) {
1422 addSuccessStages(id);
1423 }
1424 public void addSuccessStages(Object ... ids) {
1425 for (Object id : ids) {
1426 successStages.add(id);
1427 }
1428 }
1429
1430 public void setFailureStage(Object id) {
1431 addFailureStages(id);
1432 }
1433 public void addFailureStages(Object ... ids) {
1434 for (Object id : ids) {
1435 failStages.add(id);
1436 }
1437 }
1438
1439 public void setNoPenaltyFailureStage(Object id) {
1441 }
1442 public void addNoPenaltyFailureStages(Object ... ids) {
1443 addFailureStages(ids);
1444 for (Object id : ids) {
1445 noPenaltyFailStages.add(id);
1446 }
1447 }
1448
1449 protected void removeImportanceChanges(MemoryAPI memory) {
1450 Iterator<Abortable> iter = changes.iterator();
1451 while (iter.hasNext()) {
1452 Abortable curr = iter.next();
1453 if (curr instanceof MadeImportant) {
1454 MadeImportant mi = (MadeImportant) curr;
1455 if (mi.memory == memory) {
1456 iter.remove();
1457 }
1458 }
1459 }
1460 }
1461
1462 protected void removeMemoryFlagChanges(MemoryAPI memory, String flag) {
1463 Iterator<Abortable> iter = changes.iterator();
1464 while (iter.hasNext()) {
1465 Abortable curr = iter.next();
1466 if (curr instanceof VariableSet) {
1467 VariableSet vs = (VariableSet) curr;
1468 if (vs.memory == memory && flag.equals(vs.key)) {
1469 iter.remove();
1470 }
1471 }
1472 }
1473 }
1474
1475 public String getReason() {
1476 return getMissionId();
1477 }
1478
1479 public int getCreditsReward() {
1480 if (creditReward != null) return creditReward;
1481 return 0;
1482 }
1483
1484 public int getXPReward() {
1485 if (xpReward != null) return xpReward;
1486 return 0;
1487 }
1488
1490 if (repRewardPerson != null) return repRewardPerson;
1491 return RepRewards.HIGH;
1492 }
1493
1495 if (repPenaltyPerson != null) return repPenaltyPerson;
1496 return RepRewards.SMALL;
1497 }
1498
1500 if (repRewardFaction != null) return repRewardFaction;
1501 return RepRewards.MEDIUM;
1502 }
1503
1505 if (repPenaltyFaction != null) return repPenaltyFaction;
1506 return RepRewards.TINY;
1507 }
1508
1509 public RepLevel getRewardLimitPerson() {
1510 return rewardLimitPerson != null ? rewardLimitPerson : RepLevel.COOPERATIVE;
1511 }
1512
1513 public RepLevel getRewardLimitFaction() {
1514 return rewardLimitFaction != null ? rewardLimitFaction : RepLevel.COOPERATIVE;
1515 }
1516
1517 public RepLevel getPenaltyLimitPerson() {
1518 return penaltyLimitPerson != null ? penaltyLimitPerson : RepLevel.VENGEFUL;
1519 }
1520
1521 public RepLevel getPenaltyLimitFaction() {
1522 return penaltyLimitFaction != null ? penaltyLimitFaction : RepLevel.VENGEFUL;
1523 }
1524
1526 return hub;
1527 }
1528
1529 public void setHub(MissionHub hub) {
1530 this.hub = hub;
1531 }
1532
1533 public PersonAPI getPerson() {
1534 if (personOverride != null) return personOverride;
1535 if (hub == null) return null;
1536 return hub.getPerson();
1537 }
1538
1540 return creator;
1541 }
1542
1544 this.creator = creator;
1545 }
1546
1547 public void setStartingStage(Object startingStage) {
1548 this.startingStage = startingStage;
1549 }
1550
1551 public void setPersonDoGenericPortAuthorityCheck(PersonAPI person) {
1552 if (person.getMemoryWithoutUpdate().getBoolean("$doGenericPortAuthorityCheck")) return;
1553 setFlag(person, "$doGenericPortAuthorityCheck", false);
1554 }
1555
1556// public void setMarketExtraSmugglingSuspicionLevel(MarketAPI market, float extra) {
1557// setFlag(market.getMemoryWithoutUpdate(), MemFlags.MARKET_EXTRA_SUSPICION, extra, false);
1558// }
1559
1560 public void setFlagWithReason(SectorEntityToken entity, String flag, boolean permanent) {
1561 setFlag(entity.getMemoryWithoutUpdate(), flag, null, permanent, (Object[])null);
1562
1563 String reason = getReason();
1564 Misc.setFlagWithReason(entity.getMemoryWithoutUpdate(), flag, reason, true, -1f);
1565
1566 if (!permanent) {
1567 String requiredKey = flag + "_" + reason;
1568 changes.add(new VariableSet(entity.getMemoryWithoutUpdate(), requiredKey, true));
1569 }
1570 }
1571
1572 public void setFlag(SectorEntityToken entity, String flag, boolean permanent) {
1573 setFlag(entity.getMemoryWithoutUpdate(), flag, null, permanent, (Object[])null);
1574 }
1575 public void setFlag(PersonAPI person, String flag, boolean permanent) {
1576 setFlag(person.getMemoryWithoutUpdate(), flag, null, permanent, (Object[])null);
1577 }
1578
1579 public void setFlag(SectorEntityToken entity, String flag, boolean permanent, Object ... stages) {
1580 setFlag(entity.getMemoryWithoutUpdate(), flag, null, permanent, stages);
1581 }
1582 public void setFlag(PersonAPI person, String flag, boolean permanent, Object ... stages) {
1583 setFlag(person.getMemoryWithoutUpdate(), flag, null, permanent, stages);
1584 }
1585
1586 public void setGlobalFlag(String flag, Object value, Object ... stages) {
1587 setFlag(getGlobalMemory(), flag, value, false, stages);
1588 }
1589
1590 public void setFlag(MemoryAPI memory, String flag, Object value, boolean permanent) {
1591 setFlag(memory, flag, value, permanent, (Object []) null);
1592 }
1593 public void setFlag(MemoryAPI memory, String flag, Object value, boolean permanent, Object ... stages) {
1594 if (stages != null && stages.length > 0) {
1595 FlagData fd = new FlagData();
1596 fd.memory = memory;
1597 fd.flag = flag;
1598 fd.stages.addAll(Arrays.asList(stages));
1599 flags.add(fd);
1600 if (fd.stages.contains(currentStage)) {
1601 removeMemoryFlagChanges(fd.memory, fd.flag);
1602 fd.memory.set(fd.flag, true);
1603 changes.add(new VariableSet(fd.memory, fd.flag, true));
1604 }
1605 } else {
1606 if (value == null) {
1607 memory.set(flag, true);
1608 } else {
1609 memory.set(flag, value);
1610 }
1611 changes.add(new VariableSet(memory, flag, !permanent));
1612 }
1613 }
1614
1615 public boolean setGlobalReference(String key) {
1616 if (getGlobalMemory().contains(key)) {
1617 return false;
1618 }
1619 getGlobalMemory().set(key, this);
1620 changes.add(new VariableSet(getGlobalMemory(), key, true));
1621 return true;
1622 }
1623
1624 public boolean setGlobalReference(String refKey, String inProgressFlag) {
1625 if (getGlobalMemory().contains(refKey)) {
1626 return false;
1627 }
1628 getGlobalMemory().set(refKey, this);
1629 changes.add(new VariableSet(getGlobalMemory(), refKey, true));
1630
1631 if (inProgressFlag != null) {
1632 getGlobalMemory().set(inProgressFlag, true);
1633 changes.add(new VariableSet(getGlobalMemory(), inProgressFlag, true));
1634 }
1635 return true;
1636 }
1637
1638 public boolean setPersonMissionRef(PersonAPI person, String key) {
1639 if (person == null) return false;
1640 if (person.getMemoryWithoutUpdate().contains(key)) {
1641 return false;
1642 }
1643 person.getMemoryWithoutUpdate().set(key, this);
1644 changes.add(new VariableSet(person.getMemoryWithoutUpdate(), key, true));
1645 return true;
1646 }
1647
1648 public boolean setFactionMissionRef(FactionAPI faction, String key) {
1649 if (faction == null) return false;
1650 if (faction.getMemoryWithoutUpdate().contains(key)) {
1651 return false;
1652 }
1653 faction.getMemoryWithoutUpdate().set(key, this);
1654 changes.add(new VariableSet(faction.getMemoryWithoutUpdate(), key, true));
1655 return true;
1656 }
1657
1658 public boolean setMarketMissionRef(MarketAPI market, String key) {
1659 if (market == null) return false;
1660 if (market.getMemoryWithoutUpdate().contains(key)) {
1661 return false;
1662 }
1663 market.getMemoryWithoutUpdate().set(key, this);
1664 changes.add(new VariableSet(market.getMemoryWithoutUpdate(), key, true));
1665 return true;
1666 }
1667
1668 public boolean setEntityMissionRef(SectorEntityToken entity, String key) {
1669 if (entity == null) return false;
1670 if (entity.getMemoryWithoutUpdate().contains(key)) {
1671 return false;
1672 }
1673 entity.getMemoryWithoutUpdate().set(key, this);
1674 changes.add(new VariableSet(entity.getMemoryWithoutUpdate(), key, true));
1675 return true;
1676 }
1677
1678 public MemoryAPI getGlobalMemory() {
1679 return Global.getSector().getMemoryWithoutUpdate();
1680 }
1681
1682 public void makeImportantDoNotShowAsIntelMapLocation(PersonAPI person, String flag, Enum ... stages) {
1683 makeImportant(person.getMemoryWithoutUpdate(), flag, null, person, stages);
1684 }
1685 public void makeImportantDoNotShowAsIntelMapLocation(SectorEntityToken entity, String flag, Enum ... stages) {
1686 makeImportant(entity.getMemoryWithoutUpdate(), flag, null, entity, stages);
1687 }
1688 public void makeImportantDoNotShowAsIntelMapLocation(MarketAPI market, String flag, Enum ... stages) {
1689 makeImportant(market.getMemoryWithoutUpdate(), flag, null, market, stages);
1690 }
1691 public void makeImportant(PersonAPI person, String flag, Enum ... stages) {
1692 makeImportant(person.getMemoryWithoutUpdate(), flag, MapLocationType.NORMAL, person, stages);
1693 }
1694 public void makeImportant(SectorEntityToken entity, String flag, Enum ... stages) {
1695 makeImportant(entity.getMemoryWithoutUpdate(), flag, MapLocationType.NORMAL, entity, stages);
1696 }
1697 public void makeImportant(MarketAPI market, String flag, Enum ... stages) {
1698 makeImportant(market.getMemoryWithoutUpdate(), flag, MapLocationType.NORMAL, market, stages);
1699 }
1700 public void makeImportant(MemoryAPI memory, String flag, MapLocationType type, Object personOrEntityOrMarket, Enum ... stages) {
1701 boolean inCurrentStage = false;
1702 if (stages != null) {
1703 for (Object id : stages) {
1704 if (currentStage != null && id == currentStage) inCurrentStage = true;
1705 ImportanceData data = new ImportanceData();
1706 data.memory = memory;
1707 data.flag = flag;
1708 data.locType = type;
1709 if (personOrEntityOrMarket instanceof PersonAPI) {
1710 data.person = (PersonAPI) personOrEntityOrMarket;
1711 } else if (personOrEntityOrMarket instanceof SectorEntityToken) {
1712 data.entity = (SectorEntityToken) personOrEntityOrMarket;
1713 } else if (personOrEntityOrMarket instanceof MarketAPI) {
1714 data.market = (MarketAPI) personOrEntityOrMarket;
1715 }
1716 getData(id).important.add(data);
1717 }
1718 } else {
1719 inCurrentStage = true;
1720 }
1721
1722 if (inCurrentStage) {
1723 Misc.makeImportant(memory, getReason());
1724 if (stages != null) {
1725 changes.add(new MadeImportant(memory, getReason()));
1726 }
1727 if (flag != null) {
1728 memory.set(flag, true);
1729 if (stages != null) {
1730 changes.add(new VariableSet(memory, flag, true));
1731 }
1732 }
1733 }
1734 }
1735
1736 public void makeUnimportant(PersonAPI person, Enum ... stages) {
1737 if (person == null) return;
1738 makeUnimportant(person.getMemoryWithoutUpdate(), person, stages);
1739 }
1740 public void makeUnimportant(SectorEntityToken entity, Enum ... stages) {
1741 if (entity == null) return;
1742 makeUnimportant(entity.getMemoryWithoutUpdate(), entity, stages);
1743 }
1744 public void makeUnimportant(MarketAPI market, Enum ... stages) {
1745 if (market == null) return;
1746 makeUnimportant(market.getMemoryWithoutUpdate(), market, stages);
1747 }
1748 public void makeUnimportant(PersonAPI person) {
1749 if (person == null) return;
1750 makeUnimportant(person.getMemoryWithoutUpdate(), person, (Enum []) null);
1751 }
1752 public void makeUnimportant(SectorEntityToken entity) {
1753 if (entity == null) return;
1754 makeUnimportant(entity.getMemoryWithoutUpdate(), entity, (Enum []) null);
1755 }
1756 public void makeUnimportant(MarketAPI market) {
1757 if (market == null) return;
1758 makeUnimportant(market.getMemoryWithoutUpdate(), market, (Enum []) null);
1759 }
1760 public void makeUnimportant(MemoryAPI memory, Object personOrEntityOrMarket) {
1761 makeUnimportant(memory, personOrEntityOrMarket, (Enum []) null);
1762 }
1763 public void makeUnimportant(MemoryAPI memory, Object personOrEntityOrMarket, Enum ... stages) {
1764 List<StageData> list = new ArrayList<BaseHubMission.StageData>();
1765 if (stages != null) {
1766 for (Object id : stages) {
1767 StageData stageData = getData(id);
1768 list.add(stageData);
1769 }
1770 } else {
1771 list.addAll(this.stages.values());
1772 }
1773
1774 for (StageData stageData : list) {
1775 Iterator<ImportanceData> iter = stageData.important.iterator();
1776 while (iter.hasNext()) {
1777 ImportanceData data = iter.next();
1778 if (data.memory == memory ||
1779 data.person == personOrEntityOrMarket ||
1780 data.entity == personOrEntityOrMarket ||
1781 data.market == personOrEntityOrMarket) {
1782 iter.remove();
1783 }
1784 }
1785 }
1786 Misc.makeUnimportant(memory, getReason());
1787 }
1788
1789
1790// too easy to mix up with the other method
1791// public void setTimeLimit(Object failStage, float days, Object ... noLimitAfterStages) {
1792// setTimeLimit(failStage, days, null, noLimitAfterStages);
1793// }
1794 public void setTimeLimit(Object failStage, float days, StarSystemAPI noLimitWhileInSystem, Object ... noLimitAfterStages) {
1795 timeLimit = new TimeLimitData();
1796 timeLimit.days = days;
1797 timeLimit.failStage = failStage;
1798 timeLimit.noLimitWhileInSystem = noLimitWhileInSystem;
1799 if (noLimitAfterStages != null) {
1800 for (Object stage : noLimitAfterStages) {
1801 timeLimit.endLimitStages.add(stage);
1802 }
1803 }
1804 }
1805
1806 public HubMissionResult getResult() {
1807 return result;
1808 }
1809
1810
1811 public int genRoundNumber(int min, int max) {
1812 int result = min + genRandom.nextInt(max - min + 1);
1813 return getRoundNumber(result);
1814 }
1815
1816 public static int getRoundNumber(float num) {
1817 int num2 = (int) num;
1818 for (int i = 1; i < 10; i++) {
1819 int threshold = (int) Math.pow(10, i);
1820 int base = threshold / 10;
1821 if (num2 > threshold) {
1822 num2 = num2 / base * base;
1823 }
1824 }
1825 return (int) num2;
1826 }
1827 public void setCreditReward(int min, int max) {
1828 setCreditReward(min, max, true);
1829 }
1830 public void setCreditReward(int min, int max, boolean withMult) {
1831 int reward = min + genRandom.nextInt(max - min + 1);
1832 if (withMult) {
1833 reward = getRoundNumber(reward * rewardMult);
1834 }
1835 reward = reward / 1000 * 1000;
1836 if (reward > 100000) {
1837 reward = reward / 10000 * 10000;
1838 }
1839 setCreditReward(reward);
1840 }
1841
1842 public void setCreditReward(Integer creditReward) {
1843 this.creditReward = creditReward;
1844 }
1845
1848 this.creditReward = creditReward;
1849 }
1850
1851 public void setCreditReward(CreditReward reward) {
1852 setCreditReward(reward.min, reward.max);
1853 }
1854 public void setCreditReward(CreditReward reward, int marketSize) {
1855 setCreditReward(reward.min / 2 + reward.perMarketSize * Math.max(0, marketSize - 3),
1856 reward.max / 2 + reward.perMarketSize * Math.max(0, marketSize - 3));
1857 }
1858
1859 public void setCreditRewardWithBonus(CreditReward reward, int bonus) {
1860 setCreditReward(reward.min + bonus, reward.max + bonus);
1861 }
1862
1863 public int getRewardBonusForMarines(int marines) {
1864 return marines * EXTRA_REWARD_PER_MARINE;
1865 }
1866
1867// public void setXPReward(XPReward reward) {
1868// float f = reward.getFractionOfLevel();
1869// LevelupPlugin plugin = Global.getSettings().getLevelupPlugin();
1870//
1871// int level = Global.getSector().getPlayerStats().getLevel();
1872// if (level < MIN_LEVEL_TO_SCALE_XP_GAIN_AT) level = MIN_LEVEL_TO_SCALE_XP_GAIN_AT;
1873// if (level > MAX_LEVEL_TO_SCALE_XP_GAIN_AT) level = MAX_LEVEL_TO_SCALE_XP_GAIN_AT;
1874//
1875// int xp = (int) plugin.getXPForNextLevel(level);
1876// xp *= f;
1877//
1878// setXPReward(xp);
1879// }
1880
1881 public void setXPReward(int xpReward) {
1882 this.xpReward = xpReward;
1883 if (this.xpReward <= 0) this.xpReward = null;
1884 }
1885
1886
1890 }
1891
1895 }
1896
1898 setRepRewardPerson(RepRewards.TINY);
1900 }
1902 setRepRewardFaction(RepRewards.TINY);
1904 }
1906 setRepRewardPerson(RepRewards.SMALL);
1907 setRepPenaltyPerson(RepRewards.TINY);
1908 }
1910 setRepRewardFaction(RepRewards.SMALL);
1911 setRepPenaltyFaction(RepRewards.TINY);
1912 }
1914 setRepRewardPerson(RepRewards.MEDIUM);
1915 setRepPenaltyPerson(RepRewards.TINY);
1916 }
1918 setRepRewardFaction(RepRewards.MEDIUM);
1919 setRepPenaltyFaction(RepRewards.TINY);
1920 }
1922 setRepRewardPerson(RepRewards.HIGH);
1923 setRepPenaltyPerson(RepRewards.SMALL);
1924 }
1926 setRepRewardFaction(RepRewards.HIGH);
1927 setRepPenaltyFaction(RepRewards.SMALL);
1928 }
1930 setRepRewardPerson(RepRewards.VERY_HIGH);
1931 setRepPenaltyPerson(RepRewards.MEDIUM);
1932 }
1934 setRepRewardFaction(RepRewards.VERY_HIGH);
1935 setRepPenaltyFaction(RepRewards.MEDIUM);
1936 }
1938 setRepRewardPerson(RepRewards.EXTREME);
1939 setRepPenaltyPerson(RepRewards.MEDIUM);
1940 }
1942 setRepRewardFaction(RepRewards.EXTREME);
1943 setRepPenaltyFaction(RepRewards.MEDIUM);
1944 }
1945
1953 public void setNoRepChanges() {
1954 setRepChanges(0, 0, 0, 0);
1955 }
1956
1958 this.repRewardPerson = repRewardPerson;
1959 }
1960
1962 this.repPenaltyPerson = repPenaltyPerson;
1963 }
1964
1966 this.repRewardFaction = repRewardFaction;
1967 }
1968
1970 this.repPenaltyFaction = repPenaltyFaction;
1971 }
1972
1974 this.penaltyLimitPerson = penaltyLimitPerson;
1975 }
1976
1978 this.penaltyLimitFaction = penaltyLimitFaction;
1979 }
1980
1981 public static boolean playerLevelIsAtLeast(int level) {
1982 return Global.getSector().getPlayerStats().getLevel() >= level;
1983 }
1984
1985 public static boolean playerLevelIsMaxed() {
1986 int max = Global.getSettings().getLevelupPlugin().getMaxLevel();
1987 return Global.getSector().getPlayerStats().getLevel() >= max;
1988 }
1989
1990 public static int getMaxPlayerLevel() {
1991 return Global.getSettings().getLevelupPlugin().getMaxLevel();
1992 }
1993
1994 public static boolean isDevMode() {
1995 return Global.getSettings().isDevMode();
1996 }
1997
1998 protected Set<String> addedTags = null;
1999 public void addTag(String tag) {
2000 if (addedTags == null) addedTags = new HashSet<String>();
2001 addedTags.add(tag);
2002 }
2003
2004 @Override
2005 public Set<String> getIntelTags(SectorMapAPI map) {
2006 Set<String> tags = super.getIntelTags(map);
2007 tags.add(Tags.INTEL_MISSIONS);
2008 tags.add(Tags.INTEL_ACCEPTED);
2009 if (getFactionForUIColors() != null && !getFactionForUIColors().isPlayerFaction()) {
2010 tags.add(getFactionForUIColors().getId());
2011 }
2012 if (addedTags != null) {
2013 tags.addAll(addedTags);
2014 }
2015 return tags;
2016 }
2017
2018 public SectorEntityToken getMapLocationFor(SectorEntityToken entity) {
2019 if ((entity.isDiscoverable() ||
2020 (entity instanceof CampaignFleetAPI && !((CampaignFleetAPI)entity).isVisibleToPlayerFleet())) && entity.getStarSystem() != null) {
2021 return entity.getStarSystem().getCenter();
2022 }
2023 return entity;
2024 }
2025
2026 @Override
2027 public SectorEntityToken getMapLocation(SectorMapAPI map) {
2028 if (currentStage == null) return null;
2029
2030 return getMapLocation(map, currentStage);
2031 }
2032
2033 public void makePrimaryObjective(Object personOrMarketOrEntity) {
2034 StageData stage = getData(currentStage);
2035 ImportanceData data = null;
2036 for (ImportanceData curr : stage.important) {
2037 if (curr.locType == null) continue;
2038 if (curr.entity == personOrMarketOrEntity ||
2039 curr.market == personOrMarketOrEntity ||
2040 curr.person == personOrMarketOrEntity) {
2041 data = curr;
2042 break;
2043 }
2044 }
2045 if (data != null) {
2046 stage.important.remove(data);
2047 stage.important.add(0, data);
2048 }
2049 }
2050
2051 public SectorEntityToken getMapLocation(SectorMapAPI map, Object currentStage) {
2052 if (currentStage == null) {
2054 }
2055 StageData stage = getData(currentStage);
2056 ImportanceData data = null;
2057 for (ImportanceData curr : stage.important) {
2058 if (curr.locType == null) continue;
2059 if (curr.entity != null && !curr.entity.isAlive()) continue;
2060 data = curr;
2061 break;
2062 }
2063 if (data == null || data.locType == null) return null;
2064
2065 SectorEntityToken entity = data.entity;
2066 if (entity == null && data.person != null && data.person.getMarket() != null) {
2067 entity = data.person.getMarket().getPrimaryEntity();
2068 }
2069 if (entity == null && data.market!= null) {
2070 entity = data.market.getPrimaryEntity();
2071 }
2072 if (entity == null) return null;
2073
2074 if (data.locType == MapLocationType.NORMAL) {
2075 if ((entity.isDiscoverable() ||
2076 (entity instanceof CampaignFleetAPI && !((CampaignFleetAPI)entity).isVisibleToPlayerFleet())) && entity.getStarSystem() != null) {
2077 return entity.getStarSystem().getCenter();
2078 }
2079 return entity;
2080 } else if (data.locType == MapLocationType.CONSTELLATION) {
2081 Constellation c = entity.getConstellation();
2082 SectorEntityToken result = null;
2083 if (c != null && map != null) {
2084 result = map.getConstellationLabelEntity(c);
2085 }
2086 if (result == null) result = entity;
2087 return result;
2088 }
2089
2090 return entity;
2091 }
2092
2093 public String getSortString() {
2094 return getBaseName();
2095 }
2096
2097 public void setIconName(String iconName) {
2098 this.iconName = iconName;
2099 }
2100 public void setIconName(String category, String id) {
2101 this.iconName = Global.getSettings().getSpriteName(category, id);
2102 }
2103
2104 public String getPostfixForState() {
2105 if (isEnding()) {
2106 if (isSucceeded()) {
2107 return " - Completed";
2108 } else if (isFailed()) {
2109 return " - Failed";
2110 } else if (isAbandoned()) {
2111 return " - Abandoned";
2112 }
2113 return " - Ended";
2114 }
2115 if (startingStage != null) {
2116 return " - Accepted";
2117 }
2118 return "";
2119 }
2120
2121 public String getName() {
2122 return getBaseName() + (getPostfixForState() == null ? "" : getPostfixForState());
2123 }
2124
2125 @Override
2126 public FactionAPI getFactionForUIColors() {
2127 if (getPerson() == null) return Global.getSector().getPlayerFaction();
2128 return getPerson().getFaction();
2129 }
2130
2132 return getName();
2133 }
2134
2135 protected boolean isSucceeded() {
2136 return successStages.contains(currentStage);
2137 }
2138 protected boolean isFailed() {
2139 return failStages.contains(currentStage);
2140 }
2141 protected boolean isAbandoned() {
2142 return abandonStage == currentStage;
2143 }
2144
2145 public String getIcon() {
2146 if (iconName != null) return iconName;
2147 return getPerson().getPortraitSprite();
2148 }
2149
2150 @Override
2151 public String getImportantIcon() {
2152 if (!isEnding() && !isEnded()) {
2153 return Global.getSettings().getSpriteName("intel", "important_accepted_mission");
2154 }
2155 return super.getImportantIcon();
2156 }
2157
2158 protected void addResultBulletsAssumingAlreadyIndented(TooltipMakerAPI info, ListInfoMode mode) {
2159 if (result == null) return;
2160 if (mode == ListInfoMode.INTEL) return; // don't show result stuff when it's in the intel list or in a textPanel
2161
2162 Color h = Misc.getHighlightColor();
2163 Color tc = getBulletColorForMode(mode);
2164 PersonAPI person = getPerson();
2165 FactionAPI faction = getFactionForUIColors();
2166 boolean isUpdate = getListInfoParam() != null;
2167 float initPad = 3f;
2168 if (mode == ListInfoMode.IN_DESC) initPad = 10f;
2169
2170 if (result.reward > 0) {
2171 info.addPara("%s received", initPad, tc, h, Misc.getDGSCredits(result.reward));
2172 initPad = 0f;
2173 }
2174
2175 if (result.repPerson != null) {
2176 CoreReputationPlugin.addAdjustmentMessage(result.repPerson.delta, null, person,
2177 null, info, tc, isUpdate, initPad);
2178 initPad = 0f;
2179 }
2180 if (result.repFaction != null) {
2181 CoreReputationPlugin.addAdjustmentMessage(result.repFaction.delta, faction, null,
2182 null, info, tc, isUpdate, initPad);
2183 initPad = 0f;
2184 }
2185 }
2186
2187 public static String NEXT_STEP_UPDATE = "next_step_update";
2188 public static String END_MISSION_UPDATE = "end_mission_update";
2189 public void sendUpdateForNextStep(String listInfoParam, TextPanelAPI textPanel) {
2190 if (textPanel == null) {
2191 sendUpdateIfPlayerHasIntel(listInfoParam, false);
2192 } else {
2193 this.listInfoParam = listInfoParam;
2194 Global.getSector().getIntelManager().addIntelToTextPanel(this, textPanel);
2195 this.listInfoParam = null;
2196 }
2197 }
2198
2199 public void sendUpdateToTextPanel(String listInfoParam, TextPanelAPI textPanel) {
2200 this.listInfoParam = listInfoParam;
2201 Global.getSector().getIntelManager().addIntelToTextPanel(this, textPanel);
2202 this.listInfoParam = null;
2203 }
2204
2205 protected void addBulletPointsPre(TooltipMakerAPI info, Color tc, float initPad, ListInfoMode mode) {
2206
2207 }
2208 protected void addBulletPointsPost(TooltipMakerAPI info, Color tc, float initPad, ListInfoMode mode) {
2209
2210 }
2211
2212 protected String getToCompleteText() {
2213 return "to complete";
2214 }
2215
2216 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
2217
2218 Color h = Misc.getHighlightColor();
2219 Color g = Misc.getGrayColor();
2220 float pad = 3f;
2221 float opad = 10f;
2222
2223 float initPad = pad;
2224 if (mode == ListInfoMode.IN_DESC) initPad = opad;
2225
2226 Color tc = getBulletColorForMode(mode);
2227
2228 bullet(info);
2229
2230 addBulletPointsPre(info, tc, initPad, mode);
2231
2232 boolean isUpdate = getListInfoParam() != null;
2233
2234 PersonAPI person = getPerson();
2235 FactionAPI faction = getFactionForUIColors();
2236
2237 if (isUpdate) {
2238 // Possible updates: failed, completed, next step
2239 if (getListInfoParam() == NEXT_STEP_UPDATE) {
2240 if (addNextStepText(info, tc, initPad)) {
2241 initPad = 0f;
2242 }
2243 } else if (isFailed()) {
2245 addNextStepText(info, tc, initPad);
2246 } else if (isSucceeded()) {
2248 addNextStepText(info, tc, initPad);
2249 } else {
2250 addNextStepText(info, tc, initPad);
2251 }
2252 } else {
2253 // either in small description, or in tooltip/intel list
2254 if (result != null) {
2255 if (mode == ListInfoMode.IN_DESC) {
2257 }
2258 } else {
2259 if (mode == ListInfoMode.IN_DESC) {
2260// if (addNextStepText(info, tc, initPad)) {
2261// initPad = 0f;
2262// }
2263
2264 int reward = getCreditsReward();
2265 if (reward > 0) {
2266 info.addPara("%s reward", initPad, tc, h, Misc.getDGSCredits(reward));
2267 initPad = 0f;
2268 }
2269 if (timeLimit != null) {
2270 addDays(info, getToCompleteText(), timeLimit.days - elapsed, tc, initPad);
2271 initPad = 0f;
2272 }
2273 } else {
2274 if (addNextStepText(info, tc, initPad)) {
2275 initPad = 0f;
2276 }
2277// int reward = getCreditsReward();
2278// if (reward > 0) {
2279// info.addPara("%s reward", initPad, tc, h, Misc.getDGSCredits(reward));
2280// initPad = 0f;
2281// }
2282 if (timeLimit != null) {
2283 addDays(info, getToCompleteText(), timeLimit.days - elapsed, tc, initPad);
2284 initPad = 0f;
2285 }
2286 }
2287 }
2288 }
2289
2290 addBulletPointsPost(info, tc, initPad, mode);
2291
2292 unindent(info);
2293
2294 }
2295
2296 @Override
2297 public IntelSortTier getSortTier() {
2298 if (sortTier == null || isEnding() || isEnded()) return super.getSortTier();
2299 return sortTier;
2300 }
2301
2302 protected Boolean largeTitleFont;
2304 largeTitleFont = true;
2305 sortTier = IntelSortTier.TIER_2;
2306 }
2307
2308 @Override
2309 public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
2310 Color c = getTitleColor(mode);
2311 boolean large = largeTitleFont != null && largeTitleFont;
2312 if (large) info.setParaSmallInsignia();
2313 info.addPara(getName(), c, 0f);
2314 if (large) info.setParaFontDefault();
2315
2316 addBulletPoints(info, mode);
2317 }
2318
2319 @Override
2320 public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
2321 Color h = Misc.getHighlightColor();
2322 Color g = Misc.getGrayColor();
2323 float pad = 3f;
2324 float opad = 10f;
2325
2326 FactionAPI faction = getFactionForUIColors();
2327 PersonAPI person = getPerson();
2328
2329 if (person != null) {
2330 info.addImages(width, 128, opad, opad, person.getPortraitSprite(), faction.getCrest());
2331
2332 String post = "one";
2333 if (person.getPost() != null) post = person.getPost().toLowerCase();
2334 if (post == null && person.getRank() != null) post = person.getRank().toLowerCase();
2335 info.addPara(Misc.ucFirst(getMissionTypeNoun()) + " given by " + post + " " + person.getNameString() + ", affiliated with " +
2336 faction.getDisplayNameWithArticle() + ".",
2337 opad, faction.getBaseUIColor(), faction.getDisplayNameWithArticleWithoutArticle());
2338 }
2339// info.addPara("Given by: " + person.getNameString() + ", " +
2340// faction.getDisplayName() + "-affiliated.",
2341// opad, faction.getBaseUIColor(), faction.getDisplayName());
2342
2343 addDescriptionForCurrentStage(info, width, height);
2344
2345 addBulletPoints(info, ListInfoMode.IN_DESC);
2346
2347 if (abandonStage != null && !isAbandoned() && !isSucceeded() && !isFailed()) {
2348 addAbandonButton(info, width);
2349 }
2350 }
2351
2352
2353
2354
2355
2356
2357 public void setAbandonStage(Object abandonStage) {
2358 this.abandonStage = abandonStage;
2359 }
2360 public void setNoAbandon() {
2361 this.abandonStage = null;
2362 }
2363
2364 @Override
2365 public boolean doesButtonHaveConfirmDialog(Object buttonId) {
2366 if (buttonId == BUTTON_ABANDON) {
2367 return true;
2368 }
2369 return super.doesButtonHaveConfirmDialog(buttonId);
2370 }
2371
2372 protected void addAbandonButton(TooltipMakerAPI info, float width) {
2373 addAbandonButton(info, width, "Abandon");
2374 }
2375 protected void addAbandonButton(TooltipMakerAPI info, float width, String abandon) {
2376 float opad = 10f;
2377 ButtonAPI button = info.addButton(abandon, BUTTON_ABANDON,
2378 getFactionForUIColors().getBaseUIColor(), getFactionForUIColors().getDarkUIColor(),
2379 (int)(width), 20f, opad * 2f);
2380 button.setShortcut(Keyboard.KEY_U, true);
2381 }
2382
2383 public boolean canAbandonWithoutPenalty() {
2385 }
2386
2387 protected float getNoPenaltyAbandonDays() {
2388 return 1f;
2389 }
2390
2391 @Override
2392 public void buttonPressConfirmed(Object buttonId, IntelUIAPI ui) {
2393 if (buttonId == BUTTON_ABANDON) {
2394 setImportant(false);
2395
2396 setCurrentStage(abandonStage, null, null);
2397 //endImmediately();
2398 runTriggers();
2399 }
2400 super.buttonPressConfirmed(buttonId, ui);
2401 }
2402
2403
2404 @Override
2405 public void createConfirmationPrompt(Object buttonId, TooltipMakerAPI prompt) {
2406 FactionAPI faction = getFactionForUIColors();
2407
2408 if (buttonId == BUTTON_ABANDON) {
2409 boolean loseRepFaction = getRepPenaltyFailureFaction() > 0;
2410 boolean loseRepPerson = getRepPenaltyFailurePerson() > 0;
2411 if (!loseRepFaction && !loseRepPerson) {
2412 prompt.addPara("You can abandon this " + getMissionTypeNoun() + " without a penalty.", 0f);
2413 } else if (canAbandonWithoutPenalty()) {
2414 prompt.addPara("It's been less than a day, and you can still abandon this " + getMissionTypeNoun() + " without a penalty.", 0f);
2415 } else {
2416 if (loseRepFaction && !loseRepPerson) {
2417 prompt.addPara("You can abandon this " + getMissionTypeNoun() + ", but will suffer " +
2418 "a reputation penalty with " + faction.getDisplayNameWithArticle() + ".", 0f,
2419 Misc.getTextColor(), faction.getBaseUIColor(), faction.getDisplayNameWithArticleWithoutArticle());
2420 } else if (!loseRepFaction && loseRepPerson) {
2421 prompt.addPara("You can abandon this " + getMissionTypeNoun() + ", but will suffer " +
2422 "a reputation penalty with " + getPerson().getNameString() + ".",
2423 Misc.getTextColor(), 0f);
2424 } else {
2425 prompt.addPara("You can abandon this " + getMissionTypeNoun() + ", but will suffer " +
2426 "a reputation penalty with both " + getPerson().getNameString() + " and " +
2427 faction.getDisplayNameWithArticle() + ".", 0f,
2428 Misc.getTextColor(), faction.getBaseUIColor(), faction.getDisplayNameWithArticleWithoutArticle());
2429 }
2430 }
2431 } else {
2432 super.createConfirmationPrompt(buttonId, prompt);
2433 }
2434 }
2435
2436 protected String getMissionTypeNoun() {
2437 return "mission";
2438 }
2439
2440 protected String getMissionCompletionVerb() {
2441 return "completed";
2442 }
2443
2444 public int getDistanceLY(MarketAPI market) {
2445 return getDistanceLY(market.getPrimaryEntity());
2446 }
2447
2448 public int getDistanceLY(SectorEntityToken entity) {
2449 int dist = 0;
2450 if (getPerson() != null && getPerson().getMarket() != null) {
2451 dist = (int) Math.round(Misc.getDistanceLY(getPerson().getMarket().getLocationInHyperspace(), entity.getLocationInHyperspace()));
2452 }
2453 return dist;
2454 }
2455
2456 public int getDistanceLY(StarSystemAPI system) {
2457 int dist = 0;
2458 if (getPerson() != null && getPerson().getMarket() != null) {
2459 dist = (int) Math.round(Misc.getDistanceLY(getPerson().getMarket().getLocationInHyperspace(), system.getLocation()));
2460 }
2461 return dist;
2462 }
2463
2464 public int getFuel(SectorEntityToken entity, boolean bothWays) {
2465 int dist = getDistanceLY(entity);
2466
2467 float fuel = Global.getSector().getPlayerFleet().getLogistics().getFuelCostPerLightYear();
2468 fuel *= dist;
2469 if (bothWays) fuel *= 2f;
2470 return (int) Math.round(fuel);
2471 }
2472
2473 public Object pickOneObject(List options) {
2474 WeightedRandomPicker<Object> picker = new WeightedRandomPicker<Object>(genRandom);
2475 for (Object option : options) {
2476 picker.add(option);
2477 }
2478 return picker.pick();
2479 }
2480
2481 public String pickOne(List<String> options) {
2482 return pickOne(options.toArray(new String[0]));
2483 }
2484 public String pickOne(String ... options) {
2485 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(genRandom);
2486 for (String option : options) {
2487 picker.add(option);
2488 }
2489 return picker.pick();
2490 }
2491
2492 protected String getWithoutArticle(String item) {
2493 if (item.startsWith("a ")) {
2494 return item.replaceFirst("a ", "");
2495 }
2496 if (item.startsWith("an ")) {
2497 return item.replaceFirst("an ", "");
2498 }
2499 if (item.startsWith("the ")) {
2500 return item.replaceFirst("the ", "");
2501 }
2502 return item;
2503 }
2504
2505 public void setStageOnGlobalFlag(Object to, String flag) {
2506 connectWithGlobalFlag(null, to, flag);
2507 }
2508 public void setStageOnEntityNotAlive(Object to, SectorEntityToken entity) {
2509 connectWithEntityNotAlive(null, to, entity);
2510 }
2511 public void setStageOnDaysElapsed(Object to, float days) {
2512 connectWithDaysElapsed(null, to, days);
2513 }
2514 public void setStageOnInRangeOfCommRelay(Object to) {
2516 }
2517 public void setStageOnEnteredLocation(Object to, LocationAPI location) {
2518 connectWithEnteredLocation(null, to, location);
2519 }
2520 public void setStageInRangeOfEntity(Object to, SectorEntityToken entity, float range) {
2521 connectWithInRangeOfEntity(null, to, entity, range);
2522 }
2523 public void setStageOnWithinHyperspaceRange(Object to, SectorEntityToken entity, float rangeLY) {
2524 connectWithWithinHyperspaceRange(null, to, entity, rangeLY);
2525 }
2526 public void setStageOnCustomCondition(Object to, ConditionChecker custom) {
2527 connections.add(new StageConnection(null, to, custom));
2528 }
2529
2530 public void connectWithGlobalFlag(Object from, Object to, String flag) {
2531 connections.add(new StageConnection(from, to, new GlobalBooleanChecker(flag)));
2532 // so it gets auto-unset if it's ever set
2533 changes.add(new VariableSet(getGlobalMemory(), flag, true));
2534 }
2535
2536
2537 public void setStageOnMemoryFlag(Object to, HasMemory withMemory, String flag) {
2538 setStageOnMemoryFlag(to, withMemory.getMemoryWithoutUpdate(), flag);
2539 }
2540 public void connectWithMemoryFlag(Object from, Object to, HasMemory withMemory, String flag) {
2541 connectWithMemoryFlag(from, to, withMemory.getMemoryWithoutUpdate(), flag);
2542 }
2543
2544 public void setStageOnMemoryFlag(Object to, MemoryAPI memory, String flag) {
2545 connectWithMemoryFlag(null, to, memory, flag);
2546 }
2547 public void connectWithMemoryFlag(Object from, Object to, MemoryAPI memory, String flag) {
2548 connections.add(new StageConnection(from, to, new MemoryBooleanChecker(memory, flag)));
2549 // so it gets auto-unset if it's ever set
2550 changes.add(new VariableSet(memory, flag, true));
2551 }
2552
2553 public void connectWithEntityNotAlive(Object from, Object to, SectorEntityToken entity) {
2554 connections.add(new StageConnection(from, to, new EntityNotAliveChecker(entity)));
2555 }
2556
2557 public void connectWithMarketDecivilized(Object from, Object to, MarketAPI market) {
2558 connections.add(new StageConnection(from, to, new MarketDecivChecker(market)));
2559 }
2560 public void setStageOnMarketDecivilized(Object to, MarketAPI market) {
2561 connections.add(new StageConnection(null, to, new MarketDecivChecker(market)));
2562 }
2563
2564 public void connectWithHostilitiesEnded(Object from, Object to, PersonAPI person, MarketAPI market) {
2565 connections.add(new StageConnection(from, to, new HostilitiesEndedChecker(person, market)));
2566 }
2567 public void setStageOnHostilitiesEnded(Object to, PersonAPI person, MarketAPI market) {
2568 connections.add(new StageConnection(null, to, new HostilitiesEndedChecker(person, market)));
2569 }
2570 public void connectWithHostilitiesStarted(Object from, Object to, PersonAPI person, MarketAPI market) {
2571 connections.add(new StageConnection(from, to, new HostilitiesStartedChecker(person, market)));
2572 }
2573 public void setStageOnHostilitiesStarted(Object to, PersonAPI person, MarketAPI market) {
2574 connections.add(new StageConnection(null, to, new HostilitiesStartedChecker(person, market)));
2575 }
2576
2577 public void connectWithDaysElapsed(Object from, Object to, float days) {
2578 connections.add(new StageConnection(from, to, new DaysElapsedChecker(days, getData(from))));
2579 }
2580
2581 public void connectWithInRangeOfCommRelay(Object from, Object to) {
2582 connections.add(new StageConnection(from, to, new InCommRelayRangeChecker()));
2583 }
2584
2585 public void connectWithEnteredLocation(Object from, Object to, LocationAPI location) {
2586 connections.add(new StageConnection(from, to, new EnteredLocationChecker(location)));
2587 }
2588 public void connectWithInRangeOfEntity(Object from, Object to, SectorEntityToken entity, float range) {
2589 connections.add(new StageConnection(from, to, new InRangeOfEntityChecker(entity, range)));
2590 }
2591 public void connectWithWithinHyperspaceRange(Object from, Object to, SectorEntityToken entity, float rangeLY) {
2592 connectWithWithinHyperspaceRange(from, to, entity, rangeLY, false);
2593 }
2594 public void connectWithWithinHyperspaceRange(Object from, Object to, SectorEntityToken entity, float rangeLY,
2595 boolean requirePlayerInHyperspace) {
2596 connections.add(new StageConnection(from, to, new InHyperRangeOfEntityChecker(entity, rangeLY, requirePlayerInHyperspace)));
2597 }
2598
2599 public void connectWithCustomCondition(Object from, Object to, ConditionChecker custom) {
2600 connections.add(new StageConnection(from, to, custom));
2601 }
2602
2603 public boolean rollProbability(float p) {
2604 return genRandom.nextFloat() < p;
2605 }
2606
2607
2608 public SectorEntityToken spawnDebrisField(float radius, float density, LocData data) {
2609 DebrisFieldParams params = new DebrisFieldParams(
2610 radius, // field radius - should not go above 1000 for performance reasons
2611 density, // density, visual - affects number of debris pieces
2612 10000000f, // duration in days
2613 0f); // days the field will keep generating glowing pieces
2614 params.source = DebrisFieldSource.MIXED;
2615 params.baseSalvageXP = (long) radius; // base XP for scavenging in field
2616
2617 if (!data.updateLocIfNeeded(this, null)) return null;
2618
2619 SectorEntityToken debris = Misc.addDebrisField(data.system, params, genRandom);
2620 data.placeEntity(debris);
2621 changes.add(new EntityAdded(debris));
2622
2623 return debris;
2624 }
2625
2626 public SectorEntityToken spawnMissionNode(LocData data) {
2627 return spawnEntity(Entities.MISSION_LOCATION, data);
2628 }
2629
2630 public void makeMissionNodeDiscoverable(SectorEntityToken node) {
2631 makeDiscoverable(node, 1000f, 200f);
2632 }
2633 public void makeDiscoverable(SectorEntityToken entity, float range, float xp) {
2634 entity.setDiscoveryXP(xp);
2635 entity.setSensorProfile(1f);
2636 entity.setDiscoverable(true);
2637 entity.getDetectedRangeMod().modifyFlat("gen", range);
2638 }
2639
2640 public EntityLocation generateLocation(String entityId, EntityLocationType locType, SectorEntityToken param, LocationAPI system) {
2641 EntityLocation loc = null;
2642 float gap = 100f;
2643 if (system instanceof StarSystemAPI) {
2644 if (locType == EntityLocationType.HIDDEN) {
2645 loc = BaseThemeGenerator.pickHiddenLocation(genRandom, (StarSystemAPI)system, gap, null);
2646 } else if (locType == EntityLocationType.HIDDEN_NOT_NEAR_STAR) {
2647 loc = BaseThemeGenerator.pickHiddenLocationNotNearStar(genRandom, (StarSystemAPI)system, gap, null);
2648 } else if (locType == EntityLocationType.ORBITING_PLANET) {
2649 loc = BaseThemeGenerator.pickCommonLocation(genRandom, (StarSystemAPI)system, gap, false, null);
2650 } else if (locType == EntityLocationType.ORBITING_PLANET_OR_STAR) {
2651 loc = BaseThemeGenerator.pickCommonLocation(genRandom, (StarSystemAPI)system, gap, true, null);
2652 } else if (locType == EntityLocationType.UNCOMMON) {
2653 loc = BaseThemeGenerator.pickUncommonLocation(genRandom, (StarSystemAPI)system, gap, null);
2654 } else if (locType == EntityLocationType.ANY) {
2655 loc = BaseThemeGenerator.pickAnyLocation(genRandom, (StarSystemAPI)system, gap, null);
2656 }
2657 }
2658
2659 if (locType == EntityLocationType.ORBITING_PARAM) {
2660 loc = BaseThemeGenerator.createLocationAtRandomGap(genRandom, param, gap);
2661 if (loc == null) {
2662 float radius = 75f;
2663 if (entityId != null) {
2664 CustomEntitySpecAPI spec = Global.getSettings().getCustomEntitySpec(entityId);
2665 radius = spec.getDefaultRadius();
2666 }
2667 loc = new EntityLocation();
2668 loc.type = LocationType.PLANET_ORBIT;
2669 loc.orbit = Global.getFactory().createCircularOrbitWithSpin(param,
2670 genRandom.nextFloat() * 360f, param.getRadius() + radius + 100f,
2671 20f + 20f * genRandom.nextFloat(), genRandom.nextFloat() * 10f + 1f);
2672 }
2673 }
2674
2675 if (loc == null) {
2676 if (system instanceof StarSystemAPI) {
2677 loc = new EntityLocation();
2678 loc.type = LocationType.STAR_ORBIT;
2679 loc.orbit = Global.getFactory().createCircularOrbitWithSpin(((StarSystemAPI)system).getCenter(),
2680 genRandom.nextFloat() * 360f, 5000f,
2681 20f + 20f * genRandom.nextFloat(), genRandom.nextFloat() * 10f + 1f);
2682 } else {
2683 loc = new EntityLocation();
2684 loc.type = LocationType.OUTER_SYSTEM;
2685 loc.location = new Vector2f();
2686 }
2687 }
2688 return loc;
2689 }
2690
2691 public SectorEntityToken spawnEntity(String entityId, LocData data) {
2692
2693 if (!data.updateLocIfNeeded(this, entityId)) return null;
2694
2695 AddedEntity added = BaseThemeGenerator.addEntityAutoDetermineType(genRandom, data.system, data.loc, entityId, Factions.NEUTRAL);
2696 if (added == null) return null;
2697
2698 if (data.removeOnMissionOver) {
2699 added.entity.addTag(REMOVE_ON_MISSION_OVER);
2700 }
2701
2702 added.entity.addTag(Tags.NOT_RANDOM_MISSION_TARGET);
2703
2704 changes.add(new EntityAdded(added.entity));
2705 return added.entity;
2706 }
2707
2708 public SectorEntityToken spawnEntityToken(LocData data) {
2709 if (!data.updateLocIfNeeded(this, null)) return null;
2710
2711 SectorEntityToken token = data.system.createToken(0, 0);
2712 data.system.addEntity(token);
2713 data.placeEntity(token);
2714 changes.add(new EntityAdded(token));
2715
2716 return token;
2717 }
2718
2719
2720 public SectorEntityToken spawnDerelictHull(String hullId, LocData data) {
2721 if (hullId == null) {
2722 return spawnDerelictOfType((DerelictType) null, data);
2723 }
2725 return spawnDerelict(shipData, data);
2726 }
2727
2728 public SectorEntityToken spawnDerelict(String factionId, DerelictType type, LocData data) {
2729 if (factionId == null) {
2730 return spawnDerelictOfType(type, data);
2731 }
2732 DerelictShipData shipData = DerelictShipEntityPlugin.createRandom(factionId, type, genRandom, DerelictShipEntityPlugin.getDefaultSModProb());
2733 return spawnDerelict(shipData, data);
2734 }
2735 public SectorEntityToken spawnDerelictOfType(DerelictType type, LocData data) {
2736 WeightedRandomPicker<String> factions = SalvageSpecialAssigner.getNearbyFactions(genRandom, data.system.getLocation(),
2737 15f, 10f, 10f);
2738 DerelictShipData shipData = DerelictShipEntityPlugin.createRandom(factions.pick(), type, genRandom, DerelictShipEntityPlugin.getDefaultSModProb());
2739 return spawnDerelict(shipData, data);
2740 }
2741
2742 public SectorEntityToken spawnDerelict(DerelictShipData shipData, LocData data) {
2743 if (shipData == null) return null;
2744
2745 if (!data.updateLocIfNeeded(this, Entities.WRECK)) return null;
2746
2747 SectorEntityToken entity = BaseThemeGenerator.addSalvageEntity(genRandom, data.system, Entities.WRECK, Factions.NEUTRAL, shipData);
2748 entity.setDiscoverable(true);
2749 data.placeEntity(entity);
2750
2751 changes.add(new EntityAdded(entity));
2752 return entity;
2753 }
2754
2755 public void spawnShipGraveyard(String factionId, int minShips, int maxShips, LocData data) {
2756 SectorEntityToken focus = spawnEntityToken(data);
2757
2758 int numShips = minShips + genRandom.nextInt(maxShips - minShips + 1);
2759
2760 WeightedRandomPicker<Float> bands = new WeightedRandomPicker<Float>(genRandom);
2761 for (int i = 0; i < numShips + 5; i++) {
2762 bands.add(new Float(120f + i * 20f), (i + 1f) * (i + 1f));
2763 }
2764
2765 for (int i = 0; i < numShips; i++) {
2766 float r = bands.pickAndRemove();
2767
2768 EntityLocation loc = new EntityLocation();
2769 loc.type = LocationType.OUTER_SYSTEM;
2770 float orbitDays = r / (5f + genRandom.nextFloat() * 10f);
2771 loc.orbit = Global.getFactory().createCircularOrbit(focus, genRandom.nextFloat() * 360f, r, orbitDays);
2772
2773 LocData curr = new LocData(loc, data.system, data.removeOnMissionOver);
2774
2775 spawnDerelict(factionId, null, curr);
2776 }
2777 }
2778
2779
2780 protected PersonAPI findOrCreateTrader(String factionId, MarketAPI market, boolean cleanUpOnMissionOverIfWasNewPerson) {
2782 return findOrCreatePerson(factionId, market, cleanUpOnMissionOverIfWasNewPerson,
2783 Ranks.CITIZEN,
2784 Ranks.POST_MERCHANT);
2785 }
2786 return findOrCreatePerson(factionId, market, cleanUpOnMissionOverIfWasNewPerson,
2787 Ranks.CITIZEN,
2788 Ranks.POST_MERCHANT,
2789 Ranks.POST_COMMODITIES_AGENT,
2790 Ranks.POST_INVESTOR,
2791 Ranks.POST_TRADER);
2792
2793 }
2794
2795 protected PersonAPI findOrCreateCriminal(MarketAPI market, boolean cleanUpOnMissionOverIfWasNewPerson) {
2796 return findOrCreatePerson(Factions.PIRATES, market, cleanUpOnMissionOverIfWasNewPerson,
2797 Ranks.CITIZEN,
2798 Ranks.POST_GANGSTER,
2799 Ranks.POST_SMUGGLER,
2800 Ranks.POST_FENCE);
2801
2802 }
2803
2804 protected PersonAPI findOrCreateCriminalTrader(MarketAPI market, boolean cleanUpOnMissionOverIfWasNewPerson) {
2805 return findOrCreatePerson(Factions.PIRATES, market, cleanUpOnMissionOverIfWasNewPerson,
2806 Ranks.CITIZEN,
2807 Ranks.POST_SMUGGLER,
2808 Ranks.POST_FENCE);
2809
2810 }
2811
2812 protected PersonAPI findOrCreatePerson(String factionId, MarketAPI market, boolean cleanUpOnMissionOverIfWasNewPerson, String defaultRank, String ... posts) {
2813 String reason = getReason();
2814 PersonAPI person = null;
2815 ImportantPeopleAPI ip = Global.getSector().getImportantPeople();
2816
2817
2818 FactionAPI faction = null;
2819 if (market != null) faction = market.getFaction();
2820 if (factionId != null) {
2821 faction = Global.getSector().getFaction(factionId);
2822 }
2823
2824 person = ip.getPerson(genRandom, faction, market, reason, defaultRank, posts).getPerson();
2825
2826 boolean createdNewPerson = !ip.isLastGetPersonResultWasExistingPerson();
2827
2828 if (person != null && !createdNewPerson &&
2829 Misc.flagHasReason(person.getMemoryWithoutUpdate(), "$requiredForMissions", getReason())) {
2830 // this can happen if the person was already created *for this exact type of mission*
2831 // so, don't use them - they're already the target of the same mission and mission
2832 // creation would fail later anyway.
2833 // this also causes - when this mission is aborted - for that person to be removed from
2834 // their market in this failed mission's abort(), because it's requiredForMissions with the
2835 // same id as this.
2836 person = null;
2837 }
2838
2839 if (person == null) {
2840 person = faction.createRandomPerson(genRandom);
2841 WeightedRandomPicker<String> postPicker = new WeightedRandomPicker<String>(genRandom);
2842 for (String post : posts) {
2843 postPicker.add(post);
2844 }
2845 person.setPostId(postPicker.pick());
2846 person.setRankId(defaultRank);
2847 person.setMarket(market);
2848 if (market != null) market.addPerson(person);
2849 ip.addPerson(person);
2850 ip.getData(person).getLocation().setMarket(market);
2851 }
2852
2853 if (isBarEvent() || createdNewPerson) {
2854 ip.excludeFromGetPerson(person);
2855 }
2856
2857 boolean addedToComms = false;
2858 if (market != null && market.getCommDirectory().getEntryForPerson(person) == null) {
2859 market.getCommDirectory().addPerson(person);
2860 addedToComms = true;
2861 }
2862
2863 boolean willBeRemoved = false;
2864 if (createdNewPerson || addedToComms) {
2865 if (cleanUpOnMissionOverIfWasNewPerson) {
2866 person.addTag(REMOVE_ON_MISSION_OVER);
2867 }
2868 PersonAdded added = new PersonAdded(market, person, !createdNewPerson);
2869 changes.add(added);
2870 willBeRemoved = true;
2871 }
2872
2873 makePersonRequired(person);
2874 if (!willBeRemoved && person.hasTag(REMOVE_ON_MISSION_OVER)) {
2875 PersonAdded added = new PersonAdded(market, person, false);
2876 changes.add(added);
2877 }
2878
2879 person.setMarket(market);
2880
2881 return person;
2882 }
2883
2884 public void makePersonRequired(PersonAPI person) {
2885 PersonMadeRequired req = new PersonMadeRequired(person);
2886 // always add at the start so the flag is unset and the person can be deleted by the PersonAdded change
2887 changes.add(0, req);
2888 Misc.setFlagWithReason(person.getMemoryWithoutUpdate(), "$requiredForMissions", getReason(), true, -1f);
2889 }
2890
2891 protected void ensurePersonIsInCommDirectory(MarketAPI market, PersonAPI person) {
2892 boolean addedToComms = false;
2893 if (market != null && market.getCommDirectory().getEntryForPerson(person) == null) {
2894 market.getCommDirectory().addPerson(person);
2895 addedToComms = true;
2896 }
2897
2898 if (addedToComms) {
2899 PersonAdded added = new PersonAdded(market, person, true);
2900 changes.add(added);
2901 }
2902 }
2903
2904
2905 protected transient String giverFactionId;
2906 protected transient String giverRank = Ranks.CITIZEN;
2907 protected transient String giverPost = Ranks.POST_CITIZEN;
2908 protected transient String giverVoice = null;
2909 protected transient String giverPortrait;
2910 protected transient PersonImportance giverImportance = PersonImportance.MEDIUM;
2911 protected transient String [] giverTags;
2912 protected transient Gender giverGender = Gender.ANY;
2913
2914 public void setGiverVoice(String giverVoice) {
2915 this.giverVoice = giverVoice;
2916 }
2917
2918 public void setGiverFaction(String factionId) {
2919 giverFactionId = factionId;
2920 }
2921
2922 public Gender getGiverGender() {
2923 return giverGender;
2924 }
2925
2926 public void setGiverRank(String giverRank) {
2927 this.giverRank = giverRank;
2928 }
2929
2930 public void setGiverPost(String giverPost) {
2931 this.giverPost = giverPost;
2932 }
2933
2934 public void setGiverPortrait(String giverPortrait) {
2935 this.giverPortrait = giverPortrait;
2936 }
2937
2938 public void setGiverImportance(PersonImportance giverImportance) {
2939 this.giverImportance = giverImportance;
2940 }
2941
2942 public void setGiverTags(String ... giverTags) {
2943 this.giverTags = giverTags;
2944 }
2945
2946
2947 public void findOrCreateGiver(MarketAPI market, boolean addToCommDirectory, boolean cleanUpOnMissionOverIfWasNewPerson) {
2948 String factionId = giverFactionId;
2949 if (factionId == null) factionId = market.getFactionId();
2950 PersonAPI person = findOrCreatePerson(factionId, market, cleanUpOnMissionOverIfWasNewPerson, giverRank, giverPost);
2951
2952 ImportantPeopleAPI ip = Global.getSector().getImportantPeople();
2953 boolean createdNewPerson = !ip.isLastGetPersonResultWasExistingPerson();
2954
2955 if (person != null) {
2956 if (createdNewPerson) {
2957 person.setRankId(giverRank);
2958 person.setPostId(giverPost);
2959 person.setImportanceAndVoice(giverImportance, genRandom);
2960 if (giverVoice != null) {
2961 person.setVoice(giverVoice);
2962 }
2963 if (giverPortrait != null) {
2964 person.setPortraitSprite(giverPortrait);
2965 }
2966 }
2967 // add giver tags regardless of whether person was created or already existed
2968 if (giverTags != null) {
2969 for (String tag : giverTags){
2970 person.addTag(tag);
2971 }
2972 }
2973 if (createdNewPerson && !addToCommDirectory) {
2974 market.getCommDirectory().removePerson(person);
2975 }
2976 person.setMarket(market);
2977 personOverride = person;
2978 }
2979 }
2980
2981 public PersonAPI getPersonOverride() {
2982 return personOverride;
2983 }
2984
2985 public void setPersonOverride(PersonAPI personOverride) {
2986 this.personOverride = personOverride;
2987 }
2988
2989 public PersonImportance pickImportance() {
2990 WeightedRandomPicker<PersonImportance> picker = new WeightedRandomPicker<PersonImportance>(genRandom);
2991 picker.add(PersonImportance.VERY_LOW, 1f);
2992 picker.add(PersonImportance.LOW, 5f);
2993 picker.add(PersonImportance.MEDIUM, 10f);
2994 picker.add(PersonImportance.HIGH, 5f);
2995 picker.add(PersonImportance.VERY_HIGH, 1f);
2996 return picker.pick();
2997 }
2998 public PersonImportance pickMediumImportance() {
2999 WeightedRandomPicker<PersonImportance> picker = new WeightedRandomPicker<PersonImportance>(genRandom);
3000 picker.add(PersonImportance.LOW, 5f);
3001 picker.add(PersonImportance.MEDIUM, 10f);
3002 picker.add(PersonImportance.HIGH, 5f);
3003 return picker.pick();
3004 }
3005 public PersonImportance pickHighImportance() {
3006 WeightedRandomPicker<PersonImportance> picker = new WeightedRandomPicker<PersonImportance>(genRandom);
3007 picker.add(PersonImportance.MEDIUM, 10f);
3008 picker.add(PersonImportance.HIGH, 5f);
3009 picker.add(PersonImportance.VERY_HIGH, 1f);
3010 return picker.pick();
3011 }
3012 public PersonImportance pickLowImportance() {
3013 WeightedRandomPicker<PersonImportance> picker = new WeightedRandomPicker<PersonImportance>(genRandom);
3014 picker.add(PersonImportance.VERY_LOW, 10f);
3015 picker.add(PersonImportance.LOW, 5f);
3016 picker.add(PersonImportance.MEDIUM, 1f);
3017 return picker.pick();
3018 }
3019
3020 public void createGiver(MarketAPI market, boolean addToCommDirectory, boolean removeOnMissionOver) {
3021 String factionId = giverFactionId;
3022 if (factionId == null) factionId = market.getFactionId();
3023
3024 PersonAPI person = Global.getSector().getFaction(factionId).createRandomPerson(giverGender, genRandom);
3025 person.setRankId(giverRank);
3026 person.setPostId(giverPost);
3027 person.setImportanceAndVoice(giverImportance, genRandom);
3028 if (giverVoice != null) {
3029 person.setVoice(giverVoice);
3030 }
3031 if (giverPortrait != null) {
3032 person.setPortraitSprite(giverPortrait);
3033 }
3034 if (giverTags != null) {
3035 for (String tag : giverTags){
3036 person.addTag(tag);
3037 }
3038 }
3039
3040 ImportantPeopleAPI ip = Global.getSector().getImportantPeople();
3041
3042 market.addPerson(person);
3043 ip.addPerson(person);
3044 ip.getData(person).getLocation().setMarket(market);
3045
3046 if (addToCommDirectory) {
3047 market.getCommDirectory().addPerson(person);
3048 }
3049 if (removeOnMissionOver) {
3050 person.addTag(REMOVE_ON_MISSION_OVER);
3051 }
3052 PersonAdded added = new PersonAdded(market, person, false);
3053 changes.add(added);
3054
3055 makePersonRequired(person);
3056
3057 personOverride = person;
3058
3060 }
3061
3062
3064 PersonAPI person = getPerson();
3065 if (person == null) return;
3066 float rel = person.getRelToPlayer().getRel();
3067
3068 if (rel > 0) {
3069 rewardMult = 1f + rel * (Global.getSettings().getFloat("missionMaxRewardMultFromRel") - 1f);
3070 } else if (rel < 0) {
3071 rewardMult = 1f + rel * (1f - Global.getSettings().getFloat("missionMinRewardMultFromRel"));
3072 }
3073
3074 float importance = person.getImportance().getValue();
3075
3076 float min = getMinQuality();
3077 float maxRelBonus = Global.getSettings().getFloat("missionMaxPossibleQualityAboveImportance");
3078
3079 quality = Math.min(Math.max(0, rel), importance);
3080 if (rel > importance && importance < 1f) {
3081 quality += (rel - importance) / (1f - importance) * maxRelBonus;
3082 }
3083
3084 if (person.getMemoryWithoutUpdate().contains(BaseMissionHub.MISSION_QUALITY_BONUS)) {
3085 quality += person.getMemoryWithoutUpdate().getFloat(BaseMissionHub.MISSION_QUALITY_BONUS);
3086 }
3087
3088 if (quality < min) quality = min;
3089 if (quality > 1f) quality = 1f;
3090 }
3091
3092 public float getBaseQuality() {
3093 PersonAPI person = getPerson();
3094 if (person == null) return 0.5f;
3095 float importance = person.getImportance().getValue();
3096 return importance;
3097 }
3098 public float getMaxQuality() {
3099 PersonAPI person = getPerson();
3100 if (person == null) return 0f;
3101 float maxRelBonus = Global.getSettings().getFloat("missionMaxPossibleQualityAboveImportance");
3102 float importance = person.getImportance().getValue();
3103 return Math.min(1f, importance + maxRelBonus);
3104 }
3105 public float getMinQuality() {
3106 PersonAPI person = getPerson();
3107 if (person == null) return 0f;
3108 float importance = person.getImportance().getValue();
3109 float min = importance - Global.getSettings().getFloat("missionMinPossibleQualityBelowImportance");
3110 if (min < 0) min = 0;
3111 return min;
3112 }
3113
3114 public float getQuality() {
3115 return quality;
3116 }
3117
3118 public void setQuality(float quality) {
3119 this.quality = quality;
3120 }
3121
3122 public float getRewardMult() {
3123 return rewardMult;
3124 }
3125
3126 public float getRewardMultFraction() {
3127 float max = Global.getSettings().getFloat("missionMaxRewardMultFromRel");
3128 return Math.min(1f, Math.max(0f, (rewardMult - 1f) / (max - 1f)));
3129 }
3130
3131 public void setRewardMult(float rewardMult) {
3132 this.rewardMult = rewardMult;
3133 }
3134
3135 public Object getCurrentStage() {
3136 return currentStage;
3137 }
3138
3139 public void addFleetDefeatTrigger(CampaignFleetAPI fleet, String trigger, boolean permanent) {
3140 Misc.addDefeatTrigger(fleet, trigger);
3141 changes.add(new DefeatTriggerAdded(fleet, trigger, permanent));
3142 }
3143
3144 public String getLocated(SectorEntityToken entity) {
3145 return BreadcrumbSpecial.getLocatedString(entity, true);
3146 }
3147 public String getLocatedUnclear(SectorEntityToken entity) {
3148 return BreadcrumbSpecial.getLocatedString(entity, false);
3149 }
3150
3151
3153 return "Get within range of a functional comm relay to complete the mission and receive " +
3154 "your reward.";
3155 }
3156
3158 return "Get within comms range to complete the mission";
3159 }
3160
3161 public String getGoToSystemTextShort(StarSystemAPI system) {
3162 return "Go to the " + system.getNameWithLowercaseTypeShort();
3163 }
3164
3165 public String getGoToPlanetTextShort(PlanetAPI planet) {
3166 if (planet.getStarSystem() != null) {
3167 return "Go to " + planet.getName() + " in the " + planet.getStarSystem().getNameWithLowercaseTypeShort();
3168 } else {
3169 return "Go to " + planet.getName();
3170 }
3171 }
3172
3173 public String getGoToPlanetTextPre(PlanetAPI planet) {
3174 String a = planet.getSpec().getAOrAn();
3175 String world = planet.getTypeNameWithWorld().toLowerCase();
3176 if (planet.getStarSystem() != null) {
3177 return "Go to " + planet.getName() + ", " + a + " " + world + " in the " + planet.getStarSystem().getNameWithLowercaseType();
3178 } else {
3179 return "Go to " + planet.getName() + ", " + a + " " + world + " in hyperspace";
3180 }
3181 }
3182
3183 public String getGoToMarketText(MarketAPI market) {
3184 if (market.getStarSystem() != null) {
3185 return "Go to " + market.getName() + " in the " + market.getStarSystem().getNameWithLowercaseTypeShort();
3186 } else {
3187 return "Go to " + market.getName();
3188 }
3189 }
3190
3191 public String getGoTalkToPersonText(PersonAPI person) {
3192 MarketAPI market = person.getMarket();
3193 if (market != null) {
3194 return getGoToMarketText(market) + " and talk to " + person.getNameString();
3195 } else {
3196 return "Talk to " + person.getNameString();
3197 }
3198 }
3199
3200
3201 public String getReturnText(MarketAPI market) {
3202 return getReturnText(market.getName());
3203 }
3204 public String getReturnText(String locationName) {
3205 return "Return to " + locationName + " and talk to " +
3206 getPerson().getNameString() + " to receive your reward";
3207 }
3208 public String getReturnTextShort(MarketAPI market) {
3209 return getReturnTextShort(market.getName());
3210 }
3211 public String getReturnTextShort(String locationName) {
3212 return "Return to " + locationName + " and talk to " +
3213 getPerson().getNameString() + "";
3214 }
3215
3216
3217 public EntityLocation generateLocationInsideTerrain(CampaignTerrainAPI terrain) {
3218 //LocationAPI location = terrain.getContainingLocation();
3219
3220 CampaignTerrainPlugin plugin = terrain.getPlugin();
3221 boolean found = false;
3222 float orbitAngle = 0f;
3223 float orbitRadius = 0f;
3224 float orbitPeriod = 0f;
3225 SectorEntityToken orbitFocus = terrain;
3226 Vector2f forceLoc = null;
3227
3228 if (plugin instanceof BaseTiledTerrain) {
3229 BaseTiledTerrain tiles = (BaseTiledTerrain) plugin;
3230
3231 float maxRadius = plugin.getRenderRange();
3232 if (maxRadius < 100f) maxRadius = 100f;
3233 WeightedRandomPicker<Pair<Integer, Integer>> picker = new WeightedRandomPicker<Pair<Integer,Integer>>(genRandom);
3234 WeightedRandomPicker<Pair<Integer, Integer>> pickerPref = new WeightedRandomPicker<Pair<Integer,Integer>>(genRandom);
3235
3236 for (int i = 0; i < tiles.getTiles().length; i++) {
3237 for (int j = 0; j < tiles.getTiles()[0].length; j++) {
3238 if (tiles.getTiles()[i][j] >= 0) {
3239 float [] f = tiles.getTileCenter(i, j);
3240 Vector2f loc = new Vector2f(f[0], f[1]);
3241 float dist = Misc.getDistance(terrain.getLocation(), loc);
3242 float weight = (float) Math.pow(dist / maxRadius, 3);
3243 if (dist < 16000) {
3244 pickerPref.add(new Pair<Integer, Integer>(i, j), weight);
3245 } else if (pickerPref.isEmpty()) {
3246 picker.add(new Pair<Integer, Integer>(i, j), weight);
3247 }
3248 }
3249 }
3250 }
3251
3252 Pair<Integer, Integer> pick = pickerPref.pick();
3253 if (pick == null) pick = picker.pick();
3254
3255 if (pick != null) {
3256 float [] f = tiles.getTileCenter(pick.one, pick.two);
3257 Vector2f loc = new Vector2f(f[0], f[1]);
3258
3259 if (terrain.getOrbit() == null || terrain.getCircularOrbitRadius() <= 0 || terrain.getOrbitFocus() == null) {
3260 forceLoc = loc;
3261 } else {
3262 orbitFocus = terrain.getOrbitFocus();
3263 orbitAngle = Misc.getAngleInDegrees(orbitFocus.getLocation(), loc);
3264 orbitRadius = Misc.getDistance(orbitFocus.getLocation(), loc);
3265 orbitPeriod = terrain.getCircularOrbitPeriod();
3266 }
3267 found = true;
3268 }
3269
3270 } else if (plugin instanceof BaseRingTerrain) {
3271 BaseRingTerrain ring = (BaseRingTerrain) plugin;
3272 SectorEntityToken atCenter = ring.getRingParams().relatedEntity;
3273
3274 float centerRadius = 0f;
3275 if (atCenter != null) centerRadius = atCenter.getRadius();
3276 float ringMiddle = ring.getRingParams().middleRadius;
3277 float ringMin = ring.getRingParams().middleRadius - ring.getRingParams().bandWidthInEngine / 2f;
3278 float ringMax = ring.getRingParams().middleRadius + ring.getRingParams().bandWidthInEngine / 2f;
3279
3280 float min = Math.max(centerRadius, ringMin);
3281 orbitRadius = min + (ringMax - min) * (0.1f + 0.8f * genRandom.nextFloat());
3282 orbitAngle = genRandom.nextFloat() * 360f;
3283 found = true;
3284 }
3285
3286 if (!found) {
3287 orbitRadius = 100f + 100f * genRandom.nextFloat();
3288 orbitAngle = 360f * genRandom.nextFloat();
3289 }
3290
3291 EntityLocation eLoc = new EntityLocation();
3292 eLoc.type = LocationType.OUTER_SYSTEM;
3293 if (forceLoc != null) {
3294 eLoc.location = forceLoc;
3295 } else {
3296 if (orbitPeriod <= 0f) {
3297 orbitPeriod = orbitRadius / (5f + 5f * genRandom.nextFloat());
3298 }
3299 eLoc.orbit = Global.getFactory().createCircularOrbit(orbitFocus,
3300 orbitAngle, orbitRadius, orbitPeriod);
3301 }
3302
3303 return eLoc;
3304 }
3305
3306 public static String getTerrainName(CampaignTerrainAPI terrain) {
3307 String name = terrain.getPlugin().getTerrainName();
3308 if (name == null) name = "";
3309 if (name.contains(" L4") || name.contains(" L5")) {
3310 name = getTerrainType(terrain);
3311 }
3312 return name;
3313 }
3314 public static boolean hasSpecialName(CampaignTerrainAPI terrain) {
3315 return !getTerrainName(terrain).toLowerCase().equals(getTerrainType(terrain).toLowerCase());
3316 }
3317 public static String getTerrainNameAOrAn(CampaignTerrainAPI terrain) {
3318 String name = getTerrainName(terrain);
3319 if (name != null) {
3320 return Misc.getAOrAnFor(name);
3321 } else {
3322 return terrain.getPlugin().getNameAOrAn();
3323 }
3324 }
3325 public static String getTerrainTypeAOrAn(CampaignTerrainAPI terrain) {
3326 String type = getTerrainType(terrain);
3327 if (type != null) {
3328 return Misc.getAOrAnFor(type);
3329 } else {
3330 return terrain.getPlugin().getNameAOrAn();
3331 }
3332 }
3333 public static String getTerrainType(CampaignTerrainAPI terrain) {
3334 return terrain.getPlugin().getNameForTooltip().toLowerCase();
3335 }
3336
3337
3338// public void addGetWithinCommsRangeText(TooltipMakerAPI info, float pad) {
3339// info.addPara("Get within range of a functional comm relay to complete the mission and receive " +
3340// "your reward.", pad);
3341// }
3342// public void addGetWithinCommsRangeTextShort(TooltipMakerAPI info, Color tc, float pad) {
3343// info.addPara("Get within comms range to complete the mission", tc, pad);
3344// }
3345//
3346// public void addGoToSystemTextShort(StarSystemAPI system, TooltipMakerAPI info, Color tc, float pad) {
3347// info.addPara("Go to the " + system.getNameWithLowercaseTypeShort() + "", tc, pad);
3348// }
3349//
3350// public void addGoToPlanetTextShort(PlanetAPI planet, TooltipMakerAPI info, Color tc, float pad) {
3351// if (planet.getStarSystem() != null) {
3352// info.addPara("Go to " + planet.getName() + " in the " + planet.getStarSystem().getNameWithLowercaseTypeShort(), tc, pad);
3353// } else {
3354// info.addPara("Go to " + planet.getName() + " in hyperspace", tc, pad);
3355// }
3356// }
3357
3358 public static float getUnits(float lightYears) {
3359 return lightYears * Misc.getUnitsPerLightYear();
3360 }
3361
3362 public static boolean playerHasEnough(String comId, int quantity) {
3363 return Global.getSector().getPlayerFleet().getCargo().getCommodityQuantity(comId) >= quantity;
3364 }
3365
3366 public void assignShipName(FleetMemberAPI member, String factionId) {
3367 CampaignFleetAPI fleet = Global.getFactory().createEmptyFleet(factionId, null, true);
3368 fleet.getFleetData().setShipNameRandom(genRandom);
3369 fleet.getFleetData().addFleetMember(member);
3370 fleet.getFleetData().removeFleetMember(member);
3371 }
3372
3373 public String getDayOrDays(float days) {
3374 int d = (int) Math.round(days);
3375 String daysStr = "days";
3376 if (d == 1) {
3377 daysStr = "day";
3378 }
3379 return daysStr;
3380 }
3381
3382// public List<String> getHighRankingMilitaryPosts(MarketAPI market) {
3383// List<String> posts = new ArrayList<String>();
3384// if (Misc.isMilitary(market)) {
3385// posts.add(Ranks.POST_BASE_COMMANDER);
3386// }
3387// if (Misc.hasOrbitalStation(market)) {
3388// posts.add(Ranks.POST_STATION_COMMANDER);
3389// }
3390// if (posts.isEmpty()) {
3391// posts.add(Ranks.POST_GENERIC_MILITARY);
3392// }
3393// return posts;
3394// }
3395
3396 public List<Abortable> getChanges() {
3397 return changes;
3398 }
3399
3400 public Random getGenRandom() {
3401 return genRandom;
3402 }
3403
3404 public void addOnAcceptCommodity(String commodityId, int quantity) {
3405 cargoOnAccept.addCommodity(commodityId, quantity);
3406 }
3407 public void addOnAcceptWeaponDrop(final String weaponId, final int quantity) {
3408 cargoOnAccept.addWeapons(weaponId, quantity);
3409 }
3410 public void addOnAcceptFighterLPCDrop(final String wingId, final int quantity) {
3411 cargoOnAccept.addFighters(wingId, quantity);
3412 }
3413 public void addOnAcceptHullmodDrop(final String hullmodId) {
3414 cargoOnAccept.addHullmods(hullmodId, 1);
3415 }
3416 public void addOnAcceptSpecialItemDrop(final String itemId, final String data) {
3417 cargoOnAccept.addSpecial(new SpecialItemData(itemId, data), 1);
3418 }
3419
3420 public void addOnSuccessCommodity(String commodityId, int quantity) {
3422 cargoOnSuccess.addCommodity(commodityId, quantity);
3423 }
3424 public void addOnSuccessWeaponDrop(final String weaponId, final int quantity) {
3426 cargoOnSuccess.addWeapons(weaponId, quantity);
3427 }
3428 public void addOnSuccessFighterLPCDrop(final String wingId, final int quantity) {
3430 cargoOnSuccess.addFighters(wingId, quantity);
3431 }
3432 public void addOnSuccessHullmodDrop(final String hullmodId) {
3434 cargoOnSuccess.addHullmods(hullmodId, 1);
3435 }
3436 public void addOnSuccessSpecialItemDrop(final String itemId, final String data) {
3438 cargoOnSuccess.addSpecial(new SpecialItemData(itemId, data), 1);
3439 }
3440
3441 public int getMarinesRequiredToDisrupt(MarketAPI market, Industry industry, int daysRequired) {
3442 int daysPerToken = MarketCMD.getDisruptDaysPerToken(market, industry);
3443 daysRequired -= (int) industry.getDisruptedDays();
3444 int tokens = (int) Math.ceil((float) daysRequired / (float) daysPerToken);
3445 if (tokens < 1) tokens = 1;
3446
3447 int marinesRequired = MarketCMD.getMarinesFor(market, tokens);
3448 marinesRequired = getAdjustedMarinesRequired(marinesRequired);
3449 return marinesRequired;
3450 }
3451
3452 public void addDisruptRaidInfo(MarketAPI market, Industry industry, int daysRequired, TooltipMakerAPI info, float pad) {
3453 int marinesRequired = getMarinesRequiredToDisrupt(market, industry, daysRequired);
3454
3455 RaidDangerLevel danger = industry.getSpec().getDisruptDanger();
3456
3457 Color h = Misc.getHighlightColor();
3458 LabelAPI label = info.addPara(industry.getCurrentName() + " must be disrupted for at least %s days. The operation " +
3459 "will require around %s marines, and the " +
3460 "danger level is %s.",
3461 pad, h,
3462 "" + daysRequired,
3463 Misc.getWithDGS(marinesRequired),
3464 danger.name.toLowerCase());
3465 label.setHighlightColors(h, h, danger.color);
3466 }
3467
3468 public int getMarinesRequiredForCustomObjective(MarketAPI market, RaidDangerLevel danger) {
3469 int marinesRequired = MarketCMD.getMarinesFor(market, Math.max(1, danger.marineTokens));
3470 marinesRequired = getAdjustedMarinesRequired(marinesRequired);
3471 return marinesRequired;
3472 }
3473
3474 public int getMarinesRequiredForCustomDefenderStrength(int defenderStrength, RaidDangerLevel danger) {
3475 int marinesRequired = MarketCMD.getMarinesFor(defenderStrength, Math.max(1, danger.marineTokens));
3476 marinesRequired = getAdjustedMarinesRequired(marinesRequired);
3477 return marinesRequired;
3478 }
3479
3480 public void addCustomRaidInfo(MarketAPI market, RaidDangerLevel danger, TooltipMakerAPI info, float pad) {
3481 int marinesRequired = getMarinesRequiredForCustomObjective(market, danger);
3482
3483 Color h = Misc.getHighlightColor();
3484 LabelAPI label = info.addPara("The operation " +
3485 "will require around %s marines, and the " +
3486 "danger level is %s.",
3487 pad, h,
3488 Misc.getWithDGS(marinesRequired),
3489 danger.name.toLowerCase());
3490 label.setHighlightColors(h, danger.color);
3491 }
3492
3493 public void addCustomRaidInfo(int defenderStrength, RaidDangerLevel danger, TooltipMakerAPI info, float pad) {
3494 int marinesRequired = MarketCMD.getMarinesFor(defenderStrength, Math.max(1, danger.marineTokens));
3495 marinesRequired = getAdjustedMarinesRequired(marinesRequired);
3496
3497 Color h = Misc.getHighlightColor();
3498 LabelAPI label = info.addPara("The operation " +
3499 "will require around %s marines, and the " +
3500 "danger level is %s.",
3501 pad, h,
3502 Misc.getWithDGS(marinesRequired),
3503 danger.name.toLowerCase());
3504 label.setHighlightColors(h, danger.color);
3505 }
3506
3507 public static int getAdjustedMarinesRequired(int marinesRequired) {
3508 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
3509 float support = Misc.getFleetwideTotalMod(playerFleet, Stats.FLEET_GROUND_SUPPORT, 0f);
3510 StatBonus stat = playerFleet.getStats().getDynamic().getMod(Stats.PLANETARY_OPERATIONS_MOD);
3511
3512
3513 int min = 0;
3514 int max = 0;
3515 for (int i = 1; i < marinesRequired * 2; i *= 2) {
3516 float currSupport = (int) Math.round(Math.min(support, i));
3517 float strength = i + currSupport;
3518 strength = stat.computeEffective(strength);
3519 if (strength >= marinesRequired) {
3520 min = i / 2;
3521 max = i;
3522 break;
3523 }
3524 }
3525 if (max > 0) {
3526 int iter = Math.max(1, (max - min) / 100);
3527
3528 for (int i = min; i <= max; i += iter) {
3529 float currSupport = (int) Math.min(support, i);
3530 float strength = i + currSupport;
3531 strength = stat.computeEffective(strength);
3532 if (strength >= marinesRequired) {
3533 marinesRequired = (int) Math.round(strength);
3534 break;
3535 }
3536 }
3537 }
3538
3539 //if (true) return marinesRequired;
3540
3541 int base = 10;
3542 if (marinesRequired > 100) base = 50;
3543 if (marinesRequired > 500) base = 100;
3544 if (marinesRequired > 1000) base = 250;
3545 if (marinesRequired > 2000) base = 500;
3546 if (marinesRequired > 5000) base = 1000;
3547 for (int i = 0; i < 10; i++) {
3548 if (marinesRequired <= (i + 1) * base) {
3549 marinesRequired = (i + 1) * base;
3550 break;
3551 }
3552 }
3553 marinesRequired = getRoundNumber(marinesRequired);
3554 return marinesRequired;
3555 }
3556
3557
3558 public static void addStandardMarketDesc(String prefix, MarketAPI market, TooltipMakerAPI info, float pad) {
3559 Color h = Misc.getHighlightColor();
3560 FactionAPI f = market.getFaction();
3561
3562 if (Misc.isHiddenBase(market)) {
3563 String a = f.getPersonNamePrefixAOrAn();
3564 if (prefix == null || prefix.isEmpty()) {
3565 if (market.isInHyperspace()) {
3566 LabelAPI label = info.addPara(market.getName() + "is " + a + " " + f.getPersonNamePrefix() +
3567 " base located in hyperspace.",
3568 pad);
3569 label.setHighlight(market.getName(), f.getPersonNamePrefix());
3570 label.setHighlightColors(f.getBaseUIColor(), f.getBaseUIColor());
3571 } else {
3572 LabelAPI label = info.addPara(market.getName() + "is " + a + " " + f.getPersonNamePrefix() +
3573 " base in the " + market.getStarSystem().getNameWithLowercaseTypeShort() + ".",
3574 pad);
3575 label.setHighlight(market.getName(), f.getPersonNamePrefix());
3576 label.setHighlightColors(f.getBaseUIColor(), f.getBaseUIColor());
3577 }
3578 } else {
3579 if (market.isInHyperspace()) {
3580 LabelAPI label = info.addPara(prefix + " " + market.getName() + ", " + a + " " + f.getPersonNamePrefix() +
3581 " base located in hyperspace.",
3582 pad);
3583 label.setHighlight(market.getName(), f.getDisplayNameWithArticleWithoutArticle());
3584 label.setHighlightColors(f.getBaseUIColor(), f.getBaseUIColor());
3585 } else {
3586 LabelAPI label = info.addPara(prefix + " " + market.getName() + ", " + a + " " + f.getPersonNamePrefix() +
3587 " base in the " + market.getStarSystem().getNameWithLowercaseTypeShort() + ".",
3588 pad);
3589 label.setHighlight(market.getName(), f.getPersonNamePrefix());
3590 label.setHighlightColors(f.getBaseUIColor(), f.getBaseUIColor());
3591 }
3592 }
3593
3594
3595 return;
3596 }
3597
3598 if (prefix == null || prefix.isEmpty()) {
3599 if (market.isInHyperspace()) {
3600 LabelAPI label = info.addPara(market.getName() + "is a size %s " +
3601 "colony in hyperspace controlled by " + f.getDisplayNameWithArticle() + ".",
3602 pad, f.getBaseUIColor(),
3603 "" + market.getSize(), f.getDisplayNameWithArticleWithoutArticle());
3604 label.setHighlight(market.getName(), "" + market.getSize(), f.getDisplayNameWithArticleWithoutArticle());
3605 label.setHighlightColors(f.getBaseUIColor(), h, f.getBaseUIColor());
3606 } else {
3607 LabelAPI label = info.addPara(market.getName() + "is a size %s " +
3608 "colony in the " + market.getStarSystem().getNameWithLowercaseTypeShort() + " controlled by " + f.getDisplayNameWithArticle() + ".",
3609 pad, f.getBaseUIColor(),
3610 "" + market.getSize(), f.getDisplayNameWithArticleWithoutArticle());
3611 label.setHighlight(market.getName(), "" + market.getSize(), f.getDisplayNameWithArticleWithoutArticle());
3612 label.setHighlightColors(f.getBaseUIColor(), h, f.getBaseUIColor());
3613 }
3614 } else {
3615 if (market.isInHyperspace()) {
3616 LabelAPI label = info.addPara(prefix + " " + market.getName() + ", a size %s " +
3617 "colony in hyperspace controlled by " + f.getDisplayNameWithArticle() + ".",
3618 pad, f.getBaseUIColor(),
3619 "" + market.getSize(), f.getDisplayNameWithArticleWithoutArticle());
3620 label.setHighlight(market.getName(), "" + market.getSize(), f.getDisplayNameWithArticleWithoutArticle());
3621 label.setHighlightColors(f.getBaseUIColor(), h, f.getBaseUIColor());
3622 } else {
3623 LabelAPI label = info.addPara(prefix + " " + market.getName() + ", a size %s " +
3624 "colony in the " + market.getStarSystem().getNameWithLowercaseTypeShort() + " controlled by " + f.getDisplayNameWithArticle() + ".",
3625 pad, f.getBaseUIColor(),
3626 "" + market.getSize(), f.getDisplayNameWithArticleWithoutArticle());
3627 label.setHighlight(market.getName(), "" + market.getSize(), f.getDisplayNameWithArticleWithoutArticle());
3628 label.setHighlightColors(f.getBaseUIColor(), h, f.getBaseUIColor());
3629 }
3630 }
3631// label.setHighlight("" + market.getSize(), f.getDisplayNameWithArticleWithoutArticle());
3632// label.setHighlightColors(h, f.getBaseUIColor());
3633 }
3634
3635 public int getBombardmentFuel(MarketAPI market) {
3636 int fuel = MarketCMD.getBombardmentCost(market, Global.getSector().getPlayerFleet());
3637 fuel = getRoundNumber(fuel);
3638 return fuel;
3639 }
3640
3641 public void addBombardmentInfo(MarketAPI market, TooltipMakerAPI info, float pad) {
3642 int fuel = getBombardmentFuel(market);
3643
3644 Color h = Misc.getHighlightColor();
3645 info.addPara("Effectively bombarding the target will require approximately %s units of fuel.",
3646 pad, h,
3647 Misc.getWithDGS(fuel));
3648 }
3649
3650 public void addSpecialItemDropOnlyUseInAcceptImplNotUndoneOnAbort(SectorEntityToken entity, SpecialItemData data) {
3651 CargoAPI cargo = Global.getFactory().createCargo(true);
3652 cargo.addSpecial(data, 1);
3653 BaseSalvageSpecial.addExtraSalvage(entity, cargo);
3654 }
3655
3656
3657 public PersonAPI getImportantPerson(String id) {
3658 return Global.getSector().getImportantPeople().getData(id).getPerson();
3659 }
3660 public PersonDataAPI getImportantPersonData(String id) {
3661 return Global.getSector().getImportantPeople().getData(id);
3662 }
3663
3664 public void setMemoryValuePermanent(HasMemory withMemory, String key, Object value) {
3665 withMemory.getMemoryWithoutUpdate().set(key, value);
3666 }
3667
3668 protected String completedKey = null;
3669 public void setStoryMission() {
3670 setNoAbandon();
3671 addTag(Tags.INTEL_STORY);
3673 //setCompletedKey();
3674 }
3675
3676 public void setCompletedKey() {
3677 completedKey = "$" + getMissionId() + "_missionCompleted";
3678 }
3679
3680 public boolean isOkToOfferMissionRequiringMarines(int marines) {
3681 PlaythroughLog log = PlaythroughLog.getInstance();
3682 long crew = log.getPrevValue("crew");
3683 long credits = log.getPrevValue("credits");
3684 return crew > marines * 2 || credits > marines * 400;
3685 }
3686
3687 public Object getStartingStage() {
3688 return startingStage;
3689 }
3690
3691
3692 public PersonAPI getPersonAtMarketPost(MarketAPI market, String ... postIds) {
3693 for (String postId : postIds) {
3694 for (PersonAPI person : market.getPeopleCopy()) {
3695 if (postId.equals(person.getPostId())) {
3696 return person;
3697 }
3698 }
3699 }
3700 return null;
3701 }
3702
3703 public MarketAPI getMarket(String id) {
3704 return Global.getSector().getEconomy().getMarket(id);
3705 }
3706
3707 protected Color mapMarkerNameColor = null;
3708 public void setMapMarkerNameColor(Color mapMarkerColor) {
3709 this.mapMarkerNameColor = mapMarkerColor;
3710 }
3711
3712 public void setMapMarkerNameColorBasedOnStar(StarSystemAPI system) {
3713 if (system.getCenter() instanceof PlanetAPI) {
3714 Color color = Misc.setAlpha(((PlanetAPI)system.getCenter()).getSpec().getIconColor(), 255);
3715 color = Misc.setBrightness(color, 235);
3716 setMapMarkerNameColor(color);
3717 }
3718 }
3719
3720 public List<MissionTrigger> getTriggers() {
3721 return triggers;
3722 }
3723
3724
3725}
3726
3727
3728
3729
3730
3731
3732
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static SectorAPI getSector()
Definition Global.java:59
static void addAdjustmentMessage(float delta, FactionAPI faction, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad)
static DerelictShipData createRandom(String factionId, DerelictType type, Random random)
static DerelictShipData createHull(String hullId, Random random, float sModProb)
void connectWithGlobalFlag(Object from, Object to, String flag)
void addOnAcceptWeaponDrop(final String weaponId, final int quantity)
void showPersonInfo(PersonAPI person, InteractionDialogAPI dialog, boolean withFaction, boolean withRelBar)
void setTimeLimit(Object failStage, float days, StarSystemAPI noLimitWhileInSystem, Object ... noLimitAfterStages)
void makeImportantDoNotShowAsIntelMapLocation(MarketAPI market, String flag, Enum ... stages)
SectorEntityToken getMapLocationFor(SectorEntityToken entity)
boolean callEvent(String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
void connectWithMemoryFlag(Object from, Object to, HasMemory withMemory, String flag)
void setStageOnMemoryFlag(Object to, MemoryAPI memory, String flag)
void connectWithEntityNotAlive(Object from, Object to, SectorEntityToken entity)
void setStageOnHostilitiesStarted(Object to, PersonAPI person, MarketAPI market)
void setCurrentStage(Object next, InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void setStageOnCustomCondition(Object to, ConditionChecker custom)
static boolean playerHasEnough(String comId, int quantity)
void adjustRep(TextPanelAPI textPanel, HubMissionResult result, RepActions action)
void makeUnimportant(MemoryAPI memory, Object personOrEntityOrMarket)
void makeImportant(MarketAPI market, String flag, Enum ... stages)
void makeDiscoverable(SectorEntityToken entity, float range, float xp)
int getMarinesRequiredForCustomObjective(MarketAPI market, RaidDangerLevel danger)
void addOnSuccessWeaponDrop(final String weaponId, final int quantity)
void setStageOnHostilitiesEnded(Object to, PersonAPI person, MarketAPI market)
void addCustomRaidInfo(MarketAPI market, RaidDangerLevel danger, TooltipMakerAPI info, float pad)
void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode)
void makeUnimportant(SectorEntityToken entity, Enum ... stages)
SectorEntityToken spawnDerelictHull(String hullId, LocData data)
boolean addNextStepText(TooltipMakerAPI info, Color tc, float pad)
SectorEntityToken spawnDebrisField(float radius, float density, LocData data)
void setStageOnEntityNotAlive(Object to, SectorEntityToken entity)
void addOnSuccessFighterLPCDrop(final String wingId, final int quantity)
void addCustomRaidInfo(int defenderStrength, RaidDangerLevel danger, TooltipMakerAPI info, float pad)
PersonAPI findOrCreatePerson(String factionId, MarketAPI market, boolean cleanUpOnMissionOverIfWasNewPerson, String defaultRank, String ... posts)
void makeImportant(MemoryAPI memory, String flag, MapLocationType type, Object personOrEntityOrMarket, Enum ... stages)
void makeImportantDoNotShowAsIntelMapLocation(SectorEntityToken entity, String flag, Enum ... stages)
void createSmallDescription(TooltipMakerAPI info, float width, float height)
void createGiver(MarketAPI market, boolean addToCommDirectory, boolean removeOnMissionOver)
SectorEntityToken spawnDerelict(String factionId, DerelictType type, LocData data)
void connectWithCustomCondition(Object from, Object to, ConditionChecker custom)
void setFlag(PersonAPI person, String flag, boolean permanent)
SectorEntityToken spawnDerelictOfType(DerelictType type, LocData data)
void makeImportant(SectorEntityToken entity, String flag, Enum ... stages)
EntityLocation generateLocationInsideTerrain(CampaignTerrainAPI terrain)
boolean setGlobalReference(String refKey, String inProgressFlag)
PersonAPI findOrCreateTrader(String factionId, MarketAPI market, boolean cleanUpOnMissionOverIfWasNewPerson)
SectorEntityToken spawnEntity(String entityId, LocData data)
void addOnAcceptSpecialItemDrop(final String itemId, final String data)
void makeImportant(PersonAPI person, String flag, Enum ... stages)
void makeUnimportant(MemoryAPI memory, Object personOrEntityOrMarket, Enum ... stages)
void createAndAbortIfFailed(MarketAPI market, boolean barEvent)
void setFlag(MemoryAPI memory, String flag, Object value, boolean permanent, Object ... stages)
void setFlagWithReason(SectorEntityToken entity, String flag, boolean permanent)
void setStageOnMemoryFlag(Object to, HasMemory withMemory, String flag)
void makeImportantDoNotShowAsIntelMapLocation(PersonAPI person, String flag, Enum ... stages)
void sendUpdateForNextStep(String listInfoParam, TextPanelAPI textPanel)
static String getTerrainNameAOrAn(CampaignTerrainAPI terrain)
PersonAPI findOrCreateCriminal(MarketAPI market, boolean cleanUpOnMissionOverIfWasNewPerson)
void connectWithHostilitiesEnded(Object from, Object to, PersonAPI person, MarketAPI market)
void connectWithMemoryFlag(Object from, Object to, MemoryAPI memory, String flag)
SectorEntityToken spawnDerelict(DerelictShipData shipData, LocData data)
void addBulletPointsPost(TooltipMakerAPI info, Color tc, float initPad, ListInfoMode mode)
void setPersonIsPotentialContactOnSuccess(PersonAPI person, float probability)
void endFailureImpl(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void checkStageChangesAndTriggers(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void setFlag(SectorEntityToken entity, String flag, boolean permanent, Object ... stages)
void connectWithWithinHyperspaceRange(Object from, Object to, SectorEntityToken entity, float rangeLY, boolean requirePlayerInHyperspace)
void addResultBulletsAssumingAlreadyIndented(TooltipMakerAPI info, ListInfoMode mode)
EntityLocation generateLocation(String entityId, EntityLocationType locType, SectorEntityToken param, LocationAPI system)
static boolean hasSpecialName(CampaignTerrainAPI terrain)
void connectWithHostilitiesStarted(Object from, Object to, PersonAPI person, MarketAPI market)
PersonAPI getPersonAtMarketPost(MarketAPI market, String ... postIds)
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode)
void setRepChanges(float repRewardPerson, float repPenaltyPerson, float repRewardFaction, float repPenaltyFaction)
void findOrCreateGiver(MarketAPI market, boolean addToCommDirectory, boolean cleanUpOnMissionOverIfWasNewPerson)
abstract boolean create(MarketAPI createdAt, boolean barEvent)
void setCreditReward(CreditReward reward, int marketSize)
int getMarinesRequiredToDisrupt(MarketAPI market, Industry industry, int daysRequired)
void addBulletPointsPre(TooltipMakerAPI info, Color tc, float initPad, ListInfoMode mode)
SectorEntityToken getMapLocation(SectorMapAPI map, Object currentStage)
void connectWithEnteredLocation(Object from, Object to, LocationAPI location)
void addDescriptionForCurrentStage(TooltipMakerAPI info, float width, float height)
List< CampaignFleetAPI > runStageTriggersReturnFleets(Object stage)
void addSpecialItemDropOnlyUseInAcceptImplNotUndoneOnAbort(SectorEntityToken entity, SpecialItemData data)
void endSuccess(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void setGlobalFlag(String flag, Object value, Object ... stages)
int getMarinesRequiredForCustomDefenderStrength(int defenderStrength, RaidDangerLevel danger)
void addOnAcceptFighterLPCDrop(final String wingId, final int quantity)
static String getTerrainTypeAOrAn(CampaignTerrainAPI terrain)
static void addStandardMarketDesc(String prefix, MarketAPI market, TooltipMakerAPI info, float pad)
void updateInteractionData(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void createConfirmationPrompt(Object buttonId, TooltipMakerAPI prompt)
void setStageOnWithinHyperspaceRange(Object to, SectorEntityToken entity, float rangeLY)
int getFuel(SectorEntityToken entity, boolean bothWays)
void accept(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
boolean setEntityMissionRef(SectorEntityToken entity, String key)
void addDisruptRaidInfo(MarketAPI market, Industry industry, int daysRequired, TooltipMakerAPI info, float pad)
void addBombardmentInfo(MarketAPI market, TooltipMakerAPI info, float pad)
void addAbandonButton(TooltipMakerAPI info, float width, String abandon)
void addFleetDefeatTrigger(CampaignFleetAPI fleet, String trigger, boolean permanent)
void connectWithInRangeOfEntity(Object from, Object to, SectorEntityToken entity, float range)
void setStageInRangeOfEntity(Object to, SectorEntityToken entity, float range)
void setFlag(MemoryAPI memory, String flag, Object value, boolean permanent)
void assignShipName(FleetMemberAPI member, String factionId)
void setFlag(PersonAPI person, String flag, boolean permanent, Object ... stages)
void sendUpdateToTextPanel(String listInfoParam, TextPanelAPI textPanel)
void addOnSuccessSpecialItemDrop(final String itemId, final String data)
void endFailure(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void endSuccessImpl(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void connectWithWithinHyperspaceRange(Object from, Object to, SectorEntityToken entity, float rangeLY)
void acceptImpl(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void connectWithMarketDecivilized(Object from, Object to, MarketAPI market)
void addDescriptionForNonEndStage(TooltipMakerAPI info, float width, float height)
boolean callAction(String action, String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
void spawnShipGraveyard(String factionId, int minShips, int maxShips, LocData data)
void setMemoryValuePermanent(HasMemory withMemory, String key, Object value)
void connectWithDaysElapsed(Object from, Object to, float days)
PersonAPI findOrCreateCriminalTrader(MarketAPI market, boolean cleanUpOnMissionOverIfWasNewPerson)
void setFlag(SectorEntityToken entity, String flag, boolean permanent)
void ensurePersonIsInCommDirectory(MarketAPI market, PersonAPI person)
CargoAPI createCargo(boolean unlimitedStacks)
CampaignFleetAPI createEmptyFleet(String factionId, String name, boolean aiMode)
OrbitAPI createCircularOrbitWithSpin(SectorEntityToken focus, float angle, float orbitRadius, float orbitDays, float spin)
OrbitAPI createCircularOrbit(SectorEntityToken focus, float angle, float orbitRadius, float orbitDays)
String getSpriteName(String category, String id)
CustomEntitySpecAPI getCustomEntitySpec(String id)