Index: binaries/data/mods/public/gui/session/input.js
===================================================================
--- binaries/data/mods/public/gui/session/input.js	(révision 13335)
+++ binaries/data/mods/public/gui/session/input.js	(copie de travail)
@@ -270,13 +270,17 @@
 
 			var traderData = { "firstMarket": entState.id, "secondMarket": targetState.id, "template": trader };
 			var gain = Engine.GuiInterfaceCall("GetTradingRouteGain", traderData);
-			if (gain !== null)
+			if (gain && gain.trader)
 			{
 				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. Gain: " + gain + " metal.";
+				tooltip = "Click to establish a default route for new traders. Gain: " + gain.trader + " metal";
+				if (gain.market2)
+					tooltip += " and " + gain.market2 + " metal for the allied.";
+				else
+					tooltip += ".";
 			}
 		}
 
@@ -335,18 +339,35 @@
 				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 += " Gain: " + tradingDetails.gain.trader + " " + tradingDetails.goods;
+						if (tradingDetails.gain.market1)
+							tooltip += ", plus " + tradingDetails.gain.market1 + " for the player " + tradingDetails.gain.owner1;
+						if (tradingDetails.gain.market2)
+							tooltip += " and " + tradingDetails.gain.market2 + " for the player " + tradingDetails.gain.owner2;
+						tooltip += ". Right-click to create a new trade route.";
+					}
 					else
 						tooltip += " Right-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. Gain: " + tradingDetails.gain.trader + " " + tradingDetails.goods;
+					if (tradingDetails.gain.market1)
+						tooltip += ", plus " + tradingDetails.gain.market1 + " for the player " + tradingDetails.gain.owner1;
+					if (tradingDetails.gain.market2)
+						tooltip += " and " + tradingDetails.gain.market2 + " for the player " + tradingDetails.gain.owner2;
+					tooltip += ". Right-click to create a new trade route.";
 					break;
 				case "set first":
 					tooltip = "Set as origin trade market";
 					break;
 				case "set second":
-					tooltip = "Set as destination trade market. Gain: " + tradingDetails.gain + " " + tradingDetails.goods + ".";
+					tooltip = "Set as destination trade market. Gain: " + tradingDetails.gain.trader + " " + tradingDetails.goods;
+					if (tradingDetails.gain.market1)
+						tooltip += ", plus " + tradingDetails.gain.market1 + " for the player " + tradingDetails.gain.owner1;
+					if (tradingDetails.gain.market2)
+						tooltip += " and " + tradingDetails.gain.market2 + " for the player " + tradingDetails.gain.owner2;
+					tooltip += ". ";
 					break;
 				}
 				return {"possible": true, "tooltip": tooltip};
Index: binaries/data/mods/public/simulation/helpers/TraderGain.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/TraderGain.js	(révision 13335)
+++ binaries/data/mods/public/simulation/helpers/TraderGain.js	(copie de travail)
@@ -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,49 @@
 	// 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);
+	gain.trader = Math.pow(distance * DISTANCE_FACTOR, 2);
+	if (template.GainMultiplier)
+		gain.trader *= template.GainMultiplier;
+	gain.trader = Math.round(gain.trader);
 
 	// If markets belong 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;
+	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);
+		internationalGain1 = Math.round(gain.trader * internationalGain1 / 100);
+		var internationalGain2 = ApplyTechModificationsToEntity("Trade/International", INTERNATIONAL_TRADING_ADDITION, secondMarket);
+		internationalGain2 = Math.round(gain.trader * internationalGain2 / 100);
 
-	if (template.GainMultiplier)
-		gain *= template.GainMultiplier;
-	gain = Math.round(gain);
+		if (trader)
+		{
+			var cmpTraderOwnership = Engine.QueryInterface(trader, IID_Ownership);
+			if (ownerFirstMarket == cmpTraderOwnership.GetOwner())
+				gain.trader += internationalGain1;
+			else
+			{
+				gain.market1 = internationalGain1;
+				gain.owner1 = ownerFirstMarket;
+			}
+
+			if (ownerSecondMarket == cmpTraderOwnership.GetOwner())
+				gain.trader += internationalGain2;
+			else
+			{
+				gain.market2 = internationalGain2;
+				gain.owner2 = ownerSecondMarket;
+			}
+		}
+		else
+		{
+			// If trader undefined, the trader owner is supposed to be the same as the first market
+			gain.trader += internationalGain1;
+			gain.market2 = internationalGain2;
+			gain.owner2 = ownerSecondMarket;
+		}
+	}
+
 	return gain;
 }
 
Index: binaries/data/mods/public/simulation/components/Trader.js
===================================================================
--- binaries/data/mods/public/simulation/components/Trader.js	(révision 13335)
+++ binaries/data/mods/public/simulation/components/Trader.js	(copie de travail)
@@ -31,20 +31,22 @@
 	// 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, template)
 {
+	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,10 +55,17 @@
 					garrisonedTradersCount++;
 			}
 			garrisonMultiplier *= 1 + GARRISONED_TRADER_ADDITION * garrisonedTradersCount / 100;
+
+			if (gain.trader)
+				gain.trader = Math.round(garrisonMultiplier * gain.trader);
+			if (gain.market1)
+				gain.market1 = Math.round(garrisonMultiplier * gain.market1);
+			if (gain.market2)
+				gain.market2 = Math.round(garrisonMultiplier * gain.market2);
 		}
 	}
 	
-	return garrisonMultiplier * CalculateTraderGain(firstMarket, secondMarket, this.template);
+	return gain;
 }
 
 Trader.prototype.GetGain = function()
@@ -116,7 +125,7 @@
 	if (marketsChanged)
 	{
 		// Drop carried goods
-		this.goods.amount = 0;
+		this.goods.amount = null;
 	}
 	return marketsChanged;
 }
@@ -177,14 +186,34 @@
 
 Trader.prototype.PerformTrade = function()
 {
-	if (this.goods.amount > 0)
+	if (this.goods.amount && this.goods.amount.trader)
 	{
 		var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
-		cmpPlayer.AddResource(this.goods.type, this.goods.amount);
+		cmpPlayer.AddResource(this.goods.type, this.goods.amount.trader);
 
 		var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
 		if (cmpStatisticsTracker)
-			cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount);
+			cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount.trader);
+
+		if (this.goods.amount.market1)
+		{
+			var cmpPlayer = QueryOwnerInterface(this.firstMarket, IID_Player);
+			cmpPlayer.AddResource(this.goods.type, this.goods.amount.market1);
+
+			var cmpStatisticsTracker = QueryOwnerInterface(this.firstMarket, IID_StatisticsTracker);
+			if (cmpStatisticsTracker)
+				cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount.market1);
+		}
+
+		if (this.goods.amount.market2)
+		{
+			var cmpPlayer = QueryOwnerInterface(this.secondMarket, IID_Player);
+			cmpPlayer.AddResource(this.goods.type, this.goods.amount.market2);
+
+			var cmpStatisticsTracker = QueryOwnerInterface(this.secondMarket, IID_StatisticsTracker);
+			if (cmpStatisticsTracker)
+				cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount.market2);
+		}
 	}
 	this.goods.type = this.preferredGoods;
 	this.goods.amount = this.gain;
@@ -198,7 +227,7 @@
 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;
