39 public static class FactionTradeRepData {
42 public float [] getRepPointsAndVolumeUsedFor(
float volume) {
49 while (volume >= currVolumePerPoint) {
51 used += currVolumePerPoint;
52 volume -= currVolumePerPoint;
54 if (currVolumePerPoint < max) currVolumePerPoint += incr;
55 if (currVolumePerPoint > max) currVolumePerPoint = max;
57 return new float [] {points, used};
62 private IntervalUtil tracker;
63 private IntervalUtil repDecayTracker;
64 private Map<String, FactionTradeRepData> repData =
new HashMap<String, FactionTradeRepData>();
71 Object readResolve() {
72 if (repDecayTracker ==
null) {
73 repDecayTracker =
new IntervalUtil(130f, 170f);
75 if (tracker ==
null) {
76 tracker =
new IntervalUtil(3f, 7f);
85 private float [] getRepPointsAndVolumeUsedFor(
float volume, FactionAPI
faction) {
86 FactionTradeRepData data = repData.get(
faction.getId());
88 data =
new FactionTradeRepData();
89 repData.put(
faction.getId(), data);
91 return data.getRepPointsAndVolumeUsedFor(volume);
100 tracker.advance(days);
101 if (tracker.intervalElapsed()) {
106 checkForTradeReputationChanges(
faction);
119 private void checkForXPGain() {
120 PlayerTradeProfitabilityData data = SharedData.getData().getPlayerActivityTracker().getProfitabilityData();
121 final long gain = data.getAccruedXP();
124 data.setAccruedXP(0);
125 Global.
getSector().getCampaignUI().addMessage(
"Gained experience from profitable trades", Misc.getBasePlayerColor());
126 Global.
getSector().getCharacterData().getPerson().getStats().addXP(gain);
131 public static class MarketTradeInfo {
132 public MarketAPI market;
133 public float tradeTotal;
134 public float smugglingTotal;
137 private void checkForTradeReputationChanges(
final FactionAPI
faction) {
138 float playerTradeVolume = 0;
139 float playerSmugglingVolume = 0;
141 final List<MarketTradeInfo> info =
new ArrayList<MarketTradeInfo>();
142 for (MarketAPI
market :
Global.getSector().getEconomy().getMarketsCopy()) {
151 MarketTradeInfo curr =
new MarketTradeInfo();
154 for (SubmarketAPI submarket :
market.getSubmarketsCopy()) {
155 SubmarketPlugin plugin = submarket.getPlugin();
156 if (!plugin.isParticipatesInEconomy())
continue;
160 PlayerTradeDataForSubmarket tradeData = SharedData.getData().getPlayerActivityTracker().getPlayerTradeData(submarket);
163 if (
market.getFaction() ==
faction && (submarket.getFaction().isHostileTo(
faction) || submarket.getPlugin().isBlackMarket())) {
164 curr.smugglingTotal += tradeData.getAccumulatedPlayerTradeValueForNegative();
165 }
else if (submarket.getFaction() ==
faction) {
166 curr.tradeTotal += tradeData.getAccumulatedPlayerTradeValueForPositive();
171 if (curr.tradeTotal == 0 && curr.smugglingTotal == 0)
continue;
175 playerTradeVolume += curr.tradeTotal;
176 playerSmugglingVolume += curr.smugglingTotal;
183 float [] repPlus = getRepPointsAndVolumeUsedFor(playerTradeVolume,
faction);
184 float [] repMinus = getRepPointsAndVolumeUsedFor(playerSmugglingVolume,
faction);
185 final float repChange = repPlus[0] - repMinus[0];
187 if (Math.abs(repChange) < 1) {
188 log.info(
"Not enough trade/smuggling with " +
faction.getDisplayNameWithArticle() +
" for a rep change (" + playerTradeVolume +
", " + playerSmugglingVolume +
")");
192 log.info(
"Sending rep change of " + repChange +
" with " +
faction.getDisplayNameWithArticle() +
" due to trade/smuggling");
194 float tradeUsed = repPlus[1];
195 float smugglingUsed = repMinus[1];
198 for (MarketAPI
market : Global.getSector().getEconomy().getMarketsCopy()) {
200 for (SubmarketAPI submarket :
market.getSubmarketsCopy()) {
201 SubmarketPlugin plugin = submarket.getPlugin();
202 if (!plugin.isParticipatesInEconomy())
continue;
208 PlayerTradeDataForSubmarket tradeData = SharedData.getData().getPlayerActivityTracker().getPlayerTradeData(submarket);
211 if (playerSmugglingVolume > 0 &&
market.getFaction() ==
faction && (submarket.getFaction().isHostileTo(
faction) || submarket.getPlugin().isBlackMarket())) {
212 float value = tradeData.getAccumulatedPlayerTradeValueForNegative();
213 tradeData.setAccumulatedPlayerTradeValueForNegative(value - smugglingUsed * value / playerSmugglingVolume);
214 }
else if (playerTradeVolume > 0 && submarket.getFaction() ==
faction) {
215 float value = tradeData.getAccumulatedPlayerTradeValueForPositive();
216 tradeData.setAccumulatedPlayerTradeValueForPositive(value - tradeUsed * value / playerTradeVolume);
222 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
225 Collections.sort(info,
new Comparator<MarketTradeInfo>() {
226 public int compare(MarketTradeInfo o1, MarketTradeInfo o2) {
227 return (
int) (o2.tradeTotal - o1.tradeTotal);
231 RepActions action = RepActions.TRADE_EFFECT;
232 Global.getSector().adjustPlayerReputation(
233 new RepActionEnvelope(action,
new Float(Math.abs(repChange)),
null,
null,
false,
true,
"Change caused by trade with faction"),
237 }
else if (repChange < 0) {
238 Collections.sort(info,
new Comparator<MarketTradeInfo>() {
239 public int compare(MarketTradeInfo o1, MarketTradeInfo o2) {
240 return (
int) (o2.smugglingTotal - o1.smugglingTotal);
244 RepActions action = RepActions.SMUGGLING_EFFECT;
246 Global.getSector().adjustPlayerReputation(
247 new RepActionEnvelope(action,
new Float(Math.abs(repChange)),
null,
null,
false,
true,
"Change caused by black-market trade"),
259 for (
final MarketTradeInfo curr : info) {
260 float actionableTotal = curr.tradeTotal * 2f + curr.smugglingTotal * 0.5f;
262 List<FactionAPI> factions =
new ArrayList<FactionAPI>(
Global.
getSector().getAllFactions());
263 Collections.shuffle(factions);
264 for (
final FactionAPI
faction : factions) {
267 if (
faction.getCustom().optBoolean(Factions.CUSTOM_IGNORE_TRADE_WITH_ENEMIES)) {
270 if (
faction.isPlayerFaction())
continue;
273 public boolean acceptMarket(MarketAPI
market) {
277 if (
market.getFaction().isAtBest(curr.market.getFaction(), RepLevel.HOSTILE)) {
283 if (other ==
null)
continue;
285 float dist = Misc.getDistanceLY(curr.market.getLocationInHyperspace(), other.getLocationInHyperspace());
290 float [] repMinus = getRepPointsAndVolumeUsedFor(actionableTotal,
faction);
291 if (repMinus[0] <= 0)
continue;
297 final float repChange = -repMinus[0];
299 log.info(
"Sending rep change of " + repChange +
" with " + other.getFaction().getDisplayNameWithArticle() +
300 " due to trade with enemy (" + curr.market.getFaction().getDisplayNameWithArticle() +
")");
302 RepActions action = RepActions.TRADE_WITH_ENEMY;
304 new RepActionEnvelope(action,
new Float(Math.abs(repChange)),
null,
null,
false,
true,
"Change caused by trade with enemies"),
305 other.getFactionId());
308 if (sent >= maxToSend)
break;
310 if (sent >= maxToSend)
break;