diff --git a/binaries/data/mods/public/maps/random/danubius_triggers.js b/binaries/data/mods/public/maps/random/danubius_triggers.js index 9b1e81e78d..045dfcb0ad 100644 --- a/binaries/data/mods/public/maps/random/danubius_triggers.js +++ b/binaries/data/mods/public/maps/random/danubius_triggers.js @@ -12,63 +12,63 @@ const showDebugLog = false; -var shipTemplate = "gaul_ship_trireme"; -var siegeTemplate = "gaul_mechanical_siege_ram"; +var shipTemplate = "units/gaul_ship_trireme"; +var siegeTemplate = "units/gaul_mechanical_siege_ram"; var heroTemplates = [ - "gaul_hero_viridomarus", - "gaul_hero_vercingetorix", - "gaul_hero_brennus" + "units/gaul_hero_viridomarus", + "units/gaul_hero_vercingetorix", + "units/gaul_hero_brennus" ]; -var femaleTemplate = "gaul_support_female_citizen"; -var healerTemplate = "gaul_support_healer_b"; +var femaleTemplate = "units/gaul_support_female_citizen"; +var healerTemplate = "units/gaul_support_healer_b"; var citizenInfantryTemplates = [ - "gaul_infantry_javelinist_b", - "gaul_infantry_spearman_b", - "gaul_infantry_slinger_b" + "units/gaul_infantry_javelinist_b", + "units/gaul_infantry_spearman_b", + "units/gaul_infantry_slinger_b" ]; var citizenCavalryTemplates = [ - "gaul_cavalry_javelinist_b", - "gaul_cavalry_swordsman_b" + "units/gaul_cavalry_javelinist_b", + "units/gaul_cavalry_swordsman_b" ]; var citizenTemplates = [...citizenInfantryTemplates, ...citizenCavalryTemplates]; var championInfantryTemplates = [ - "gaul_champion_fanatic", - "gaul_champion_infantry" + "units/gaul_champion_fanatic", + "units/gaul_champion_infantry" ]; var championCavalryTemplates = [ - "gaul_champion_cavalry" + "units/gaul_champion_cavalry" ]; var championTemplates = [...championInfantryTemplates, ...championCavalryTemplates]; var ccDefenders = [ - { "count": 8, "template": "units/" + pickRandom(citizenInfantryTemplates) }, - { "count": 8, "template": "units/" + pickRandom(championInfantryTemplates) }, - { "count": 4, "template": "units/" + pickRandom(championCavalryTemplates) }, - { "count": 4, "template": "units/" + healerTemplate }, - { "count": 5, "template": "units/" + femaleTemplate }, + { "count": 8, "template": pickRandom(citizenInfantryTemplates) }, + { "count": 8, "template": pickRandom(championInfantryTemplates) }, + { "count": 4, "template": pickRandom(championCavalryTemplates) }, + { "count": 4, "template": healerTemplate }, + { "count": 5, "template": femaleTemplate }, { "count": 10, "template": "gaia/fauna_sheep" } ]; var gallicBuildingGarrison = [ { - "buildings": ["House"], - "units": [femaleTemplate, healerTemplate] + "buildingClasses": ["House"], + "unitTemplates": [femaleTemplate, healerTemplate] }, { - "buildings": ["CivCentre", "Temple"], - "units": championTemplates + "buildingClasses": ["CivCentre", "Temple"], + "unitTemplates": championTemplates }, { - "buildings": ["DefenseTower", "Outpost"], - "units": championInfantryTemplates + "buildingClasses": ["DefenseTower", "Outpost"], + "unitTemplates": championInfantryTemplates } ]; @@ -216,64 +216,16 @@ Trigger.prototype.debugLog = function(txt) Math.round(Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime() / 60 / 1000) + "] " + txt + "\n"); }; -/** - * Return a random amount of these templates whose sum is count. - */ -Trigger.prototype.RandomAttackerTemplates = function(templates, count) -{ - let ratios = new Array(templates.length).fill(1).map(i => randFloat(0, 1)); - let ratioSum = ratios.reduce((current, sum) => current + sum, 0); - - let remainder = count; - let templateCounts = {}; - - for (let i in templates) - { - let currentCount = +i == templates.length - 1 ? remainder : Math.round(ratios[i] / ratioSum * count); - if (!currentCount) - continue; - - templateCounts[templates[i]] = currentCount; - remainder -= currentCount; - } - - if (remainder != 0) - warn("Not as many templates as expected: " + count + " vs " + uneval(templateCounts)); - - return templateCounts; -}; - Trigger.prototype.GarrisonAllGallicBuildings = function(gaiaEnts) { this.debugLog("Garrisoning all gallic buildings"); for (let buildingGarrison of gallicBuildingGarrison) - for (let building of buildingGarrison.buildings) - this.SpawnAndGarrisonBuilding(gaiaEnts, building, buildingGarrison.units); -}; - -/** - * Garrisons all targetEnts that match the targetClass with newly spawned entities of the given template. - */ -Trigger.prototype.SpawnAndGarrisonBuilding = function(gaiaEnts, targetClass, templates) -{ - for (let gaiaEnt of gaiaEnts) - { - let cmpIdentity = Engine.QueryInterface(gaiaEnt, IID_Identity); - if (!cmpIdentity || !cmpIdentity.HasClass(targetClass)) - continue; - - let cmpGarrisonHolder = Engine.QueryInterface(gaiaEnt, IID_GarrisonHolder); - if (!cmpGarrisonHolder) - continue; - - let unitCounts = this.RandomAttackerTemplates(templates, cmpGarrisonHolder.GetCapacity()); - this.debugLog("Garrisoning " + uneval(unitCounts) + " at " + targetClass); - - for (let template in unitCounts) - for (let newEnt of TriggerHelper.SpawnUnits(gaiaEnt, "units/" + template, unitCounts[template], gaulPlayer)) - Engine.QueryInterface(gaiaEnt, IID_GarrisonHolder).Garrison(newEnt); - } + for (let buildingClass of buildingGarrison.buildingClasses) + { + let unitCounts = this.SpawnAndGarrison(gaulPlayer, buildingClass, buildingGarrison.unitTemplates, 1); + this.debugLog("Garrisoning at " + buildingClass + ": " + uneval(unitCounts)); + } }; /** @@ -316,7 +268,7 @@ Trigger.prototype.SpawnCCAttackers = function() for (let spawn of toSpawn) { - let ents = TriggerHelper.SpawnUnits(gaiaCC, "units/" + spawn.template, spawn.count, gaulPlayer); + let ents = TriggerHelper.SpawnUnits(gaiaCC, spawn.template, spawn.count, gaulPlayer); if (spawn.hero && ents[0]) this.heroes.push({ "template": spawn.template, "ent": ents[0] }); @@ -399,7 +351,7 @@ Trigger.prototype.SpawnShips = function() this.debugLog("Spawning " + shipSpawnCount + " ships"); while (this.ships.length < shipSpawnCount) - this.ships.push(TriggerHelper.SpawnUnits(pickRandom(this.GetTriggerPoints(triggerPointShipSpawn)), "units/" + shipTemplate, 1, gaulPlayer)[0]); + this.ships.push(TriggerHelper.SpawnUnits(pickRandom(this.GetTriggerPoints(triggerPointShipSpawn)), shipTemplate, 1, gaulPlayer)[0]); for (let ship of this.ships) this.AttackAndPatrol([ship], shipTargetClass, triggerPointShipPatrol, "Ships"); @@ -436,7 +388,7 @@ Trigger.prototype.GetAttackerComposition = function(attackerCount, addSiege) remainder -= healerCount; let championCount = Math.round(championRatio(time) * remainder); - let championTemplateCounts = this.RandomAttackerTemplates(championTemplates, championCount); + let championTemplateCounts = this.RandomTemplateComposition(championTemplates, championCount); for (let template in championTemplateCounts) { let count = championTemplateCounts[template]; @@ -445,7 +397,7 @@ Trigger.prototype.GetAttackerComposition = function(attackerCount, addSiege) remainder -= count; } - let citizenTemplateCounts = this.RandomAttackerTemplates(citizenTemplates, remainder); + let citizenTemplateCounts = this.RandomTemplateComposition(citizenTemplates, remainder); for (let template in citizenTemplateCounts) { let count = citizenTemplateCounts[template]; @@ -478,7 +430,7 @@ Trigger.prototype.FillShips = function() for (let i = 0; i < spawn.count; ++i) { - let ent = Engine.AddEntity("units/" + spawn.template); + let ent = Engine.AddEntity(spawn.template); Engine.QueryInterface(ent, IID_Ownership).SetOwner(gaulPlayer); if (spawn.hero) diff --git a/binaries/data/mods/public/maps/random/elephantine_triggers.js b/binaries/data/mods/public/maps/random/elephantine_triggers.js index 494b8bb8b2..13af677158 100644 --- a/binaries/data/mods/public/maps/random/elephantine_triggers.js +++ b/binaries/data/mods/public/maps/random/elephantine_triggers.js @@ -1,70 +1,26 @@ Trigger.prototype.InitElephantine = function() { - let gaiaEnts = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).GetEntitiesByPlayer(0); - - for (let ent of gaiaEnts) + for (let ent of Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).GetEntitiesByPlayer(0)) { let cmpIdentity = Engine.QueryInterface(ent, IID_Identity); if (cmpIdentity && cmpIdentity.HasClass("Soldier")) Engine.QueryInterface(ent, IID_UnitAI).SwitchToStance("defensive"); } - let kushSupportUnits = ["kush_support_healer_e", "kush_support_female_citizen"]; - let kushInfantryUnits = ["kush_infantry_archer_e", "kush_infantry_spearman_e"]; + let kushSupportUnits = [ + "units/kush_support_healer_e", + "units/kush_support_female_citizen" + ]; - this.SpawnAndGarrisonBuilding(gaiaEnts, "Tower", kushInfantryUnits); + let kushInfantryUnits = [ + "units/kush_infantry_archer_e", + "units/kush_infantry_spearman_e" + ]; + + this.SpawnAndGarrison(0, "Tower", kushInfantryUnits, 1); for (let identityClass of ["Wonder", "Temple", "Pyramid"]) - this.SpawnAndGarrisonBuilding(gaiaEnts, identityClass, kushInfantryUnits.concat(kushSupportUnits)); -}; - -// Shameless copy of Danubius - -Trigger.prototype.SpawnAndGarrisonBuilding = function(gaiaEnts, targetClass, templates) -{ - for (let gaiaEnt of gaiaEnts) - { - let cmpIdentity = Engine.QueryInterface(gaiaEnt, IID_Identity); - if (!cmpIdentity || !cmpIdentity.HasClass(targetClass)) - continue; - - let cmpGarrisonHolder = Engine.QueryInterface(gaiaEnt, IID_GarrisonHolder); - if (!cmpGarrisonHolder) - continue; - - let unitCounts = this.RandomAttackerTemplates(templates, cmpGarrisonHolder.GetCapacity()); - - for (let template in unitCounts) - for (let newEnt of TriggerHelper.SpawnUnits(gaiaEnt, "units/" + template, unitCounts[template], 0)) - Engine.QueryInterface(gaiaEnt, IID_GarrisonHolder).Garrison(newEnt); - } -}; - -/** - * Return a random amount of these templates whose sum is count. - */ -Trigger.prototype.RandomAttackerTemplates = function(templates, count) -{ - let ratios = new Array(templates.length).fill(1).map(i => randFloat(0, 1)); - let ratioSum = ratios.reduce((current, sum) => current + sum, 0); - - let remainder = count; - let templateCounts = {}; - - for (let i in templates) - { - let currentCount = +i == templates.length - 1 ? remainder : Math.round(ratios[i] / ratioSum * count); - if (!currentCount) - continue; - - templateCounts[templates[i]] = currentCount; - remainder -= currentCount; - } - - if (remainder != 0) - warn("Not as many templates as expected: " + count + " vs " + uneval(templateCounts)); - - return templateCounts; + this.SpawnAndGarrison(0, identityClass, kushInfantryUnits.concat(kushSupportUnits), 1); }; { diff --git a/binaries/data/mods/public/maps/scripts/TriggerHelper.js b/binaries/data/mods/public/maps/scripts/TriggerHelper.js index 991d3ebc6e..604396e7da 100644 --- a/binaries/data/mods/public/maps/scripts/TriggerHelper.js +++ b/binaries/data/mods/public/maps/scripts/TriggerHelper.js @@ -261,4 +261,62 @@ TriggerHelper.HasDealtWithTech = function(playerID, techName) cmpTechnologyManager.IsTechnologyResearched(techName)); }; +/** + * Composes a random set of the given templates of the given total size. + * Returns an object where the keys are template names and values are amounts. + */ +Trigger.prototype.RandomTemplateComposition = function(templates, count) +{ + let ratios = new Array(templates.length).fill(1).map(i => randFloat(0, 1)); + let ratioSum = ratios.reduce((current, sum) => current + sum, 0); + + let remainder = count; + let templateCounts = {}; + + for (let i = 0; i < templates.length; ++i) + { + let currentCount = i == templates.length - 1 ? remainder : Math.round(ratios[i] / ratioSum * count); + if (!currentCount) + continue; + + templateCounts[templates[i]] = currentCount; + remainder -= currentCount; + } + + if (remainder != 0) + error("Could not chose as many templates as intended: " + count + " vs " + uneval(templateCounts)); + + return templateCounts; +}; + +/** + * This will spawn random compositions of entities of the given templates at all garrisonholders of the given targetClass of the given player. + * The garrisonholder will be filled to capacityPercent. + * Returns an object where keys are entityIDs of the affected garrisonholders and the properties are template compositions, see RandomTemplateComposition. + */ +Trigger.prototype.SpawnAndGarrison = function(playerID, targetClass, templates, capacityPercent) +{ + let results = {}; + + for (let entGarrisonHolder of Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).GetEntitiesByPlayer(playerID)) + { + let cmpIdentity = Engine.QueryInterface(entGarrisonHolder, IID_Identity); + if (!cmpIdentity || !cmpIdentity.HasClass(targetClass)) + continue; + + let cmpGarrisonHolder = Engine.QueryInterface(entGarrisonHolder, IID_GarrisonHolder); + if (!cmpGarrisonHolder) + continue; + + // TODO: account for already garrisoned entities + results[entGarrisonHolder] = this.RandomTemplateComposition(templates, Math.floor(cmpGarrisonHolder.GetCapacity() * capacityPercent)); + + for (let template in results[entGarrisonHolder]) + for (let entSpawned of TriggerHelper.SpawnUnits(entGarrisonHolder, template, results[entGarrisonHolder][template], playerID)) + Engine.QueryInterface(entGarrisonHolder, IID_GarrisonHolder).Garrison(entSpawned); + } + + return results; +}; + Engine.RegisterGlobal("TriggerHelper", TriggerHelper);