Ticket #23: barter_2011_09_12_v2.diff

File barter_2011_09_12_v2.diff, 15.0 KB (added by fcxSanya, 13 years ago)
  • 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", "action": command.action, "resource": command.resource});
     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

     
    332332    {
    333333        layoutButtonRowCentered(0, guiName, 0, numButtons, COMMANDS_PANEL_WIDTH);
    334334    }
    335     else
     335    // exclude case when there is only barter buttons on training panel,
     336    // which is processed separatedly in addBarterButtonsToTrainingPanel function
     337    else if (!(guiName == "Training" && numButtons == 0))
    336338    {
    337339        for (var i = 0; i < numRows; i++)
    338340            layoutButtonRow(i, guiName, buttonSideLength, buttonSpacer, rowLength*i, rowLength*(i+1) );
     
    347349        panel.size = size;
    348350    }
    349351
    350     // Hide any buttons we're no longer using
    351     for (i = numButtons; i < g_unitPanelButtons[guiName]; ++i)
    352         getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true;
     352    if (guiName == "Training" && unitEntState.barterMarket)
     353    {
     354        addBarterButtonsToTrainingPanel(usedPanels, unitEntState, numButtons);
     355    }
     356    else
     357    {
     358        // Hide any buttons we're no longer using
     359        for (i = numButtons; i < g_unitPanelButtons[guiName]; ++i)
     360            getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true;
    353361
    354     g_unitPanelButtons[guiName] = numButtons;
     362        g_unitPanelButtons[guiName] = numButtons;
     363    }
    355364}
    356365
     366// add barter buttons to training panel to next row after last row with trainable units
     367function addBarterButtonsToTrainingPanel(usedPanels, unitEntState, newButtonsCount)
     368{
     369    var previousButtonsCount = g_unitPanelButtons["Training"];
     370    var rowLength = 8;
     371    // index of row where we are going to add barter buttons
     372    var rowIndex = 0;
     373    // if Training panel have some buttons, calculate row index
     374    // for barter buttons
     375    if (newButtonsCount > 0)
     376    {
     377        rowIndex = Math.ceil(newButtonsCount / rowLength);
     378    }
     379
     380    for (var i = 0; i < 6; i++)
     381    {
     382        var action = ["buy", "sell"][Math.floor(i/3)];
     383        var resource = ["food", "wood", "stone"][i%3];
     384
     385        var buttonIndex = i + rowLength*rowIndex;
     386
     387        var button = getGUIObjectByName("unitTrainingButton["+buttonIndex+"]");
     388        button.hidden = false;
     389        button.tooltip = action + " 100 " + resource + " for " + unitEntState.barterPrices[action][resource] + " metal";
     390        var command = { "action": action, "resource": resource };
     391        button.onpress = (function(e) { return function() { exchangeResources(e) } })(command);
     392       
     393        var icon = getGUIObjectByName("unitTrainingIcon["+buttonIndex+"]");
     394        icon.sprite = "stretched:session/actions/" + action + "_" + resource + ".png";
     395    }
     396
     397    var buttonSideLength = getGUIObjectByName("unitTrainingButton[0]").size.bottom;
     398    var buttonSpacer = buttonSideLength+1;
     399    layoutButtonRow(rowIndex, "Training", buttonSideLength, buttonSpacer, rowLength*rowIndex, rowLength*(rowIndex+1));
     400
     401    // Hide any buttons we're no longer using
     402    // hide buttons between last unit train button and first barter button
     403    for (i = newButtonsCount; i < rowIndex * rowLength; ++i)
     404        getGUIObjectByName("unitTrainingButton["+i+"]").hidden = true;
     405    // hide buttons after last barter button
     406    for (i = rowLength*rowIndex + 6; i < previousButtonsCount; ++i)
     407        getGUIObjectByName("unitTrainingButton["+i+"]").hidden = true;
     408    // update number of buttons, we suppose that all rows before one with barter buttons
     409    // are fully filled (indeed there can be some empty places) and barter buttons row
     410    // always have 6 buttons
     411    g_unitPanelButtons["Training"] = rowIndex * rowLength + 6;
     412}
     413
    357414// Updates right Unit Commands Panel - runs in the main session loop via updateSelectionDetails()
    358415function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection)
    359416{
     
    422479                function (trainEntType) { addToTrainingQueue(entState.id, trainEntType); } );
    423480//          isInvisible = false;
    424481        }
     482        else if (entState.barterMarket)
     483        {
     484            setupUnitPanel("Training", usedPanels, entState, [], null);
     485        }
    425486
    426487        if (entState.training && entState.training.queue.length)
    427488            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

     
    135135            "classes": cmpIdentity.GetClassesList(),
    136136            "selectionGroupName": cmpIdentity.GetSelectionGroupName()
    137137        };
     138
     139        if (cmpIdentity.GetClassesList().indexOf("BarterMarket") != -1)
     140        {
     141            ret.barterMarket = true;
     142            var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     143            var playerEntity = cmpPlayerManager.GetPlayerByID(player);
     144            var cmpPlayerBarter = Engine.QueryInterface(playerEntity, IID_PlayerBarter);
     145            ret.barterPrices = cmpPlayerBarter.GetPrices();
     146        }
    138147    }
    139148   
    140149    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": 200, "stone": 300 };
     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        // clamping into [-DIFFERENCE_RESTORE; DIFFERENCE_RESTORE] interval
     92        var differenceRestore = Math.min(DIFFERENCE_RESTORE, Math.max(-DIFFERENCE_RESTORE, this.priceDifferences[resource]));
     93        // change sign, because we need to restore price
     94        differenceRestore = -differenceRestore;
     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>