Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/Attack.js
Show First 20 Lines • Show All 455 Lines • ▼ Show 20 Lines | for (let key in template.Bonuses) | ||||||||||||||
continue; | continue; | ||||||||||||||
attackBonus *= bonus.Multiplier; | attackBonus *= bonus.Multiplier; | ||||||||||||||
} | } | ||||||||||||||
} | } | ||||||||||||||
return attackBonus; | return attackBonus; | ||||||||||||||
}; | }; | ||||||||||||||
// Calculate the elevation damage multiplier | |||||||||||||||
Stan: You should use doxygen style comments. I'm not sure this function even needs a comment as it's… | |||||||||||||||
elexisUnsubmitted Done Inline Actionsdoxygen = C++, JSdoc = JS. GetElevationDamageBonus would indeed remove the last bit of ambiguity making the comment unneeded. elexis: doxygen = C++, JSdoc = JS.
GetElevationDamageBonus would indeed remove the last bit of… | |||||||||||||||
Attack.prototype.GetElevationBonus = function(type, elevationDifference) | |||||||||||||||
{ | |||||||||||||||
return Math.max(0.1, 1 + 0.01 * (elevationDifference + (this.template[type].ElevationBonus || 0))); | |||||||||||||||
}; | |||||||||||||||
elexisUnsubmitted Done Inline Actions-> Damage component I guess elexis: -> Damage component I guess | |||||||||||||||
/** | /** | ||||||||||||||
* Attack the target entity. This should only be called after a successful range check, | * Attack the target entity. This should only be called after a successful range check, | ||||||||||||||
* and should only be called after GetTimers().repeat msec has passed since the last | * and should only be called after GetTimers().repeat msec has passed since the last | ||||||||||||||
* call to PerformAttack. | * call to PerformAttack. | ||||||||||||||
*/ | */ | ||||||||||||||
Attack.prototype.PerformAttack = function(type, target) | Attack.prototype.PerformAttack = function(type, target) | ||||||||||||||
{ | { | ||||||||||||||
let attackerOwner = Engine.QueryInterface(this.entity, IID_Ownership).GetOwner(); | let attackerOwner = Engine.QueryInterface(this.entity, IID_Ownership).GetOwner(); | ||||||||||||||
let cmpDamage = Engine.QueryInterface(SYSTEM_ENTITY, IID_Damage); | let cmpDamage = Engine.QueryInterface(SYSTEM_ENTITY, IID_Damage); | ||||||||||||||
// If this is a ranged attack, then launch a projectile | // If this is a ranged attack, then launch a projectile | ||||||||||||||
Done Inline ActionsNot sure we need that temp. variable. Stan: Not sure we need that temp. variable. | |||||||||||||||
Done Inline ActionsIt is needed further up in the code as well :) For the TTT calculation. Freagarach: It is needed further up in the code as well :) For the TTT calculation. | |||||||||||||||
if (type == "Ranged") | if (type == "Ranged") | ||||||||||||||
{ | { | ||||||||||||||
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | ||||||||||||||
let turnLength = cmpTimer.GetLatestTurnLength()/1000; | let turnLength = cmpTimer.GetLatestTurnLength()/1000; | ||||||||||||||
// In the future this could be extended: | // In the future this could be extended: | ||||||||||||||
// * Obstacles like trees could reduce the probability of the target being hit | // * Obstacles like trees could reduce the probability of the target being hit | ||||||||||||||
// * Obstacles like walls should block projectiles entirely | // * Obstacles like walls should block projectiles entirely | ||||||||||||||
Show All 13 Lines | if (type == "Ranged") | ||||||||||||||
let previousTargetPosition = Engine.QueryInterface(target, IID_Position).GetPreviousPosition(); | let previousTargetPosition = Engine.QueryInterface(target, IID_Position).GetPreviousPosition(); | ||||||||||||||
let targetVelocity = Vector3D.sub(targetPosition, previousTargetPosition).div(turnLength); | let targetVelocity = Vector3D.sub(targetPosition, previousTargetPosition).div(turnLength); | ||||||||||||||
let timeToTarget = this.PredictTimeToTarget(selfPosition, horizSpeed, targetPosition, targetVelocity); | let timeToTarget = this.PredictTimeToTarget(selfPosition, horizSpeed, targetPosition, targetVelocity); | ||||||||||||||
let predictedPosition = (timeToTarget !== false) ? Vector3D.mult(targetVelocity, timeToTarget).add(targetPosition) : targetPosition; | let predictedPosition = (timeToTarget !== false) ? Vector3D.mult(targetVelocity, timeToTarget).add(targetPosition) : targetPosition; | ||||||||||||||
// Add inaccuracy based on spread. | // Add inaccuracy based on spread. | ||||||||||||||
let distanceModifiedSpread = ApplyValueModificationsToEntity("Attack/Ranged/Spread", +this.template.Ranged.Spread, this.entity) * | let distanceModifiedSpread = ApplyValueModificationsToEntity("Attack/Ranged/Spread", +this.template.Ranged.Spread, this.entity) * | ||||||||||||||
targetPosition.horizDistanceTo(selfPosition) / 100; | predictedPosition.horizDistanceTo(selfPosition) / 100; | ||||||||||||||
let randNorm = randomNormal2D(); | let randNorm = randomNormal2D(); | ||||||||||||||
let offsetX = randNorm[0] * distanceModifiedSpread; | let offsetX = randNorm[0] * distanceModifiedSpread; | ||||||||||||||
let offsetZ = randNorm[1] * distanceModifiedSpread; | let offsetZ = randNorm[1] * distanceModifiedSpread; | ||||||||||||||
let realTargetPosition = new Vector3D(predictedPosition.x + offsetX, targetPosition.y, predictedPosition.z + offsetZ); | let realTargetPosition = new Vector3D(predictedPosition.x + offsetX, targetPosition.y, predictedPosition.z + offsetZ); | ||||||||||||||
let elevationDifference = selfPosition.y - realTargetPosition.y; | |||||||||||||||
// Recalculate when the missile will hit the target position. | // Recalculate when the missile will hit the target position. | ||||||||||||||
let realHorizDistance = realTargetPosition.horizDistanceTo(selfPosition); | let realHorizDistance = realTargetPosition.horizDistanceTo(selfPosition); | ||||||||||||||
timeToTarget = realHorizDistance / horizSpeed; | timeToTarget = realHorizDistance / horizSpeed; | ||||||||||||||
let missileDirection = Vector3D.sub(realTargetPosition, selfPosition).div(realHorizDistance); | let missileDirection = Vector3D.sub(realTargetPosition, selfPosition).div(realHorizDistance); | ||||||||||||||
// Launch the graphical projectile. | // Launch the graphical projectile. | ||||||||||||||
let cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager); | let cmpProjectileManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ProjectileManager); | ||||||||||||||
let id = cmpProjectileManager.LaunchProjectileAtPoint(this.entity, realTargetPosition, horizSpeed, gravity); | let id = cmpProjectileManager.LaunchProjectileAtPoint(this.entity, realTargetPosition, horizSpeed, gravity); | ||||||||||||||
cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | ||||||||||||||
let data = { | let data = { | ||||||||||||||
"type": type, | "type": type, | ||||||||||||||
"attacker": this.entity, | "attacker": this.entity, | ||||||||||||||
"target": target, | "target": target, | ||||||||||||||
"strengths": this.GetAttackStrengths(type), | "strengths": this.GetAttackStrengths(type), | ||||||||||||||
"position": realTargetPosition, | "position": realTargetPosition, | ||||||||||||||
"direction": missileDirection, | "direction": missileDirection, | ||||||||||||||
"projectileId": id, | "projectileId": id, | ||||||||||||||
"multiplier": this.GetAttackBonus(type, target), | "multiplier": this.GetAttackBonus(type, target) * this.GetElevationBonus(type, elevationDifference), | ||||||||||||||
elexisUnsubmitted Done Inline Actionswold be better to only pass atomic values rather than doing any kind of computation (logic) here elexis: wold be better to only pass atomic values rather than doing any kind of computation (logic) here | |||||||||||||||
"isSplash": false, | "isSplash": false, | ||||||||||||||
"attackerOwner": attackerOwner | "attackerOwner": attackerOwner | ||||||||||||||
}; | }; | ||||||||||||||
if (this.template.Ranged.Splash) | if (this.template.Ranged.Splash) | ||||||||||||||
{ | { | ||||||||||||||
data.friendlyFire = this.template.Ranged.Splash.FriendlyFire != "false"; | data.friendlyFire = this.template.Ranged.Splash.FriendlyFire != "false"; | ||||||||||||||
data.radius = +this.template.Ranged.Splash.Range; | data.radius = +this.template.Ranged.Splash.Range; | ||||||||||||||
data.shape = this.template.Ranged.Splash.Shape; | data.shape = this.template.Ranged.Splash.Shape; | ||||||||||||||
Show All 23 Lines | if (cmpCapturable.Reduce(strength, attackerOwner) && IsOwnedByEnemyOfPlayer(attackerOwner, target)) | ||||||||||||||
"attacker": this.entity, | "attacker": this.entity, | ||||||||||||||
"target": target, | "target": target, | ||||||||||||||
"type": type, | "type": type, | ||||||||||||||
"damage": strength, | "damage": strength, | ||||||||||||||
"attackerOwner": attackerOwner | "attackerOwner": attackerOwner | ||||||||||||||
}); | }); | ||||||||||||||
} | } | ||||||||||||||
else | else | ||||||||||||||
{ | { | ||||||||||||||
// Melee attack - hurt the target immediately | // Melee attack - hurt the target immediately | ||||||||||||||
cmpDamage.CauseDamage({ | cmpDamage.CauseDamage({ | ||||||||||||||
"strengths": this.GetAttackStrengths(type), | "strengths": this.GetAttackStrengths(type), | ||||||||||||||
"target": target, | "target": target, | ||||||||||||||
"attacker": this.entity, | "attacker": this.entity, | ||||||||||||||
"multiplier": this.GetAttackBonus(type, target), | "multiplier": this.GetAttackBonus(type, target), | ||||||||||||||
"type": type, | "type": type, | ||||||||||||||
"attackerOwner": attackerOwner | "attackerOwner": attackerOwner | ||||||||||||||
}); | }); | ||||||||||||||
} | } | ||||||||||||||
Done Inline Actions
(or even go the whole way, and: Attacking.HandleAttackEffects(target, { "type": type, "attackData": this.GetAttackEffectsData(type), "attacker": this.entity, "attackerOwner": attackerOwner, "attackerPosition": selfPosition, "attackHeightOffset": this.GetRange(type).elevationBonus }); ) wraitii: (or even go the whole way, and:
```
Attacking.HandleAttackEffects(target, {
"type": type… | |||||||||||||||
}; | }; | ||||||||||||||
/** | /** | ||||||||||||||
* Get the predicted time of collision between a projectile (or a chaser) | * Get the predicted time of collision between a projectile (or a chaser) | ||||||||||||||
* and its target, assuming they both move in straight line at a constant speed. | * and its target, assuming they both move in straight line at a constant speed. | ||||||||||||||
* Vertical component of movement is ignored. | * Vertical component of movement is ignored. | ||||||||||||||
* @param {Vector3D} selfPosition - the 3D position of the projectile (or chaser). | * @param {Vector3D} selfPosition - the 3D position of the projectile (or chaser). | ||||||||||||||
* @param {number} horizSpeed - the horizontal speed of the projectile (or chaser). | * @param {number} horizSpeed - the horizontal speed of the projectile (or chaser). | ||||||||||||||
Show All 39 Lines |
Wildfire Games · Phabricator
You should use doxygen style comments. I'm not sure this function even needs a comment as it's self explicit but maybe for parameters.