2014-06-23 11:12:51 -07:00
|
|
|
// Contains standardized functions suitable for using in trigger scripts.
|
|
|
|
|
// Do not use them in any other simulation script.
|
|
|
|
|
|
|
|
|
|
var TriggerHelper = {};
|
|
|
|
|
|
|
|
|
|
TriggerHelper.GetPlayerIDFromEntity = function(ent)
|
|
|
|
|
{
|
2016-06-14 04:18:28 -07:00
|
|
|
let cmpPlayer = Engine.QueryInterface(ent, IID_Player);
|
2014-06-23 11:12:51 -07:00
|
|
|
if (cmpPlayer)
|
|
|
|
|
return cmpPlayer.GetPlayerID();
|
2016-06-14 04:18:28 -07:00
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
return -1;
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-23 04:22:46 -07:00
|
|
|
TriggerHelper.IsInWorld = function(ent)
|
|
|
|
|
{
|
|
|
|
|
let cmpPosition = Engine.QueryInterface(ent, IID_Position);
|
|
|
|
|
return cmpPosition && cmpPosition.IsInWorld();
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-10 09:16:39 -08:00
|
|
|
TriggerHelper.GetEntityPosition2D = function(ent)
|
|
|
|
|
{
|
|
|
|
|
let cmpPosition = Engine.QueryInterface(ent, IID_Position);
|
|
|
|
|
|
|
|
|
|
if (!cmpPosition || !cmpPosition.IsInWorld())
|
|
|
|
|
return undefined;
|
|
|
|
|
|
|
|
|
|
return cmpPosition.GetPosition2D();
|
|
|
|
|
};
|
|
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
TriggerHelper.GetOwner = function(ent)
|
|
|
|
|
{
|
2016-06-14 04:18:28 -07:00
|
|
|
let cmpOwnership = Engine.QueryInterface(ent, IID_Ownership);
|
2014-06-23 11:12:51 -07:00
|
|
|
if (cmpOwnership)
|
|
|
|
|
return cmpOwnership.GetOwner();
|
2016-06-14 04:18:28 -07:00
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
return -1;
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-10 09:16:39 -08:00
|
|
|
/**
|
|
|
|
|
* This returns the mapsize in number of tiles, the value corresponding to map_sizes.json, also used by random map scripts.
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.GetMapSizeTiles = function()
|
|
|
|
|
{
|
|
|
|
|
return Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain).GetTilesPerSide();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This returns the mapsize in the the coordinate system used in the simulation/, especially cmpPosition.
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.GetMapSizeTerrain = function()
|
|
|
|
|
{
|
|
|
|
|
return Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain).GetMapSize();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the elapsed ingame time in milliseconds since the gamestart.
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.GetTime = function()
|
|
|
|
|
{
|
|
|
|
|
return Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the elpased ingame time in minutes since the gamestart. Useful for balancing.
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.GetMinutes = function()
|
|
|
|
|
{
|
|
|
|
|
return Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime() / 60 / 1000;
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-07 05:54:58 -08:00
|
|
|
TriggerHelper.GetEntitiesByPlayer = function(playerID)
|
|
|
|
|
{
|
|
|
|
|
return Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).GetEntitiesByPlayer(playerID);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TriggerHelper.GetAllPlayersEntities = function()
|
|
|
|
|
{
|
|
|
|
|
return Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).GetNonGaiaEntities();
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-07 04:36:45 -08:00
|
|
|
TriggerHelper.SetUnitStance = function(ent, stance)
|
|
|
|
|
{
|
|
|
|
|
let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
|
|
|
|
|
if (cmpUnitAI)
|
|
|
|
|
cmpUnitAI.SwitchToStance(stance);
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-10 09:16:39 -08:00
|
|
|
TriggerHelper.SetUnitFormation = function(playerID, entities, formation)
|
|
|
|
|
{
|
|
|
|
|
ProcessCommand(playerID, {
|
|
|
|
|
"type": "formation",
|
|
|
|
|
"entities": entities,
|
|
|
|
|
"name": formation
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
/**
|
2016-07-21 08:12:49 -07:00
|
|
|
* Can be used to "force" a building/unit to spawn a group of entities.
|
|
|
|
|
*
|
2014-06-23 11:12:51 -07:00
|
|
|
* @param source Entity id of the point where they will be spawned from
|
|
|
|
|
* @param template Name of the template
|
|
|
|
|
* @param count Number of units to spawn
|
|
|
|
|
* @param owner Player id of the owner of the new units. By default, the owner
|
|
|
|
|
* of the source entity.
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.SpawnUnits = function(source, template, count, owner)
|
|
|
|
|
{
|
2016-06-14 04:18:28 -07:00
|
|
|
let entities = [];
|
|
|
|
|
let cmpFootprint = Engine.QueryInterface(source, IID_Footprint);
|
|
|
|
|
let cmpPosition = Engine.QueryInterface(source, IID_Position);
|
|
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
if (!cmpPosition || !cmpPosition.IsInWorld())
|
|
|
|
|
{
|
|
|
|
|
error("tried to create entity from a source without position");
|
2016-06-14 04:18:28 -07:00
|
|
|
return entities;
|
2014-06-23 11:12:51 -07:00
|
|
|
}
|
2016-06-14 04:18:28 -07:00
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
if (owner == null)
|
|
|
|
|
owner = TriggerHelper.GetOwner(source);
|
|
|
|
|
|
2016-06-15 09:16:55 -07:00
|
|
|
for (let i = 0; i < count; ++i)
|
2014-06-23 11:12:51 -07:00
|
|
|
{
|
2016-06-14 04:18:28 -07:00
|
|
|
let ent = Engine.AddEntity(template);
|
|
|
|
|
let cmpEntPosition = Engine.QueryInterface(ent, IID_Position);
|
2014-06-23 11:12:51 -07:00
|
|
|
if (!cmpEntPosition)
|
|
|
|
|
{
|
2017-02-24 07:41:19 -08:00
|
|
|
Engine.DestroyEntity(ent);
|
2014-06-23 11:12:51 -07:00
|
|
|
error("tried to create entity without position");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2016-06-14 04:18:28 -07:00
|
|
|
|
|
|
|
|
let cmpEntOwnership = Engine.QueryInterface(ent, IID_Ownership);
|
2014-06-23 11:12:51 -07:00
|
|
|
if (cmpEntOwnership)
|
|
|
|
|
cmpEntOwnership.SetOwner(owner);
|
2016-06-14 04:18:28 -07:00
|
|
|
|
|
|
|
|
entities.push(ent);
|
|
|
|
|
|
|
|
|
|
let pos;
|
2014-06-23 11:12:51 -07:00
|
|
|
if (cmpFootprint)
|
|
|
|
|
pos = cmpFootprint.PickSpawnPoint(ent);
|
2016-06-14 04:18:28 -07:00
|
|
|
|
2016-10-18 06:08:01 -07:00
|
|
|
// TODO this can happen if the player build on the place
|
2014-06-23 11:12:51 -07:00
|
|
|
// where our trigger point is
|
|
|
|
|
// We should probably warn the trigger maker in some way,
|
|
|
|
|
// but not interrupt the game for the player
|
|
|
|
|
if (!pos || pos.y < 0)
|
|
|
|
|
pos = cmpPosition.GetPosition();
|
2016-06-14 04:18:28 -07:00
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
cmpEntPosition.JumpTo(pos.x, pos.z);
|
|
|
|
|
}
|
2016-06-14 04:18:28 -07:00
|
|
|
|
|
|
|
|
return entities;
|
2016-10-18 06:08:01 -07:00
|
|
|
};
|
2014-06-23 11:12:51 -07:00
|
|
|
|
2017-12-17 09:17:00 -08:00
|
|
|
/**
|
|
|
|
|
* Can be used to spawn garrisoned units inside a building/ship.
|
|
|
|
|
*
|
|
|
|
|
* @param entity Entity id of the garrison holder in which units will be garrisoned
|
|
|
|
|
* @param template Name of the template
|
|
|
|
|
* @param count Number of units to spawn
|
|
|
|
|
* @param owner Player id of the owner of the new units. By default, the owner
|
|
|
|
|
* of the garrisonholder entity.
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.SpawnGarrisonedUnits = function(entity, template, count, owner)
|
|
|
|
|
{
|
|
|
|
|
let entities = [];
|
|
|
|
|
|
2018-03-07 04:36:45 -08:00
|
|
|
let cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder);
|
2017-12-17 09:17:00 -08:00
|
|
|
if (!cmpGarrisonHolder)
|
|
|
|
|
{
|
|
|
|
|
error("tried to create garrisoned entities inside a non-garrisonholder");
|
|
|
|
|
return entities;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (owner == null)
|
|
|
|
|
owner = TriggerHelper.GetOwner(entity);
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < count; ++i)
|
|
|
|
|
{
|
|
|
|
|
let ent = Engine.AddEntity(template);
|
2018-03-07 04:36:45 -08:00
|
|
|
|
2017-12-17 09:17:00 -08:00
|
|
|
let cmpOwnership = Engine.QueryInterface(ent, IID_Ownership);
|
|
|
|
|
if (cmpOwnership)
|
|
|
|
|
cmpOwnership.SetOwner(owner);
|
2018-03-07 04:36:45 -08:00
|
|
|
|
2018-03-16 08:49:08 -07:00
|
|
|
if (cmpGarrisonHolder.Garrison(ent))
|
2017-12-17 09:17:00 -08:00
|
|
|
{
|
2018-03-07 04:36:45 -08:00
|
|
|
let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
|
|
|
|
|
if (cmpUnitAI)
|
|
|
|
|
cmpUnitAI.Autogarrison(entity);
|
|
|
|
|
|
2017-12-17 09:17:00 -08:00
|
|
|
entities.push(ent);
|
|
|
|
|
}
|
|
|
|
|
else
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
error("failed to garrison entity " + ent + " (" + template + ") inside " + entity);
|
2017-12-17 09:17:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return entities;
|
|
|
|
|
};
|
|
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
/**
|
|
|
|
|
* Spawn units from all trigger points with this reference
|
|
|
|
|
* If player is defined, only spaw units from the trigger points
|
|
|
|
|
* that belong to that player
|
|
|
|
|
* @param ref Trigger point reference name to spawn units from
|
|
|
|
|
* @param template Template name
|
|
|
|
|
* @param count Number of spawned entities per Trigger point
|
|
|
|
|
* @param owner Owner of the spawned units. Default: the owner of the origins
|
|
|
|
|
* @return A list of new entities per origin like
|
|
|
|
|
* {originId1: [entId1, entId2], originId2: [entId3, entId4], ...}
|
|
|
|
|
*/
|
2016-10-18 06:08:01 -07:00
|
|
|
TriggerHelper.SpawnUnitsFromTriggerPoints = function(ref, template, count, owner = null)
|
2014-06-23 11:12:51 -07:00
|
|
|
{
|
2016-06-14 04:18:28 -07:00
|
|
|
let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
|
|
|
|
|
let triggerPoints = cmpTrigger.GetTriggerPoints(ref);
|
|
|
|
|
|
|
|
|
|
let entities = {};
|
|
|
|
|
for (let point of triggerPoints)
|
|
|
|
|
entities[point] = TriggerHelper.SpawnUnits(point, template, count, owner);
|
|
|
|
|
|
|
|
|
|
return entities;
|
2014-06-30 14:38:45 -07:00
|
|
|
};
|
2014-06-23 11:12:51 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the resource type that can be gathered from an entity
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.GetResourceType = function(entity)
|
|
|
|
|
{
|
2016-06-14 04:18:28 -07:00
|
|
|
let cmpResourceSupply = Engine.QueryInterface(entity, IID_ResourceSupply);
|
2014-06-23 11:12:51 -07:00
|
|
|
if (!cmpResourceSupply)
|
|
|
|
|
return undefined;
|
2016-06-14 04:18:28 -07:00
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
return cmpResourceSupply.GetType();
|
2016-10-18 06:08:01 -07:00
|
|
|
};
|
2014-06-23 11:12:51 -07:00
|
|
|
|
|
|
|
|
/**
|
2016-06-25 21:40:50 -07:00
|
|
|
* The given player will win the game.
|
2017-08-08 04:32:00 -07:00
|
|
|
* If it's not a last man standing game, then allies will win too and others will be defeated.
|
|
|
|
|
*
|
|
|
|
|
* @param {number} playerID - The player who will win.
|
|
|
|
|
* @param {function} victoryReason - Function that maps from number to plural string, for example
|
|
|
|
|
* n => markForPluralTranslation(
|
|
|
|
|
* "%(lastPlayer)s has won (game mode).",
|
|
|
|
|
* "%(players)s and %(lastPlayer)s have won (game mode).",
|
|
|
|
|
* n));
|
|
|
|
|
* It's a function since we don't know in advance how many players will have won.
|
2014-06-23 11:12:51 -07:00
|
|
|
*/
|
2017-08-08 04:32:00 -07:00
|
|
|
TriggerHelper.SetPlayerWon = function(playerID, victoryReason, defeatReason)
|
2014-06-23 11:12:51 -07:00
|
|
|
{
|
2016-06-14 04:18:28 -07:00
|
|
|
let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
|
2018-03-05 10:02:27 -08:00
|
|
|
cmpEndGameManager.MarkPlayerAndAlliesAsWon(playerID, victoryReason, defeatReason);
|
2014-06-23 11:12:51 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
2017-08-08 04:32:00 -07:00
|
|
|
* Defeats a single player.
|
|
|
|
|
*
|
|
|
|
|
* @param {number} - ID of that player.
|
|
|
|
|
* @param {string} - String to be shown in chat, for example
|
|
|
|
|
* markForTranslation("%(player)s has been defeated (objective).")
|
2014-06-23 11:12:51 -07:00
|
|
|
*/
|
2017-08-08 04:32:00 -07:00
|
|
|
TriggerHelper.DefeatPlayer = function(playerID, defeatReason)
|
2014-06-23 11:12:51 -07:00
|
|
|
{
|
2016-06-25 21:40:50 -07:00
|
|
|
let cmpPlayer = QueryPlayerIDInterface(playerID);
|
|
|
|
|
if (cmpPlayer)
|
2017-08-08 04:32:00 -07:00
|
|
|
cmpPlayer.SetState("defeated", defeatReason);
|
2014-06-23 11:12:51 -07:00
|
|
|
};
|
|
|
|
|
|
2014-06-30 06:59:34 -07:00
|
|
|
/**
|
2018-04-24 05:46:59 -07:00
|
|
|
* Returns the number of players including gaia and defeated ones.
|
2014-06-30 06:59:34 -07:00
|
|
|
*/
|
|
|
|
|
TriggerHelper.GetNumberOfPlayers = function()
|
|
|
|
|
{
|
2017-12-13 12:41:41 -08:00
|
|
|
return Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers();
|
2014-06-30 14:38:45 -07:00
|
|
|
};
|
2014-06-30 06:59:34 -07:00
|
|
|
|
|
|
|
|
/**
|
2017-11-10 04:14:16 -08:00
|
|
|
* A function to determine if an entity matches specific classes.
|
|
|
|
|
* See globalscripts/Templates.js for details of MatchesClassList.
|
|
|
|
|
*
|
|
|
|
|
* @param entity - ID of the entity that we want to check for classes.
|
2018-03-07 05:54:58 -08:00
|
|
|
* @param classes - List of the classes we are checking if the entity matches.
|
2014-06-30 06:59:34 -07:00
|
|
|
*/
|
2018-03-07 05:54:58 -08:00
|
|
|
TriggerHelper.EntityMatchesClassList = function(entity, classes)
|
2014-06-30 06:59:34 -07:00
|
|
|
{
|
2016-06-14 04:18:28 -07:00
|
|
|
let cmpIdentity = Engine.QueryInterface(entity, IID_Identity);
|
2018-03-07 05:54:58 -08:00
|
|
|
return cmpIdentity && MatchesClassList(cmpIdentity.GetClassesList(), classes);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TriggerHelper.MatchEntitiesByClass = function(entities, classes)
|
|
|
|
|
{
|
|
|
|
|
return entities.filter(ent => TriggerHelper.EntityMatchesClassList(ent, classes));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TriggerHelper.GetPlayerEntitiesByClass = function(playerID, classes)
|
|
|
|
|
{
|
|
|
|
|
return TriggerHelper.MatchEntitiesByClass(TriggerHelper.GetEntitiesByPlayer(playerID), classes);
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-08 06:06:41 -08:00
|
|
|
TriggerHelper.GetAllPlayersEntitiesByClass = function(classes)
|
2018-03-07 05:54:58 -08:00
|
|
|
{
|
|
|
|
|
return TriggerHelper.MatchEntitiesByClass(TriggerHelper.GetAllPlayersEntities(), classes);
|
2014-06-30 14:38:45 -07:00
|
|
|
};
|
2014-06-30 06:59:34 -07:00
|
|
|
|
2017-05-21 18:18:51 -07:00
|
|
|
/**
|
|
|
|
|
* Return valid gaia-owned spawn points on land in neutral territory.
|
|
|
|
|
* If there are none, use those available in player-owned territory.
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.GetLandSpawnPoints = function()
|
|
|
|
|
{
|
|
|
|
|
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
|
|
|
|
|
let cmpWaterManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_WaterManager);
|
|
|
|
|
let cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager);
|
|
|
|
|
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
|
|
|
|
|
|
|
|
|
let neutralSpawnPoints = [];
|
|
|
|
|
let nonNeutralSpawnPoints = [];
|
|
|
|
|
|
|
|
|
|
for (let ent of cmpRangeManager.GetEntitiesByPlayer(0))
|
|
|
|
|
{
|
|
|
|
|
let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
|
|
|
|
|
let cmpPosition = Engine.QueryInterface(ent, IID_Position);
|
|
|
|
|
if (!cmpIdentity || !cmpPosition || !cmpPosition.IsInWorld())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
let templateName = cmpTemplateManager.GetCurrentTemplateName(ent);
|
|
|
|
|
if (!templateName)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
let template = cmpTemplateManager.GetTemplate(templateName);
|
|
|
|
|
if (!template || template.UnitMotionFlying)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
let pos = cmpPosition.GetPosition();
|
|
|
|
|
if (pos.y <= cmpWaterManager.GetWaterLevel(pos.x, pos.z))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (cmpTerritoryManager.GetOwner(pos.x, pos.z) == 0)
|
|
|
|
|
neutralSpawnPoints.push(ent);
|
|
|
|
|
else
|
|
|
|
|
nonNeutralSpawnPoints.push(ent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return neutralSpawnPoints.length ? neutralSpawnPoints : nonNeutralSpawnPoints;
|
|
|
|
|
};
|
|
|
|
|
|
2017-08-19 02:38:52 -07:00
|
|
|
TriggerHelper.HasDealtWithTech = function(playerID, techName)
|
|
|
|
|
{
|
|
|
|
|
let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
|
|
|
|
let playerEnt = cmpPlayerManager.GetPlayerByID(playerID);
|
|
|
|
|
let cmpTechnologyManager = Engine.QueryInterface(playerEnt, IID_TechnologyManager);
|
|
|
|
|
return cmpTechnologyManager && (cmpTechnologyManager.IsTechnologyQueued(techName) ||
|
|
|
|
|
cmpTechnologyManager.IsTechnologyStarted(techName) ||
|
2017-08-31 10:48:50 -07:00
|
|
|
cmpTechnologyManager.IsTechnologyResearched(techName));
|
2017-08-19 02:38:52 -07:00
|
|
|
};
|
|
|
|
|
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
/**
|
|
|
|
|
* Returns all names of templates that match the given identity classes, constrainted to an optional civ.
|
|
|
|
|
*
|
|
|
|
|
* @param {String} classes - See MatchesClassList for the accepted formats, for example "Class1 Class2+!Class3".
|
|
|
|
|
* @param [String] civ - Optionally only retrieve templates of the given civ. Can be left undefined.
|
|
|
|
|
* @param [String] packedState - When retrieving siege engines filter for the "packed" or "unpacked" state
|
|
|
|
|
* @param [String] rank - If given, only return templates that have no or the given rank. For example "Elite".
|
|
|
|
|
* @param [Boolean] excludeBarracksVariants - Optionally exclude templates whose name ends with "_barracks"
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.GetTemplateNamesByClasses = function(classes, civ, packedState, rank, excludeBarracksVariants)
|
|
|
|
|
{
|
|
|
|
|
let templateNames = [];
|
|
|
|
|
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
|
|
|
|
|
for (let templateName of cmpTemplateManager.FindAllTemplates(false))
|
|
|
|
|
{
|
|
|
|
|
if (templateName.startsWith("campaigns/army_"))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (excludeBarracksVariants && templateName.endsWith("_barracks"))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
let template = cmpTemplateManager.GetTemplate(templateName);
|
|
|
|
|
|
|
|
|
|
if (civ && (!template.Identity || template.Identity.Civ != civ))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!MatchesClassList(GetIdentityClasses(template.Identity), classes))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (rank && template.Identity.Rank && template.Identity.Rank != rank)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (packedState && template.Pack && packedState != template.Pack.State)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
templateNames.push(templateName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return templateNames;
|
|
|
|
|
};
|
2018-03-02 08:32:10 -08:00
|
|
|
/**
|
|
|
|
|
* Composes a random set of the given templates of the given total size.
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
*
|
|
|
|
|
* @param {String[]} templateNames - for example ["brit_infantry_javelinist_b", "brit_cavalry_swordsman_e"]
|
|
|
|
|
* @param {Number} totalCount - total amount of templates, in this example 12
|
|
|
|
|
* @returns an object where the keys are template names and values are amounts,
|
|
|
|
|
* for example { "brit_infantry_javelinist_b": 4, "brit_cavalry_swordsman_e": 8 }
|
2018-03-02 08:32:10 -08:00
|
|
|
*/
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
TriggerHelper.RandomTemplateComposition = function(templateNames, totalCount)
|
2018-03-02 08:32:10 -08:00
|
|
|
{
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
let frequencies = templateNames.map(() => randFloat(0, 1));
|
|
|
|
|
let frequencySum = frequencies.reduce((sum, frequency) => sum + frequency, 0);
|
2018-03-02 08:32:10 -08:00
|
|
|
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
let remainder = totalCount;
|
2018-03-02 08:32:10 -08:00
|
|
|
let templateCounts = {};
|
|
|
|
|
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
for (let i = 0; i < templateNames.length; ++i)
|
2018-03-02 08:32:10 -08:00
|
|
|
{
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
let count = i == templateNames.length - 1 ? remainder : Math.min(remainder, Math.round(frequencies[i] / frequencySum * totalCount));
|
|
|
|
|
if (!count)
|
2018-03-02 08:32:10 -08:00
|
|
|
continue;
|
|
|
|
|
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
templateCounts[templateNames[i]] = count;
|
|
|
|
|
remainder -= count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return templateCounts;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Composes a random set of the given templates so that the sum of templates matches totalCount.
|
|
|
|
|
* For each template array that has a count item, it choses exactly that number of templates at random.
|
|
|
|
|
* The remaining template arrays are chosen depending on the given frequency.
|
|
|
|
|
* If a unique_entities array is given, it will only select the template if none of the given entityIDs
|
|
|
|
|
* already have that entity (useful to let heroes remain unique).
|
|
|
|
|
*
|
|
|
|
|
* @param {Object[]} templateBalancing - for example
|
|
|
|
|
* [
|
|
|
|
|
* { "templates": ["template1", "template2"], "frequency": 2 },
|
|
|
|
|
* { "templates": ["template3"], "frequency": 1 },
|
|
|
|
|
* { "templates": ["hero1", "hero2"], "unique_entities": [380, 495], "count": 1 }
|
|
|
|
|
* ]
|
|
|
|
|
* @param {Number} totalCount - total amount of templates, for example 5.
|
|
|
|
|
*
|
|
|
|
|
* @returns an object where the keys are template names and values are amounts,
|
|
|
|
|
* for example { "template1": 1, "template2": 3, "template3": 2, "hero1": 1 }
|
|
|
|
|
*/
|
|
|
|
|
TriggerHelper.BalancedTemplateComposition = function(templateBalancing, totalCount)
|
|
|
|
|
{
|
|
|
|
|
// Remove all unavailable unique templates (heroes) and empty template arrays
|
|
|
|
|
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
|
|
|
|
|
let templateBalancingFiltered = [];
|
|
|
|
|
for (let templateBalance of templateBalancing)
|
|
|
|
|
{
|
|
|
|
|
let templateBalanceNew = clone(templateBalance);
|
|
|
|
|
|
|
|
|
|
if (templateBalanceNew.unique_entities)
|
|
|
|
|
templateBalanceNew.templates = templateBalanceNew.templates.filter(templateName =>
|
|
|
|
|
templateBalanceNew.unique_entities.every(ent => templateName != cmpTemplateManager.GetCurrentTemplateName(ent)));
|
|
|
|
|
|
|
|
|
|
if (templateBalanceNew.templates.length)
|
|
|
|
|
templateBalancingFiltered.push(templateBalanceNew);
|
2018-03-02 08:32:10 -08:00
|
|
|
}
|
|
|
|
|
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
// Helper function to add randomized templates to the result
|
|
|
|
|
let remainder = totalCount;
|
|
|
|
|
let results = {};
|
|
|
|
|
let addTemplates = (templateNames, count) => {
|
|
|
|
|
let templateCounts = TriggerHelper.RandomTemplateComposition(templateNames, count);
|
|
|
|
|
for (let templateName in templateCounts)
|
|
|
|
|
{
|
|
|
|
|
if (!results[templateName])
|
|
|
|
|
results[templateName] = 0;
|
|
|
|
|
|
2018-03-07 04:21:09 -08:00
|
|
|
results[templateName] += templateCounts[templateName];
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
remainder -= templateCounts[templateName];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Add template groups with fixed counts
|
|
|
|
|
for (let templateBalance of templateBalancingFiltered)
|
|
|
|
|
if (templateBalance.count)
|
|
|
|
|
addTemplates(templateBalance.templates, Math.min(remainder, templateBalance.count));
|
|
|
|
|
|
|
|
|
|
// Add template groups with frequency weights
|
|
|
|
|
let templateBalancingFrequencies = templateBalancingFiltered.filter(templateBalance => !!templateBalance.frequency);
|
|
|
|
|
let templateBalancingFrequencySum = templateBalancingFrequencies.reduce((sum, templateBalance) => sum + templateBalance.frequency, 0);
|
|
|
|
|
for (let i = 0; i < templateBalancingFrequencies.length; ++i)
|
|
|
|
|
addTemplates(
|
|
|
|
|
templateBalancingFrequencies[i].templates,
|
|
|
|
|
i == templateBalancingFrequencies.length - 1 ?
|
|
|
|
|
remainder :
|
|
|
|
|
Math.min(remainder, Math.round(templateBalancingFrequencies[i].frequency / templateBalancingFrequencySum * totalCount)));
|
|
|
|
|
|
2018-03-02 08:32:10 -08:00
|
|
|
if (remainder != 0)
|
2018-12-29 10:15:09 -08:00
|
|
|
warn("Could not choose as many templates as intended, remaining " + remainder + ", chosen: " + uneval(results));
|
2018-03-02 08:32:10 -08:00
|
|
|
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
return results;
|
2018-03-02 08:32:10 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
TriggerHelper.SpawnAndGarrisonAtClasses = function(playerID, classes, templates, capacityPercent)
|
2018-03-02 08:32:10 -08:00
|
|
|
{
|
|
|
|
|
let results = {};
|
|
|
|
|
|
|
|
|
|
for (let entGarrisonHolder of Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).GetEntitiesByPlayer(playerID))
|
|
|
|
|
{
|
|
|
|
|
let cmpIdentity = Engine.QueryInterface(entGarrisonHolder, IID_Identity);
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
if (!cmpIdentity || !MatchesClassList(cmpIdentity.GetClassesList(), classes))
|
2018-03-02 08:32:10 -08:00
|
|
|
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])
|
Refactor and move random template composition triggerscript code used for gaia attacker waves from Danubius (026dcf10eb / D204) and Survival Of The Fittest (18e7d8a518 / D145) to the TriggerHelper.
Eases implementation of new maps with diverse scripted attackers, refs
#5040, D11 and map difficulties, refs #4963, D1189.
Replaces hardcoded templatenames with calls to a new TriggerHelper
function to query template names, given Classes, Civ, Rank or Packed
state.
Removes the duplicated template counting logic, that was intertwined
with map specific unit classes balancing logic, refs #4805.
Use mimos garrison function from e29dfb7000 / D1146 to support
doubleclicking on garrisoned gaia heroes on Danubius, fixing the bug
described in comment:10 of #4291.
Fix wrong (Trigger) prototype reference in ce65af8dcb.
This was SVN commit r21445.
2018-03-06 05:31:34 -08:00
|
|
|
TriggerHelper.SpawnGarrisonedUnits(entGarrisonHolder, template, results[entGarrisonHolder][template], playerID);
|
2018-03-02 08:32:10 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return results;
|
|
|
|
|
};
|
|
|
|
|
|
2014-06-23 11:12:51 -07:00
|
|
|
Engine.RegisterGlobal("TriggerHelper", TriggerHelper);
|