Index: binaries/data/mods/public/simulation/components/Attack.js =================================================================== --- binaries/data/mods/public/simulation/components/Attack.js +++ binaries/data/mods/public/simulation/components/Attack.js @@ -560,6 +560,11 @@ return; } + // when a unit gets attacked by aggressive animals, ping (idle) units nearby to help out + const cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI); + if (cmpUnitAI.IsDangerousAnimal()) + cmpUnitAI.PingForHelp(this.target); + // ToDo: Enable entities to keep facing a target. Engine.QueryInterface(this.entity, IID_UnitAI)?.FaceTowardsTarget(this.target); Index: binaries/data/mods/public/simulation/components/UnitAI.js =================================================================== --- binaries/data/mods/public/simulation/components/UnitAI.js +++ binaries/data/mods/public/simulation/components/UnitAI.js @@ -6426,7 +6426,7 @@ return true; let cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI); - return cmpUnitAI && (!cmpUnitAI.IsAnimal() || cmpUnitAI.IsDangerousAnimal()); + return cmpUnitAI && !cmpUnitAI.IsAnimal(); }; let entsByPreferences = {}; @@ -6460,6 +6460,33 @@ }; /** + * Ping nearby owned idle units to help if a unit gets attacked by aggressive animals. + * @param {number} ent - The unit that gets attacked. + * @param {number} attacker - The attacker unit. + * @param {number} radius - The range of the radius to ping units. + */ + UnitAI.prototype.PingForHelp = function(ent, attacker = this.entity, radius = 60) + { + const cmpOwnership = Engine.QueryInterface(ent, IID_Ownership); + if (!cmpOwnership) + return; + + const owner = cmpOwnership.GetOwner(); + if (owner == INVALID_PLAYER) + return; + + const cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); + const nearby = cmpRangeManager.ExecuteQuery(ent, 0, radius, [owner], IID_UnitAI, true); + + for (let i = 0; i < nearby.length; ++i) + { + const cmpUnitAI = Engine.QueryInterface(nearby[i], IID_UnitAI); + if (cmpUnitAI.isIdle) + this["Attack"].apply(cmpUnitAI, [attacker]); + } + }; + +/** * Call UnitAI.funcname(args) on all formation members. * @param resetFinishedEntities - If true, call ResetFinishedEntities first. * If the controller wants to wait on its members to finish their order,