Index: binaries/data/mods/public/gui/session/selection_details.js
===================================================================
--- binaries/data/mods/public/gui/session/selection_details.js	(révision 13554)
+++ binaries/data/mods/public/gui/session/selection_details.js	(copie de travail)
@@ -134,13 +134,18 @@
 		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)
Index: binaries/data/mods/public/gui/session/utility_functions.js
===================================================================
--- binaries/data/mods/public/gui/session/utility_functions.js	(révision 13554)
+++ binaries/data/mods/public/gui/session/utility_functions.js	(copie de travail)
@@ -547,3 +547,24 @@
 
 	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 + ")";
+	tooltip += ".";
+
+	return tooltip;
+}
Index: binaries/data/mods/public/gui/session/input.js
===================================================================
--- binaries/data/mods/public/gui/session/input.js	(révision 13554)
+++ binaries/data/mods/public/gui/session/input.js	(copie de travail)
@@ -271,17 +271,17 @@
 
 			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 @@
 				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};
Index: binaries/data/mods/public/simulation/helpers/TraderGain.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/TraderGain.js	(révision 13554)
+++ 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,31 @@
 	// 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.traderGain = Math.pow(distance * DISTANCE_FACTOR, 2);
+	if (template && template.GainMultiplier)
+		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 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;
+	// 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;
 
-	if (template && template.GainMultiplier)
-		gain *= template.GainMultiplier;
-	gain = Math.round(gain);
+	}
+
 	return gain;
 }
 
Index: binaries/data/mods/public/simulation/components/Looter.js
===================================================================
--- binaries/data/mods/public/simulation/components/Looter.js	(révision 13554)
+++ binaries/data/mods/public/simulation/components/Looter.js	(copie de travail)
@@ -27,11 +27,15 @@
 	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);
 		}
 	}
Index: binaries/data/mods/public/simulation/components/Trader.js
===================================================================
--- binaries/data/mods/public/simulation/components/Trader.js	(révision 13554)
+++ 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)
 {
+	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 @@
 					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 @@
 	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.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.StopTrading = function()
 {
 	// Drop carried goods
-	this.goods.amount = 0;
+	this.goods.amount = null;
 	// Reset markets
 	this.firstMarket = INVALID_ENTITY;
 	this.secondMarket = INVALID_ENTITY;
