Index: ps/trunk/binaries/data/mods/public/simulation/components/Barter.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/Barter.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/Barter.js
@@ -4,23 +4,37 @@
"";
/**
- * The "true price" is a base price of 100 units of resource (for the case of some resources being of more worth than others).
+ * The "true price" is a base price of Barter.prototype.DEAL_AMOUNT units of resource (for the case of some resources being of more worth than others).
* With current bartering system only relative values makes sense so if for example stone is two times more expensive than wood,
* there will 2:1 exchange rate.
*
+ * Keep gui/session/trade/BarterButton.js in sync with this value.
+ */
+Barter.prototype.DEAL_AMOUNT = 100;
+
+/**
+ * Deals per mass barter.
+ * Keep gui/session/trade/BarterButton.js in sync with this value.
+ */
+Barter.prototype.BATCH_SIZE = 5;
+
+/**
* Constant part of price percentage difference between true price and buy/sell price.
* Buy price equal to true price plus constant difference.
* Sell price equal to true price minus constant difference.
*/
Barter.prototype.CONSTANT_DIFFERENCE = 10;
+
/**
* Additional difference of prices in percents, added after each deal to specified resource price.
*/
Barter.prototype.DIFFERENCE_PER_DEAL = 2;
+
/**
* Price difference percentage which restored each restore timer tick
*/
Barter.prototype.DIFFERENCE_RESTORE = 0.5;
+
/**
* Interval of timer which slowly restore prices after deals
*/
@@ -29,20 +43,19 @@
Barter.prototype.Init = function()
{
this.priceDifferences = {};
- for (let resource of Resources.GetBarterableCodes())
+ for (const resource of Resources.GetBarterableCodes())
this.priceDifferences[resource] = 0;
- this.restoreTimer = undefined;
};
Barter.prototype.GetPrices = function(cmpPlayer)
{
- let prices = { "buy": {}, "sell": {} };
- let multiplier = cmpPlayer.GetBarterMultiplier();
- for (let resource of Resources.GetBarterableCodes())
- {
- let truePrice = Resources.GetResource(resource).truePrice;
- prices.buy[resource] = truePrice * (100 + this.CONSTANT_DIFFERENCE + this.priceDifferences[resource]) * multiplier.buy[resource] / 100;
- prices.sell[resource] = truePrice * (100 - this.CONSTANT_DIFFERENCE + this.priceDifferences[resource]) * multiplier.sell[resource] / 100;
+ const prices = { "buy": {}, "sell": {} };
+ const multiplier = cmpPlayer.GetBarterMultiplier();
+ for (const resource in this.priceDifferences)
+ {
+ const truePrice = Resources.GetResource(resource).truePrice;
+ prices.buy[resource] = truePrice * (this.DEAL_AMOUNT + this.CONSTANT_DIFFERENCE + this.priceDifferences[resource]) * multiplier.buy[resource] / this.DEAL_AMOUNT;
+ prices.sell[resource] = truePrice * (this.DEAL_AMOUNT - this.CONSTANT_DIFFERENCE + this.priceDifferences[resource]) * multiplier.sell[resource] / this.DEAL_AMOUNT;
}
return prices;
};
@@ -55,85 +68,81 @@
return;
}
- let availResources = Resources.GetBarterableCodes();
- if (availResources.indexOf(resourceToSell) == -1)
+ if (!(resourceToSell in this.priceDifferences))
{
warn("ExchangeResources: incorrect resource to sell: " + uneval(resourceToSell));
return;
}
- if (availResources.indexOf(resourceToBuy) == -1)
+ if (!(resourceToBuy in this.priceDifferences))
{
warn("ExchangeResources: incorrect resource to buy: " + uneval(resourceToBuy));
return;
}
- if (amount != 100 && amount != 500)
+ if (amount !== this.DEAL_AMOUNT && amount !== (this.BATCH_SIZE * this.DEAL_AMOUNT))
return;
- let cmpPlayer = QueryPlayerIDInterface(playerID);
- if (!cmpPlayer || !cmpPlayer.CanBarter())
+ const cmpPlayer = QueryPlayerIDInterface(playerID);
+ if (!cmpPlayer?.CanBarter())
return;
- let prices = this.GetPrices(cmpPlayer);
- let amountsToSubtract = {};
- amountsToSubtract[resourceToSell] = amount;
- if (cmpPlayer.TrySubtractResources(amountsToSubtract))
- {
- let amountToAdd = Math.round(prices.sell[resourceToSell] / prices.buy[resourceToBuy] * amount);
- cmpPlayer.AddResource(resourceToBuy, amountToAdd);
-
- // Display chat message to observers.
- let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
- if (cmpGUIInterface)
- cmpGUIInterface.PushNotification({
- "type": "barter",
- "players": [playerID],
- "amountGiven": amount,
- "amountGained": amountToAdd,
- "resourceGiven": resourceToSell,
- "resourceGained": resourceToBuy
- });
-
- let cmpStatisticsTracker = QueryPlayerIDInterface(playerID, IID_StatisticsTracker);
- if (cmpStatisticsTracker)
- {
- cmpStatisticsTracker.IncreaseResourcesSoldCounter(resourceToSell, amount);
- cmpStatisticsTracker.IncreaseResourcesBoughtCounter(resourceToBuy, amountToAdd);
- }
-
- let difference = this.DIFFERENCE_PER_DEAL * amount / 100;
- // Increase price difference for both exchange resources.
- // Overall price difference (dynamic +/- constant) can't exceed +-99%.
- this.priceDifferences[resourceToSell] -= difference;
- this.priceDifferences[resourceToSell] = Math.min(99 - this.CONSTANT_DIFFERENCE, Math.max(this.CONSTANT_DIFFERENCE - 99, this.priceDifferences[resourceToSell]));
- this.priceDifferences[resourceToBuy] += difference;
- this.priceDifferences[resourceToBuy] = Math.min(99 - this.CONSTANT_DIFFERENCE, Math.max(this.CONSTANT_DIFFERENCE - 99, this.priceDifferences[resourceToBuy]));
- }
+ const amountsToSubtract = {
+ [resourceToSell]: amount
+ };
+ if (!cmpPlayer.TrySubtractResources(amountsToSubtract))
+ return;
+
+ const prices = this.GetPrices(cmpPlayer);
+ const amountToAdd = Math.round(prices.sell[resourceToSell] / prices.buy[resourceToBuy] * amount);
+ cmpPlayer.AddResource(resourceToBuy, amountToAdd);
+
+ Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface)?.PushNotification({
+ "type": "barter",
+ "players": [playerID],
+ "amountGiven": amount,
+ "amountGained": amountToAdd,
+ "resourceGiven": resourceToSell,
+ "resourceGained": resourceToBuy
+ });
+
+ const cmpStatisticsTracker = QueryPlayerIDInterface(playerID, IID_StatisticsTracker);
+ if (cmpStatisticsTracker)
+ {
+ cmpStatisticsTracker.IncreaseResourcesSoldCounter(resourceToSell, amount);
+ cmpStatisticsTracker.IncreaseResourcesBoughtCounter(resourceToBuy, amountToAdd);
+ }
+
+ const difference = this.DIFFERENCE_PER_DEAL * amount / this.DEAL_AMOUNT;
+ // Overall price difference (dynamic +/- constant) can't exceed +-99%.
+ const maxDifference = this.DEAL_AMOUNT * 0.99;
+
+ // Increase price difference for both exchanged resources.
+ this.priceDifferences[resourceToSell] -= difference;
+ this.priceDifferences[resourceToSell] = Math.min(maxDifference - this.CONSTANT_DIFFERENCE, Math.max(this.CONSTANT_DIFFERENCE - maxDifference, this.priceDifferences[resourceToSell]));
+ this.priceDifferences[resourceToBuy] += difference;
+ this.priceDifferences[resourceToBuy] = Math.min(maxDifference - this.CONSTANT_DIFFERENCE, Math.max(this.CONSTANT_DIFFERENCE - maxDifference, this.priceDifferences[resourceToBuy]));
- if (this.restoreTimer === undefined)
- this.restoreTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).SetInterval(this.entity, IID_Barter, "ProgressTimeout", this.RESTORE_TIMER_INTERVAL, this.RESTORE_TIMER_INTERVAL, {});
+ if (!this.restoreTimer)
+ this.restoreTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).SetInterval(this.entity, IID_Barter, "ProgressTimeout", this.RESTORE_TIMER_INTERVAL, this.RESTORE_TIMER_INTERVAL, null);
};
Barter.prototype.ProgressTimeout = function(data)
{
let needRestore = false;
- for (let resource of Resources.GetBarterableCodes())
+ for (const resource in this.priceDifferences)
{
// Calculate value to restore, it should be limited to [-DIFFERENCE_RESTORE; DIFFERENCE_RESTORE] interval
- let differenceRestore = Math.min(this.DIFFERENCE_RESTORE, Math.max(-this.DIFFERENCE_RESTORE, this.priceDifferences[resource]));
- differenceRestore = -differenceRestore;
- this.priceDifferences[resource] += differenceRestore;
- // If price difference still exists then set flag to run timer again
- if (this.priceDifferences[resource] != 0)
+ this.priceDifferences[resource] -= Math.min(this.DIFFERENCE_RESTORE, Math.max(-this.DIFFERENCE_RESTORE, this.priceDifferences[resource]));
+ // If price difference still exists then set flag to keep the timer running.
+ if (this.priceDifferences[resource] !== 0)
needRestore = true;
}
if (!needRestore)
{
- let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
- cmpTimer.CancelTimer(this.restoreTimer);
- this.restoreTimer = undefined;
+ Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).CancelTimer(this.restoreTimer);
+ delete this.restoreTimer;
}
};
Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Barter.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Barter.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Barter.js
@@ -144,10 +144,6 @@
});
cmpBarter.ExchangeResources(playerID, "wood", "stone", 100);
-// It seems useless to try to activate the timer if we don't barter any resources.
-TS_ASSERT_EQUALS(cmpBarter.restoreTimer, 7);
-TS_ASSERT(timerActivated);
-
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.priceDifferences, { "wood": 0, "stone": 0, "metal": 0 });
DeleteMock(playerEnt, IID_Player);