Starsector API
Loading...
Searching...
No Matches
CoreScript.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign;
2
3import java.util.ArrayList;
4import java.util.HashSet;
5import java.util.List;
6import java.util.Random;
7import java.util.Set;
8
9import java.awt.Color;
10
11import org.apache.log4j.Logger;
12import org.lwjgl.util.vector.Vector2f;
13
14import com.fs.starfarer.api.EveryFrameScript;
15import com.fs.starfarer.api.Global;
16import com.fs.starfarer.api.campaign.BaseCampaignEventListener;
17import com.fs.starfarer.api.campaign.BattleAPI;
18import com.fs.starfarer.api.campaign.CampaignFleetAPI;
19import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
20import com.fs.starfarer.api.campaign.CargoAPI;
21import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
22import com.fs.starfarer.api.campaign.CargoStackAPI;
23import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
24import com.fs.starfarer.api.campaign.FactionAPI;
25import com.fs.starfarer.api.campaign.FactionAPI.ShipPickMode;
26import com.fs.starfarer.api.campaign.FactionProductionAPI;
27import com.fs.starfarer.api.campaign.FactionProductionAPI.ItemInProductionAPI;
28import com.fs.starfarer.api.campaign.FactionProductionAPI.ProductionItemType;
29import com.fs.starfarer.api.campaign.FleetInflater;
30import com.fs.starfarer.api.campaign.JumpPointAPI.JumpDestination;
31import com.fs.starfarer.api.campaign.LocationAPI;
32import com.fs.starfarer.api.campaign.PlanetAPI;
33import com.fs.starfarer.api.campaign.PlayerMarketTransaction;
34import com.fs.starfarer.api.campaign.PlayerMarketTransaction.ShipSaleInfo;
35import com.fs.starfarer.api.campaign.SectorAPI;
36import com.fs.starfarer.api.campaign.SectorEntityToken;
37import com.fs.starfarer.api.campaign.SpecialItemData;
38import com.fs.starfarer.api.campaign.SpecialItemPlugin;
39import com.fs.starfarer.api.campaign.StarSystemAPI;
40import com.fs.starfarer.api.campaign.comm.CommMessageAPI.MessageClickAction;
41import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
42import com.fs.starfarer.api.campaign.econ.Industry;
43import com.fs.starfarer.api.campaign.econ.MarketAPI;
44import com.fs.starfarer.api.campaign.econ.MarketAPI.SurveyLevel;
45import com.fs.starfarer.api.campaign.econ.MonthlyReport;
46import com.fs.starfarer.api.campaign.econ.MonthlyReport.FDNode;
47import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
48import com.fs.starfarer.api.campaign.listeners.ListenerUtil;
49import com.fs.starfarer.api.campaign.rules.MemoryAPI;
50import com.fs.starfarer.api.characters.AdminData;
51import com.fs.starfarer.api.characters.OfficerDataAPI;
52import com.fs.starfarer.api.characters.PersonAPI;
53import com.fs.starfarer.api.characters.SkillsChangeRemoveExcessOPEffect;
54import com.fs.starfarer.api.characters.SkillsChangeRemoveVentsCapsEffect;
55import com.fs.starfarer.api.combat.ShipVariantAPI;
56import com.fs.starfarer.api.fleet.FleetMemberAPI;
57import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictShipData;
58import com.fs.starfarer.api.impl.campaign.econ.impl.InstallableItemEffect;
59import com.fs.starfarer.api.impl.campaign.econ.impl.ItemEffectsRepo;
60import com.fs.starfarer.api.impl.campaign.events.BaseEventPlugin.MarketFilter;
61import com.fs.starfarer.api.impl.campaign.fleets.DefaultFleetInflaterParams;
62import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
63import com.fs.starfarer.api.impl.campaign.ids.Commodities;
64import com.fs.starfarer.api.impl.campaign.ids.Drops;
65import com.fs.starfarer.api.impl.campaign.ids.Entities;
66import com.fs.starfarer.api.impl.campaign.ids.Factions;
67import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
68import com.fs.starfarer.api.impl.campaign.ids.Stats;
69import com.fs.starfarer.api.impl.campaign.ids.Tags;
70import com.fs.starfarer.api.impl.campaign.intel.MessageIntel;
71import com.fs.starfarer.api.impl.campaign.intel.misc.ProductionReportIntel;
72import com.fs.starfarer.api.impl.campaign.intel.misc.ProductionReportIntel.ProductionData;
73import com.fs.starfarer.api.impl.campaign.procgen.SalvageEntityGenDataSpec.DropData;
74import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator;
75import com.fs.starfarer.api.impl.campaign.procgen.themes.SalvageSpecialAssigner;
76import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial;
77import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.PerShipData;
78import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.ShipCondition;
79import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.ShipRecoverySpecialData;
80import com.fs.starfarer.api.impl.campaign.shared.SharedData;
81import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin;
82import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin.DebrisFieldParams;
83import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin.DebrisFieldSource;
84import com.fs.starfarer.api.impl.campaign.tutorial.TutorialMissionIntel;
85import com.fs.starfarer.api.loading.FighterWingSpecAPI;
86import com.fs.starfarer.api.loading.HullModSpecAPI;
87import com.fs.starfarer.api.loading.WeaponSpecAPI;
88import com.fs.starfarer.api.util.IntervalUtil;
89import com.fs.starfarer.api.util.Misc;
90import com.fs.starfarer.api.util.WeightedRandomPicker;
91
92public class CoreScript extends BaseCampaignEventListener implements EveryFrameScript {
93
94 public static Logger log = Global.getLogger(CoreScript.class);
95
96 public static final String SHARED_DATA_KEY = "core_CEFSSharedDataKey";
97
98 private SharedData shared;
99
100 private IntervalUtil timer = new IntervalUtil(0.5f, 1.5f);
101 //private Set<String> marketsWithAssignedPatrolScripts = new HashSet<String>();
102
103 public CoreScript() {
104 super(true);
105// shared = new SharedData();
106 shared = SharedData.getData();
107 }
108
109 private boolean firstFrame = true;
110 public void advance(float amount) {
111 SectorAPI sector = Global.getSector();
112 playRepChangeSoundsIfNeeded();
113
114 if (sector.isPaused()) {
115 if (Global.getSettings().isDevMode()) {
116 //RouteManager.getInstance().advance(amount);
118 }
119 return;
120 }
121
122 if (firstFrame) {
123 firstFrame = false;
124 }
125
126 float days = sector.getClock().convertToDays(amount);
127 shared.advance(amount);
128
129 timer.advance(days);
130 if (timer.intervalElapsed()) {
131 }
132
134
136
137 //updateSlipstreamVisibility(amount);
138 }
139
140// protected transient CampaignTerrainAPI currentStream = null;
141// public void updateSlipstreamVisibility(float amount) {
142// float sw = Global.getSettings().getFloat("sectorWidth");
143// float sh = Global.getSettings().getFloat("sectorHeight");
144// float minCellSize = 12000f;
145// float cellSize = Math.max(minCellSize, sw * 0.05f);
146// CollisionGridUtil grid = new CollisionGridUtil(-sw/2f, sw/2f, -sh/2f, sh/2f, cellSize);
147// Set<String> seenSystems = new LinkedHashSet<String>();
148// for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
149// if (market.isHidden()) continue;
150// if (market.getContainingLocation() == null) continue;
151// if (!market.getContainingLocation().isHyperspace()) {
152// String systemId = market.getContainingLocation().getId();
153// if (seenSystems.contains(systemId)) continue;
154// seenSystems.add(systemId);
155// }
156// //if (market.hasIndustry(Industries.SPACEPORT)) continue;
157// Industry spaceport = market.getIndustry(Industries.SPACEPORT);
158// if (spaceport == null || !spaceport.isFunctional()) continue;
159//
160// Vector2f loc = market.getLocationInHyperspace();
161// float size = 10000f;
162// if (!market.getContainingLocation().hasTag(Tags.THEME_CORE)) {
163// size = 10000f;
164// }
165// //size = 200000;
169// CustomStreamRevealer revealer = new CustomStreamRevealer(loc, size);
170// grid.addObject(revealer, loc, size * 2f, size * 2f);
171// }
172//
173// //System.out.println("BEGIN");
174// float maxDist = 0f;
175// List<CampaignTerrainAPI> terrainList = Global.getSector().getHyperspace().getTerrainCopy();
176// boolean processNext = false;
177// for (CampaignTerrainAPI terrain : terrainList) {
178// if (terrain.getPlugin() instanceof SlipstreamTerrainPlugin2) {
179// boolean process = false;
180// if (currentStream == null || processNext) {
181// process = true;
182// } else if (currentStream == terrain) {
183// processNext = true;
184// }
185//
186// if (!process) continue;
187//
188// currentStream = terrain;
189// if (terrainList.indexOf(terrain) == terrainList.size() - 1) {
190// currentStream = null;
191// }
192// //System.out.println("Processing: " + terrain.getId());
193// SlipstreamTerrainPlugin2 stream = (SlipstreamTerrainPlugin2) terrain.getPlugin();
194// for (SlipstreamSegment curr : stream.getSegments()) {
195// if (curr.discovered) continue;
196// Iterator<Object> iter = grid.getCheckIterator(curr.loc, curr.width / 2f, curr.width / 2f);
197// //Iterator<Object> iter = grid.getCheckIterator(curr.loc, 100f, 100f);
198// while (iter.hasNext()) {
199// Object obj = iter.next();
200// if (obj instanceof CustomStreamRevealer) {
201// CustomStreamRevealer rev = (CustomStreamRevealer) obj;
202// Vector2f loc = rev.loc;
203// float radius = rev.radius;
204//
205// float dist = Misc.getDistance(loc, curr.loc);
206// if (dist > maxDist) {
207// maxDist = dist;
212// }
213// if (dist < radius) {
214// curr.discovered = true;
215// break;
216// }
217// }
218// }
219// }
220// break;
221// }
222// }
223// //System.out.println("Max dist: " + maxDist);
224// }
225
226
227 private void playRepChangeSoundsIfNeeded() {
228 if (deltaFaction != null) {
229 if (highestDelta > 0) {
230 Global.getSoundPlayer().playUISound("ui_rep_raise", 1, 1);
231 } else if (highestDelta < 0) {
232 Global.getSoundPlayer().playUISound("ui_rep_drop", 1, 1);
233 }
234 }
235
236 highestDelta = 0f;
237 deltaFaction = null;
238 }
239
240
241 private float highestDelta = 0f;
242 private String deltaFaction = null;
243 @Override
244 public void reportPlayerReputationChange(String faction, float delta) {
245 super.reportPlayerReputationChange(faction, delta);
246 if (Math.abs(delta) > Math.abs(highestDelta)) {
247 highestDelta = delta;
248 deltaFaction = faction;
249 }
250 }
251
252
253 @Override
254 public void reportPlayerReputationChange(PersonAPI person, float delta) {
255 super.reportPlayerReputationChange(person, delta);
256 if (Math.abs(delta) > Math.abs(highestDelta)) {
257 highestDelta = delta;
258 deltaFaction = person.getFaction().getId();
259 }
260 }
261
262
263 public boolean isDone() {
264 return false;
265 }
266
267 public boolean runWhilePaused() {
268 return true;
269 }
270
271
272 @Override
274 super.reportPlayerMarketTransaction(transaction);
275
276 for (ShipSaleInfo info : transaction.getShipsBought()) {
277 FleetMemberAPI member = info.getMember();
281 }
282 }
283
284
285
286 SubmarketAPI submarket = transaction.getSubmarket();
287 MarketAPI market = transaction.getMarket();
288
289 if (!market.isPlayerOwned() && submarket.getPlugin().isParticipatesInEconomy() &&
290 !submarket.getPlugin().isBlackMarket() && submarket.getFaction() == market.getFaction()) {
291 CargoAPI cargo = transaction.getSubmarket().getCargo();
292 boolean didAnything = false;
293 OUTER: for (CargoStackAPI stack : transaction.getSold().getStacksCopy()) {
294 SpecialItemPlugin plugin = stack.getPlugin();
295 if (plugin == null) continue;
296
297 SpecialItemData data = stack.getSpecialDataIfSpecial();
298
300 for (Industry ind : market.getIndustries()) {
301 if (ind.wantsToUseSpecialItem(data)) {
302 if (effect != null) {
303 List<String> unmet = effect.getUnmetRequirements(ind);
304 if (unmet != null && !unmet.isEmpty()) {
305 continue;
306 }
307 }
308
309 if (ind.getSpecialItem() != null) { // upgrade, put item into cargo
310 cargo.addItems(CargoItemType.SPECIAL, ind.getSpecialItem(), 1);
311 }
312 cargo.removeItems(CargoItemType.SPECIAL, data, 1);
313 ind.setSpecialItem(data);
314 didAnything = true;
315 continue OUTER;
316 }
317 }
318 }
319
320 if (didAnything) {
321 cargo.sort();
322 }
323
324 // not sure about doing this for major factions:
325 // - it can mess with their flavor, unintentionally if the player just sells blueprints
326 // - it can be a way to make their fleets weaker, by selling loads of blueprints for poor ships
327 //BlackMarketPlugin.delayedLearnBlueprintsFromTransaction(submarket.getFaction(), cargo, transaction);
328 }
329
330 //SharedData.getData().getPlayerActivityTracker().updateLastVisit(transaction.getMarket());
331
332 // moved below code to BaseSubmarketPlugin
333// SubmarketAPI sub = transaction.getSubmarket();
334// if (sub.getPlugin().isParticipatesInEconomy()) {
335// SharedData.getData().getPlayerActivityTracker().getPlayerTradeData(sub).addTransaction(transaction);
336// }
337 }
338
339 @Override
341 super.reportPlayerOpenedMarket(market);
343
344 //new TempImmigrationModifier(market, 100, 200f, "Testing immigration mod");
345 }
346
347
348
349 @Override
350 public void reportBattleOccurred(CampaignFleetAPI primaryWinner, BattleAPI battle) {
351
352 generateOrAddToDebrisFieldFromBattle(primaryWinner, battle);
353
354 if (!battle.isPlayerInvolved()) return;
355
356
358 if (!playerFleet.isValidPlayerFleet()) {
359 float fp = 0;
360 float crew = 0;
361 for (FleetMemberAPI member : Misc.getSnapshotMembersLost(playerFleet)) {
362 fp += member.getFleetPointCost();
363 crew = member.getMinCrew();
364 }
366 shared.setPlayerPreLosingBattleCrew(crew);
368 }
369
370
371 for (final CampaignFleetAPI otherFleet : battle.getNonPlayerSideSnapshot()) {
372 if (otherFleet.hasScriptOfClass(TOffAlarm.class)) continue;
373 MemoryAPI memory = otherFleet.getMemoryWithoutUpdate();
374 //if (!playerFleet.isTransponderOn()) {
375 //if (!memory.getBoolean(MemFlags.MEMORY_KEY_LOW_REP_IMPACT)) {
376 Misc.setFlagWithReason(memory, MemFlags.MEMORY_KEY_MAKE_HOSTILE_WHILE_TOFF, "battle", true, 7f + (float) Math.random() * 7f);
377 //}
378 //}
379
380 if (!otherFleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_LOW_REP_IMPACT) ||
381 otherFleet.getMemoryWithoutUpdate().getBoolean(MemFlags.SPREAD_TOFF_HOSTILITY_IF_LOW_IMPACT)) {
382 otherFleet.addScript(new TOffAlarm(otherFleet));
383 }
384
385
386 float fpLost = Misc.getSnapshotFPLost(otherFleet);
387
388 List<MarketAPI> markets = Misc.findNearbyLocalMarkets(otherFleet,
389 Global.getSettings().getFloat("sensorRangeMax") + 500f,
390 new MarketFilter() {
391 public boolean acceptMarket(MarketAPI market) {
392 //return market.getFaction().isAtWorst(otherFleet.getFaction(), RepLevel.COOPERATIVE);
393 return market.getFaction() != null && market.getFaction() == otherFleet.getFaction();
394 }
395 });
396
397 for (MarketAPI market : markets) {
398 MemoryAPI mem = market.getMemoryWithoutUpdate();
399 float expire = fpLost;
402 }
403 if (expire > 180) expire = 180;
404 if (expire > 0) {
406 }
407 }
408 }
409
410 Misc.getSimulatorPlugin().reportPlayerBattleOccurred(primaryWinner, battle);
411 }
412
413
414 @Override
415 public void reportFleetJumped(CampaignFleetAPI fleet, SectorEntityToken from, JumpDestination to) {
416 super.reportFleetJumped(fleet, from, to);
417
418 if (!fleet.isPlayerFleet()) return;
419
421 Color color = faction.getBaseUIColor();
422 Color dark = faction.getDarkUIColor();
423 Color grid = faction.getGridUIColor();
424 Color bright = faction.getBrightUIColor();
425
426 if (fleet.getContainingLocation() instanceof StarSystemAPI) {
428 markSystemAsEntered(system, true);
429 }
430 }
431
432 public static void markSystemAsEntered(StarSystemAPI system, boolean withMessages) {
433 system.setEnteredByPlayer(true);
434
435 for (PlanetAPI planet : system.getPlanets()) {
436 if (planet.isStar()) continue;
437
438 MarketAPI market = planet.getMarket();
439 if (market == null) continue;
440 if (market.getSurveyLevel() == SurveyLevel.NONE) {
441 market.setSurveyLevel(SurveyLevel.SEEN);
442 String type = planet.getSpec().getName();
443 if (!planet.isGasGiant()) type += " World";
444// Global.getSector().getCampaignUI().addMessage(
445// "New planet data: " + planet.getName() + ", " + type,
446// color);
447
448
449 if (withMessages) {
450// CommMessageAPI message = Global.getFactory().createMessage();
451// message.setSubject("New planet data: " + planet.getName() + ", " + type);
452// message.setAction(MessageClickAction.INTEL_TAB);
453// message.setCustomData(planet);
454// message.setAddToIntelTab(false);
455// message.setSmallIcon(Global.getSettings().getSpriteName("intel_categories", "star_systems"));
456// Global.getSector().getCampaignUI().addMessage(message);
457
458 MessageIntel intel = new MessageIntel("New planet data: " + planet.getName() + ", " + type,
459 Misc.getBasePlayerColor());//, new String[] {"" + points}, Misc.getHighlightColor());
460 intel.setIcon(Global.getSettings().getSpriteName("intel", "new_planet_info"));
461 Global.getSector().getCampaignUI().addMessage(intel, MessageClickAction.INTEL_TAB, planet);
462 }
463 }
464 }
465 }
466
467
468 public static void addMiscToDropData(DropData data, FleetMemberAPI member,
469 boolean weapons, boolean mods, boolean fighters) {
470 ShipVariantAPI variant = member.getVariant();
471
472 if (weapons) {
473 float p = Global.getSettings().getFloat("salvageWeaponProb");
474 for (String slotId : variant.getNonBuiltInWeaponSlots()) {
475 String weaponId = variant.getWeaponId(slotId);
477 if (spec.hasTag(Tags.NO_DROP)) continue;
478 data.addWeapon(weaponId, 1f * p);
479 }
480 }
481
482 if (mods) {
483 float p = Global.getSettings().getFloat("salvageHullmodProb");
484 for (String id : member.getVariant().getHullMods()) {
486 if (spec.isHidden() || spec.isHiddenEverywhere()) continue;
487 if (spec.hasTag(Tags.HULLMOD_NO_DROP)) continue;
488 data.addHullMod(id, 1f * p);
489 }
490 }
491
492 if (fighters) {
493 float p = Global.getSettings().getFloat("salvageWingProb");
494
495 for (String id : member.getVariant().getFittedWings()) {
497 if (spec.hasTag(Tags.WING_NO_DROP)) continue;
498 data.addFighterChip(id, 1f * p);
499 }
500 }
501
502 data.valueMult = Global.getSettings().getFloat("salvageDebrisFieldFraction");
503 }
504
505 public static Set<String> getCargoCommodities(CargoAPI cargo) {
506 Set<String> result = new HashSet<String>();
507 for (CargoStackAPI stack : cargo.getStacksCopy()) {
508 if (stack.isCommodityStack()) {
509 result.add(stack.getCommodityId());
510 }
511 }
512 return result;
513 }
514
515 public static void generateOrAddToDebrisFieldFromBattle(CampaignFleetAPI primaryWinner, BattleAPI battle) {
516
517 if (primaryWinner == null) return;
518 LocationAPI location = primaryWinner.getContainingLocation();
519 if (location == null) return;
520
521 //if (location.isHyperspace()) return;
522
523 boolean allowDebris = !location.isHyperspace();
524
525
526 boolean playerInvolved = battle.isPlayerInvolved();
527
528 DropData misc = new DropData();
529 int miscChances = 0;
530
531 List<DropData> cargoList = new ArrayList<DropData>();
532
534
535 Vector2f com = new Vector2f();
536 float count = 0f;
537 float fpDestroyed = 0;
538 for (CampaignFleetAPI fleet : battle.getSnapshotSideOne()) {
539 count++;
540 com.x += fleet.getLocation().x;
541 com.y += fleet.getLocation().y;
542
543 float fpForThisFleet = 0;
544 for (FleetMemberAPI loss : Misc.getSnapshotMembersLost(fleet)) {
545 //if (loss.getVariant().isStockVariant()) {
546 if (!loss.getVariant().hasTag(Tags.SHIP_RECOVERABLE)) { // was not recoverable by player
547 if (!loss.isStation() && !fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_NO_SHIP_RECOVERY)) {
548 recoverySpecialChoices.add(loss);
549 }
550 }
551 fpDestroyed += loss.getFleetPointCost();
552 fpForThisFleet += loss.getFleetPointCost();
553 if (allowDebris && !fleet.isPlayerFleet()) {
554 addMiscToDropData(misc, loss, true, true, true);
555 miscChances++;
556 }
557 }
558 if (allowDebris && !fleet.isPlayerFleet()) {
559 DropData cargo = new DropData();
560 float cargoValue = fpForThisFleet * Global.getSettings().getFloat("salvageValuePerFP");
561 cargoValue *= Global.getSettings().getFloat("salvageDebrisFieldFraction");
562 if (cargoValue >= 1) {
563 for (String cid : getCargoCommodities(fleet.getCargo())) {
564 cargo.addCommodity(cid, 1f);
565 }
566 cargo.value = (int) cargoValue;
567 cargo.chances = 1;
568 cargoList.add(cargo);
569 }
570 }
571 }
572 for (CampaignFleetAPI fleet : battle.getSnapshotSideTwo()) {
573 count++;
574 com.x += fleet.getLocation().x;
575 com.y += fleet.getLocation().y;
576
577 float fpForThisFleet = 0;
578 for (FleetMemberAPI loss : Misc.getSnapshotMembersLost(fleet)) {
579 //if (loss.getVariant().isStockVariant()) {
580 if (!loss.getVariant().hasTag(Tags.SHIP_RECOVERABLE)) { // was not recoverable by player
581 if (!loss.isStation() && !fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_NO_SHIP_RECOVERY)) {
582 recoverySpecialChoices.add(loss);
583 }
584 } else {
585 loss.getVariant().removeTag(Tags.SHIP_RECOVERABLE);
586 }
587
588 fpDestroyed += loss.getFleetPointCost();
589 fpForThisFleet += loss.getFleetPointCost();
590 if (allowDebris && !fleet.isPlayerFleet()) {
591 addMiscToDropData(misc, loss, true, true, true);
592 miscChances++;
593 }
594 }
595 if (allowDebris && !fleet.isPlayerFleet()) {
596 DropData cargo = new DropData();
597 float cargoValue = fpForThisFleet * Global.getSettings().getFloat("salvageValuePerFP");
598 cargoValue *= Global.getSettings().getFloat("salvageDebrisFieldFraction");
599 if (cargoValue >= 1) {
600 for (String cid : getCargoCommodities(fleet.getCargo())) {
601 cargo.addCommodity(cid, 1f);
602 }
603 cargo.value = (int) cargoValue;
604 cargo.chances = 1;
605 cargoList.add(cargo);
606 }
607 }
608 }
609 //Global.getSector().getPlayerFleet().getLocation()
610 if (count <= 0) return;
611
612 com.scale(1f / count);
613
614 // spawn some derelict ships, maybe. do this here, regardless of whether the value is enough to
615 // warrant a debris field
616 float numShips = recoverySpecialChoices.getItems().size();
617 float chanceDerelict = 1f - 10f / (numShips + 10f);
618 //chanceNothing = 0f;
619 //Vector2f com = battle.computeCenterOfMass();
620
621 // in a battle that involves the player, recoverable ships are non-stock variants
622 // (due to being prepared for recovery; dmods etc) and so don't show up as possible recovery choices here
623 // which is good! since 1) they could've been actually recovered, and 2) they already contributed to player salvage
624 // replaced this with Tags.SHIP_RECOVERABLE tag in recoverable variant for cleanness
625 int max = 3;
626 if (playerInvolved) {
627 max = 2;
628 chanceDerelict *= 0.25f;
629 }
630 for (int i = 0; i < max && !recoverySpecialChoices.isEmpty(); i++) {
631 boolean spawnShip = Math.random() < chanceDerelict;
632 if (spawnShip) {
633 FleetMemberAPI member = recoverySpecialChoices.pickAndRemove();
634 String variantId = member.getVariant().getHullVariantId();
635 if (!member.getVariant().isStockVariant()) variantId = member.getVariant().getOriginalVariant();
636 if (variantId == null) continue;
637 DerelictShipData params = new DerelictShipData(new PerShipData(variantId,
639 params.durationDays = DerelictShipEntityPlugin.getBaseDuration(member.getHullSpec().getHullSize());
641 primaryWinner.getContainingLocation(),
642 Entities.WRECK, Factions.NEUTRAL, params);
643 entity.addTag(Tags.EXPIRES);
645
646// entity.getLocation().x = com.x + (50f - (float) Math.random() * 100f);
647// entity.getLocation().y = com.y + (50f - (float) Math.random() * 100f);
648
649 float angle = (float) Math.random() * 360f;
650 float speed = 10f + 10f * (float) Math.random();
651 Vector2f vel = Misc.getUnitVectorAtDegreeAngle(angle);
652 vel.scale(speed);
653 entity.getVelocity().set(vel);
654
655 entity.getLocation().x = com.x + vel.x * 3f;
656 entity.getLocation().y = com.y + vel.y * 3f;
657 }
658 }
659
660
661
662 float salvageValue = fpDestroyed * Global.getSettings().getFloat("salvageValuePerFP");
663 if (Misc.isEasy()) {
664 salvageValue *= Global.getSettings().getFloat("easySalvageMult");
665 }
666
667
668 salvageValue *= Global.getSettings().getFloat("salvageDebrisFieldFraction");
669 float salvageXP = salvageValue * 0.1f;
670
671 float minForField = Global.getSettings().getFloat("minSalvageValueForDebrisField");
672 //if (playerInvolved) minForField *= 6f;
673 if (playerInvolved) minForField = 2500f + (float) Math.random() * 1000f;
674
675 if (salvageValue < minForField || !allowDebris) return;
676
677
678 CampaignTerrainAPI debris = null;
679 for (CampaignTerrainAPI curr : primaryWinner.getContainingLocation().getTerrainCopy()) {
680 if (curr.getPlugin() instanceof DebrisFieldTerrainPlugin) {
681 DebrisFieldTerrainPlugin plugin = (DebrisFieldTerrainPlugin) curr.getPlugin();
682 if (plugin.params.source == DebrisFieldSource.BATTLE &&
683 plugin.params.density >= 1f &&
684 plugin.containsPoint(com, 100f)) {
685 debris = curr;
686 break;
687 }
688 }
689 }
690
691 if (debris == null) {
692 DebrisFieldParams params = new DebrisFieldParams(
693 200f, // field radius - should not go above 1000 for performance reasons
694 -1f, // density, visual - affects number of debris pieces
695 1f, // duration in days
696 1f); // days the field will keep generating glowing pieces
697 params.source = DebrisFieldSource.BATTLE;
698 params.baseSalvageXP = (long) salvageXP; // base XP for scavenging in field
699
700 debris = (CampaignTerrainAPI) Misc.addDebrisField(location, params, null);
701
702 // makes the debris field always visible on map/sensors and not give any xp or notification on being discovered
703 //debris.setSensorProfile(null);
704 //debris.setDiscoverable(null);
705
706 // makes it discoverable and give 200 xp on being found
707 // sets the range at which it can be detected (as a sensor contact) to 2000 units
708 //debris.setDiscoverable(true);
709 //debris.setDiscoveryXP(200f);
710 //debris.setSensorProfile(1f);
711 //debris.getDetectedRangeMod().modifyFlat("gen", 2000);
712
713 debris.setDiscoverable(null);
714 debris.setDiscoveryXP(null);
715 //debris.setSensorProfile(1f);
716 //debris.getDetectedRangeMod().modifyFlat("gen", 1000);
717
718 debris.getLocation().set(com);
719
720 debris.getDropValue().clear();
721 debris.getDropRandom().clear();
722 }
723
724
726 DropData basicDrop = null;
727 for (DropData data : debris.getDropValue()) {
728 if (Drops.BASIC.equals(data.group)) {
729 basicDrop = data;
730 break;
731 }
732 }
733
734 // since we're only adding to fields with density 1 (i.e. ones the player hasn't salvaged)
735 // no need to worry about how density would affect the salvage value of what we're adding
736 if (basicDrop == null) {
737 basicDrop = new DropData();
738 basicDrop.group = Drops.BASIC;
739 debris.addDropValue(basicDrop);
740 }
741 basicDrop.value += salvageValue;
742
743 if (misc.getCustom() != null) {
744 misc.chances = miscChances;
745
746 float total = misc.getCustom().getTotal();
747 if (total > 0) {
748 misc.addNothing(Math.max(1f, total));
749 }
750 debris.addDropRandom(misc);
751 //misc.getCustom().print("MISC DROP");
752 }
753
754 for (DropData cargo : cargoList) {
755 debris.addDropRandom(cargo);
756 }
757
758
759 //if (!battle.isPlayerInvolved()) {
760 ShipRecoverySpecialData data = ShipRecoverySpecial.getSpecialData(debris, null, true, false);
761 if (data != null && data.ships.size() < 3) {
762 float items = recoverySpecialChoices.getTotal();
763 float total = items + 25f;
764 for (int i = 0; i < 3; i++) {
765 if ((float) Math.random() * total < items) {
766 FleetMemberAPI pick = recoverySpecialChoices.pick();
767 if (pick != null) {
768 String variantId = pick.getVariant().getHullVariantId();
769 if (!pick.getVariant().isStockVariant()) variantId = pick.getVariant().getOriginalVariant();
770 data.addShip(variantId, ShipCondition.WRECKED, 0f);
771 }
772 }
773 }
774 }
775 //}
776
777// basicDrop = new DropData();
778// basicDrop.group = "misc_test";
779// basicDrop.value = 100000;
780// existing.addDropValue(basicDrop);
781
782 // resize and adjust duration here
783
784 float radius = 100f + (float) Math.min(900, Math.sqrt(basicDrop.value));
785 float durationExtra = (float) Math.sqrt(salvageValue) * 0.1f;
786
787 float minDays = DebrisFieldTerrainPlugin.DISSIPATE_DAYS + 1f;
788 if (durationExtra < minDays) durationExtra = minDays;
789
790 float time = durationExtra + plugin.params.lastsDays;
791 if (time > 30f) time = 30f;
792
793 plugin.params.lastsDays = time;
794 plugin.params.glowsDays = time;
795
796 plugin.params.bandWidthInEngine = radius;
797 plugin.params.middleRadius = plugin.params.bandWidthInEngine / 2f;
798
799 float range = DebrisFieldTerrainPlugin.computeDetectionRange(plugin.params.bandWidthInEngine);
800 debris.getDetectedRangeMod().modifyFlat("gen", range);
801 }
802
803
804
805
806 @Override
808 super.reportPlayerDumpedCargo(cargo);
809
810
812
814 pods.getCargo().addAll(cargo);
815
816 CargoPodsResponse script = new CargoPodsResponse(pods);
817 pods.getContainingLocation().addScript(script);
819// pods.getMemoryWithoutUpdate().set(CargoPods.LOCKED, true);
820// pods.getMemoryWithoutUpdate().set(CargoPods.CAN_UNLOCK, true);
821 //pods.getMemoryWithoutUpdate().set(CargoPods.TRAPPED, true);
822
823 //pods.getDetectedRangeMod().modifyFlat("gen", 1000);
824 }
825
826 @Override
828 super.reportPlayerDumpedCargo(cargo);
829
831
833 pods.getCargo().addAll(cargo);
834
836 }
837
838 protected Random prodRandom = new Random();
839 public void doCustomProduction() {
842
843 MarketAPI gatheringPoint = prod.getGatheringPoint();
844 if (gatheringPoint == null) return;
845
846 //CargoAPI local = Misc.getLocalResourcesCargo(gatheringPoint);
847 CargoAPI local = Misc.getStorageCargo(gatheringPoint);
848 if (local == null) return;
849
852 report.computeTotals();
853
854 // limit production capacity by available credits - the net coming in this month plus what the player has
855 int total = (int) (report.getRoot().totalIncome - report.getRoot().totalUpkeep);
856 int credits = (int) playerFleet.getCargo().getCredits().get();
857 credits += total;
858 if (credits < 0) credits = 0;
859
860 int capacity = prod.getMonthlyProductionCapacity();
861 capacity = Math.min(capacity, credits);
862 //capacity = 1000000;
863
864 int remainingValue = capacity + prod.getAccruedProduction();
865 //if (remainingValue <= 0) return;
866
867
868
869 //Random random = new Random();
870 if (prodRandom == null) prodRandom = new Random();
871 Random random = prodRandom;
872
874 for (ItemInProductionAPI item : prod.getCurrent()) {
875 if (item.getBuildDelay() > 0 && !Global.getSettings().isDevMode()) continue;
876 picker.add(item, item.getQuantity());
877 }
878 int accrued = 0;
879
880 boolean wantedToDoProduction = !picker.isEmpty();
881 boolean unableToDoProduction = capacity <= 0;
882
883 ProductionData data = new ProductionData();
884 //CargoAPI cargo = Global.getFactory().createCargo(true);
885 //cargo.initMothballedShips(Factions.PLAYER);
886 CargoAPI cargo = data.getCargo("Heavy Industry - Custom Production");
887
888 float quality = -1f;
889 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
890 if (!market.isPlayerOwned()) continue;
891 //quality = Math.max(quality, ShipQuality.getShipQuality(market, Factions.PLAYER));
892 float currQuality = market.getStats().getDynamic().getMod(Stats.PRODUCTION_QUALITY_MOD).computeEffective(0f);
893 currQuality += market.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).computeEffective(0f);
894 quality = Math.max(quality, currQuality);
895 }
897 quality += 4f * Global.getSettings().getFloat("doctrineFleetQualityPerPoint");
898
902 p.quality = quality;
903 p.mode = ShipPickMode.PRIORITY_THEN_ALL;
904 p.persistent = false;
905 p.seed = random.nextLong();
906 p.timestamp = null;
907
908 FleetInflater inflater = Misc.getInflater(ships, p);
909 ships.setInflater(inflater);
910
911 int totalCost = 0;
912 while (remainingValue > 0 && !picker.isEmpty()) {
913 ItemInProductionAPI pick = picker.pick();
914 int baseCost = pick.getBaseCost();
915
916 int count = Math.min(pick.getQuantity(), remainingValue / Math.max(1, baseCost));
917 if (count > 0) {
918 count = random.nextInt(count) + 1;
919 }
920 if (count <= 0) {
921 accrued = remainingValue;
922 remainingValue = 0;
923 } else {
924 int currCost = count * baseCost;
925 totalCost += currCost;
926 remainingValue -= currCost;
927
928 if (pick.getType() == ProductionItemType.SHIP) {
929 List<String> variants = Global.getSettings().getHullIdToVariantListMap().get(pick.getSpecId());
930 if (variants.isEmpty()) {
931 variants.add(pick.getSpecId() + "_Hull");
932 continue;
933 }
934
935 int index = random.nextInt(variants.size());
936 //cargo.addMothballedShip(FleetMemberType.SHIP, variants.get(index), null);
937 for (int i = 0; i < count; i++) {
938 ships.getFleetData().addFleetMember(variants.get(index));
939 }
940 } else if (pick.getType() == ProductionItemType.FIGHTER) {
941 cargo.addFighters(pick.getSpecId(), count);
942 } else if (pick.getType() == ProductionItemType.WEAPON) {
943 cargo.addWeapons(pick.getSpecId(), count);
944 }
945
946 prod.removeItem(pick.getType(), pick.getSpecId(), count);
947 if (pick.getQuantity() <= 0) {
948 picker.remove(pick);
949 }
950 }
951 }
952
953 int weaponCost = 0;
954 ships.inflateIfNeeded();
955 for (FleetMemberAPI member : ships.getFleetData().getMembersListCopy()) {
956 cargo.getMothballedShips().addFleetMember(member);
957 for (String wingId : member.getVariant().getNonBuiltInWings()) {
959 weaponCost += spec.getBaseValue();
960 }
961 for (String slotId : member.getVariant().getNonBuiltInWeaponSlots()) {
962 WeaponSpecAPI spec = member.getVariant().getWeaponSpec(slotId);
963 weaponCost += spec.getBaseValue();
964 }
965 }
967 weaponCost = 0;
968 }
969
970 // add some supplies, fuel, and crew
971 int addedValue = (int) (totalCost * Global.getSettings().getFloat("productionSuppliesBonusFraction"));
975
976 int supplies = (int) (addedValue * (0.5f * (0.5f + random.nextFloat() * 0.5f))) / sCost;
977 int fuel = (int) (addedValue * (0.3f * (0.5f + random.nextFloat() * 0.5f))) / fCost;
978 int crew = (addedValue - sCost * supplies - fCost * fuel) / cCost;
979
980 supplies = supplies / 10 * 10;
981 fuel = fuel / 10 * 10;
982 crew = crew / 10 * 10;
983
984 cargo.addSupplies(supplies);
985 cargo.addFuel(fuel);
986 cargo.addCrew(crew);
987
988 //accrued += remainingValue; // don't do that, only want to accrue when trying to produce something
989
990 totalCost -= prod.getAccruedProduction();
991 totalCost += accrued;
992 if (totalCost < 0) totalCost = 0;
993 prod.setAccruedProduction(accrued);
994
995 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
996 if (!market.isPlayerOwned()) continue;
997
998 for (Industry ind : market.getIndustries()) {
999 Random curr = Misc.getRandom(random.nextLong(), 11);
1000 CargoAPI added = ind.generateCargoForGatheringPoint(curr);
1001 if (added != null && (!added.isEmpty() ||
1002 (added.getMothballedShips() != null && !added.getMothballedShips().getMembersListCopy().isEmpty()))) {
1003 String title = ind.getCargoTitleForGatheringPoint();
1004 data.getCargo(title).addAll(added, true);
1005 }
1006 }
1007 }
1008
1009
1010 // done with production
1011
1012
1013
1014 if (!data.isEmpty() || totalCost > 0 || (wantedToDoProduction && unableToDoProduction)) {
1015 if (totalCost > 0) {
1016 //MonthlyReport report = SharedData.getData().getCurrentReport();
1017
1018 FDNode marketsNode = report.getNode(MonthlyReport.OUTPOSTS);
1019 if (marketsNode.name == null) {
1020 marketsNode.name = "Colonies";
1021 marketsNode.custom = MonthlyReport.OUTPOSTS;
1022 marketsNode.tooltipCreator = report.getMonthlyReportTooltip();
1023 }
1024
1025 FDNode production = report.getNode(marketsNode, MonthlyReport.PRODUCTION);
1026 production.name = "Custom production orders";
1027 production.custom = MonthlyReport.PRODUCTION;
1028 production.custom2 = cargo;
1029 production.tooltipCreator = report.getMonthlyReportTooltip();
1030
1031 production.upkeep += totalCost;
1032
1033 if (weaponCost > 0) {
1034 FDNode productionWeapons = report.getNode(marketsNode, MonthlyReport.PRODUCTION_WEAPONS);
1035 productionWeapons.name = "Weapons & fighter LPCs for produced ships";
1036 productionWeapons.custom = MonthlyReport.PRODUCTION_WEAPONS;
1037 productionWeapons.tooltipCreator = report.getMonthlyReportTooltip();
1038 productionWeapons.upkeep += weaponCost;
1039 }
1040 }
1041
1042 for (CargoAPI curr : data.data.values()) {
1043 local.addAll(curr);
1045 for (FleetMemberAPI member : curr.getMothballedShips().getMembersListCopy()) {
1046// member.getRepairTracker().setCR(0f);
1047// member.getRepairTracker().setMothballed(true);
1048 member.getRepairTracker().setMothballed(false);
1049 member.getRepairTracker().setCR(0.5f);
1050 local.getMothballedShips().addFleetMember(member);
1051 }
1052 }
1053 local.sort();
1054
1055 ProductionReportIntel intel = new ProductionReportIntel(gatheringPoint, data,
1056 totalCost + weaponCost, prod.getAccruedProduction(),
1057 wantedToDoProduction && unableToDoProduction);
1059 }
1060
1061 }
1062
1063
1064 @Override
1066 super.reportEconomyMonthEnd();
1067
1069 return;
1070 }
1071
1073 FDNode marketsNode = report.getNode(MonthlyReport.OUTPOSTS);
1074 if (marketsNode.custom != null) {
1075 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
1076 if (!market.isPlayerOwned()) continue;
1077
1078 float incentive = market.getIncentiveCredits();
1079 if (incentive > 0) {
1080 FDNode mNode = report.getNode(marketsNode, market.getId());
1081 if (mNode.custom != null) {
1082 FDNode incNode = report.getNode(mNode, "incentives");
1083 incNode.name = "Hazard pay";
1084 incNode.custom = MonthlyReport.INCENTIVES;
1085 incNode.mapEntity = market.getPrimaryEntity();
1086 incNode.tooltipCreator = report.getMonthlyReportTooltip();
1087 incNode.upkeep += incentive;
1088 }
1089 market.setIncentiveCredits(0);
1090 }
1091 }
1092 }
1093
1094
1096 float debt = previous.getDebt();
1097 if (debt > 0) {
1099 current.getDebtNode().upkeep = debt;
1100 }
1101
1103
1105
1106 //MonthlyReport previous = SharedData.getData().getPreviousReport();
1109 report.setPreviousDebt(previous.getDebt());
1111
1112 report.computeTotals();
1113 int total = (int) (report.getRoot().totalIncome - report.getRoot().totalUpkeep);
1114 float credits = (int) playerFleet.getCargo().getCredits().get();
1115
1116 float newCredits = credits + total;
1117 if (newCredits < 0) {
1118 report.setDebt((int) Math.abs(newCredits));
1119 newCredits = 0;
1120 }
1121 playerFleet.getCargo().getCredits().set(newCredits);
1122
1123
1124 String totalStr = Misc.getDGSCredits(Math.abs(total));
1125 //Global.getSector().getCampaignUI().showCoreUITab(CoreUITabId.OUTPOSTS);
1126
1127 String title = "Monthly income: " + totalStr;
1128 Color highlight = Misc.getHighlightColor();
1129 if (total < 0) {
1130 title = "Monthly expenses: " + totalStr;
1131 highlight = Misc.getNegativeHighlightColor();
1132 }
1133
1134 MessageIntel intel = new MessageIntel(title,
1135 Misc.getBasePlayerColor(), new String[] {totalStr}, highlight);
1136 intel.setIcon(Global.getSettings().getSpriteName("intel", "monthly_income_report"));
1137
1138 if (total >= 0) {
1139 intel.setSound("ui_intel_monthly_income_positive");
1140 } else {
1141 intel.setSound("ui_intel_monthly_income_negative");
1142 }
1143
1144 Global.getSector().getCampaignUI().addMessage(intel, MessageClickAction.INCOME_TAB, Tags.INCOME_REPORT);
1145
1146
1147// CommMessageAPI message = FleetLog.beginEntry(
1148// title,
1149// playerFleet,
1150// highlight,
1151// totalStr
1152// );
1153//
1154// message.setSmallIcon(Global.getSettings().getSpriteName("intel_categories", "bounties"));
1155// if (total >= 0) {
1156// message.getSection1().addPara("Over the last month, your fleet, outposts, and other ventures have" +
1157// " produced an income of " + totalStr + ".");
1158// } else {
1159// message.getSection1().addPara("Over the last month, your fleet, outposts, and other ventures have" +
1160// " produced expenses of " + totalStr + ".");
1161// }
1162//
1163// if (total < 0 && Math.abs(total) > credits) {
1164// message.getSection1().addPara("Your expenses have exceeded your credit balance. If this continues for more than a month, " +
1165// "some crew and officers may begin to leave, and other undertakings requiring credit expenditures may fail.");
1166// //message.getSection1().addPara(".");
1167// }
1168// message.getSection1().addPara("See the \"Income\" tab in the command screen for a detailed breakdown.");
1169//
1170// message.getSection1().setHighlights(totalStr);
1171// message.getSection1().setHighlightColors(highlight);
1172//
1173// message.setShowInCampaignList(true);
1174// message.setAddToIntelTab(true);
1175// message.setAction(MessageClickAction.INCOME_TAB);
1176// message.addTag(Tags.FLEET_LOG);
1177// message.addTag(Tags.INCOME_REPORT);
1178//
1179// Global.getSector().getCampaignUI().addMessage(message);
1180 }
1181
1182// private MonthlyReportNodeTooltipCreator monthlyReportTooltip;
1183// public static MonthlyReportNodeTooltipCreator getMonthlyReportTooltip() {
1184// if (monthlyReportTooltip == null) {
1185// monthlyReportTooltip = new MonthlyReportNodeTooltipCreator();
1186// }
1187// return monthlyReportTooltip;
1188// }
1189
1190
1191 @Override
1192 public void reportEconomyTick(int iterIndex) {
1193 super.reportEconomyTick(iterIndex);
1194
1196 return;
1197 }
1198
1199 //for (int i = 0; i < 100; i++) {
1200 int crewSalary = Global.getSettings().getInt("crewSalary");
1201 int marineSalary = Global.getSettings().getInt("marineSalary");
1202
1203 float numIter = Global.getSettings().getFloat("economyIterPerMonth");
1204 float f = 1f / numIter;
1205
1206 //f = 1f;
1207
1210
1211
1212 FDNode fleetNode = report.getNode(MonthlyReport.FLEET);
1213 fleetNode.name = "Fleet";
1214 fleetNode.custom = MonthlyReport.FLEET;
1215 fleetNode.tooltipCreator = report.getMonthlyReportTooltip();
1216
1217 int crewCost = playerFleet.getCargo().getCrew() * crewSalary;
1218 FDNode crewNode = report.getNode(fleetNode, MonthlyReport.CREW);
1219 crewNode.upkeep += crewCost * f;
1220 crewNode.name = "Crew payroll";
1221 crewNode.custom = MonthlyReport.CREW;
1222 crewNode.tooltipCreator = report.getMonthlyReportTooltip();
1223
1224 int marineCost = playerFleet.getCargo().getMarines() * marineSalary;
1225 if (marineSalary > 0) {
1226 FDNode marineNode = report.getNode(fleetNode, MonthlyReport.MARINES);
1227 marineNode.upkeep += marineCost * f;
1228 marineNode.name = "Marine payroll";
1229 marineNode.custom = MonthlyReport.MARINES;
1230 marineNode.tooltipCreator = report.getMonthlyReportTooltip();
1231 }
1232
1233
1234// List<PersonnelAtEntity> droppedOffMarines = PlayerFleetPersonnelTracker.getInstance().getDroppedOff();
1235// for (PersonnelAtEntity curr : droppedOffMarines) {
1236//
1237// }
1238// for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
1239// if (Misc.playerHasStorageAccess(market)) {
1240//
1241// }
1242// }
1243
1244
1245
1246 //FDNode officersNode = report.getNode(MonthlyReport.OFFICERS);
1247 FDNode officersNode = report.getNode(fleetNode, MonthlyReport.OFFICERS);
1248 officersNode.name = "Officer payroll";
1249 officersNode.custom = MonthlyReport.OFFICERS;
1250 officersNode.tooltipCreator = report.getMonthlyReportTooltip();
1251
1252
1253 for (OfficerDataAPI od : playerFleet.getFleetData().getOfficersCopy()) {
1254 float salary = Misc.getOfficerSalary(od.getPerson());
1255 FDNode oNode = report.getNode(officersNode, od.getPerson().getId());
1256 oNode.name = od.getPerson().getName().getFullName();
1257 oNode.upkeep += salary * f;
1258 oNode.custom = od;
1259 }
1260
1261 FDNode marketsNode = report.getNode(MonthlyReport.OUTPOSTS);
1262 marketsNode.name = "Colonies";
1263 marketsNode.custom = MonthlyReport.OUTPOSTS;
1264 marketsNode.tooltipCreator = report.getMonthlyReportTooltip();
1265
1266 FDNode storageNode = null;
1267// storageNode = report.getNode(MonthlyReport.STORAGE);
1268// storageNode.name = "Storage";
1269// storageNode.custom = MonthlyReport.STORAGE;
1270// storageNode.tooltipCreator = report.getMonthlyReportTooltip();
1271
1272 float storageFraction = Global.getSettings().getFloat("storageFreeFraction");
1273
1274 int index = 0;
1275 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
1276// if (index % 10 != 3 || index == 0) {
1277// index++;
1278// continue;
1279// }
1280
1281 if (!market.isPlayerOwned() && Misc.playerHasStorageAccess(market)) {
1282 float vc = Misc.getStorageCargoValue(market);
1283 float vs = Misc.getStorageShipValue(market);
1284
1285 float fc = (int) (vc * storageFraction);
1286 float fs = (int) (vs * storageFraction);
1287 if (fc > 0 || fs > 0) {
1288 if (storageNode == null) {
1289 storageNode = report.getNode(MonthlyReport.STORAGE);
1290 storageNode.name = "Storage";
1291 storageNode.custom = MonthlyReport.STORAGE;
1292 storageNode.tooltipCreator = report.getMonthlyReportTooltip();
1293 }
1294 FDNode mNode = report.getNode(storageNode, market.getId());
1295 String desc = "";
1296 if (fc > 0 && fs > 0) {
1297 desc = "ships & cargo";
1298 } else if (fc > 0) {
1299 desc = "cargo";
1300 } else {
1301 desc = "ships";
1302 }
1303 mNode.name = market.getName() + " (" + desc + ")";
1304 mNode.custom = market;
1305 mNode.custom2 = MonthlyReport.STORAGE;
1306 //mNode.tooltipCreator = report.getMonthlyReportTooltip();
1307
1308 mNode.upkeep += (fc + fs) * f;
1309 }
1310 continue;
1311 }
1312
1313
1314 //if (market.isHidden()) continue;
1315 //if (!Factions.DIKTAT.equals(market.getFaction().getId()) && !market.isPlayerOwned()) continue;
1316 if (!market.isPlayerOwned()) continue;
1317
1318 FDNode mNode = report.getNode(marketsNode, market.getId());
1319 mNode.name = market.getName() + " (" + market.getSize() + ")";
1320 mNode.custom = market;
1321
1322 FDNode indNode = report.getNode(mNode, "industries");
1323 indNode.name = "Industries & structures";
1324 indNode.custom = MonthlyReport.INDUSTRIES;
1325 indNode.mapEntity = market.getPrimaryEntity();
1326 indNode.tooltipCreator = report.getMonthlyReportTooltip();
1327// node.income += (int) market.getIndustryIncome();
1328// node.upkeep += (int) market.getIndustryUpkeep();
1329
1330 for (Industry curr : market.getIndustries()) {
1331 FDNode iNode = report.getNode(indNode, curr.getId());
1332 iNode.name = curr.getCurrentName();
1333 iNode.income += curr.getIncome().getModifiedInt() * f;
1334 iNode.upkeep += curr.getUpkeep().getModifiedInt() * f;
1335 iNode.custom = curr;
1336 iNode.mapEntity = market.getPrimaryEntity();
1337 }
1338
1339 FDNode exportNode = report.getNode(mNode, "exports");
1340 exportNode.name = "Exports";
1341 exportNode.custom = MonthlyReport.EXPORTS;
1342 exportNode.mapEntity = market.getPrimaryEntity();
1343 exportNode.tooltipCreator = report.getMonthlyReportTooltip();
1344
1345 addExportsGroupedByCommodity(report, exportNode, market, f);
1346 //addExportsGroupedByFaction(report, exportNode, market, f);
1347
1348
1349// FDNode overheadNode = report.getNode(exportNode, "overhead");
1350// if (overheadNode.name == null) {
1351// overheadNode.name = "Overhead";
1352// overheadNode.icon = Global.getSettings().getSpriteName("income_report", "overhead");
1353// overheadNode.custom = market;
1354// overheadNode.mapEntity = market.getPrimaryEntity();
1355// overheadNode.tooltipCreator = new OverheadTooltipCreator();
1356// }
1357//
1358// OverheadData overhead = computeOverhead(market);
1359// if (overhead.fraction > 0) {
1360// float totalIncome = market.getExportIncome(false);
1361// overheadNode.upkeep += totalIncome * overhead.fraction * f;
1362// }
1363
1364 index++;
1365 }
1366 //}
1367
1368
1369 FDNode adminNode = report.getNode(marketsNode, MonthlyReport.ADMIN);
1370 adminNode.name = "Administrators";
1371 adminNode.custom = MonthlyReport.ADMIN;
1372 adminNode.tooltipCreator = report.getMonthlyReportTooltip();
1373
1375 float salary = Misc.getAdminSalary(data.getPerson());
1376 if (salary <= 0) continue;
1377
1378 FDNode aNode = report.getNode(adminNode, data.getPerson().getId());
1379 aNode.name = data.getPerson().getName().getFullName();
1380 if (data.getMarket() != null) {
1381 aNode.name += " (" + data.getMarket().getName() + ")";
1382 } else {
1383 aNode.name += " (unassigned)";
1384 salary *= Global.getSettings().getFloat("idleAdminSalaryMult");
1385 }
1386 aNode.upkeep += salary * f;
1387 aNode.custom = data;
1388 }
1389
1390 //reportEconomyMonthEnd();
1391 }
1392
1393// public static class OverheadData {
1394// public SupplierData max;
1395// public float fraction;
1396// }
1397//
1398// public static OverheadData computeOverhead(MarketAPI market) {
1399// OverheadData result = new OverheadData();
1400//
1401// SupplierData max = null;
1402// float maxValue = 0;
1403// float total = 0f;
1404// List<CommodityOnMarketAPI> comList = market.getCommoditiesCopy();
1405// for (CommodityOnMarketAPI com : comList) {
1406// for (SupplierData sd : com.getExports()) {
1407// int income = sd.getExportValue(market);
1408// if (income <= 0) continue;
1409//
1410// total += income;
1411// if (income > maxValue) {
1412// max = sd;
1413// maxValue = income;
1414// }
1415// }
1416// }
1417//
1418// if (max != null && maxValue > 0) {
1419// result.max = max;
1420// float units = total / maxValue;
1421// float mult = Misc.logOfBase(2f, units) + 1f;
1422// result.fraction = 1f - (mult / units);
1423// if (result.fraction < 0) result.fraction = 0;
1424// if (result.fraction > 0) {
1425// result.fraction = Math.round(result.fraction * 100f) / 100f;
1426// result.fraction = Math.max(result.fraction, 0.01f);
1427// }
1428// }
1429// return result;
1430// }
1431
1432 public static class ExportCommodityGroupData {
1433 public CommodityOnMarketAPI com;
1434 public int quantity;
1435 }
1436
1437 protected void addExportsGroupedByCommodity(MonthlyReport report, FDNode parent, MarketAPI market, float f) {
1438 for (CommodityOnMarketAPI com : market.getCommoditiesCopy()) {
1439 FDNode eNode = report.getNode(parent, com.getId());
1440 eNode.name = com.getCommodity().getName();
1441 eNode.income += com.getExportIncome() * f;
1442 eNode.custom = com;
1443 eNode.mapEntity = market.getPrimaryEntity();
1444 }
1445
1446// List<FDNode> sorted = new ArrayList<FDNode>(parent.getChildren().values());
1447// Collections.sort(sorted, new Comparator<FDNode>() {
1448// public int compare(FDNode o1, FDNode o2) {
1449// return o2.income - o1.income;
1450// }
1451// });
1452// parent.getChildren().clear();
1453// parent.getChildren().
1454 }
1455
1456
1457
1458}
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
static SettingsAPI getSettings()
Definition Global.java:57
static SoundPlayerAPI getSoundPlayer()
Definition Global.java:49
static FactoryAPI getFactory()
Definition Global.java:41
static Logger getLogger(Class c)
Definition Global.java:32
static SectorAPI getSector()
Definition Global.java:65
MonthlyReportNodeTooltipCreator getMonthlyReportTooltip()
static void reportPlayerLeftCargoPods(SectorEntityToken entity)
static void clampOP(FleetMemberAPI member, MutableCharacterStatsAPI stats)
static void clampNumVentsAndCaps(FleetMemberAPI member, MutableCharacterStatsAPI stats)
void modifyFlat(String source, float value)
void reportBattleOccurred(CampaignFleetAPI primaryWinner, BattleAPI battle)
static void markSystemAsEntered(StarSystemAPI system, boolean withMessages)
void reportPlayerReputationChange(String faction, float delta)
void addExportsGroupedByCommodity(MonthlyReport report, FDNode parent, MarketAPI market, float f)
void reportPlayerReputationChange(PersonAPI person, float delta)
static void generateOrAddToDebrisFieldFromBattle(CampaignFleetAPI primaryWinner, BattleAPI battle)
static void addMiscToDropData(DropData data, FleetMemberAPI member, boolean weapons, boolean mods, boolean fighters)
void reportPlayerMarketTransaction(PlayerMarketTransaction transaction)
void reportFleetJumped(CampaignFleetAPI fleet, SectorEntityToken from, JumpDestination to)
static Set< String > getCargoCommodities(CargoAPI cargo)
static Map< String, InstallableItemEffect > ITEM_EFFECTS
static final String MEMORY_KEY_PLAYER_HOSTILE_ACTIVITY_NEAR_MARKET
static final String VARIANT_ALLOW_EXCESS_OP_ETC
Definition Tags.java:74
static SectorEntityToken addSalvageEntity(LocationAPI location, String id, String faction)
static ShipRecoverySpecialData getSpecialData(SectorEntityToken entity, String desc, boolean create, boolean replace)
void setPlayerLosingBattleTimestamp(long playerLosingBattleTimestamp)
void setPlayerPreLosingBattleFP(float playerPreLosingBattleFP)
void setPlayerPreLosingBattleCrew(float playerPreLosingBattleCrew)
static String getDGSCredits(float num)
Definition Misc.java:1390
static FleetInflater getInflater(CampaignFleetAPI fleet, Object params)
Definition Misc.java:4246
static float getStorageShipValue(MarketAPI market)
Definition Misc.java:4333
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1196
static SectorEntityToken addDebrisField(LocationAPI loc, DebrisFieldParams params, Random random)
Definition Misc.java:3262
static List< FleetMemberAPI > getSnapshotMembersLost(CampaignFleetAPI fleet)
Definition Misc.java:748
static Color getNegativeHighlightColor()
Definition Misc.java:802
static CargoAPI getStorageCargo(MarketAPI market)
Definition Misc.java:4307
static float getStorageCargoValue(MarketAPI market)
Definition Misc.java:4323
static Random getRandom(long seed, int level)
Definition Misc.java:2973
static CustomCampaignEntityAPI addCargoPods(LocationAPI where, Vector2f loc)
Definition Misc.java:3245
static boolean playerHasStorageAccess(MarketAPI market)
Definition Misc.java:4262
static Color getBasePlayerColor()
Definition Misc.java:833
static List< MarketAPI > findNearbyLocalMarkets(SectorEntityToken token, float maxDist, MarketFilter filter)
Definition Misc.java:1165
static void computeCoreWorldsExtent()
Definition Misc.java:6463
static float getAdminSalary(PersonAPI admin)
Definition Misc.java:4409
static Color getHighlightColor()
Definition Misc.java:792
static boolean setFlagWithReason(MemoryAPI memory, String flagKey, String reason, boolean value, float expire)
Definition Misc.java:1439
static float getSnapshotFPLost(CampaignFleetAPI fleet)
Definition Misc.java:738
static SimulatorPlugin getSimulatorPlugin()
Definition Misc.java:4213
static float getOfficerSalary(PersonAPI officer)
Definition Misc.java:4416
static boolean isEasy()
Definition Misc.java:2284
CampaignFleetAPI createEmptyFleet(String factionId, String name, boolean aiMode)
ListMap< String > getHullIdToVariantListMap()
String getSpriteName(String category, String id)
HullModSpecAPI getHullModSpec(String modId)
CommoditySpecAPI getCommoditySpec(String commodityId)
FighterWingSpecAPI getFighterWingSpec(String wingId)
WeaponSpecAPI getWeaponSpec(String weaponId)
SoundAPI playUISound(String id, float pitch, float volume)
List< CampaignFleetAPI > getNonPlayerSideSnapshot()
List< CampaignFleetAPI > getSnapshotSideOne()
List< CampaignFleetAPI > getSnapshotSideTwo()
void setInflater(FleetInflater inflater)
void addWeapons(String id, int count)
boolean removeItems(CargoAPI.CargoItemType itemType, Object data, float quantity)
void initMothballedShips(String factionId)
List< CargoStackAPI > getStacksCopy()
void addItems(CargoAPI.CargoItemType itemType, Object data, float quantity)
void addFighters(String id, int count)
FactionProductionAPI getProduction()
void setAccruedProduction(int accruedProduction)
void removeItem(ProductionItemType type, String specId, int count)
List< OfficerDataAPI > getOfficersCopy()
void addFleetMember(FleetMemberAPI member)
List< FleetMemberAPI > getMembersListCopy()
void addScript(EveryFrameScript script)
List< CampaignTerrainAPI > getTerrainCopy()
MutableCharacterStatsAPI getPlayerStats()
FactionAPI getFaction(String factionId)
void addDropRandom(String group, int chances)
void addDropValue(String group, int value)
void setDiscoverable(Boolean discoverable)
void setEnteredByPlayer(boolean enteredByPlayer)
void setSurveyLevel(SurveyLevel surveyLevel)
List< CommodityOnMarketAPI > getCommoditiesCopy()
void set(String key, Object value)
void reportPlayerBattleOccurred(CampaignFleetAPI primaryWinner, BattleAPI battle)