mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-18 06:13:55 -07:00
Add barter multiplier for barter prices. They can be altered by technologies or auras. Reviewed by mimo.
Differential Revision: https://code.wildfiregames.com/D478 This was SVN commit r19615.
This commit is contained in:
parent
d8490b8c2e
commit
dc17836fe5
11 changed files with 156 additions and 34 deletions
|
|
@ -773,7 +773,7 @@ function barterUpdateCommon(resourceCode, idx, prefix, player)
|
|||
barterIcon.Buy.sprite = canBuyAny + "stretched:" + grayscale + "session/icons/resources/" + resourceCode + ".png";
|
||||
|
||||
barterAmount.Sell.caption = "-" + amountToSell;
|
||||
let prices = GetSimState().barterPrices;
|
||||
let prices = GetSimState().players[player].barterPrices;
|
||||
barterAmount.Buy.caption = "+" + Math.round(prices.sell[g_BarterSell] / prices.buy[resourceCode] * amountToSell);
|
||||
|
||||
barterButton.Buy.onPress = function() {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ m.GameState.prototype.init = function(SharedScript, state, player) {
|
|||
this.entities = SharedScript.entities;
|
||||
this.player = player;
|
||||
this.playerData = SharedScript.playersData[this.player];
|
||||
this.barterPrices = SharedScript.barterPrices;
|
||||
this.gameType = SharedScript.gameType;
|
||||
this.alliedVictory = SharedScript.alliedVictory;
|
||||
this.ceasefireActive = SharedScript.ceasefireActive;
|
||||
|
|
@ -66,7 +65,6 @@ m.GameState.prototype.update = function(SharedScript)
|
|||
{
|
||||
this.timeElapsed = SharedScript.timeElapsed;
|
||||
this.playerData = SharedScript.playersData[this.player];
|
||||
this.barterPrices = SharedScript.barterPrices;
|
||||
this.ceasefireActive = SharedScript.ceasefireActive;
|
||||
};
|
||||
|
||||
|
|
@ -122,7 +120,7 @@ m.GameState.prototype.getTimeElapsed = function()
|
|||
|
||||
m.GameState.prototype.getBarterPrices = function()
|
||||
{
|
||||
return this.barterPrices;
|
||||
return this.playerData.barterPrices;
|
||||
};
|
||||
|
||||
m.GameState.prototype.getGameType = function()
|
||||
|
|
|
|||
|
|
@ -142,7 +142,6 @@ m.SharedScript.prototype.init = function(state, deserialization)
|
|||
this.circularMap = state.circularMap;
|
||||
this.mapSize = state.mapSize;
|
||||
this.gameType = state.gameType;
|
||||
this.barterPrices = state.barterPrices;
|
||||
this.alliedVictory = state.alliedVictory;
|
||||
this.ceasefireActive = state.ceasefireActive;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,14 +34,16 @@ Barter.prototype.Init = function()
|
|||
this.restoreTimer = undefined;
|
||||
};
|
||||
|
||||
Barter.prototype.GetPrices = function()
|
||||
Barter.prototype.GetPrices = function(playerEntity)
|
||||
{
|
||||
var prices = { "buy": {}, "sell": {} };
|
||||
let cmpPlayer = Engine.QueryInterface(playerEntity, IID_Player);
|
||||
let multiplier = cmpPlayer.GetBarterMultiplier();
|
||||
for (let resource of Resources.GetCodes())
|
||||
{
|
||||
let truePrice = Resources.GetResource(resource).truePrice;
|
||||
prices.buy[resource] = truePrice * (100 + this.CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100;
|
||||
prices.sell[resource] = truePrice * (100 - this.CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100;
|
||||
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;
|
||||
}
|
||||
return prices;
|
||||
};
|
||||
|
|
@ -87,7 +89,7 @@ Barter.prototype.ExchangeResources = function(playerEntity, resourceToSell, reso
|
|||
}
|
||||
|
||||
var cmpPlayer = Engine.QueryInterface(playerEntity, IID_Player);
|
||||
var prices = this.GetPrices();
|
||||
var prices = this.GetPrices(playerEntity);
|
||||
var amountsToSubtract = {};
|
||||
amountsToSubtract[resourceToSell] = amount;
|
||||
if (cmpPlayer.TrySubtractResources(amountsToSubtract))
|
||||
|
|
@ -116,8 +118,7 @@ Barter.prototype.ExchangeResources = function(playerEntity, resourceToSell, reso
|
|||
}
|
||||
|
||||
// Increase price difference for both exchange resources.
|
||||
// Overal price difference (constant + dynamic) can't exceed +-99%
|
||||
// so both buy/sell prices limited to [1%; 199%] interval.
|
||||
// Overal price difference (dynamic +- constant) can't exceed +-99%.
|
||||
this.priceDifferences[resourceToSell] -= this.DIFFERENCE_PER_DEAL * numberOfDeals;
|
||||
this.priceDifferences[resourceToSell] = Math.min(99 - this.CONSTANT_DIFFERENCE, Math.max(this.CONSTANT_DIFFERENCE - 99, this.priceDifferences[resourceToSell]));
|
||||
this.priceDifferences[resourceToBuy] += this.DIFFERENCE_PER_DEAL * numberOfDeals;
|
||||
|
|
|
|||
|
|
@ -124,10 +124,13 @@ GuiInterface.prototype.GetSimulationState = function()
|
|||
"researchedTechs": cmpTechnologyManager ? cmpTechnologyManager.GetResearchedTechs() : null,
|
||||
"classCounts": cmpTechnologyManager ? cmpTechnologyManager.GetClassCounts() : null,
|
||||
"typeCountsByClass": cmpTechnologyManager ? cmpTechnologyManager.GetTypeCountsByClass() : null,
|
||||
"canBarter": Engine.QueryInterface(SYSTEM_ENTITY, IID_Barter).PlayerHasMarket(playerEnt)
|
||||
"canBarter": Engine.QueryInterface(SYSTEM_ENTITY, IID_Barter).PlayerHasMarket(playerEnt),
|
||||
"barterPrices": Engine.QueryInterface(SYSTEM_ENTITY, IID_Barter).GetPrices(playerEnt)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||
if (cmpRangeManager)
|
||||
ret.circularMap = cmpRangeManager.GetLosCircular();
|
||||
|
|
@ -153,8 +156,6 @@ GuiInterface.prototype.GetSimulationState = function()
|
|||
ret.gameType = cmpEndGameManager.GetGameType();
|
||||
ret.alliedVictory = cmpEndGameManager.GetAlliedVictory();
|
||||
|
||||
ret.barterPrices = Engine.QueryInterface(SYSTEM_ENTITY, IID_Barter).GetPrices();
|
||||
|
||||
// Add Resource Codes, untranslated names and AI Analysis
|
||||
ret.resources = {
|
||||
"codes": Resources.GetCodes(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
function Player() {}
|
||||
|
||||
Player.prototype.Schema =
|
||||
"<element name='BarterMultiplier' a:help='Multipliers for barter prices.'>" +
|
||||
"<interleave>" +
|
||||
"<element name='Buy' a:help='Multipliers for the buy prices.'>" +
|
||||
Resources.BuildSchema("positiveDecimal") +
|
||||
"</element>" +
|
||||
"<element name='Sell' a:help='Multipliers for the sell prices.'>" +
|
||||
Resources.BuildSchema("positiveDecimal") +
|
||||
"</element>" +
|
||||
"</interleave>" +
|
||||
"</element>" +
|
||||
"<element name='SharedLosTech' a:help='Allies will share los when this technology is researched. Leave empty to never share LOS.'>" +
|
||||
"<text/>" +
|
||||
"</element>" +
|
||||
|
|
@ -47,6 +57,7 @@ Player.prototype.Init = function()
|
|||
this.disabledTechnologies = {};
|
||||
this.startingTechnologies = [];
|
||||
this.spyCostMultiplier = +this.template.SpyCostMultiplier;
|
||||
this.barterMultiplier = {"buy": this.template.BarterMultiplier.Buy, "sell": this.template.BarterMultiplier.Sell };
|
||||
|
||||
// Initial resources and trading goods probability in steps of 5
|
||||
let resCodes = Resources.GetCodes();
|
||||
|
|
@ -164,6 +175,11 @@ Player.prototype.GetMaxPopulation = function()
|
|||
return Math.round(ApplyValueModificationsToPlayer("Player/MaxPopulation", this.maxPop, this.entity, this.playerID));
|
||||
};
|
||||
|
||||
Player.prototype.GetBarterMultiplier = function()
|
||||
{
|
||||
return this.barterMultiplier;
|
||||
};
|
||||
|
||||
Player.prototype.SetGatherRateMultiplier = function(value)
|
||||
{
|
||||
this.gatherRateMultiplier = value;
|
||||
|
|
@ -740,9 +756,18 @@ Player.prototype.OnDiplomacyChanged = function()
|
|||
|
||||
Player.prototype.OnValueModification = function(msg)
|
||||
{
|
||||
if (msg.component != "Player" || msg.valueNames.indexOf("Player/SpyCostMultiplier") === -1)
|
||||
if (msg.component != "Player")
|
||||
return;
|
||||
this.spyCostMultiplier = ApplyValueModificationsToPlayer("Player/SpyCostMultiplier", +this.template.SpyCostMultiplier, this.entity, this.playerID);
|
||||
|
||||
if (msg.valueNames.indexOf("Player/SpyCostMultiplier") != -1)
|
||||
this.spyCostMultiplier = ApplyValueModificationsToPlayer("Player/SpyCostMultiplier", +this.template.SpyCostMultiplier, this.entity, this.playerID);
|
||||
|
||||
if (msg.valueNames.toString().search("Player/BarterMultiplier") != -1)
|
||||
for (let res in this.template.BarterMultiplier.Buy)
|
||||
{
|
||||
this.barterMultiplier.buy[res] = ApplyValueModificationsToEntity("Player/BarterMultiplier/Buy/"+res, +this.template.BarterMultiplier.Buy[res], this.entity);
|
||||
this.barterMultiplier.sell[res] = ApplyValueModificationsToEntity("Player/BarterMultiplier/Sell/"+res, +this.template.BarterMultiplier.Sell[res], this.entity);
|
||||
}
|
||||
};
|
||||
|
||||
Player.prototype.SetCheatsEnabled = function(flag)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,18 @@ const playerEnt = 11;
|
|||
let timerActivated = false;
|
||||
let bought = 0;
|
||||
let sold = 0;
|
||||
let multiplier = {
|
||||
"buy": {
|
||||
"wood": 1.0,
|
||||
"stone": 1.0,
|
||||
"metal": 1.0
|
||||
},
|
||||
"sell": {
|
||||
"wood": 1.0,
|
||||
"stone": 1.0,
|
||||
"metal": 1.0
|
||||
}
|
||||
};
|
||||
|
||||
AddMock(SYSTEM_ENTITY, IID_Timer, {
|
||||
"CancelTimer": id => { timerActivated = false; },
|
||||
|
|
@ -46,7 +58,8 @@ AddMock(playerEnt, IID_Player, {
|
|||
"AddResource": (type, amount) => {
|
||||
bought = amount;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
"GetBarterMultiplier": () => (multiplier)
|
||||
});
|
||||
|
||||
AddMock(SYSTEM_ENTITY, IID_RangeManager, {
|
||||
|
|
@ -61,17 +74,30 @@ AddMock(60, IID_Foundation, {});
|
|||
|
||||
// GetPrices
|
||||
cmpBarter.priceDifferences = { "wood": 8, "stone": 0, "metal": 0 };
|
||||
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.GetPrices().buy, {
|
||||
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.GetPrices(playerEnt).buy, {
|
||||
"wood": truePrice * (100 + 8 + cmpBarter.CONSTANT_DIFFERENCE) / 100,
|
||||
"stone": truePrice * (100 + cmpBarter.CONSTANT_DIFFERENCE) / 100,
|
||||
"metal": truePrice * (100 + cmpBarter.CONSTANT_DIFFERENCE) / 100
|
||||
});
|
||||
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.GetPrices().sell, {
|
||||
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.GetPrices(playerEnt).sell, {
|
||||
"wood": truePrice * (100 + 8 - cmpBarter.CONSTANT_DIFFERENCE) / 100,
|
||||
"stone": truePrice * (100 - cmpBarter.CONSTANT_DIFFERENCE) / 100,
|
||||
"metal": truePrice * (100 - cmpBarter.CONSTANT_DIFFERENCE) / 100
|
||||
});
|
||||
|
||||
multiplier.buy.stone = 2.0;
|
||||
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.GetPrices(playerEnt).buy, {
|
||||
"wood": truePrice * (100 + 8 + cmpBarter.CONSTANT_DIFFERENCE) / 100,
|
||||
"stone": truePrice * (100 + cmpBarter.CONSTANT_DIFFERENCE) * 2.0 / 100,
|
||||
"metal": truePrice * (100 + cmpBarter.CONSTANT_DIFFERENCE) / 100
|
||||
});
|
||||
TS_ASSERT_UNEVAL_EQUALS(cmpBarter.GetPrices(playerEnt).sell, {
|
||||
"wood": truePrice * (100 + 8 - cmpBarter.CONSTANT_DIFFERENCE) / 100,
|
||||
"stone": truePrice * (100 - cmpBarter.CONSTANT_DIFFERENCE) / 100,
|
||||
"metal": truePrice * (100 - cmpBarter.CONSTANT_DIFFERENCE) / 100
|
||||
});
|
||||
multiplier.buy.stone = 1.0;
|
||||
|
||||
// PlayerHasMarket
|
||||
TS_ASSERT(!cmpBarter.PlayerHasMarket(11));
|
||||
|
||||
|
|
@ -119,7 +145,8 @@ timerActivated = false;
|
|||
AddMock(playerEnt, IID_Player, {
|
||||
"GetPlayerID": () => 1,
|
||||
"TrySubtractResources": () => false,
|
||||
"AddResource": () => {}
|
||||
"AddResource": () => {},
|
||||
"GetBarterMultiplier": () => (multiplier)
|
||||
});
|
||||
cmpBarter.ExchangeResources(11, "wood", "stone", 100);
|
||||
|
||||
|
|
|
|||
|
|
@ -299,6 +299,10 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
|
|||
classCounts: {},
|
||||
typeCountsByClass: {},
|
||||
canBarter: false,
|
||||
barterPrices: {
|
||||
"buy": { "food": 150 },
|
||||
"sell": { "food": 25 }
|
||||
},
|
||||
statistics: {
|
||||
resourcesGathered: {
|
||||
food: 100,
|
||||
|
|
@ -344,6 +348,10 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
|
|||
classCounts: {},
|
||||
typeCountsByClass: {},
|
||||
canBarter: false,
|
||||
barterPrices: {
|
||||
"buy": { "food": 150 },
|
||||
"sell": { "food": 25 }
|
||||
},
|
||||
statistics: {
|
||||
resourcesGathered: {
|
||||
food: 100,
|
||||
|
|
@ -360,10 +368,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
|
|||
timeElapsed: 0,
|
||||
gameType: "conquest",
|
||||
alliedVictory: false,
|
||||
"barterPrices": {
|
||||
"buy": { "food": 150 },
|
||||
"sell": { "food": 25 }
|
||||
},
|
||||
"resources": {
|
||||
"codes": ["food", "metal", "stone", "wood"],
|
||||
"names": {
|
||||
|
|
@ -417,6 +421,10 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
|
|||
"classCounts": {},
|
||||
"typeCountsByClass": {},
|
||||
"canBarter": false,
|
||||
"barterPrices": {
|
||||
"buy": { "food": 150 },
|
||||
"sell": { "food": 25 }
|
||||
},
|
||||
"statistics": {
|
||||
"resourcesGathered": {
|
||||
"food": 100,
|
||||
|
|
@ -485,6 +493,10 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
|
|||
"classCounts": {},
|
||||
"typeCountsByClass": {},
|
||||
"canBarter": false,
|
||||
"barterPrices": {
|
||||
"buy": { "food": 150 },
|
||||
"sell": { "food": 25 }
|
||||
},
|
||||
"statistics": {
|
||||
"resourcesGathered": {
|
||||
"food": 100,
|
||||
|
|
@ -524,10 +536,6 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
|
|||
"timeElapsed": 0,
|
||||
"gameType": "conquest",
|
||||
"alliedVictory": false,
|
||||
"barterPrices": {
|
||||
"buy": { "food": 150 },
|
||||
"sell": { "food": 25 }
|
||||
},
|
||||
"resources": {
|
||||
"codes": ["food", "metal", "stone", "wood"],
|
||||
"names": {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,19 @@
|
|||
Resources = {
|
||||
"GetCodes": () => ["food", "metal", "stone", "wood"],
|
||||
"GetResource": () => ({}),
|
||||
"BuildSchema": (type) => {
|
||||
let schema = "";
|
||||
for (let res of Resources.GetCodes())
|
||||
schema +=
|
||||
"<optional>" +
|
||||
"<element name='" + res + "'>" +
|
||||
"<ref name='" + type + "'/>" +
|
||||
"</element>" +
|
||||
"</optional>";
|
||||
return "<interleave>" + schema + "</interleave>";
|
||||
}
|
||||
};
|
||||
|
||||
Engine.LoadHelperScript("Player.js");
|
||||
Engine.LoadHelperScript("ValueModification.js");
|
||||
Engine.LoadComponentScript("interfaces/AuraManager.js");
|
||||
|
|
@ -5,11 +21,6 @@ Engine.LoadComponentScript("interfaces/Player.js");
|
|||
Engine.LoadComponentScript("interfaces/TechnologyManager.js");
|
||||
Engine.LoadComponentScript("Player.js");
|
||||
|
||||
Resources = {
|
||||
"GetCodes": () => ["food", "metal", "stone", "wood"],
|
||||
"GetResource": () => ({}),
|
||||
};
|
||||
|
||||
AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
|
||||
"GetTemplate": name => null,
|
||||
"GetCurrentTemplateName" : ent => null
|
||||
|
|
@ -20,7 +31,19 @@ AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
|
|||
});
|
||||
|
||||
var cmpPlayer = ConstructComponent(10, "Player", {
|
||||
"SpyCostMultiplier": 1
|
||||
"SpyCostMultiplier": 1,
|
||||
"BarterMultiplier": {
|
||||
"Buy": {
|
||||
"wood": 1.0,
|
||||
"stone": 1.0,
|
||||
"metal": 1.0
|
||||
},
|
||||
"Sell": {
|
||||
"wood": 1.0,
|
||||
"stone": 1.0,
|
||||
"metal": 1.0
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
TS_ASSERT_EQUALS(cmpPlayer.GetPopulationCount(), 0);
|
||||
|
|
@ -40,3 +63,15 @@ diplo[1] = -1;
|
|||
TS_ASSERT(cmpPlayer.IsAlly(1));
|
||||
|
||||
TS_ASSERT_EQUALS(cmpPlayer.GetSpyCostMultiplier(), 1);
|
||||
TS_ASSERT_UNEVAL_EQUALS(cmpPlayer.GetBarterMultiplier(), {
|
||||
"buy": {
|
||||
"wood": 1.0,
|
||||
"stone": 1.0,
|
||||
"metal": 1.0
|
||||
},
|
||||
"sell": {
|
||||
"wood": 1.0,
|
||||
"stone": 1.0,
|
||||
"metal": 1.0
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -58,6 +58,20 @@
|
|||
<Classes datatype="tokens">Player</Classes>
|
||||
</Identity>
|
||||
<Player>
|
||||
<BarterMultiplier>
|
||||
<Buy>
|
||||
<food>1.0</food>
|
||||
<wood>1.0</wood>
|
||||
<stone>1.0</stone>
|
||||
<metal>1.0</metal>
|
||||
</Buy>
|
||||
<Sell>
|
||||
<food>1.0</food>
|
||||
<wood>1.0</wood>
|
||||
<stone>1.0</stone>
|
||||
<metal>1.0</metal>
|
||||
</Sell>
|
||||
</BarterMultiplier>
|
||||
<SharedLosTech>unlock_shared_los</SharedLosTech>
|
||||
<SharedDropsitesTech>unlock_shared_dropsites</SharedDropsitesTech>
|
||||
<SpyCostMultiplier>1.0</SpyCostMultiplier>
|
||||
|
|
|
|||
|
|
@ -4,5 +4,19 @@
|
|||
<SharedLosTech/>
|
||||
<SharedDropsitesTech/>
|
||||
<SpyCostMultiplier>1.0</SpyCostMultiplier>
|
||||
<BarterMultiplier>
|
||||
<Buy>
|
||||
<food>1.0</food>
|
||||
<wood>1.0</wood>
|
||||
<stone>1.0</stone>
|
||||
<metal>1.0</metal>
|
||||
</Buy>
|
||||
<Sell>
|
||||
<food>1.0</food>
|
||||
<wood>1.0</wood>
|
||||
<stone>1.0</stone>
|
||||
<metal>1.0</metal>
|
||||
</Sell>
|
||||
</BarterMultiplier>
|
||||
</Player>
|
||||
</Entity>
|
||||
|
|
|
|||
Loading…
Reference in a new issue