Ticket #1432: one_hero_2012_10_02_v4.diff

File one_hero_2012_10_02_v4.diff, 55.6 KB (added by fcxSanya, 12 years ago)

Current WIP version

  • binaries/data/mods/public/gui/session/input.js

     
    14701470
    14711471function flushTrainingBatch()
    14721472{
    1473     Engine.PostNetworkCommand({"type": "train", "entities": batchTrainingEntities, "template": batchTrainingType, "count": batchTrainingCount});
     1473    var appropriateBuildings = getBuidlingsWhichCanTrainEntity(batchTrainingEntities, batchTrainingType);
     1474    // If training limits don't allow us to train batchTrainingCount in each appropriate building
     1475    if (batchTrainingEntityAllowedCount !== undefined && batchTrainingEntityAllowedCount < batchTrainingCount * appropriateBuildings.length)
     1476    {
     1477        // Train as many full batches as we can
     1478        var buildingsCountToTrainFullBatch = Math.floor(batchTrainingEntityAllowedCount / batchTrainingCount);
     1479        var buildingsToTrainFullBatch = appropriateBuildings.slice(0, buildingsCountToTrainFullBatch);
     1480        Engine.PostNetworkCommand({"type": "train", "entities": buildingsToTrainFullBatch, "template": batchTrainingType, "count": batchTrainingCount});
     1481
     1482        // Train remainer in one more building
     1483        var remainderToTrain = batchTrainingEntityAllowedCount % batchTrainingCount;
     1484        Engine.PostNetworkCommand({"type": "train", "entities": [ appropriateBuildings[buildingsCountToTrainFullBatch] ], "template": batchTrainingType, "count": remainderToTrain});
     1485    }
     1486    else
     1487    {
     1488        Engine.PostNetworkCommand({"type": "train", "entities": appropriateBuildings, "template": batchTrainingType, "count": batchTrainingCount});
     1489    }
    14741490}
    14751491
     1492
     1493
     1494
     1495
     1496
     1497
     1498
     1499
     1500
     1501
     1502
     1503
     1504
     1505
     1506
     1507
     1508
     1509
     1510
     1511
     1512
     1513
     1514
     1515
     1516
     1517
     1518
    14761519// Called by GUI when user clicks training button
    1477 function addTrainingToQueue(selection, trainEntType)
     1520function addTrainingToQueue(selection, trainEntType)
    14781521{
    1479     if (Engine.HotkeyIsPressed("session.batchtrain"))
     1522    // Create list of buildings which can train trainEntType
     1523    var appropriateBuildings = getBuidlingsWhichCanTrainEntity(selection, trainEntType);
     1524
     1525    // Check trainEntType entity limit and count
     1526    var [trainEntLimit, trainEntCount, canBeTrainedCount] = getEntityLimitAndCount(playerState, trainEntType)
     1527
     1528    // Batch training possible if we can train at least 2 units
     1529    var batchTrainingPossible = canBeTrainedCount !== undefined && canBeTrainedCount > 1;
     1530
     1531    if (Engine.HotkeyIsPressed("session.batchtrain") && batchTrainingPossible)
    14801532    {
    14811533        if (inputState == INPUT_BATCHTRAINING)
    14821534        {
     
    14931545                }
    14941546            }
    14951547            // If we're already creating a batch of this unit (in the same building(s)), then just extend it
     1548
    14961549            if (sameEnts && batchTrainingType == trainEntType)
    14971550            {
    1498                 batchTrainingCount += batchIncrementSize;
     1551                if (canBeTrainedCount !== undefined && canBeTrainedCount > batchTrainingCount * appropriateBuildings.length)
     1552                    batchTrainingCount += batchIncrementSize;
     1553                batchTrainingEntityAllowedCount = canBeTrainedCount;
    14991554                return;
    15001555            }
    15011556            // Otherwise start a new one
     
    15081563        inputState = INPUT_BATCHTRAINING;
    15091564        batchTrainingEntities = selection;
    15101565        batchTrainingType = trainEntType;
     1566
    15111567        batchTrainingCount = batchIncrementSize;
    15121568    }
    15131569    else
    15141570    {
    1515         // Non-batched - just create a single entity
    1516         Engine.PostNetworkCommand({"type": "train", "template": trainEntType, "count": 1, "entities": selection});
     1571        // Non-batched - just create a single entity in each building
     1572        // (but no more than entity limit allows)
     1573        var buildingsForTraining = appropriateBuildings;
     1574        if (trainEntLimit)
     1575            buildingsForTraining = buildingsForTraining.slice(0, canBeTrainedCount);
     1576        Engine.PostNetworkCommand({"type": "train", "template": trainEntType, "count": 1, "entities": buildingsForTraining});
    15171577    }
    15181578}
    15191579
     
    15251585
    15261586// Returns the number of units that will be present in a batch if the user clicks
    15271587// the training button with shift down
    1528 function getTrainingBatchStatus(entity, trainEntType)
     1588function getTrainingBatchStatus()
    15291589{
     1590
     1591
     1592
     1593
    15301594    if (inputState == INPUT_BATCHTRAINING && batchTrainingEntities.indexOf(entity) != -1 && batchTrainingType == trainEntType)
    1531         return [batchTrainingCount, batchIncrementSize];
     1595    {
     1596        nextBatchTrainingCount = batchTrainingCount;
     1597        var canBeTrainedCount = batchTrainingEntityAllowedCount;
     1598    }
    15321599    else
    1533         return [0, batchIncrementSize];
     1600    {
     1601        var [trainEntLimit, trainEntCount, canBeTrainedCount] = getEntityLimitAndCount(playerState, trainEntType);
     1602        var batchSize = Math.min(canBeTrainedCount, batchIncrementSize);
     1603    }
     1604    // We need to calculate count after the next increment if it's possible
     1605    if (canBeTrainedCount == undefined || canBeTrainedCount > nextBatchTrainingCount * appropriateBuildings.length)
     1606        nextBatchTrainingCount += batchIncrementSize;
     1607    // If training limits don't allow us to train batchTrainingCount in each appropriate building
     1608    // train as many full batches as we can and remainer in one more building.
     1609    var buildingsCountToTrainFullBatch = appropriateBuildings.length;
     1610    var remainderToTrain = 0;
     1611    if (canBeTrainedCount !== undefined && canBeTrainedCount < nextBatchTrainingCount * appropriateBuildings.length)
     1612    {
     1613        buildingsCountToTrainFullBatch = Math.floor(canBeTrainedCount / nextBatchTrainingCount);
     1614        remainderToTrain = batchTrainingEntityAllowedCount % nextBatchTrainingCount;
     1615    }
     1616    return [buildingsCountToTrainFullBatch, nextBatchTrainingCount, remainderToTrain];
    15341617}
    15351618
    15361619// Called by GUI when user clicks production queue item
  • binaries/data/mods/public/gui/session/unit_commands.js

     
    150150 * @param items Panel-specific data to construct the icons with.
    151151 * @param callback Callback function to argument to execute when an item's icon gets clicked. Takes a single 'item' argument.
    152152 */
    153 function setupUnitPanel(guiName, usedPanels, unitEntState, items, callback)
     153function setupUnitPanel(guiName, usedPanels, unitEntState, items, callback)
    154154{
    155155    usedPanels[guiName] = 1;
    156156
     
    347347            case GATE:
    348348                var tooltip = item.tooltip;
    349349                if (item.template)
    350                 {
     350                {
    351351                    var template = GetTemplateData(item.template);
    352                     tooltip += "\n" + getEntityCostTooltip(template);
    353 
    354                     var affordableMask = getGUIObjectByName("unitGateUnaffordable["+i+"]");
     352                    tooltip += "\n" + getEntityCostTooltip(template);
     353
     354                    var affordableMask = getGUIObjectByName("unitGateUnaffordable["+i+"]");
    355355                    affordableMask.hidden = true;
    356 
    357                     var neededResources = Engine.GuiInterfaceCall("GetNeededResources", template.cost);
    358                     if (neededResources)
    359                     {
    360                         affordableMask.hidden = false;
    361                         tooltip += getNeededResourcesTooltip(neededResources);
    362                     }
    363                 }
     356
     357                    var neededResources = Engine.GuiInterfaceCall("GetNeededResources", template.cost);
     358                    if (neededResources)
     359                    {
     360                        affordableMask.hidden = false;
     361                        tooltip += getNeededResourcesTooltip(neededResources);
     362                    }
     363                }
    364364                break;
    365365
    366366            case STANCE:
     
    374374                if (template.tooltip)
    375375                    tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]";
    376376
    377                 var [batchSize, batchIncrement] = getTrainingBatchStatus(unitEntState.id, entType);
    378                 var trainNum = batchSize ? batchSize+batchIncrement : batchIncrement;
     377                var [b);
     378                var t;
    379379
    380380                tooltip += "\n" + getEntityCostTooltip(template);
    381381
     
    388388                if (template.speed)
    389389                    tooltip += "\n" + getEntitySpeed(template);
    390390
    391                 tooltip += "\n\n[font=\"serif-bold-13\"]Shift-click[/font][font=\"serif-13\"] to train " + trainNum + ".[/font]";
    392 
     391                if (totalBatchTrainingCount > 0)
     392                {
     393                    var fullBatchesString = buildingsCountToTrainFullBatch * fullBatchSize > 0 ? buildingsCountToTrainFullBatch + "*" + fullBatchSize : "";
     394                    var remainderBatchString = remainderBatch > 0 ? remainderBatch : "";
     395                    var batchDetailsString = buildingsCountToTrainFullBatch > 1 || (buildingsCountToTrainFullBatch == 1 && remainderBatch > 0) ?
     396                        " (" + [fullBatchesString, remainderBatchString].filter(function(string) { return string != "" }).join(" + ") + ")" :
     397                        "";
     398                    tooltip += "\n\n[font=\"serif-bold-13\"]Shift-click[/font][font=\"serif-13\"] to train "
     399                        + totalBatchTrainingCount + batchDetailsString + ".[/font]";
     400                }
    393401                break;
    394402               
    395403            case RESEARCH:
     
    444452        // Button
    445453        var button = getGUIObjectByName("unit"+guiName+"Button["+i+"]");
    446454        var button1 = getGUIObjectByName("unit"+guiName+"Button["+(i+rowLength)+"]");
    447         var affordableMask = getGUIObjectByName("unit"+guiName+"Unaffordable["+i+"]");
    448         var affordableMask1 = getGUIObjectByName("unit"+guiName+"Unaffordable["+(i+rowLength)+"]");
     455        var affordableMask = getGUIObjectByName("unit"+guiName+"Unaffordable["+i+"]");
     456        var affordableMask1 = getGUIObjectByName("unit"+guiName+"Unaffordable["+(i+rowLength)+"]");
    449457        var icon = getGUIObjectByName("unit"+guiName+"Icon["+i+"]");
    450458        var selection = getGUIObjectByName("unit"+guiName+"Selection["+i+"]");
    451459        var pair = getGUIObjectByName("unit"+guiName+"Pair["+i+"]");
     
    540548        {
    541549            icon.sprite = "stretched:session/icons/" + item.icon;
    542550        }
     551
     552
     553
     554
     555
     556
     557
     558
     559
     560
     561
     562
     563
    543564        else if (guiName == GATE)
    544565        {
    545566            var gateIcon;
     
    583604           
    584605            if (guiName == RESEARCH)
    585606            {
    586                 // Check resource requirements for first button
    587                 affordableMask.hidden = true;
    588                 var neededResources = Engine.GuiInterfaceCall("GetNeededResources", template.cost);
    589                 if (neededResources)
    590                 {
    591                     if (button.enabled !== false)
    592                     {
    593                         button.enabled = false;
    594                         affordableMask.hidden = false;
    595                     }
    596                     button.tooltip += getNeededResourcesTooltip(neededResources);
    597                 }
    598 
     607                // Check resource requirements for first button
     608                affordableMask.hidden = true;
     609                var neededResources = Engine.GuiInterfaceCall("GetNeededResources", template.cost);
     610                if (neededResources)
     611                {
     612                    if (button.enabled !== false)
     613                    {
     614                        button.enabled = false;
     615                        affordableMask.hidden = false;
     616                    }
     617                    button.tooltip += getNeededResourcesTooltip(neededResources);
     618                }
     619
    599620                if (item.pair)
    600621                {
    601622                    grayscale = "";
    602623                    button1.enabled = true;
    603 
    604                     if (!Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType1))
     624
     625                    if (!Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType1))
    605626                    {
    606627                        button1.enabled = false;
    607628                        button1.tooltip += "\n" + GetTechnologyData(entType1).requirementsTooltip;
    608629                        grayscale = "grayscale:";
    609630                    }
    610631                    icon1.sprite = "stretched:" + grayscale + "session/portraits/" +template1.icon;
    611 
    612                     // Check resource requirements for second button
    613                     affordableMask1.hidden = true;
    614                     neededResources = Engine.GuiInterfaceCall("GetNeededResources", template.cost);
    615                     if (neededResources)
    616                     {
    617                         if (button1.enabled !== false)
    618                         {
    619                             button1.enabled = false;
    620                             affordableMask1.hidden = false;
    621                         }
    622                         button1.tooltip += getNeededResourcesTooltip(neededResources);
    623                     }
     632
     633                    // Check resource requirements for second button
     634                    affordableMask1.hidden = true;
     635                    neededResources = Engine.GuiInterfaceCall("GetNeededResources", template.cost);
     636                    if (neededResources)
     637                    {
     638                        if (button1.enabled !== false)
     639                        {
     640                            button1.enabled = false;
     641                            affordableMask1.hidden = false;
     642                        }
     643                        button1.tooltip += getNeededResourcesTooltip(neededResources);
     644                    }
    624645                }
    625646                else
    626647                {
    627648                    pair.hidden = true;
    628649                    button1.hidden = true;
    629                     affordableMask1.hidden = true;
    630                 }
    631             }
    632             else if (guiName == CONSTRUCTION || guiName == TRAINING)
    633             {
    634                 affordableMask.hidden = true;
    635                 var totalCosts = {};
    636                 var trainNum = 1;
    637                 if (Engine.HotkeyIsPressed("session.batchtrain") && guiName == TRAINING)
    638                 {
    639                     var [batchSize, batchIncrement] = getTrainingBatchStatus(unitEntState.id, entType);
    640                     trainNum = batchSize + batchIncrement;
     650                    affordableMask1.hidden = true;
     651                }
     652            }
     653            else if (guiName == CONSTRUCTION || guiName == TRAINING)
     654            {
     655                affordableMask.hidden = true;
     656                var totalCosts = {};
     657                var trainNum = 1;
     658                if (Engine.HotkeyIsPressed("session.batchtrain") && guiName == TRAINING)
     659                {
     660                    var [b);
     661                    trainNum = b;
    641662                }
    642 
    643                 // Walls have no cost defined.
     663
     664                // Walls have no cost defined.
    644665                if (template.cost !== undefined)
    645666                    for (var r in template.cost)
    646667                        totalCosts[r] = Math.floor(template.cost[r] * trainNum);
    647 
    648                 var neededResources = Engine.GuiInterfaceCall("GetNeededResources", totalCosts);
    649                 if (neededResources)
     668
     669                var neededResources = Engine.GuiInterfaceCall("GetNeededResources", totalCosts);
     670                if (neededResources)
    650671                {
    651                     var totalCost = 0;
    652                     if (button.enabled !== false)
     672                    var totalCost = 0;
     673                    if (button.enabled !== false)
    653674                    {
    654675                        for each (var resource in neededResources)
    655676                            totalCost += resource;
    656 
    657                         button.enabled = false;
    658                         affordableMask.hidden = false;
    659                         var alpha = 75 + totalCost/6;
    660                         alpha = alpha > 150 ? 150 : alpha;
    661                         affordableMask.sprite = "colour: 255 0 0 " + (alpha);
    662                     }
    663                     button.tooltip += getNeededResourcesTooltip(neededResources);
    664                 }
     677
     678                        button.enabled = false;
     679                        affordableMask.hidden = false;
     680                        var alpha = 75 + totalCost/6;
     681                        alpha = alpha > 150 ? 150 : alpha;
     682                        affordableMask.sprite = "colour: 255 0 0 " + (alpha);
     683                    }
     684                    button.tooltip += getNeededResourcesTooltip(neededResources);
     685                }
    665686            }
    666687        }
    667688        else
     
    767788}
    768789
    769790// Sets up "unit barter panel" - special case for setupUnitPanel
    770 function setupUnitBarterPanel(unitEntState)
     791function setupUnitBarterPanel(unitEntState)
    771792{
    772793    // Amount of player's resource to exchange
    773794    var amountToSell = BARTER_RESOURCE_AMOUNT_TO_SELL;
     
    862883    var player = Engine.GetPlayerID();
    863884    if (entState.player == player || g_DevSettings.controlAll)
    864885    {
     886
     887
     888
     889
     890
    865891        if (selection.length > 1)
    866             setupUnitPanel(SELECTION, usedPanels, entState, g_Selection.groups.getTemplateNames(),
     892            setupUnitPanel(SELECTION, usedPanels, entState, g_Selection.groups.getTemplateNames(),
    867893                function (entType) { changePrimarySelectionGroup(entType); } );
    868894
    869895        var commands = getEntityCommandsList(entState);
    870896        if (commands.length)
    871             setupUnitPanel(COMMAND, usedPanels, entState, commands,
     897            setupUnitPanel(COMMAND, usedPanels, entState, commands,
    872898                function (item) { performCommand(entState.id, item.name); } );
    873899
    874900        if (entState.garrisonHolder)
     
    881907                    groups.add(state.garrisonHolder.entities)
    882908            }
    883909
    884             setupUnitPanel(GARRISON, usedPanels, entState, groups.getTemplateNames(),
     910            setupUnitPanel(GARRISON, usedPanels, entState, groups.getTemplateNames(),
    885911                function (item) { unloadTemplate(item); } );
    886912        }
    887913
    888914        var formations = Engine.GuiInterfaceCall("GetAvailableFormations");
    889915        if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && !entState.garrisonHolder && formations.length)
    890916        {
    891             setupUnitPanel(FORMATION, usedPanels, entState, formations,
     917            setupUnitPanel(FORMATION, usedPanels, entState, formations,
    892918                function (item) { performFormation(entState.id, item); } );
    893919        }
    894920
     
    897923        var stances = ["violent", "aggressive", "passive", "defensive", "standground"];
    898924        if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && stances.length)
    899925        {
    900             setupUnitPanel(STANCE, usedPanels, entState, stances,
     926            setupUnitPanel(STANCE, usedPanels, entState, stances,
    901927                function (item) { performStance(entState.id, item); } );
    902928        }
    903929
     
    905931        if (entState.barterMarket)
    906932        {
    907933            usedPanels["Barter"] = 1;
    908             setupUnitBarterPanel(entState);
     934            setupUnitBarterPanel(entState);
    909935        }
    910936
    911937        var buildableEnts = [];
     
    929955
    930956        // The first selected entity's type has priority.
    931957        if (entState.buildEntities)
    932             setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement);
     958            setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement);
    933959        else if (entState.production && entState.production.entities)
    934             setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts,
    935                 function (trainEntType) { addTrainingToQueue(selection, trainEntType); } );
     960            setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts,
     961                function (trainEntType) { addTrainingToQueue(selection, trainEntType); } );
    936962        else if (entState.trader)
    937963            setupUnitTradingPanel(usedPanels, entState, selection);
    938964        else if (!entState.foundation && entState.gate || hasClass(entState, "LongWall"))
     
    9941020                setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement);
    9951021            else if (trainableEnts.length)
    9961022                setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts,
    997                     function (trainEntType) { addTrainingToQueue(selection, trainEntType); } );
     1023                    function (trainEntType) { addTrainingToQueue(selection, trainEntType); } );
    9981024        }
    9991025
    10001026        // Show technologies if the active panel has at most one row of icons.
     
    10071033        }
    10081034
    10091035        if (entState.production && entState.production.queue.length)
    1010             setupUnitPanel(QUEUE, usedPanels, entState, entState.production.queue,
     1036            setupUnitPanel(QUEUE, usedPanels, entState, entState.production.queue,
    10111037                function (item) { removeFromProductionQueue(entState.id, item.id); } );
    10121038       
    10131039        supplementalDetailsPanel.hidden = false;
  • binaries/data/mods/public/simulation/ai/jubot/gamestate.js

     
    416416     * Returns player build limits
    417417     * an object where each key is a category corresponding to a build limit for the player.
    418418     */
    419     getBuildLimits: function()
     419    getLimits: function()
    420420    {
    421         return this.playerData.buildLimits;
     421        return this.playerData.Limits;
    422422    },
    423423   
    424424    /**
    425425     * Returns player build counts
    426426     * an object where each key is a category corresponding to the current building count for the player.
    427427     */
    428     getBuildCounts: function()
     428    getCounts: function()
    429429    {
    430         return this.playerData.buildCounts;
     430        return this.playerData.Counts;
    431431    },
    432432   
    433433    /**
    434434     * Checks if the player's build limit has been reached for the given category.
    435435     * The category comes from the entity tenplate, specifically the BuildRestrictions component.
    436436     */
    437     isBuildLimitReached: function(category)
     437    isLimitReached: function(category)
    438438    {
    439         if (this.playerData.buildLimits[category] === undefined || this.playerData.buildCounts[category] === undefined)
     439        if (this.playerData.Counts[category] === undefined)
    440440            return false;
    441441       
    442442        // There's a special case of build limits per civ centre, so check that first
    443         if (this.playerData.buildLimits[category].LimitPerCivCentre !== undefined)
    444             return (this.playerData.buildCounts[category] >= this.playerData.buildCounts["CivilCentre"]*this.playerData.buildLimits[category].LimitPerCivCentre);
     443        if (this.playerData.Limits[category].LimitPerCivCentre !== undefined)
     444            return (this.playerData.Limits[category].LimitPerCivCentre);
    445445        else
    446             return (this.playerData.buildCounts[category] >= this.playerData.buildLimits[category]);
     446            return (this.playerData.Limits[category]);
    447447    },
    448448});
  • binaries/data/mods/public/simulation/ai/qbot/gamestate.js

     
    303303    return this.updatingCollection("resource-" + resource, Filters.byResource(resource), this.getEntities());
    304304};
    305305
    306 GameState.prototype.getBuildLimits = function() {
    307     return this.playerData.buildLimits;
     306GameState.prototype.getLimits = function() {
     307    return this.playerData.Limits;
    308308};
    309309
    310 GameState.prototype.getBuildCounts = function() {
    311     return this.playerData.buildCounts;
     310GameState.prototype.getCounts = function() {
     311    return this.playerData.Counts;
    312312};
    313313
    314314// Checks whether the maximum number of buildings have been cnstructed for a certain catergory
    315 GameState.prototype.isBuildLimitReached = function(category) {
    316     if(this.playerData.buildLimits[category] === undefined || this.playerData.buildCounts[category] === undefined)
     315GameState.prototype.isLimitReached = function(category) {
     316    if(this.playerData.Counts[category] === undefined)
    317317        return false;
    318     if(this.playerData.buildLimits[category].LimitsPerCivCentre != undefined)
    319         return (this.playerData.buildCounts[category] >= this.playerData.buildCounts["CivilCentre"]*this.playerData.buildLimits[category].LimitPerCivCentre);
     318    if(this.playerData.Limits[category].LimitsPerCivCentre != undefined)
     319        return (this.playerData.Limits[category].LimitPerCivCentre);
    320320    else
    321         return (this.playerData.buildCounts[category] >= this.playerData.buildLimits[category]);
     321        return (this.playerData.Limits[category]);
    322322};
  • binaries/data/mods/public/simulation/ai/qbot/military.js

     
    324324// Adds towers to the defenceBuilding queue
    325325MilitaryAttackManager.prototype.buildDefences = function(gameState, queues){
    326326    if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv('structures/{civ}_defense_tower'))
    327             + queues.defenceBuilding.totalLength() < gameState.getBuildLimits()["DefenseTower"]) {
     327            + queues.defenceBuilding.totalLength() < gameState.getLimits()["DefenseTower"]) {
    328328       
    329329       
    330330        gameState.getOwnEntities().forEach(function(dropsiteEnt) {
     
    343343        numFortresses += gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bFort[i]));
    344344    }
    345345   
    346     if (numFortresses + queues.defenceBuilding.totalLength() < gameState.getBuildLimits()["Fortress"]) {
     346    if (numFortresses + queues.defenceBuilding.totalLength() < gameState.getLimits()["Fortress"]) {
    347347        if (gameState.countEntitiesByType(gameState.applyCiv("units/{civ}_support_female_citizen")) > gameState.ai.modules["economy"].targetNumWorkers * 0.5){
    348348            if (gameState.getTimeElapsed() > 350 * 1000 * numFortresses){
    349349                if (gameState.ai.pathsToMe && gameState.ai.pathsToMe.length > 0){
  • binaries/data/mods/public/simulation/ai/testbot/gamestate.js

     
    269269     * Returns player build limits
    270270     * an object where each key is a category corresponding to a build limit for the player.
    271271     */
    272     getBuildLimits: function()
     272    getLimits: function()
    273273    {
    274         return this.playerData.buildLimits;
     274        return this.playerData.Limits;
    275275    },
    276276   
    277277    /**
    278      * Returns player build counts
    279      * an object where each key is a category corresponding to the current building count for the player.
     278     * Returns player counts
     279     * an object where each key is a category corresponding to the current count for the player.
    280280     */
    281     getBuildCounts: function()
     281    getCounts: function()
    282282    {
    283         return this.playerData.buildCounts;
     283        return this.playerData.Counts;
    284284    },
    285285   
    286286    /**
    287      * Checks if the player's build limit has been reached for the given category.
     287     * Checks if the player's limit has been reached for the given category.
    288288     * The category comes from the entity tenplate, specifically the BuildRestrictions component.
    289289     */
    290     isBuildLimitReached: function(category)
     290    isLimitReached: function(category)
    291291    {
    292         if (this.playerData.buildLimits[category] === undefined || this.playerData.buildCounts[category] === undefined)
     292        if (this.playerData.Counts[category] === undefined)
    293293            return false;
    294294       
    295295        // There's a special case of build limits per civ centre, so check that first
    296         if (this.playerData.buildLimits[category].LimitPerCivCentre !== undefined)
    297             return (this.playerData.buildCounts[category] >= this.playerData.buildCounts["CivilCentre"]*this.playerData.buildLimits[category].LimitPerCivCentre);
     296        if (this.playerData.Limits[category].LimitPerCivCentre !== undefined)
     297            return (this.playerData.Limits[category].LimitPerCivCentre);
    298298        else
    299             return (this.playerData.buildCounts[category] >= this.playerData.buildLimits[category]);
     299            return (this.playerData.Limits[category]);
    300300    },
    301301});
  • binaries/data/mods/public/simulation/components/BuildLimits.js

     
    1 function BuildLimits() {}
    2 
    3 BuildLimits.prototype.Schema =
    4     "<a:help>Specifies per category limits on number of buildings that can be constructed for each player.</a:help>" +
    5     "<a:example>" +
    6         "<Limits>" +
    7           "<CivilCentre/>" +
    8           "<DefenseTower>25</DefenseTower>" +
    9           "<Fortress>10</Fortress>" +
    10           "<Special>" +
    11             "<LimitPerCivCentre>1</LimitPerCivCentre>" +
    12           "</Special>" +
    13         "</Limits>" +
    14     "</a:example>" +
    15     "<element name='LimitMultiplier'>" +
    16         "<ref name='positiveDecimal'/>" +
    17     "</element>" +
    18     "<element name='Limits'>" +
    19         "<zeroOrMore>" +
    20             "<element a:help='Specifies a category of building on which to apply this limit. See BuildRestrictions for list of categories.'>" +
    21                 "<anyName />" +
    22                 "<choice>" +
    23                     "<text />" +
    24                     "<element name='LimitPerCivCentre' a:help='Specifies that this limit is per number of civil centres.'>" +
    25                         "<data type='nonNegativeInteger'/>" +
    26                     "</element>" +
    27                 "</choice>" +
    28             "</element>" +
    29         "</zeroOrMore>" +
    30     "</element>";
    31 
    32 /*
    33  *  TODO: Use an inheriting player_{civ}.xml template for civ-specific limits
    34  */
    35 
    36 BuildLimits.prototype.Init = function()
    37 {
    38     this.limit = {};
    39     this.count = {};
    40     for (var category in this.template.Limits)
    41     {
    42         this.limit[category] = this.template.Limits[category];
    43         this.count[category] = 0;
    44     }
    45 };
    46 
    47 BuildLimits.prototype.IncrementCount = function(category)
    48 {
    49     if (this.count[category] !== undefined)
    50     {
    51         this.count[category]++;
    52     }
    53 };
    54 
    55 BuildLimits.prototype.DecrementCount = function(category)
    56 {
    57     if (this.count[category] !== undefined)
    58     {
    59         this.count[category]--;
    60     }
    61 };
    62 
    63 BuildLimits.prototype.GetLimits = function()
    64 {
    65     return this.limit;
    66 };
    67 
    68 BuildLimits.prototype.GetCounts = function()
    69 {
    70     return this.count;
    71 };
    72 
    73 BuildLimits.prototype.AllowedToBuild = function(category)
    74 {
    75     // TODO: The UI should reflect this before the user tries to place the building,
    76     //          since the limits are independent of placement location
    77 
    78     // Allow unspecified categories and those with no limit
    79     if (this.count[category] === undefined || this.limit[category] === undefined)
    80     {
    81         return true;
    82     }
    83    
    84     // Rather than complicating the schema unecessarily, just handle special cases here
    85     if (this.limit[category].LimitPerCivCentre !== undefined)
    86     {
    87         if (this.count[category] >= this.count["CivilCentre"] * this.limit[category].LimitPerCivCentre)
    88         {
    89             var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player);
    90             var notification = {"player": cmpPlayer.GetPlayerID(), "message": category+" build limit of "+this.limit[category].LimitPerCivCentre+" per civil centre reached"};
    91             var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
    92             cmpGUIInterface.PushNotification(notification);
    93            
    94             return false;
    95         }
    96     }
    97     else if (this.count[category] >= this.limit[category])
    98     {
    99         var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player);
    100         var notification = {"player": cmpPlayer.GetPlayerID(), "message": category+" build limit of "+this.limit[category]+ " reached"};
    101         var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
    102         cmpGUIInterface.PushNotification(notification);
    103        
    104         return false;
    105     }
    106    
    107     return true;
    108 };
    109 
    110 BuildLimits.prototype.OnGlobalOwnershipChanged = function(msg)
    111 {
    112     // This automatically updates build counts
    113     var cmpBuildRestrictions = Engine.QueryInterface(msg.entity, IID_BuildRestrictions);
    114     if (cmpBuildRestrictions)
    115     {
    116         var playerID = (Engine.QueryInterface(this.entity, IID_Player)).GetPlayerID();
    117         if (msg.from == playerID)
    118         {
    119             this.DecrementCount(cmpBuildRestrictions.GetCategory());
    120         }
    121         if (msg.to == playerID)
    122         {
    123             this.IncrementCount(cmpBuildRestrictions.GetCategory());
    124         }
    125     }
    126 };
    127 
    128 Engine.RegisterComponentType(IID_BuildLimits, "BuildLimits", BuildLimits);
  • binaries/data/mods/public/simulation/components/EntityLimits.js

     
     1
     2
     3
     4
     5
     6
     7
     8
     9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
     111
     112
     113
     114
     115
     116
     117
     118
     119
     120
     121
     122
     123
     124
     125
     126
     127
     128
     129
     130
     131
     132
     133
     134
     135
     136
     137
     138
     139
     140
     141
     142
     143
     144
     145
     146
     147
     148
     149
     150
     151
     152
     153
     154
     155
     156
     157
     158
     159
     160
     161
     162
     163
     164
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    4949    for (var i = 0; i < n; ++i)
    5050    {
    5151        var playerEnt = cmpPlayerMan.GetPlayerByID(i);
    52         var cmpPlayerBuildLimits = Engine.QueryInterface(playerEnt, IID_BuildLimits);
     52        var cmpPlayerLimits);
    5353        var cmpPlayer = Engine.QueryInterface(playerEnt, IID_Player);
    5454       
    5555        // Work out what phase we are in
     
    8484            "phase": phase,
    8585            "isAlly": allies,
    8686            "isEnemy": enemies,
    87             "buildLimits": cmpPlayerBuildLimits.GetLimits(),
    88             "buildCounts": cmpPlayerBuildLimits.GetCounts(),
     87            "Limits.GetLimits(),
     88            "Limits.GetCounts(),
    8989            "techModifications": cmpTechnologyManager.GetTechModifications()
    9090        };
    9191        ret.players.push(playerData);
     
    380380            if (template.BuildRestrictions.Distance.MaxDistance) ret.buildRestrictions.distance.max = +template.BuildRestrictions.Distance.MaxDistance;
    381381        }
    382382    }
    383    
     383
     384    if (template.TrainingRestrictions)
     385    {
     386        ret.trainingRestrictions = {
     387            "category": template.TrainingRestrictions.Category,
     388        };
     389    }
     390
    384391    if (template.Cost)
    385392    {
    386393        ret.cost = {};
     
    449456        ret.icon = template.Identity.Icon;
    450457        ret.tooltip =  template.Identity.Tooltip;
    451458        ret.requiredTechnology = template.Identity.RequiredTechnology;
     459
    452460    }
    453461
    454462    if (template.UnitMotion)
  • binaries/data/mods/public/simulation/components/Player.js

     
    358358Player.prototype.OnGlobalOwnershipChanged = function(msg)
    359359{
    360360    var isConquestCritical = false;
    361 
    362361    // Load class list only if we're going to need it
    363362    if (msg.from == this.playerID || msg.to == this.playerID)
    364363    {
    365364        var cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity);
    366365        if (cmpIdentity)
    367366        {
    368             var classes = cmpIdentity.GetClassesList();
    369             isConquestCritical = classes.indexOf("ConquestCritical") != -1;
     367            isConquestCritical = cmpIdentity.HasClass("ConquestCritical");
    370368        }
    371369    }
    372    
    373370    if (msg.from == this.playerID)
    374371    {
    375372        if (isConquestCritical)
    376             this.conquestCriticalEntitiesCount--;   
    377 
     373            this.conquestCriticalEntitiesCount--;
    378374        var cost = Engine.QueryInterface(msg.entity, IID_Cost);
    379375        if (cost)
    380376        {
     
    382378            this.popBonuses -= cost.GetPopBonus();
    383379        }
    384380    }
    385    
    386381    if (msg.to == this.playerID)
    387382    {
    388383        if (isConquestCritical)
    389384            this.conquestCriticalEntitiesCount++;
    390            
    391385        var cost = Engine.QueryInterface(msg.entity, IID_Cost);
    392386        if (cost)
    393387        {
  • binaries/data/mods/public/simulation/components/ProductionQueue.js

     
    212212            if (!cmpPlayer.TrySubtractResources(totalCosts))
    213213                return;
    214214
     215
     216
     217
     218
     219
     220
     221
     222
    215223            this.queue.push({
    216224                "id": this.nextID++,
    217225                "player": cmpPlayer.GetPlayerID(),
     
    307315       
    308316        var cmpPlayer = QueryPlayerIDInterface(item.player, IID_Player);
    309317
     318
     319
     320
     321
     322
     323
     324
     325
     326
     327
     328
     329
     330
    310331        // Refund the resource cost for this batch
    311332        var totalCosts = {};
    312333        var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
     
    422443        //  so only create them once and use as needed
    423444        for (var i = 0; i < count; ++i)
    424445        {
    425             this.entityCache.push(Engine.AddEntity(templateName));
     446            var ent = Engine.AddEntity(templateName);
     447            this.entityCache.push(ent);
     448
     449            // Decrement entity count in the EntityLimits component
     450            // since it will be increased by EntityLimits.OnGlobalOwnershipChanged function,
     451            // i.e. we replace a 'trained' entity to an 'alive' one
     452            var cmpTrainingRestrictions = Engine.QueryInterface(ent, IID_TrainingRestrictions);
     453            if (cmpTrainingRestrictions)
     454            {
     455                var unitCategory = cmpTrainingRestrictions.GetCategory();
     456                var cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits);
     457                cmpPlayerEntityLimits.DecrementCount(unitCategory);
     458            }
    426459        }
    427460    }
    428461
  • binaries/data/mods/public/simulation/components/TrainingRestrictions.js

     
     1
     2
     3
     4
     5
     6
     7
     8
     9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
  • binaries/data/mods/public/simulation/components/interfaces/BuildLimits.js

     
    1 Engine.RegisterInterface("BuildLimits");
    2  No newline at end of file
  • binaries/data/mods/public/simulation/components/interfaces/EntityLimits.js

     
     1
  • binaries/data/mods/public/simulation/components/interfaces/TrainingRestrictions.js

     
     1
     2
  • binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js

     
    11Engine.LoadComponentScript("interfaces/Attack.js");
    22Engine.LoadComponentScript("interfaces/Barter.js");
    33Engine.LoadComponentScript("interfaces/Builder.js");
    4 Engine.LoadComponentScript("interfaces/BuildLimits.js");
    54Engine.LoadComponentScript("interfaces/DamageReceiver.js");
     5
    66Engine.LoadComponentScript("interfaces/Foundation.js");
    77Engine.LoadComponentScript("interfaces/GarrisonHolder.js");
    88Engine.LoadComponentScript("interfaces/Gate.js");
     
    6767    IsEnemy: function() { return true; },
    6868});
    6969
    70 AddMock(100, IID_BuildLimits, {
     70AddMock(100, IID_Limits, {
    7171    GetLimits: function() { return {"Foo": 10}; },
    7272    GetCounts: function() { return {"Foo": 5}; },
    7373});
     
    118118    IsEnemy: function() { return false; },
    119119});
    120120
    121 AddMock(101, IID_BuildLimits, {
     121AddMock(101, IID_Limits, {
    122122    GetLimits: function() { return {"Bar": 20}; },
    123123    GetCounts: function() { return {"Bar": 0}; },
    124124});
     
    171171            phase: "",
    172172            isAlly: [false, false, false],
    173173            isEnemy: [true, true, true],
    174             buildLimits: {"Foo": 10},
    175             buildCounts: {"Foo": 5},
     174            Limits: {"Foo": 10},
     175            Counts: {"Foo": 5},
    176176            techModifications: {},
    177177        },
    178178        {
     
    189189            phase: "village",
    190190            isAlly: [true, true, true],
    191191            isEnemy: [false, false, false],
    192             buildLimits: {"Bar": 20},
    193             buildCounts: {"Bar": 0},
     192            Limits: {"Bar": 20},
     193            Counts: {"Bar": 0},
    194194            techModifications: {},
    195195        }
    196196    ],
     
    214214            phase: "",
    215215            isAlly: [false, false, false],
    216216            isEnemy: [true, true, true],
    217             buildLimits: {"Foo": 10},
    218             buildCounts: {"Foo": 5},
     217            Limits: {"Foo": 10},
     218            Counts: {"Foo": 5},
    219219            techModifications: {},
    220220            statistics: {
    221221                unitsTrained: 10,
     
    248248            phase: "village",
    249249            isAlly: [true, true, true],
    250250            isEnemy: [false, false, false],
    251             buildLimits: {"Bar": 20},
    252             buildCounts: {"Bar": 0},
     251            Limits: {"Bar": 20},
     252            Counts: {"Bar": 0},
    253253            techModifications: {},
    254254            statistics: {
    255255                unitsTrained: 10,
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    146146
    147147    case "train":
    148148        var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     149
     150
     151
     152
     153
     154
     155
     156
    149157        // Verify that the building(s) can be controlled by the player
    150158        if (entities.length > 0)
    151159        {
    152160            for each (var ent in entities)
    153161            {
     162
     163
     164
     165
     166
     167
     168
     169
     170
     171
     172
     173
     174
    154175                var cmpTechnologyManager = QueryOwnerInterface(ent, IID_TechnologyManager);
    155176                // TODO: Enable this check once the AI gets technology support
    156177                if (cmpTechnologyManager.CanProduce(cmd.template) || true)
     
    545566        return false;
    546567    }
    547568   
    548     // Check build limits
    549     var cmpBuildLimits = QueryPlayerIDInterface(player, IID_BuildLimits);
    550     if (!cmpBuildLimits || !cmpBuildLimits.AllowedToBuild(cmpBuildRestrictions.GetCategory()))
     569    // Check limits
     570    var cmpLimits);
     571    if (!cmpLimits.AllowedToBuild(cmpBuildRestrictions.GetCategory()))
    551572    {
    552573        if (g_DebugCommands)
    553574  ��     {
  • binaries/data/mods/public/simulation/helpers/Templates.js

     
     1
     2
     3
     4
     5
     6
     7
     8
     9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
  • binaries/data/mods/public/simulation/templates/special/player.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity>
    3   <BuildLimits>
     3  <Limits>
    44    <LimitMultiplier>1.0</LimitMultiplier>
    55    <Limits>
    66      <CivilCentre/>
    77      <DefenseTower>25</DefenseTower>
    88      <Fortress>10</Fortress>
     9
     10
    911    </Limits>
    10   </BuildLimits>
     12  </Limits>
    1113  <Player/>
    1214  <StatisticsTracker/>
    1315  <TechnologyManager/>
  • binaries/data/mods/public/simulation/templates/template_unit_hero.xml

     
    6363      <death>actor/human/death/death.xml</death>
    6464    </SoundGroups>
    6565  </Sound>
     66
     67
     68
    6669  <UnitMotion>
    6770    <WalkSpeed>9.0</WalkSpeed>
    6871    <Run>
  • binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml

     
    7070  <Stamina>
    7171    <Max>2500</Max>
    7272  </Stamina>
     73
     74
     75
    7376  <UnitMotion>
    7477    <WalkSpeed>11.0</WalkSpeed>
    7578    <Run>
  • binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_archer.xml

     
    7070      </Texture>
    7171    </Overlay>
    7272  </Selectable>
     73
     74
     75
    7376  <UnitMotion>
    7477    <WalkSpeed>11.0</WalkSpeed>
    7578    <Run>
  • binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_javelinist.xml

     
    6060      </Texture>
    6161    </Overlay>
    6262  </Selectable>
     63
     64
     65
    6366  <UnitMotion>
    6467    <WalkSpeed>11.5</WalkSpeed>
    6568    <Run>
  • binaries/data/mods/public/simulation/templates/template_unit_hero_infantry.xml

     
    6868  <Stamina>
    6969    <Max>1500</Max>
    7070  </Stamina>
     71
     72
     73
    7174  <UnitMotion>
    7275    <WalkSpeed>8.5</WalkSpeed>
    7376    <Run>
  • binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_archer.xml

     
    6262      </Texture>
    6363    </Overlay>
    6464  </Selectable>
     65
     66
     67
    6568</Entity>
  • binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_javelinist.xml

     
    6666      </Texture>
    6767    </Overlay>
    6868  </Selectable>
     69
     70
     71
    6972</Entity>
  • binaries/data/mods/public/simulation/templates/template_unit_hero_ranged.xml

     
    5151      </Texture>
    5252    </Overlay>
    5353  </Selectable>
     54
     55
     56
    5457  <UnitMotion>
    5558    <WalkSpeed>8.5</WalkSpeed>
    5659    <Run>
  • binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml

     
    9999  <Stamina>
    100100    <Max>500</Max>
    101101  </Stamina>
     102
     103
     104
    102105  <UnitMotion>
    103106    <WalkSpeed>8.0</WalkSpeed>
    104107    <Run>