Ticket #3747: 3747+3801_modifiers.patch

File 3747+3801_modifiers.patch, 16.8 KB (added by s0600204, 8 years ago)

Rebased patch, as requested. Applies modifiers from promotion and civbonuses.

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

    diff --git a/binaries/data/mods/public/globalscripts/Technologies.js b/binaries/data/mods/public/globalscripts/Technologies.js
    index b6783e2..b5fab79 100644
    a b  
    44 * any global state, but each context should do its own caching as needed.
    55 * Also it cannot directly access the simulation and requires data passed to it.
    66 */
    7  
     7
     8/**
     9 * Returns the name of the technology defining the bonus for a given rank
     10 */
     11const g_UnitBonusTechNameSuffix = "_unit_bonus";
     12function GetUnitBonusTechName(rank = "basic")
     13{
     14    return rank.toLowerCase() + g_UnitBonusTechNameSuffix;
     15}
     16
    817/**
    918 * Returns modified property value modified by the applicable tech
    1019 * modifications.
    1120 *
    1221 * @param currentTechModifications Object with mapping of property names to
    1322 * modification arrays, retrieved from the intended player's TechnologyManager.
    14  * @param classes Array contianing the class list of the template.
     23 * @param classes Array containing the class list of the template.
    1524 * @param propertyName String encoding the name of the value.
    1625 * @param propertyValue Number storing the original value. Can also be
    1726 * non-numberic, but then only "replace" techs can be supported.
    function GetTechModifiedProperty(currentTechModifications, classes, propertyName  
    4453}
    4554
    4655/**
     56 * Derives modifications (to be applied to entities) from a given technology
     57 *
     58 * @param techTemplate The technology template to derive the modifications from.
     59 * @return Object containing the relevant modifications.
     60 */
     61function DeriveModificationsFromTech(techTemplate)
     62{
     63    if (!techTemplate.modifications)
     64        return {};
     65
     66    let techMods = {};
     67    let techAffects = [];
     68    if (techTemplate.affects && techTemplate.affects.length > 0)
     69        for (let affected of techTemplate.affects)
     70            techAffects.push(affected.split(/\s+/));
     71    else
     72        techAffects.push([]);
     73
     74    for (let mod of techTemplate.modifications)
     75    {
     76        let affects = techAffects.slice();
     77        if (mod.affects)
     78        {
     79            let specAffects = mod.affects.split(/\s+/);
     80            for (let a in affects)
     81                affects[a] = affects[a].concat(specAffects);
     82        }
     83
     84        let newModifier = {
     85            "affects": affects
     86        };
     87        for (let idx in mod)
     88            if (idx !== "value" && idx !== "affects")
     89                newModifier[idx] = mod[idx];
     90
     91        if (!techMods[mod.value])
     92            techMods[mod.value] = [];
     93        techMods[mod.value].push(newModifier);
     94    }
     95    return techMods;
     96}
     97
     98/**
    4799 * Returns whether the given modification applies to the entity containing the given class list
    48100 */
    49101function DoesModificationApply(modification, classes)
  • binaries/data/mods/public/globalscripts/Templates.js

    diff --git a/binaries/data/mods/public/globalscripts/Templates.js b/binaries/data/mods/public/globalscripts/Templates.js
    index e50cbe4..cb55e91 100644
    a b function GetTemplateDataHelper(template, player, auraTemplates)  
    7979    var func;
    8080    if (player)
    8181        func = ApplyValueModificationsToTemplate;
     82    else if (g_Modifiers)
     83        func = function(property, val, c, template) {
     84            return GetTechModifiedProperty(g_Modifiers, GetIdentityClasses(template.Identity), property, val);
     85        }
    8286    else
    8387        func = function(a, val, c, d) { return val; }
    8488
  • binaries/data/mods/public/gui/structree/load.js

    diff --git a/binaries/data/mods/public/gui/structree/load.js b/binaries/data/mods/public/gui/structree/load.js
    index dee89d2..d62b96a 100644
    a b function getGatherRates(templateName)  
    3535    return rates;
    3636}
    3737
     38function preloadUnit(templateName)
     39{
     40    if (!Engine.TemplateExists(templateName))
     41        return;
     42    let template = loadTemplate(templateName);
     43
     44    if (template.Builder && template.Builder.Entities._string)
     45        for (let build of template.Builder.Entities._string.split(" "))
     46        {
     47            build = build.replace("{civ}", g_SelectedCiv);
     48            if (g_Lists.structures.indexOf(build) < 0)
     49                g_Lists.structures.push(build);
     50        }
     51
     52    if (template.ProductionQueue)
     53    {
     54        if (template.ProductionQueue.Entities)
     55            for (let build of template.ProductionQueue.Entities._string.split(" "))
     56            {
     57                build = build.replace("{civ}", g_SelectedCiv);
     58                if (g_Lists.units.indexOf(build) === -1)
     59                    g_Lists.units.push(build);
     60            }
     61
     62        if (template.ProductionQueue.Technologies)
     63            for (let research of template.ProductionQueue.Technologies._string.split(" "))
     64                if (g_Lists.techs.indexOf(research) < 0)
     65                    g_Lists.techs.push(research);
     66    }
     67
     68    if (template.Identity.Rank)
     69    {
     70        let promotionTech = GetUnitBonusTechName(template.Identity.Rank);
     71        if (g_Lists.modifiers.indexOf(promotionTech) < 0)
     72            g_Lists.modifiers.push(promotionTech);
     73
     74        // recurse through promotions to get all techs
     75        if (template.Promotion)
     76            preloadUnit(template.Promotion.Entity);
     77    }
     78}
     79
    3880function loadUnit(templateName)
    3981{
    4082    if (!Engine.TemplateExists(templateName))
    function loadUnit(templateName)  
    61103        {
    62104            unit.production.units = [];
    63105            for (let build of template.ProductionQueue.Entities._string.split(" "))
    64             {
    65                 build = build.replace("{civ}", g_SelectedCiv);
    66                 unit.production.units.push(build);
    67                 if (g_Lists.units.indexOf(build) < 0)
    68                     g_Lists.units.push(build);
    69             }
     106                unit.production.units.push(build.replace("{civ}", g_SelectedCiv));
    70107        }
    71108        if (template.ProductionQueue.Technologies)
    72109        {
    73110            unit.production.techs = [];
    74111            for (let research of template.ProductionQueue.Technologies._string.split(" "))
    75             {
    76112                unit.production.techs.push(research);
    77                 if (g_Lists.techs.indexOf(research) < 0)
    78                     g_Lists.techs.push(research);
    79             }
    80113        }
    81114    }
    82115
    function loadUnit(templateName)  
    98131    return unit;
    99132}
    100133
     134function preloadStructure(templateName)
     135{
     136    let template = loadTemplate(templateName);
     137
     138    if (template.ProductionQueue && template.ProductionQueue.Entities && template.ProductionQueue.Entities._string)
     139        for (let build of template.ProductionQueue.Entities._string.split(" "))
     140        {
     141            build = build.replace("{civ}", g_SelectedCiv);
     142            if (g_Lists.units.indexOf(build) < 0)
     143                g_Lists.units.push(build);
     144        }
     145}
     146
    101147function loadStructure(templateName)
    102148{
    103149    var template = loadTemplate(templateName);
    function loadStructure(templateName)  
    124170            {
    125171                build = build.replace("{civ}", g_SelectedCiv);
    126172                structure.production.units.push(build);
    127                 if (g_Lists.units.indexOf(build) < 0)
    128                     g_Lists.units.push(build);
    129173            }
    130174
    131175        if (template.ProductionQueue.Technologies && template.ProductionQueue.Technologies._string)
    function loadPhase(phaseCode)  
    261305    return phase;
    262306}
    263307
     308function loadModifierTech(modCode)
     309{
     310    if (!Engine.FileExists("simulation/data/technologies/"+modCode+".json"))
     311        return {};
     312    return loadTechData(modCode);
     313}
     314
    264315function loadTechnologyPair(pairCode)
    265316{
    266317    var pairInfo = loadTechData(pairCode);
  • binaries/data/mods/public/gui/structree/structree.js

    diff --git a/binaries/data/mods/public/gui/structree/structree.js b/binaries/data/mods/public/gui/structree/structree.js
    index 65bfd9e..3bfecdd 100644
    a b var g_ParsedData = {  
    77
    88var g_Lists = {};
    99var g_CivData = {};
     10var g_Modifiers = {};
    1011var g_SelectedCiv = "";
    1112var g_CallbackSet = false;
    1213
    function selectCiv(civCode)  
    5859    g_Lists = {
    5960        "units": [],
    6061        "structures": [],
    61         "techs": []
     62        "techs": [],
     63        "modifiers": []
    6264    };
     65    g_Modifiers = {};
     66
     67    // Get initial modifier techs
     68    if (g_CivData[g_SelectedCiv].CivBonusTechs)
     69        g_Lists.modifiers = g_CivData[g_SelectedCiv].CivBonusTechs;
    6370
    6471    // get initial units
    65     var startStructs = [];
     72    let startStructs = [];
    6673    for (let entity of g_CivData[civCode].StartEntities)
    6774    {
    6875        if (entity.Template.slice(0, 5) == "units")
    function selectCiv(civCode)  
    7481        }
    7582    }
    7683
    77     // Load units and structures
    78     var unitCount = 0;
     84    // Compile lists of units and structures belonging to this civ
     85    let unitCount = 0;
    7986    do
    8087    {
    8188        for (let u of g_Lists.units)
    82             if (!g_ParsedData.units[u])
    83                 g_ParsedData.units[u] = loadUnit(u);
     89            preloadUnit(u);
    8490
    8591        unitCount = g_Lists.units.length;
    8692
    8793        for (let s of g_Lists.structures)
    88             if (!g_ParsedData.structures[s])
    89                 g_ParsedData.structures[s] = loadStructure(s);
     94            preloadStructure(s);
    9095
    9196    } while (unitCount < g_Lists.units.length);
    9297
     98
     99    // Load modifiers
     100    for (let modCode of g_Lists.modifiers)
     101    {
     102        let modTech = loadModifierTech(modCode);
     103        let derivedModifiers = DeriveModificationsFromTech(modTech);
     104
     105        for (let modPath in derivedModifiers)
     106        {
     107            if (!g_Modifiers[modPath])
     108                g_Modifiers[modPath] = [];
     109            g_Modifiers[modPath] = g_Modifiers[modPath].concat(derivedModifiers[modPath]);
     110        }
     111    }
     112
     113    // Properly load units and structures, now we have modifiers
     114    for (let u of g_Lists.units)
     115        if (!g_ParsedData.units[u])
     116            g_ParsedData.units[u] = loadUnit(u);
     117
     118    for (let s of g_Lists.structures)
     119        if (!g_ParsedData.structures[s])
     120            g_ParsedData.structures[s] = loadStructure(s);
     121
    93122    // Load technologies
    94     var techPairs = {};
     123    let techPairs = {};
    95124    for (let techcode of g_Lists.techs)
    96125    {
    97126        let realcode = depath(techcode);
  • binaries/data/mods/public/simulation/components/TechnologyManager.js

    diff --git a/binaries/data/mods/public/simulation/components/TechnologyManager.js b/binaries/data/mods/public/simulation/components/TechnologyManager.js
    index f1f9cc7..ad8ff00 100644
    a b TechnologyManager.prototype.ResearchTechnology = function(tech)  
    267267    // store the modifications in an easy to access structure
    268268    if (template.modifications)
    269269    {
    270         var affects = [];
    271         if (template.affects && template.affects.length > 0)
     270        let derivedModifiers = DeriveModificationsFromTech(template);
     271        for (let modifierPath in derivedModifiers)
    272272        {
    273             for (let affect of template.affects)
    274             {
    275                 // Put the list of classes into an array for convenient access
    276                 affects.push(affect.split(/\s+/));
    277             }
    278         }
    279         else
    280         {
    281             affects.push([]);
    282         }
    283 
    284         // We add an item to this.modifications for every modification in the template.modifications array
    285         for (var i in template.modifications)
    286         {
    287             var modification = template.modifications[i];
    288             if (!this.modifications[modification.value])
    289                 this.modifications[modification.value] = [];
    290            
    291             var modAffects = affects.slice();
    292             if (modification.affects)
    293             {
    294                 var extraAffects = modification.affects.split(/\s+/);
    295                 for (var a in modAffects)
    296                     modAffects[a] = modAffects[a].concat(extraAffects);
    297             }
    298 
    299             var mod = {"affects": modAffects};
    300 
    301             // copy the modification data into our new data structure
    302             for (var j in modification)
    303                 if (j !== "value" && j !== "affects")
    304                     mod[j] = modification[j];
     273            if (!this.modifications[modifierPath])
     274                this.modifications[modifierPath] = [];
     275            this.modifications[modifierPath] = this.modifications[modifierPath].concat(derivedModifiers[modifierPath]);
    305276
    306             this.modifications[modification.value].push(mod);
    307             var component = modification.value.split("/")[0];
     277            let component = modifierPath.split("/")[0];
    308278            if (!modifiedComponents[component])
    309279                modifiedComponents[component] = [];
    310             modifiedComponents[component].push(modification.value);
    311             this.modificationCache[modification.value] = {};
     280            modifiedComponents[component].push(modifierPath);
     281            this.modificationCache[modifierPath] = {};
    312282        }
    313283    }
    314284
  • binaries/data/mods/public/simulation/data/civs/athen.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/athen.json b/binaries/data/mods/public/simulation/data/civs/athen.json
    index 3ce6b26..58823d9 100644
    a b  
    7979            "Description":"Ships construct 25% faster."
    8080        }
    8181    ],
     82    "CivBonusTechs":
     83    [
     84        "hellenes/civbonus_hellenic_architecture"
     85    ],
    8286    "Structures":
    8387    [
    8488        {
  • binaries/data/mods/public/simulation/data/civs/brit.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/brit.json b/binaries/data/mods/public/simulation/data/civs/brit.json
    index b8b12fe..8356c65 100644
    a b  
    7575            "Description": "Bonus to tech speed."
    7676        }
    7777    ],
     78    "CivBonusTechs":
     79    [
     80        "celts/civbonus_celts_wooden_struct"
     81    ],
    7882    "Structures":
    7983    [
    8084        {
  • binaries/data/mods/public/simulation/data/civs/cart.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/cart.json b/binaries/data/mods/public/simulation/data/civs/cart.json
    index c6e9efb..16c7212 100644
    a b  
    7373            "Description": "+33% trade profit international routes."
    7474        }
    7575    ],
     76    "CivBonusTechs":
     77    [
     78        "carthaginians/civbonus_triple_walls"
     79    ],
    7680    "Structures":
    7781    [
    7882        {
  • binaries/data/mods/public/simulation/data/civs/gaul.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/gaul.json b/binaries/data/mods/public/simulation/data/civs/gaul.json
    index 28b4953..6c549f6 100644
    a b  
    7575            "Description": "Bonus to tech speed."
    7676        }
    7777    ],
     78    "CivBonusTechs":
     79    [
     80        "celts/civbonus_celts_wooden_struct"
     81    ],
    7882    "Structures":
    7983    [
    8084        {
  • binaries/data/mods/public/simulation/data/civs/iber.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/iber.json b/binaries/data/mods/public/simulation/data/civs/iber.json
    index 3039a29..65ed169 100644
    a b  
    7373            "Description": "Citizen-soldier infantry skirmishers and cavalry skirmishers -20% cost for allies."
    7474        }
    7575    ],
     76    "CivBonusTechs":
     77    [
     78    ],
    7679    "Structures":
    7780    [
    7881        {
  • binaries/data/mods/public/simulation/data/civs/mace.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/mace.json b/binaries/data/mods/public/simulation/data/civs/mace.json
    index 739da20..3b4457b 100644
    a b  
    8484            "Description":"+15% tribute and trade bonus on metal."
    8585        }
    8686    ],
     87    "CivBonusTechs":
     88    [
     89        "hellenes/civbonus_hellenic_architecture"
     90    ],
    8791    "Structures":
    8892    [
    8993        {
  • binaries/data/mods/public/simulation/data/civs/maur.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/maur.json b/binaries/data/mods/public/simulation/data/civs/maur.json
    index 5d230ae..fe4e539 100644
    a b  
    7373            "Description": "Allied Temple techs -50% cost and research time."
    7474        }
    7575    ],
     76    "CivBonusTechs":
     77    [
     78        "mauryans/civbonus_maur_popcap",
     79        "mauryans/wooden_walls"
     80    ],
    7681    "Structures":
    7782    [
    7883        {
  • binaries/data/mods/public/simulation/data/civs/pers.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/pers.json b/binaries/data/mods/public/simulation/data/civs/pers.json
    index a0c8b7e..cd2b263 100644
    a b  
    8383            "Description": "+25% trade profit land routes."
    8484        }
    8585    ],
     86    "CivBonusTechs":
     87    [
     88        "persians/civbonus_pers_popcap"
     89    ],
    8690    "Structures":
    8791    [
    8892        {
  • binaries/data/mods/public/simulation/data/civs/ptol.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/ptol.json b/binaries/data/mods/public/simulation/data/civs/ptol.json
    index a76f7b7..0f0232c 100644
    a b  
    8383            "Description":"All allies automatically gain a slow trickle of food income."
    8484        }
    8585    ],
     86    "CivBonusTechs":
     87    [
     88    ],
    8689    "Structures":
    8790    [
    8891        {
  • binaries/data/mods/public/simulation/data/civs/rome.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/rome.json b/binaries/data/mods/public/simulation/data/civs/rome.json
    index c79048a..ecb5bb9 100644
    a b  
    6868            "Description": "Allied citizen-soldiers gain a +15% attack when in Roman territory."
    6969        }
    7070    ],
     71    "CivBonusTechs":
     72    [
     73    ],
    7174    "Structures":
    7275    [
    7376        {
  • binaries/data/mods/public/simulation/data/civs/sele.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/sele.json b/binaries/data/mods/public/simulation/data/civs/sele.json
    index 39619c1..6447505 100644
    a b  
    8484            "Description":"Allied Civic Centers are 20% cheaper."
    8585        }
    8686    ],
     87    "CivBonusTechs":
     88    [
     89    ],
    8790    "Structures":
    8891    [
    8992        {
  • binaries/data/mods/public/simulation/data/civs/spart.json

    diff --git a/binaries/data/mods/public/simulation/data/civs/spart.json b/binaries/data/mods/public/simulation/data/civs/spart.json
    index fee64cc..7029793 100644
    a b  
    8484            "Description":"Allies can train Spartiates."
    8585        }
    8686    ],
     87    "CivBonusTechs":
     88    [
     89        "hellenes/civbonus_hellenic_architecture",
     90        "hellenes/civpenalty_spart_popcap"
     91    ],
    8792    "Structures":
    8893    [
    8994        {