Starsector API
Loading...
Searching...
No Matches
PirateBaseIntel.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.ArrayList;
5import java.util.LinkedHashMap;
6import java.util.List;
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.JumpPointAPI;
20import com.fs.starfarer.api.campaign.PersonImportance;
21import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin.ReputationAdjustmentResult;
22import com.fs.starfarer.api.campaign.SectorEntityToken;
23import com.fs.starfarer.api.campaign.StarSystemAPI;
24import com.fs.starfarer.api.campaign.TextPanelAPI;
25import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin;
26import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
27import com.fs.starfarer.api.campaign.econ.EconomyAPI.EconomyUpdateListener;
28import com.fs.starfarer.api.campaign.econ.Industry;
29import com.fs.starfarer.api.campaign.econ.MarketAPI;
30import com.fs.starfarer.api.campaign.econ.MarketAPI.SurveyLevel;
31import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
32import com.fs.starfarer.api.characters.PersonAPI;
33import com.fs.starfarer.api.combat.MutableStat.StatMod;
34import com.fs.starfarer.api.combat.ShipVariantAPI;
35import com.fs.starfarer.api.fleet.FleetMemberAPI;
36import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin;
37import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact;
38import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
39import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
40import com.fs.starfarer.api.impl.campaign.DebugFlags;
41import com.fs.starfarer.api.impl.campaign.Tuning;
42import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator;
43import com.fs.starfarer.api.impl.campaign.ids.Conditions;
44import com.fs.starfarer.api.impl.campaign.ids.Entities;
45import com.fs.starfarer.api.impl.campaign.ids.Factions;
46import com.fs.starfarer.api.impl.campaign.ids.Industries;
47import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
48import com.fs.starfarer.api.impl.campaign.ids.Ranks;
49import com.fs.starfarer.api.impl.campaign.ids.Stats;
50import com.fs.starfarer.api.impl.campaign.ids.Submarkets;
51import com.fs.starfarer.api.impl.campaign.ids.Tags;
52import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
53import com.fs.starfarer.api.impl.campaign.intel.PersonBountyIntel.BountyResult;
54import com.fs.starfarer.api.impl.campaign.intel.PersonBountyIntel.BountyResultType;
55import com.fs.starfarer.api.impl.campaign.intel.bar.PortsideBarData;
56import com.fs.starfarer.api.impl.campaign.intel.bar.events.PirateBaseRumorBarEvent;
57import com.fs.starfarer.api.impl.campaign.intel.deciv.DecivTracker;
58import com.fs.starfarer.api.impl.campaign.intel.events.PirateBasePirateActivityCause2;
59import com.fs.starfarer.api.impl.campaign.intel.raid.PirateRaidActionStage;
60import com.fs.starfarer.api.impl.campaign.intel.raid.PirateRaidAssembleStage;
61import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel;
62import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel.RaidDelegate;
63import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel.RaidStageStatus;
64import com.fs.starfarer.api.impl.campaign.intel.raid.ReturnStage;
65import com.fs.starfarer.api.impl.campaign.intel.raid.TravelStage;
66import com.fs.starfarer.api.impl.campaign.procgen.MarkovNames;
67import com.fs.starfarer.api.impl.campaign.procgen.MarkovNames.MarkovNameResult;
68import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator;
69import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.AddedEntity;
70import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.EntityLocation;
71import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.LocationType;
72import com.fs.starfarer.api.impl.campaign.rulecmd.HA_CMD;
73import com.fs.starfarer.api.ui.Alignment;
74import com.fs.starfarer.api.ui.LabelAPI;
75import com.fs.starfarer.api.ui.SectorMapAPI;
76import com.fs.starfarer.api.ui.TooltipMakerAPI;
77import com.fs.starfarer.api.util.IntervalUtil;
78import com.fs.starfarer.api.util.Misc;
79import com.fs.starfarer.api.util.WeightedRandomPicker;
80
81public class PirateBaseIntel extends BaseIntelPlugin implements EveryFrameScript, FleetEventListener,
82 EconomyUpdateListener, RaidDelegate {
83
84 public static final String PIRATE_BASE_COMMANDER = "$pirateBaseCommander";
85 public static final String HAS_DEAL_WITH_BASE_COMMANDER = "$playerHasDealWithPirateBaseCommander";
86
87 public static String MEM_FLAG = "$core_pirateBase";
88
89 public static PirateBaseIntel getIntelFor(StarSystemAPI system) {
90 for (IntelInfoPlugin intel : Global.getSector().getIntelManager().getIntel(PirateBaseIntel.class)) {
91 if (((PirateBaseIntel)intel).getSystem() == system) {
92 return (PirateBaseIntel) intel;
93 }
94 }
95 return null;
96 }
97 public static PirateBaseIntel getIntelFor(SectorEntityToken station) {
98 for (IntelInfoPlugin intel : Global.getSector().getIntelManager().getIntel(PirateBaseIntel.class)) {
99 if (((PirateBaseIntel)intel).getEntity() == station) {
100 return (PirateBaseIntel) intel;
101 }
102 }
103 return null;
104 }
105
106 public static enum PirateBaseTier {
107 TIER_1_1MODULE,
108 TIER_2_1MODULE,
109 TIER_3_2MODULE,
110 TIER_4_3MODULE,
111 TIER_5_3MODULE,
112 }
113
114
115 public static Object DEAL_MADE_PARAM = new Object();
116 public static Object DEAL_BROKEN_PARAM = new Object();
117 public static Object DEAL_CANCELLED_PARAM = new Object();
118
119 public static Object BOUNTY_EXPIRED_PARAM = new Object();
120 public static Object DISCOVERED_PARAM = new Object();
121
122 public static class BaseBountyData {
123 public float bountyElapsedDays = 0f;
124 public float bountyDuration = 0;
125 public float baseBounty = 0;
126 public float repChange = 0;
127 public FactionAPI bountyFaction = null;
128 }
129
130 public static Logger log = Global.getLogger(PirateBaseIntel.class);
131
132 protected StarSystemAPI system;
133 protected MarketAPI market;
134 protected PersonAPI baseCommander;
135 protected SectorEntityToken entity;
136
137 protected float elapsedDays = 0f;
138 protected float duration = 45f;
139
140 protected BaseBountyData bountyData = null;
141
142 protected PirateBaseTier tier;
143 protected PirateBaseTier matchedStationToTier = null;
144
145 protected IntervalUtil monthlyInterval = new IntervalUtil(20f, 40f);
146 protected int raidTimeoutMonths = 0;
147
148 public static PirateBaseIntel getIntelFor(MarketAPI market) {
149 for (IntelInfoPlugin p : Global.getSector().getIntelManager().getIntel(PirateBaseIntel.class)) {
151 if (intel.getMarket() == market) return intel;
152 }
153 return null;
154 }
155
156
158 return baseCommander != null && baseCommander.getMemoryWithoutUpdate().getBoolean(HAS_DEAL_WITH_BASE_COMMANDER);
159 }
160 public void setPlayerHasDealWithBaseCommander(boolean hasDeal) {
161 if (baseCommander == null) return;
162 baseCommander.getMemoryWithoutUpdate().set(HAS_DEAL_WITH_BASE_COMMANDER, hasDeal);
163 }
164
165 public PirateBaseIntel(StarSystemAPI system, String factionId, PirateBaseTier tier) {
166 this.system = system;
167 this.tier = tier;
168
169 raidTimeoutMonths = Tuning.PIRATE_RAID_MIN_TIMEOUT_MONTHS +
171
172 market = Global.getFactory().createMarket(Misc.genUID(), "Pirate Base", 3);
173 market.setSize(3);
174 market.setHidden(true);
175 market.getMemoryWithoutUpdate().set(MEM_FLAG, true);
176 market.getMemoryWithoutUpdate().set(MemFlags.HIDDEN_BASE_MEM_FLAG, true);
177 //market.getMemoryWithoutUpdate().set(ContactIntel.NO_CONTACTS_ON_MARKET, true);
178
179 market.setFactionId(Factions.PIRATES);
180
181 market.setSurveyLevel(SurveyLevel.FULL);
182
183 market.setFactionId(factionId);
184 market.addCondition(Conditions.POPULATION_3);
185
186 market.addIndustry(Industries.POPULATION);
187 market.addIndustry(Industries.SPACEPORT);
188 market.addIndustry(Industries.MILITARYBASE);
189
190 market.addSubmarket(Submarkets.SUBMARKET_OPEN);
191 market.addSubmarket(Submarkets.SUBMARKET_BLACK);
192
193 market.getTariff().modifyFlat("default_tariff", market.getFaction().getTariffFraction());
194
195 LinkedHashMap<LocationType, Float> weights = new LinkedHashMap<LocationType, Float>();
196 weights.put(LocationType.IN_ASTEROID_BELT, 10f);
197 weights.put(LocationType.IN_ASTEROID_FIELD, 10f);
198 weights.put(LocationType.IN_RING, 10f);
199 weights.put(LocationType.IN_SMALL_NEBULA, 10f);
200 weights.put(LocationType.GAS_GIANT_ORBIT, 10f);
201 weights.put(LocationType.PLANET_ORBIT, 10f);
202 WeightedRandomPicker<EntityLocation> locs = BaseThemeGenerator.getLocations(null, system, null, 100f, weights);
203 EntityLocation loc = locs.pick();
204
205 if (loc == null) {
207 return;
208 }
209
210 AddedEntity added = BaseThemeGenerator.addNonSalvageEntity(system, loc, Entities.MAKESHIFT_STATION, factionId);
211
212 if (added == null || added.entity == null) {
214 return;
215 }
216
217 entity = added.entity;
218
219
220 String name = generateName();
221 if (name == null) {
223 return;
224 }
225
226 market.setName(name);
227 entity.setName(name);
228
229
230// boolean down = false;
231// if (entity.getOrbitFocus() instanceof PlanetAPI) {
232// PlanetAPI planet = (PlanetAPI) entity.getOrbitFocus();
233// if (!planet.isStar()) {
234// down = true;
235// }
236// }
237// if (down) {
238// BaseThemeGenerator.convertOrbitPointingDown(entity);
239// }
240 BaseThemeGenerator.convertOrbitWithSpin(entity, -5f);
241
242 market.setPrimaryEntity(entity);
243 entity.setMarket(market);
244
245 entity.setSensorProfile(1f);
246 entity.setDiscoverable(true);
247 entity.getDetectedRangeMod().modifyFlat("gen", 5000f);
248
249 market.setEconGroup(market.getId());
250 market.getMemoryWithoutUpdate().set(DecivTracker.NO_DECIV_KEY, true);
251
252 market.reapplyIndustries();
253
254 Global.getSector().getEconomy().addMarket(market, true);
255
256 baseCommander = market.getFaction().createRandomPerson(Misc.random);
257 baseCommander.setRankId(Ranks.SPACE_CAPTAIN);
258 baseCommander.setPostId(Ranks.POST_STATION_COMMANDER);
259 baseCommander.setImportanceAndVoice(PersonImportance.HIGH, Misc.random);
260 baseCommander.addTag(Tags.CONTACT_UNDERWORLD);
261 baseCommander.getMemoryWithoutUpdate().set(PIRATE_BASE_COMMANDER, true);
262 market.getCommDirectory().addPerson(baseCommander);
263
264 log.info(String.format("Added pirate base in [%s], tier: %s", system.getName(), tier.name()));
265
266 Global.getSector().getIntelManager().addIntel(this, true);
267 timestamp = null;
268
269 Global.getSector().getListenerManager().addListener(this);
270 Global.getSector().getEconomy().addUpdateListener(this);
271
272 updateTarget();
273
274// if ((float) Math.random() > 0.067f) {
275// SectorEntityToken raidDest = Global.getSector().getEconomy().getMarket("yama").getPrimaryEntity();
276// startRaid(raidDest.getStarSystem(), getRaidFP());
277// }
278
279 PortsideBarData.getInstance().addEvent(new PirateBaseRumorBarEvent(this));
280 }
281
282 @Override
283 public boolean isHidden() {
284 if (super.isHidden()) return true;
285 //if (true) return false;
286 return timestamp == null;
287 }
288
289
290 public float getRaidFP() {
291 float base = getBaseRaidFP();
292 return base * (0.75f + (float) Math.random() * 0.5f);
293 }
294 public float getBaseRaidFP() {
295 float base = 100f;
296 switch (tier) {
297 case TIER_1_1MODULE: base = 100f; break;
298 case TIER_2_1MODULE: base = 150f; break;
299 case TIER_3_2MODULE: base = 250f; break;
300 case TIER_4_3MODULE: base = 300f; break;
301 case TIER_5_3MODULE: base = 450f; break;
302 }
303 return base * (0.75f + (float) Math.random() * 0.5f);
304 }
305
306 public void notifyRaidEnded(RaidIntel raid, RaidStageStatus status) {
307 if (status == RaidStageStatus.SUCCESS) {
308 //raidTimeoutMonths = 0;
311 } else {
312 float base = getBaseRaidFP();
313 float raidFP = raid.getAssembleStage().getOrigSpawnFP();
314 raidTimeoutMonths += Math.min(Math.round(raidFP / base) * 2, Tuning.PIRATE_RAID_DEFEATED_TIMEOUT_MONTHS);
315 }
316 }
317
318 public void startRaid(StarSystemAPI target, float raidFP) {
319 // if piracy respite: no raids against systems with player colonies
320 //if (PiracyRespiteScript.get() != null && target != null &&
321 // actually just no raids against the player, period - that's handled by Colony Crises
322 if (target != null &&
323 !Misc.getMarketsInLocation(target, Factions.PLAYER).isEmpty()) {
324 return;
325 }
326
327 boolean hasTargets = false;
328 for (MarketAPI curr : Misc.getMarketsInLocation(target)) {
329 if (curr.getFaction().isHostileTo(getFactionForUIColors())) {
330 hasTargets = true;
331 break;
332 }
333 }
334
335 if (!hasTargets) return;
336
337 RaidIntel raid = new RaidIntel(target, getFactionForUIColors(), this);
338
339 //float raidFP = 1000;
340 float successMult = 0.5f;
341
342 JumpPointAPI gather = null;
343 List<JumpPointAPI> points = system.getEntities(JumpPointAPI.class);
344 float min = Float.MAX_VALUE;
345 for (JumpPointAPI curr : points) {
346 float dist = Misc.getDistance(entity.getLocation(), curr.getLocation());
347 if (dist < min) {
348 min = dist;
349 gather = curr;
350 }
351 }
352
353 SectorEntityToken raidJump = RouteLocationCalculator.findJumpPointToUse(getFactionForUIColors(), target.getCenter());
354 if (gather == null || raidJump == null) return;
355
356 PirateRaidAssembleStage assemble = new PirateRaidAssembleStage(raid, gather, this);
357 assemble.addSource(market);
358 assemble.setSpawnFP(raidFP);
359 assemble.setAbortFP(raidFP * successMult);
360 raid.addStage(assemble);
361
362 TravelStage travel = new TravelStage(raid, gather, raidJump, false);
363 travel.setAbortFP(raidFP * successMult);
364 raid.addStage(travel);
365
366 PirateRaidActionStage action = new PirateRaidActionStage(raid, target);
367 action.setAbortFP(raidFP * successMult);
368 raid.addStage(action);
369
370 raid.addStage(new ReturnStage(raid));
371
372 boolean shouldNotify = raid.shouldSendUpdate();
373 Global.getSector().getIntelManager().addIntel(raid, !shouldNotify);
374// if (!Misc.getMarketsInLocation(target, Factions.PLAYER).isEmpty() || true) {
375// Global.getSector().getIntelManager().addIntel(raid);
376// } else {
377// Global.getSector().getIntelManager().queueIntel(raid);
378// }
379 }
380
381 public StarSystemAPI getSystem() {
382 return system;
383 }
384
385 protected String pickStationType() {
386 WeightedRandomPicker<String> stations = new WeightedRandomPicker<String>();
387
388 if (getFactionForUIColors().getCustom().has(Factions.CUSTOM_PIRATE_BASE_STATION_TYPES)) {
389 try {
390 JSONObject json = getFactionForUIColors().getCustom().getJSONObject(Factions.CUSTOM_PIRATE_BASE_STATION_TYPES);
391 for (String key : JSONObject.getNames(json)) {
392 stations.add(key, (float) json.optDouble(key, 0f));
393 }
394 } catch (JSONException e) {
395 stations.clear();
396 }
397 }
398
399 if (stations.isEmpty()) {
400 stations.add(Industries.ORBITALSTATION, 5f);
401 stations.add(Industries.ORBITALSTATION_MID, 3f);
402 stations.add(Industries.ORBITALSTATION_HIGH, 1f);
403 }
404
405 //stations.add(Industries.STARFORTRESS, 100000f);
406 return stations.pick();
407 }
408
409 protected Industry getStationIndustry() {
410 for (Industry curr : market.getIndustries()) {
411 if (curr.getSpec().hasTag(Industries.TAG_STATION)) {
412 return curr;
413 }
414 }
415 return null;
416 }
417
418 protected void updateStationIfNeeded() {
419 if (matchedStationToTier == tier) return;
420
423
424 Industry stationInd = getStationIndustry();
425
426 String currIndId = null;
427 if (stationInd != null) {
428 currIndId = stationInd.getId();
429 market.removeIndustry(stationInd.getId(), null, false);
430 stationInd = null;
431 }
432
433 if (currIndId == null) {
434 currIndId = pickStationType();
435 }
436
437 if (currIndId == null) return;
438
439 market.addIndustry(currIndId);
440 stationInd = getStationIndustry();
441 if (stationInd == null) return;
442
443 stationInd.finishBuildingOrUpgrading();
444
445
446 CampaignFleetAPI fleet = Misc.getStationFleet(entity);
447 if (fleet == null) return;
448
449 List<FleetMemberAPI> members = fleet.getFleetData().getMembersListCopy();
450 if (members.size() < 1) return;
451
452 fleet.inflateIfNeeded();
453
454 FleetMemberAPI station = members.get(0);
455
456 WeightedRandomPicker<Integer> picker = new WeightedRandomPicker<Integer>();
457 int index = 1; // index 0 is station body
458 for (String slotId : station.getVariant().getModuleSlots()) {
459 ShipVariantAPI mv = station.getVariant().getModuleVariant(slotId);
460 if (Misc.isActiveModule(mv)) {
461 picker.add(index, 1f);
462 }
463 index++;
464 }
465
466 float removeMult = 0f;
467
468 switch (tier) {
469 case TIER_1_1MODULE:
470 case TIER_2_1MODULE:
471 removeMult = 0.67f;
472 break;
473 case TIER_3_2MODULE:
474 removeMult = 0.33f;
475 break;
476 case TIER_4_3MODULE:
477 case TIER_5_3MODULE:
478 removeMult = 0;
479 break;
480 }
481
482 int remove = Math.round(picker.getItems().size() * removeMult);
483 if (remove < 1 && removeMult > 0) remove = 1;
484
485 // one-module bases are a bit too boring to fight
486 if (remove >= picker.getItems().size() - 1) {
487 remove = picker.getItems().size() - 2;
488 }
489
490 for (int i = 0; i < remove; i++) {
491 Integer pick = picker.pickAndRemove();
492 if (pick != null) {
493 station.getStatus().setHullFraction(pick, 0f);
494 station.getStatus().setDetached(pick, true);
495 station.getStatus().setPermaDetached(pick, true);
496 }
497 }
498
499 if (tier == PirateBaseTier.TIER_5_3MODULE || tier == PirateBaseTier.TIER_4_3MODULE) {
500 baseCommander.setImportance(PersonImportance.VERY_HIGH);
501 } else {
502 baseCommander.setImportance(PersonImportance.HIGH);
503 }
504 }
505
506 public CampaignFleetAPI getAddedListenerTo() {
507 return addedListenerTo;
508 }
509
510
511
512 protected CampaignFleetAPI addedListenerTo = null;
513 @Override
514 protected void advanceImpl(float amount) {
515 //makeKnown();
516 float days = Global.getSector().getClock().convertToDays(amount);
517 //days *= 1000f;
518 //Global.getSector().getCurrentLocation().getName()
519 //entity.getContainingLocation().getName()
520 if (getPlayerVisibleTimestamp() == null && entity.isInCurrentLocation() && isHidden()) {
521 makeKnown();
523 }
524
525
526 //System.out.println("Name: " + market.getName());
527
528 if (!sentBountyUpdate && bountyData != null &&
529 (Global.getSector().getIntelManager().isPlayerInRangeOfCommRelay() ||
531 makeKnown();
533 sentBountyUpdate = true;
534 }
535
536 CampaignFleetAPI fleet = Misc.getStationFleet(market);
537 if (fleet != null && addedListenerTo != fleet) {
538 if (addedListenerTo != null) {
539 addedListenerTo.removeEventListener(this);
540 }
541 fleet.addEventListener(this);
542 addedListenerTo = fleet;
543 }
544
545
546 if (target != null) {
547 if (getAffectedMarkets(target).isEmpty()) {
548 clearTarget();
549 }
550 }
551
553 days *= 100f;
554 }
555
556 monthlyInterval.advance(days);
557 if (monthlyInterval.intervalElapsed()) {
558// if (targetPlayerColonies) {
559// System.out.println("wefwefwe");
560// }
564
565 if ((monthsWithSameTarget > 6 && (float) Math.random() < 0.2f) || target == null) {
566 updateTarget();
567 }
568 if (target != null &&
569 (float) Math.random() < monthsWithSameTarget * 0.05f &&
570 bountyData == null) {
571 setBounty();
572 }
573 //if (target != null && (float) Math.random() < 0.2f && raidTimeoutMonths <= 0) {
575// if (target != null && !Misc.getMarketsInLocation(target).isEmpty() &&
576// Misc.getMarketsInLocation(target).get(0).isPlayerOwned()) {
577// System.out.println("wefwefew");
578// }
579 if (target != null &&
580 (((float) Math.random() < 0.2f && allowRandomRaids) ||
583 raidTimeoutMonths = Tuning.PIRATE_RAID_MIN_TIMEOUT_MONTHS +
585// raidTimeoutMonths = Tuning.PIRATE_RAID_MIN_TIMEOUT_MONTHS +
586// (int)Math.round((float) Math.random() * (Tuning.PIRATE_RAID_MIN_TIMEOUT_MONTHS=_TIMEOUT_MONTHSf);
587 }
588
590 }
591
592// if (bountyData == null && target != null) {
593// setBounty();
594// }
595
596 if (bountyData != null) {
597 boolean canEndBounty = !entity.isInCurrentLocation();
598 bountyData.bountyElapsedDays += days;
599 if (bountyData.bountyElapsedDays > bountyData.bountyDuration && canEndBounty) {
600 endBounty();
601 }
602 }
603
604 //elapsedDays += days;
605// if (elapsedDays >= duration && !isDone()) {
606// endAfterDelay();
607// boolean current = market.getContainingLocation() == Global.getSector().getCurrentLocation();
608// sendUpdateIfPlayerHasIntel(new Object(), !current);
609// return;
610// }
611
613 }
614
615 protected void checkForTierChange() {
616 if (bountyData != null) return;
617 if (entity.isInCurrentLocation()) return;
618
619 float minMonths = Global.getSettings().getFloat("pirateBaseMinMonthsForNextTier");
620 if (monthsAtCurrentTier > minMonths) {
621 float prob = (monthsAtCurrentTier - minMonths) * 0.1f;
622 if ((float) Math.random() < prob) {
623 PirateBaseTier next = getNextTier(tier);
624 if (next != null) {
625 tier = next;
628 return;
629 }
630 }
631 }
632
634 }
635
636 protected PirateBaseTier getNextTier(PirateBaseTier tier) {
637 switch (tier) {
638 case TIER_1_1MODULE: return PirateBaseTier.TIER_2_1MODULE;
639 case TIER_2_1MODULE: return PirateBaseTier.TIER_3_2MODULE;
640 case TIER_3_2MODULE: return PirateBaseTier.TIER_4_3MODULE;
641 case TIER_4_3MODULE: return PirateBaseTier.TIER_5_3MODULE;
642 case TIER_5_3MODULE: return null;
643 }
644 return null;
645 }
646
647 protected PirateBaseTier getPrevTier(PirateBaseTier tier) {
648 switch (tier) {
649 case TIER_1_1MODULE: return null;
650 case TIER_2_1MODULE: return PirateBaseTier.TIER_1_1MODULE;
651 case TIER_3_2MODULE: return PirateBaseTier.TIER_2_1MODULE;
652 case TIER_4_3MODULE: return PirateBaseTier.TIER_3_2MODULE;
653 case TIER_5_3MODULE: return PirateBaseTier.TIER_4_3MODULE;
654 }
655 return null;
656 }
657
658 public void makeKnown() {
659 makeKnown(null);
660 }
661 public void makeKnown(TextPanelAPI text) {
662// entity.setDiscoverable(null);
663// entity.setSensorProfile(null);
664// entity.getDetectedRangeMod().unmodify("gen");
665
666 if (getPlayerVisibleTimestamp() == null) {
667 Global.getSector().getIntelManager().removeIntel(this);
668 Global.getSector().getIntelManager().addIntel(this, text == null, text);
669 }
670 }
671
673 float f = 1f - elapsedDays / duration;
674 return f;
675 }
676
677
678
679 @Override
680 protected void notifyEnding() {
681 super.notifyEnding();
682 log.info(String.format("Removing pirate base at [%s]", system.getName()));
683 Global.getSector().getListenerManager().removeListener(this);
684 clearTarget();
685
686 Global.getSector().getEconomy().removeMarket(market);
687 Global.getSector().getEconomy().removeUpdateListener(this);
688 Misc.removeRadioChatter(market);
689 market.advance(0f);
690 }
691
692 @Override
693 protected void notifyEnded() {
694 super.notifyEnded();
695 }
696
697
698
699 protected BountyResult result = null;
700 public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
701 if (isEnding()) return;
702
703 //CampaignFleetAPI station = Misc.getStationFleet(market); // null here since it's the skeleton station at this point
704 if (addedListenerTo != null && fleet == addedListenerTo) {
705 Misc.fadeAndExpire(entity);
707
708 result = new BountyResult(BountyResultType.END_OTHER, 0, null);
709
710 if (reason == FleetDespawnReason.DESTROYED_BY_BATTLE &&
711 param instanceof BattleAPI) {
712 BattleAPI battle = (BattleAPI) param;
713 if (battle.isPlayerInvolved()) {
714 int payment = 0;
715 if (bountyData != null) {
716 payment = (int) (bountyData.baseBounty * battle.getPlayerInvolvementFraction());
717 }
718 if (payment > 0) {
719 Global.getSector().getPlayerFleet().getCargo().getCredits().add(payment);
720
721 CustomRepImpact impact = new CustomRepImpact();
722 impact.delta = bountyData.repChange * battle.getPlayerInvolvementFraction();
723 if (impact.delta < 0.01f) impact.delta = 0.01f;
724 ReputationAdjustmentResult rep = Global.getSector().adjustPlayerReputation(
725 new RepActionEnvelope(RepActions.CUSTOM,
726 impact, null, null, false, true),
727 bountyData.bountyFaction.getId());
728
729 result = new BountyResult(BountyResultType.END_PLAYER_BOUNTY, payment, rep);
730 } else {
731 result = new BountyResult(BountyResultType.END_PLAYER_NO_REWARD, 0, null);
732 }
733 }
734 }
735
736 boolean sendUpdate = DebugFlags.SEND_UPDATES_WHEN_NO_COMM ||
737 result.type != BountyResultType.END_OTHER ||
738 Global.getSector().getIntelManager().isPlayerInRangeOfCommRelay();
739 sendUpdate = true;
740 if (sendUpdate) {
742 }
743
746 }
747 }
748
749 public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
750
751 }
752
753 public boolean runWhilePaused() {
754 return false;
755 }
756 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
757
758 Color h = Misc.getHighlightColor();
759 Color g = Misc.getGrayColor();
760 float pad = 3f;
761 float opad = 10f;
762
763 float initPad = pad;
764 if (mode == ListInfoMode.IN_DESC) initPad = opad;
765
766 Color tc = getBulletColorForMode(mode);
767
768 bullet(info);
769 boolean isUpdate = getListInfoParam() != null;
770
772 info.addPara("Agreement broken", initPad, tc,
773 Misc.getNegativeHighlightColor(), "Agreement broken");
774 initPad = 0f;
775 } else if (getListInfoParam() == DEAL_CANCELLED_PARAM) {
776 info.addPara("Agreement dissolved", tc, initPad);
777 initPad = 0f;
778 } else if (mode == ListInfoMode.INTEL || getListInfoParam() == DEAL_MADE_PARAM) {
780 info.addPara("Agreement made with base commander", initPad, tc,
781 Misc.getPositiveHighlightColor(), "Agreement");
782 initPad = 0f;
783 }
784 }
785
786 if (bountyData != null && result == null) {
788 if (isUpdate || mode != ListInfoMode.IN_DESC) {
789 FactionAPI faction = bountyData.bountyFaction;
790 info.addPara("Bounty faction: " + faction.getDisplayName(), initPad, tc,
791 faction.getBaseUIColor(), faction.getDisplayName());
792 initPad = 0f;
793 }
794 info.addPara("%s reward", initPad, tc, h, Misc.getDGSCredits(bountyData.baseBounty));
795 addDays(info, "remaining", bountyData.bountyDuration - bountyData.bountyElapsedDays, tc);
796 }
797 }
798
799 if (result != null && bountyData != null) {
800 switch (result.type) {
801 case END_PLAYER_BOUNTY:
802 info.addPara("%s received", initPad, tc, h, Misc.getDGSCredits(result.payment));
803 CoreReputationPlugin.addAdjustmentMessage(result.rep.delta, bountyData.bountyFaction, null,
804 null, null, info, tc, isUpdate, 0f);
805 break;
806 case END_TIME:
807 break;
808 case END_OTHER:
809 break;
810
811 }
812 }
813
814 unindent(info);
815 }
816
817 @Override
818 public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
819 Color c = getTitleColor(mode);
820 info.addPara(getName(), c, 0f);
821 addBulletPoints(info, mode);
822 }
823
824 public String getSortString() {
825 String base = Misc.ucFirst(getFactionForUIColors().getPersonNamePrefix());
826 return base + " Base";
827 //return "Pirate Base";
828 }
829
830 public String getName() {
831 String base = Misc.ucFirst(getFactionForUIColors().getPersonNamePrefix());
832
833 if (getListInfoParam() == bountyData && bountyData != null) {
834 return base + " Base - Bounty Posted";
835 } else if (getListInfoParam() == BOUNTY_EXPIRED_PARAM) {
836 return base + " Base - Bounty Expired";
837 }
838
839 if (result != null) {
840 if (result.type == BountyResultType.END_PLAYER_BOUNTY) {
841 return base + " Base - Bounty Completed";
842 } else if (result.type == BountyResultType.END_PLAYER_NO_REWARD) {
843 return base + " Base - Destroyed";
844 }
845 }
846
847 String name = market.getName();
848 if (isEnding()) {
849 //return "Base Abandoned - " + name;
850 return base + " Base - Abandoned";
851 }
853 return base + " Base - Discovered";
854 }
855 if (entity.isDiscoverable()) {
856 return base + " Base - Exact Location Unknown";
857 }
858 return base + " Base - " + name;
859 }
860
861 @Override
862 public FactionAPI getFactionForUIColors() {
863 return market.getFaction();
864 }
865
866 public String getSmallDescriptionTitle() {
867 return getName();
868 }
869
870 public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
871
872 Color h = Misc.getHighlightColor();
873 Color g = Misc.getGrayColor();
874 Color tc = Misc.getTextColor();
875 float pad = 3f;
876 float opad = 10f;
877
878 //info.addPara(getName(), c, 0f);
879
880 //info.addSectionHeading(getName(), Alignment.MID, 0f);
881
882 FactionAPI faction = market.getFaction();
883
884 info.addImage(faction.getLogo(), width, 128, opad);
885
886 String has = faction.getDisplayNameHasOrHave();
887
888 info.addPara(Misc.ucFirst(faction.getDisplayNameWithArticle()) + " " + has +
889 " established a base in the " +
890 market.getContainingLocation().getNameWithLowercaseType() + ". " +
891 "The base serves as a staging ground for raids against nearby colonies.",
892 opad, faction.getBaseUIColor(), faction.getDisplayNameWithArticleWithoutArticle());
893
894 if (!entity.isDiscoverable()) {
895 switch (tier) {
896 case TIER_1_1MODULE:
897 info.addPara("It has limited defensive capabilities " +
898 "and is protected by a few fleets.", opad);
899 break;
900 case TIER_2_1MODULE:
901 info.addPara("It has limited defensive capabilities " +
902 "and is protected by a small number of fleets.", opad);
903 break;
904 case TIER_3_2MODULE:
905 info.addPara("It has fairly well-developed defensive capabilities " +
906 "and is protected by a considerable number of fleets.", opad);
907 break;
908 case TIER_4_3MODULE:
909 info.addPara("It has very well-developed defensive capabilities " +
910 "and is protected by a large number of fleets.", opad);
911 break;
912 case TIER_5_3MODULE:
913 info.addPara("It has very well-developed defensive capabilities " +
914 "and is protected by a large number of fleets. Both the " +
915 "base and the fleets have elite-level equipment, at least by pirate standards.", opad);
916 break;
917
918 }
919 } else {
920 info.addPara("You have not yet discovered the exact location or capabilities of this base.", opad);
921 }
922
923 boolean deal = playerHasDealWithBaseCommander();
924 if (deal) {
925// FactionAPI pf = Global.getSector().getPlayerFaction();
926// info.addSectionHeading("Protection payments",
927// pf.getBaseUIColor(), pf.getDarkUIColor(), Alignment.MID, opad);
928 float feeFraction = Global.getSettings().getFloat("pirateProtectionPaymentFraction");
929 String fee = Misc.getDGSCredits(HA_CMD.computePirateProtectionPaymentPerMonth(this));
930 LabelAPI label = info.addPara("You have an %s with "
931 + "the base commander, and fleets from this base do not, as a rule, "
932 + "harass your colonies or shipping. The protection payment is %s of "
933 + "the gross income of all of your affected colonies, which "
934 + "amounts to %s per month at their current level of income.", opad,
935 Misc.getPositiveHighlightColor(),
936 "agreement",
937 "" + (int)Math.round(feeFraction * 100f) + "%", fee
938 );
939 label.setHighlightColors(Misc.getPositiveHighlightColor(), h, h);
940 label.setHighlight("agreement", "" + (int)Math.round(feeFraction * 100f) + "%", fee);
941 }
942
943
944 info.addSectionHeading("Recent events",
945 faction.getBaseUIColor(), faction.getDarkUIColor(), Alignment.MID, opad);
946
947 if (target != null && !getAffectedMarkets(target).isEmpty() && !isEnding()) {
948 info.addPara("Pirates operating from this base have been targeting the " +
949 target.getNameWithLowercaseType() + ".", opad);
950 }
951
952 if (bountyData != null) {
953 info.addPara(Misc.ucFirst(bountyData.bountyFaction.getDisplayNameWithArticle()) + " " +
954 bountyData.bountyFaction.getDisplayNameHasOrHave() +
955 " posted a bounty for the destruction of this base.",
956 opad, bountyData.bountyFaction.getBaseUIColor(),
957 bountyData.bountyFaction.getDisplayNameWithArticleWithoutArticle());
958
959 if (result != null && result.type == BountyResultType.END_PLAYER_BOUNTY) {
960 info.addPara("You have successfully completed this bounty.", opad);
961 }
962
963 addBulletPoints(info, ListInfoMode.IN_DESC);
964 }
965
966 if (result != null) {
967 if (result.type == BountyResultType.END_PLAYER_NO_REWARD) {
968 info.addPara("You have destroyed this base.", opad);
969 } else if (result.type == BountyResultType.END_OTHER) {
970 info.addPara("It is rumored that this base is no longer operational.", opad);
971 }
972 }
973
974 }
975
976 public String getIcon() {
977 return Global.getSettings().getSpriteName("intel", "pirate_base");
978 //return market.getFaction().getCrest();
979 }
980
981 public Set<String> getIntelTags(SectorMapAPI map) {
982 Set<String> tags = super.getIntelTags(map);
983 if (bountyData != null) {
984 tags.add(Tags.INTEL_BOUNTY);
985 }
986 tags.add(Tags.INTEL_EXPLORATION);
987
988 // old way, when pirate activity applied to player colonies
989 // not needed anymore but shouldn't hurt
990 // aaand, needed again since HA is now "Colony Crises" and works differently
991 if (target != null && !Misc.getMarketsInLocation(target, Factions.PLAYER).isEmpty()) {
992 tags.add(Tags.INTEL_COLONIES);
993 }
994
995 // new hostile activity
996 if (!PirateBasePirateActivityCause2.getColoniesAffectedBy(this).isEmpty()) {
997 tags.add(Tags.INTEL_COLONIES);
998 }
999
1000 tags.add(market.getFactionId());
1001 if (bountyData != null) {
1002 tags.add(bountyData.bountyFaction.getId());
1003 }
1004 return tags;
1005 }
1006
1007 @Override
1008 public SectorEntityToken getMapLocation(SectorMapAPI map) {
1009 //return market.getPrimaryEntity();
1010 if (market.getPrimaryEntity().isDiscoverable()) {
1011 return system.getCenter();
1012 }
1013 return market.getPrimaryEntity();
1014 }
1015
1016
1017
1018
1019
1020 protected String generateName() {
1021 MarkovNames.loadIfNeeded();
1022
1023 MarkovNameResult gen = null;
1024 for (int i = 0; i < 10; i++) {
1025 gen = MarkovNames.generate(null);
1026 if (gen != null) {
1027 String test = gen.name;
1028 if (test.toLowerCase().startsWith("the ")) continue;
1029 String p = pickPostfix();
1030 if (p != null && !p.isEmpty()) {
1031 test += " " + p;
1032 }
1033 if (test.length() > 22) continue;
1034
1035 return test;
1036 }
1037 }
1038 return null;
1039 }
1040
1041 protected String pickPostfix() {
1042 WeightedRandomPicker<String> post = new WeightedRandomPicker<String>();
1043 post.add("Asylum");
1044 post.add("Astrome");
1045 post.add("Barrage");
1046 post.add("Briganderie");
1047 post.add("Camp");
1048 post.add("Cover");
1049 post.add("Citadel");
1050 post.add("Den");
1051 post.add("Donjon");
1052 post.add("Depot");
1053 post.add("Fort");
1054 post.add("Freehold");
1055 post.add("Freeport");
1056 post.add("Freehaven");
1057 post.add("Free Orbit");
1058 post.add("Galastat");
1059 post.add("Garrison");
1060 post.add("Harbor");
1061 post.add("Haven");
1062 post.add("Headquarters");
1063 post.add("Hideout");
1064 post.add("Hideaway");
1065 post.add("Hold");
1066 post.add("Lair");
1067 post.add("Locus");
1068 post.add("Main");
1069 post.add("Mine Depot");
1070 post.add("Nexus");
1071 post.add("Orbit");
1072 post.add("Port");
1073 post.add("Post");
1074 post.add("Presidio");
1075 post.add("Prison");
1076 post.add("Platform");
1077 post.add("Corsairie");
1078 post.add("Refuge");
1079 post.add("Retreat");
1080 post.add("Refinery");
1081 post.add("Shadow");
1082 post.add("Safehold");
1083 post.add("Starhold");
1084 post.add("Starport");
1085 post.add("Stardock");
1086 post.add("Sanctuary");
1087 post.add("Station");
1088 post.add("Spacedock");
1089 post.add("Tertiary");
1090 post.add("Terminus");
1091 post.add("Terminal");
1092 post.add("Tortuga");
1093 post.add("Ward");
1094 post.add("Warsat");
1095 return post.pick();
1096 }
1097
1098 public void commodityUpdated(String commodityId) {
1099 CommodityOnMarketAPI com = market.getCommodityData(commodityId);
1100 int curr = 0;
1101 String modId = market.getId();
1102 StatMod mod = com.getAvailableStat().getFlatStatMod(modId);
1103 if (mod != null) {
1104 curr = Math.round(mod.value);
1105 }
1106
1107 int avWithoutPenalties = (int) Math.round(com.getAvailableStat().getBaseValue());
1108 for (StatMod m : com.getAvailableStat().getFlatMods().values()) {
1109 if (m.value < 0) continue;
1110 avWithoutPenalties += (int) Math.round(m.value);
1111 }
1112
1113 int a = com.getAvailable() - curr;
1114 a = avWithoutPenalties - curr;
1115 int d = com.getMaxDemand();
1116 if (d > a) {
1117 //int supply = Math.max(1, d - a - 1);
1118 int supply = Math.max(1, d - a);
1119 com.getAvailableStat().modifyFlat(modId, supply, "Brought in by raiders");
1120 }
1121 }
1122
1123 public void economyUpdated() {
1124
1125 float fleetSizeBonus = 1f;
1126 float qualityBonus = 0f;
1127 int light = 0;
1128 int medium = 0;
1129 int heavy = 0;
1130
1131 switch (tier) {
1132 case TIER_1_1MODULE:
1133 qualityBonus = 0f;
1134 fleetSizeBonus = 0.2f;
1135 break;
1136 case TIER_2_1MODULE:
1137 qualityBonus = 0.2f;
1138 fleetSizeBonus = 0.3f;
1139 light = 2;
1140 break;
1141 case TIER_3_2MODULE:
1142 qualityBonus = 0.3f;
1143 fleetSizeBonus = 0.4f;
1144 light = 2;
1145 medium = 1;
1146 break;
1147 case TIER_4_3MODULE:
1148 qualityBonus = 0.4f;
1149 fleetSizeBonus = 0.5f;
1150 light = 2;
1151 medium = 2;
1152 break;
1153 case TIER_5_3MODULE:
1154 qualityBonus = 0.5f;
1155 fleetSizeBonus = 0.75f;
1156 light = 2;
1157 medium = 2;
1158 heavy = 2;
1159 break;
1160 }
1161
1162 market.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).
1163 modifyFlatAlways(market.getId(), qualityBonus,
1164 "Development level");
1165
1166 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).modifyFlatAlways(market.getId(),
1167 fleetSizeBonus,
1168 "Development level");
1169
1170
1171 String modId = market.getId();
1172 market.getStats().getDynamic().getMod(Stats.PATROL_NUM_LIGHT_MOD).modifyFlat(modId, light);
1173 market.getStats().getDynamic().getMod(Stats.PATROL_NUM_MEDIUM_MOD).modifyFlat(modId, medium);
1174 market.getStats().getDynamic().getMod(Stats.PATROL_NUM_HEAVY_MOD).modifyFlat(modId, heavy);
1175 }
1176
1177 public boolean isEconomyListenerExpired() {
1178 return isEnded();
1179 }
1180
1181 public MarketAPI getMarket() {
1182 return market;
1183 }
1184
1185
1186 protected void setBounty() {
1187 bountyData = new BaseBountyData();
1188 float base = 100000f;
1189 switch (tier) {
1190 case TIER_1_1MODULE:
1191 base = Global.getSettings().getFloat("pirateBaseBounty1");
1192 bountyData.repChange = 0.02f;
1193 break;
1194 case TIER_2_1MODULE:
1195 base = Global.getSettings().getFloat("pirateBaseBounty2");
1196 bountyData.repChange = 0.05f;
1197 break;
1198 case TIER_3_2MODULE:
1199 base = Global.getSettings().getFloat("pirateBaseBounty3");
1200 bountyData.repChange = 0.06f;
1201 break;
1202 case TIER_4_3MODULE:
1203 base = Global.getSettings().getFloat("pirateBaseBounty4");
1204 bountyData.repChange = 0.07f;
1205 break;
1206 case TIER_5_3MODULE:
1207 base = Global.getSettings().getFloat("pirateBaseBounty5");
1208 bountyData.repChange = 0.1f;
1209 break;
1210 }
1211
1212 bountyData.baseBounty = base * (0.9f + (float) Math.random() * 0.2f);
1213
1214 bountyData.baseBounty = (int)(bountyData.baseBounty / 10000) * 10000;
1215
1216
1217 WeightedRandomPicker<FactionAPI> picker = new WeightedRandomPicker<FactionAPI>();
1218 for (MarketAPI curr : Global.getSector().getEconomy().getMarkets(target)) {
1219 if (curr.getFaction().isPlayerFaction()) continue;
1220 if (curr.getFaction().getCustom().optBoolean(Factions.CUSTOM_POSTS_NO_BOUNTIES)) continue;
1221
1222 if (affectsMarket(curr)) {
1223 picker.add(curr.getFaction(), (float) Math.pow(2f, curr.getSize()));
1224 }
1225 }
1226
1227 FactionAPI faction = picker.pick();
1228 if (faction == null) {
1229 bountyData = null;
1230 return;
1231 }
1232
1233 bountyData.bountyFaction = faction;
1234 bountyData.bountyDuration = 180f;
1235 bountyData.bountyElapsedDays = 0f;
1236
1237 Misc.makeImportant(entity, "baseBounty");
1238
1239 sentBountyUpdate = false;
1240// makeKnown();
1241// sendUpdateIfPlayerHasIntel(bountyData, false);
1242 }
1243
1244 protected boolean sentBountyUpdate = false;
1245 protected void endBounty() {
1247 bountyData = null;
1248 sentBountyUpdate = false;
1249 Misc.makeUnimportant(entity, "baseBounty");
1250 }
1251
1252 protected int monthsWithSameTarget = 0;
1253 protected int monthsAtCurrentTier = 0;
1254 protected StarSystemAPI target = null;
1255 public void updateTarget() {
1256 StarSystemAPI newTarget = pickTarget();
1257 if (newTarget == target) return;
1258
1259 clearTarget();
1260
1261 target = newTarget;
1263
1264 if (target != null) {
1265// for (MarketAPI curr : Global.getSector().getEconomy().getMarkets(system)) {
1266// curr.addCondition(Conditions.PIRATE_ACTIVITY, this);
1267// }
1268 new PirateActivityIntel(target, this);
1269// PirateActivityIntel intel = new PirateActivityIntel(target, this);
1270// if (!isPlayerVisible()) {
1271// Global.getSector().getIntelManager().queueIntel(intel);
1272// } else {
1273// Global.getSector().getIntelManager().addIntel(intel);
1274// }
1275 }
1276 }
1277
1278 public StarSystemAPI getTarget() {
1279 return target;
1280 }
1281
1282 protected void clearTarget() {
1283 if (target != null) {
1284 target = null;
1286 }
1287 }
1288
1289 public List<MarketAPI> getAffectedMarkets(StarSystemAPI system) {
1290 List<MarketAPI> result = new ArrayList<MarketAPI>();
1291 for (MarketAPI curr : Global.getSector().getEconomy().getMarkets(system)) {
1292 if (!affectsMarket(curr)) continue;
1293 result.add(curr);
1294 }
1295 return result;
1296 }
1297
1298 public boolean affectsMarket(MarketAPI market) {
1299 if (market.isHidden()) return false;
1300 if (market.getFaction() == this.market.getFaction()) return false;
1301
1302 // player colonies affected by "Hostile Activity" instead
1303 // not anymore
1304 //if (market.getFaction().isPlayerFaction()) return false;
1305
1306 if (market.getFaction().isPlayerFaction() && playerHasDealWithBaseCommander()) {
1307 return false;
1308 }
1309
1310 return true;
1311 }
1312
1313
1314 public void setTargetPlayerColoniesOnly(boolean targetPlayerColonies) {
1315 this.targetPlayerColoniesOnly = targetPlayerColonies;
1316 }
1319 }
1320 public StarSystemAPI getForceTarget() {
1321 return forceTarget;
1322 }
1323 public void setForceTarget(StarSystemAPI forceTarget) {
1324 this.forceTarget = forceTarget;
1325 }
1326 protected boolean targetPlayerColoniesOnly = false;
1327 protected StarSystemAPI forceTarget = null;
1328
1329 protected StarSystemAPI pickTarget() {
1330
1331 WeightedRandomPicker<StarSystemAPI> picker = new WeightedRandomPicker<StarSystemAPI>();
1332 boolean forceTargetIsValid = false;
1333 for (StarSystemAPI system : Global.getSector().getEconomy().getStarSystemsWithMarkets()) {
1334 float score = 0f;
1335 for (MarketAPI curr : Global.getSector().getEconomy().getMarkets(system)) {
1336 if (!affectsMarket(curr)) continue;
1337 if (targetPlayerColoniesOnly && !curr.getFaction().isPlayerFaction()) continue;
1338
1339 if (system == forceTarget) {
1340 forceTargetIsValid = true;
1341 }
1342 if (curr.hasCondition(Conditions.PIRATE_ACTIVITY)) continue;
1343
1344// if (curr.getId().equals("jangala")) {
1345// score += 10000000f;
1346// }
1347
1348 float w = curr.getSize();
1349
1350 //float dist = Misc.getDistance(curr.getPrimaryEntity(), market.getPrimaryEntity());
1351 float dist = Misc.getDistanceLY(curr.getLocationInHyperspace(), market.getLocationInHyperspace());
1352
1353 float mult = 1f - Math.max(0f, dist - 10f) / 10f;
1354 if (mult < 0.1f) mult = 0.1f;
1355 if (mult > 1) mult = 1;
1356
1357 if (!targetPlayerColoniesOnly && curr.getFaction().isPlayerFaction()) {
1358 if (dist > 15f) continue;
1359 }
1360
1361 score += w * mult;
1362
1363 }
1364 picker.add(system, score);
1365 }
1366
1367 if (forceTargetIsValid) {
1368 return forceTarget;
1369 }
1370
1371 return picker.pick();
1372 }
1373
1374 public List<ArrowData> getArrowData(SectorMapAPI map) {
1375 if (target == null|| target == entity.getContainingLocation()) return null;
1376
1377 List<ArrowData> result = new ArrayList<ArrowData>();
1378
1379 SectorEntityToken entityFrom = entity;
1380 if (map != null) {
1381 SectorEntityToken iconEntity = map.getIntelIconEntity(this);
1382 if (iconEntity != null) {
1383 entityFrom = iconEntity;
1384 }
1385 }
1386
1387 ArrowData arrow = new ArrowData(entityFrom, target.getCenter());
1388 arrow.color = getFactionForUIColors().getBaseUIColor();
1389 result.add(arrow);
1390
1391 return result;
1392 }
1393
1395 switch (tier) {
1396 case TIER_1_1MODULE: return 0.1f;
1397 case TIER_2_1MODULE: return 0.2f;
1398 case TIER_3_2MODULE: return 0.3f;
1399 case TIER_4_3MODULE: return 0.4f;
1400 case TIER_5_3MODULE: return 0.5f;
1401 }
1402 return 0f;
1403 }
1404
1405 public float getStabilityPenalty() {
1406 switch (tier) {
1407 case TIER_1_1MODULE: return 1f;
1408 case TIER_2_1MODULE: return 1f;
1409 case TIER_3_2MODULE: return 2f;
1410 case TIER_4_3MODULE: return 2f;
1411 case TIER_5_3MODULE: return 3f;
1412 }
1413 return 0f;
1414 }
1415
1416 public PirateBaseTier getTier() {
1417 return tier;
1418 }
1419
1420 public SectorEntityToken getEntity() {
1421 return entity;
1422 }
1423 public PersonAPI getBaseCommander() {
1424 return baseCommander;
1425 }
1426 public void setBaseCommander(PersonAPI baseCommander) {
1427 this.baseCommander = baseCommander;
1428 }
1429
1430}
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
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 PirateBaseIntel getIntelFor(SectorEntityToken station)
void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle)
void createSmallDescription(TooltipMakerAPI info, float width, float height)
void notifyRaidEnded(RaidIntel raid, RaidStageStatus status)
PirateBaseIntel(StarSystemAPI system, String factionId, PirateBaseTier tier)
static PirateBaseIntel getIntelFor(StarSystemAPI system)
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode)
void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode)
void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
MarketAPI createMarket(String id, String name, int size)
String getSpriteName(String category, String id)