Ticket #23: barter_2011_08_30.diff

File barter_2011_08_30.diff, 15.6 KB (added by fcxSanya, 13 years ago)
  • binaries/data/mods/public/gui/session/input.js

     
    999999    inputState = INPUT_BUILDING_PLACEMENT;
    10001000}
    10011001
     1002// Called by GUI when user clicks exchange resources button
     1003function exchangeResources(command)
     1004{
     1005    Engine.PostNetworkCommand({"type": "barter", "action": command.action, "resource": command.resource});
     1006}
     1007
     1008
    10021009// Batch training:
    10031010// When the user shift-clicks, we set these variables and switch to INPUT_BATCHTRAINING
    10041011// 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

     
    119119    if (guiName == "Selection")
    120120    {
    121121        if (numberOfItems > 16)
    122                 numberOfItems = 16;
     122            numberOfItems = 16;
    123123    }
    124124    else if (guiName == "Formation")
    125125    {
    126126        if (numberOfItems > 16)
    127                 numberOfItems = 16;
     127            numberOfItems = 16;
    128128    }   
    129129    else if (guiName == "Stance")
    130130    {
    131131        if (numberOfItems > 5)
    132                 numberOfItems = 5;
     132            numberOfItems = 5;
    133133    }
    134134    else if (guiName == "Queue")
    135135    {
     
    150150    }
    151151    else if (numberOfItems > 24)
    152152    {
    153         numberOfItems =  24;
     153        numberOfItems = 24;
    154154    }
    155155
    156156    var i;
     
    321321    {
    322322        layoutButtonRowCentered(0, guiName, 0, numButtons, COMMANDS_PANEL_WIDTH);
    323323    }
    324     else
     324    // exclude case when there is only barter buttons on training panel,
     325    // which is processed separatedly in addBarterButtonsToTrainingPanel function
     326    else if (!(guiName == "Training" && numButtons == 0))
    325327    {
    326328        for (var i = 0; i < numRows; i++)
    327329            layoutButtonRow(i, guiName, buttonSideLength, buttonSpacer, rowLength*i, rowLength*(i+1) );
     
    336338        panel.size = size;
    337339    }
    338340
    339     // Hide any buttons we're no longer using
    340     for (i = numButtons; i < g_unitPanelButtons[guiName]; ++i)
    341         getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true;
     341    if (guiName == "Training" && unitEntState.barterMarket)
     342    {
     343        addBarterButtonsToTrainingPanel(usedPanels, unitEntState, numButtons);
     344    }
     345    else
     346    {
     347        // Hide any buttons we're no longer using
     348        for (i = numButtons; i < g_unitPanelButtons[guiName]; ++i)
     349            getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true;
    342350
    343     g_unitPanelButtons[guiName] = numButtons;
     351        g_unitPanelButtons[guiName] = numButtons;
     352    }
    344353}
    345354
     355// add barter buttons to training panel to next row after last row with trainable units
     356function addBarterButtonsToTrainingPanel(usedPanels, unitEntState, newButtonsCount)
     357{
     358    var previousButtonsCount = g_unitPanelButtons["Training"];
     359    var rowLength = 8;
     360    // index of row where we are going to add barter buttons
     361    var rowIndex = 0;
     362    // if Training panel have some buttons, calculate row index
     363    // for barter buttons
     364    if (newButtonsCount > 0)
     365    {
     366        rowIndex = Math.ceil(newButtonsCount / rowLength);
     367    }
     368
     369    for (var i = 0; i < 6; i++)
     370    {
     371        var action = ["buy", "sell"][Math.floor(i/3)];
     372        var resource = ["food", "wood", "stone"][i%3];
     373
     374        var buttonIndex = i + rowLength*rowIndex;
     375
     376        var button = getGUIObjectByName("unitTrainingButton["+buttonIndex+"]");
     377        button.hidden = false;
     378        button.tooltip = action + " 100 " + resource + " for " + unitEntState.barterPrices[action][resource] + " metal";
     379        var command = { "action": action, "resource": resource };
     380        button.onpress = (function(e) { return function() { exchangeResources(e) } })(command);
     381       
     382        var icon = getGUIObjectByName("unitTrainingIcon["+buttonIndex+"]");
     383        icon.sprite = "stretched:session/actions/" + action + "_" + resource + ".png";
     384    }
     385
     386    var buttonSideLength = getGUIObjectByName("unitTrainingButton[0]").size.bottom;
     387    var buttonSpacer = buttonSideLength+1;
     388    layoutButtonRow(rowIndex, "Training", buttonSideLength, buttonSpacer, rowLength*rowIndex, rowLength*(rowIndex+1));
     389
     390    // Hide any buttons we're no longer using
     391    // hide buttons between last unit train button and first barter button
     392    for (i = newButtonsCount; i < rowIndex * rowLength; ++i)
     393        getGUIObjectByName("unitTrainingButton["+i+"]").hidden = true;
     394    // hide buttons after last barter button
     395    for (i = rowLength*rowIndex + 6; i < previousButtonsCount; ++i)
     396        getGUIObjectByName("unitTrainingButton["+i+"]").hidden = true;
     397    // update number of buttons, we suppose that all rows before one with barter buttons
     398    // are fully filled (indeed there can be some empty places) and barter buttons row
     399    // always have 6 buttons
     400    g_unitPanelButtons["Training"] = rowIndex * rowLength + 6;
     401}
     402
    346403// Updates right Unit Commands Panel - runs in the main session loop via updateSelectionDetails()
    347404function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection)
    348405{
     
    411468                function (trainEntType) { addToTrainingQueue(entState.id, trainEntType); } );
    412469//          isInvisible = false;
    413470        }
     471        else if (entState.barterMarket)
     472        {
     473            setupUnitPanel("Training", usedPanels, entState, [], null);
     474        }
    414475
    415476        if (entState.training && entState.training.queue.length)
    416477            setupUnitPanel("Queue", usedPanels, entState, entState.training.queue,
  • binaries/data/mods/public/simulation/helpers/Commands.js

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

     
    132132            "classes": cmpIdentity.GetClassesList(),
    133133            "selectionGroupName": cmpIdentity.GetSelectionGroupName()
    134134        };
     135
     136        if (cmpIdentity.GetClassesList().indexOf("BarterMarket") != -1)
     137        {
     138            ret.barterMarket = true;
     139            var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     140            var playerEntity = cmpPlayerManager.GetPlayerByID(player);
     141            var cmpPlayerBarter = Engine.QueryInterface(playerEntity, IID_PlayerBarter);
     142            ret.barterPrices = cmpPlayerBarter.GetPrices();
     143        }
    135144    }
    136145   
    137146    var cmpPosition = Engine.QueryInterface(ent, IID_Position);
  • binaries/data/mods/public/simulation/components/interfaces/PlayerBarter.js

     
     1Engine.RegisterInterface("PlayerBarter");
  • 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/PlayerBarter.js

     
     1// true price of 100 resource in metal (for case if some resource is more worth)
     2const TRUE_PRICES = { "food": 100, "wood": 100, "stone": 100 };
     3
     4// constant part of price different between true price and buy/sell price
     5// in percents
     6// buy price equal to true price plus constant difference
     7// sell price equal to true price minus constant difference
     8const CONSTANT_DIFFERENCE = 25;
     9
     10// additional difference of prices, added after each deal to specified resource price
     11// in percents
     12const DIFFERENCE_PER_DEAL = 5;
     13
     14// price difference which restored each restore timer tick
     15// in percents
     16const DIFFERENCE_RESTORE = 2;
     17
     18// interval of timer which slowly restore prices after deals
     19const RESTORE_TIMER_INTERVAL = 5000;
     20
     21function PlayerBarter() {}
     22
     23PlayerBarter.prototype.Schema =
     24    "<a:component type='system'/><empty/>";
     25
     26PlayerBarter.prototype.Init = function()
     27{
     28    this.priceDifferences = {};
     29    for each (var resource in ["food", "wood", "stone"])
     30        this.priceDifferences[resource] = 0;
     31    this.restoreTimer = undefined;
     32};
     33
     34PlayerBarter.prototype.GetPrices = function()
     35{
     36    var prices = { "buy": {}, "sell": {} };
     37    for each (var resource in ["food", "wood", "stone"])
     38    {
     39        prices["buy"][resource] = Math.round(TRUE_PRICES[resource] * (100 + CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100);
     40        prices["sell"][resource] = Math.round(TRUE_PRICES[resource] * (100 - CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100);
     41    }
     42    return prices;
     43};
     44
     45PlayerBarter.prototype.ExchangeResources = function(action, resource)
     46{
     47    var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player);
     48    var amountsToSubtract = {
     49        "food": 0,
     50        "wood": 0,
     51        "stone": 0,
     52        "metal": 0
     53    };
     54    var prices = this.GetPrices();
     55    switch (action)
     56    {
     57    case "buy":
     58        amountsToSubtract["metal"] = prices["buy"][resource];
     59        if (cmpPlayer.TrySubtractResources(amountsToSubtract))
     60        {
     61            cmpPlayer.AddResource(resource, 100);
     62            if (this.priceDifferences[resource] + DIFFERENCE_PER_DEAL < 100 - CONSTANT_DIFFERENCE)
     63                this.priceDifferences[resource] += DIFFERENCE_PER_DEAL;
     64        }
     65        break;
     66    case "sell":
     67        amountsToSubtract[resource] = 100;
     68        if (cmpPlayer.TrySubtractResources(amountsToSubtract))
     69        {
     70            cmpPlayer.AddResource("metal", prices["sell"][resource]);
     71            if (this.priceDifferences[resource] - DIFFERENCE_PER_DEAL > CONSTANT_DIFFERENCE - 100)
     72                this.priceDifferences[resource] -= DIFFERENCE_PER_DEAL;
     73        }
     74        break;
     75    }
     76    if (this.restoreTimer == undefined)
     77    {
     78        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     79        this.restoreTimer = cmpTimer.SetTimeout(this.entity, IID_PlayerBarter, "ProgressTimeout", RESTORE_TIMER_INTERVAL, {});
     80    }
     81};
     82
     83PlayerBarter.prototype.ProgressTimeout = function(data)
     84{
     85    this.restoreTimer = undefined;
     86
     87    var needRestore = false;
     88    for each (var resource in ["food", "wood", "stone"])
     89    {
     90        // calculate value to restore, it should be:
     91        //  DIFFERENCE_RESTORE if this.priceDifferences[resource] < 0
     92        //  -DIFFERENCE_RESTORE if this.priceDifferences[resource] > 0
     93        //  this.priceDifferences[resource] if it's modulus less than DIFFERENCE_RESTORE
     94        var differenceRestore = -Math.min(DIFFERENCE_RESTORE, Math.max(-DIFFERENCE_RESTORE, this.priceDifferences[resource]));
     95        this.priceDifferences[resource] += differenceRestore;
     96        // if price difference still exists then set flag to run timer again
     97        if (this.priceDifferences[resource] != 0)
     98            needRestore = true;
     99    }
     100
     101    if (needRestore)
     102    {
     103        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     104        this.restoreTimer = cmpTimer.SetTimeout(this.entity, IID_PlayerBarter, "ProgressTimeout", RESTORE_TIMER_INTERVAL, data);
     105    }
     106}
     107
     108Engine.RegisterComponentType(IID_PlayerBarter, "PlayerBarter", PlayerBarter);
     109
  • binaries/data/mods/public/simulation/templates/special/player.xml

     
    99    </Limits>
    1010  </BuildLimits>
    1111  <Player/>
     12  <PlayerBarter/>
    1213  <StatisticsTracker/>
    1314</Entity>
  • 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>