Ticket #23: barter_2011_10_17.diff

File barter_2011_10_17.diff, 20.3 KB (added by fcxSanya, 19 months ago)
  • source/simulation2/Simulation2.cpp

     
    101101                LOGERROR(L"Can't find component type " L##name); \ 
    102102            m_ComponentManager.AddComponent(SYSTEM_ENTITY, cid, noParam) 
    103103 
     104            LOAD_SCRIPTED_COMPONENT("Barter"); 
    104105            LOAD_SCRIPTED_COMPONENT("AIInterface"); 
    105106            LOAD_SCRIPTED_COMPONENT("EndGameManager"); 
    106107            LOAD_SCRIPTED_COMPONENT("GuiInterface"); 
  • binaries/data/mods/public/gui/session/session.xml

     
    493493                    </object> 
    494494                </object> 
    495495 
     496                <object name="unitBarterPanel" hidden="true" 
     497                    size="5 5 100% 100%" 
     498                > 
     499                    <object ghost="true" style="resourceText" type="text" size="0 0 100% 18">Exchange resources:</object> 
     500                    <object size="0 18 100% 64"> 
     501                        <repeat count="4"> 
     502                            <object name="unitBarterSellButton[n]" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottomBold" z="100"> 
     503                                <object name="unitBarterSellIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 
     504                                <object name="unitBarterSellAmount[n]" ghost="true" style="resourceText" type="text" size="0 0 100% 50%"/> 
     505                            </object> 
     506                        </repeat> 
     507                    </object> 
     508                    <object size="0 64 100% 110"> 
     509                        <repeat count="4"> 
     510                            <object name="unitBarterBuyButton[n]" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottomBold" z="100"> 
     511                                <object name="unitBarterBuyIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 
     512                                <object name="unitBarterBuyAmount[n]" ghost="true" style="resourceText" type="text" size="0 0 100% 50%"/> 
     513                            </object> 
     514                        </repeat> 
     515                    </object> 
     516                    <object name="PerformDealButton" type="button" style="StoneButton" size="2 112 100%-7 142" z="100"> 
     517                        <object ghost="true" style="statsText" type="text" size="0 0 100% 100%">Perform deal</object> 
     518                    </object> 
     519                </object> 
     520 
    496521                <!-- Stance Selection --> 
    497522                <object name="unitStancePanel" 
    498523                    style="TranslucentPanel" 
  • binaries/data/mods/public/gui/session/input.js

     
    10081008    inputState = INPUT_BUILDING_PLACEMENT; 
    10091009} 
    10101010 
     1011// Called by GUI when user clicks exchange resources button 
     1012function exchangeResources(command) 
     1013{ 
     1014    Engine.PostNetworkCommand({"type": "barter", "sell": command.sell, "buy": command.buy, "amount": command.amount }); 
     1015} 
     1016 
     1017 
    10111018// Batch training: 
    10121019// When the user shift-clicks, we set these variables and switch to INPUT_BATCHTRAINING 
    10131020// When the user releases shift, or clicks on a different training button, we create the batched units 
  • binaries/data/mods/public/gui/session/unit_commands.js

     
    1313const UNIT_PANEL_BASE = -52; // QUEUE: The offset above the main panel (will often be negative) 
    1414const UNIT_PANEL_HEIGHT = 44; // QUEUE: The height needed for a row of buttons 
    1515 
     16// Barter constants 
     17const BARTER_RESOURCE_AMOUNT_TO_SELL = 100; 
     18const BARTER_BUNCH_MULTIPLIER = 5; 
     19const BARTER_RESOURCES = ["food", "wood", "stone", "metal"]; 
     20const BARTER_ACTIONS = ["Sell", "Buy"]; 
     21 
    1622// The number of currently visible buttons (used to optimise showing/hiding) 
    17 var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Training": 0, "Construction": 0, "Command": 0, "Stance": 0}; 
     23var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Barter": 0, "Training": 0, "Construction": 0, "Command": 0, "Stance": 0}; 
    1824 
    1925// Unit panels are panels with row(s) of buttons 
    20 var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Training", "Construction", "Research", "Stance", "Command"]; 
     26var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Barter", "Training", "Construction", "Research", "Stance", "Command"]; 
    2127 
     28// Indexes of resources to sell and buy on barter panel 
     29var g_barterSell = 0; 
     30var g_barterBuy = 1; 
     31 
    2232// Lay out a row of centered buttons (does not work inside a loop like the other function) 
    2333function layoutButtonRowCentered(rowNumber, guiName, startIndex, endIndex, width) 
    2434{ 
     
    108118    } 
    109119} 
    110120 
     121function selectBarterResourceToSell(resourceIndex) 
     122{ 
     123    g_barterSell = resourceIndex; 
     124    // g_barterBuy should be set to different value in case if it is the same as g_barterSell 
     125    // (it is no make sense to exchange resource to the same one). 
     126    // We change it cyclic to next value. 
     127    if (g_barterBuy == g_barterSell) 
     128        g_barterBuy = (g_barterBuy + 1) % BARTER_RESOURCES.length; 
     129} 
     130 
    111131// Sets up "unit panels" - the panels with rows of icons (Helper function for updateUnitDisplay) 
    112132function setupUnitPanel(guiName, usedPanels, unitEntState, items, callback) 
    113133{ 
    114134    usedPanels[guiName] = 1; 
     135 
     136    // Use separate logic for bartering panel 
     137    if (guiName == "Barter") 
     138    { 
     139        setupUnitBarterPanel(unitEntState); 
     140        return; 
     141    } 
     142 
    115143    var numberOfItems = items.length; 
    116144    var selection = g_Selection.toList(); 
    117145    var garrisonGroups = new EntityGroups(); 
     
    354382    g_unitPanelButtons[guiName] = numButtons; 
    355383} 
    356384 
     385// Sets up "unit barter panel" - special case for setupUnitPanel 
     386function setupUnitBarterPanel(unitEntState) 
     387{ 
     388    // Amount of player's resource to exchange 
     389    var amountToSell = BARTER_RESOURCE_AMOUNT_TO_SELL; 
     390    if (Engine.HotkeyIsPressed("session.massbarter")) 
     391        amountToSell *= BARTER_BUNCH_MULTIPLIER; 
     392    // One pass for each resource 
     393    for (var i = 0; i < BARTER_RESOURCES.length; i++) 
     394    { 
     395        var resource = BARTER_RESOURCES[i]; 
     396        // One pass for 'sell' row and another for 'buy' 
     397        for (var j = 0; j < BARTER_ACTIONS.length; j++) 
     398        { 
     399            var selectedResourceIndex = [g_barterSell, g_barterBuy][j]; 
     400            var action = BARTER_ACTIONS[j]; 
     401 
     402            var imageNameSuffix = (i == selectedResourceIndex) ? "selected" : "inactive"; 
     403            var icon = getGUIObjectByName("unitBarter" + action + "Icon["+i+"]"); 
     404 
     405            var button = getGUIObjectByName("unitBarter" + action + "Button["+i+"]"); 
     406            button.size = (i * 46) + " 0 " + ((i + 1) * 46) + " 46"; 
     407            var amountToBuy; 
     408            // In 'buy' row show black icon in place corresponding to selected resource in 'sell' row 
     409            if (j == 1 && i == g_barterSell) 
     410            { 
     411                button.enabled = false; 
     412                button.tooltip = ""; 
     413                icon.sprite = ""; 
     414                amountToBuy = ""; 
     415            } 
     416            else 
     417            { 
     418                button.enabled = true; 
     419                button.tooltip = action + " " + resource; 
     420                icon.sprite = "stretched:session/resources/" + resource + "_" + imageNameSuffix + ".png"; 
     421                var sellPrice = unitEntState.barterMarket.prices["sell"][BARTER_RESOURCES[g_barterSell]]; 
     422                var buyPrice = unitEntState.barterMarket.prices["buy"][resource]; 
     423                amountToBuy = "+" + Math.round(sellPrice / buyPrice * amountToSell); 
     424            } 
     425            var amount; 
     426            if (j == 0) 
     427            { 
     428                button.onpress = (function(e){ return function() { selectBarterResourceToSell(e); } })(i); 
     429                amount = (i == g_barterSell) ? "-" + amountToSell : ""; 
     430            } 
     431            else 
     432            { 
     433                button.onpress = (function(e){ return function() { g_barterBuy = e; } })(i); 
     434                amount = amountToBuy 
     435            } 
     436            getGUIObjectByName("unitBarter" + action + "Amount["+i+"]").caption = amount; 
     437        } 
     438    } 
     439    performDealButton = getGUIObjectByName("PerformDealButton"); 
     440    var exchangeResourcesParameters = { "sell": BARTER_RESOURCES[g_barterSell], "buy": BARTER_RESOURCES[g_barterBuy], "amount": amountToSell }; 
     441    performDealButton.onpress = (function(e){ return function() { exchangeResources(e) } })(exchangeResourcesParameters); 
     442} 
     443 
    357444// Updates right Unit Commands Panel - runs in the main session loop via updateSelectionDetails() 
    358445function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection) 
    359446{ 
     
    410497                function (item) { performStance(entState.id, item); } ); 
    411498        } 
    412499 
     500        getGUIObjectByName("unitBarterPanel").hidden = !entState.barterMarket; 
     501        if (entState.barterMarket) 
     502        { 
     503            setupUnitPanel("Barter", usedPanels, entState, [], null); 
     504        } 
     505 
    413506        if (entState.buildEntities && entState.buildEntities.length) 
    414507        { 
    415508            setupUnitPanel("Construction", usedPanels, entState, entState.buildEntities, startBuildingPlacement); 
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    323323        } 
    324324        break; 
    325325 
     326    case "barter": 
     327        var cmpBarter = Engine.QueryInterface(SYSTEM_ENTITY, IID_Barter); 
     328        cmpBarter.ExchangeResources(playerEnt, cmd.sell, cmd.buy, cmd.amount); 
     329        break; 
     330 
    326331    default: 
    327332        error("Ignoring unrecognised command type '" + cmd.type + "'"); 
    328333    } 
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    252252        }; 
    253253    } 
    254254 
     255    if (!cmpFoundation && cmpIdentity.HasClass("BarterMarket")) 
     256    { 
     257        var cmpBarter = Engine.QueryInterface(SYSTEM_ENTITY, IID_Barter); 
     258        ret.barterMarket = { "prices": cmpBarter.GetPrices() }; 
     259    } 
     260 
    255261    var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 
    256262    ret.visibility = cmpRangeManager.GetLosVisibility(ent, player); 
    257263 
  • binaries/data/mods/public/simulation/components/interfaces/Barter.js

     
     1Engine.RegisterInterface("Barter"); 
  • binaries/data/mods/public/simulation/components/Barter.js

     
     1// True price of 100 units of resource (for case if some resource is more worth). 
     2// With current bartering system only relative values makes sense 
     3// so if for example stone is two times more expensive than wood, 
     4// there will 2:1 exchange rate. 
     5const TRUE_PRICES = { "food": 100, "wood": 100, "stone": 100, "metal": 100 }; 
     6 
     7// Constant part of price difference between true price and buy/sell price. 
     8// In percents. 
     9// Buy price equal to true price plus constant difference. 
     10// Sell price equal to true price minus constant difference. 
     11const CONSTANT_DIFFERENCE = 10; 
     12 
     13// Additional difference of prices, added after each deal to specified resource price. 
     14// In percents. 
     15const DIFFERENCE_PER_DEAL = 5; 
     16 
     17// Price difference which restored each restore timer tick 
     18// In percents. 
     19const DIFFERENCE_RESTORE = 2; 
     20 
     21// Interval of timer which slowly restore prices after deals 
     22const RESTORE_TIMER_INTERVAL = 5000; 
     23 
     24// Array of resource names 
     25const RESOURCES = ["food", "wood", "stone", "metal"]; 
     26 
     27function Barter() {} 
     28 
     29Barter.prototype.Schema = 
     30    "<a:component type='system'/><empty/>"; 
     31 
     32Barter.prototype.Init = function() 
     33{ 
     34    this.priceDifferences = {}; 
     35    for each (var resource in RESOURCES) 
     36        this.priceDifferences[resource] = 0; 
     37    this.restoreTimer = undefined; 
     38}; 
     39 
     40Barter.prototype.GetPrices = function() 
     41{ 
     42    var prices = { "buy": {}, "sell": {} }; 
     43    for each (var resource in RESOURCES) 
     44    { 
     45        prices["buy"][resource] = TRUE_PRICES[resource] * (100 + CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100; 
     46        prices["sell"][resource] = TRUE_PRICES[resource] * (100 - CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100; 
     47    } 
     48    return prices; 
     49}; 
     50 
     51Barter.prototype.ExchangeResources = function(playerEntity, resourceToSell, resourceToBuy, amount) 
     52{ 
     53    var cmpPlayer = Engine.QueryInterface(playerEntity, IID_Player); 
     54 
     55    var prices = this.GetPrices(); 
     56 
     57    var amountsToSubtract = {}; 
     58    amountsToSubtract[resourceToSell] = amount; 
     59    if (cmpPlayer.TrySubtractResources(amountsToSubtract)) 
     60    { 
     61        var amountToAdd = Math.round(prices["sell"][resourceToSell] / prices["buy"][resourceToBuy] * amount); 
     62        cmpPlayer.AddResource(resourceToBuy, amountToAdd); 
     63        var numberOfDeals = Math.round(amount / 100); 
     64 
     65        // Increase price difference for both exchange resources. 
     66        // Overal price difference (constant + dynamic) can't exceed +-99% 
     67        // so both buy/sell prices limited to [1%; 199%] interval. 
     68        this.priceDifferences[resourceToSell] -= DIFFERENCE_PER_DEAL * numberOfDeals; 
     69        this.priceDifferences[resourceToSell] = Math.min(99-CONSTANT_DIFFERENCE, Math.max(CONSTANT_DIFFERENCE-99, this.priceDifferences[resourceToSell])); 
     70        this.priceDifferences[resourceToBuy] += DIFFERENCE_PER_DEAL * numberOfDeals; 
     71        this.priceDifferences[resourceToBuy] = Math.min(99-CONSTANT_DIFFERENCE, Math.max(CONSTANT_DIFFERENCE-99, this.priceDifferences[resourceToBuy])); 
     72    } 
     73 
     74    if (this.restoreTimer == undefined) 
     75    { 
     76        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 
     77        this.restoreTimer = cmpTimer.SetTimeout(this.entity, IID_Barter, "ProgressTimeout", RESTORE_TIMER_INTERVAL, {}); 
     78    } 
     79}; 
     80 
     81Barter.prototype.ProgressTimeout = function(data) 
     82{ 
     83    this.restoreTimer = undefined; 
     84 
     85    var needRestore = false; 
     86    for each (var resource in RESOURCES) 
     87    { 
     88        // Calculate value to restore, it should be limited to [-DIFFERENCE_RESTORE; DIFFERENCE_RESTORE] interval 
     89        var differenceRestore = Math.min(DIFFERENCE_RESTORE, Math.max(-DIFFERENCE_RESTORE, this.priceDifferences[resource])); 
     90        differenceRestore = -differenceRestore; 
     91        this.priceDifferences[resource] += differenceRestore; 
     92        // If price difference still exists then set flag to run timer again 
     93        if (this.priceDifferences[resource] != 0) 
     94            needRestore = true; 
     95    } 
     96 
     97    if (needRestore) 
     98    { 
     99        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 
     100        this.restoreTimer = cmpTimer.SetTimeout(this.entity, IID_Barter, "ProgressTimeout", RESTORE_TIMER_INTERVAL, data); 
     101    } 
     102} 
     103 
     104Engine.RegisterComponentType(IID_Barter, "Barter", Barter); 
     105 
  • binaries/data/mods/public/simulation/components/Identity.js

     
    8282                        "<value>CivCentre</value>" + 
    8383                        "<value>Economic</value>" + 
    8484                        "<value>Defensive</value>" + 
     85                        "<value>BarterMarket</value>" + 
    8586                        "<value>Village</value>" + 
    8687                        "<value>Town</value>" + 
    8788                        "<value>City</value>" + 
  • binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml

     
    2323  </Health> 
    2424  <Identity> 
    2525    <GenericName>Market</GenericName> 
    26     <Tooltip>Create Trade units and Barter resources. (Currently a useless structure)</Tooltip> 
    27     <Classes datatype="tokens">Town</Classes> 
     26    <Tooltip>Create Trade units and Barter resources.</Tooltip> 
     27    <Classes datatype="tokens">Town BarterMarket</Classes> 
    2828    <Icon>structures/market.png</Icon> 
    2929  </Identity> 
    3030  <Obstruction> 
  • binaries/data/config/default.cfg

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: binaries/data/mods/public/art/textures/ui/session/resources/food_selected.png
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: binaries/data/mods/public/art/textures/ui/session/resources/wood_selected.png
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: binaries/data/mods/public/art/textures/ui/session/resources/stone_selected.png
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: binaries/data/mods/public/art/textures/ui/session/resources/metal_inactive.png
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: binaries/data/mods/public/art/textures/ui/session/resources/food_inactive.png
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: binaries/data/mods/public/art/textures/ui/session/resources/wood_inactive.png
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: binaries/data/mods/public/art/textures/ui/session/resources/stone_inactive.png
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: binaries/data/mods/public/art/textures/ui/session/resources/metal_selected.png
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
     
    176176hotkey.session.garrison = Ctrl              ; Modifier to garrison when clicking on building 
    177177hotkey.session.queue = Shift                ; Modifier to queue unit orders instead of replacing 
    178178hotkey.session.batchtrain = Shift           ; Modifier to train units in batches 
     179hotkey.session.massbarter = Shift           ; Modifier to barter bunch of resources 
    179180hotkey.session.deselectgroup = Ctrl         ; Modifier to deselect units when clicking group icon, instead of selecting 
    180181hotkey.session.rotate.cw = RightBracket     ; Rotate building placement preview clockwise 
    181182hotkey.session.rotate.ccw = LeftBracket     ; Rotate building placement preview anticlockwise