Ticket #1432: one_hero_2012_10_02_v4.diff
File one_hero_2012_10_02_v4.diff, 55.6 KB (added by , 12 years ago) |
---|
-
binaries/data/mods/public/gui/session/input.js
1470 1470 1471 1471 function flushTrainingBatch() 1472 1472 { 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 } 1474 1490 } 1475 1491 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 1476 1519 // Called by GUI when user clicks training button 1477 function addTrainingToQueue(selection, trainEntType )1520 function addTrainingToQueue(selection, trainEntType) 1478 1521 { 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) 1480 1532 { 1481 1533 if (inputState == INPUT_BATCHTRAINING) 1482 1534 { … … 1493 1545 } 1494 1546 } 1495 1547 // If we're already creating a batch of this unit (in the same building(s)), then just extend it 1548 1496 1549 if (sameEnts && batchTrainingType == trainEntType) 1497 1550 { 1498 batchTrainingCount += batchIncrementSize; 1551 if (canBeTrainedCount !== undefined && canBeTrainedCount > batchTrainingCount * appropriateBuildings.length) 1552 batchTrainingCount += batchIncrementSize; 1553 batchTrainingEntityAllowedCount = canBeTrainedCount; 1499 1554 return; 1500 1555 } 1501 1556 // Otherwise start a new one … … 1508 1563 inputState = INPUT_BATCHTRAINING; 1509 1564 batchTrainingEntities = selection; 1510 1565 batchTrainingType = trainEntType; 1566 1511 1567 batchTrainingCount = batchIncrementSize; 1512 1568 } 1513 1569 else 1514 1570 { 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}); 1517 1577 } 1518 1578 } 1519 1579 … … 1525 1585 1526 1586 // Returns the number of units that will be present in a batch if the user clicks 1527 1587 // the training button with shift down 1528 function getTrainingBatchStatus( entity, trainEntType)1588 function getTrainingBatchStatus() 1529 1589 { 1590 1591 1592 1593 1530 1594 if (inputState == INPUT_BATCHTRAINING && batchTrainingEntities.indexOf(entity) != -1 && batchTrainingType == trainEntType) 1531 return [batchTrainingCount, batchIncrementSize]; 1595 { 1596 nextBatchTrainingCount = batchTrainingCount; 1597 var canBeTrainedCount = batchTrainingEntityAllowedCount; 1598 } 1532 1599 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]; 1534 1617 } 1535 1618 1536 1619 // Called by GUI when user clicks production queue item -
binaries/data/mods/public/gui/session/unit_commands.js
150 150 * @param items Panel-specific data to construct the icons with. 151 151 * @param callback Callback function to argument to execute when an item's icon gets clicked. Takes a single 'item' argument. 152 152 */ 153 function setupUnitPanel(guiName, usedPanels, unitEntState, items, callback)153 function setupUnitPanel(guiName, usedPanels, unitEntState, items, callback) 154 154 { 155 155 usedPanels[guiName] = 1; 156 156 … … 347 347 case GATE: 348 348 var tooltip = item.tooltip; 349 349 if (item.template) 350 { 350 { 351 351 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+"]"); 355 355 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 } 364 364 break; 365 365 366 366 case STANCE: … … 374 374 if (template.tooltip) 375 375 tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]"; 376 376 377 var [b atchSize, batchIncrement] = getTrainingBatchStatus(unitEntState.id, entType);378 var t rainNum = batchSize ? batchSize+batchIncrement : batchIncrement;377 var [b); 378 var t; 379 379 380 380 tooltip += "\n" + getEntityCostTooltip(template); 381 381 … … 388 388 if (template.speed) 389 389 tooltip += "\n" + getEntitySpeed(template); 390 390 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 } 393 401 break; 394 402 395 403 case RESEARCH: … … 444 452 // Button 445 453 var button = getGUIObjectByName("unit"+guiName+"Button["+i+"]"); 446 454 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)+"]"); 449 457 var icon = getGUIObjectByName("unit"+guiName+"Icon["+i+"]"); 450 458 var selection = getGUIObjectByName("unit"+guiName+"Selection["+i+"]"); 451 459 var pair = getGUIObjectByName("unit"+guiName+"Pair["+i+"]"); … … 540 548 { 541 549 icon.sprite = "stretched:session/icons/" + item.icon; 542 550 } 551 552 553 554 555 556 557 558 559 560 561 562 563 543 564 else if (guiName == GATE) 544 565 { 545 566 var gateIcon; … … 583 604 584 605 if (guiName == RESEARCH) 585 606 { 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 599 620 if (item.pair) 600 621 { 601 622 grayscale = ""; 602 623 button1.enabled = true; 603 604 if (!Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType1)) 624 625 if (!Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType1)) 605 626 { 606 627 button1.enabled = false; 607 628 button1.tooltip += "\n" + GetTechnologyData(entType1).requirementsTooltip; 608 629 grayscale = "grayscale:"; 609 630 } 610 631 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 } 624 645 } 625 646 else 626 647 { 627 648 pair.hidden = true; 628 649 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 [b atchSize, batchIncrement] = getTrainingBatchStatus(unitEntState.id, entType);640 trainNum = b atchSize + 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; 641 662 } 642 643 // Walls have no cost defined. 663 664 // Walls have no cost defined. 644 665 if (template.cost !== undefined) 645 666 for (var r in template.cost) 646 667 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) 650 671 { 651 var totalCost = 0; 652 if (button.enabled !== false) 672 var totalCost = 0; 673 if (button.enabled !== false) 653 674 { 654 675 for each (var resource in neededResources) 655 676 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 } 665 686 } 666 687 } 667 688 else … … 767 788 } 768 789 769 790 // Sets up "unit barter panel" - special case for setupUnitPanel 770 function setupUnitBarterPanel(unitEntState )791 function setupUnitBarterPanel(unitEntState) 771 792 { 772 793 // Amount of player's resource to exchange 773 794 var amountToSell = BARTER_RESOURCE_AMOUNT_TO_SELL; … … 862 883 var player = Engine.GetPlayerID(); 863 884 if (entState.player == player || g_DevSettings.controlAll) 864 885 { 886 887 888 889 890 865 891 if (selection.length > 1) 866 setupUnitPanel(SELECTION, usedPanels, entState, g_Selection.groups.getTemplateNames(),892 setupUnitPanel(SELECTION, usedPanels, entState, g_Selection.groups.getTemplateNames(), 867 893 function (entType) { changePrimarySelectionGroup(entType); } ); 868 894 869 895 var commands = getEntityCommandsList(entState); 870 896 if (commands.length) 871 setupUnitPanel(COMMAND, usedPanels, entState, commands,897 setupUnitPanel(COMMAND, usedPanels, entState, commands, 872 898 function (item) { performCommand(entState.id, item.name); } ); 873 899 874 900 if (entState.garrisonHolder) … … 881 907 groups.add(state.garrisonHolder.entities) 882 908 } 883 909 884 setupUnitPanel(GARRISON, usedPanels, entState, groups.getTemplateNames(),910 setupUnitPanel(GARRISON, usedPanels, entState, groups.getTemplateNames(), 885 911 function (item) { unloadTemplate(item); } ); 886 912 } 887 913 888 914 var formations = Engine.GuiInterfaceCall("GetAvailableFormations"); 889 915 if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && !entState.garrisonHolder && formations.length) 890 916 { 891 setupUnitPanel(FORMATION, usedPanels, entState, formations,917 setupUnitPanel(FORMATION, usedPanels, entState, formations, 892 918 function (item) { performFormation(entState.id, item); } ); 893 919 } 894 920 … … 897 923 var stances = ["violent", "aggressive", "passive", "defensive", "standground"]; 898 924 if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && stances.length) 899 925 { 900 setupUnitPanel(STANCE, usedPanels, entState, stances,926 setupUnitPanel(STANCE, usedPanels, entState, stances, 901 927 function (item) { performStance(entState.id, item); } ); 902 928 } 903 929 … … 905 931 if (entState.barterMarket) 906 932 { 907 933 usedPanels["Barter"] = 1; 908 setupUnitBarterPanel(entState );934 setupUnitBarterPanel(entState); 909 935 } 910 936 911 937 var buildableEnts = []; … … 929 955 930 956 // The first selected entity's type has priority. 931 957 if (entState.buildEntities) 932 setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement);958 setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement); 933 959 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); } ); 936 962 else if (entState.trader) 937 963 setupUnitTradingPanel(usedPanels, entState, selection); 938 964 else if (!entState.foundation && entState.gate || hasClass(entState, "LongWall")) … … 994 1020 setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement); 995 1021 else if (trainableEnts.length) 996 1022 setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts, 997 function (trainEntType) { addTrainingToQueue(selection, trainEntType ); } );1023 function (trainEntType) { addTrainingToQueue(selection, trainEntType); } ); 998 1024 } 999 1025 1000 1026 // Show technologies if the active panel has at most one row of icons. … … 1007 1033 } 1008 1034 1009 1035 if (entState.production && entState.production.queue.length) 1010 setupUnitPanel(QUEUE, usedPanels, entState, entState.production.queue,1036 setupUnitPanel(QUEUE, usedPanels, entState, entState.production.queue, 1011 1037 function (item) { removeFromProductionQueue(entState.id, item.id); } ); 1012 1038 1013 1039 supplementalDetailsPanel.hidden = false; -
binaries/data/mods/public/simulation/ai/jubot/gamestate.js
416 416 * Returns player build limits 417 417 * an object where each key is a category corresponding to a build limit for the player. 418 418 */ 419 get BuildLimits: function()419 getLimits: function() 420 420 { 421 return this.playerData. buildLimits;421 return this.playerData.Limits; 422 422 }, 423 423 424 424 /** 425 425 * Returns player build counts 426 426 * an object where each key is a category corresponding to the current building count for the player. 427 427 */ 428 get BuildCounts: function()428 getCounts: function() 429 429 { 430 return this.playerData. buildCounts;430 return this.playerData.Counts; 431 431 }, 432 432 433 433 /** 434 434 * Checks if the player's build limit has been reached for the given category. 435 435 * The category comes from the entity tenplate, specifically the BuildRestrictions component. 436 436 */ 437 is BuildLimitReached: function(category)437 isLimitReached: function(category) 438 438 { 439 if (this.playerData. buildLimits[category] === undefined || this.playerData.buildCounts[category] === undefined)439 if (this.playerData.Counts[category] === undefined) 440 440 return false; 441 441 442 442 // 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); 445 445 else 446 return (this.playerData. buildCounts[category] >= this.playerData.buildLimits[category]);446 return (this.playerData.Limits[category]); 447 447 }, 448 448 }); -
binaries/data/mods/public/simulation/ai/qbot/gamestate.js
303 303 return this.updatingCollection("resource-" + resource, Filters.byResource(resource), this.getEntities()); 304 304 }; 305 305 306 GameState.prototype.get BuildLimits = function() {307 return this.playerData. buildLimits;306 GameState.prototype.getLimits = function() { 307 return this.playerData.Limits; 308 308 }; 309 309 310 GameState.prototype.get BuildCounts = function() {311 return this.playerData. buildCounts;310 GameState.prototype.getCounts = function() { 311 return this.playerData.Counts; 312 312 }; 313 313 314 314 // Checks whether the maximum number of buildings have been cnstructed for a certain catergory 315 GameState.prototype.is BuildLimitReached = function(category) {316 if(this.playerData. buildLimits[category] === undefined || this.playerData.buildCounts[category] === undefined)315 GameState.prototype.isLimitReached = function(category) { 316 if(this.playerData.Counts[category] === undefined) 317 317 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); 320 320 else 321 return (this.playerData. buildCounts[category] >= this.playerData.buildLimits[category]);321 return (this.playerData.Limits[category]); 322 322 }; -
binaries/data/mods/public/simulation/ai/qbot/military.js
324 324 // Adds towers to the defenceBuilding queue 325 325 MilitaryAttackManager.prototype.buildDefences = function(gameState, queues){ 326 326 if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv('structures/{civ}_defense_tower')) 327 + queues.defenceBuilding.totalLength() < gameState.get BuildLimits()["DefenseTower"]) {327 + queues.defenceBuilding.totalLength() < gameState.getLimits()["DefenseTower"]) { 328 328 329 329 330 330 gameState.getOwnEntities().forEach(function(dropsiteEnt) { … … 343 343 numFortresses += gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bFort[i])); 344 344 } 345 345 346 if (numFortresses + queues.defenceBuilding.totalLength() < gameState.get BuildLimits()["Fortress"]) {346 if (numFortresses + queues.defenceBuilding.totalLength() < gameState.getLimits()["Fortress"]) { 347 347 if (gameState.countEntitiesByType(gameState.applyCiv("units/{civ}_support_female_citizen")) > gameState.ai.modules["economy"].targetNumWorkers * 0.5){ 348 348 if (gameState.getTimeElapsed() > 350 * 1000 * numFortresses){ 349 349 if (gameState.ai.pathsToMe && gameState.ai.pathsToMe.length > 0){ -
binaries/data/mods/public/simulation/ai/testbot/gamestate.js
269 269 * Returns player build limits 270 270 * an object where each key is a category corresponding to a build limit for the player. 271 271 */ 272 get BuildLimits: function()272 getLimits: function() 273 273 { 274 return this.playerData. buildLimits;274 return this.playerData.Limits; 275 275 }, 276 276 277 277 /** 278 * Returns player buildcounts279 * an object where each key is a category corresponding to the current buildingcount for the player.278 * Returns player counts 279 * an object where each key is a category corresponding to the current count for the player. 280 280 */ 281 get BuildCounts: function()281 getCounts: function() 282 282 { 283 return this.playerData. buildCounts;283 return this.playerData.Counts; 284 284 }, 285 285 286 286 /** 287 * Checks if the player's buildlimit has been reached for the given category.287 * Checks if the player's limit has been reached for the given category. 288 288 * The category comes from the entity tenplate, specifically the BuildRestrictions component. 289 289 */ 290 is BuildLimitReached: function(category)290 isLimitReached: function(category) 291 291 { 292 if (this.playerData. buildLimits[category] === undefined || this.playerData.buildCounts[category] === undefined)292 if (this.playerData.Counts[category] === undefined) 293 293 return false; 294 294 295 295 // 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); 298 298 else 299 return (this.playerData. buildCounts[category] >= this.playerData.buildLimits[category]);299 return (this.playerData.Limits[category]); 300 300 }, 301 301 }); -
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 limits34 */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 location77 78 // Allow unspecified categories and those with no limit79 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 here85 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 counts113 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
49 49 for (var i = 0; i < n; ++i) 50 50 { 51 51 var playerEnt = cmpPlayerMan.GetPlayerByID(i); 52 var cmpPlayer BuildLimits = Engine.QueryInterface(playerEnt, IID_BuildLimits);52 var cmpPlayerLimits); 53 53 var cmpPlayer = Engine.QueryInterface(playerEnt, IID_Player); 54 54 55 55 // Work out what phase we are in … … 84 84 "phase": phase, 85 85 "isAlly": allies, 86 86 "isEnemy": enemies, 87 " buildLimits": cmpPlayerBuildLimits.GetLimits(),88 " buildCounts": cmpPlayerBuildLimits.GetCounts(),87 "Limits.GetLimits(), 88 "Limits.GetCounts(), 89 89 "techModifications": cmpTechnologyManager.GetTechModifications() 90 90 }; 91 91 ret.players.push(playerData); … … 380 380 if (template.BuildRestrictions.Distance.MaxDistance) ret.buildRestrictions.distance.max = +template.BuildRestrictions.Distance.MaxDistance; 381 381 } 382 382 } 383 383 384 if (template.TrainingRestrictions) 385 { 386 ret.trainingRestrictions = { 387 "category": template.TrainingRestrictions.Category, 388 }; 389 } 390 384 391 if (template.Cost) 385 392 { 386 393 ret.cost = {}; … … 449 456 ret.icon = template.Identity.Icon; 450 457 ret.tooltip = template.Identity.Tooltip; 451 458 ret.requiredTechnology = template.Identity.RequiredTechnology; 459 452 460 } 453 461 454 462 if (template.UnitMotion) -
binaries/data/mods/public/simulation/components/Player.js
358 358 Player.prototype.OnGlobalOwnershipChanged = function(msg) 359 359 { 360 360 var isConquestCritical = false; 361 362 361 // Load class list only if we're going to need it 363 362 if (msg.from == this.playerID || msg.to == this.playerID) 364 363 { 365 364 var cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity); 366 365 if (cmpIdentity) 367 366 { 368 var classes = cmpIdentity.GetClassesList(); 369 isConquestCritical = classes.indexOf("ConquestCritical") != -1; 367 isConquestCritical = cmpIdentity.HasClass("ConquestCritical"); 370 368 } 371 369 } 372 373 370 if (msg.from == this.playerID) 374 371 { 375 372 if (isConquestCritical) 376 this.conquestCriticalEntitiesCount--; 377 373 this.conquestCriticalEntitiesCount--; 378 374 var cost = Engine.QueryInterface(msg.entity, IID_Cost); 379 375 if (cost) 380 376 { … … 382 378 this.popBonuses -= cost.GetPopBonus(); 383 379 } 384 380 } 385 386 381 if (msg.to == this.playerID) 387 382 { 388 383 if (isConquestCritical) 389 384 this.conquestCriticalEntitiesCount++; 390 391 385 var cost = Engine.QueryInterface(msg.entity, IID_Cost); 392 386 if (cost) 393 387 { -
binaries/data/mods/public/simulation/components/ProductionQueue.js
212 212 if (!cmpPlayer.TrySubtractResources(totalCosts)) 213 213 return; 214 214 215 216 217 218 219 220 221 222 215 223 this.queue.push({ 216 224 "id": this.nextID++, 217 225 "player": cmpPlayer.GetPlayerID(), … … 307 315 308 316 var cmpPlayer = QueryPlayerIDInterface(item.player, IID_Player); 309 317 318 319 320 321 322 323 324 325 326 327 328 329 330 310 331 // Refund the resource cost for this batch 311 332 var totalCosts = {}; 312 333 var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); … … 422 443 // so only create them once and use as needed 423 444 for (var i = 0; i < count; ++i) 424 445 { 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 } 426 459 } 427 460 } 428 461 -
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
1 1 Engine.LoadComponentScript("interfaces/Attack.js"); 2 2 Engine.LoadComponentScript("interfaces/Barter.js"); 3 3 Engine.LoadComponentScript("interfaces/Builder.js"); 4 Engine.LoadComponentScript("interfaces/BuildLimits.js");5 4 Engine.LoadComponentScript("interfaces/DamageReceiver.js"); 5 6 6 Engine.LoadComponentScript("interfaces/Foundation.js"); 7 7 Engine.LoadComponentScript("interfaces/GarrisonHolder.js"); 8 8 Engine.LoadComponentScript("interfaces/Gate.js"); … … 67 67 IsEnemy: function() { return true; }, 68 68 }); 69 69 70 AddMock(100, IID_ BuildLimits, {70 AddMock(100, IID_Limits, { 71 71 GetLimits: function() { return {"Foo": 10}; }, 72 72 GetCounts: function() { return {"Foo": 5}; }, 73 73 }); … … 118 118 IsEnemy: function() { return false; }, 119 119 }); 120 120 121 AddMock(101, IID_ BuildLimits, {121 AddMock(101, IID_Limits, { 122 122 GetLimits: function() { return {"Bar": 20}; }, 123 123 GetCounts: function() { return {"Bar": 0}; }, 124 124 }); … … 171 171 phase: "", 172 172 isAlly: [false, false, false], 173 173 isEnemy: [true, true, true], 174 buildLimits: {"Foo": 10},175 buildCounts: {"Foo": 5},174 Limits: {"Foo": 10}, 175 Counts: {"Foo": 5}, 176 176 techModifications: {}, 177 177 }, 178 178 { … … 189 189 phase: "village", 190 190 isAlly: [true, true, true], 191 191 isEnemy: [false, false, false], 192 buildLimits: {"Bar": 20},193 buildCounts: {"Bar": 0},192 Limits: {"Bar": 20}, 193 Counts: {"Bar": 0}, 194 194 techModifications: {}, 195 195 } 196 196 ], … … 214 214 phase: "", 215 215 isAlly: [false, false, false], 216 216 isEnemy: [true, true, true], 217 buildLimits: {"Foo": 10},218 buildCounts: {"Foo": 5},217 Limits: {"Foo": 10}, 218 Counts: {"Foo": 5}, 219 219 techModifications: {}, 220 220 statistics: { 221 221 unitsTrained: 10, … … 248 248 phase: "village", 249 249 isAlly: [true, true, true], 250 250 isEnemy: [false, false, false], 251 buildLimits: {"Bar": 20},252 buildCounts: {"Bar": 0},251 Limits: {"Bar": 20}, 252 Counts: {"Bar": 0}, 253 253 techModifications: {}, 254 254 statistics: { 255 255 unitsTrained: 10, -
binaries/data/mods/public/simulation/helpers/Commands.js
146 146 147 147 case "train": 148 148 var entities = FilterEntityList(cmd.entities, player, controlAllUnits); 149 150 151 152 153 154 155 156 149 157 // Verify that the building(s) can be controlled by the player 150 158 if (entities.length > 0) 151 159 { 152 160 for each (var ent in entities) 153 161 { 162 163 164 165 166 167 168 169 170 171 172 173 174 154 175 var cmpTechnologyManager = QueryOwnerInterface(ent, IID_TechnologyManager); 155 176 // TODO: Enable this check once the AI gets technology support 156 177 if (cmpTechnologyManager.CanProduce(cmd.template) || true) … … 545 566 return false; 546 567 } 547 568 548 // Check buildlimits549 var cmp BuildLimits = QueryPlayerIDInterface(player, IID_BuildLimits);550 if (!cmp BuildLimits || !cmpBuildLimits.AllowedToBuild(cmpBuildRestrictions.GetCategory()))569 // Check limits 570 var cmpLimits); 571 if (!cmpLimits.AllowedToBuild(cmpBuildRestrictions.GetCategory())) 551 572 { 552 573 if (g_DebugCommands) 553 574 �� { -
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
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity> 3 < BuildLimits>3 <Limits> 4 4 <LimitMultiplier>1.0</LimitMultiplier> 5 5 <Limits> 6 6 <CivilCentre/> 7 7 <DefenseTower>25</DefenseTower> 8 8 <Fortress>10</Fortress> 9 10 9 11 </Limits> 10 </ BuildLimits>12 </Limits> 11 13 <Player/> 12 14 <StatisticsTracker/> 13 15 <TechnologyManager/> -
binaries/data/mods/public/simulation/templates/template_unit_hero.xml
63 63 <death>actor/human/death/death.xml</death> 64 64 </SoundGroups> 65 65 </Sound> 66 67 68 66 69 <UnitMotion> 67 70 <WalkSpeed>9.0</WalkSpeed> 68 71 <Run> -
binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml
70 70 <Stamina> 71 71 <Max>2500</Max> 72 72 </Stamina> 73 74 75 73 76 <UnitMotion> 74 77 <WalkSpeed>11.0</WalkSpeed> 75 78 <Run> -
binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_archer.xml
70 70 </Texture> 71 71 </Overlay> 72 72 </Selectable> 73 74 75 73 76 <UnitMotion> 74 77 <WalkSpeed>11.0</WalkSpeed> 75 78 <Run> -
binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_javelinist.xml
60 60 </Texture> 61 61 </Overlay> 62 62 </Selectable> 63 64 65 63 66 <UnitMotion> 64 67 <WalkSpeed>11.5</WalkSpeed> 65 68 <Run> -
binaries/data/mods/public/simulation/templates/template_unit_hero_infantry.xml
68 68 <Stamina> 69 69 <Max>1500</Max> 70 70 </Stamina> 71 72 73 71 74 <UnitMotion> 72 75 <WalkSpeed>8.5</WalkSpeed> 73 76 <Run> -
binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_archer.xml
62 62 </Texture> 63 63 </Overlay> 64 64 </Selectable> 65 66 67 65 68 </Entity> -
binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_javelinist.xml
66 66 </Texture> 67 67 </Overlay> 68 68 </Selectable> 69 70 71 69 72 </Entity> -
binaries/data/mods/public/simulation/templates/template_unit_hero_ranged.xml
51 51 </Texture> 52 52 </Overlay> 53 53 </Selectable> 54 55 56 54 57 <UnitMotion> 55 58 <WalkSpeed>8.5</WalkSpeed> 56 59 <Run> -
binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml
99 99 <Stamina> 100 100 <Max>500</Max> 101 101 </Stamina> 102 103 104 102 105 <UnitMotion> 103 106 <WalkSpeed>8.0</WalkSpeed> 104 107 <Run>