1
0
forked from 0ad/0ad

allow trade with mirage markets, fixes #3894

This was SVN commit r18172.
This commit is contained in:
mimo 2016-05-14 12:27:48 +00:00
parent 866d04a22b
commit 58e356babb
7 changed files with 165 additions and 39 deletions

View File

@ -129,6 +129,10 @@ Fogging.prototype.LoadMirage = function(player)
if (cmpResourceSupply)
cmpMirage.CopyResourceSupply(cmpResourceSupply);
var cmpMarket = Engine.QueryInterface(this.entity, IID_Market);
if (cmpMarket)
cmpMirage.CopyMarket(cmpMarket);
// Notify the GUI the entity has been replaced by a mirage, in case it is selected at this moment
var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
cmpGuiInterface.AddMiragedEntity(player, this.entity, this.mirages[player]);

View File

@ -289,7 +289,7 @@ GuiInterface.prototype.GetEntityState = function(player, ent)
if (cmpBuilder)
ret.builder = true;
let cmpMarket = Engine.QueryInterface(ent, IID_Market);
let cmpMarket = QueryMiragedInterface(ent, IID_Market);
if (cmpMarket)
ret.market = {
"land": cmpMarket.HasType("land"),

View File

@ -41,39 +41,47 @@ Market.prototype.HasType = function(type)
return this.tradeType.has(type);
};
Market.prototype.GetType = function()
{
return this.tradeType;
};
Market.prototype.GetTraders = function()
{
return this.traders;
};
/**
* Check if all traders with a route on this market can still trade
* Check if the traders attached to this market can still trade with it
* Warning: traders currently trading with a mirage of this market are dealt with in Mirage.js
*/
Market.prototype.UpdateTraders = function(onDestruction)
{
for (let trader of this.traders)
{
let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
if (!cmpTrader)
{
this.RemoveTrader(trader);
continue;
}
if (!cmpTrader.HasMarket(this.entity) || !onDestruction && cmpTrader.CanTrade(this.entity))
continue;
// this trader can no more trade
this.RemoveTrader(trader);
cmpTrader.RemoveMarket(this.entity);
}
};
Market.prototype.OnDiplomacyChanged = function(msg)
{
for (let ent of this.traders)
{
let cmpTrader = Engine.QueryInterface(ent, IID_Trader);
if (!cmpTrader)
this.RemoveTrader(ent);
else if (!cmpTrader.CanTrade(this.entity))
{
this.RemoveTrader(ent);
cmpTrader.RemoveMarket(this.entity);
}
}
this.UpdateTraders(false);
};
Market.prototype.OnOwnershipChanged = function(msg)
{
for (let ent of this.traders)
{
let cmpTrader = Engine.QueryInterface(ent, IID_Trader);
if (!cmpTrader)
this.RemoveTrader(ent);
else if (msg.to == -1)
cmpTrader.RemoveMarket(this.entity);
else if (!cmpTrader.CanTrade(this.entity))
{
this.RemoveTrader(ent);
cmpTrader.RemoveMarket(this.entity);
}
}
this.UpdateTraders(msg.to == -1);
};
Engine.RegisterComponentType(IID_Market, "Market", Market);

View File

@ -34,6 +34,10 @@ Mirage.prototype.Init = function()
this.killBeforeGather = null;
this.maxGatherers = null;
this.numGatherers = null;
this.traders = null;
this.marketType = null;
this.internationalBonus = null;
};
Mirage.prototype.SetParent = function(ent)
@ -125,6 +129,62 @@ Mirage.prototype.GetKillBeforeGather = function() { return this.killBeforeGather
Mirage.prototype.GetMaxGatherers = function() { return this.maxGatherers; };
Mirage.prototype.GetNumGatherers = function() { return this.numGatherers; };
// Market data
Mirage.prototype.CopyMarket = function(cmpMarket)
{
this.miragedIids.add(IID_Market);
this.traders = new Set();
for (let trader of cmpMarket.GetTraders())
{
let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
let cmpOwnership = Engine.QueryInterface(trader, IID_Ownership);
if (!cmpTrader || !cmpOwnership)
{
cmpMarket.RemoveTrader(trader);
continue;
}
if (this.player != cmpOwnership.GetOwner())
continue;
cmpTrader.SwitchMarket(cmpMarket.entity, this.entity);
cmpMarket.RemoveTrader(trader);
this.AddTrader(trader);
}
this.marketType = cmpMarket.GetType();
this.internationalBonus = cmpMarket.GetInternationalBonus();
};
Mirage.prototype.HasType = function(type) { return this.marketType.has(type); };
Mirage.prototype.GetInternationalBonus = function() { return this.internationalBonus; };
Mirage.prototype.AddTrader = function(trader) { this.traders.add(trader); };
Mirage.prototype.RemoveTrader = function(trader) { this.traders.delete(trader); };
Mirage.prototype.UpdateTraders = function(msg)
{
let cmpMarket = Engine.QueryInterface(this.parent, IID_Market);
if (!cmpMarket) // The parent market does not exist anymore
{
for (let trader of this.traders)
{
let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
if (cmpTrader)
cmpTrader.RemoveMarket(this.entity);
}
return;
}
// The market becomes visible, switch all traders from the mirage to the market
for (let trader of this.traders)
{
let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
if (!cmpTrader)
continue;
cmpTrader.SwitchMarket(this.entity, cmpMarket.entity);
this.RemoveTrader(trader);
cmpMarket.AddTrader(trader);
}
};
// ============================
Mirage.prototype.OnVisibilityChanged = function(msg)
@ -132,6 +192,9 @@ Mirage.prototype.OnVisibilityChanged = function(msg)
if (msg.player != this.player || msg.newVisibility != VIS_HIDDEN)
return;
if (this.miragedIids.has(IID_Market))
this.UpdateTraders(msg);
if (this.parent == INVALID_ENTITY)
Engine.DestroyEntity(this.entity);
else

View File

@ -44,7 +44,7 @@ Trader.prototype.CalculateGain = function(currentMarket, nextMarket)
{
var garrisonMultiplier = 1;
var garrisonedTradersCount = 0;
for each (var entity in cmpGarrisonHolder.GetEntities())
for (let entity of cmpGarrisonHolder.GetEntities())
{
var cmpGarrisonedUnitTrader = Engine.QueryInterface(entity, IID_Trader);
if (cmpGarrisonedUnitTrader)
@ -68,18 +68,17 @@ Trader.prototype.CalculateGain = function(currentMarket, nextMarket)
// Return true if at least one of markets was changed.
Trader.prototype.SetTargetMarket = function(target, source)
{
var cmpTargetMarket = Engine.QueryInterface(target, IID_Market);
let cmpTargetMarket = QueryMiragedInterface(target, IID_Market);
if (!cmpTargetMarket)
return false;
if (source)
{
// Establish a trade route with both markets in one go.
let cmpSourceMarket = Engine.QueryInterface(source, IID_Market);
let cmpSourceMarket = QueryMiragedInterface(source, IID_Market);
if (!cmpSourceMarket)
return false;
this.markets = [source];
cmpSourceMarket.AddTrader(this.entity);
}
if (this.markets.length >= 2)
{
@ -87,7 +86,7 @@ Trader.prototype.SetTargetMarket = function(target, source)
// and use the target as first market
for (let market of this.markets)
{
let cmpMarket = Engine.QueryInterface(market, IID_Market);
let cmpMarket = QueryMiragedInterface(market, IID_Market);
if (cmpMarket)
cmpMarket.RemoveTrader(this.entity);
}
@ -160,7 +159,7 @@ Trader.prototype.CanTrade = function(target)
{
var cmpTraderIdentity = Engine.QueryInterface(this.entity, IID_Identity);
// Check that the target exists
var cmpTargetMarket = Engine.QueryInterface(target, IID_Market);
var cmpTargetMarket = QueryMiragedInterface(target, IID_Market);
if (!cmpTargetMarket)
return false;
// Check that the target is not a foundation
@ -251,20 +250,46 @@ Trader.prototype.GetGoods = function()
};
/**
* Called when this trader can no longer trade with the market
* Returns true if the trader has the given market (can be either a market or a mirage)
*/
Trader.prototype.HasMarket = function(market)
{
return this.markets.indexOf(market) != -1;
};
/**
* Remove a market when this trader can no longer trade with it
*/
Trader.prototype.RemoveMarket = function(market)
{
let index = this.markets.indexOf(market);
if (index != -1)
this.markets.splice(index, 1);
if (index == -1)
return;
this.markets.splice(index, 1);
let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
if (cmpUnitAI)
cmpUnitAI.MarketRemoved(market);
};
/**
* Switch between a market and its mirage according to visibility
*/
Trader.prototype.SwitchMarket = function(oldMarket, newMarket)
{
let index = this.markets.indexOf(oldMarket);
if (index == -1)
return;
this.markets[index] = newMarket;
let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
if (cmpUnitAI)
cmpUnitAI.SwitchMarketOrder(oldMarket, newMarket);
};
Trader.prototype.StopTrading = function()
{
for (let market of this.markets)
{
let cmpMarket = Engine.QueryInterface(market, IID_Market);
let cmpMarket = QueryMiragedInterface(market, IID_Market);
if (cmpMarket)
cmpMarket.RemoveTrader(this.entity);
}

View File

@ -166,6 +166,10 @@ UnitAI.prototype.UnitFsmSpec = {
// ignore
},
"TradingCanceled": function(msg) {
// ignore
},
"GuardedAttacked": function(msg) {
// ignore
},
@ -648,7 +652,7 @@ UnitAI.prototype.UnitFsmSpec = {
"Order.Trade": function(msg) {
// We must check if this trader has both markets in case it was a back-to-work order
var cmpTrader = Engine.QueryInterface(this.entity, IID_Trader);
if (!cmpTrader || ! cmpTrader.HasBothMarkets())
if (!cmpTrader || !cmpTrader.HasBothMarkets())
{
this.FinishOrder();
return;
@ -2614,6 +2618,16 @@ UnitAI.prototype.UnitFsmSpec = {
this.PerformTradeAndMoveToNextMarket(this.order.data.target);
},
},
"TradingCanceled": function(msg) {
if (msg.market != this.order.data.target)
return;
let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader);
let otherMarket = cmpTrader && cmpTrader.GetFirstMarket();
this.StopTrading();
if (otherMarket)
this.WalkToTarget(otherMarket);
},
},
"REPAIR": {
@ -5209,6 +5223,12 @@ UnitAI.prototype.SetTargetMarket = function(target, source)
return marketsChanged;
};
UnitAI.prototype.SwitchMarketOrder = function(oldMarket, newMarket)
{
if (this.order.data && this.order.data.target && this.order.data.target == oldMarket)
this.order.data.target == newMarket;
};
UnitAI.prototype.MoveToMarket = function(targetMarket)
{
if (this.waypoints && this.waypoints.length > 1)
@ -5268,6 +5288,12 @@ UnitAI.prototype.PerformTradeAndMoveToNextMarket = function(currentMarket)
this.StopTrading();
};
UnitAI.prototype.MarketRemoved = function(market)
{
if (this.order.data.target == market)
this.UnitFsm.ProcessMessage(this, { "type": "TradingCanceled", "market": market });
};
UnitAI.prototype.StopTrading = function()
{
this.StopMoving();

View File

@ -1,7 +1,7 @@
function CalculateTraderGain(firstMarket, secondMarket, traderTemplate, trader)
{
let cmpMarket1 = Engine.QueryInterface(firstMarket, IID_Market);
let cmpMarket2 = Engine.QueryInterface(secondMarket, IID_Market);
let cmpMarket1 = QueryMiragedInterface(firstMarket, IID_Market);
let cmpMarket2 = QueryMiragedInterface(secondMarket, IID_Market);
if (!cmpMarket1 || !cmpMarket2)
return null;