Add accelerations in unit movement.

This helps preventing arrow dodging.

Differential Revision: D3200
Reviewed By: Freagarach
Comments By: wraitii, vladislav, Palaxin, Stan
refs: #5106

This was SVN commit r25953.
This commit is contained in:
bb
2021-10-09 21:31:11 +00:00
parent 4640a1fd36
commit acc780bcbb
79 changed files with 226 additions and 43 deletions
@@ -437,10 +437,12 @@ function GetTemplateDataHelper(template, player, auraTemplates, modifiers = {})
if (template.UnitMotion) if (template.UnitMotion)
{ {
const walkSpeed = getEntityValue("UnitMotion/WalkSpeed");
ret.speed = { ret.speed = {
"walk": getEntityValue("UnitMotion/WalkSpeed"), "walk": walkSpeed,
"run": walkSpeed,
"acceleration": getEntityValue("UnitMotion/Acceleration")
}; };
ret.speed.run = getEntityValue("UnitMotion/WalkSpeed");
if (template.UnitMotion.RunMultiplier) if (template.UnitMotion.RunMultiplier)
ret.speed.run *= getEntityValue("UnitMotion/RunMultiplier"); ret.speed.run *= getEntityValue("UnitMotion/RunMultiplier");
} }
@@ -1005,12 +1005,13 @@ function getSpeedTooltip(template)
if (!template.speed) if (!template.speed)
return ""; return "";
let walk = template.speed.walk.toFixed(1); const walk = template.speed.walk.toFixed(1);
let run = template.speed.run.toFixed(1); const run = template.speed.run.toFixed(1);
if (walk == 0 && run == 0) if (walk == 0 && run == 0)
return ""; return "";
const acceleration = template.speed.acceleration.toFixed(1);
return sprintf(translate("%(label)s %(speeds)s"), { return sprintf(translate("%(label)s %(speeds)s"), {
"label": headerFont(translate("Speed:")), "label": headerFont(translate("Speed:")),
"speeds": "speeds":
@@ -1022,6 +1023,11 @@ function getSpeedTooltip(template)
sprintf(translate("%(speed)s %(movementType)s"), { sprintf(translate("%(speed)s %(movementType)s"), {
"speed": run, "speed": run,
"movementType": unitFont(translate("Run")) "movementType": unitFont(translate("Run"))
}) +
commaFont(translate(", ")) +
sprintf(translate("%(speed)s %(movementType)s"), {
"speed": acceleration,
"movementType": unitFont(translate("Acceleration"))
}) })
}); });
} }
@@ -895,17 +895,22 @@ Formation.prototype.ComputeMotionParameters = function()
{ {
let maxRadius = 0; let maxRadius = 0;
let minSpeed = Infinity; let minSpeed = Infinity;
let minAcceleration = Infinity;
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());
minAcceleration = Math.min(minAcceleration, cmpUnitMotion.GetAcceleration());
}
} }
minSpeed *= this.GetSpeedMultiplier(); minSpeed *= this.GetSpeedMultiplier();
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());
cmpUnitMotion.SetAcceleration(minAcceleration);
}; };
Formation.prototype.ShapeUpdate = function() Formation.prototype.ShapeUpdate = function()
@@ -585,7 +585,8 @@ GuiInterface.prototype.GetEntityState = function(player, ent)
if (cmpUnitMotion) if (cmpUnitMotion)
ret.speed = { ret.speed = {
"walk": cmpUnitMotion.GetWalkSpeed(), "walk": cmpUnitMotion.GetWalkSpeed(),
"run": cmpUnitMotion.GetWalkSpeed() * cmpUnitMotion.GetRunMultiplier() "run": cmpUnitMotion.GetWalkSpeed() * cmpUnitMotion.GetRunMultiplier(),
"acceleration": cmpUnitMotion.GetAcceleration()
}; };
let cmpUpkeep = Engine.QueryInterface(ent, IID_Upkeep); let cmpUpkeep = Engine.QueryInterface(ent, IID_Upkeep);
@@ -345,6 +345,16 @@ UnitMotionFlying.prototype.GetSpeedMultiplier = function()
return this.speed / +this.template.MaxSpeed; return this.speed / +this.template.MaxSpeed;
}; };
UnitMotionFlying.prototype.GetAcceleration = function()
{
return +this.template.AccelRate;
};
UnitMotionFlying.prototype.SetAcceleration = function()
{
// Acceleration is set by the template. Ignore.
};
UnitMotionFlying.prototype.GetPassabilityClassName = function() UnitMotionFlying.prototype.GetPassabilityClassName = function()
{ {
return this.template.PassabilityClass; return this.template.PassabilityClass;
@@ -94,6 +94,7 @@ TestTargetEntityRenaming(
"MoveToTargetRange": () => true, "MoveToTargetRange": () => true,
"GetRunMultiplier": () => 1, "GetRunMultiplier": () => 1,
"SetSpeedMultiplier": () => {}, "SetSpeedMultiplier": () => {},
"GetAcceleration": () => 1,
"StopMoving": () => {} "StopMoving": () => {}
}); });
@@ -168,6 +169,7 @@ function TestFormationExiting(mode)
AddMock(unit, IID_UnitMotion, { AddMock(unit, IID_UnitMotion, {
"GetWalkSpeed": () => 1, "GetWalkSpeed": () => 1,
"GetAcceleration": () => 1,
"MoveToFormationOffset": (target, x, z) => {}, "MoveToFormationOffset": (target, x, z) => {},
"MoveToTargetRange": (target, min, max) => true, "MoveToTargetRange": (target, min, max) => true,
"SetMemberOfFormation": () => {}, "SetMemberOfFormation": () => {},
@@ -243,6 +245,7 @@ function TestFormationExiting(mode)
"GetWalkSpeed": () => 1, "GetWalkSpeed": () => 1,
"StopMoving": () => {}, "StopMoving": () => {},
"SetSpeedMultiplier": () => {}, "SetSpeedMultiplier": () => {},
"SetAcceleration": (accel) => {},
"MoveToPointRange": () => true, "MoveToPointRange": () => true,
"SetFacePointAfterMove": () => {}, "SetFacePointAfterMove": () => {},
"GetFacePointAfterMove": () => true, "GetFacePointAfterMove": () => true,
@@ -348,6 +351,7 @@ function TestMoveIntoFormationWhileAttacking()
AddMock(unit + i, IID_UnitMotion, { AddMock(unit + i, IID_UnitMotion, {
"GetWalkSpeed": () => 1, "GetWalkSpeed": () => 1,
"GetAcceleration": () => 1,
"MoveToFormationOffset": (target, x, z) => {}, "MoveToFormationOffset": (target, x, z) => {},
"MoveToTargetRange": (target, min, max) => true, "MoveToTargetRange": (target, min, max) => true,
"SetMemberOfFormation": () => {}, "SetMemberOfFormation": () => {},
@@ -414,6 +418,7 @@ function TestMoveIntoFormationWhileAttacking()
AddMock(controller, IID_UnitMotion, { AddMock(controller, IID_UnitMotion, {
"GetWalkSpeed": () => 1, "GetWalkSpeed": () => 1,
"SetSpeedMultiplier": (speed) => {}, "SetSpeedMultiplier": (speed) => {},
"SetAcceleration": (accel) => {},
"MoveToPointRange": (x, z, minRange, maxRange) => {}, "MoveToPointRange": (x, z, minRange, maxRange) => {},
"StopMoving": () => {}, "StopMoving": () => {},
"SetFacePointAfterMove": () => {}, "SetFacePointAfterMove": () => {},
@@ -27,6 +27,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.45</WalkSpeed> <WalkSpeed op="mul">0.45</WalkSpeed>
<Acceleration op="mul">0.45</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/camel.xml</Actor> <Actor>fauna/camel.xml</Actor>
@@ -42,6 +42,7 @@
</UnitAI> </UnitAI>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.15</WalkSpeed> <WalkSpeed op="mul">0.15</WalkSpeed>
<Acceleration op="mul">0.15</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/chicken.xml</Actor> <Actor>fauna/chicken.xml</Actor>
@@ -47,6 +47,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.3</WalkSpeed> <WalkSpeed op="mul">0.3</WalkSpeed>
<Acceleration op="mul">0.3</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/crocodile.xml</Actor> <Actor>fauna/crocodile.xml</Actor>
@@ -28,6 +28,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.8</WalkSpeed> <WalkSpeed op="mul">0.8</WalkSpeed>
<Acceleration op="mul">0.8</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/donkey.xml</Actor> <Actor>fauna/donkey.xml</Actor>
@@ -20,6 +20,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.6</WalkSpeed> <WalkSpeed op="mul">0.6</WalkSpeed>
<Acceleration op="mul">0.6</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/giraffe_adult.xml</Actor> <Actor>fauna/giraffe_adult.xml</Actor>
@@ -20,6 +20,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.6</WalkSpeed> <WalkSpeed op="mul">0.6</WalkSpeed>
<Acceleration op="mul">0.6</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/giraffe_baby.xml</Actor> <Actor>fauna/giraffe_baby.xml</Actor>
@@ -35,6 +35,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.45</WalkSpeed> <WalkSpeed op="mul">0.45</WalkSpeed>
<Acceleration op="mul">0.45</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/goat.xml</Actor> <Actor>fauna/goat.xml</Actor>
@@ -28,6 +28,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.8</WalkSpeed> <WalkSpeed op="mul">0.8</WalkSpeed>
<Acceleration op="mul">0.8</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/horse.xml</Actor> <Actor>fauna/horse.xml</Actor>
@@ -36,6 +36,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.45</WalkSpeed> <WalkSpeed op="mul">0.45</WalkSpeed>
<Acceleration op="mul">0.45</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/lion.xml</Actor> <Actor>fauna/lion.xml</Actor>
@@ -40,6 +40,7 @@
</UnitAI> </UnitAI>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.3</WalkSpeed> <WalkSpeed op="mul">0.3</WalkSpeed>
<Acceleration op="mul">0.3</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/peacock.xml</Actor> <Actor>fauna/peacock.xml</Actor>
@@ -35,6 +35,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.45</WalkSpeed> <WalkSpeed op="mul">0.45</WalkSpeed>
<Acceleration op="mul">0.45</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/pig1.xml</Actor> <Actor>fauna/pig1.xml</Actor>
@@ -29,6 +29,7 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">3.5</WalkSpeed> <WalkSpeed op="mul">3.5</WalkSpeed>
<Acceleration op="mul">3.5</Acceleration>
</UnitMotion> </UnitMotion>
<Upgrade disable=""/> <Upgrade disable=""/>
<VisualActor> <VisualActor>
@@ -19,6 +19,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.25</WalkSpeed> <WalkSpeed op="mul">0.25</WalkSpeed>
<Acceleration op="mul">0.25</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/piglet.xml</Actor> <Actor>fauna/piglet.xml</Actor>
@@ -45,6 +45,7 @@
<UnitMotion> <UnitMotion>
<PassabilityClass>ship-small</PassabilityClass> <PassabilityClass>ship-small</PassabilityClass>
<WalkSpeed op="mul">0.6</WalkSpeed> <WalkSpeed op="mul">0.6</WalkSpeed>
<Acceleration op="mul">0.6</Acceleration>
</UnitMotion> </UnitMotion>
<Visibility> <Visibility>
<RetainInFog>false</RetainInFog> <RetainInFog>false</RetainInFog>
@@ -35,6 +35,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.45</WalkSpeed> <WalkSpeed op="mul">0.45</WalkSpeed>
<Acceleration op="mul">0.45</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/sheep3.xml</Actor> <Actor>fauna/sheep3.xml</Actor>
@@ -20,6 +20,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/wildebeest.xml</Actor> <Actor>fauna/wildebeest.xml</Actor>
@@ -20,6 +20,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>fauna/zebra.xml</Actor> <Actor>fauna/zebra.xml</Actor>
@@ -69,8 +69,10 @@
</UnitAI> </UnitAI>
<UnitMotion> <UnitMotion>
<FormationController>true</FormationController> <FormationController>true</FormationController>
<WalkSpeed>1.0</WalkSpeed> <WalkSpeed>1</WalkSpeed>
<RunMultiplier>100.0</RunMultiplier> <!-- = Max formation speed --> <RunMultiplier>100</RunMultiplier> <!-- = Max formation speed -->
<InstantTurnAngle>0.1</InstantTurnAngle>
<Acceleration>100</Acceleration> <!-- Unused -->
<PassabilityClass>large</PassabilityClass> <PassabilityClass>large</PassabilityClass>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -123,8 +123,10 @@
<UnitMotion> <UnitMotion>
<FormationController>false</FormationController> <FormationController>false</FormationController>
<PassabilityClass>default</PassabilityClass> <PassabilityClass>default</PassabilityClass>
<WalkSpeed>9.0</WalkSpeed> <WalkSpeed>9</WalkSpeed>
<RunMultiplier>1.67</RunMultiplier> <RunMultiplier>1.67</RunMultiplier>
<InstantTurnAngle>1.5</InstantTurnAngle>
<Acceleration>18</Acceleration>
</UnitMotion> </UnitMotion>
<Visibility> <Visibility>
<RetainInFog>false</RetainInFog> <RetainInFog>false</RetainInFog>
@@ -52,6 +52,7 @@
<UnitMotion> <UnitMotion>
<PassabilityClass>large</PassabilityClass> <PassabilityClass>large</PassabilityClass>
<WalkSpeed op="mul">0.55</WalkSpeed> <WalkSpeed op="mul">0.55</WalkSpeed>
<Acceleration op="mul">0.275</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>units/global/catafalque.xml</Actor> <Actor>units/global/catafalque.xml</Actor>
@@ -36,5 +36,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.85</WalkSpeed> <WalkSpeed op="mul">0.85</WalkSpeed>
<Acceleration op="mul">0.85</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -41,5 +41,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.8</WalkSpeed> <WalkSpeed op="mul">0.8</WalkSpeed>
<Acceleration op="mul">0.8</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -36,5 +36,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -42,5 +42,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.85</WalkSpeed> <WalkSpeed op="mul">0.85</WalkSpeed>
<Acceleration op="mul">0.85</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -42,5 +42,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.8</WalkSpeed> <WalkSpeed op="mul">0.8</WalkSpeed>
<Acceleration op="mul">0.8</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -42,5 +42,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -55,6 +55,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<PassabilityClass>large</PassabilityClass> <PassabilityClass>large</PassabilityClass>
<Acceleration op="mul">0.5</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>100</Range> <Range>100</Range>
@@ -46,5 +46,6 @@
<Turretable/> <Turretable/>
<UnitMotion> <UnitMotion>
<WalkSpeed op="add">1.2</WalkSpeed> <WalkSpeed op="add">1.2</WalkSpeed>
<Acceleration op="add">2.4</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -46,5 +46,6 @@
<Turretable/> <Turretable/>
<UnitMotion> <UnitMotion>
<WalkSpeed op="add">0.6</WalkSpeed> <WalkSpeed op="add">0.6</WalkSpeed>
<Acceleration op="add">1.2</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -46,5 +46,6 @@
<Turretable/> <Turretable/>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.2</WalkSpeed> <WalkSpeed op="mul">1.2</WalkSpeed>
<Acceleration op="mul">1.2</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -46,5 +46,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -67,6 +67,7 @@
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.5</WalkSpeed> <WalkSpeed op="mul">1.5</WalkSpeed>
<RunMultiplier>2</RunMultiplier> <RunMultiplier>2</RunMultiplier>
<Acceleration op="mul">1.5</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>30</Range> <Range>30</Range>
@@ -54,6 +54,7 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<PassabilityClass>large</PassabilityClass> <PassabilityClass>large</PassabilityClass>
<Acceleration op="mul">0.5</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>100</Range> <Range>100</Range>
@@ -46,6 +46,7 @@
</UnitAI> </UnitAI>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.7</WalkSpeed> <WalkSpeed op="mul">0.7</WalkSpeed>
<Acceleration op="mul">0.7</Acceleration>
</UnitMotion> </UnitMotion>
<Visibility> <Visibility>
<RetainInFog>true</RetainInFog> <RetainInFog>true</RetainInFog>
@@ -11,5 +11,6 @@
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.4</WalkSpeed> <WalkSpeed op="mul">0.4</WalkSpeed>
<RunMultiplier>1.4</RunMultiplier> <RunMultiplier>1.4</RunMultiplier>
<Acceleration op="mul">0.4</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -16,5 +16,6 @@
<PassabilityClass>large</PassabilityClass> <PassabilityClass>large</PassabilityClass>
<WalkSpeed op="mul">0.4</WalkSpeed> <WalkSpeed op="mul">0.4</WalkSpeed>
<RunMultiplier>2.0</RunMultiplier> <RunMultiplier>2.0</RunMultiplier>
<Acceleration op="mul">0.4</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -21,5 +21,6 @@
<UnitMotion> <UnitMotion>
<PassabilityClass>large</PassabilityClass> <PassabilityClass>large</PassabilityClass>
<WalkSpeed op="mul">0.5</WalkSpeed> <WalkSpeed op="mul">0.5</WalkSpeed>
<Acceleration op="mul">0.25</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -55,5 +55,6 @@
<PassabilityClass>ship-small</PassabilityClass> <PassabilityClass>ship-small</PassabilityClass>
<WalkSpeed op="mul">1.8</WalkSpeed> <WalkSpeed op="mul">1.8</WalkSpeed>
<RunMultiplier>1</RunMultiplier> <RunMultiplier>1</RunMultiplier>
<Acceleration op="mul">1.8</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -14,5 +14,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.6</WalkSpeed> <WalkSpeed op="mul">1.6</WalkSpeed>
<Acceleration op="mul">1.6</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -42,5 +42,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.85</WalkSpeed> <WalkSpeed op="mul">0.85</WalkSpeed>
<Acceleration op="mul">0.85</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -42,5 +42,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.8</WalkSpeed> <WalkSpeed op="mul">0.8</WalkSpeed>
<Acceleration op="mul">0.8</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -42,5 +42,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -73,5 +73,6 @@
</StatusBars> </StatusBars>
<UnitMotion> <UnitMotion>
<PassabilityClass>large</PassabilityClass> <PassabilityClass>large</PassabilityClass>
<Acceleration op="mul">0.5</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -50,5 +50,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -48,5 +48,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="add">1.2</WalkSpeed> <WalkSpeed op="add">1.2</WalkSpeed>
<Acceleration op="add">2.4</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -49,5 +49,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="add">0.6</WalkSpeed> <WalkSpeed op="add">0.6</WalkSpeed>
<Acceleration op="add">1.2</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -47,5 +47,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="add">2.4</WalkSpeed> <WalkSpeed op="add">2.4</WalkSpeed>
<Acceleration op="add">4.8</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -49,5 +49,6 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.2</WalkSpeed> <WalkSpeed op="mul">1.2</WalkSpeed>
<Acceleration op="mul">1.2</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -73,5 +73,7 @@
<TreasureCollector disable=""/> <TreasureCollector disable=""/>
<UnitMotion> <UnitMotion>
<PassabilityClass>ship</PassabilityClass> <PassabilityClass>ship</PassabilityClass>
<InstantTurnAngle>0.5</InstantTurnAngle>
<Acceleration op="mul">0.25</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -59,6 +59,7 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.55</WalkSpeed> <WalkSpeed op="mul">1.55</WalkSpeed>
<Acceleration op="mul">1.55</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>90</Range> <Range>90</Range>
@@ -47,6 +47,7 @@
<UnitMotion> <UnitMotion>
<PassabilityClass>ship-small</PassabilityClass> <PassabilityClass>ship-small</PassabilityClass>
<WalkSpeed op="mul">1.6</WalkSpeed> <WalkSpeed op="mul">1.6</WalkSpeed>
<Acceleration op="mul">1.6</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>60</Range> <Range>60</Range>
@@ -71,6 +71,7 @@
<UnitMotion> <UnitMotion>
<PassabilityClass>ship-small</PassabilityClass> <PassabilityClass>ship-small</PassabilityClass>
<WalkSpeed op="mul">1.1</WalkSpeed> <WalkSpeed op="mul">1.1</WalkSpeed>
<Acceleration op="mul">1.1</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>30</Range> <Range>30</Range>
@@ -39,6 +39,7 @@
<UnitMotion> <UnitMotion>
<PassabilityClass>ship-small</PassabilityClass> <PassabilityClass>ship-small</PassabilityClass>
<WalkSpeed op="mul">1.35</WalkSpeed> <WalkSpeed op="mul">1.35</WalkSpeed>
<Acceleration op="mul">1.6</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>50</Range> <Range>50</Range>
@@ -67,6 +67,7 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.8</WalkSpeed> <WalkSpeed op="mul">1.8</WalkSpeed>
<Acceleration op="mul">1.8</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>110</Range> <Range>110</Range>
@@ -62,6 +62,7 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.8</WalkSpeed> <WalkSpeed op="mul">1.8</WalkSpeed>
<Acceleration op="mul">1.8</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>90</Range> <Range>90</Range>
@@ -60,5 +60,7 @@
<UnitMotion> <UnitMotion>
<PassabilityClass>large</PassabilityClass> <PassabilityClass>large</PassabilityClass>
<RunMultiplier>1</RunMultiplier> <RunMultiplier>1</RunMultiplier>
<InstantTurnAngle>0.75</InstantTurnAngle>
<Acceleration op="mul">0.25</Acceleration>
</UnitMotion> </UnitMotion>
</Entity> </Entity>
@@ -71,6 +71,7 @@
</UnitAI> </UnitAI>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>100</Range> <Range>100</Range>
@@ -59,6 +59,7 @@
</Sound> </Sound>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.8</WalkSpeed> <WalkSpeed op="mul">0.8</WalkSpeed>
<Acceleration op="mul">0.8</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>80</Range> <Range>80</Range>
@@ -64,6 +64,7 @@
</UnitAI> </UnitAI>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.8</WalkSpeed> <WalkSpeed op="mul">0.8</WalkSpeed>
<Acceleration op="mul">0.8</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>100</Range> <Range>100</Range>
@@ -95,6 +95,7 @@
</Resistance> </Resistance>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.7</WalkSpeed> <WalkSpeed op="mul">0.7</WalkSpeed>
<Acceleration op="mul">0.7</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>80</Range> <Range>80</Range>
@@ -70,6 +70,7 @@
<UnitMotion> <UnitMotion>
<PassabilityClass>large</PassabilityClass> <PassabilityClass>large</PassabilityClass>
<WalkSpeed op="mul">0.6</WalkSpeed> <WalkSpeed op="mul">0.6</WalkSpeed>
<Acceleration op="mul">0.3</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range>50</Range> <Range>50</Range>
@@ -23,6 +23,7 @@
</Loot> </Loot>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>structures/celts/warship.xml</Actor> <Actor>structures/celts/warship.xml</Actor>
@@ -17,6 +17,7 @@
</Resistance> </Resistance>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.4</WalkSpeed> <WalkSpeed op="mul">1.4</WalkSpeed>
<Acceleration op="mul">1.4</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>units/gauls/infantry_spearman_c.xml</Actor> <Actor>units/gauls/infantry_spearman_c.xml</Actor>
@@ -23,6 +23,7 @@
</Loot> </Loot>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>structures/celts/warship.xml</Actor> <Actor>structures/celts/warship.xml</Actor>
@@ -24,6 +24,7 @@
</Loot> </Loot>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>structures/iberians/warship.xml</Actor> <Actor>structures/iberians/warship.xml</Actor>
@@ -23,6 +23,7 @@
</Loot> </Loot>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">0.9</WalkSpeed> <WalkSpeed op="mul">0.9</WalkSpeed>
<Acceleration op="mul">0.9</Acceleration>
</UnitMotion> </UnitMotion>
<VisualActor> <VisualActor>
<Actor>structures/mauryas/trireme.xml</Actor> <Actor>structures/mauryas/trireme.xml</Actor>
@@ -36,6 +36,7 @@
</TrainingRestrictions> </TrainingRestrictions>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.5</WalkSpeed> <WalkSpeed op="mul">1.5</WalkSpeed>
<Acceleration op="mul">1.5</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range op="mul">0.5</Range> <Range op="mul">0.5</Range>
@@ -37,6 +37,7 @@
</TrainingRestrictions> </TrainingRestrictions>
<UnitMotion> <UnitMotion>
<WalkSpeed op="mul">1.4</WalkSpeed> <WalkSpeed op="mul">1.4</WalkSpeed>
<Acceleration op="mul">1.4</Acceleration>
</UnitMotion> </UnitMotion>
<Vision> <Vision>
<Range op="mul">0.5</Range> <Range op="mul">0.5</Range>
+90 -34
View File
@@ -153,7 +153,7 @@ public:
bool m_IsFormationController; bool m_IsFormationController;
fixed m_TemplateWalkSpeed, m_TemplateRunMultiplier; fixed m_TemplateWalkSpeed, m_TemplateRunMultiplier, m_TemplateAcceleration;
pass_class_t m_PassClass; pass_class_t m_PassClass;
std::string m_PassClassName; std::string m_PassClassName;
@@ -225,8 +225,12 @@ public:
// This caches the resulting speed from m_WalkSpeed * m_SpeedMultiplier for convenience. // This caches the resulting speed from m_WalkSpeed * m_SpeedMultiplier for convenience.
fixed m_Speed; fixed m_Speed;
// Current mean speed (over the last turn). // The speed achieved at the end of the current turn.
fixed m_CurSpeed; fixed m_CurrentSpeed;
fixed m_InstantTurnAngle;
fixed m_Acceleration;
// Currently active paths (storing waypoints in reverse order). // Currently active paths (storing waypoints in reverse order).
// The last item in each path is the point we're currently heading towards. // The last item in each path is the point we're currently heading towards.
@@ -244,15 +248,21 @@ public:
"<element name='FormationController'>" "<element name='FormationController'>"
"<data type='boolean'/>" "<data type='boolean'/>"
"</element>" "</element>"
"<element name='WalkSpeed' a:help='Basic movement speed (in metres per second)'>" "<element name='WalkSpeed' a:help='Basic movement speed (in metres per second).'>"
"<ref name='positiveDecimal'/>" "<ref name='positiveDecimal'/>"
"</element>" "</element>"
"<optional>" "<optional>"
"<element name='RunMultiplier' a:help='How much faster the unit goes when running (as a multiple of walk speed)'>" "<element name='RunMultiplier' a:help='How much faster the unit goes when running (as a multiple of walk speed).'>"
"<ref name='positiveDecimal'/>" "<ref name='positiveDecimal'/>"
"</element>" "</element>"
"</optional>" "</optional>"
"<element name='PassabilityClass' a:help='Identifies the terrain passability class (values are defined in special/pathfinder.xml)'>" "<element name='InstantTurnAngle' a:help='Angle we can turn instantly. Any value greater than pi will disable turning times. Avoid zero since it stops the entity every turn.'>"
"<ref name='positiveDecimal'/>"
"</element>"
"<element name='Acceleration' a:help='Acceleration (in metres per second^2).'>"
"<ref name='positiveDecimal'/>"
"</element>"
"<element name='PassabilityClass' a:help='Identifies the terrain passability class (values are defined in special/pathfinder.xml).'>"
"<text/>" "<text/>"
"</element>" "</element>"
"<optional>" "<optional>"
@@ -270,12 +280,16 @@ public:
m_WalkSpeed = m_TemplateWalkSpeed = m_Speed = paramNode.GetChild("WalkSpeed").ToFixed(); m_WalkSpeed = m_TemplateWalkSpeed = m_Speed = paramNode.GetChild("WalkSpeed").ToFixed();
m_SpeedMultiplier = fixed::FromInt(1); m_SpeedMultiplier = fixed::FromInt(1);
m_CurSpeed = fixed::Zero(); m_CurrentSpeed = fixed::Zero();
m_RunMultiplier = m_TemplateRunMultiplier = fixed::FromInt(1); m_RunMultiplier = m_TemplateRunMultiplier = fixed::FromInt(1);
if (paramNode.GetChild("RunMultiplier").IsOk()) if (paramNode.GetChild("RunMultiplier").IsOk())
m_RunMultiplier = m_TemplateRunMultiplier = paramNode.GetChild("RunMultiplier").ToFixed(); m_RunMultiplier = m_TemplateRunMultiplier = paramNode.GetChild("RunMultiplier").ToFixed();
m_InstantTurnAngle = paramNode.GetChild("InstantTurnAngle").ToFixed();
m_Acceleration = m_TemplateAcceleration = paramNode.GetChild("Acceleration").ToFixed();
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
if (cmpPathfinder) if (cmpPathfinder)
{ {
@@ -322,7 +336,11 @@ public:
serialize.NumberFixed_Unbounded("speed multiplier", m_SpeedMultiplier); serialize.NumberFixed_Unbounded("speed multiplier", m_SpeedMultiplier);
serialize.NumberFixed_Unbounded("current speed", m_CurSpeed); serialize.NumberFixed_Unbounded("current speed", m_CurrentSpeed);
serialize.NumberFixed_Unbounded("instant turn angle", m_InstantTurnAngle);
serialize.NumberFixed_Unbounded("acceleration", m_Acceleration);
serialize.Bool("facePointAfterMove", m_FacePointAfterMove); serialize.Bool("facePointAfterMove", m_FacePointAfterMove);
serialize.Bool("pushing", m_Pushing); serialize.Bool("pushing", m_Pushing);
@@ -456,15 +474,25 @@ public:
CFixedVector2D pos = cmpPosition->GetPosition2D(); CFixedVector2D pos = cmpPosition->GetPosition2D();
entity_angle_t angle = cmpPosition->GetRotation().Y; entity_angle_t angle = cmpPosition->GetRotation().Y;
fixed speed = m_CurrentSpeed;
// Copy the path so we don't change it. // Copy the path so we don't change it.
WaypointPath shortPath = m_ShortPath; WaypointPath shortPath = m_ShortPath;
WaypointPath longPath = m_LongPath; WaypointPath longPath = m_LongPath;
PerformMove(dt, cmpPosition->GetTurnRate(), shortPath, longPath, pos, angle); PerformMove(dt, cmpPosition->GetTurnRate(), shortPath, longPath, pos, speed, angle);
return pos; return pos;
} }
virtual fixed GetAcceleration() const
{
return m_Acceleration;
}
virtual void SetAcceleration(fixed acceleration)
{
m_Acceleration = acceleration;
}
virtual pass_class_t GetPassabilityClass() const virtual pass_class_t GetPassabilityClass() const
{ {
return m_PassClass; return m_PassClass;
@@ -485,7 +513,7 @@ public:
virtual fixed GetCurrentSpeed() const virtual fixed GetCurrentSpeed() const
{ {
return m_CurSpeed; return m_CurrentSpeed;
} }
virtual void SetFacePointAfterMove(bool facePointAfterMove) virtual void SetFacePointAfterMove(bool facePointAfterMove)
@@ -721,13 +749,13 @@ private:
* This does not send actually change the position. * This does not send actually change the position.
* @returns true if the move was obstructed. * @returns true if the move was obstructed.
*/ */
bool PerformMove(fixed dt, const fixed& turnRate, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, entity_angle_t& angle) const; bool PerformMove(fixed dt, const fixed& turnRate, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, fixed& speed, entity_angle_t& angle) const;
/** /**
* Update other components on our speed. * Update other components on our speed.
* (For performance, this should try to avoid sending messages). * (For performance, this should try to avoid sending messages).
*/ */
void UpdateMovementState(entity_pos_t speed); void UpdateMovementState(entity_pos_t speed, entity_pos_t meanSpeed);
/** /**
* React if our move was obstructed. * React if our move was obstructed.
@@ -993,7 +1021,7 @@ void CCmpUnitMotion::PreMove(CCmpUnitMotionManager::MotionState& state)
// If we were idle and will still be, no need for an update. // If we were idle and will still be, no need for an update.
state.needUpdate = state.cmpPosition->IsInWorld() && state.needUpdate = state.cmpPosition->IsInWorld() &&
(m_CurSpeed != fixed::Zero() || m_MoveRequest.m_Type != MoveRequest::NONE); (m_CurrentSpeed != fixed::Zero() || m_MoveRequest.m_Type != MoveRequest::NONE);
if (!m_BlockMovement) if (!m_BlockMovement)
return; return;
@@ -1017,7 +1045,7 @@ void CCmpUnitMotion::Move(CCmpUnitMotionManager::MotionState& state, fixed dt)
// to it, then throw away our current path and go straight to it. // to it, then throw away our current path and go straight to it.
state.wentStraight = TryGoingStraightToTarget(state.initialPos, true); state.wentStraight = TryGoingStraightToTarget(state.initialPos, true);
state.wasObstructed = PerformMove(dt, state.cmpPosition->GetTurnRate(), m_ShortPath, m_LongPath, state.pos, state.angle); state.wasObstructed = PerformMove(dt, state.cmpPosition->GetTurnRate(), m_ShortPath, m_LongPath, state.pos, state.speed, state.angle);
} }
void CCmpUnitMotion::PostMove(CCmpUnitMotionManager::MotionState& state, fixed dt) void CCmpUnitMotion::PostMove(CCmpUnitMotionManager::MotionState& state, fixed dt)
@@ -1027,7 +1055,7 @@ void CCmpUnitMotion::PostMove(CCmpUnitMotionManager::MotionState& state, fixed d
{ {
if (state.angle != state.initialAngle) if (state.angle != state.initialAngle)
state.cmpPosition->TurnTo(state.angle); state.cmpPosition->TurnTo(state.angle);
UpdateMovementState(fixed::Zero()); UpdateMovementState(fixed::Zero(), fixed::Zero());
} }
else else
{ {
@@ -1041,7 +1069,7 @@ void CCmpUnitMotion::PostMove(CCmpUnitMotionManager::MotionState& state, fixed d
state.cmpPosition->MoveAndTurnTo(state.pos.X, state.pos.Y, state.angle); state.cmpPosition->MoveAndTurnTo(state.pos.X, state.pos.Y, state.angle);
// Calculate the mean speed over this past turn. // Calculate the mean speed over this past turn.
UpdateMovementState(offset.Length() / dt); UpdateMovementState(state.speed, offset.Length() / dt);
} }
if (state.wasObstructed && HandleObstructedMove(state.pos != state.initialPos)) if (state.wasObstructed && HandleObstructedMove(state.pos != state.initialPos))
@@ -1094,7 +1122,7 @@ bool CCmpUnitMotion::PossiblyAtDestination() const
return false; return false;
} }
bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, entity_angle_t& angle) const bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, fixed& speed, entity_angle_t& angle) const
{ {
// If there are no waypoint, behave as though we were obstructed and let HandleObstructedMove handle it. // If there are no waypoint, behave as though we were obstructed and let HandleObstructedMove handle it.
if (shortPath.m_Waypoints.empty() && longPath.m_Waypoints.empty()) if (shortPath.m_Waypoints.empty() && longPath.m_Waypoints.empty())
@@ -1151,21 +1179,26 @@ bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath&
target = CFixedVector2D(shortPath.m_Waypoints.back().x, shortPath.m_Waypoints.back().z); target = CFixedVector2D(shortPath.m_Waypoints.back().x, shortPath.m_Waypoints.back().z);
CFixedVector2D offset = target - pos; CFixedVector2D offset = target - pos;
if (turnRate > zero && !offset.IsZero())
fixed angleDiff = angle - atan2_approx(offset.X, offset.Y);
fixed absoluteAngleDiff = angleDiff.Absolute();
if (absoluteAngleDiff > entity_angle_t::Pi())
absoluteAngleDiff = entity_angle_t::Pi() * 2 - absoluteAngleDiff;
// We only rotate to the instantTurnAngle angle. The rest we rotate during movement.
if (absoluteAngleDiff > m_InstantTurnAngle)
{ {
fixed maxRotation = turnRate.Multiply(timeLeft); // Stop moving when rotating this far.
fixed angleDiff = angle - atan2_approx(offset.X, offset.Y); speed = zero;
if (angleDiff != zero) if (turnRate > zero && !offset.IsZero())
{ {
fixed absoluteAngleDiff = angleDiff.Absolute(); fixed maxRotation = turnRate.Multiply(timeLeft);
if (absoluteAngleDiff > entity_angle_t::Pi())
absoluteAngleDiff = entity_angle_t::Pi() * 2 - absoluteAngleDiff;
// Figure out whether rotating will increase or decrease the angle, and how far we need to rotate in that direction. // Figure out whether rotating will increase or decrease the angle, and how far we need to rotate in that direction.
int direction = (entity_angle_t::Zero() < angleDiff && angleDiff <= entity_angle_t::Pi()) || angleDiff < -entity_angle_t::Pi() ? -1 : 1; int direction = (entity_angle_t::Zero() < angleDiff && angleDiff <= entity_angle_t::Pi()) || angleDiff < -entity_angle_t::Pi() ? -1 : 1;
// Can't rotate far enough, just rotate in the correct direction. // Can't rotate far enough, just rotate in the correct direction.
if (absoluteAngleDiff > maxRotation) if (absoluteAngleDiff - m_InstantTurnAngle > maxRotation)
{ {
angle += maxRotation * direction; angle += maxRotation * direction;
if (angle * direction > entity_angle_t::Pi()) if (angle * direction > entity_angle_t::Pi())
@@ -1174,13 +1207,21 @@ bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath&
} }
// Rotate towards the next waypoint and continue moving. // Rotate towards the next waypoint and continue moving.
angle = atan2_approx(offset.X, offset.Y); angle = atan2_approx(offset.X, offset.Y);
// Give some 'free' rotation for angles below 0.5 radians. timeLeft = std::min(maxRotation, maxRotation - absoluteAngleDiff + m_InstantTurnAngle) / turnRate;
timeLeft = (std::min(maxRotation, maxRotation - absoluteAngleDiff + fixed::FromInt(1)/2)) / turnRate;
} }
} }
else
{
// Modify the speed depending on the angle difference.
fixed sin, cos;
sincos_approx(angleDiff, sin, cos);
speed = speed.Multiply(cos);
}
// Work out how far we can travel in timeLeft. // Work out how far we can travel in timeLeft.
fixed maxdist = maxSpeed.Multiply(timeLeft); fixed accelTime = std::min(timeLeft, (maxSpeed - speed) / m_Acceleration);
fixed accelDist = speed.Multiply(accelTime) + accelTime.Square().Multiply(m_Acceleration) / 2;
fixed maxdist = accelDist + maxSpeed.Multiply(timeLeft - accelTime);
// If the target is close, we can move there directly. // If the target is close, we can move there directly.
fixed offsetLength = offset.Length(); fixed offsetLength = offset.Length();
@@ -1191,7 +1232,20 @@ bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath&
pos = target; pos = target;
// Spend the rest of the time heading towards the next waypoint. // Spend the rest of the time heading towards the next waypoint.
timeLeft = (maxdist - offsetLength) / maxSpeed; // Either we still need to accelerate after, or we have reached maxSpeed.
// The former is much less likely than the latter: usually we can reach
// maxSpeed within one waypoint. So the Sqrt is not too bad.
if (offsetLength <= accelDist)
{
fixed requiredTime = (-speed + (speed.Square() + offsetLength.Multiply(m_Acceleration).Multiply(fixed::FromInt(2))).Sqrt()) / m_Acceleration;
timeLeft -= requiredTime;
speed += m_Acceleration.Multiply(requiredTime);
}
else
{
timeLeft -= accelTime + (offsetLength - accelDist) / maxSpeed;
speed = maxSpeed;
}
if (shortPath.m_Waypoints.empty()) if (shortPath.m_Waypoints.empty())
longPath.m_Waypoints.pop_back(); longPath.m_Waypoints.pop_back();
@@ -1212,6 +1266,8 @@ bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath&
offset.Normalize(maxdist); offset.Normalize(maxdist);
target = pos + offset; target = pos + offset;
speed = std::min(maxSpeed, speed + m_Acceleration.Multiply(timeLeft));
if (cmpPathfinder->CheckMovement(GetObstructionFilter(specificIgnore), pos.X, pos.Y, target.X, target.Y, m_Clearance, m_PassClass)) if (cmpPathfinder->CheckMovement(GetObstructionFilter(specificIgnore), pos.X, pos.Y, target.X, target.Y, m_Clearance, m_PassClass))
pos = target; pos = target;
else else
@@ -1223,18 +1279,18 @@ bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath&
return false; return false;
} }
void CCmpUnitMotion::UpdateMovementState(entity_pos_t speed) void CCmpUnitMotion::UpdateMovementState(entity_pos_t speed, entity_pos_t meanSpeed)
{ {
CmpPtr<ICmpVisual> cmpVisual(GetEntityHandle()); CmpPtr<ICmpVisual> cmpVisual(GetEntityHandle());
if (cmpVisual) if (cmpVisual)
{ {
if (speed == fixed::Zero()) if (meanSpeed == fixed::Zero())
cmpVisual->SelectMovementAnimation("idle", fixed::FromInt(1)); cmpVisual->SelectMovementAnimation("idle", fixed::FromInt(1));
else else
cmpVisual->SelectMovementAnimation(speed > (m_WalkSpeed / 2).Multiply(m_RunMultiplier + fixed::FromInt(1)) ? "run" : "walk", speed); cmpVisual->SelectMovementAnimation(meanSpeed > (m_WalkSpeed / 2).Multiply(m_RunMultiplier + fixed::FromInt(1)) ? "run" : "walk", meanSpeed);
} }
m_CurSpeed = speed; m_CurrentSpeed = speed;
} }
bool CCmpUnitMotion::HandleObstructedMove(bool moved) bool CCmpUnitMotion::HandleObstructedMove(bool moved)
@@ -60,6 +60,8 @@ public:
// Accumulated "pushing" from nearby units. // Accumulated "pushing" from nearby units.
CFixedVector2D push; CFixedVector2D push;
fixed speed;
fixed initialAngle; fixed initialAngle;
fixed angle; fixed angle;
@@ -167,6 +167,7 @@ void CCmpUnitMotionManager::Move(EntityMap<MotionState>& ents, fixed dt)
it->second.initialPos = it->second.cmpPosition->GetPosition2D(); it->second.initialPos = it->second.cmpPosition->GetPosition2D();
it->second.initialAngle = it->second.cmpPosition->GetRotation().Y; it->second.initialAngle = it->second.cmpPosition->GetRotation().Y;
it->second.pos = it->second.initialPos; it->second.pos = it->second.initialPos;
it->second.speed = it->second.cmpUnitMotion->GetCurrentSpeed();
it->second.angle = it->second.initialAngle; it->second.angle = it->second.initialAngle;
ENSURE(it->second.pos.X.ToInt_RoundToZero() / PUSHING_GRID_SIZE < m_MovingUnits.width() && ENSURE(it->second.pos.X.ToInt_RoundToZero() / PUSHING_GRID_SIZE < m_MovingUnits.width() &&
it->second.pos.Y.ToInt_RoundToZero() / PUSHING_GRID_SIZE < m_MovingUnits.height()); it->second.pos.Y.ToInt_RoundToZero() / PUSHING_GRID_SIZE < m_MovingUnits.height());
@@ -37,6 +37,8 @@ DEFINE_INTERFACE_METHOD("GetWalkSpeed", ICmpUnitMotion, GetWalkSpeed)
DEFINE_INTERFACE_METHOD("GetRunMultiplier", ICmpUnitMotion, GetRunMultiplier) DEFINE_INTERFACE_METHOD("GetRunMultiplier", ICmpUnitMotion, GetRunMultiplier)
DEFINE_INTERFACE_METHOD("EstimateFuturePosition", ICmpUnitMotion, EstimateFuturePosition) DEFINE_INTERFACE_METHOD("EstimateFuturePosition", ICmpUnitMotion, EstimateFuturePosition)
DEFINE_INTERFACE_METHOD("SetSpeedMultiplier", ICmpUnitMotion, SetSpeedMultiplier) DEFINE_INTERFACE_METHOD("SetSpeedMultiplier", ICmpUnitMotion, SetSpeedMultiplier)
DEFINE_INTERFACE_METHOD("GetAcceleration", ICmpUnitMotion, GetAcceleration)
DEFINE_INTERFACE_METHOD("SetAcceleration", ICmpUnitMotion, SetAcceleration)
DEFINE_INTERFACE_METHOD("GetPassabilityClassName", ICmpUnitMotion, GetPassabilityClassName) DEFINE_INTERFACE_METHOD("GetPassabilityClassName", ICmpUnitMotion, GetPassabilityClassName)
DEFINE_INTERFACE_METHOD("GetUnitClearance", ICmpUnitMotion, GetUnitClearance) DEFINE_INTERFACE_METHOD("GetUnitClearance", ICmpUnitMotion, GetUnitClearance)
DEFINE_INTERFACE_METHOD("SetFacePointAfterMove", ICmpUnitMotion, SetFacePointAfterMove) DEFINE_INTERFACE_METHOD("SetFacePointAfterMove", ICmpUnitMotion, SetFacePointAfterMove)
@@ -124,6 +126,16 @@ public:
return m_Script.Call<CFixedVector2D>("EstimateFuturePosition", dt); return m_Script.Call<CFixedVector2D>("EstimateFuturePosition", dt);
} }
virtual fixed GetAcceleration() const
{
return m_Script.Call<fixed>("GetAcceleration");
}
virtual void SetAcceleration(fixed acceleration)
{
m_Script.CallVoid("SetAcceleration", acceleration);
}
virtual void SetFacePointAfterMove(bool facePointAfterMove) virtual void SetFacePointAfterMove(bool facePointAfterMove)
{ {
m_Script.CallVoid("SetFacePointAfterMove", facePointAfterMove); m_Script.CallVoid("SetFacePointAfterMove", facePointAfterMove);
+12 -1
View File
@@ -87,7 +87,7 @@ public:
virtual void StopMoving() = 0; virtual void StopMoving() = 0;
/** /**
* Get the distance travelled over the last turn. * Get the speed at the end of the current turn.
*/ */
virtual fixed GetCurrentSpeed() const = 0; virtual fixed GetCurrentSpeed() const = 0;
@@ -129,6 +129,17 @@ public:
*/ */
virtual CFixedVector2D EstimateFuturePosition(const fixed dt) const = 0; virtual CFixedVector2D EstimateFuturePosition(const fixed dt) const = 0;
/**
* Get the current acceleration.
*/
virtual fixed GetAcceleration() const = 0;
/**
* Set the current acceleration.
* @param acceleration The acceleration.
*/
virtual void SetAcceleration(fixed acceleration) = 0;
/** /**
* Set whether the unit will turn to face the target point after finishing moving. * Set whether the unit will turn to face the target point after finishing moving.
*/ */