Ticket #23: barter_2011_09_20_v2.diff

File barter_2011_09_20_v2.diff, 21.0 KB (added by fcxSanya, 13 years 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("GlobalBarter");
    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

     
    1414const UNIT_PANEL_HEIGHT = 44; // QUEUE: The height needed for a row of buttons
    1515
    1616// 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};
     17var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Barter": 0, "Training": 0, "Construction": 0, "Command": 0, "Stance": 0};
    1818
    1919// Unit panels are panels with row(s) of buttons
    20 var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Training", "Construction", "Research", "Stance", "Command"];
     20var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Barter", "Training", "Construction", "Research", "Stance", "Command"];
    2121
     22// Indexes of resources to sell and buy on barter panel
     23var g_barterSell = 0;
     24var g_barterBuy = 1;
     25
    2226// Lay out a row of centered buttons (does not work inside a loop like the other function)
    2327function layoutButtonRowCentered(rowNumber, guiName, startIndex, endIndex, width)
    2428{
     
    108112    }
    109113}
    110114
     115function selectBarterResourceToSell(resourceIndex)
     116{
     117    g_barterSell = resourceIndex;
     118    // barter to should be set to different value in case if it is the same
     119    // we change cyclic it to next value
     120    if (g_barterBuy == g_barterSell)
     121        g_barterBuy = (g_barterBuy + 5) % 4;
     122}
     123
    111124// Sets up "unit panels" - the panels with rows of icons (Helper function for updateUnitDisplay)
    112125function setupUnitPanel(guiName, usedPanels, unitEntState, items, callback)
    113126{
     
    323336    else if (guiName == "Formation" || guiName == "Garrison" || guiName == "Command")
    324337        rowLength = 4;
    325338
    326     var numRows = Math.ceil(numButtons / rowLength);
    327     var buttonSideLength = getGUIObjectByName("unit"+guiName+"Button[0]").size.bottom;
    328     var buttonSpacer = buttonSideLength+1;
     339    if (guiName == "Barter")
     340    {
     341        // amount of player's resource to exchange
     342        var amountToSell = Engine.HotkeyIsPressed("session.massbarter") ? 500 : 100;
     343        // for each resource
     344        for (var i = 0; i < 4; i++)
     345        {
     346            var resources = ["food", "wood", "stone", "metal"];
     347            var resource = resources[i%4];
     348            // one pass for 'sell' row and another for 'buy'
     349            for (var j = 0; j < 2; j++)
     350            {
     351                var selectedResourceIndex = [g_barterSell, g_barterBuy][j%2];
     352                var action = ["Sell", "Buy"][j%2];
    329353
    330     // Layout buttons
    331     if (guiName == "Command")
    332     {
    333         layoutButtonRowCentered(0, guiName, 0, numButtons, COMMANDS_PANEL_WIDTH);
     354                var button = getGUIObjectByName("unitBarter" + action + "Button["+i+"]");
     355
     356                button.size = (i * 46) + " 0 " + ((i + 1) * 46) + " 46";
     357                if (j == 0)
     358                    button.onpress = (function(e){ return function() { selectBarterResourceToSell(e); } })(i);
     359                else
     360                    button.onpress = (function(e){ return function() { g_barterBuy = e; } })(i);
     361
     362                var imageNameSuffix = (i == selectedResourceIndex) ? "selected" : "inactive";
     363                var icon = getGUIObjectByName("unitBarter" + action + "Icon["+i+"]");
     364
     365                getGUIObjectByName("unitBarterSellAmount["+i+"]").caption = (i == g_barterSell) ? "-" + amountToSell : "";
     366                var amountToBuy;
     367                // in 'buy' row show black icon in place corresponding to selected resource in 'sell' row
     368                if (j == 1 && i == g_barterSell)
     369                {
     370                    button.enabled = false;
     371                    button.tooltip = "";
     372                    icon.sprite = "";
     373                    amountToBuy = "";
     374                }
     375                else
     376                {
     377                    button.enabled = true;
     378                    button.tooltip = action + " " + resource;
     379                    icon.sprite = "stretched:session/resources/" + resource + "_" + imageNameSuffix + ".png";
     380                    amountToBuy = "+" + Math.round(unitEntState.barterPrices["sell"][resources[g_barterSell]] / unitEntState.barterPrices["buy"][resource] * amountToSell);
     381                }
     382                getGUIObjectByName("unitBarterBuyAmount["+i+"]").caption = amountToBuy;
     383            }
     384
     385            performDealButton = getGUIObjectByName("PerformDealButton");
     386            performDealButton.onpress = (function(e){ return function() { exchangeResources(e) } })({"sell": resources[g_barterSell], "buy": resources[g_barterBuy], "amount": amountToSell});
     387        }
    334388    }
    335389    else
    336390    {
    337         for (var i = 0; i < numRows; i++)
    338             layoutButtonRow(i, guiName, buttonSideLength, buttonSpacer, rowLength*i, rowLength*(i+1) );
    339     }
     391        var numRows = Math.ceil(numButtons / rowLength);
     392        var buttonSideLength = getGUIObjectByName("unit"+guiName+"Button[0]").size.bottom;
     393        var buttonSpacer = buttonSideLength+1;
    340394
    341     // Resize Queue panel if needed
    342     if (guiName == "Queue") // or garrison
    343     {
    344         var panel = getGUIObjectByName("unitQueuePanel");
    345         var size = panel.size;
    346         size.top = (UNIT_PANEL_BASE - ((numRows-1)*UNIT_PANEL_HEIGHT));
    347         panel.size = size;
     395        // Layout buttons
     396        if (guiName == "Command")
     397        {
     398            layoutButtonRowCentered(0, guiName, 0, numButtons, COMMANDS_PANEL_WIDTH);
     399        }
     400        else
     401        {
     402            for (var i = 0; i < numRows; i++)
     403                layoutButtonRow(i, guiName, buttonSideLength, buttonSpacer, rowLength*i, rowLength*(i+1) );
     404        }
     405
     406        // Resize Queue panel if needed
     407        if (guiName == "Queue") // or garrison
     408        {
     409            var panel = getGUIObjectByName("unitQueuePanel");
     410            var size = panel.size;
     411            size.top = (UNIT_PANEL_BASE - ((numRows-1)*UNIT_PANEL_HEIGHT));
     412            panel.size = size;
     413        }
    348414    }
    349 
    350415    // Hide any buttons we're no longer using
    351416    for (i = numButtons; i < g_unitPanelButtons[guiName]; ++i)
    352417        getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true;
     
    410475                function (item) { performStance(entState.id, item); } );
    411476        }
    412477
     478        getGUIObjectByName("unitBarterPanel").hidden = !entState.barterMarket;
     479        if (entState.barterMarket)
     480        {
     481            setupUnitPanel("Barter", usedPanels, entState, [], null);
     482        }
     483
    413484        if (entState.buildEntities && entState.buildEntities.length)
    414485        {
    415486            setupUnitPanel("Construction", usedPanels, entState, entState.buildEntities, startBuildingPlacement);
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    319319        }
    320320        break;
    321321
     322    case "barter":
     323        var cmpGlobalBarter = Engine.QueryInterface(SYSTEM_ENTITY, IID_GlobalBarter);
     324        cmpGlobalBarter.ExchangeResources(playerEnt, cmd.sell, cmd.buy, cmd.amount);
     325        break;
     326
    322327    default:
    323328        error("Ignoring unrecognised command type '" + cmd.type + "'");
    324329    }
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    135135            "classes": cmpIdentity.GetClassesList(),
    136136            "selectionGroupName": cmpIdentity.GetSelectionGroupName()
    137137        };
     138
     139        if (cmpIdentity.GetClassesList().indexOf("BarterMarket") != -1)
     140        {
     141            ret.barterMarket = true;
     142            var cmpGlobalBarter = Engine.QueryInterface(SYSTEM_ENTITY, IID_GlobalBarter);
     143            ret.barterPrices = cmpGlobalBarter.GetPrices();
     144        }
    138145    }
    139146   
    140147    var cmpPosition = Engine.QueryInterface(ent, IID_Position);
  • binaries/data/mods/public/simulation/components/interfaces/GlobalBarter.js

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

     
    8181                        "<value>Civic</value>" +
    8282                        "<value>CivCentre</value>" +
    8383                        "<value>Economic</value>" +
     84                        "<value>BarterMarket</value>" +
    8485                        "<value>Defensive</value>" +
    8586                        "<value>Village</value>" +
    8687                        "<value>Town</value>" +
  • binaries/data/mods/public/simulation/components/GlobalBarter.js

     
     1// true price of 100 units of resource (for case if some resource is more worth)
     2// with current bartering system only relarive 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
     24function GlobalBarter() {}
     25
     26GlobalBarter.prototype.Schema =
     27    "<a:component type='system'/><empty/>";
     28
     29GlobalBarter.prototype.Init = function()
     30{
     31    this.priceDifferences = {};
     32    for each (var resource in ["food", "wood", "stone", "metal"])
     33        this.priceDifferences[resource] = 0;
     34    this.restoreTimer = undefined;
     35};
     36
     37GlobalBarter.prototype.GetPrices = function()
     38{
     39    var prices = { "buy": {}, "sell": {} };
     40    for each (var resource in ["food", "wood", "stone", "metal"])
     41    {
     42        prices["buy"][resource] = TRUE_PRICES[resource] * (100 + CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100;
     43        prices["sell"][resource] = TRUE_PRICES[resource] * (100 - CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100;
     44    }
     45    return prices;
     46};
     47
     48GlobalBarter.prototype.ExchangeResources = function(playerEntity, resourceToSell, resourceToBuy, amount)
     49{
     50    var cmpPlayer = Engine.QueryInterface(playerEntity, IID_Player);
     51    var amountsToSubtract = {
     52        "food": 0,
     53        "wood": 0,
     54        "stone": 0,
     55        "metal": 0
     56    };
     57   
     58    var prices = this.GetPrices();
     59
     60    amountsToSubtract[resourceToSell] = amount;
     61    if (cmpPlayer.TrySubtractResources(amountsToSubtract))
     62    {
     63        var amountToAdd = Math.round(prices["sell"][resourceToSell] / prices["buy"][resourceToBuy] * amount);
     64        cmpPlayer.AddResource(resourceToBuy, amountToAdd);
     65        var numberOfDeals = Math.round(amount / 100);
     66
     67        // increase price difference for both exchange resources
     68        // overal price difference (constant + dynamic) can exceed +-99%
     69        // so both buy/sell prices limited to [1%; 199%] interval
     70        this.priceDifferences[resourceToSell] -= DIFFERENCE_PER_DEAL * numberOfDeals;
     71        this.priceDifferences[resourceToSell] = Math.min(99-CONSTANT_DIFFERENCE, Math.max(CONSTANT_DIFFERENCE-99, this.priceDifferences[resourceToSell]));
     72        this.priceDifferences[resourceToBuy] += DIFFERENCE_PER_DEAL * numberOfDeals;
     73        this.priceDifferences[resourceToBuy] = Math.min(99-CONSTANT_DIFFERENCE, Math.max(CONSTANT_DIFFERENCE-99, this.priceDifferences[resourceToBuy]));
     74    }
     75
     76    if (this.restoreTimer == undefined)
     77    {
     78        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     79        this.restoreTimer = cmpTimer.SetTimeout(this.entity, IID_GlobalBarter, "ProgressTimeout", RESTORE_TIMER_INTERVAL, {});
     80    }
     81};
     82
     83GlobalBarter.prototype.ProgressTimeout = function(data)
     84{
     85    this.restoreTimer = undefined;
     86
     87    var needRestore = false;
     88    for each (var resource in ["food", "wood", "stone", "metal"])
     89    {
     90        // calculate value to restore, it should be limited to [-DIFFERENCE_RESTORE; DIFFERENCE_RESTORE] interval
     91        var differenceRestore = Math.min(DIFFERENCE_RESTORE, Math.max(-DIFFERENCE_RESTORE, this.priceDifferences[resource]));
     92        differenceRestore = -differenceRestore;
     93        this.priceDifferences[resource] += differenceRestore;
     94        // if price difference still exists then set flag to run timer again
     95        if (this.priceDifferences[resource] != 0)
     96            needRestore = true;
     97    }
     98
     99    if (needRestore)
     100    {
     101        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     102        this.restoreTimer = cmpTimer.SetTimeout(this.entity, IID_GlobalBarter, "ProgressTimeout", RESTORE_TIMER_INTERVAL, data);
     103    }
     104}
     105
     106Engine.RegisterComponentType(IID_GlobalBarter, "GlobalBarter", GlobalBarter);
     107
  • 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/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/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/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/metal_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_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
    
     
    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