Ticket #2160: regicide_early_attack_v2.patch

File regicide_early_attack_v2.patch, 30.1 KB (added by elexis, 8 years ago)
  • binaries/data/mods/public/gui/gamesetup/gamesetup.js

    function initRadioButtons()  
    496496    let options = {
    497497        "RevealMap": "revealMap",
    498498        "ExploreMap": "exploreMap",
    499499        "DisableTreasures": "disableTreasures",
    500500        "LockTeams": "lockTeams",
    501         "LastManStanding" : "lastManStanding",
     501        "LastManStanding": "lastManStanding",
     502        "RegicideEarlyAttack": "regicideEarlyAttack",
    502503        "CheatsEnabled": "enableCheats"
    503504    };
    504505
    505506    Object.keys(options).forEach(attribute => {
    506507        Engine.GetGUIObjectByName(options[attribute]).onPress = function() {
    function selectMap(name)  
    11811182
    11821183    if (g_GameAttributes.mapType == "scenario")
    11831184    {
    11841185        delete g_GameAttributes.settings.WonderDuration;
    11851186        delete g_GameAttributes.settings.LastManStanding;
     1187        delete g_GameAttributes.settings.RegicideEarlyAttack;
    11861188    }
    11871189
    11881190    if (mapSettings.PlayerData)
    11891191        sanitizePlayerData(mapSettings.PlayerData);
    11901192
    function updateGUIObjects()  
    13781380    setGUIBoolean("disableTreasures", "disableTreasuresText", !!mapSettings.DisableTreasures);
    13791381    setGUIBoolean("exploreMap", "exploreMapText", !!mapSettings.ExploreMap);
    13801382    setGUIBoolean("revealMap", "revealMapText", !!mapSettings.RevealMap);
    13811383    setGUIBoolean("lockTeams", "lockTeamsText", !!mapSettings.LockTeams);
    13821384    setGUIBoolean("lastManStanding", "lastManStandingText", !!mapSettings.LastManStanding);
     1385    setGUIBoolean("regicideEarlyAttack", "regicideEarlyAttackText", !!mapSettings.RegicideEarlyAttack);
    13831386    setGUIBoolean("enableRating", "enableRatingText", !!mapSettings.RatingEnabled);
    13841387
    13851388    Engine.GetGUIObjectByName("optionWonderDuration").hidden =
    13861389        g_GameAttributes.settings.GameType &&
    13871390        g_GameAttributes.settings.GameType != "wonder";
    13881391    Engine.GetGUIObjectByName("optionLastManStanding").hidden = mapSettings.LockTeams;
     1392    Engine.GetGUIObjectByName("optionRegicideEarlyAttack").hidden =
     1393        g_GameAttributes.settings.GameType &&
     1394        g_GameAttributes.settings.GameType != "regicide";
    13891395
    13901396    Engine.GetGUIObjectByName("cheatWarningText").hidden = !g_IsNetworked || !mapSettings.CheatsEnabled;
    13911397
    13921398    Engine.GetGUIObjectByName("enableCheats").enabled = !mapSettings.RatingEnabled;
    13931399    Engine.GetGUIObjectByName("lockTeams").enabled = !mapSettings.RatingEnabled;
    function updateGUIObjects()  
    14011407
    14021408    let notScenario = g_GameAttributes.mapType != "scenario" && g_IsController ;
    14031409
    14041410    for (let ctrl of ["victoryCondition", "wonderDuration", "populationCap",
    14051411                      "startingResources", "ceasefire", "revealMap",
    1406                       "exploreMap", "disableTreasures", "lockTeams", "lastManStanding"])
     1412                      "exploreMap", "disableTreasures", "lockTeams",
     1413                      "lastManStanding", "regicideEarlyAttack"])
    14071414        hideControl(ctrl, ctrl + "Text", notScenario);
    14081415
    14091416    Engine.GetGUIObjectByName("civResetButton").hidden = !notScenario;
    14101417    Engine.GetGUIObjectByName("teamResetButton").hidden = !notScenario;
    14111418
  • binaries/data/mods/public/gui/gamesetup/gamesetup.xml

     
    333333                    <object name="wonderDuration" size="40%+10 0 100% 28" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip">
    334334                        <translatableAttribute id="tooltip">Number of minutes that the player has to keep the wonder in order to win.</translatableAttribute>
    335335                    </object>
    336336                </object>
    337337
    338                 <object name="optionPopulationCap" size="14 98 94% 126">
     338                <object name="optionRegicideEarlyAttack" size="14 98 94% 126">
     339                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
     340                        <translatableAttribute id="caption">Early Hero Attack:</translatableAttribute>
     341                    </object>
     342                    <object name="regicideEarlyAttackText" size="40% 0 100% 28" type="text" style="ModernLeftLabelText"/>
     343                    <object name="regicideEarlyAttack" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip">
     344                        <translatableAttribute id="tooltip">Toggle whether heroes can attack from the start of the game, or from City Phase.</translatableAttribute>
     345                    </object>
     346                </object>
     347
     348                <object name="optionPopulationCap" size="14 128 94% 156">
    339349                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
    340350                        <translatableAttribute id="caption">Population Cap:</translatableAttribute>
    341351                    </object>
    342352                    <object name="populationCapText" size="40% 0 100% 100%" type="text" style="ModernLeftLabelText"/>
    343353                    <object name="populationCap" size="40%+10 0 100% 28" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip">
    344354                        <translatableAttribute id="tooltip">Select population cap.</translatableAttribute>
    345355                    </object>
    346356                </object>
    347357
    348                 <object name="optionStartingResources" size="14 128 94% 156">
     358                <object name="optionStartingResources" size="14 158 94% 186">
    349359                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
    350360                        <translatableAttribute id="caption">Starting Resources:</translatableAttribute>
    351361                    </object>
    352362                    <object name="startingResourcesText" size="40% 0 100% 100%" type="text" style="ModernLeftLabelText"/>
    353363                    <object name="startingResources" size="40%+10 0 100% 28" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip">
    354364                        <translatableAttribute id="tooltip">Select the game's starting resources.</translatableAttribute>
    355365                    </object>
    356366                </object>
    357367
    358                 <object name="optionCeasefire" size="14 158 94% 186">
     368                <object name="optionCeasefire" size="14 188 94% 216">
    359369                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
    360370                        <translatableAttribute id="caption">Ceasefire:</translatableAttribute>
    361371                    </object>
    362372                    <object name="ceasefireText" size="40% 0 100% 100%" type="text" style="ModernLeftLabelText"/>
    363373                    <object name="ceasefire" size="40%+10 0 100% 28" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip">
     
    438448                <!-- Hide More Options Button -->
    439449                <object
    440450                    name="hideMoreOptions"
    441451                    type="button"
    442452                    style="StoneButton"
    443                     size="50%-70 428 50%+70 456"
     453                    size="50%-70 458 50%+70 486"
    444454                    tooltip_style="onscreenToolTip"
    445455                    hotkey="cancel"
    446456                >
    447457                    <translatableAttribute id="caption">OK</translatableAttribute>
    448458                    <translatableAttribute id="tooltip">Close more game options window</translatableAttribute>
  • binaries/data/mods/public/gui/session/selection_panels.js

    g_SelectionPanels.Training = {  
    990990        tooltips.push(
    991991            "[color=\"" + g_HotkeyColor + "\"]" +
    992992            formatBatchTrainingString(buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch) +
    993993            "[/color]");
    994994
     995        let productionQueueEnabled = Engine.GuiInterfaceCall("GetProductionQueueEnabled", {
     996            "player": data.unitEntState.player,
     997            "ents": data.selection
     998        });
     999
     1000        if (!productionQueueEnabled)
     1001            tooltips.push(sprintf(translate("The Production Queue is disabled for this entity")));
     1002
    9951003        if (!technologyEnabled)
    9961004            tooltips.push(sprintf(translate("Requires %(technology)s"), {
    9971005                "technology": getEntityNames(GetTechnologyData(template.requiredTechnology))
    9981006            }));
    9991007
    g_SelectionPanels.Training = {  
    10011009            tooltips.push(getNeededResourcesTooltip(neededResources));
    10021010
    10031011        data.button.tooltip = tooltips.filter(tip => tip).join("\n");
    10041012
    10051013        let modifier = "";
    1006         if (!technologyEnabled || limits.canBeAddedCount == 0)
     1014        if (!technologyEnabled || limits.canBeAddedCount == 0 || !productionQueueEnabled)
    10071015        {
    10081016            data.button.enabled = false;
    10091017            modifier = "color:0 0 0 127:grayscale:";
    10101018        }
    10111019        else if (neededResources)
  • binaries/data/mods/public/maps/scripts/Regicide.js

    Trigger.prototype.InitRegicideGame = fun  
    4747        return 0;
    4848    };
    4949
    5050    // Attempt to spawn one hero per player
    5151    let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
     52    let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
     53    this.regicideEarlyAttack = cmpEndGameManager.GetGameTypeSettings().regicideEarlyAttack;
     54
    5255    for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID)
    5356    {
    5457        let spawnPoints = cmpRangeManager.GetEntitiesByPlayer(playerID).sort((entity1, entity2) =>
    5558            getSpawnPreference(entity2) - getSpawnPreference(entity1));
    5659
    5760        this.regicideHeroes[playerID] = this.SpawnRegicideHero(playerID, heroTemplates[playersCivs[playerID]], spawnPoints);
     61
     62        if (!this.regicideEarlyAttack)
     63            this.SetRegicideEarlyAttack(this.regicideHeroes[playerID], false);
    5864    }
    5965};
    6066
    6167/**
    6268 * Spawn a random hero at one of the given locations (which are checked in order).
    Trigger.prototype.SpawnRegicideHero = fu  
    100106
    101107    error("Couldn't spawn hero for player " + playerID);
    102108    return undefined;
    103109};
    104110
     111Trigger.prototype.CheckRegicideCityPhase = function(data)
     112{
     113    if (data.tech.indexOf("phase_city") == -1 || this.regicideEarlyAttack)
     114        return;
     115
     116    this.SetRegicideEarlyAttack(this.regicideHeroes[data.player], true);
     117};
     118
     119Trigger.prototype.SetRegicideEarlyAttack(hero, enabled)
     120{
     121    let cmpAttack = Engine.QueryInterface(heor, IID_Attack);
     122    if (cmpAttack)
     123        cmpAttack.SetEnabled(enabled);
     124
     125    let cmpAuras = Engine.QueryInterface(hero, IID_Auras);
     126    if (cmpAuras)
     127        cmpAuras.SetEnabled(enabled);
     128
     129    let cmpProductionQueue = Engine.QueryInterface(hero, IID_ProductionQueue);
     130    if (cmpProductionQueue)
     131        cmpProductionQueue.SetEnabled(enabled);
     132};
     133
    105134let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
    106135cmpTrigger.regicideHeroes = [];
     136cmpTrigger.regicideEarlyAttack = false;
    107137cmpTrigger.DoAfterDelay(0, "InitRegicideGame", {});
    108138cmpTrigger.RegisterTrigger("OnOwnershipChanged", "CheckRegicideDefeat", { "enabled": true });
     139cmpTrigger.RegisterTrigger("OnResearchFinished", "CheckRegicideCityPhase", { "enabled": true });
  • binaries/data/mods/public/simulation/components/Attack.js

    Attack.prototype.Schema =  
    200200        "</element>" +
    201201    "</optional>";
    202202
    203203Attack.prototype.Init = function()
    204204{
     205    this.enabled = true;
    205206};
    206207
    207208Attack.prototype.Serialize = null; // we have no dynamic state to save
    208209
     210Attack.prototype.GetEnabled = function()
     211{
     212    return this.enabled;
     213};
     214
     215Attack.prototype.SetEnabled = function(enabled)
     216{
     217    this.enabled = enabled;
     218};
     219
    209220Attack.prototype.GetAttackTypes = function()
    210221{
    211222    return ["Melee", "Ranged", "Capture"].filter(type => !!this.template[type]);
    212223};
    213224
    Attack.prototype.GetRestrictedClasses =  
    229240    return [];
    230241};
    231242
    232243Attack.prototype.CanAttack = function(target)
    233244{
     245    if (!this.enabled)
     246        return false;
     247
    234248    let cmpFormation = Engine.QueryInterface(target, IID_Formation);
    235249    if (cmpFormation)
    236250        return true;
    237251
    238252    let cmpThisPosition = Engine.QueryInterface(this.entity, IID_Position);
    Attack.prototype.GetBestAttackAgainst =  
    339353    // check if the target is capturable
    340354    let captureIndex = types.indexOf("Capture");
    341355    if (captureIndex != -1)
    342356    {
    343357        let cmpCapturable = QueryMiragedInterface(target, IID_Capturable);
    344 
    345358        let cmpPlayer = QueryOwnerInterface(this.entity);
     359
    346360        if (allowCapture && cmpPlayer && cmpCapturable && cmpCapturable.CanCapture(cmpPlayer.GetPlayerID()))
    347361            return "Capture";
     362
    348363        // not captureable, so remove this attack
    349364        types.splice(captureIndex, 1);
    350365    }
    351366
    352367    let isPreferred = className => attack.GetPreferredClasses(className).some(isTargetClass);
  • binaries/data/mods/public/simulation/components/Auras.js

    Auras.prototype.Schema =  
    66    "</attribute>" +
    77    "<text a:help='A whitespace-separated list of aura files, placed under simulation/data/auras/'/>";
    88
    99Auras.prototype.Init = function()
    1010{
     11    this.enabled = true;
    1112    let cmpDataTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_DataTemplateManager);
    1213    this.auras = {};
    1314    this.affectedPlayers = {};
    1415    let auraNames = this.GetAuraNames();
    1516    for (let name of auraNames)
    Auras.prototype.Init = function()  
    2021    // In case of autogarrisoning, this component can be called before ownership is set.
    2122    // So it needs to be completely initialised from the start.
    2223    this.Clean();
    2324};
    2425
     26Auras.prototype.GetEnabled = function()
     27{
     28    return this.enabled;
     29};
     30
     31Auras.prototype.SetEnabled = function(enabled)
     32{
     33    this.enabled = enabled;
     34    this.Clean();
     35};
     36
    2537// We can modify identifier if we want stackable auras in some case.
    2638Auras.prototype.GetModifierIdentifier = function(name)
    2739{
    2840    if (this.auras[name].stackable)
    2941        return name + this.entity;
    Auras.prototype.CalculateAffectedPlayers  
    107119    }
    108120};
    109121
    110122Auras.prototype.CanApply = function(name)
    111123{
     124    if (!this.enabled)
     125        return false;
    112126    if (!this.auras[name].requiredTechnology)
    113127        return true;
    114128    let cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager);
    115129    if (!cmpTechnologyManager)
    116130        return false;
  • binaries/data/mods/public/simulation/components/Formation.js

    Formation.prototype.SetMembers = functio  
    302302        var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
    303303        cmpUnitAI.SetFormationController(this.entity);
    304304        cmpUnitAI.SetLastFormationTemplate(templateName);
    305305
    306306        var cmpAuras = Engine.QueryInterface(ent, IID_Auras);
    307         if (cmpAuras && cmpAuras.HasFormationAura())
     307        if (cmpAuras && cmpAuras.HasFormationAura() && cmpAuras.GetEnabled())
    308308        {
    309309            this.formationMembersWithAura.push(ent);
    310310            cmpAuras.ApplyFormationBonus(ents);
    311311        }
    312312    }
    Formation.prototype.AddMembers = functio  
    385385    {
    386386        var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
    387387        cmpUnitAI.SetFormationController(this.entity);
    388388       
    389389        var cmpAuras = Engine.QueryInterface(ent, IID_Auras);
    390         if (cmpAuras && cmpAuras.HasFormationAura())
     390        if (cmpAuras && cmpAuras.HasFormationAura() && cmpAuras.GetEnabled())
    391391        {
    392392            this.formationMembersWithAura.push(ent);
    393393            cmpAuras.ApplyFormationBonus(ents);
    394394        }
    395395    }
  • binaries/data/mods/public/simulation/components/GarrisonHolder.js

    GarrisonHolder.prototype.PerformGarrison  
    273273    var cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue);
    274274    if (cmpProductionQueue)
    275275        cmpProductionQueue.PauseProduction();
    276276
    277277    var cmpAura = Engine.QueryInterface(entity, IID_Auras);
    278     if (cmpAura && cmpAura.HasGarrisonAura())
     278    if (cmpAura && cmpAura.HasGarrisonAura() && cmpAura.GetEnabled())
    279279        cmpAura.ApplyGarrisonBonus(this.entity);
    280280
    281281    Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });
    282282
    283283    var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
    GarrisonHolder.prototype.Eject = functio  
    346346    var cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue);
    347347    if (cmpProductionQueue)
    348348        cmpProductionQueue.UnpauseProduction();
    349349
    350350    var cmpAura = Engine.QueryInterface(entity, IID_Auras);
    351     if (cmpAura && cmpAura.HasGarrisonAura())
     351    if (cmpAura && cmpAura.HasGarrisonAura() && cmpAura.GetEnabled())
    352352        cmpAura.RemoveGarrisonBonus(this.entity);
    353353
    354354
    355355    cmpNewPosition.JumpTo(pos.x, pos.z);
    356356    cmpNewPosition.SetHeightOffset(0);
  • binaries/data/mods/public/simulation/components/GuiInterface.js

    GuiInterface.prototype.GetTimeNotificati  
    755755    let time = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime();
    756756    // filter on players and time, since the delete timer might be executed with a delay
    757757    return this.timeNotifications.filter(n => n.players.indexOf(player) != -1 && n.endTime > time);
    758758};
    759759
     760GuiInterface.prototype.GetProductionQueueEnabled = function(player, data)
     761{
     762    for (let ent of data.ents)
     763    {
     764        let cmpProductionQueue = Engine.QueryInterface(ent, IID_ProductionQueue);
     765        if (!cmpProductionQueue)
     766            continue;
     767        else
     768            return cmpProductionQueue.GetEnabled();
     769    }
     770    return false;
     771};
     772
    760773GuiInterface.prototype.PushNotification = function(notification)
    761774{
    762775    if (!notification.type || notification.type == "text")
    763776        this.AddTimeNotification(notification);
    764777    else
    let exposedFunctions = {  
    19591972    "GetBattleState": 1,
    19601973    "GetIncomingAttacks": 1,
    19611974    "GetNeededResources": 1,
    19621975    "GetNotifications": 1,
    19631976    "GetTimeNotifications": 1,
     1977    "GetProductionQueueEnabled": 1,
    19641978
    19651979    "GetAvailableFormations": 1,
    19661980    "GetFormationRequirements": 1,
    19671981    "CanMoveEntsIntoFormation": 1,
    19681982    "IsFormationSelected": 1,
  • binaries/data/mods/public/simulation/components/ProductionQueue.js

    ProductionQueue.prototype.Schema =  
    4040        "</interleave>" +
    4141    "</element>";
    4242
    4343ProductionQueue.prototype.Init = function()
    4444{
     45    this.enabled = true;
    4546    this.nextID = 1;
    4647
    4748    this.queue = [];
    4849    // Queue items are:
    4950    //   {
    ProductionQueue.prototype.Init = functio  
    7677    this.spawnNotified = false;
    7778   
    7879    this.alertRaiser = undefined;
    7980};
    8081
     82ProductionQueue.prototype.GetEnabled = function()
     83{
     84    return this.enabled;
     85};
     86
     87ProductionQueue.prototype.SetEnabled = function(enabled)
     88{
     89    this.enabled = enabled;
     90};
     91
    8192ProductionQueue.prototype.PutUnderAlert = function(raiser)
    8293{
    8394    this.alertRaiser = raiser;
    8495};
    8596
    ProductionQueue.prototype.IsTechnologyRe  
    258269ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadata)
    259270{
    260271    // TODO: there should probably be a limit on the number of queued batches
    261272    // TODO: there should be a way for the GUI to determine whether it's going
    262273    // to be possible to add a batch (based on resource costs and length limits)
     274    if (!this.enabled)
     275        return;
    263276    var cmpPlayer = QueryOwnerInterface(this.entity);
    264277
    265278    if (this.queue.length < MAX_QUEUE_SIZE)
    266279    {
    267280       
    ProductionQueue.prototype.SpawnUnits = f  
    656669            "entities": createdEnts,
    657670            "owner": cmpOwnership.GetOwner(),
    658671            "metadata": metadata,
    659672        });
    660673       
    661         if(this.alertRaiser && spawnedEnts.length > 0)
     674        if (this.alertRaiser && spawnedEnts.length > 0)
    662675        {
    663676            var cmpAlertRaiser = Engine.QueryInterface(this.alertRaiser, IID_AlertRaiser);
    664             if(cmpAlertRaiser)
     677            if (cmpAlertRaiser)
    665678                cmpAlertRaiser.UpdateUnits(spawnedEnts);
    666679        }
    667680    }
    668681   
    669682    return createdEnts.length;
  • binaries/data/mods/public/simulation/components/tests/test_Attack.js

     
     1Engine.LoadHelperScript("Player.js");
     2Engine.LoadHelperScript("ValueModification.js");
     3Engine.LoadComponentScript("interfaces/Auras.js");
     4Engine.LoadComponentScript("interfaces/AuraManager.js");
     5Engine.LoadComponentScript("interfaces/Capturable.js");
     6Engine.LoadComponentScript("interfaces/TechnologyManager.js");
     7Engine.LoadComponentScript("interfaces/Formation.js");
     8Engine.LoadComponentScript("Formation.js");
     9Engine.LoadComponentScript("interfaces/Attack.js");
     10Engine.LoadComponentScript("Attack.js");
     11
     12function TS_ASSERT_EQUAL_OBJECTS(obj1, obj2)
     13{
     14    TS_ASSERT_EQUALS(typeof obj1, typeof obj2);
     15
     16    if (typeof obj1 == "object")
     17    {
     18        TS_ASSERT_EQUALS(Object.keys(obj1).toString(), Object.keys(obj2).toString());
     19
     20        for (let prop in obj1)
     21            TS_ASSERT_EQUAL_OBJECTS(obj1[prop], obj2[prop]);
     22    }
     23    else
     24        TS_ASSERT_EQUALS(obj1, obj2);
     25}
     26
     27// Initialize player
     28{
     29    let playerEnt1 = 5;
     30
     31    AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
     32        "GetPlayerByID": () => playerEnt1
     33    });
     34
     35    AddMock(playerEnt1, IID_Player, {
     36        "GetPlayerID": () => 1
     37    });
     38}
     39
     40// Create attacker
     41let entityID = 903;
     42let attacker = ++entityID;
     43
     44AddMock(attacker, IID_Position, {
     45    "IsInWorld": () => true,
     46    "GetHeightOffset": () => 5
     47});
     48
     49AddMock(attacker, IID_Ownership, {
     50    "GetOwner": owner => 1
     51});
     52
     53let cmpAttack = ConstructComponent(attacker, "Attack", {
     54    "Melee" : {
     55        "Hack": 11,
     56        "Pierce": 5,
     57        "Crush": 0,
     58        "MinRange": 3,
     59        "MaxRange": 5,
     60        "PreferredClasses": {
     61            "_string": "Female"
     62        },
     63        "RestrictedClasses": {
     64            "_string": "Elephant Archer"
     65        }
     66    },
     67    "Ranged" : {
     68        "Hack": 0,
     69        "Pierce": 10,
     70        "Crush": 0,
     71        "MinRange": 10,
     72        "MaxRange": 80,
     73        "PrepareTime": 300,
     74        "RepeatTime": 500,
     75        "PreferredClasses": {
     76            "_string": "Archer"
     77        },
     78        "RestrictedClasses": {
     79            "_string": "Elephant"
     80        }
     81    },
     82    "Capture" : {
     83        "Value": 8,
     84        "MaxRange": 10,
     85    },
     86    "Slaughter": {}
     87});
     88
     89TS_ASSERT_EQUAL_OBJECTS(cmpAttack.GetAttackTypes(), ["Melee", "Ranged", "Capture"]);
     90TS_ASSERT_EQUAL_OBJECTS(cmpAttack.GetPreferredClasses("Melee"), ["Female"]);
     91TS_ASSERT_EQUAL_OBJECTS(cmpAttack.GetRestrictedClasses("Melee"), ["Elephant", "Archer"]);
     92TS_ASSERT_EQUAL_OBJECTS(cmpAttack.GetFullAttackRange(), { "min": 0, "max": 80 });
     93TS_ASSERT_EQUAL_OBJECTS(cmpAttack.GetAttackStrengths("Capture"), { "value": 8 });
     94
     95TS_ASSERT_EQUAL_OBJECTS(cmpAttack.GetAttackStrengths("Ranged"), {
     96    "hack": 0,
     97    "pierce": 10,
     98    "crush": 0,
     99});
     100
     101TS_ASSERT_EQUAL_OBJECTS(cmpAttack.GetTimers("Ranged"), {
     102    "prepare": 300,
     103    "repeat": 500,
     104    "recharge": 200
     105});
     106
     107TS_ASSERT_EQUAL_OBJECTS(cmpAttack.GetTimers("Capture"), {
     108    "prepare": 0,
     109    "repeat": 1000,
     110    "recharge": 1000
     111});
     112
     113// Create elephant to ensure CanAttack takes restricted classes into account and rejects
     114{
     115    let innocentElephant = ++entityID;
     116
     117    AddMock(innocentElephant, IID_Identity, {
     118        "GetClassesList": () => ["Elephant"]
     119    });
     120
     121    AddMock(innocentElephant, IID_Position, {
     122        "IsInWorld": () => true,
     123        "GetHeightOffset": () => 8
     124    });
     125
     126    TS_ASSERT_EQUALS(cmpAttack.CanAttack(innocentElephant), false);
     127
     128    cmpAttack.SetEnabled(true);
     129    TS_ASSERT_EQUALS(cmpAttack.CanAttack(innocentElephant), false);
     130}
     131
     132// Create woman to test SetEnabled, GetEnabled, CanAttack and GetBestAttackAgainst
     133{
     134    let helplessWoman = ++entityID;
     135
     136    AddMock(helplessWoman, IID_Identity, {
     137        "GetClassesList": () => ["Female"]
     138    });
     139
     140    AddMock(helplessWoman, IID_Position, {
     141        "IsInWorld": () => true,
     142        "GetHeightOffset": () => 2
     143    });
     144
     145    TS_ASSERT_EQUALS(cmpAttack.GetEnabled(helplessWoman), true);
     146    TS_ASSERT_EQUALS(cmpAttack.CanAttack(helplessWoman), true);
     147    TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(helplessWoman), "Melee");
     148
     149    for (let value of [true, false, true])
     150    {
     151        cmpAttack.SetEnabled(value);
     152        TS_ASSERT_EQUALS(cmpAttack.GetEnabled(helplessWoman), value);
     153        TS_ASSERT_EQUALS(cmpAttack.CanAttack(helplessWoman), value);
     154    }
     155}
     156
     157// Create archer to test CanAttack and GetBestAttackAgainst
     158{
     159    let archer = ++entityID;
     160
     161    AddMock(archer, IID_Identity, {
     162        "GetClassesList": () => ["Archer"]
     163    });
     164
     165    AddMock(archer, IID_Position, {
     166        "IsInWorld": () => true,
     167        "GetHeightOffset": () => 4
     168    });
     169
     170    TS_ASSERT_EQUALS(cmpAttack.CanAttack(archer), true);
     171    TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(archer), "Ranged");
     172}
     173
     174// Create building to test CanAttack and GetBestAttackAgainst with capturing
     175{
     176    let darkFortress = ++entityID;
     177
     178    AddMock(darkFortress, IID_Identity, {
     179        "GetClassesList": () => ["Structure"]
     180    });
     181
     182    AddMock(darkFortress, IID_Position, {
     183        "IsInWorld": () => true,
     184        "GetHeightOffset": () => 4
     185    });
     186
     187    AddMock(darkFortress, IID_Capturable, {
     188        "CanCapture": playerID => {
     189            TS_ASSERT_EQUALS(playerID, 1);
     190            return true;
     191        }
     192    });
     193
     194    TS_ASSERT_EQUALS(cmpAttack.CanAttack(darkFortress), true);
     195    TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(darkFortress, true), "Capture");
     196}
     197
     198// Slaughter sheep
     199{
     200    let sheep = ++entityID;
     201
     202    AddMock(sheep, IID_Identity, {
     203        "GetClassesList": () => ["Domestic"]
     204    });
     205
     206    AddMock(sheep, IID_Position, {
     207        "IsInWorld": () => true,
     208        "GetHeightOffset": () => 2
     209    });
     210
     211    TS_ASSERT_EQUALS(cmpAttack.CanAttack(sheep), true);
     212    TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(sheep, true), "Slaughter");
     213}
  • binaries/data/mods/public/simulation/components/tests/test_Auras.js

    Property changes on: binaries/data/mods/public/simulation/components/tests/test_Attack.js
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
    AddMock(SYSTEM_ENTITY, IID_RangeManager,  
    2121    },
    2222    EnableActiveQuery: function(id) { },
    2323    ResetActiveQuery: function(id) { if (mode == 0) return []; else return [enemy]; },
    2424    DisableActiveQuery: function(id) { },
    2525    GetEntityFlagMask: function(identifier) { },
     26    "DestroyActiveQuery": () => {}
    2627});
    2728
    2829AddMock(SYSTEM_ENTITY, IID_DataTemplateManager, {
    2930    GetAuraTemplate: function(name) {
    3031        if (name == "test1")
    var auras = ConstructComponent(auraEnt,  
    7172
    7273// send the rangeManager message
    7374auras.OnRangeUpdate({"tag": 1, "added": [30], "removed": []});
    7475
    7576TS_ASSERT_EQUALS(ApplyValueModificationsToEntity("Component/Value", 1, targetEnt), 2);
     77TS_ASSERT_EQUALS(auras.GetEnabled(), true);
     78
     79auras.SetEnabled(false)
     80TS_ASSERT_EQUALS(auras.GetEnabled(), false);
     81
     82auras.SetEnabled(true)
     83TS_ASSERT_EQUALS(auras.GetEnabled(), true);
  • binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js

     
     1Engine.LoadHelperScript("Player.js");
     2Engine.LoadComponentScript("interfaces/GarrisonHolder.js");
     3Engine.LoadComponentScript("interfaces/Health.js");
     4Engine.LoadComponentScript("GarrisonHolder.js");
     5Engine.LoadComponentScript("Identity.js");
     6
     7let garrisonEnt = 15;
     8let unitEnt = 33;
     9let entHP = 1000;
     10
     11AddMock(garrisonEnt, IID_Health, {
     12    "GetHitpoints": () => entHP,
     13    "Decrease": hp => {
     14        entHP = Math.max(entHP - hp, 0);
     15    },
     16});
     17
     18let cmpGarrisonHolder = ConstructComponent(garrisonEnt, "GarrisonHolder", {
     19    "LoadingRange": "2.0",
     20    "Max": "20",
     21    "List": "Support"
     22});
     23
     24TS_ASSERT_EQUALS(cmpGarrisonHolder.GetGarrisonedEntitiesCount(), 0);
     25TS_ASSERT_EQUALS(cmpGarrisonHolder.entities.length, 0);
     26TS_ASSERT_EQUALS(cmpGarrisonHolder.visibleGarrisonPoints.length, 0);
     27TS_ASSERT_EQUALS(+cmpGarrisonHolder.template.Max, 20);
     28TS_ASSERT_EQUALS(cmpGarrisonHolder.GetLoadingRange().max, 2.0);
  • binaries/data/mods/public/simulation/components/tests/test_ProductionQueue.js

    Property changes on: binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
     1Engine.LoadHelperScript("Player.js");
     2Engine.LoadHelperScript("ValueModification.js");
     3Engine.LoadComponentScript("interfaces/ProductionQueue.js");
     4Engine.LoadComponentScript("interfaces/TechnologyManager.js");
     5Engine.LoadComponentScript("interfaces/Player.js");
     6Engine.LoadComponentScript("ProductionQueue.js");
     7Engine.LoadComponentScript("TechnologyManager.js");
     8Engine.LoadComponentScript("Player.js");
     9
     10let playerEntity = 1;
     11let productionEnt = 31;
     12let trainTemplate = "units/athen_infantry_spearman_b";
     13
     14AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
     15    "GetPlayerByID": id => playerEntity,
     16    "GetCheatTimeMultiplier": () => 20,
     17});
     18
     19AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
     20    "GetTemplate": trainTemplate => trainTemplate,
     21});
     22
     23let cmpProductionQueue = ConstructComponent(productionEnt, "ProductionQueue", {
     24    "BatchTimeModifier": "0.7",
     25    "Entities": "units/athen_infantry_spearman_b"
     26});
     27
     28TS_ASSERT_EQUALS(cmpProductionQueue.GetEnabled(), true);
     29
     30cmpProductionQueue.SetEnabled(false);
     31TS_ASSERT_EQUALS(cmpProductionQueue.GetEnabled(), false);
     32
     33cmpProductionQueue.SetEnabled(true);
     34TS_ASSERT_EQUALS(cmpProductionQueue.GetEnabled(), true);
     35
     36cmpProductionQueue.PutUnderAlert(productionEnt);
     37TS_ASSERT_EQUALS(cmpProductionQueue.alertRaiser, productionEnt);
     38
     39cmpProductionQueue.ResetAlert();
     40TS_ASSERT_EQUALS(cmpProductionQueue.alertRaiser, undefined);
     41TS_ASSERT_EQUALS(cmpProductionQueue.GetQueue().length, 0);