Starsector API
Loading...
Searching...
No Matches
EconomyFleetRouteManager.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.fleets;
2
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.Comparator;
6import java.util.HashMap;
7import java.util.List;
8import java.util.Map;
9import java.util.Random;
10
11import org.apache.log4j.Logger;
12
13import com.fs.starfarer.api.Global;
14import com.fs.starfarer.api.campaign.BattleAPI;
15import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
16import com.fs.starfarer.api.campaign.CampaignFleetAPI;
17import com.fs.starfarer.api.campaign.StarSystemAPI;
18import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
19import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
20import com.fs.starfarer.api.campaign.econ.MarketAPI;
21import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
22import com.fs.starfarer.api.impl.campaign.command.WarSimScript;
23import com.fs.starfarer.api.impl.campaign.command.WarSimScript.LocationDanger;
24import com.fs.starfarer.api.impl.campaign.econ.ShippingDisruption;
25import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetAssignmentAI.CargoQuantityData;
26import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetAssignmentAI.EconomyRouteData;
27import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
28import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
29import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
30import com.fs.starfarer.api.impl.campaign.ids.Commodities;
31import com.fs.starfarer.api.impl.campaign.ids.Factions;
32import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
33import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
34import com.fs.starfarer.api.impl.campaign.intel.misc.TradeFleetDepartureIntel;
35import com.fs.starfarer.api.impl.campaign.shared.SharedData;
36import com.fs.starfarer.api.util.Misc;
37import com.fs.starfarer.api.util.TimeoutTracker;
38import com.fs.starfarer.api.util.WeightedRandomPicker;
39
40public class EconomyFleetRouteManager extends BaseRouteFleetManager implements FleetEventListener {
41
42 public static final Integer ROUTE_SRC_LOAD = 1;
43 public static final Integer ROUTE_TRAVEL_DST = 2;
44 public static final Integer ROUTE_TRAVEL_WS = 3;
45 public static final Integer ROUTE_RESUPPLY_WS = 4;
46 public static final Integer ROUTE_DST_UNLOAD = 5;
47 public static final Integer ROUTE_DST_LOAD = 6;
48 public static final Integer ROUTE_TRAVEL_BACK_WS = 7;
49 public static final Integer ROUTE_RESUPPLY_BACK_WS = 8;
50 public static final Integer ROUTE_TRAVEL_SRC = 9;
51 public static final Integer ROUTE_SRC_UNLOAD = 10;
52
53 public static final String SOURCE_ID = "econ";
54 public static Logger log = Global.getLogger(EconomyFleetRouteManager.class);
55
56 public static Map<LocationDanger, Float> DANGER_LOSS_PROB = new HashMap<LocationDanger, Float>();
57 static {
58 DANGER_LOSS_PROB.put(LocationDanger.NONE, 0.01f);
59 DANGER_LOSS_PROB.put(LocationDanger.MINIMAL, 0.03f);
60 DANGER_LOSS_PROB.put(LocationDanger.LOW, 0.07f);
61 DANGER_LOSS_PROB.put(LocationDanger.MEDIUM, 0.1f);
62 DANGER_LOSS_PROB.put(LocationDanger.HIGH, 0.15f);
63 DANGER_LOSS_PROB.put(LocationDanger.EXTREME, 0.2f);
64 }
65
66
67 protected TimeoutTracker<String> recentlySentTradeFleet = new TimeoutTracker<String>();
68
70 //super(1f, 14f);
71 super(0.2f, 0.3f);
72 }
73
74 protected Object readResolve() {
75 if (recentlySentTradeFleet == null) {
76 recentlySentTradeFleet = new TimeoutTracker<String>();
77 }
78 return this;
79 }
80
81 @Override
82 public void advance(float amount) {
83 super.advance(amount);
84
85 float days = Global.getSector().getClock().convertToDays(amount);
86 recentlySentTradeFleet.advance(days);
87
88// MarketAPI from = pickSourceMarket();
89// MarketAPI to = pickDestMarket(from);
90 }
91
92 protected String getRouteSourceId() {
93 return SOURCE_ID;
94 }
95
96 protected int getMaxFleets() {
97 int numMarkets = Global.getSector().getEconomy().getNumMarkets();
98 int maxBasedOnMarkets = numMarkets * 2;
99 return Math.min(maxBasedOnMarkets, Global.getSettings().getInt("maxEconFleets"));
100 }
101
102
103 protected void addRouteFleetIfPossible() {
104 MarketAPI from = pickSourceMarket();
105 MarketAPI to = pickDestMarket(from);
106 if (from != null && to != null) {
107
108 EconomyRouteData data = createData(from, to);
109 if (data == null) return;
110
111 log.info("Added trade fleet route from " + from.getName() + " to " + to.getName());
112
113 Long seed = Misc.genRandomSeed();
114 String id = getRouteSourceId();
115
116 OptionalFleetData extra = new OptionalFleetData(from);
117 float tier = data.size;
118 float stability = from.getStabilityValue();
119 String factionId = from.getFactionId();
120 if (!from.getFaction().isHostileTo(Factions.INDEPENDENT) &&
121 !to.getFaction().isHostileTo(Factions.INDEPENDENT)) {
122 if ((float) Math.random() * 10f > stability + tier) {
123 factionId = Factions.INDEPENDENT;
124 }
125 }
126 if (data.smuggling) {
127 factionId = Factions.INDEPENDENT;
128 }
129 extra.factionId = factionId;
130
131 RouteData route = RouteManager.getInstance().addRoute(id, from, seed, extra, this);
132 route.setCustom(data);
133
134
135 StarSystemAPI sysFrom = data.from.getStarSystem();
136 StarSystemAPI sysTo = data.to.getStarSystem();
137
138// if (sysFrom.getName().startsWith("Rama") ||
139// sysTo.getName().startsWith("Rama")) {
140// System.out.println("32ff32f23");
141// }
142
143 LocationDanger dFrom = WarSimScript.getDangerFor(factionId, sysFrom);
144 LocationDanger dTo = WarSimScript.getDangerFor(factionId, sysTo);
145
146 LocationDanger danger = dFrom.ordinal() > dTo.ordinal() ? dFrom : dTo;
147
148 if (sysFrom != null && sysFrom.isCurrentLocation()) {
149 // the player is in the from location, don't auto-lose the trade fleet
150 // let it get destroyed by actual fleets, if it does
151 danger = LocationDanger.NONE;
152 }
153
154// if (danger != LocationDanger.NONE) {
155// System.out.println("efwe234523fwe " + danger.name());
156// dFrom = WarSimScript.getDangerFor(factionId, sysFrom);
157// dTo = WarSimScript.getDangerFor(factionId, sysTo);
158// }
159 float pLoss = DANGER_LOSS_PROB.get(danger);
160 if (data.smuggling) pLoss *= 0.5;
161 if ((float) Math.random() < pLoss) {
162 boolean returning = (float) Math.random() < 0.5f;
163 applyLostShipping(data, returning, true, true, true);
165 return;
166 }
167
168
169 //float distLY = Misc.getDistanceLY(from.getLocationInHyperspace(), to.getLocation());
170
171 float orbitDays = 2f + (float) Math.random() * 3f;
172 //float endDays = 8f + (float) Math.random() * 3f; // longer since includes time from jump-point to source
173
174 //orbitDays = 1f;
175 orbitDays = data.size * (0.75f + (float) Math.random() * 0.5f);
176
177// endDays = 0.5f;
178// float totalTravelTime = orbitDays + endDays + travelDays * 2f;
179
180 //boolean inSystem = from.getContainingLocation() == to.getContainingLocation();
181
182// WaystationBonus ws = Misc.getWaystation(from, to);
183// if (ws != null && !data.smuggling) {
184// route.addSegment(new RouteSegment(ROUTE_SRC_LOAD, orbitDays, from.getPrimaryEntity()));
185// route.addSegment(new RouteSegment(ROUTE_TRAVEL_WS, from.getPrimaryEntity(), ws.market.getPrimaryEntity()));
186// route.addSegment(new RouteSegment(ROUTE_RESUPPLY_WS, orbitDays, ws.market.getPrimaryEntity()));
187// route.addSegment(new RouteSegment(ROUTE_TRAVEL_DST, ws.market.getPrimaryEntity(), to.getPrimaryEntity()));
188// route.addSegment(new RouteSegment(ROUTE_DST_UNLOAD, orbitDays * 0.5f, to.getPrimaryEntity()));
189// route.addSegment(new RouteSegment(ROUTE_DST_LOAD, orbitDays * 0.5f, to.getPrimaryEntity()));
190// route.addSegment(new RouteSegment(ROUTE_TRAVEL_BACK_WS, to.getPrimaryEntity(), ws.market.getPrimaryEntity()));
191// route.addSegment(new RouteSegment(ROUTE_RESUPPLY_BACK_WS, orbitDays, ws.market.getPrimaryEntity()));
192// route.addSegment(new RouteSegment(ROUTE_TRAVEL_SRC, ws.market.getPrimaryEntity(), from.getPrimaryEntity()));
193// route.addSegment(new RouteSegment(ROUTE_SRC_UNLOAD, orbitDays, from.getPrimaryEntity()));
194// } else {
195 route.addSegment(new RouteSegment(ROUTE_SRC_LOAD, orbitDays, from.getPrimaryEntity()));
196 route.addSegment(new RouteSegment(ROUTE_TRAVEL_DST, from.getPrimaryEntity(), to.getPrimaryEntity()));
197 route.addSegment(new RouteSegment(ROUTE_DST_UNLOAD, orbitDays * 0.5f, to.getPrimaryEntity()));
198 route.addSegment(new RouteSegment(ROUTE_DST_LOAD, orbitDays * 0.5f, to.getPrimaryEntity()));
199 route.addSegment(new RouteSegment(ROUTE_TRAVEL_SRC, to.getPrimaryEntity(), from.getPrimaryEntity()));
200 route.addSegment(new RouteSegment(ROUTE_SRC_UNLOAD, orbitDays, from.getPrimaryEntity()));
201// }
202
204
205 recentlySentTradeFleet.add(from.getId(), Global.getSettings().getFloat("minEconSpawnIntervalPerMarket"));
206 }
207 }
208
209 protected void setDelayAndSendMessage(RouteData route) {
210 EconomyRouteData data = (EconomyRouteData) route.getCustom();
211
212 float delay = 0.1f;
213 delay = 10f;
214 if (data.size <= 4f) {
215 delay = 5f;
216 } else if (data.size <= 6f) {
217 delay = 10f;
218 } else {
219 delay = 15f;
220 }
221 delay *= 0.75f + (float) Math.random() * 0.5f;
222 delay = (int) delay;
223 route.setDelay(delay);
224
225 if (!Factions.PLAYER.equals(route.getFactionId())) {
226 // queues itself
227 new TradeFleetDepartureIntel(route);
228 }
229 }
230
231
232
233
234 public MarketAPI pickSourceMarket() {
235 //return Global.getSector().getEconomy().getMarket("jangala");
236 //return Global.getSector().getEconomy().getMarket("sindria");
237 //if (true) return Global.getSector().getEconomy().getMarket("chicomoztoc");
238
239 WeightedRandomPicker<MarketAPI> markets = new WeightedRandomPicker<MarketAPI>();
240 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
241 if (market.isHidden()) continue;
242 //float distLY = Misc.getDistanceToPlayerLY(market.getPrimaryEntity());
243 if (!market.hasSpaceport()) continue; // markets w/o spaceports don't launch fleets
244 if (SharedData.getData().getMarketsWithoutTradeFleetSpawn().contains(market.getId())) continue;
245
246// if (market.getId().equals("volturn")) {
247// return market;
248// }
249
250 if (recentlySentTradeFleet.contains(market.getId())) continue;
251
252 markets.add(market, market.getSize());
253
254// if (market.getName().toLowerCase().equals("jannow")) {
255// markets.add(market, 100000f);
256// }
257 }
258 return markets.pick();
259 }
260
261 public MarketAPI pickDestMarket(MarketAPI from) {
262 //return Global.getSector().getEconomy().getMarket("asharu");
263 //return Global.getSector().getEconomy().getMarket("chicomoztoc");
264 //if (true) return Global.getSector().getEconomy().getMarket("sindria");
265 if (from == null) return null;
266
267 WeightedRandomPicker<MarketAPI> markets = new WeightedRandomPicker<MarketAPI>();
268
269// com.getCommodityMarketData().getMarkets()
270// for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
271// if ((from.getEconGroup() == null && market.getEconGroup() != null) ||
272// (from.getEconGroup() != null && !from.getEconGroup().equals(market.getEconGroup()))) {
273// continue;
274// }
275// }
276
277 List<CommodityOnMarketAPI> relevant = new ArrayList<CommodityOnMarketAPI>();
278 for (CommodityOnMarketAPI com : from.getAllCommodities()) {
279 if (com.isNonEcon()) continue;
280
281 int exported = Math.min(com.getAvailable(), com.getMaxSupply());
282 int imported = Math.max(0, com.getMaxDemand() - exported);
283 if (imported > 0 || exported > 0) {
284 relevant.add(com);
285 }
286 }
287
288 for (MarketAPI market : Global.getSector().getEconomy().getMarketsInGroup(from.getEconGroup())) {
289 if (market.isHidden()) continue;
290 if (!market.hasSpaceport()) continue; // markets w/o spaceports don't launch fleets
291 if (SharedData.getData().getMarketsWithoutTradeFleetSpawn().contains(market.getId())) continue;
292 if (market == from) continue;
293
294 int shipping = Misc.getShippingCapacity(market, market.getFaction() == from.getFaction());
295 if (shipping <= 0) continue;
296
297 float w = 0f;
298 for (CommodityOnMarketAPI com : relevant) {
299 int exported = Math.min(com.getAvailable(), com.getMaxSupply());
300 exported = Math.min(exported, shipping);
301 int imported = Math.max(0, com.getMaxDemand() - exported);
302 imported = Math.min(imported, shipping);
303
304 CommodityOnMarketAPI other = market.getCommodityData(com.getId());
305 exported = Math.min(exported, other.getMaxDemand() - other.getMaxSupply());
306 if (exported < 0) exported = 0;
307 imported = Math.min(imported, Math.min(other.getAvailable(), other.getMaxSupply()));
308
309 w += imported;
310 w += exported;
311 }
312
313 if (from.getFaction().isHostileTo(market.getFaction())) {
314 w *= 0.25f;
315 }
316 markets.add(market, w);
317 }
318
319 return markets.pick();
320
321// for (CommodityOnMarketAPI com : from.getCommoditiesCopy()) {
322//
323// SupplierData sd = com.getSupplier();
324// if (sd != null) {
325// if (sd.getMarket() == from) continue;
326// if (SharedData.getData().getMarketsWithoutTradeFleetSpawn().contains(sd.getMarket().getId())) continue;
327// markets.add(sd.getMarket(), sd.getQuantity());
328// }
329// for (SupplierData curr : com.getExports()) {
330// if (curr.getMarket() == from) continue;
331// if (SharedData.getData().getMarketsWithoutTradeFleetSpawn().contains(sd.getMarket().getId())) continue;
332// markets.add(curr.getMarket(), curr.getQuantity());
333// }
334// }
335// return markets.pick();
336
337 }
338
339 public static EconomyRouteData createData(MarketAPI from, MarketAPI to) {
340 EconomyRouteData smuggling = new EconomyRouteData();
341 smuggling.from = from;
342 smuggling.to = to;
343 smuggling.smuggling = true;
344
345 EconomyRouteData legal = new EconomyRouteData();
346 legal.from = from;
347 legal.to = to;
348 legal.smuggling = false;
349
350 float legalTotal = 0;
351 float smugglingTotal = 0;
352
353
354 List<CommodityOnMarketAPI> relevant = new ArrayList<CommodityOnMarketAPI>();
355 for (CommodityOnMarketAPI com : from.getAllCommodities()) {
356 if (com.isNonEcon()) continue;
357 CommodityOnMarketAPI orig = com;
358 int exported = Math.min(com.getAvailable(), com.getMaxSupply());
359 if (!com.getCommodity().isPrimary()) {
360 com = from.getCommodityData(com.getCommodity().getDemandClass());
361 }
362
363 int imported = Math.max(0, com.getMaxDemand() - exported);
364 if (imported > 0 || exported > 0) {
365 relevant.add(orig);
366 }
367 }
368
369 int shipping = Misc.getShippingCapacity(from, to.getFaction() == from.getFaction());
370 for (CommodityOnMarketAPI com : relevant) {
371 CommodityOnMarketAPI orig = com;
372 int exported = Math.min(com.getAvailable(), com.getMaxSupply());
373 exported = Math.min(exported, shipping);
374
375 if (!com.getCommodity().isPrimary()) {
376 com = from.getCommodityData(com.getCommodity().getDemandClass());
377 }
378
379 int imported = Math.max(0, com.getMaxDemand() - exported);
380 imported = Math.min(imported, shipping);
381 if (orig != com) imported = 0;
382
383 CommodityOnMarketAPI other = to.getCommodityData(com.getId());
384 exported = Math.min(exported, other.getMaxDemand() - other.getMaxSupply());
385 if (exported < 0) exported = 0;
386 imported = Math.min(imported, Math.min(other.getAvailable(), other.getMaxSupply()));
387
388 if (imported < 0) imported = 0;
389
390 if (imported <= 0 && exported <= 0) continue;
391
392 boolean illegal = com.getCommodityMarketData().getMarketShareData(from).isSourceIsIllegal() ||
393 com.getCommodityMarketData().getMarketShareData(to).isSourceIsIllegal() ||
394 from.getFaction().isHostileTo(to.getFaction());
395
396 if (imported > exported) {
397 if (illegal) {
398 smuggling.addReturn(orig.getId(), imported);
399 smugglingTotal += imported;
400 } else {
401 legal.addReturn(orig.getId(), imported);
402 legalTotal += imported;
403 }
404 } else {
405 if (illegal) {
406 smuggling.addDeliver(orig.getId(), exported);
407 smugglingTotal += exported;
408 } else {
409 legal.addDeliver(orig.getId(), exported);
410 legalTotal += exported;
411 }
412 }
413 }
414
415 Comparator<CargoQuantityData> comp = new Comparator<CargoQuantityData>() {
416 public int compare(CargoQuantityData o1, CargoQuantityData o2) {
417 if (o1.getCommodity().isPersonnel() && !o2.getCommodity().isPersonnel()) {
418 return 1;
419 }
420 if (o2.getCommodity().isPersonnel() && !o1.getCommodity().isPersonnel()) {
421 return -1;
422 }
423 return o2.units - o1.units;
424 }
425 };
426 Collections.sort(legal.cargoDeliver, comp);
427 Collections.sort(legal.cargoReturn, comp);
428 Collections.sort(smuggling.cargoDeliver, comp);
429 Collections.sort(smuggling.cargoReturn, comp);
430
431 if (smugglingTotal <= 0 && legalTotal <= 0) return null;
432
433 EconomyRouteData data = null;
434 if ((float) Math.random() * (smugglingTotal + legalTotal) < smugglingTotal) {
435 data = smuggling;
436 } else {
437 data = legal;
438 }
439
440 while (data.cargoDeliver.size() > 4) {
441 data.cargoDeliver.remove(4);
442 }
443 while (data.cargoReturn.size() > 4) {
444 data.cargoReturn.remove(4);
445 }
446
447// data.cargoDeliver = data.cargoDeliver.subList(0, Math.min(data.cargoDeliver.size(), 4));
448// data.cargoReturn = data.cargoReturn.subList(0, Math.min(data.cargoReturn.size(), 4));
449
450// data.cargoDeliver.clear();
451// data.cargoReturn.clear();
452// data.addDeliver(Commodities.SHIPS, 5);
453
454 float max = 0f;
455 for (CargoQuantityData curr : data.cargoDeliver) {
456 if (curr.units > max) max = curr.units;
457 }
458 for (CargoQuantityData curr : data.cargoReturn) {
459 if (curr.units > max) max = curr.units;
460 }
461
462 int types = Math.max(data.cargoDeliver.size(), data.cargoReturn.size());
463 if (types >= 3) {
464 data.size++;
465 }
466 if (types >= 4) {
467 data.size++;
468 }
469
470 data.size = max;
471
472
473 return data;
474 }
475
476
477
478 public boolean shouldCancelRouteAfterDelayCheck(RouteData route) {
479 String factionId = route.getFactionId();
480
481 boolean smuggling = false;
482 if (route.getCustom() instanceof EconomyRouteData) {
483 smuggling = ((EconomyRouteData) route.getCustom()).smuggling;
484 }
485
486 if (factionId != null && route.getMarket() != null && !smuggling &&
487 route.getMarket().getFaction().isHostileTo(factionId)) {
488 return true;
489 }
490 return false;
491 }
492
493
494 public CampaignFleetAPI spawnFleet(RouteData route) {
495 Random random = new Random();
496 if (route.getSeed() != null) {
497 random = new Random(route.getSeed());
498 }
499
500 CampaignFleetAPI fleet = createTradeRouteFleet(route, random);
501 if (fleet == null) return null;;
502
503 //fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_TRADE_FLEET, true);
504
505 fleet.addEventListener(this);
506
507 fleet.addScript(new EconomyFleetAssignmentAI(fleet, route));
508 return fleet;
509 }
510
511
512 public static String getFleetTypeIdForTier(float tier, boolean smuggling) {
513 String type = FleetTypes.TRADE;
514 if (tier <= 3) type = FleetTypes.TRADE_SMALL;
515 if (smuggling) {
516 type = FleetTypes.TRADE_SMUGGLER;
517 }
518 return type;
519 }
520
521 public static CampaignFleetAPI createTradeRouteFleet(RouteData route, Random random) {
522 EconomyRouteData data = (EconomyRouteData) route.getCustom();
523
524 MarketAPI from = data.from;
525 MarketAPI to = data.to;
526
527// if (from.getId().equals("umbra")) {
528// System.out.println("wefwefw");
529// }
530
531 float tier = data.size;
532
533 if (data.smuggling && tier > 4) {
534 tier = 4;
535 }
536
537// data.smuggling = false;
538// tier = 4;
539
540// float stability = from.getStabilityValue();
541// String factionId = from.getFactionId();
542// if (!from.getFaction().isHostileTo(Factions.INDEPENDENT) &&
543// !to.getFaction().isHostileTo(Factions.INDEPENDENT)) {
544// if ((float) Math.random() * 10f > stability + tier) {
545// factionId = Factions.INDEPENDENT;
546// }
547// }
548//
549// if (data.smuggling) {
550// factionId = Factions.INDEPENDENT;
551// }
552 String factionId = route.getFactionId();
553
554 float total = 0f;
555 float fuel = 0f;
556 float cargo = 0f;
557 float personnel = 0f;
558 //float ships = 0f;
559
560 List<CargoQuantityData> all = new ArrayList<CargoQuantityData>();
561 all.addAll(data.cargoDeliver);
562 all.addAll(data.cargoReturn);
563 for (CargoQuantityData curr : all) {
564 CommoditySpecAPI spec = curr.getCommodity();
565// if (spec.getId().equals(Commodities.SHIPS)) {
566// ships = Math.max(ships, curr.units);
567// }
568 if (spec.isMeta()) continue;
569
570 total += curr.units;
571 if (spec.hasTag(Commodities.TAG_PERSONNEL)) {
572 personnel += curr.units;
573 } else if (spec.getId().equals(Commodities.FUEL)) {
574 fuel += curr.units;
575 } else {
576 cargo += curr.units;
577 }
578 }
579
580// System.out.println("Ships: " + ships);
581 if (total < 1f) total = 1f;
582
583 float fuelFraction = fuel / total;
584 float personnelFraction = personnel / total;
585 float cargoFraction = cargo / total;
586
587// fuelFraction = 0.33f;
588// personnelFraction = 0.33f;
589// cargoFraction = 0.33f;
590
591 if (fuelFraction + personnelFraction + cargoFraction > 0) {
592 float mult = 1f / (fuelFraction + personnelFraction + cargoFraction);
593 fuelFraction *= mult;
594 personnelFraction *= mult;
595 cargoFraction *= mult;
596 }
597
598 log.info("Creating trade fleet of tier " + tier + " for market [" + from.getName() + "]");
599
600 float stabilityFactor = 1f + from.getStabilityValue() / 20f;
601
602 float combat = Math.max(1f, tier * stabilityFactor * 0.5f) * 10f;
603 float freighter = tier * 2f * cargoFraction * 3f;
604 float tanker = tier * 2f * fuelFraction * 3f;
605 float transport = tier * 2f * personnelFraction * 3f;
606 float liner = 0f;
607
608 //float utility = 1f + tier * 0.25f;
609 float utility = 0f;
610
611 String type = getFleetTypeIdForTier(tier, data.smuggling);
612 if (data.smuggling) {
613 //combat *= 2f;
614 freighter *= 0.5f;
615 tanker *= 0.5f;
616 transport *= 0.5f;
617 liner *= 0.5f;
618 }
619
620 FleetParamsV3 params = new FleetParamsV3(
621 from,
622 null, // locInHyper
623 factionId,
624 route.getQualityOverride(), // qualityOverride
625 type,
626 combat, // combatPts
627 freighter, // freighterPts
628 tanker, // tankerPts
629 transport, // transportPts
630 liner, // linerPts
631 utility, // utilityPts
632 0f //-0.5f // qualityBonus
633 );
634 params.timestamp = route.getTimestamp();
635 params.onlyApplyFleetSizeToCombatShips = true;
636 params.maxShipSize = 3;
637 params.officerLevelBonus = -2;
638 params.officerNumberMult = 0.5f;
639 params.random = random;
640 CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params);
641
642 if (fleet == null || fleet.isEmpty()) return null;
643
644 if (Misc.isPirateFaction(fleet.getFaction())) {
645 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_FORCE_TRANSPONDER_OFF, true);
646 }
647
648 if (data.smuggling) {
649 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_SMUGGLER, true);
650 Misc.makeLowRepImpact(fleet, "smuggler");
651 } else {
652 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_TRADE_FLEET, true);
653 }
654
655 //cargoCap, fuelCap, personnelCap;
656 data.cargoCap = fleet.getCargo().getMaxCapacity();
657 data.fuelCap = fleet.getCargo().getMaxFuel();
658 data.personnelCap = fleet.getCargo().getMaxPersonnel();
659
660 //ShippingDisruption.getShippingDisruption(from).getShippingPenalty().addTemporaryModFlat(1f, "fwefwe", 1f);
661
662 return fleet;
663
664 }
665
666 public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
667 // already reduced by losses taken
668 //System.out.println("Cargo: " + fleet.getCargo().getMaxCapacity());
669
670 RouteData route = RouteManager.getInstance().getRoute(getRouteSourceId(), fleet);
671 if (route == null || !(route.getCustom() instanceof EconomyRouteData)) return;
672
673 if (route.isExpired()) return;
674
675 EconomyRouteData data = (EconomyRouteData) route.getCustom();
676
677 float cargoCap = fleet.getCargo().getMaxCapacity();
678 float fuelCap = fleet.getCargo().getMaxFuel();
679 float personnelCap = fleet.getCargo().getMaxPersonnel();
680
681 float lossFraction = 0.34f;
682
683 //boolean returning = route.getCurrentIndex() >= 3;
684 boolean returning = false;
685 if (route.getCurrent() != null && route.getCurrentSegmentId() >= ROUTE_DST_LOAD) {
686 returning = true;
687 }
688
689 // whether it lost enough carrying capacity to count as an economic loss
690 // of that commodity at destination markets
691 boolean lostCargo = data.cargoCap * lossFraction > cargoCap;
692 boolean lostFuel = data.fuelCap * lossFraction > fuelCap;
693 boolean lostPersonnel = data.personnelCap * lossFraction > personnelCap;
694
695 // set to 0f so that the loss doesn't happen multiple times for a commodity
696 if (lostCargo) data.cargoCap = 0f;
697 if (lostFuel) data.fuelCap = 0f;
698 if (lostPersonnel) data.personnelCap = 0f;
699
700 applyLostShipping(data, returning, lostCargo, lostFuel, lostPersonnel);
701
702 // if it's lost all 3 capacities, also trigger a general shipping capacity loss at market
703 boolean allThreeLost = true;
704 allThreeLost &= data.cargoCap <= 0f || lostCargo;
705 allThreeLost &= data.fuelCap <= 0f || lostFuel;
706 allThreeLost &= data.personnelCap <= 0f || lostPersonnel;
707// if (fullyLost) {
708
709 boolean applyAccessLoss = allThreeLost;
710 if (applyAccessLoss) {
711 ShippingDisruption.getDisruption(data.from).addShippingLost(data.size);
712 ShippingDisruption.getDisruption(data.from).notifyDisrupted(ShippingDisruption.ACCESS_LOSS_DURATION);
713 }
714
715 }
716
717
718 public static void applyLostShipping(EconomyRouteData data, boolean returning, boolean cargo, boolean fuel, boolean personnel) {
719 if (!cargo && !fuel && !personnel) return;
720
721 int penalty = 1;
722 int penalty2 = 2;
723 if (!returning) {
724 for (CargoQuantityData curr : data.cargoDeliver) {
725 CommodityOnMarketAPI com = data.to.getCommodityData(curr.cargo);
726 if (!fuel && com.isFuel()) continue;
727 if (!personnel && com.isPersonnel()) continue;
728 if (!cargo && !com.isFuel() && !com.isPersonnel()) continue;
729
730 com.getAvailableStat().addTemporaryModFlat(
731 ShippingDisruption.ACCESS_LOSS_DURATION,
732 ShippingDisruption.COMMODITY_LOSS_PREFIX + Misc.genUID(), "Recent incoming shipment lost", -penalty2);
733
734 ShippingDisruption.getDisruption(data.to).notifyDisrupted(ShippingDisruption.ACCESS_LOSS_DURATION);
735 }
736 }
737 for (CargoQuantityData curr : data.cargoReturn) {
738 CommodityOnMarketAPI com = data.from.getCommodityData(curr.cargo);
739 if (!fuel && com.isFuel()) continue;
740 if (!personnel && com.isPersonnel()) continue;
741 if (!cargo && !com.isFuel() && !com.isPersonnel()) continue;
742
743 com.getAvailableStat().addTemporaryModFlat(
744 ShippingDisruption.ACCESS_LOSS_DURATION,
745 ShippingDisruption.COMMODITY_LOSS_PREFIX + Misc.genUID(), "Recent incoming shipment lost", -penalty2);
746
747 ShippingDisruption.getDisruption(data.from).notifyDisrupted(ShippingDisruption.ACCESS_LOSS_DURATION);
748 }
749 }
750
751
752 public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
753
754 }
755
756 public boolean shouldRepeat(RouteData route) {
757 return false;
758 }
759
760 public void reportAboutToBeDespawnedByRouteManager(RouteData route) {
761
762 }
763
764
765}
766
767
768
769
770
771
772
static SettingsAPI getSettings()
Definition Global.java:51
static Logger getLogger(Class c)
Definition Global.java:26
static SectorAPI getSector()
Definition Global.java:59
static CampaignFleetAPI createTradeRouteFleet(RouteData route, Random random)
static EconomyRouteData createData(MarketAPI from, MarketAPI to)
void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle)
void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
static void applyLostShipping(EconomyRouteData data, boolean returning, boolean cargo, boolean fuel, boolean personnel)
static CampaignFleetAPI createFleet(FleetParamsV3 params)
RouteData addRoute(String source, MarketAPI market, Long seed, OptionalFleetData extra, RouteFleetSpawner spawner)
RouteData getRoute(String source, CampaignFleetAPI fleet)