Ticket #2160: Regicide_v0.4.patch

File Regicide_v0.4.patch, 9.1 KB (added by elexis, 8 years ago)

Rewrote the loops to address the remarks

  • binaries/data/mods/public/globalscripts/utility.js

    function clone(o)  
    1414        return o;
    1515    for (let key in o)
    1616        r[key] = clone(o[key]);
    1717    return r;
    1818}
     19
     20/**
     21 * "Inside-out" implementation of Fisher-Yates shuffle
     22 */
     23function shuffleArray(source)
     24{
     25    if (!source.length)
     26        return [];
     27
     28    let result = [source[0]];
     29    for (let i = 1; i < source.length; ++i)
     30    {
     31        let j = Math.floor(Math.random() * i);
     32        result[i] = result[j];
     33        result[j] = source[i];
     34    }
     35    return result;
     36}
  • binaries/data/mods/public/maps/random/rmgen/library.js

    const MAX_MAP_SIZE = 512;  
    99const MAP_BORDER_WIDTH = 3;
    1010const FALLBACK_CIV = "athen";
    1111/**
    1212 * Constants needed for heightmap_manipulation.js
    1313 */
    14 const MAX_HEIGHT_RANGE = 0xFFFF / HEIGHT_UNITS_PER_METRE // Engine limit, Roughly 700 meters
     14const MAX_HEIGHT_RANGE = 0xFFFF / HEIGHT_UNITS_PER_METRE; // Engine limit, Roughly 700 meters
    1515const MIN_HEIGHT = - SEA_LEVEL;
    1616const MAX_HEIGHT = MAX_HEIGHT_RANGE - SEA_LEVEL;
    1717// Default angle for buildings
    1818const BUILDING_ORIENTATION = - PI / 4;
    1919
    function min(a, b)  
    9090{
    9191    return a < b ? a : b;
    9292}
    9393
    9494/**
    95  * "Inside-out" implementation of Fisher-Yates shuffle
    96  */
    97 function shuffleArray(source)
    98 {
    99     if (!source.length)
    100         return [];
    101 
    102     let result = [source[0]];
    103     for (let i = 1; i < source.length; ++i)
    104     {
    105         let j = randInt(0, i);
    106         result[i] = result[j];
    107         result[j] = source[i];
    108     }
    109     return result;
    110 }
    111 
    112 /**
    11395 * Retries the given function with those arguments as often as specified.
    11496 */
    11597function retryPlacing(placeFunc, placeArgs, retryFactor, amount, getResult)
    11698{
    11799    let maxFail = amount * retryFactor;
  • binaries/data/mods/public/maps/scripts/Regicide.js

     
     1Trigger.prototype.CheckRegicideDefeat = function(data)
     2{
     3    if (data.entity == this.heroes[data.from])
     4        TriggerHelper.DefeatPlayer(data.from);
     5};
     6
     7Trigger.prototype.InitRegicideGame = function(msg)
     8{
     9    let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
     10
     11    // Get unique list of chosen civs
     12    let civs = [];
     13    let playersCivs = [];
     14    for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID)
     15    {
     16        let civ = QueryPlayerIDInterface(playerID).GetCiv();
     17        playersCivs[playerID] = civ;
     18
     19        if (civs.indexOf(civ) == -1)
     20            civs.push(civ);
     21    }
     22
     23    // Get all hero templates of these civs
     24    let heroTemplates = {};
     25    for (let templateName of cmpTemplateManager.FindAllTemplates(false))
     26    {
     27        if (templateName.substring(0,6) != "units/")
     28            continue;
     29
     30        let identity = cmpTemplateManager.GetTemplate(templateName).Identity;
     31        let classes = GetIdentityClasses(identity);
     32
     33        if (classes.indexOf("Hero") == -1)
     34            continue;
     35
     36        if (!heroTemplates[identity.Civ])
     37            heroTemplates[identity.Civ] = [];
     38
     39        if (heroTemplates[identity.Civ].indexOf(templateName) == -1)
     40            heroTemplates[identity.Civ].push({
     41                "templateName": templateName,
     42                "classes": classes
     43            });
     44    }
     45
     46    // Sort spawn points by preference
     47    let getPreference = entity => {
     48        let cmpIdentity = Engine.QueryInterface(entity, IID_Identity);
     49        let classes = cmpIdentity.GetClassesList();
     50
     51        if (classes.indexOf("CivilCentre") != -1)
     52            return 3;
     53
     54        if (classes.indexOf("Structure") != -1)
     55            return 2;
     56
     57        if (classes.indexOf("Ship") != -1)
     58            return 1;
     59
     60        return 0;
     61    };
     62
     63    let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
     64    for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID)
     65    {
     66        let spawnPoints = cmpRangeManager.GetEntitiesByPlayer(playerID).sort((entity1, entity2) =>
     67            getPreference(entity2) - getPreference(entity1));
     68
     69        this.heroes[playerID] = this.SpawnHero(playerID, heroTemplates[playersCivs[playerID]], spawnPoints);
     70    }
     71};
     72
     73/**
     74 * Spawn a random hero at one of the given locations (which are checked in order).
     75 * Garrison it if the location is a ship.
     76 *
     77 * @param spawnPoints - entity IDs at which to spawn
     78 */
     79Trigger.prototype.SpawnHero = function(playerID, heroTemplates, spawnPoints)
     80{
     81    for (let heroTemplate of shuffleArray(heroTemplates))
     82        for (let spawnPoint of spawnPoints)
     83        {
     84            let cmpPosition = Engine.QueryInterface(spawnPoint, IID_Position);
     85            if (!cmpPosition || !cmpPosition.IsInWorld())
     86                continue;
     87
     88            let isShip = TriggerHelper.EntityHasClass(spawnPoint, "Ship");
     89            if (isShip)
     90            {
     91                let cmpGarrisonHolder = Engine.QueryInterface(spawnPoint, IID_GarrisonHolder);
     92                if (cmpGarrisonHolder.IsFull() ||
     93                    !MatchesClassList(heroTemplate.classes, cmpGarrisonHolder.GetAllowedClasses()))
     94                    continue;
     95            }
     96
     97            let hero = TriggerHelper.SpawnUnits(spawnPoint, heroTemplate.templateName, 1, playerID);
     98            if (!hero.length)
     99                continue;
     100
     101            hero = hero[0];
     102
     103            if (isShip)
     104            {
     105                let cmpUnitAI = Engine.QueryInterface(hero, IID_UnitAI);
     106                cmpUnitAI.Garrison(spawnPoint);
     107            }
     108
     109            return hero;
     110        }
     111
     112    error("Couldn't spawn hero for player " + playerID);
     113    return undefined;
     114};
     115
     116let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
     117cmpTrigger.heroes = []; // TODO: what if gaia gets a hero?
     118cmpTrigger.DoAfterDelay(0, "InitRegicideGame", {});
     119
     120cmpTrigger.RegisterTrigger("OnOwnershipChanged", "CheckRegicideDefeat", { "enabled": true });
  • binaries/data/mods/public/maps/scripts/TriggerHelper.js

    TriggerHelper.GetOwner = function(ent)  
    2020
    2121    return -1;
    2222};
    2323
    2424/**
    25  * Can be used to "force" a building to spawn a group of entities.
    26  * Only works for buildings that can already train units.
     25 * Can be used to "force" a building/unit to spawn a group of entities.
     26 * A default position is returned if no valid position is found.
    2727 * @param source Entity id of the point where they will be spawned from
    2828 * @param template Name of the template
    2929 * @param count Number of units to spawn
    3030 * @param owner Player id of the owner of the new units. By default, the owner
    3131 * of the source entity.
  • binaries/data/mods/public/simulation/data/settings/victory_conditions/regicide.json

     
     1{
     2    "TranslatedKeys": ["Title", "Description"],
     3    "Data":
     4    {
     5        "Title": "Regicide",
     6        "Description": "Keep your Hero alive to win",
     7        "Scripts":
     8        [
     9            "scripts/TriggerHelper.js",
     10            "scripts/ConquestCommon.js",
     11            "scripts/Conquest.js",
     12            "scripts/Regicide.js"
     13        ]
     14    }
     15}
  • binaries/data/mods/public/simulation/templates/units/maur_ship_trireme.xml

     
    66  <Footprint>
    77    <Square width="17.0" depth="45.0"/>
    88    <Height>8.0</Height>
    99  </Footprint>
    1010  <GarrisonHolder>
    11     <Max>40</Max>
     11    <Max>15</Max>
    1212  </GarrisonHolder>
    1313  <Health>
    1414    <Max op="add">200</Max>
    1515  </Health>
    1616  <Identity>
  • source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp

     
    1 /* Copyright (C) 2015 Wildfire Games.
     1/* Copyright (C) 2016 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
    void MapSettingsControl::CreateWidgets()  
    146146    gameTypes.Add(_T("conquest"));
    147147    gameTypes.Add(_T("conquest_structures"));
    148148    gameTypes.Add(_T("conquest_units"));
    149149    gameTypes.Add(_T("wonder"));
    150150    gameTypes.Add(_T("endless"));
     151    gameTypes.Add(_T("regicide"));
    151152
    152153    wxFlexGridSizer* gridSizer = new wxFlexGridSizer(2, 5, 5);
    153154    gridSizer->AddGrowableCol(1);
    154155    // TODO: have preview selector tool?
    155156    gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Preview")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));