1
0
forked from 0ad/0ad

Implements shared trade gain with allies, patch by mimo, fixes #1691

This was SVN commit r13567.
This commit is contained in:
historic_bruno 2013-07-16 05:59:48 +00:00
parent f302faf8e4
commit da4d1916dc
6 changed files with 113 additions and 38 deletions

View File

@ -271,17 +271,17 @@ function getActionInfo(action, target)
var traderData = { "firstMarket": entState.id, "secondMarket": targetState.id, "template": trader };
var gain = Engine.GuiInterfaceCall("GetTradingRouteGain", traderData);
if (gain !== null)
if (gain && gain.traderGain)
{
data.command = "trade";
data.target = traderData.secondMarket;
data.source = traderData.firstMarket;
cursor = "action-setup-trade-route";
tooltip = "Click to establish a default route for new traders.";
tooltip = "Right-click to establish a default route for new traders.";
if (trader)
tooltip += " Gain: " + gain + " metal.";
tooltip += "\nGain (metal): " + getTradingTooltip(gain);
else // Foundation or cannot produce traders
tooltip += " Expected gain: " + gain + " metal.";
tooltip += "\nExpected gain (metal): " + getTradingTooltip(gain);
}
}
@ -348,18 +348,18 @@ function getActionInfo(action, target)
case "is first":
tooltip = "Origin trade market.";
if (tradingDetails.hasBothMarkets)
tooltip += " Gain: " + tradingDetails.gain + " " + tradingDetails.goods + ". Right-click to create a new trade route."
tooltip += "\nGain (" + tradingDetails.goods + "): " + getTradingTooltip(tradingDetails.gain);
else
tooltip += " Right-click on another market to set it as a destination trade market."
tooltip += "\nRight-click on another market to set it as a destination trade market."
break;
case "is second":
tooltip = "Destination trade market. Gain: " + tradingDetails.gain + " " + tradingDetails.goods + "." + " Right-click to create a new trade route.";
tooltip = "Destination trade market.\nGain (" + tradingDetails.goods + "): " + getTradingTooltip(tradingDetails.gain);
break;
case "set first":
tooltip = "Set as origin trade market";
tooltip = "Right-click to set as origin trade market";
break;
case "set second":
tooltip = "Set as destination trade market. Gain: " + tradingDetails.gain + " " + tradingDetails.goods + ".";
tooltip = "Right-click to set as destination trade market.\nGain (" + tradingDetails.goods + "): " + getTradingTooltip(tradingDetails.gain);
break;
}
return {"possible": true, "tooltip": tooltip};

View File

@ -134,13 +134,18 @@ function displaySingle(entState, template)
getGUIObjectByName("resourceCarryingIcon").tooltip = "";
}
// Use the same indicators for traders
else if (entState.trader && entState.trader.goods.amount > 0)
else if (entState.trader && entState.trader.goods.amount)
{
getGUIObjectByName("resourceCarryingIcon").hidden = false;
getGUIObjectByName("resourceCarryingText").hidden = false;
getGUIObjectByName("resourceCarryingIcon").sprite = "stretched:session/icons/resources/"+entState.trader.goods.type+".png";
getGUIObjectByName("resourceCarryingText").caption = entState.trader.goods.amount;
getGUIObjectByName("resourceCarryingIcon").tooltip = "";
var totalGain = entState.trader.goods.amount.traderGain;
if (entState.trader.goods.amount.market1Gain)
totalGain += entState.trader.goods.amount.market1Gain;
if (entState.trader.goods.amount.market2Gain)
totalGain += entState.trader.goods.amount.market2Gain;
getGUIObjectByName("resourceCarryingText").caption = totalGain;
getGUIObjectByName("resourceCarryingIcon").tooltip = "Gain: " + getTradingTooltip(entState.trader.goods.amount);
}
// And for number of workers
else if (entState.foundation)

View File

@ -547,3 +547,23 @@ function getRankIconSprite(entState)
return "";
}
/**
* Returns a message with the details of the trade gain.
*/
function getTradingTooltip(gain)
{
var tooltip = gain.traderGain;
if (gain.market1Gain && gain.market1Owner == gain.traderOwner)
tooltip += "+" + gain.market1Gain;
if (gain.market2Gain && gain.market2Owner == gain.traderOwner)
tooltip += "+" + gain.market2Gain;
tooltip += " (you)";
if (gain.market1Gain && gain.market1Owner != gain.traderOwner)
tooltip += ", " + gain.market1Gain + " (player " + gain.market1Owner + ")";
if (gain.market2Gain && gain.market2Owner != gain.traderOwner)
tooltip += ", " + gain.market2Gain + " (player " + gain.market2Owner + ")";
return tooltip;
}

View File

@ -27,11 +27,15 @@ Looter.prototype.Collect = function(targetEntity)
if (cmpTrader)
{
var carriedGoods = cmpTrader.GetGoods();
if (carriedGoods.amount > 0)
if (carriedGoods.amount && carriedGoods.amount.traderGain)
{
// Convert from {type:<type>,amount:<amount>} to {<type>:<amount>}
var resourcesToAdd = {};
resourcesToAdd[carriedGoods.type] = carriedGoods.amount;
resourcesToAdd[carriedGoods.type] = carriedGoods.amount.traderGain;
if (carriedGoods.amount.market1Gain)
resourcesToAdd[carriedGoods.type] += carriedGoods.amount.market1Gain;
if (carriedGoods.amount.market2Gain)
resourcesToAdd[carriedGoods.type] += carriedGoods.amount.market2Gain;
cmpPlayer.AddResources(resourcesToAdd);
}
}

View File

@ -31,20 +31,22 @@ Trader.prototype.Init = function()
// Selected resource for trading
this.preferredGoods = "metal";
// Currently carried goods
this.goods = { "type": null, "amount": 0 };
};
this.goods = { "type": null, "amount": null };
}
Trader.prototype.CalculateGain = function(firstMarket, secondMarket)
{
var gain = CalculateTraderGain(firstMarket, secondMarket, this.template, this.entity);
// For ship increase gain for each garrisoned trader
// Calculate this here to save passing unnecessary stuff into the CalculatetraderGain function
var garrisonMultiplier = 1;
// Calculate this here to save passing unnecessary stuff into the CalculateTraderGain function
var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
if (cmpIdentity && cmpIdentity.HasClass("Ship"))
{
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
if (cmpGarrisonHolder)
{
var garrisonMultiplier = 1;
var garrisonedTradersCount = 0;
for each (var entity in cmpGarrisonHolder.GetEntities())
{
@ -53,11 +55,18 @@ Trader.prototype.CalculateGain = function(firstMarket, secondMarket)
garrisonedTradersCount++;
}
garrisonMultiplier *= 1 + GARRISONED_TRADER_ADDITION * garrisonedTradersCount / 100;
if (gain.traderGain)
gain.traderGain = Math.round(garrisonMultiplier * gain.traderGain);
if (gain.market1Gain)
gain.market1Gain = Math.round(garrisonMultiplier * gain.market1Gain);
if (gain.market2Gain)
gain.market2Gain = Math.round(garrisonMultiplier * gain.market2Gain);
}
}
return Math.round(garrisonMultiplier * CalculateTraderGain(firstMarket, secondMarket, this.template));
};
return gain;
}
Trader.prototype.GetGain = function()
{
@ -116,7 +125,7 @@ Trader.prototype.SetTargetMarket = function(target, source)
if (marketsChanged)
{
// Drop carried goods
this.goods.amount = 0;
this.goods.amount = null;
}
return marketsChanged;
};
@ -177,14 +186,34 @@ Trader.prototype.CanTrade = function(target)
Trader.prototype.PerformTrade = function()
{
if (this.goods.amount > 0)
if (this.goods.amount && this.goods.amount.traderGain)
{
var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
cmpPlayer.AddResource(this.goods.type, this.goods.amount);
cmpPlayer.AddResource(this.goods.type, this.goods.amount.traderGain);
var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
if (cmpStatisticsTracker)
cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount);
cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount.traderGain);
if (this.goods.amount.market1Gain)
{
var cmpPlayer = QueryOwnerInterface(this.firstMarket, IID_Player);
cmpPlayer.AddResource(this.goods.type, this.goods.amount.market1Gain);
var cmpStatisticsTracker = QueryOwnerInterface(this.firstMarket, IID_StatisticsTracker);
if (cmpStatisticsTracker)
cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount.market1Gain);
}
if (this.goods.amount.market2Gain)
{
var cmpPlayer = QueryOwnerInterface(this.secondMarket, IID_Player);
cmpPlayer.AddResource(this.goods.type, this.goods.amount.market2Gain);
var cmpStatisticsTracker = QueryOwnerInterface(this.secondMarket, IID_StatisticsTracker);
if (cmpStatisticsTracker)
cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount.market2Gain);
}
}
this.goods.type = this.preferredGoods;
this.goods.amount = this.gain;
@ -198,7 +227,7 @@ Trader.prototype.GetGoods = function()
Trader.prototype.StopTrading = function()
{
// Drop carried goods
this.goods.amount = 0;
this.goods.amount = null;
// Reset markets
this.firstMarket = INVALID_ENTITY;
this.secondMarket = INVALID_ENTITY;

View File

@ -1,11 +1,14 @@
// This constant used to adjust gain value depending on distance
const DISTANCE_FACTOR = 1 / 110;
// Additional gain for trading performed between markets of different players, in percents
const INTERNATIONAL_TRADING_ADDITION = 50;
// Additional gain (applying to each market) for trading performed between markets of different players, in percents
const INTERNATIONAL_TRADING_ADDITION = 25;
function CalculateTraderGain(firstMarket, secondMarket, template)
// If trader undefined, the trader owner is supposed to be the same as the first market
function CalculateTraderGain(firstMarket, secondMarket, template, trader)
{
var gain = {};
var cmpFirstMarketPosition = Engine.QueryInterface(firstMarket, IID_Position);
var cmpSecondMarketPosition = Engine.QueryInterface(secondMarket, IID_Position);
if (!cmpFirstMarketPosition || !cmpFirstMarketPosition.IsInWorld() || !cmpSecondMarketPosition || !cmpSecondMarketPosition.IsInWorld())
@ -17,17 +20,31 @@ function CalculateTraderGain(firstMarket, secondMarket, template)
// We don't use pathfinder, because ordinary distance looks more fair.
var distance = Math.sqrt(Math.pow(firstMarketPosition.x - secondMarketPosition.x, 2) + Math.pow(firstMarketPosition.y - secondMarketPosition.y, 2));
// We calculate gain as square of distance to encourage trading between remote markets
var gain = Math.pow(distance * DISTANCE_FACTOR, 2);
// If markets belongs to different players, multiple gain to INTERNATIONAL_TRADING_MULTIPLIER
var cmpFirstMarketOwnership = Engine.QueryInterface(firstMarket, IID_Ownership);
var cmpSecondMarketOwnership = Engine.QueryInterface(secondMarket, IID_Ownership);
if (cmpFirstMarketOwnership.GetOwner() != cmpSecondMarketOwnership.GetOwner())
gain *= 1 + INTERNATIONAL_TRADING_ADDITION / 100;
gain.traderGain = Math.pow(distance * DISTANCE_FACTOR, 2);
if (template && template.GainMultiplier)
gain *= template.GainMultiplier;
gain = Math.round(gain);
gain.traderGain *= template.GainMultiplier;
gain.traderGain = Math.round(gain.traderGain);
// If trader undefined, the trader owner is supposed to be the same as the first market
if (trader)
var cmpOwnership = Engine.QueryInterface(trader, IID_Ownership);
else
var cmpOwnership = Engine.QueryInterface(firstMarket, IID_Ownership);
gain.traderOwner = cmpOwnership.GetOwner();
// If markets belong to different players, add gain from international trading
var ownerFirstMarket = Engine.QueryInterface(firstMarket, IID_Ownership).GetOwner();
var ownerSecondMarket = Engine.QueryInterface(secondMarket, IID_Ownership).GetOwner();
if (ownerFirstMarket != ownerSecondMarket)
{
var internationalGain1 = ApplyTechModificationsToEntity("Trade/International", INTERNATIONAL_TRADING_ADDITION, firstMarket);
gain.market1Gain = Math.round(gain.traderGain * internationalGain1 / 100);
gain.market1Owner = ownerFirstMarket;
var internationalGain2 = ApplyTechModificationsToEntity("Trade/International", INTERNATIONAL_TRADING_ADDITION, secondMarket);
gain.market2Gain = Math.round(gain.traderGain * internationalGain2 / 100);
gain.market2Owner = ownerSecondMarket;
}
return gain;
}