Starsector API
Loading...
Searching...
No Matches
LionsGuardHQ.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.econ.impl;
2
3import java.util.Random;
4
5import com.fs.starfarer.api.Global;
6import com.fs.starfarer.api.campaign.BattleAPI;
7import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
8import com.fs.starfarer.api.campaign.CampaignFleetAPI;
9import com.fs.starfarer.api.campaign.FactionAPI.ShipPickMode;
10import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
11import com.fs.starfarer.api.campaign.econ.Industry;
12import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
13import com.fs.starfarer.api.campaign.rules.MemoryAPI;
14import com.fs.starfarer.api.fleet.FleetMemberAPI;
15import com.fs.starfarer.api.impl.campaign.econ.impl.MilitaryBase.PatrolFleetData;
16import com.fs.starfarer.api.impl.campaign.fleets.FleetFactory.PatrolType;
17import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
18import com.fs.starfarer.api.impl.campaign.fleets.FleetParamsV3;
19import com.fs.starfarer.api.impl.campaign.fleets.PatrolAssignmentAIV4;
20import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
21import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
22import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
23import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteFleetSpawner;
24import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
25import com.fs.starfarer.api.impl.campaign.ids.Commodities;
26import com.fs.starfarer.api.impl.campaign.ids.Factions;
27import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
28import com.fs.starfarer.api.impl.campaign.ids.Ranks;
29import com.fs.starfarer.api.impl.campaign.ids.Stats;
30import com.fs.starfarer.api.impl.campaign.ids.Tags;
31import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.RaidDangerLevel;
32import com.fs.starfarer.api.loading.VariantSource;
33import com.fs.starfarer.api.ui.TooltipMakerAPI;
34import com.fs.starfarer.api.util.IntervalUtil;
35import com.fs.starfarer.api.util.Misc;
36import com.fs.starfarer.api.util.Pair;
37import com.fs.starfarer.api.util.WeightedRandomPicker;
38
39
40public class LionsGuardHQ extends BaseIndustry implements RouteFleetSpawner, FleetEventListener {
41
42 @Override
43 public boolean isHidden() {
44 return !market.getFactionId().equals(Factions.DIKTAT);
45 }
46
47 @Override
48 public boolean isFunctional() {
49 return super.isFunctional() && market.getFactionId().equals(Factions.DIKTAT);
50 }
51
52 public void apply() {
53 super.apply(true);
54
55 int size = market.getSize();
56
57 demand(Commodities.SUPPLIES, size - 1);
58 demand(Commodities.FUEL, size - 1);
59 demand(Commodities.SHIPS, size - 1);
60
61 supply(Commodities.CREW, size);
62
63 demand(Commodities.HAND_WEAPONS, size);
64 supply(Commodities.MARINES, size);
65
66 Pair<String, Integer> deficit = getMaxDeficit(Commodities.HAND_WEAPONS);
67 applyDeficitToProduction(1, deficit, Commodities.MARINES);
68
70
71 MemoryAPI memory = market.getMemoryWithoutUpdate();
72 Misc.setFlagWithReason(memory, MemFlags.MARKET_PATROL, getModId(), true, -1);
73 Misc.setFlagWithReason(memory, MemFlags.MARKET_MILITARY, getModId(), true, -1);
74
75 if (!isFunctional()) {
76 supply.clear();
77 unapply();
78 }
79
80 }
81
82 @Override
83 public void unapply() {
84 super.unapply();
85
86 MemoryAPI memory = market.getMemoryWithoutUpdate();
87 Misc.setFlagWithReason(memory, MemFlags.MARKET_PATROL, getModId(), false, -1);
88 Misc.setFlagWithReason(memory, MemFlags.MARKET_MILITARY, getModId(), false, -1);
89
91 }
92
93 protected boolean hasPostDemandSection(boolean hasDemand, IndustryTooltipMode mode) {
94 return mode != IndustryTooltipMode.NORMAL || isFunctional();
95 }
96
97 @Override
98 protected void addPostDemandSection(TooltipMakerAPI tooltip, boolean hasDemand, IndustryTooltipMode mode) {
99 if (mode != IndustryTooltipMode.NORMAL || isFunctional()) {
100 addStabilityPostDemandSection(tooltip, hasDemand, mode);
101 }
102 }
103
104 @Override
105 protected int getBaseStabilityMod() {
106 return 2;
107 }
108
109 public String getNameForModifier() {
110 if (getSpec().getName().contains("HQ")) {
111 return getSpec().getName();
112 }
113 return Misc.ucFirst(getSpec().getName());
114 }
115
116 @Override
117 protected Pair<String, Integer> getStabilityAffectingDeficit() {
118 return getMaxDeficit(Commodities.SUPPLIES, Commodities.FUEL, Commodities.SHIPS, Commodities.HAND_WEAPONS);
119 }
120
121 @Override
122 public String getCurrentImage() {
123 return super.getCurrentImage();
124 }
125
126
127 public boolean isDemandLegal(CommodityOnMarketAPI com) {
128 return true;
129 }
130
131 public boolean isSupplyLegal(CommodityOnMarketAPI com) {
132 return true;
133 }
134
135 protected IntervalUtil tracker = new IntervalUtil(Global.getSettings().getFloat("averagePatrolSpawnInterval") * 0.7f,
136 Global.getSettings().getFloat("averagePatrolSpawnInterval") * 1.3f);
137
138 protected float returningPatrolValue = 0f;
139
140 @Override
141 protected void buildingFinished() {
142 super.buildingFinished();
143
144 tracker.forceIntervalElapsed();
145 }
146
147 @Override
148 protected void upgradeFinished(Industry previous) {
149 super.upgradeFinished(previous);
150
151 tracker.forceIntervalElapsed();
152 }
153
154 @Override
155 public void advance(float amount) {
156 super.advance(amount);
157
158 if (Global.getSector().getEconomy().isSimMode()) return;
159
160 if (!isFunctional()) return;
161
162 float days = Global.getSector().getClock().convertToDays(amount);
163
164 float spawnRate = 1f;
165 float rateMult = market.getStats().getDynamic().getStat(Stats.COMBAT_FLEET_SPAWN_RATE_MULT).getModifiedValue();
166 spawnRate *= rateMult;
167
168
169 float extraTime = 0f;
170 if (returningPatrolValue > 0) {
171 // apply "returned patrols" to spawn rate, at a maximum rate of 1 interval per day
172 float interval = tracker.getIntervalDuration();
173 extraTime = interval * days;
174 returningPatrolValue -= days;
176 }
177 tracker.advance(days * spawnRate + extraTime);
178
179 //tracker.advance(days * spawnRate * 100f);
180
181 if (tracker.intervalElapsed()) {
182 String sid = getRouteSourceId();
183
184 int light = getCount(PatrolType.FAST);
185 int medium = getCount(PatrolType.COMBAT);
186 int heavy = getCount(PatrolType.HEAVY);
187
188 int maxLight = 2;
189 int maxMedium = 2;
190 int maxHeavy = 2;
191
192 WeightedRandomPicker<PatrolType> picker = new WeightedRandomPicker<PatrolType>();
193 picker.add(PatrolType.HEAVY, maxHeavy - heavy);
194 picker.add(PatrolType.COMBAT, maxMedium - medium);
195 picker.add(PatrolType.FAST, maxLight - light);
196
197 if (picker.isEmpty()) return;
198
199 PatrolType type = picker.pick();
200 PatrolFleetData custom = new PatrolFleetData(type);
201
202 OptionalFleetData extra = new OptionalFleetData(market);
203 extra.fleetType = type.getFleetType();
204
205 RouteData route = RouteManager.getInstance().addRoute(sid, market, Misc.genRandomSeed(), extra, this, custom);
206 float patrolDays = 35f + (float) Math.random() * 10f;
207
208 route.addSegment(new RouteSegment(patrolDays, market.getPrimaryEntity()));
209 }
210 }
211
212 public void reportAboutToBeDespawnedByRouteManager(RouteData route) {
213 }
214
215 public boolean shouldRepeat(RouteData route) {
216 return false;
217 }
218
219 public int getCount(PatrolType ... types) {
220 int count = 0;
221 for (RouteData data : RouteManager.getInstance().getRoutesForSource(getRouteSourceId())) {
222 if (data.getCustom() instanceof PatrolFleetData) {
223 PatrolFleetData custom = (PatrolFleetData) data.getCustom();
224 for (PatrolType type : types) {
225 if (type == custom.type) {
226 count++;
227 break;
228 }
229 }
230 }
231 }
232 return count;
233 }
234
235 public int getMaxPatrols(PatrolType type) {
236 if (type == PatrolType.FAST) {
237 return (int) market.getStats().getDynamic().getMod(Stats.PATROL_NUM_LIGHT_MOD).computeEffective(0);
238 }
239 if (type == PatrolType.COMBAT) {
240 return (int) market.getStats().getDynamic().getMod(Stats.PATROL_NUM_MEDIUM_MOD).computeEffective(0);
241 }
242 if (type == PatrolType.HEAVY) {
243 return (int) market.getStats().getDynamic().getMod(Stats.PATROL_NUM_HEAVY_MOD).computeEffective(0);
244 }
245 return 0;
246 }
247
248 public boolean shouldCancelRouteAfterDelayCheck(RouteData route) {
249 return false;
250 }
251
252 public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
253
254 }
255
256 public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
257 if (!isFunctional()) return;
258
259 if (reason == FleetDespawnReason.REACHED_DESTINATION) {
260 RouteData route = RouteManager.getInstance().getRoute(getRouteSourceId(), fleet);
261 if (route.getCustom() instanceof PatrolFleetData) {
262 PatrolFleetData custom = (PatrolFleetData) route.getCustom();
263 if (custom.spawnFP > 0) {
264 float fraction = fleet.getFleetPoints() / custom.spawnFP;
265 returningPatrolValue += fraction;
266 }
267 }
268 }
269 }
270
271 public CampaignFleetAPI spawnFleet(RouteData route) {
272
273 PatrolFleetData custom = (PatrolFleetData) route.getCustom();
274 PatrolType type = custom.type;
275
276 Random random = route.getRandom();
277
278 float combat = 0f;
279 float tanker = 0f;
280 float freighter = 0f;
281 String fleetType = type.getFleetType();
282 switch (type) {
283 case FAST:
284 combat = Math.round(3f + (float) random.nextFloat() * 2f) * 5f;
285 break;
286 case COMBAT:
287 combat = Math.round(6f + (float) random.nextFloat() * 3f) * 5f;
288 tanker = Math.round((float) random.nextFloat()) * 5f;
289 break;
290 case HEAVY:
291 combat = Math.round(10f + (float) random.nextFloat() * 5f) * 5f;
292 tanker = Math.round((float) random.nextFloat()) * 10f;
293 freighter = Math.round((float) random.nextFloat()) * 10f;
294 break;
295 }
296
297 FleetParamsV3 params = new FleetParamsV3(
298 market,
299 null, // loc in hyper; don't need if have market
300 Factions.LIONS_GUARD,
301 route.getQualityOverride(), // quality override
302 fleetType,
303 combat, // combatPts
304 freighter, // freighterPts
305 tanker, // tankerPts
306 0f, // transportPts
307 0f, // linerPts
308 0f, // utilityPts
309 0f // qualityMod - since the Lion's Guard is in a different-faction market, counter that penalty
310 );
311 params.timestamp = route.getTimestamp();
312 params.random = random;
313 params.modeOverride = Misc.getShipPickMode(market);
314 params.modeOverride = ShipPickMode.PRIORITY_THEN_ALL;
315 CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params);
316
317 if (fleet == null || fleet.isEmpty()) return null;
318
319 fleet.setFaction(market.getFactionId(), true);
320 fleet.setNoFactionInName(true);
321
322 fleet.addEventListener(this);
323
324// PatrolAssignmentAIV2 ai = new PatrolAssignmentAIV2(fleet, custom);
325// fleet.addScript(ai);
326
327 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_PATROL_FLEET, true);
328 fleet.getMemoryWithoutUpdate().set(MemFlags.FLEET_IGNORES_OTHER_FLEETS, true, 0.3f);
329
330 if (type == PatrolType.FAST || type == PatrolType.COMBAT) {
331 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_CUSTOMS_INSPECTOR, true);
332 }
333
334 String postId = Ranks.POST_PATROL_COMMANDER;
335 String rankId = Ranks.SPACE_COMMANDER;
336 switch (type) {
337 case FAST:
338 rankId = Ranks.SPACE_LIEUTENANT;
339 break;
340 case COMBAT:
341 rankId = Ranks.SPACE_COMMANDER;
342 break;
343 case HEAVY:
344 rankId = Ranks.SPACE_CAPTAIN;
345 break;
346 }
347
348 fleet.getCommander().setPostId(postId);
349 fleet.getCommander().setRankId(rankId);
350
351 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
352 if (member.isCapital()) {
353 member.setVariant(member.getVariant().clone(), false, false);
354 member.getVariant().setSource(VariantSource.REFIT);
355 member.getVariant().addTag(Tags.TAG_NO_AUTOFIT);
356 member.getVariant().addTag(Tags.VARIANT_CONSISTENT_WEAPON_DROPS);
357 }
358 }
359
360 market.getContainingLocation().addEntity(fleet);
361 fleet.setFacing((float) Math.random() * 360f);
362 // this will get overridden by the patrol assignment AI, depending on route-time elapsed etc
363 fleet.setLocation(market.getPrimaryEntity().getLocation().x, market.getPrimaryEntity().getLocation().y);
364
365 fleet.addScript(new PatrolAssignmentAIV4(fleet, route));
366
367 //market.getContainingLocation().addEntity(fleet);
368 //fleet.setLocation(market.getPrimaryEntity().getLocation().x, market.getPrimaryEntity().getLocation().y);
369
370 if (custom.spawnFP <= 0) {
371 custom.spawnFP = fleet.getFleetPoints();
372 }
373
374 return fleet;
375 }
376
377 public String getRouteSourceId() {
378 return getMarket().getId() + "_" + "lionsguard";
379 }
380
381 @Override
382 public boolean isAvailableToBuild() {
383 return false;
384 }
385
386 public boolean showWhenUnavailable() {
387 return false;
388 }
389
390 @Override
391 public boolean canImprove() {
392 return false;
393 }
394
395 @Override
396 public RaidDangerLevel adjustCommodityDangerLevel(String commodityId, RaidDangerLevel level) {
397 return level.next();
398 }
399
400 @Override
401 public RaidDangerLevel adjustItemDangerLevel(String itemId, String data, RaidDangerLevel level) {
402 return level.next();
403 }
404
405}
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
Map< String, MutableCommodityQuantity > supply
void addStabilityPostDemandSection(TooltipMakerAPI tooltip, boolean hasDemand, IndustryTooltipMode mode)
Map< String, MutableCommodityQuantity > demand
Pair< String, Integer > getMaxDeficit(String ... commodityIds)
void applyDeficitToProduction(int index, Pair< String, Integer > deficit, String ... commodities)
RaidDangerLevel adjustCommodityDangerLevel(String commodityId, RaidDangerLevel level)
RaidDangerLevel adjustItemDangerLevel(String itemId, String data, RaidDangerLevel level)
void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle)
boolean hasPostDemandSection(boolean hasDemand, IndustryTooltipMode mode)
void addPostDemandSection(TooltipMakerAPI tooltip, boolean hasDemand, IndustryTooltipMode mode)