Source: polar_sea_triggers.js

const debugLog = false;

var attackerTemplate = "gaia/fauna_wolf_arctic_violent";

var minWaveSize = 1;
var maxWaveSize = 3;

var firstWaveTime = 5;
var minWaveTime = 2;
var maxWaveTime = 4;

/**
 * Attackers will focus the targetCount closest units that have the targetClasses type.
 */
var targetClasses = "Organic+!Domestic";
var targetCount = 3;

Trigger.prototype.DisableTechnologies = function()
{
	for (let i = 1; i < TriggerHelper.GetNumberOfPlayers(); ++i)
		QueryPlayerIDInterface(i).SetDisabledTechnologies([
			"gather_lumbering_ironaxes",
			"gather_lumbering_sharpaxes",
			"gather_lumbering_strongeraxes",
			"gather_wicker_baskets"
		]);
};

Trigger.prototype.SpawnWolvesAndAttack = function()
{
	let waveSize = Math.round(Math.random() * (maxWaveSize - minWaveSize) + minWaveSize);
	let attackers = TriggerHelper.SpawnUnitsFromTriggerPoints("A", attackerTemplate, waveSize, 0);

	if (debugLog)
		print("Spawned " + waveSize + " " + attackerTemplate + " at " + Object.keys(attackers).length + " points\n");

	let allTargets;

	let players = new Array(TriggerHelper.GetNumberOfPlayers()).fill(0).map((v, i) => i + 1);

	for (let spawnPoint in attackers)
	{
		// TriggerHelper.SpawnUnits is guaranteed to spawn
		let firstAttacker = attackers[spawnPoint][0];
		if (!firstAttacker)
			continue;

		let attackerPos = TriggerHelper.GetEntityPosition2D(firstAttacker);
		if (!attackerPos)
			continue;

		// The returned entities are sorted by RangeManager already
		// Only consider units implementing Health since wolves deal damage.
		let targets = PositionHelper.EntitiesNearPoint(attackerPos, 200, players, IID_Health).filter(ent => {
			let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
			return cmpIdentity && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses);
		});

		let goodTargets = targets.slice(0, targetCount);

		// Look through all targets if there aren't enough nearby ones
		if (goodTargets.length < targetCount)
		{
			if (!allTargets)
				allTargets = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).GetNonGaiaEntities().filter(ent => {
					let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
					return cmpIdentity && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses);
				});

			let getDistance = target => {
				let targetPos = TriggerHelper.GetEntityPosition2D(target);
				return targetPos ? attackerPos.distanceToSquared(targetPos) : Infinity;
			};

			goodTargets = [];
			let goodDists = [];
			for (let target of allTargets)
			{
				let dist = getDistance(target);
				let i = goodDists.findIndex(element => dist < element);
				if (i != -1 || goodTargets.length < targetCount)
				{
					if (i == -1)
						i = goodTargets.length;
					goodTargets.splice(i, 0, target);
					goodDists.splice(i, 0, dist);
					if (goodTargets.length > targetCount)
					{
						goodTargets.pop();
						goodDists.pop();
					}
				}
			}
		}

		for (let target of goodTargets)
			ProcessCommand(0, {
				"type": "attack",
				"entities": attackers[spawnPoint],
				"target": target,
				"queued": true
			});
	}

	this.DoAfterDelay((Math.random() * (maxWaveTime - minWaveTime) + minWaveTime) * 60 * 1000, "SpawnWolvesAndAttack", {});
};

{
	let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
	cmpTrigger.RegisterTrigger("OnInitGame", "DisableTechnologies", { "enabled": true });
	cmpTrigger.DoAfterDelay(firstWaveTime * 60 * 1000, "SpawnWolvesAndAttack", {});
}