diff --git a/binaries/data/mods/public/gui/session/utility_functions.js b/binaries/data/mods/public/gui/session/utility_functions.js index 4676f36ab1..21b9d82ab5 100644 --- a/binaries/data/mods/public/gui/session/utility_functions.js +++ b/binaries/data/mods/public/gui/session/utility_functions.js @@ -74,6 +74,8 @@ function getRankIconSprite(entState) */ function getTradingTooltip(gain) { + if (!gain) + return ""; var playerID = Engine.GetPlayerID(); var simState = GetSimState(); diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js index 851d4c4c1e..8dd6f81a78 100644 --- a/binaries/data/mods/public/simulation/components/GuiInterface.js +++ b/binaries/data/mods/public/simulation/components/GuiInterface.js @@ -1667,13 +1667,13 @@ GuiInterface.prototype.GetTradingDetails = function(player, data) "hasBothMarkets": cmpEntityTrader.HasBothMarkets() }; if (cmpEntityTrader.HasBothMarkets()) - result.gain = cmpEntityTrader.GetGain(); + result.gain = cmpEntityTrader.GetGoods().amount; } else if (data.target === secondMarket) { result = { "type": "is second", - "gain": cmpEntityTrader.GetGain(), + "gain": cmpEntityTrader.GetGoods().amount, }; } else if (!firstMarket) diff --git a/binaries/data/mods/public/simulation/components/Trader.js b/binaries/data/mods/public/simulation/components/Trader.js index d3e43e0477..685cd62548 100644 --- a/binaries/data/mods/public/simulation/components/Trader.js +++ b/binaries/data/mods/public/simulation/components/Trader.js @@ -21,19 +21,17 @@ Trader.prototype.Schema = Trader.prototype.Init = function() { - this.firstMarket = INVALID_ENTITY; - this.secondMarket = INVALID_ENTITY; - // Gain from one pass between markets - this.gain = null; + this.markets = []; + this.index = -1; // Selected resource for trading this.requiredGoods = undefined; // Currently carried goods this.goods = { "type": null, "amount": null, "origin": null }; }; -Trader.prototype.CalculateGain = function(firstMarket, secondMarket) +Trader.prototype.CalculateGain = function(currentMarket, nextMarket) { - var gain = CalculateTraderGain(firstMarket, secondMarket, this.template, this.entity); + let gain = CalculateTraderGain(currentMarket, nextMarket, this.template, this.entity); if (!gain) // One of our markets must have been destroyed return null; @@ -67,11 +65,6 @@ Trader.prototype.CalculateGain = function(firstMarket, secondMarket) return gain; }; -Trader.prototype.GetGain = function() -{ - return this.gain; -}; - // Set target as target market. // Return true if at least one of markets was changed. Trader.prototype.SetTargetMarket = function(target, source) @@ -91,35 +84,34 @@ Trader.prototype.SetTargetMarket = function(target, source) return false; if (!cmpTargetIdentity.HasClass("Market") && !cmpTargetIdentity.HasClass("NavalMarket")) return false; - - this.firstMarket = source; - this.secondMarket = INVALID_ENTITY; + this.markets = [source]; } - - if (this.secondMarket) + if (this.markets.length >= 2) { // If we already have both markets - drop them // and use the target as first market - this.firstMarket = target; - this.secondMarket = INVALID_ENTITY; + this.index = 0; + this.markets = [target]; } - else if (this.firstMarket) + else if (this.markets.length == 1) { // If we have only one market and target is different from it, // set the target as second one - if (target == this.firstMarket) + if (target == this.markets[0]) marketsChanged = false; else { - this.secondMarket = target; - this.gain = this.CalculateGain(this.firstMarket, this.secondMarket); + this.index = 0; + this.markets.push(target); + this.goods.amount = this.CalculateGain(this.markets[0], this.markets[1]); } } else { // Else we don't have target markets at all, // set the target as first market - this.firstMarket = target; + this.index = 0; + this.markets = [target]; } if (marketsChanged) { @@ -131,17 +123,17 @@ Trader.prototype.SetTargetMarket = function(target, source) Trader.prototype.GetFirstMarket = function() { - return this.firstMarket; + return this.markets[0] || null; }; Trader.prototype.GetSecondMarket = function() { - return this.secondMarket; + return this.markets[1] || null; }; Trader.prototype.HasBothMarkets = function() { - return this.firstMarket && this.secondMarket; + return this.markets.length >= 2; }; Trader.prototype.GetRequiredGoods = function() @@ -186,6 +178,15 @@ Trader.prototype.CanTrade = function(target) Trader.prototype.PerformTrade = function(currentMarket) { + let previousMarket = this.markets[(this.index+this.markets.length) % this.markets.length]; + + this.index = ++this.index % this.markets.length; + + let nextMarket = this.markets[(this.index+this.markets.length) % this.markets.length]; + + if (previousMarket != currentMarket) + warn("Markets are not matching."); + if (this.goods.amount && this.goods.amount.traderGain) { var cmpPlayer = QueryOwnerInterface(this.entity); @@ -198,22 +199,22 @@ Trader.prototype.PerformTrade = function(currentMarket) if (this.goods.amount.market1Gain) { - var cmpPlayer = QueryOwnerInterface(this.firstMarket); + let cmpPlayer = QueryOwnerInterface(previousMarket); if (cmpPlayer) cmpPlayer.AddResource(this.goods.type, this.goods.amount.market1Gain); - var cmpStatisticsTracker = QueryOwnerInterface(this.firstMarket, IID_StatisticsTracker); + let cmpStatisticsTracker = QueryOwnerInterface(previousMarket, IID_StatisticsTracker); if (cmpStatisticsTracker) cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount.market1Gain); } if (this.goods.amount.market2Gain) { - var cmpPlayer = QueryOwnerInterface(this.secondMarket); + let cmpPlayer = QueryOwnerInterface(nextMarket); if (cmpPlayer) cmpPlayer.AddResource(this.goods.type, this.goods.amount.market2Gain); - var cmpStatisticsTracker = QueryOwnerInterface(this.secondMarket, IID_StatisticsTracker); + let cmpStatisticsTracker = QueryOwnerInterface(nextMarket, IID_StatisticsTracker); if (cmpStatisticsTracker) cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount.market2Gain); } @@ -234,7 +235,7 @@ Trader.prototype.PerformTrade = function(currentMarket) nextGoods = "metal"; } this.goods.type = nextGoods; - this.goods.amount = this.CalculateGain(this.firstMarket, this.secondMarket); + this.goods.amount = this.CalculateGain(currentMarket, nextMarket); this.goods.origin = currentMarket; }; @@ -243,23 +244,14 @@ Trader.prototype.GetGoods = function() return this.goods; }; -Trader.prototype.GetNextMarket = function() -{ - if (this.goods.amount && this.goods.origin == this.firstMarket) - return this.secondMarket; - - if (this.goods.amount && this.goods.origin != this.secondMarket) - this.goods.amount = null; // leftover from previous trading - return this.firstMarket; -}; - Trader.prototype.StopTrading = function() { + this.index = -1; + this.markets = []; // Drop carried goods this.goods.amount = null; // Reset markets - this.firstMarket = INVALID_ENTITY; - this.secondMarket = INVALID_ENTITY; + this.markets = []; }; // Get range in which deals with market are available, @@ -277,7 +269,7 @@ Trader.prototype.GetRange = function() Trader.prototype.OnGarrisonedUnitsChanged = function() { if (this.HasBothMarkets()) - this.gain = this.CalculateGain(this.firstMarket, this.secondMarket); + this.goods.amount = this.CalculateGain(this.markets[0], this.markets[1]); }; Engine.RegisterComponentType(IID_Trader, "Trader", Trader); diff --git a/binaries/data/mods/public/simulation/components/UnitAI.js b/binaries/data/mods/public/simulation/components/UnitAI.js index 55425f0446..43d0092f25 100644 --- a/binaries/data/mods/public/simulation/components/UnitAI.js +++ b/binaries/data/mods/public/simulation/components/UnitAI.js @@ -654,17 +654,11 @@ UnitAI.prototype.UnitFsmSpec = { return; } - var nextMarket = cmpTrader.GetNextMarket(); - if (nextMarket == this.order.data.firstMarket) - var state = "TRADE.APPROACHINGFIRSTMARKET"; - else - var state = "TRADE.APPROACHINGSECONDMARKET"; - // TODO find the nearest way-point from our position, and start with it this.waypoints = undefined; - if (this.MoveToMarket(nextMarket)) + if (this.MoveToMarket(this.order.data.target)) // We've started walking to the next market - this.SetNextState(state); + this.SetNextState("TRADE.APPROACHINGMARKET"); else this.FinishOrder(); }, @@ -2605,7 +2599,7 @@ UnitAI.prototype.UnitFsmSpec = { // TODO: Inform player }, - "APPROACHINGFIRSTMARKET": { + "APPROACHINGMARKET": { "enter": function () { this.SelectAnimation("move"); }, @@ -2613,27 +2607,11 @@ UnitAI.prototype.UnitFsmSpec = { "MoveCompleted": function() { if (this.waypoints && this.waypoints.length) { - if (!this.MoveToMarket(this.order.data.firstMarket)) + if (!this.MoveToMarket(this.order.data.target)) this.StopTrading(); } else - this.PerformTradeAndMoveToNextMarket(this.order.data.firstMarket, this.order.data.secondMarket, "APPROACHINGSECONDMARKET"); - }, - }, - - "APPROACHINGSECONDMARKET": { - "enter": function () { - this.SelectAnimation("move"); - }, - - "MoveCompleted": function() { - if (this.waypoints && this.waypoints.length) - { - if (!this.MoveToMarket(this.order.data.secondMarket)) - this.StopTrading(); - } - else - this.PerformTradeAndMoveToNextMarket(this.order.data.secondMarket, this.order.data.firstMarket, "APPROACHINGFIRSTMARKET"); + this.PerformTradeAndMoveToNextMarket(this.order.data.target); }, }, }, @@ -5170,7 +5148,13 @@ UnitAI.prototype.SetupTradeRoute = function(target, source, route, queued) var cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); if (cmpTrader.HasBothMarkets()) { - var data = { "firstMarket": cmpTrader.GetFirstMarket(), "secondMarket": cmpTrader.GetSecondMarket(), "route": route, "force": false }; + let data = { + "target": cmpTrader.GetFirstMarket(), + "firstMarket": cmpTrader.GetFirstMarket(), + "secondMarket": cmpTrader.GetSecondMarket(), + "route": route, + "force": false + }; if (this.expectedRoute) { @@ -5230,7 +5214,7 @@ UnitAI.prototype.MoveToMarket = function(targetMarket) return ok; }; -UnitAI.prototype.PerformTradeAndMoveToNextMarket = function(currentMarket, nextMarket, nextFsmStateName) +UnitAI.prototype.PerformTradeAndMoveToNextMarket = function(currentMarket) { if (!this.CanTrade(currentMarket)) { @@ -5238,34 +5222,36 @@ UnitAI.prototype.PerformTradeAndMoveToNextMarket = function(currentMarket, nextM return; } - if (this.CheckTargetRange(currentMarket, IID_Trader)) - { - var cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); - cmpTrader.PerformTrade(currentMarket); - if (!cmpTrader.GetGain().traderGain) - { - this.StopTrading(); - return; - } - - if (this.order.data.route && this.order.data.route.length) - { - this.waypoints = this.order.data.route.slice(); - if (nextFsmStateName == "APPROACHINGSECONDMARKET") - this.waypoints.reverse(); - this.waypoints.unshift(null); // additionnal dummy point for the market - } - - if (this.MoveToMarket(nextMarket)) // We've started walking to the next market - this.SetNextState(nextFsmStateName); - else - this.StopTrading(); - } - else + if (!this.CheckTargetRange(currentMarket, IID_Trader)) { if (!this.MoveToMarket(currentMarket)) // If the current market is not reached try again this.StopTrading(); + return; } + + let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); + cmpTrader.PerformTrade(currentMarket); + let nextMarket = cmpTrader.markets[cmpTrader.index]; + if (!cmpTrader.GetGoods().amount.traderGain) + { + this.StopTrading(); + return; + } + + this.order.data.target = nextMarket; + + if (this.order.data.route && this.order.data.route.length) + { + this.waypoints = this.order.data.route.slice(); + if (this.order.data.target == cmpTrader.GetSecondMarket()) + this.waypoints.reverse(); + this.waypoints.unshift(null); // additionnal dummy point for the market + } + + if (this.MoveToMarket(nextMarket)) // We've started walking to the next market + this.SetNextState("APPROACHINGMARKET"); + else + this.StopTrading(); }; UnitAI.prototype.StopTrading = function()