Changeset View
Standalone View
binaries/data/mods/public/simulation/components/Formation.js
Show First 20 Lines • Show All 344 Lines • ▼ Show 20 Lines | if (cmpAuras && cmpAuras.HasFormationAura()) | ||||
cmpAuras.ApplyFormationAura(ents); | cmpAuras.ApplyFormationAura(ents); | ||||
} | } | ||||
} | } | ||||
this.offsets = undefined; | this.offsets = undefined; | ||||
// Locate this formation controller in the middle of its members. | // Locate this formation controller in the middle of its members. | ||||
this.MoveToMembersCenter(); | this.MoveToMembersCenter(); | ||||
// Compute the speed etc. of the formation. | // Compute the speed etc. of the formation. | ||||
Freagarach: Ditch. | |||||
this.ComputeMotionParameters(); | this.ComputeMotionParameters(); | ||||
}; | }; | ||||
/** | /** | ||||
* Remove the given list of entities. | * Remove the given list of entities. | ||||
* The entities must already be members of this formation. | * The entities must already be members of this formation. | ||||
* @param {boolean} rename - Whether the removal was part of an entity rename | * @param {boolean} rename - Whether the removal was part of an entity rename | ||||
(prevents disbanding of the formation when under the member limit). | (prevents disbanding of the formation when under the member limit). | ||||
▲ Show 20 Lines • Show All 517 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* Set formation controller's speed based on its current members. | * Set formation controller's speed based on its current members. | ||||
*/ | */ | ||||
Formation.prototype.ComputeMotionParameters = function() | Formation.prototype.ComputeMotionParameters = function() | ||||
{ | { | ||||
let maxRadius = 0; | let maxRadius = 0; | ||||
let minSpeed = Infinity; | let minSpeed = Infinity; | ||||
let minTurnRateSq = Infinity; | |||||
let speedMultiplier = this.GetSpeedMultiplier(); | |||||
for (let ent of this.members) | for (let ent of this.members) | ||||
{ | { | ||||
let cmpUnitMotion = Engine.QueryInterface(ent, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(ent, IID_UnitMotion); | ||||
if (cmpUnitMotion) | if (cmpUnitMotion) | ||||
minSpeed = Math.min(minSpeed, cmpUnitMotion.GetWalkSpeed()); | minSpeed = Math.min(minSpeed, cmpUnitMotion.GetWalkSpeed()); | ||||
} | } | ||||
minSpeed *= this.GetSpeedMultiplier(); | minSpeed *= speedMultiplier; | ||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
cmpUnitMotion.SetSpeedMultiplier(minSpeed / cmpUnitMotion.GetWalkSpeed()); | cmpUnitMotion.SetSpeedMultiplier(minSpeed / cmpUnitMotion.GetWalkSpeed()); | ||||
if (!this.offsets) | |||||
return; | |||||
for (let offset of this.offsets) | |||||
{ | |||||
let offsetLengthSq = Vector2D(offset.x, offset.y).LengthSquared(); | |||||
let cmpUnitMotion = Engine.QueryInterface(offset.ent, IID_UnitMotion); | |||||
Lint: ESLintBear (no-shadow) 'cmpUnitMotion' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'cmpUnitMotion' is already declared in the upper scope.` | |||||
if (cmpUnitMotion) | |||||
{ | |||||
let runSpeed = cmpUnitMotion.GetWalkSpeed() * cmpUnitMotion.GetRunMultiplier() * speedMultiplier; | |||||
minTurnRateSq = Math.min(minTurnRateSq, runSpeed * runSpeed / offsetLengthSq); | |||||
} | |||||
} | |||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | |||||
cmpPosition.SetTurnRate(Math.sqrt(minTurnRateSq)); | |||||
}; | }; | ||||
Formation.prototype.ShapeUpdate = function() | Formation.prototype.ShapeUpdate = function() | ||||
{ | { | ||||
Not Done Inline Actions
Fits nicely here. ;) Freagarach: > Assume the members will need to run in a circle keeping their current offset. Ignore the… | |||||
if (!this.rearrange) | if (!this.rearrange) | ||||
return; | return; | ||||
Not Done Inline ActionsTests? Stan: Tests? | |||||
// Check the distance to twin formations, and merge if | // Check the distance to twin formations, and merge if | ||||
// the formations could collide. | // the formations could collide. | ||||
for (let i = this.twinFormations.length - 1; i >= 0; --i) | for (let i = this.twinFormations.length - 1; i >= 0; --i) | ||||
{ | { | ||||
// Only do the check on one side. | // Only do the check on one side. | ||||
if (this.twinFormations[i] <= this.entity) | if (this.twinFormations[i] <= this.entity) | ||||
continue; | continue; | ||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||
let cmpOtherPosition = Engine.QueryInterface(this.twinFormations[i], IID_Position); | let cmpOtherPosition = Engine.QueryInterface(this.twinFormations[i], IID_Position); | ||||
Not Done Inline ActionsIs this the responsibility of the formation or the unit to compute its turn rate ? Stan: Is this the responsibility of the formation or the unit to compute its turn rate ? | |||||
Done Inline ActionsWe are only setting the turnrate of the formation entity. So that is pretty much the responsibility of the formation. We just need some data from the members' unitMotion components. bb: We are only setting the turnrate of the formation entity. So that is pretty much the… | |||||
Not Done Inline ActionsYeah shouldn't that computation be done by unitmotion instead ? Stan: Yeah shouldn't that computation be done by unitmotion instead ? | |||||
Done Inline ActionsNo unitmotion shouldn't compute this formation specific thingy. Also notice that we use the this.offsets formation internal heavily here. I rather not be moving that around. Also notice the exact same is done for speeds above. bb: No unitmotion shouldn't compute this formation specific thingy. Also notice that we use the… | |||||
let cmpOtherFormation = Engine.QueryInterface(this.twinFormations[i], IID_Formation); | let cmpOtherFormation = Engine.QueryInterface(this.twinFormations[i], IID_Formation); | ||||
if (!cmpPosition || !cmpOtherPosition || !cmpOtherFormation || | if (!cmpPosition || !cmpOtherPosition || !cmpOtherFormation || | ||||
!cmpPosition.IsInWorld() || !cmpOtherPosition.IsInWorld()) | !cmpPosition.IsInWorld() || !cmpOtherPosition.IsInWorld()) | ||||
continue; | continue; | ||||
Not Done Inline ActionsMight be creating a lot of vectors on 200 unit formation? Could maybe create it once and change x, y ? I've seen elexis do that in the past. I suppose we're squaring everything to avoid the vector square root? Should we cache this data on formation creation ? Or using a different data structure' Stan: Might be creating a lot of vectors on 200 unit formation? Could maybe create it once and change… | |||||
Done Inline Actionswe only call this function whenever the offsets change, so there is nothing possible to cache. bb: we only call this function whenever the offsets change, so there is nothing possible to cache. | |||||
let thisPosition = cmpPosition.GetPosition2D(); | let thisPosition = cmpPosition.GetPosition2D(); | ||||
let otherPosition = cmpOtherPosition.GetPosition2D(); | let otherPosition = cmpOtherPosition.GetPosition2D(); | ||||
let dx = thisPosition.x - otherPosition.x; | let dx = thisPosition.x - otherPosition.x; | ||||
let dy = thisPosition.y - otherPosition.y; | let dy = thisPosition.y - otherPosition.y; | ||||
let dist = Math.sqrt(dx * dx + dy * dy); | let dist = Math.sqrt(dx * dx + dy * dy); | ||||
▲ Show 20 Lines • Show All 122 Lines • Show Last 20 Lines |
Ditch.