Ticket #2311: trade.diff
File trade.diff, 23.5 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/gui/page_session.xml
8 8 <include>common/common_sprites.xml</include> 9 9 <include>common/common_styles.xml</include> 10 10 11 <include>common/modern/styles.xml</include> 12 <include>common/modern/sprites.xml</include> 13 <include>common/modern/setup.xml</include> 14 11 15 <include>session/sprites.xml</include> 12 16 <include>session/setup.xml</include> 13 17 <include>session/styles.xml</include> -
binaries/data/mods/public/gui/session/input.js
290 290 cursor = "action-setup-trade-route"; 291 291 tooltip = "Right-click to establish a default route for new traders."; 292 292 if (trader) 293 tooltip += "\nGain (metal): " + getTradingTooltip(gain);293 tooltip += "\nGain: " + getTradingTooltip(gain); 294 294 else // Foundation or cannot produce traders 295 tooltip += "\nExpected gain (metal): " + getTradingTooltip(gain);295 tooltip += "\nExpected gain: " + getTradingTooltip(gain); 296 296 } 297 297 } 298 298 … … 363 363 case "is first": 364 364 tooltip = "Origin trade market."; 365 365 if (tradingDetails.hasBothMarkets) 366 tooltip += "\nGain (" + tradingDetails.goods + "): " + getTradingTooltip(tradingDetails.gain);366 tooltip += "\nGain: " + getTradingTooltip(tradingDetails.gain); 367 367 else 368 368 tooltip += "\nRight-click on another market to set it as a destination trade market." 369 369 break; 370 370 case "is second": 371 tooltip = "Destination trade market.\nGain (" + tradingDetails.goods + "): " + getTradingTooltip(tradingDetails.gain);371 tooltip = "Destination trade market.\nGain: " + getTradingTooltip(tradingDetails.gain); 372 372 break; 373 373 case "set first": 374 374 tooltip = "Right-click to set as origin trade market"; 375 375 break; 376 376 case "set second": 377 tooltip = "Right-click to set as destination trade market.\nGain (" + tradingDetails.goods + "): " + getTradingTooltip(tradingDetails.gain);377 tooltip = "Right-click to set as destination trade market.\nGain: " + getTradingTooltip(tradingDetails.gain); 378 378 break; 379 379 } 380 380 return {"possible": true, "tooltip": tooltip}; … … 1572 1572 } 1573 1573 } 1574 1574 1575 // Called by GUI when user changes preferred trading goods1576 function selectTradingPreferredGoods(data)1577 {1578 Engine.PostNetworkCommand({"type": "select-trading-goods", "entities": data.entities, "preferredGoods": data.preferredGoods});1579 }1580 1581 1575 // Called by GUI when user clicks exchange resources button 1582 1576 function exchangeResources(command) 1583 1577 { … … 1906 1900 case "back-to-work": 1907 1901 backToWork(); 1908 1902 break; 1903 case "select-trading-goods": 1904 toggleTrade(); 1905 break; 1909 1906 default: 1910 1907 break; 1911 1908 } -
binaries/data/mods/public/gui/session/menu.js
29 29 // Number of pixels per millisecond to move 30 30 const MENU_SPEED = 1.2; 31 31 32 // Trade menu: available resources and step for probability changes 33 const RESOURCES = ["food", "wood", "stone", "metal"]; 34 const STEP = 10; 35 32 36 var isMenuOpen = false; 33 37 var menu; 34 38 35 39 var isDiplomacyOpen = false; 40 var isTradeOpen = false; 36 41 37 42 // Redefined every time someone makes a tribute (so we can save some data in a closure). Called in input.js handleInputBeforeGui. 38 43 var flushTributing = function() {}; … … 116 121 openChat(); 117 122 } 118 123 119 function diplomacyMenuButton()120 {121 closeMenu();122 closeOpenDialogs();123 openDiplomacy();124 }125 126 124 function pauseMenuButton() 127 125 { 128 126 togglePause(); … … 369 367 openDiplomacy(); 370 368 }; 371 369 370 function openTrade() 371 { 372 isTradeOpen = true; 373 374 var updateButtons = function() 375 { 376 for (var res in button) 377 { 378 button[res].label.caption = proba[res] + "%"; 379 if (res == selec) 380 { 381 button[res].sel.hidden = false; 382 button[res].up.hidden = true; 383 button[res].dn.hidden = true; 384 } 385 else 386 { 387 button[res].sel.hidden = true; 388 button[res].up.hidden = (proba[res] == 100 || proba[selec] == 0); 389 button[res].dn.hidden = (proba[res] == 0 || proba[selec] == 100); 390 } 391 } 392 } 393 394 var proba = Engine.GuiInterfaceCall("GetTradingGoods"); 395 var button = {}; 396 var selec = RESOURCES[0]; 397 for (var i = 0; i < RESOURCES.length; ++i) 398 { 399 if (i > 0) 400 { 401 var size = getGUIObjectByName("tradeResource["+(i-1)+"]").size; 402 var width = size.right - size.left; 403 size.left += width; 404 size.right += width; 405 getGUIObjectByName("tradeResource["+i+"]").size = size; 406 } 407 var resource = RESOURCES[i]; 408 proba[resource] = (proba[resource] ? proba[resource] : 0); 409 var buttonSel = getGUIObjectByName("tradeResourceButton["+i+"]"); 410 var icon = getGUIObjectByName("tradeResourceIcon["+i+"]"); 411 icon.sprite = "stretched:session/icons/resources/" + resource + ".png"; 412 var label = getGUIObjectByName("tradeResourceText["+i+"]"); 413 var buttonUp = getGUIObjectByName("tradeArrowUp["+i+"]"); 414 var buttonDn = getGUIObjectByName("tradeArrowDn["+i+"]"); 415 var iconSel = getGUIObjectByName("tradeResourceSelection["+i+"]"); 416 button[resource] = { "up": buttonUp, "dn": buttonDn, "label": label, "sel": iconSel }; 417 418 buttonSel.onpress = (function(resource){ 419 return function() { 420 if (selec == resource) 421 return; 422 selec = resource; 423 updateButtons(); 424 } 425 })(resource); 426 427 buttonUp.onpress = (function(resource){ 428 return function() { 429 proba[resource] += Math.min(STEP, proba[selec]); 430 proba[selec] -= Math.min(STEP, proba[selec]); 431 Engine.PostNetworkCommand({"type": "set-trading-goods", "tradingGoods": proba}); 432 updateButtons(); 433 } 434 })(resource); 435 436 buttonDn.onpress = (function(resource){ 437 return function() { 438 proba[selec] += Math.min(STEP, proba[resource]); 439 proba[resource] -= Math.min(STEP, proba[resource]); 440 Engine.PostNetworkCommand({"type": "set-trading-goods", "tradingGoods": proba}); 441 updateButtons(); 442 } 443 })(resource); 444 } 445 updateButtons(); 446 447 var traderNumber = Engine.GuiInterfaceCall("GetTraderNumber"); 448 var caption = ""; 449 var comma = ""; 450 if (traderNumber.landTrader.total == 0) 451 caption += "0"; 452 else 453 { 454 if (traderNumber.landTrader.trading > 0) 455 { 456 caption += traderNumber.landTrader.trading + " trading" 457 comma = ", "; 458 } 459 if (traderNumber.landTrader.garrisoned > 0) 460 { 461 caption += comma + traderNumber.landTrader.garrisoned + " garrisoned inside ships"; 462 comma = ", "; 463 } 464 var inactive = traderNumber.landTrader.total - traderNumber.landTrader.trading - traderNumber.landTrader.garrisoned; 465 if (inactive > 0) 466 caption += comma + "[color=\"orange\"]" + inactive + " inactive[/color]"; 467 } 468 getGUIObjectByName("landTraders").caption = caption; 469 470 caption = ""; 471 comma = ""; 472 if (traderNumber.shipTrader.total == 0) 473 caption += "0"; 474 else 475 { 476 if (traderNumber.shipTrader.trading > 0) 477 { 478 caption += traderNumber.shipTrader.trading + " trading" 479 comma = ", "; 480 } 481 var inactive = traderNumber.shipTrader.total - traderNumber.shipTrader.trading; 482 if (inactive > 0) 483 caption += comma + "[color=\"orange\"]" + inactive + " inactive[/color]"; 484 } 485 getGUIObjectByName("shipTraders").caption = caption; 486 487 getGUIObjectByName("tradeDialogPanel").hidden = false; 488 } 489 490 function closeTrade() 491 { 492 isTradeOpen = false; 493 getGUIObjectByName("tradeDialogPanel").hidden = true; 494 } 495 496 function toggleTrade() 497 { 498 if (isTradeOpen) 499 closeTrade(); 500 else 501 openTrade(); 502 }; 503 372 504 function toggleGameSpeed() 373 505 { 374 506 var gameSpeed = getGUIObjectByName("gameSpeed"); … … 436 568 closeMenu(); 437 569 closeChat(); 438 570 closeDiplomacy(); 571 closeTrade(); 439 572 closeSettings(false); 440 573 } 441 574 -
binaries/data/mods/public/gui/session/session.js
54 54 function GetSimState() 55 55 { 56 56 if (!g_SimState) 57 {58 57 g_SimState = Engine.GuiInterfaceCall("GetSimulationState"); 59 }60 58 61 59 return g_SimState; 62 60 } -
binaries/data/mods/public/gui/session/session.xml
435 435 </object> 436 436 437 437 <!-- ================================ ================================ --> 438 <!-- Trade Window --> 439 <!-- ================================ ================================ --> 440 <object name="tradeDialogPanel" 441 size="50%-250 50%-130 50%+250 50%+100" 442 type="image" 443 hidden="true" 444 sprite="ModernDialog" 445 > 446 <object type="text" style="TitleText" size="50%-96 -16 50%+96 16">Trade</object> 447 448 <!-- Trading goods --> 449 <object name="tradeGoods" size="20 50 100%-20 114"> 450 <object name="tradeHeader" size="0 0 180 100%" type="text" style="chatPanel" ghost="true" caption="Trading goods selection:"/> 451 452 <object size="180 0 100% 32"> 453 <repeat count="4"> 454 <object name="tradeResource[n]" size="0 0 56 32"> 455 <object name="tradeResourceButton[n]" size="4 0 36 100%" type="button" style="StoneButton"> 456 <object name="tradeResourceIcon[n]" type="image" ghost="true"/> 457 <object name="tradeResourceSelection[n]" type="image" sprite="stretched:session/icons/corners.png" ghost="true"/> 458 <object name="tradeResourceText[n]" type="text" style="ModernCenteredLabelText" ghost="true"/> 459 </object> 460 <object name="tradeArrowUp[n]" size="36 0 52 50%" type="button" style="iconButton"> 461 <object type="image" ghost="true" sprite="wheatArrowUp"/> 462 </object> 463 <object name="tradeArrowDn[n]" size="36 50% 52 100%" type="button" style="iconButton"> 464 <object type="image" ghost="true" sprite="wheatArrowDn"/> 465 </object> 466 </object> 467 </repeat> 468 <object name="tradeHelp" size="100%-24 4 100% 28" enabled="false" type="button" style="StoneButton" tooltip_style="sessionToolTipBold" tooltip="Select one goods as origin of the changes, \nthen use the arrows of the target goods to make the changes."> 469 <object size="20% 15% 80% 75%" type="image" ghost="true" sprite="iconInfoWhite"/> 470 </object> 471 </object> 472 </object> 473 474 <object name="tradeStatistics" size="20 120 100%-20 168"> 475 <object size="0 0 130 50%" type="text" style="chatPanel" ghost="true" caption="Traders:"/> 476 <object name="landTraders" size="130 0 100% 50%" type="text" style="chatPanel" ghost="true" /> 477 <object size="0 50% 130 100%" type="text" style="chatPanel" ghost="true" caption = "Merchant ships:"/> 478 <object name="shipTraders" size="130 50% 100% 100%" type="text" style="chatPanel" ghost="true" /> 479 </object> 480 481 <object size="50%-64 100%-50 50%+64 100%-22" type="button" style="StoneButton"> 482 Close 483 <action on="Press">closeTrade();</action> 484 </object> 485 </object> 486 487 <!-- ================================ ================================ --> 438 488 <!-- Settings Window --> 439 489 <!-- ================================ ================================ --> 440 490 <object name="settingsDialogPanel" … … 635 685 <!-- ================================ ================================ --> 636 686 <object type="button" 637 687 name="gameSpeedButton" 638 size="100%-2 26 4 100%-19832"688 size="100%-258 4 100%-230 32" 639 689 style="iconButton" 640 690 tooltip_style="sessionToolTip" 641 691 tooltip="Game speed" … … 646 696 </action> 647 697 </object> 648 698 649 <object size="100%-3 48 40 100%-19865" name="gameSpeed" type="dropdown" buffer_zone="5" style="StoneDropDown" hidden="true" tooltip="Choose game speed" tooltip_style="sessionToolTip"/>699 <object size="100%-380 40 100%-230 65" name="gameSpeed" type="dropdown" buffer_zone="5" style="StoneDropDown" hidden="true" tooltip="Choose game speed" tooltip_style="sessionToolTip"/> 650 700 651 701 <!-- ================================ ================================ --> 652 702 <!-- Diplomacy Button --> 653 703 <!-- ================================ ================================ --> 654 704 <object type="button" 655 705 name="diplomacyButton1" 656 size="100%- 194 4 100%-16632"706 size="100%-226 4 100%-198 32" 657 707 style="iconButton" 658 708 tooltip_style="sessionToolTip" 659 709 tooltip="Diplomacy" … … 666 716 </object> 667 717 668 718 <!-- ================================ ================================ --> 719 <!-- Trade Button --> 720 <!-- ================================ ================================ --> 721 <object type="button" 722 name="tradeButton1" 723 size="100%-194 4 100%-166 32" 724 style="iconButton" 725 tooltip_style="sessionToolTip" 726 tooltip="Trade" 727 > 728 <!-- TODO make the button less ugly --> 729 <object size="0 0 100% 100%" name="tradeButtonImage" type="image" sprite="stretched:session/icons/economics.png" ghost="true"/> 730 <action on="Press"> 731 toggleTrade(); 732 </action> 733 </object> 734 735 <!-- ================================ ================================ --> 669 736 <!-- Menu Button --> 670 737 <!-- ================================ ================================ --> 671 738 <object type="button" -
binaries/data/mods/public/gui/session/unit_commands.js
17 17 const UNIT_PANEL_BASE = -52; // QUEUE: The offset above the main panel (will often be negative) 18 18 const UNIT_PANEL_HEIGHT = 44; // QUEUE: The height needed for a row of buttons 19 19 20 // Trading constants21 const TRADING_RESOURCES = ["food", "wood", "stone", "metal"];22 23 20 // Barter constants 24 21 const BARTER_RESOURCE_AMOUNT_TO_SELL = 100; 25 22 const BARTER_BUNCH_MULTIPLIER = 5; … … 898 895 function setupUnitTradingPanel(usedPanels, unitEntState, selection) 899 896 { 900 897 usedPanels[TRADING] = 1; 901 902 for (var i = 0; i < TRADING_RESOURCES.length; i++)903 {904 var resource = TRADING_RESOURCES[i];905 var button = getGUIObjectByName("unitTradingButton["+i+"]");906 button.size = (i * 46) + " 0 " + ((i + 1) * 46) + " 46";907 var selectTradingPreferredGoodsData = { "entities": selection, "preferredGoods": resource };908 button.onpress = (function(e){ return function() { selectTradingPreferredGoods(e); } })(selectTradingPreferredGoodsData);909 button.enabled = true;910 button.tooltip = "Set " + resource + " as trading goods";911 var icon = getGUIObjectByName("unitTradingIcon["+i+"]");912 var preferredGoods = unitEntState.trader.preferredGoods;913 var selected = getGUIObjectByName("unitTradingSelection["+i+"]");914 selected.hidden = !(resource == preferredGoods);915 var grayscale = (resource != preferredGoods) ? "grayscale:" : "";916 icon.sprite = "stretched:"+grayscale+"session/icons/resources/" + resource + ".png";917 }918 898 } 919 899 920 900 // Sets up "unit barter panel" - special case for setupUnitPanel … … 1078 1058 else if (entState.production && entState.production.entities) 1079 1059 setupUnitPanel(TRAINING, usedPanels, entState, playerState, trainableEnts, 1080 1060 function (trainEntType) { addTrainingToQueue(selection, trainEntType, playerState); } ); 1081 else if (entState.trader)1082 setupUnitTradingPanel(usedPanels, entState, selection);1061 // else if (entState.trader) 1062 // setupUnitTradingPanel(usedPanels, entState, selection); 1083 1063 else if (!entState.foundation && entState.gate || hasClass(entState, "LongWall")) 1084 1064 { 1085 1065 // Allow long wall pieces to be converted to gates -
binaries/data/mods/public/gui/session/utility_functions.js
321 321 }); 322 322 } 323 323 324 if (hasClass(entState, "Market")) 325 { 326 commands.push({ 327 "name": "select-trading-goods", 328 "tooltip": "Select trading goods", 329 "icon": "economics.png" 330 }); 331 } 332 324 333 return commands; 325 334 } 326 335 -
binaries/data/mods/public/simulation/components/GuiInterface.js
217 217 if (cmpTrader) 218 218 { 219 219 ret.trader = { 220 "goods": cmpTrader.GetGoods(), 221 "preferredGoods": cmpTrader.GetPreferredGoods() 220 "goods": cmpTrader.GetGoods() 222 221 }; 223 222 } 224 223 … … 1709 1708 { 1710 1709 result = { 1711 1710 "type": "is first", 1712 "goods": cmpEntityTrader.GetPreferredGoods(),1713 1711 "hasBothMarkets": cmpEntityTrader.HasBothMarkets() 1714 1712 }; 1715 1713 if (cmpEntityTrader.HasBothMarkets()) … … 1720 1718 result = { 1721 1719 "type": "is second", 1722 1720 "gain": cmpEntityTrader.GetGain(), 1723 "goods": cmpEntityTrader.GetPreferredGoods()1724 1721 }; 1725 1722 } 1726 1723 else if (!firstMarket) … … 1732 1729 result = { 1733 1730 "type": "set second", 1734 1731 "gain": cmpEntityTrader.CalculateGain(firstMarket, data.target), 1735 "goods": cmpEntityTrader.GetPreferredGoods()1736 1732 }; 1737 1733 } 1738 1734 else … … 1798 1794 cmpRangeManager.SetDebugOverlay(enabled); 1799 1795 }; 1800 1796 1797 GuiInterface.prototype.GetTraderNumber = function(player) 1798 { 1799 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 1800 var traders = cmpRangeManager.GetEntitiesByPlayer(player).filter( function(e) { 1801 return Engine.QueryInterface(e, IID_Trader); 1802 }); 1803 1804 var landTrader = { "total": 0, "trading": 0, "garrisoned": 0 }; 1805 var shipTrader = { "total": 0, "trading": 0 }; 1806 for each (var ent in traders) 1807 { 1808 var cmpIdentity = Engine.QueryInterface(ent, IID_Identity); 1809 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); 1810 if (!cmpIdentity || !cmpUnitAI) 1811 continue; 1812 if (cmpIdentity.HasClass("Ship")) 1813 { 1814 ++shipTrader.total; 1815 if (cmpUnitAI.order && cmpUnitAI.order.type == "Trade") 1816 ++shipTrader.trading; 1817 } 1818 else 1819 { 1820 ++landTrader.total; 1821 if (cmpUnitAI.order && cmpUnitAI.order.type == "Trade") 1822 ++landTrader.trading; 1823 if (cmpUnitAI.order && cmpUnitAI.order.type == "Garrison") 1824 { 1825 var holder = cmpUnitAI.order.data.target; 1826 var cmpHolderUnitAI = Engine.QueryInterface(holder, IID_UnitAI); 1827 if (cmpHolderUnitAI && cmpHolderUnitAI.order && cmpHolderUnitAI.order.type == "Trade") 1828 ++landTrader.garrisoned; 1829 } 1830 } 1831 } 1832 1833 return { "landTrader": landTrader, "shipTrader": shipTrader }; 1834 }; 1835 1836 GuiInterface.prototype.GetTradingGoods = function(player, tradingGoods) 1837 { 1838 var cmpPlayer = QueryPlayerIDInterface(player, IID_Player); 1839 return cmpPlayer.GetTradingGoods(); 1840 }; 1841 1801 1842 GuiInterface.prototype.OnGlobalEntityRenamed = function(msg) 1802 1843 { 1803 1844 this.renamedEntities.push(msg); … … 1852 1893 "SetObstructionDebugOverlay": 1, 1853 1894 "SetMotionDebugOverlay": 1, 1854 1895 "SetRangeDebugOverlay": 1, 1896 1897 "GetTraderNumber": 1, 1898 "GetTradingGoods": 1, 1855 1899 }; 1856 1900 1857 1901 GuiInterface.prototype.ScriptCall = function(player, name, args) -
binaries/data/mods/public/simulation/components/Player.js
19 19 "metal": 300, 20 20 "stone": 300 21 21 }; 22 22 this.tradingGoods = [ // goods for next trade-route and its proba in % (the sum of probas must be 100) 23 { "goods": "stone", "proba": 50 }, 24 { "goods": "metal", "proba": 50 } ]; 23 25 this.team = -1; // team number of the player, players on the same team will always have ally diplomatic status - also this is useful for team emblems, scoring, etc. 24 26 this.teamsLocked = false; 25 27 this.state = "active"; // game state - one of "active", "defeated", "won" … … 234 236 return true; 235 237 }; 236 238 239 Player.prototype.GetNextTradingGoods = function() 240 { 241 var value = 100*Math.random(); 242 var last = this.tradingGoods.length - 1; 243 var sumProba = 0; 244 for (var i = 0; i < last; ++i) 245 { 246 sumProba += this.tradingGoods[i].proba; 247 if (value < sumProba) 248 return this.tradingGoods[i].goods; 249 } 250 return this.tradingGoods[last].goods; 251 }; 252 253 Player.prototype.GetTradingGoods = function() 254 { 255 var tradingGoods = {}; 256 for each (var resource in this.tradingGoods) 257 tradingGoods[resource.goods] = resource.proba; 258 259 return tradingGoods; 260 }; 261 262 Player.prototype.SetTradingGoods = function(tradingGoods) 263 { 264 var sumProba = 0; 265 for (var resource in tradingGoods) 266 sumProba += tradingGoods[resource]; 267 if (sumProba != 100) // consistency check 268 { 269 error("Player.js SetTradingGoods: " + uneval(tradingGoods)); 270 tradingGoods = { "food": 20, "wood":20, "stone":30, "metal":30 }; 271 } 272 273 this.tradingGoods = []; 274 for (var resource in tradingGoods) 275 this.tradingGoods.push( {"goods": resource, "proba": tradingGoods[resource]} ); 276 }; 277 237 278 Player.prototype.GetState = function() 238 279 { 239 280 return this.state; -
binaries/data/mods/public/simulation/components/Trader.js
28 28 this.secondMarket = INVALID_ENTITY; 29 29 // Gain from one pass between markets 30 30 this.gain = null; 31 // Selected resource for trading32 this.preferredGoods = "metal";33 31 // Currently carried goods 34 32 this.goods = { "type": null, "amount": null, "origin": null }; 35 33 }; … … 145 143 return this.firstMarket && this.secondMarket; 146 144 }; 147 145 148 Trader.prototype.GetPreferredGoods = function()149 {150 return this.preferredGoods;151 };152 153 Trader.prototype.SetPreferredGoods = function(preferredGoods)154 {155 // Check that argument is a correct resource name156 if (RESOURCES.indexOf(preferredGoods) == -1)157 return;158 this.preferredGoods = preferredGoods;159 };160 161 146 Trader.prototype.CanTrade = function(target) 162 147 { 163 148 var cmpTraderIdentity = Engine.QueryInterface(this.entity, IID_Identity); … … 218 203 cmpStatisticsTracker.IncreaseTradeIncomeCounter(this.goods.amount.market2Gain); 219 204 } 220 205 } 221 this.goods.type = this.preferredGoods; 206 207 var nextGoods = undefined; 208 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 209 if (cmpPlayer) 210 nextGoods = cmpPlayer.GetNextTradingGoods(); 211 212 if (!nextGoods || RESOURCES.indexOf(nextGoods) == -1) 213 nextGoods = "metal"; 214 215 this.goods.type = nextGoods; 222 216 this.goods.amount = this.gain; 223 217 this.goods.origin = currentMarket; 224 218 }; -
binaries/data/mods/public/simulation/helpers/Commands.js
481 481 } 482 482 break; 483 483 484 case "select-trading-goods": 485 for each (var ent in entities) 486 { 487 var cmpTrader = Engine.QueryInterface(ent, IID_Trader); 488 if (cmpTrader) 489 cmpTrader.SetPreferredGoods(cmd.preferredGoods); 490 } 484 case "set-trading-goods": 485 cmpPlayer.SetTradingGoods(cmd.tradingGoods); 491 486 break; 492 487 493 488 case "barter":