Starsector API
Loading...
Searching...
No Matches
LuddicPathBaseIntel.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.bases;
2
3import java.awt.Color;
4import java.util.LinkedHashMap;
5import java.util.List;
6import java.util.Random;
7import java.util.Set;
8
9import org.apache.log4j.Logger;
10import org.json.JSONException;
11import org.json.JSONObject;
12
13import com.fs.starfarer.api.EveryFrameScript;
14import com.fs.starfarer.api.Global;
15import com.fs.starfarer.api.campaign.BattleAPI;
16import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
17import com.fs.starfarer.api.campaign.CampaignFleetAPI;
18import com.fs.starfarer.api.campaign.FactionAPI;
19import com.fs.starfarer.api.campaign.PersonImportance;
20import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin.ReputationAdjustmentResult;
21import com.fs.starfarer.api.campaign.SectorEntityToken;
22import com.fs.starfarer.api.campaign.StarSystemAPI;
23import com.fs.starfarer.api.campaign.TextPanelAPI;
24import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin;
25import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
26import com.fs.starfarer.api.campaign.econ.EconomyAPI.EconomyUpdateListener;
27import com.fs.starfarer.api.campaign.econ.Industry;
28import com.fs.starfarer.api.campaign.econ.MarketAPI;
29import com.fs.starfarer.api.campaign.econ.MarketAPI.SurveyLevel;
30import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
31import com.fs.starfarer.api.campaign.listeners.ListenerUtil;
32import com.fs.starfarer.api.characters.PersonAPI;
33import com.fs.starfarer.api.combat.MutableStat.StatMod;
34import com.fs.starfarer.api.fleet.FleetMemberAPI;
35import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin;
36import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact;
37import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
38import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
39import com.fs.starfarer.api.impl.campaign.DebugFlags;
40import com.fs.starfarer.api.impl.campaign.ids.Conditions;
41import com.fs.starfarer.api.impl.campaign.ids.Entities;
42import com.fs.starfarer.api.impl.campaign.ids.Factions;
43import com.fs.starfarer.api.impl.campaign.ids.Industries;
44import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
45import com.fs.starfarer.api.impl.campaign.ids.Ranks;
46import com.fs.starfarer.api.impl.campaign.ids.Stats;
47import com.fs.starfarer.api.impl.campaign.ids.Submarkets;
48import com.fs.starfarer.api.impl.campaign.ids.Tags;
49import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
50import com.fs.starfarer.api.impl.campaign.intel.PersonBountyIntel.BountyResult;
51import com.fs.starfarer.api.impl.campaign.intel.PersonBountyIntel.BountyResultType;
52import com.fs.starfarer.api.impl.campaign.intel.bar.PortsideBarData;
53import com.fs.starfarer.api.impl.campaign.intel.bar.events.LuddicPathBaseBarEvent;
54import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseIntel.BaseBountyData;
55import com.fs.starfarer.api.impl.campaign.intel.deciv.DecivTracker;
56import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel;
57import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel.RaidDelegate;
58import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel.RaidStageStatus;
59import com.fs.starfarer.api.impl.campaign.procgen.MarkovNames;
60import com.fs.starfarer.api.impl.campaign.procgen.MarkovNames.MarkovNameResult;
61import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator;
62import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.AddedEntity;
63import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.EntityLocation;
64import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.LocationType;
65import com.fs.starfarer.api.ui.Alignment;
66import com.fs.starfarer.api.ui.SectorMapAPI;
67import com.fs.starfarer.api.ui.TooltipMakerAPI;
68import com.fs.starfarer.api.util.IntervalUtil;
69import com.fs.starfarer.api.util.Misc;
70import com.fs.starfarer.api.util.WeightedRandomPicker;
71
72public class LuddicPathBaseIntel extends BaseIntelPlugin implements EveryFrameScript, FleetEventListener,
73 EconomyUpdateListener, RaidDelegate {
74
75 public static final String PATHER_BASE_COMMANDER = "$patherBaseCommander";
76
77 public static String MEM_FLAG = "$core_luddicPathBase";
78
79 public static Object BOUNTY_EXPIRED_PARAM = new Object();
80 public static Object DISCOVERED_PARAM = new Object();
81
82 public static Logger log = Global.getLogger(LuddicPathBaseIntel.class);
83
84 protected PersonAPI baseCommander;
85 protected StarSystemAPI system;
86 protected MarketAPI market;
87 protected SectorEntityToken entity;
88
89 protected float elapsedDays = 0f;
90 protected float duration = 45f;
91
92 protected BaseBountyData bountyData = null;
93
94 protected IntervalUtil monthlyInterval = new IntervalUtil(20f, 40f);
95 protected int monthsNoBounty = 0;
96
97 protected boolean large = false;
98
99 protected Random random = new Random();
100
101 public static LuddicPathBaseIntel getIntelFor(StarSystemAPI system) {
102 for (IntelInfoPlugin intel : Global.getSector().getIntelManager().getIntel(LuddicPathBaseIntel.class)) {
103 if (((LuddicPathBaseIntel)intel).getSystem() == system) {
104 return (LuddicPathBaseIntel) intel;
105 }
106 }
107 return null;
108 }
109
110 public static LuddicPathBaseIntel getIntelFor(MarketAPI market) {
111 for (IntelInfoPlugin p : Global.getSector().getIntelManager().getIntel(LuddicPathBaseIntel.class)) {
113 if (intel.getMarket() == market) return intel;
114 }
115 return null;
116 }
117
118 public LuddicPathBaseIntel(StarSystemAPI system, String factionId) {
119 this.system = system;
120
121 market = Global.getFactory().createMarket(Misc.genUID(), "Luddic Path Base", 3);
122 market.setSize(3);
123 market.setHidden(true);
124 market.getMemoryWithoutUpdate().set(MEM_FLAG, true);
125 market.getMemoryWithoutUpdate().set(MemFlags.HIDDEN_BASE_MEM_FLAG, true);
126
127 market.setFactionId(Factions.LUDDIC_PATH);
128
129 market.setSurveyLevel(SurveyLevel.FULL);
130
131 market.setFactionId(factionId);
132 market.addCondition(Conditions.POPULATION_3);
133
134 market.addIndustry(Industries.POPULATION);
135 market.addIndustry(Industries.SPACEPORT);
136 market.addIndustry(Industries.MILITARYBASE);
137
138 market.addSubmarket(Submarkets.SUBMARKET_OPEN);
139 market.addSubmarket(Submarkets.SUBMARKET_BLACK);
140
141 market.getTariff().modifyFlat("default_tariff", market.getFaction().getTariffFraction());
142
143 LinkedHashMap<LocationType, Float> weights = new LinkedHashMap<LocationType, Float>();
144 weights.put(LocationType.IN_ASTEROID_BELT, 10f);
145 weights.put(LocationType.IN_ASTEROID_FIELD, 10f);
146 weights.put(LocationType.IN_RING, 10f);
147 weights.put(LocationType.IN_SMALL_NEBULA, 10f);
148 weights.put(LocationType.GAS_GIANT_ORBIT, 10f);
149 weights.put(LocationType.PLANET_ORBIT, 10f);
150 WeightedRandomPicker<EntityLocation> locs = BaseThemeGenerator.getLocations(null, system, null, 100f, weights);
151 EntityLocation loc = locs.pick();
152
153 if (loc == null) {
155 return;
156 }
157
158 AddedEntity added = BaseThemeGenerator.addNonSalvageEntity(system, loc, Entities.MAKESHIFT_STATION, factionId);
159
160 if (added == null || added.entity == null) {
162 return;
163 }
164
165 entity = added.entity;
166
167
168 String name = generateName();
169 if (name == null) {
171 return;
172 }
173
174 market.setName(name);
175 entity.setName(name);
176
177 BaseThemeGenerator.convertOrbitWithSpin(entity, -5f);
178
179 market.setPrimaryEntity(entity);
180 entity.setMarket(market);
181
182 entity.setSensorProfile(1f);
183 entity.setDiscoverable(true);
184 entity.getDetectedRangeMod().modifyFlat("gen", 5000f);
185
186 market.setEconGroup(market.getId());
187 market.getMemoryWithoutUpdate().set(DecivTracker.NO_DECIV_KEY, true);
188
189 market.reapplyIndustries();
190
191 Global.getSector().getEconomy().addMarket(market, true);
192
193 baseCommander = market.getFaction().createRandomPerson(Misc.random);
194 baseCommander.setRankId(Ranks.SPACE_CAPTAIN);
195 baseCommander.setPostId(Ranks.POST_STATION_COMMANDER);
196 baseCommander.setImportanceAndVoice(PersonImportance.HIGH, Misc.random);
197 baseCommander.addTag(Tags.CONTACT_MILITARY);
198 //baseCommander.addTag(Tags.CONTACT_PATHER); // currently no missions for that
199 baseCommander.getMemoryWithoutUpdate().set(PATHER_BASE_COMMANDER, true);
200 baseCommander.setImportance(PersonImportance.VERY_HIGH);
201 market.getCommDirectory().addPerson(baseCommander);
202
203 Global.getSector().getIntelManager().addIntel(this, true);
205 timestamp = null;
206 }
207
208 Global.getSector().getListenerManager().addListener(this);
209 Global.getSector().getEconomy().addUpdateListener(this);
210
211 large = random.nextFloat() > 0.5f;
213
214 PortsideBarData.getInstance().addEvent(new LuddicPathBaseBarEvent(this));
215
216 log.info(String.format("Added luddic path base in [%s], isLarge: %s", system.getName(), "" + large));
217 }
218
219 @Override
220 public boolean isHidden() {
221 //if (true) return false;
222 if (super.isHidden()) return true;
223 return timestamp == null;
224 }
225
226// public float getRaidFP() {
227// float base = getBaseRaidFP();
228// return base * (0.75f + (float) Math.random() * 0.5f);
229// }
230// public float getBaseRaidFP() {
231// float base = 100f;
232// return base * (0.75f + (float) Math.random() * 0.5f);
233// }
234//
235 public void notifyRaidEnded(RaidIntel raid, RaidStageStatus status) {
236 if (status == RaidStageStatus.SUCCESS) {
237 } else {
238 }
239 }
240//
241// public void startRaid(StarSystemAPI target, float raidFP) {
242// boolean hasTargets = false;
243// for (MarketAPI curr : Misc.getMarketsInLocation(target)) {
244// if (curr.getFaction().isHostileTo(getFactionForUIColors())) {
245// hasTargets = true;
246// break;
247// }
248// }
249//
250// if (!hasTargets) return;
251//
252// RaidIntel raid = new RaidIntel(target, getFactionForUIColors(), this);
253//
254// //float raidFP = 1000;
255// float successMult = 0.75f;
256//
257// JumpPointAPI gather = null;
258// List<JumpPointAPI> points = system.getEntities(JumpPointAPI.class);
259// float min = Float.MAX_VALUE;
260// for (JumpPointAPI curr : points) {
261// float dist = Misc.getDistance(entity.getLocation(), curr.getLocation());
262// if (dist < min) {
263// min = dist;
264// gather = curr;
265// }
266// }
267//
268//
269// PirateRaidAssembleStage assemble = new PirateRaidAssembleStage(raid, gather, this);
270// assemble.addSource(market);
271// assemble.setSpawnFP(raidFP);
272// assemble.setAbortFP(raidFP * successMult);
273// raid.addStage(assemble);
274//
275//
276// SectorEntityToken raidJump = RouteLocationCalculator.findJumpPointToUse(getFactionForUIColors(), target.getCenter());
277//
278// TravelStage travel = new TravelStage(raid, gather, raidJump, false);
279// travel.setAbortFP(raidFP * successMult * successMult);
280// raid.addStage(travel);
281//
282// PirateRaidActionStage action = new PirateRaidActionStage(raid, target);
283// action.setAbortFP(raidFP * successMult * successMult * successMult);
284// raid.addStage(action);
285//
286// raid.addStage(new ReturnStage(raid));
287//
288// if (!Misc.getMarketsInLocation(target, Factions.PLAYER).isEmpty()) {
289// Global.getSector().getIntelManager().addIntel(raid);
290// } else {
291// Global.getSector().getIntelManager().queueIntel(raid);
292// }
293// }
294
295 public StarSystemAPI getSystem() {
296 return system;
297 }
298
299 protected String pickStationType(boolean large) {
300 WeightedRandomPicker<String> stations = new WeightedRandomPicker<String>();
301
302 //large = true;
303
304 try {
305 JSONObject json = getFactionForUIColors().getCustom().getJSONObject(Factions.CUSTOM_PATHER_BASES_SMALL);
306 if (large) json = getFactionForUIColors().getCustom().getJSONObject(Factions.CUSTOM_PATHER_BASES_LARGE);
307 for (String key : JSONObject.getNames(json)) {
308 stations.add(key, (float) json.optDouble(key, 0f));
309 }
310 if (stations.isEmpty()) {
311 stations.add(Industries.ORBITALSTATION, 5f);
312 }
313 } catch (JSONException e) {
314 stations.clear();
315 }
316
317 return stations.pick();
318 }
319
320 protected Industry getStationIndustry() {
321 for (Industry curr : market.getIndustries()) {
322 if (curr.getSpec().hasTag(Industries.TAG_STATION)) {
323 return curr;
324 }
325 }
326 return null;
327 }
328
329 protected void updateStationIfNeeded(boolean large) {
330 Industry stationInd = getStationIndustry();
331
332 String currIndId = null;
333 if (stationInd != null) {
334 currIndId = stationInd.getId();
335 market.removeIndustry(stationInd.getId(), null, false);
336 stationInd = null;
337 }
338
339 if (currIndId == null) {
340 currIndId = pickStationType(large);
341 }
342
343 if (currIndId == null) return;
344
345 market.addIndustry(currIndId);
346 stationInd = getStationIndustry();
347 if (stationInd == null) return;
348
349 stationInd.finishBuildingOrUpgrading();
350
351
352 CampaignFleetAPI fleet = Misc.getStationFleet(entity);
353 if (fleet == null) return;
354
355 List<FleetMemberAPI> members = fleet.getFleetData().getMembersListCopy();
356 if (members.size() < 1) return;
357
358 fleet.inflateIfNeeded();
359 }
360
361
362 protected CampaignFleetAPI addedListenerTo = null;
363 @Override
364 protected void advanceImpl(float amount) {
365 float days = Global.getSector().getClock().convertToDays(amount);
366 //days *= 1000f;
367 //Global.getSector().getCurrentLocation().getName()
368 //entity.getContainingLocation().getName()
369 if (getPlayerVisibleTimestamp() == null && entity.isInCurrentLocation() && isHidden()) {
370 makeKnown();
372 }
373
374 if (!sentBountyUpdate && bountyData != null &&
375 (Global.getSector().getIntelManager().isPlayerInRangeOfCommRelay() ||
377 makeKnown();
379 sentBountyUpdate = true;
380 }
381
382 CampaignFleetAPI fleet = Misc.getStationFleet(market);
383 if (fleet != null && addedListenerTo != fleet) {
384 if (addedListenerTo != null) {
385 addedListenerTo.removeEventListener(this);
386 }
387 fleet.addEventListener(this);
388 addedListenerTo = fleet;
389 }
390
391 monthlyInterval.advance(days);
392 if (monthlyInterval.intervalElapsed()) {
393 if (bountyData == null && random.nextFloat() < Math.min(0.3f, monthsNoBounty * 0.02f)) {
394 setBounty();
395 } else {
397 }
398 }
399
400// if (bountyData == null) {
401// setBounty();
402// }
403
404 if (bountyData != null) {
405 boolean canEndBounty = !entity.isInCurrentLocation();
406 bountyData.bountyElapsedDays += days;
407 if (bountyData.bountyElapsedDays > bountyData.bountyDuration && canEndBounty) {
408 endBounty();
409 }
410 }
411 }
412
413
414 public void makeKnown() {
415 makeKnown(null);
416 }
417 public void makeKnown(TextPanelAPI text) {
418// entity.setDiscoverable(null);
419// entity.setSensorProfile(null);
420// entity.getDetectedRangeMod().unmodify("gen");
421
422 if (getPlayerVisibleTimestamp() == null) {
423 Global.getSector().getIntelManager().removeIntel(this);
424 Global.getSector().getIntelManager().addIntel(this, text == null, text);
425 }
426 }
427
429 float f = 1f - elapsedDays / duration;
430 return f;
431 }
432
433
434
435 @Override
436 protected void notifyEnding() {
437 super.notifyEnding();
438 log.info(String.format("Removing luddic path base at [%s]", system.getName()));
439 Global.getSector().getListenerManager().removeListener(this);
440
441 Global.getSector().getEconomy().removeMarket(market);
442 Global.getSector().getEconomy().removeUpdateListener(this);
443 Misc.removeRadioChatter(market);
444 market.advance(0f);
445 }
446
447 @Override
448 protected void notifyEnded() {
449 super.notifyEnded();
450 }
451
452
453
454 protected BountyResult result = null;
455 public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
456 if (isEnding()) return;
457
458 //CampaignFleetAPI station = Misc.getStationFleet(market); // null here since it's the skeleton station at this point
459 if (addedListenerTo != null && fleet == addedListenerTo) {
460 Misc.fadeAndExpire(entity);
462
463 result = new BountyResult(BountyResultType.END_OTHER, 0, null);
464
465 if (reason == FleetDespawnReason.DESTROYED_BY_BATTLE &&
466 param instanceof BattleAPI) {
467 BattleAPI battle = (BattleAPI) param;
468 if (battle.isPlayerInvolved()) {
469 int payment = 0;
470 if (bountyData != null) {
471 payment = (int) (bountyData.baseBounty * battle.getPlayerInvolvementFraction());
472 }
473 if (payment > 0) {
474 Global.getSector().getPlayerFleet().getCargo().getCredits().add(payment);
475
476 CustomRepImpact impact = new CustomRepImpact();
477 impact.delta = bountyData.repChange * battle.getPlayerInvolvementFraction();
478 if (impact.delta < 0.01f) impact.delta = 0.01f;
479 ReputationAdjustmentResult rep = Global.getSector().adjustPlayerReputation(
480 new RepActionEnvelope(RepActions.CUSTOM,
481 impact, null, null, false, true),
482 bountyData.bountyFaction.getId());
483
484 result = new BountyResult(BountyResultType.END_PLAYER_BOUNTY, payment, rep);
485 } else {
486 result = new BountyResult(BountyResultType.END_PLAYER_NO_REWARD, 0, null);
487 }
488 }
489 }
490
491 boolean sendUpdate = DebugFlags.SEND_UPDATES_WHEN_NO_COMM ||
492 result.type != BountyResultType.END_OTHER ||
493 Global.getSector().getIntelManager().isPlayerInRangeOfCommRelay();
494 sendUpdate = true;
495 if (sendUpdate) {
497 }
498
500 cell.makeSleeper(Global.getSettings().getFloat("patherCellDisruptionDuration"));
501 if (cell.getMarket().isPlayerOwned() || DebugFlags.PATHER_BASE_DEBUG) {
502 cell.sendUpdateIfPlayerHasIntel(LuddicPathCellsIntel.UPDATE_DISRUPTED, false);
503 }
504 ListenerUtil.reportCellDisrupted(cell);
505 }
506
509
510 }
511 }
512
513 public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
514
515 }
516
517 public boolean runWhilePaused() {
518 return false;
519 }
520 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
521
522 Color h = Misc.getHighlightColor();
523 Color g = Misc.getGrayColor();
524 float pad = 3f;
525 float opad = 10f;
526
527 float initPad = pad;
528 if (mode == ListInfoMode.IN_DESC) initPad = opad;
529
530 Color tc = getBulletColorForMode(mode);
531
532 bullet(info);
533 boolean isUpdate = getListInfoParam() != null;
534
535
536 if (bountyData != null && result == null) {
538 if (isUpdate || mode != ListInfoMode.IN_DESC) {
539 FactionAPI faction = bountyData.bountyFaction;
540 info.addPara("Bounty faction: " + faction.getDisplayName(), initPad, tc,
541 faction.getBaseUIColor(), faction.getDisplayName());
542 initPad = 0f;
543 }
544 info.addPara("%s reward", initPad, tc, h, Misc.getDGSCredits(bountyData.baseBounty));
545 addDays(info, "remaining", bountyData.bountyDuration - bountyData.bountyElapsedDays, tc);
546 }
547 }
548
549 if (result != null && bountyData != null) {
550 switch (result.type) {
551 case END_PLAYER_BOUNTY:
552 info.addPara("%s received", initPad, tc, h, Misc.getDGSCredits(result.payment));
553 CoreReputationPlugin.addAdjustmentMessage(result.rep.delta, bountyData.bountyFaction, null,
554 null, null, info, tc, isUpdate, 0f);
555 break;
556 case END_TIME:
557 break;
558 case END_OTHER:
559 break;
560
561 }
562 }
563
564 unindent(info);
565 }
566
567 @Override
568 public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
569 Color c = getTitleColor(mode);
570 info.addPara(getName(), c, 0f);
571 addBulletPoints(info, mode);
572 }
573
574 public String getSortString() {
575 String base = Misc.ucFirst(getFactionForUIColors().getPersonNamePrefix());
576 return base + " Base";
577 }
578
579 public String getName() {
580 String base = Misc.ucFirst(getFactionForUIColors().getPersonNamePrefix());
581
582 if (getListInfoParam() == bountyData && bountyData != null) {
583 return base + " Base - Bounty Posted";
584 } else if (getListInfoParam() == BOUNTY_EXPIRED_PARAM) {
585 return base + " Base - Bounty Expired";
586 }
587
588 if (result != null) {
589 if (result.type == BountyResultType.END_PLAYER_BOUNTY) {
590 return base + " Base - Bounty Completed";
591 } else if (result.type == BountyResultType.END_PLAYER_NO_REWARD) {
592 return base + " Base - Destroyed";
593 }
594 }
595
596 String name = market.getName();
597 if (isEnding()) {
598 //return "Base Abandoned - " + name;
599 return base + " Base - Abandoned";
600 }
602 return base + " Base - Discovered";
603 }
604 if (entity.isDiscoverable()) {
605 return base + " Base - Exact Location Unknown";
606 }
607 return base + " Base - " + name;
608 }
609
610 @Override
611 public FactionAPI getFactionForUIColors() {
612 return market.getFaction();
613 }
614
615 public String getSmallDescriptionTitle() {
616 return getName();
617 }
618
619 public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
620
621 Color h = Misc.getHighlightColor();
622 Color g = Misc.getGrayColor();
623 Color tc = Misc.getTextColor();
624 float pad = 3f;
625 float opad = 10f;
626
627 FactionAPI faction = market.getFaction();
628
629 info.addImage(faction.getLogo(), width, 128, opad);
630
631 String has = faction.getDisplayNameHasOrHave();
632
633 info.addPara(Misc.ucFirst(faction.getDisplayNameWithArticle()) + " " + has +
634 " established a base in the " +
635 market.getContainingLocation().getNameWithLowercaseType() + ". " +
636 "The base serves to provide material support to active Pather cells on nearby colonies, enabling them " +
637 "to cause widespread damage and destruction.",
638 opad, faction.getBaseUIColor(), faction.getDisplayNameWithArticleWithoutArticle());
639
640 if (!entity.isDiscoverable()) {
641 if (large) {
642 info.addPara("It has extremely well-developed defensive capabilities " +
643 "and is protected by a large number of fleets.", opad);
644 } else {
645 info.addPara("It has well-developed defensive capabilities " +
646 "and is protected by a large number of fleets.", opad);
647 }
648 } else {
649 info.addPara("You have not yet discovered the exact location or capabilities of this base.", opad);
650 }
651 info.addSectionHeading("Recent events",
652 faction.getBaseUIColor(), faction.getDarkUIColor(), Alignment.MID, opad);
653
654
655 List<LuddicPathCellsIntel> cells = LuddicPathCellsIntel.getCellsForBase(this, false);
656 if (!cells.isEmpty()) {
657 float initPad = opad;
658
659 info.addPara("This base is known to be providing support to active Pather cells at the following colonies:", opad);
660 for (LuddicPathCellsIntel intel : cells) {
661 addMarketToList(info, intel.getMarket(), initPad, tc);
662 initPad = 0f;
663 }
664 initPad = 0f;
665 } else {
666 info.addPara("You do not know of any active pather cells this base might be providing support to.", opad);
667 }
668
669
670 if (bountyData != null) {
671 info.addPara(Misc.ucFirst(bountyData.bountyFaction.getDisplayNameWithArticle()) + " " +
672 bountyData.bountyFaction.getDisplayNameHasOrHave() +
673 " posted a bounty for the destruction of this base.",
674 opad, bountyData.bountyFaction.getBaseUIColor(),
675 bountyData.bountyFaction.getDisplayNameWithArticleWithoutArticle());
676
677 if (result != null && result.type == BountyResultType.END_PLAYER_BOUNTY) {
678 info.addPara("You have successfully completed this bounty.", opad);
679 }
680
681 addBulletPoints(info, ListInfoMode.IN_DESC);
682 }
683
684 if (result != null) {
685 if (result.type == BountyResultType.END_PLAYER_NO_REWARD) {
686 info.addPara("You have destroyed this base.", opad);
687 } else if (result.type == BountyResultType.END_OTHER) {
688 info.addPara("It is rumored that this base is no longer operational.", opad);
689 }
690 }
691
692 }
693
694 public String getIcon() {
695 return Global.getSettings().getSpriteName("intel", "pather_base");
696 //return market.getFaction().getCrest();
697 }
698
699 public Set<String> getIntelTags(SectorMapAPI map) {
700 Set<String> tags = super.getIntelTags(map);
701 if (bountyData != null) {
702 tags.add(Tags.INTEL_BOUNTY);
703 }
704 tags.add(Tags.INTEL_EXPLORATION);
705
706// if (target != null && !Misc.getMarketsInLocation(target, Factions.PLAYER).isEmpty()) {
707// tags.add(Tags.INTEL_COLONIES);
708// }
709
711 if (cell.getMarket().isPlayerOwned() && !cell.isSleeper()) {
712 tags.add(Tags.INTEL_COLONIES);
713 break;
714 }
715 }
716
717 tags.add(market.getFactionId());
718 if (bountyData != null) {
719 tags.add(bountyData.bountyFaction.getId());
720 }
721 return tags;
722 }
723
724 @Override
725 public SectorEntityToken getMapLocation(SectorMapAPI map) {
726 if (market.getPrimaryEntity().isDiscoverable()) {
727 return system.getCenter();
728 }
729 return market.getPrimaryEntity();
730 }
731
732
733
734 protected String generateName() {
735 MarkovNames.loadIfNeeded();
736
737 MarkovNameResult gen = null;
738 for (int i = 0; i < 10; i++) {
739 gen = MarkovNames.generate(null);
740 if (gen != null) {
741 String test = gen.name;
742 if (test.toLowerCase().startsWith("the ")) continue;
743 String p = pickPostfix();
744 if (p != null && !p.isEmpty()) {
745 test += " " + p;
746 }
747 if (test.length() > 22) continue;
748
749 return test;
750 }
751 }
752 return null;
753 }
754
755 private String pickPostfix() {
756 WeightedRandomPicker<String> post = new WeightedRandomPicker<String>();
757 post.add("Asylum");
758 //post.add("Base"); -> otherwise intel title can look like this: "Luddic Path Base: Scrimshaw Base"
759 post.add("Citadel");
760 post.add("Hammer");
761 post.add("Harbor");
762 post.add("Haven");
763 post.add("Hold");
764 post.add("Locus");
765 post.add("Nexus");
766 post.add("Refuge");
767 post.add("Sanctuary");
768 post.add("Sanctum");
769 post.add("Shadow");
770 post.add("Shelter");
771 post.add("Safehold");
772 post.add("Terminus");
773 post.add("Principle");
774 post.add("Offering");
775 post.add("Devotion");
776 post.add("Atonement");
777 post.add("Cleansing");
778 post.add("Oblation");
779 post.add("Sacrement");
780 return post.pick();
781 }
782
783 public void commodityUpdated(String commodityId) {
784 CommodityOnMarketAPI com = market.getCommodityData(commodityId);
785 int curr = 0;
786 String modId = market.getId();
787 StatMod mod = com.getAvailableStat().getFlatStatMod(modId);
788 if (mod != null) {
789 curr = Math.round(mod.value);
790 }
791
792 int a = com.getAvailable() - curr;
793 int d = com.getMaxDemand();
794 if (d > a) {
795 com.getAvailableStat().modifyFlat(modId, (d - a), "Brought in by smugglers");
796 }
797 }
798
799 public void economyUpdated() {
800 float qualityBonus = 0f;
801 int light = 0;
802 int medium = 0;
803 int heavy = 0;
804
805 if (large) {
806 qualityBonus = 0.5f;
807 light = 4;
808 medium = 4;
809 heavy = 3;
810 } else {
811 qualityBonus = 0f;
812 light = 3;
813 medium = 2;
814 heavy = 1;
815 }
816
817 market.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).
818 modifyFlatAlways(market.getId(), qualityBonus,
819 "Development level");
820
821 float fleetSizeBonus = 0.5f;
822 if (large) fleetSizeBonus = 1f;
823 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).modifyFlatAlways(market.getId(),
824 fleetSizeBonus,
825 "Development level");
826
827 String modId = market.getId();
828 market.getStats().getDynamic().getMod(Stats.PATROL_NUM_LIGHT_MOD).modifyFlat(modId, light);
829 market.getStats().getDynamic().getMod(Stats.PATROL_NUM_MEDIUM_MOD).modifyFlat(modId, medium);
830 market.getStats().getDynamic().getMod(Stats.PATROL_NUM_HEAVY_MOD).modifyFlat(modId, heavy);
831 }
832
833 public boolean isEconomyListenerExpired() {
834 return isEnded();
835 }
836
837 public MarketAPI getMarket() {
838 return market;
839 }
840
841
842 protected void setBounty() {
843
844 List<IntelInfoPlugin> bases = Global.getSector().getIntelManager().getIntel(LuddicPathBaseIntel.class);
845 for (IntelInfoPlugin curr : bases) {
847 if (intel != this && intel.bountyData != null) {
848 return;
849 }
850 }
851
852 bountyData = new BaseBountyData();
853 float base = 100000f;
854 if (large) {
855 base = Global.getSettings().getFloat("luddicPathBaseBountyLarge");
856 bountyData.repChange = 0.05f;
857 } else {
858 base = Global.getSettings().getFloat("luddicPathBaseBountySmall");
859 bountyData.repChange = 0.1f;
860 }
861
862 bountyData.baseBounty = base * (0.9f + (float) Math.random() * 0.2f);
863 bountyData.baseBounty = (int)(bountyData.baseBounty / 10000) * 10000;
864
865
866 WeightedRandomPicker<FactionAPI> picker = new WeightedRandomPicker<FactionAPI>();
868 FactionAPI faction = cell.getMarket().getFaction();
869 //if (faction.isPlayerFaction()) continue;
870 picker.add(faction, (float) Math.pow(2f, cell.getMarket().getSize()));
871 }
872
873 FactionAPI faction = picker.pick();
874 // player faction is in picker to reduce bounties offered on cells that are already bothering the player
875 if (faction == null || faction.isPlayerFaction()) {
876 bountyData = null;
877 return;
878 }
879
880 bountyData.bountyFaction = faction;
881 bountyData.bountyDuration = 180f;
882 bountyData.bountyElapsedDays = 0f;
883
884 monthsNoBounty = 0;
885 Misc.makeImportant(entity, "baseBounty");
886
887
888// makeKnown();
889// sendUpdateIfPlayerHasIntel(bountyData, false);
890 sentBountyUpdate = false;
891 }
892
893 protected boolean sentBountyUpdate = false;
894 protected void endBounty() {
896 bountyData = null;
897 monthsNoBounty = 0;
898 Misc.makeUnimportant(entity, "baseBounty");
899 sentBountyUpdate = false;
900 }
901
902
903 public List<ArrowData> getArrowData(SectorMapAPI map) {
904 return null;
905 }
906
907 public SectorEntityToken getEntity() {
908 return entity;
909 }
910
911 public boolean isLarge() {
912 return large;
913 }
914
915 public PersonAPI getBaseCommander() {
916 return baseCommander;
917 }
918 public void setBaseCommander(PersonAPI baseCommander) {
919 this.baseCommander = baseCommander;
920 }
921}
922
923
924
925
926
927
928
929
930
931
932
933
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static Logger getLogger(Class c)
Definition Global.java:26
static SectorAPI getSector()
Definition Global.java:59
static void addAdjustmentMessage(float delta, FactionAPI faction, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad)
void sendUpdate(Object listInfoParam, TextPanelAPI textPanel)
void addDays(TooltipMakerAPI info, String after, float days)
void sendUpdateIfPlayerHasIntel(Object listInfoParam, TextPanelAPI textPanel)
static void addMarketToList(TooltipMakerAPI info, MarketAPI market, float pad)
void createSmallDescription(TooltipMakerAPI info, float width, float height)
void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
static LuddicPathBaseIntel getIntelFor(StarSystemAPI system)
void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle)
static List< LuddicPathCellsIntel > getCellsForBase(LuddicPathBaseIntel base, boolean includeSleeper)
MarketAPI createMarket(String id, String name, int size)
String getSpriteName(String category, String id)