Ticket #23: barter_2011_08_30.diff

File barter_2011_08_30.diff, 15.6 KB (added by fcxSanya, 21 months 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>