117 float days = Misc.getDays(amount);
119 Set<FactionAPI> seen =
new HashSet<FactionAPI>();
120 for (MarketAPI market :
Global.
getSector().getEconomy().getMarketsInGroup(
null)) {
125 FactionAPI faction = market.getFaction();
126 if (Misc.getCommissionFaction() == faction)
continue;
128 if (seen.contains(faction) ||
data.containsKey(faction)) {
132 JSONObject json = faction.getCustomJSONObject(Factions.CUSTOM_PUNITIVE_EXPEDITION_DATA);
134 PunExData curr =
new PunExData();
135 curr.faction = faction;
136 data.put(faction, curr);
141 data.keySet().retainAll(seen);
144 timeout -= days * (DebugFlags.PUNITIVE_EXPEDITION_DEBUG ? 1000f : 1f);
152 boolean first =
true;
153 for (PunExData curr :
data.values()) {
161 if (curr.intel !=
null) {
162 if (curr.intel.isEnded()) {
163 curr.timeout = 100f + 100f * curr.random.nextFloat();
175 curr.timeout -= days;
176 if (curr.timeout <= 0) curr.timeout = 0;
180 curr.tracker.advance(days);
182 if (curr.tracker.intervalElapsed() &&
183 curr.intel ==
null &&
258 List<PunExReason> result =
new ArrayList<PunExReason>();
260 JSONObject json = curr.faction.getCustom().optJSONObject(Factions.CUSTOM_PUNITIVE_EXPEDITION_DATA);
261 if (json ==
null)
return result;
263 List<MarketAPI> markets = Misc.getFactionMarkets(curr.faction,
null);
264 if (markets.isEmpty())
return result;
266 boolean vsCompetitors = json.optBoolean(
"vsCompetitors",
false);
267 boolean vsFreePort = json.optBoolean(
"vsFreePort",
false);
268 boolean territorial = json.optBoolean(
"territorial",
false);
270 MarketAPI test = markets.get(0);
274 for (CommodityOnMarketAPI com : test.getAllCommodities()) {
275 if (com.isNonEcon())
continue;
276 if (curr.faction.isIllegal(com.getId()))
continue;
278 CommodityMarketDataAPI cmd = com.getCommodityMarketData();
279 if (cmd.getMarketValue() <= 0)
continue;
281 Map<FactionAPI, Integer> shares = cmd.getMarketSharePercentPerFaction();
283 int factionShare = shares.get(curr.faction);
284 if (factionShare <= 0)
continue;
286 for (FactionAPI faction : shares.keySet()) {
287 if (curr.faction == faction)
continue;
288 if (shares.get(faction) > factionShare) {
295 int playerShare = cmd.getMarketSharePercent(player);
300 if (playerShare < factionShare * threshold || playerShare <= 0)
continue;
302 PunExReason reason =
new PunExReason(PunExType.ANTI_COMPETITION);
304 reason.commodityId = com.getId();
310 for (MarketAPI market :
Global.
getSector().getEconomy().getMarketsInGroup(
null)) {
311 if (!market.isPlayerOwned())
continue;
312 if (!market.isFreePort())
continue;
313 if (market.isInHyperspace())
continue;
315 for (CommodityOnMarketAPI com : test.getAllCommodities()) {
316 if (com.isNonEcon())
continue;
317 if (!curr.faction.isIllegal(com.getId()))
continue;
319 CommodityMarketDataAPI cmd = com.getCommodityMarketData();
320 if (cmd.getMarketValue() <= 0)
continue;
322 int playerShare = cmd.getMarketSharePercent(player);
323 if (playerShare <= 0)
continue;
325 PunExReason reason =
new PunExReason(PunExType.ANTI_FREE_PORT);
327 reason.commodityId = com.getId();
328 reason.marketId = market.getId();
332 if (market.isFreePort()) {
333 PunExReason reason =
new PunExReason(PunExType.ANTI_FREE_PORT);
335 reason.marketId = market.getId();
342 int maxSize = MarketCMD.getBombardDestroyThreshold();
343 for (MarketAPI market :
Global.
getSector().getEconomy().getMarketsInGroup(
null)) {
344 if (!market.isPlayerOwned())
continue;
345 if (market.isInHyperspace())
continue;
347 boolean destroy = market.getSize() <= maxSize;
348 if (!destroy)
continue;
350 FactionAPI claimedBy = Misc.getClaimingFaction(market.getPrimaryEntity());
351 if (claimedBy != curr.faction)
continue;
353 PunExReason reason =
new PunExReason(PunExType.TERRITORIAL);
355 reason.marketId = market.getId();
369 JSONObject json = curr.faction.getCustom().optJSONObject(Factions.CUSTOM_PUNITIVE_EXPEDITION_DATA);
370 if (json ==
null)
return;
374 boolean canBombard = json.optBoolean(
"canBombard",
false);
378 WeightedRandomPicker<PunExReason> reasonPicker =
new WeightedRandomPicker<PunExReason>(curr.random);
379 for (PunExReason r : reasons) {
381 reasonPicker.add(r, r.weight);
383 PunExReason reason = reasonPicker.pick();
384 if (reason ==
null)
return;
387 WeightedRandomPicker<MarketAPI> targetPicker =
new WeightedRandomPicker<MarketAPI>(curr.random);
391 for (MarketAPI market :
Global.
getSector().getEconomy().getMarketsCopy()) {
392 if (!market.isPlayerOwned())
continue;
393 if (market.isInHyperspace())
continue;
396 if (reason.type == PunExType.ANTI_COMPETITION && reason.commodityId !=
null) {
399 CommodityOnMarketAPI com = market.getCommodityData(reason.commodityId);
400 int share = com.getCommodityMarketData().getExportMarketSharePercent(market);
404 weight += share * share;
405 }
else if (reason.type == PunExType.ANTI_FREE_PORT && market.getId().equals(reason.marketId)) {
409 }
else if (reason.type == PunExType.TERRITORIAL && market.getId().equals(reason.marketId)) {
413 targetPicker.add(market, weight);
416 MarketAPI target = targetPicker.pick();
417 if (target ==
null)
return;
419 WeightedRandomPicker<MarketAPI> picker =
new WeightedRandomPicker<MarketAPI>(curr.random);
420 for (MarketAPI market :
Global.
getSector().getEconomy().getMarketsInGroup(
null)) {
421 boolean canSendWithoutMilitaryBase = json.optBoolean(
"canSendWithoutMilitaryBase",
false);
422 boolean military = market.getMemoryWithoutUpdate().getBoolean(MemFlags.MARKET_MILITARY);
423 if (market.getFaction() == curr.faction &&
424 (military || canSendWithoutMilitaryBase)) {
426 if (military) w *= 10f;
427 picker.add(market, market.getSize() * w);
431 MarketAPI from = picker.pick();
432 if (from ==
null)
return;
434 PunExGoal goal =
null;
435 Industry industry =
null;
436 if (reason.type == PunExType.ANTI_FREE_PORT) {
437 goal = PunExGoal.RAID_SPACEPORT;
438 if (canBombard && curr.numSuccesses >= 2) {
439 goal = PunExGoal.BOMBARD;
441 }
else if (reason.type == PunExType.TERRITORIAL) {
442 if (canBombard ||
true) {
443 goal = PunExGoal.BOMBARD;
448 goal = PunExGoal.RAID_PRODUCTION;
449 if (reason.commodityId ==
null || curr.numSuccesses >= 1) {
450 goal = PunExGoal.RAID_SPACEPORT;
452 if (canBombard && curr.numSuccesses >= 2) {
453 goal = PunExGoal.BOMBARD;
459 if (goal == PunExGoal.RAID_SPACEPORT) {
460 for (Industry temp : target.getIndustries()) {
461 if (temp.getSpec().hasTag(Industries.TAG_UNRAIDABLE))
continue;
462 if (temp.getSpec().hasTag(Industries.TAG_SPACEPORT)) {
467 if (industry ==
null)
return;
468 }
else if (goal == PunExGoal.RAID_PRODUCTION && reason.commodityId !=
null) {
470 for (Industry temp : target.getIndustries()) {
471 if (temp.getSpec().hasTag(Industries.TAG_UNRAIDABLE))
continue;
473 int prod = temp.getSupply(reason.commodityId).getQuantity().getModifiedInt();
479 if (industry ==
null)
return;
483 float fp = 50 + curr.threshold * 0.5f;
484 fp = Math.max(50, fp - 50);
490 if (fpOverride !=
null) {
495 float totalAttempts = 0f;
496 for (PunExData d :
data.values()) {
497 totalAttempts += d.numAttempts;
501 float extraMult = 0f;
502 if (totalAttempts <= 2) {
504 }
else if (totalAttempts <= 4) {
506 }
else if (totalAttempts <= 7) {
508 }
else if (totalAttempts <= 10) {
514 float orgDur = 20f + extraMult * 10f + (10f + extraMult * 5f) * (
float) Math.random();
518 goal, industry, reason);
519 if (curr.intel.isDone()) {
532 curr.threshold *= 2f;