106 if (from !=
null && to !=
null) {
109 if (data ==
null)
return;
111 log.info(
"Added trade fleet route from " + from.getName() +
" to " + to.getName());
113 Long seed = Misc.genRandomSeed();
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;
126 if (data.smuggling) {
127 factionId = Factions.INDEPENDENT;
129 extra.factionId = factionId;
132 route.setCustom(data);
135 StarSystemAPI sysFrom = data.from.getStarSystem();
136 StarSystemAPI sysTo = data.to.getStarSystem();
143 LocationDanger dFrom = WarSimScript.getDangerFor(factionId, sysFrom);
144 LocationDanger dTo = WarSimScript.getDangerFor(factionId, sysTo);
146 LocationDanger danger = dFrom.ordinal() > dTo.ordinal() ? dFrom : dTo;
148 if (sysFrom !=
null && sysFrom.isCurrentLocation()) {
151 danger = LocationDanger.NONE;
160 if (data.smuggling) pLoss *= 0.5;
161 if ((
float) Math.random() < pLoss) {
162 boolean returning = (float) Math.random() < 0.5f;
171 float orbitDays = 2f + (float) Math.random() * 3f;
175 orbitDays = data.size * (0.75f + (float) Math.random() * 0.5f);
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()));
265 if (from ==
null)
return null;
267 WeightedRandomPicker<MarketAPI> markets =
new WeightedRandomPicker<MarketAPI>();
277 List<CommodityOnMarketAPI> relevant =
new ArrayList<CommodityOnMarketAPI>();
278 for (CommodityOnMarketAPI com : from.getAllCommodities()) {
279 if (com.isNonEcon())
continue;
281 int exported = Math.min(com.getAvailable(), com.getMaxSupply());
282 int imported = Math.max(0, com.getMaxDemand() - exported);
283 if (imported > 0 || exported > 0) {
288 for (MarketAPI market :
Global.
getSector().getEconomy().getMarketsInGroup(from.getEconGroup())) {
289 if (market.isHidden())
continue;
290 if (!market.hasSpaceport())
continue;
291 if (SharedData.getData().getMarketsWithoutTradeFleetSpawn().contains(market.getId()))
continue;
292 if (market == from)
continue;
294 int shipping = Misc.getShippingCapacity(market, market.getFaction() == from.getFaction());
295 if (shipping <= 0)
continue;
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);
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()));
313 if (from.getFaction().isHostileTo(market.getFaction())) {
316 markets.add(market, w);
319 return markets.pick();
339 public static EconomyRouteData
createData(MarketAPI from, MarketAPI to) {
340 EconomyRouteData smuggling =
new EconomyRouteData();
341 smuggling.from = from;
343 smuggling.smuggling =
true;
345 EconomyRouteData legal =
new EconomyRouteData();
348 legal.smuggling =
false;
350 float legalTotal = 0;
351 float smugglingTotal = 0;
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());
363 int imported = Math.max(0, com.getMaxDemand() - exported);
364 if (imported > 0 || exported > 0) {
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);
375 if (!com.getCommodity().isPrimary()) {
376 com = from.getCommodityData(com.getCommodity().getDemandClass());
379 int imported = Math.max(0, com.getMaxDemand() - exported);
380 imported = Math.min(imported, shipping);
381 if (orig != com) imported = 0;
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()));
388 if (imported < 0) imported = 0;
390 if (imported <= 0 && exported <= 0)
continue;
392 boolean illegal = com.getCommodityMarketData().getMarketShareData(from).isSourceIsIllegal() ||
393 com.getCommodityMarketData().getMarketShareData(to).isSourceIsIllegal() ||
394 from.getFaction().isHostileTo(to.getFaction());
396 if (imported > exported) {
398 smuggling.addReturn(orig.getId(), imported);
399 smugglingTotal += imported;
401 legal.addReturn(orig.getId(), imported);
402 legalTotal += imported;
406 smuggling.addDeliver(orig.getId(), exported);
407 smugglingTotal += exported;
409 legal.addDeliver(orig.getId(), exported);
410 legalTotal += exported;
415 Comparator<CargoQuantityData> comp =
new Comparator<CargoQuantityData>() {
416 public int compare(CargoQuantityData o1, CargoQuantityData o2) {
417 if (o1.getCommodity().isPersonnel() && !o2.getCommodity().isPersonnel()) {
420 if (o2.getCommodity().isPersonnel() && !o1.getCommodity().isPersonnel()) {
423 return o2.units - o1.units;
426 Collections.sort(legal.cargoDeliver, comp);
427 Collections.sort(legal.cargoReturn, comp);
428 Collections.sort(smuggling.cargoDeliver, comp);
429 Collections.sort(smuggling.cargoReturn, comp);
431 if (smugglingTotal <= 0 && legalTotal <= 0)
return null;
433 EconomyRouteData data =
null;
434 if ((
float) Math.random() * (smugglingTotal + legalTotal) < smugglingTotal) {
440 while (data.cargoDeliver.size() > 4) {
441 data.cargoDeliver.remove(4);
443 while (data.cargoReturn.size() > 4) {
444 data.cargoReturn.remove(4);
455 for (CargoQuantityData curr : data.cargoDeliver) {
456 if (curr.units > max) max = curr.units;
458 for (CargoQuantityData curr : data.cargoReturn) {
459 if (curr.units > max) max = curr.units;
462 int types = Math.max(data.cargoDeliver.size(), data.cargoReturn.size());
522 EconomyRouteData data = (EconomyRouteData) route.getCustom();
524 MarketAPI from = data.from;
525 MarketAPI to = data.to;
531 float tier = data.size;
533 if (data.smuggling && tier > 4) {
552 String factionId = route.getFactionId();
557 float personnel = 0f;
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();
568 if (spec.isMeta())
continue;
571 if (spec.hasTag(Commodities.TAG_PERSONNEL)) {
572 personnel += curr.units;
573 }
else if (spec.getId().equals(Commodities.FUEL)) {
581 if (total < 1f) total = 1f;
583 float fuelFraction = fuel / total;
584 float personnelFraction = personnel / total;
585 float cargoFraction = cargo / total;
591 if (fuelFraction + personnelFraction + cargoFraction > 0) {
592 float mult = 1f / (fuelFraction + personnelFraction + cargoFraction);
593 fuelFraction *= mult;
594 personnelFraction *= mult;
595 cargoFraction *= mult;
598 log.info(
"Creating trade fleet of tier " + tier +
" for market [" + from.getName() +
"]");
600 float stabilityFactor = 1f + from.getStabilityValue() / 20f;
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;
612 if (data.smuggling) {
624 route.getQualityOverride(),
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;
642 if (fleet ==
null || fleet.isEmpty())
return null;
644 if (Misc.isPirateFaction(fleet.getFaction())) {
645 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_FORCE_TRANSPONDER_OFF,
true);
648 if (data.smuggling) {
649 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_SMUGGLER,
true);
650 Misc.makeLowRepImpact(fleet,
"smuggler");
652 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_TRADE_FLEET,
true);
656 data.cargoCap = fleet.getCargo().getMaxCapacity();
657 data.fuelCap = fleet.getCargo().getMaxFuel();
658 data.personnelCap = fleet.getCargo().getMaxPersonnel();
671 if (route ==
null || !(route.getCustom() instanceof EconomyRouteData))
return;
673 if (route.isExpired())
return;
675 EconomyRouteData data = (EconomyRouteData) route.getCustom();
677 float cargoCap = fleet.getCargo().getMaxCapacity();
678 float fuelCap = fleet.getCargo().getMaxFuel();
679 float personnelCap = fleet.getCargo().getMaxPersonnel();
681 float lossFraction = 0.34f;
684 boolean returning =
false;
685 if (route.getCurrent() !=
null && route.getCurrentSegmentId() >=
ROUTE_DST_LOAD) {
691 boolean lostCargo = data.cargoCap * lossFraction > cargoCap;
692 boolean lostFuel = data.fuelCap * lossFraction > fuelCap;
693 boolean lostPersonnel = data.personnelCap * lossFraction > personnelCap;
696 if (lostCargo) data.cargoCap = 0f;
697 if (lostFuel) data.fuelCap = 0f;
698 if (lostPersonnel) data.personnelCap = 0f;
703 boolean allThreeLost =
true;
704 allThreeLost &= data.cargoCap <= 0f || lostCargo;
705 allThreeLost &= data.fuelCap <= 0f || lostFuel;
706 allThreeLost &= data.personnelCap <= 0f || lostPersonnel;
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);
718 public static void applyLostShipping(EconomyRouteData data,
boolean returning,
boolean cargo,
boolean fuel,
boolean personnel) {
719 if (!cargo && !fuel && !personnel)
return;
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;
730 com.getAvailableStat().addTemporaryModFlat(
731 ShippingDisruption.ACCESS_LOSS_DURATION,
732 ShippingDisruption.COMMODITY_LOSS_PREFIX + Misc.genUID(),
"Recent incoming shipment lost", -penalty2);
734 ShippingDisruption.getDisruption(data.to).notifyDisrupted(ShippingDisruption.ACCESS_LOSS_DURATION);
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;
743 com.getAvailableStat().addTemporaryModFlat(
744 ShippingDisruption.ACCESS_LOSS_DURATION,
745 ShippingDisruption.COMMODITY_LOSS_PREFIX + Misc.genUID(),
"Recent incoming shipment lost", -penalty2);
747 ShippingDisruption.getDisruption(data.from).notifyDisrupted(ShippingDisruption.ACCESS_LOSS_DURATION);