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