Ticket #23: barter_2011_10_17.diff

File barter_2011_10_17.diff, 20.3 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("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