Differential D2016 Diff 19185 ps/trunk/binaries/data/mods/public/simulation/components/BuildingAI.js
Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/binaries/data/mods/public/simulation/components/BuildingAI.js
Show First 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | BuildingAI.prototype.SetupRangeQuery = function() | ||||
var enemies = cmpPlayer.GetEnemies(); | var enemies = cmpPlayer.GetEnemies(); | ||||
// Remove gaia. | // Remove gaia. | ||||
if (enemies.length && enemies[0] == 0) | if (enemies.length && enemies[0] == 0) | ||||
enemies.shift(); | enemies.shift(); | ||||
if (!enemies.length) | if (!enemies.length) | ||||
return; | return; | ||||
var range = cmpAttack.GetRange(attackType); | const range = cmpAttack.GetRange(attackType); | ||||
const yOrigin = cmpAttack.GetAttackYOrigin(attackType); | |||||
// This takes entity sizes into accounts, so no need to compensate for structure size. | // This takes entity sizes into accounts, so no need to compensate for structure size. | ||||
this.enemyUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery( | this.enemyUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery( | ||||
this.entity, range.min, range.max, range.elevationBonus, | this.entity, range.min, range.max, yOrigin, | ||||
enemies, IID_Resistance, cmpRangeManager.GetEntityFlagMask("normal")); | enemies, IID_Resistance, cmpRangeManager.GetEntityFlagMask("normal")); | ||||
cmpRangeManager.EnableActiveQuery(this.enemyUnitsQuery); | cmpRangeManager.EnableActiveQuery(this.enemyUnitsQuery); | ||||
}; | }; | ||||
// Set up a range query for Gaia units within LOS range which can be attacked. | // Set up a range query for Gaia units within LOS range which can be attacked. | ||||
// This should be called whenever our ownership changes. | // This should be called whenever our ownership changes. | ||||
BuildingAI.prototype.SetupGaiaRangeQuery = function() | BuildingAI.prototype.SetupGaiaRangeQuery = function() | ||||
{ | { | ||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | ||||
if (!cmpAttack) | if (!cmpAttack) | ||||
return; | return; | ||||
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); | var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); | ||||
if (this.gaiaUnitsQuery) | if (this.gaiaUnitsQuery) | ||||
{ | { | ||||
cmpRangeManager.DestroyActiveQuery(this.gaiaUnitsQuery); | cmpRangeManager.DestroyActiveQuery(this.gaiaUnitsQuery); | ||||
this.gaiaUnitsQuery = undefined; | this.gaiaUnitsQuery = undefined; | ||||
} | } | ||||
var cmpPlayer = QueryOwnerInterface(this.entity); | var cmpPlayer = QueryOwnerInterface(this.entity); | ||||
if (!cmpPlayer || !cmpPlayer.IsEnemy(0)) | if (!cmpPlayer || !cmpPlayer.IsEnemy(0)) | ||||
return; | return; | ||||
var range = cmpAttack.GetRange(attackType); | const range = cmpAttack.GetRange(attackType); | ||||
const yOrigin = cmpAttack.GetAttackYOrigin(attackType); | |||||
// This query is only interested in Gaia entities that can attack. | // This query is only interested in Gaia entities that can attack. | ||||
// This takes entity sizes into accounts, so no need to compensate for structure size. | // This takes entity sizes into accounts, so no need to compensate for structure size. | ||||
this.gaiaUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery( | this.gaiaUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery( | ||||
this.entity, range.min, range.max, range.elevationBonus, | this.entity, range.min, range.max, yOrigin, | ||||
[0], IID_Attack, cmpRangeManager.GetEntityFlagMask("normal")); | [0], IID_Attack, cmpRangeManager.GetEntityFlagMask("normal")); | ||||
cmpRangeManager.EnableActiveQuery(this.gaiaUnitsQuery); | cmpRangeManager.EnableActiveQuery(this.gaiaUnitsQuery); | ||||
}; | }; | ||||
/** | /** | ||||
* Called when units enter or leave range. | * Called when units enter or leave range. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 158 Lines • ▼ Show 20 Lines | if (this.unitAITarget && this.targetUnits.indexOf(this.unitAITarget) == -1) | ||||
addTarget(this.unitAITarget); | addTarget(this.unitAITarget); | ||||
for (let target of this.targetUnits) | for (let target of this.targetUnits) | ||||
addTarget(target); | addTarget(target); | ||||
// The obstruction manager performs approximate range checks. | // The obstruction manager performs approximate range checks. | ||||
// so we need to verify them here. | // so we need to verify them here. | ||||
// TODO: perhaps an optional 'precise' mode to range queries would be more performant. | // TODO: perhaps an optional 'precise' mode to range queries would be more performant. | ||||
let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | ||||
let range = cmpAttack.GetRange(attackType); | const range = cmpAttack.GetRange(attackType); | ||||
let thisCmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let thisCmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||
if (!thisCmpPosition.IsInWorld()) | if (!thisCmpPosition.IsInWorld()) | ||||
return; | return; | ||||
let s = thisCmpPosition.GetPosition(); | const y = thisCmpPosition.GetPosition().y + cmpAttack.GetAttackYOrigin(attackType); | ||||
let firedArrows = 0; | let firedArrows = 0; | ||||
while (firedArrows < arrowsToFire && targets.length()) | while (firedArrows < arrowsToFire && targets.length()) | ||||
{ | { | ||||
let selectedTarget = targets.randomItem(); | let selectedTarget = targets.randomItem(); | ||||
let targetCmpPosition = Engine.QueryInterface(selectedTarget, IID_Position); | let targetCmpPosition = Engine.QueryInterface(selectedTarget, IID_Position); | ||||
if (targetCmpPosition && targetCmpPosition.IsInWorld() && this.CheckTargetVisible(selectedTarget)) | if (targetCmpPosition && targetCmpPosition.IsInWorld() && this.CheckTargetVisible(selectedTarget)) | ||||
{ | { | ||||
// Parabolic range compuation is the same as in UnitAI's MoveToTargetAttackRange. | // Parabolic range compuation is the same as in UnitAI's MoveToTargetAttackRange. | ||||
// h is positive when I'm higher than the target. | // h is positive when I'm higher than the target. | ||||
let h = s.y - targetCmpPosition.GetPosition().y + range.elevationBonus; | const h = y - targetCmpPosition.GetPosition().y; | ||||
if (h > -range.max / 2 && cmpObstructionManager.IsInTargetRange( | if (h > -range.max / 2 && cmpObstructionManager.IsInTargetRange( | ||||
this.entity, | this.entity, | ||||
selectedTarget, | selectedTarget, | ||||
range.min, | range.min, | ||||
Math.sqrt(Math.square(range.max) + 2 * range.max * h), false)) | Math.sqrt(Math.square(range.max) + 2 * range.max * h), false)) | ||||
{ | { | ||||
cmpAttack.PerformAttack(attackType, selectedTarget); | cmpAttack.PerformAttack(attackType, selectedTarget); | ||||
PlaySound("attack_" + attackType.toLowerCase(), this.entity); | PlaySound("attack_" + attackType.toLowerCase(), this.entity); | ||||
Show All 33 Lines |
Wildfire Games · Phabricator