Index: ps/trunk/binaries/data/mods/public/simulation/components/Formation.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/Formation.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/Formation.js
@@ -859,36 +859,18 @@
};
/**
- * Calculate the estimated rotation of the formation
- * based on the first unitAI target position when ordered to walk,
- * based on the current rotation in other cases.
+ * Calculate the estimated rotation of the formation based on the current rotation.
* Return the sine and cosine of the angle.
*/
Formation.prototype.GetEstimatedOrientation = function(pos)
{
- let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
- let r = { "sin": 0, "cos": 1 };
- let unitAIState = cmpUnitAI.GetCurrentState();
- if (unitAIState == "FORMATIONCONTROLLER.WALKING" || unitAIState == "FORMATIONCONTROLLER.COMBAT.APPROACHING")
- {
- let targetPos = cmpUnitAI.GetTargetPositions();
- if (!targetPos.length)
- return r;
- let d = targetPos[0].sub(pos).normalize();
- if (!d.x && !d.y)
- return r;
- r.cos = d.y;
- r.sin = d.x;
- }
- else
- {
- let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
- if (!cmpPosition)
- return r;
- let rot = cmpPosition.GetRotation().y;
- r.sin = Math.sin(rot);
- r.cos = Math.cos(rot);
- }
+ let r = {};
+ let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
+ if (!cmpPosition)
+ return r;
+ let rot = cmpPosition.GetRotation().y;
+ r.sin = Math.sin(rot);
+ r.cos = Math.cos(rot);
return r;
};
Index: ps/trunk/binaries/data/mods/public/simulation/templates/gaia/fauna_shark.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/gaia/fauna_shark.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/gaia/fauna_shark.xml
@@ -23,8 +23,8 @@
-1
upright
true
- 0.0
- 5.0
+ 0
+ 5
Index: ps/trunk/binaries/data/mods/public/simulation/templates/special/actor.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/special/actor.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/special/actor.xml
@@ -4,8 +4,8 @@
0
upright
false
- 0.0
- 6.0
+ 0
+ 6
true
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_bird.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_bird.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_bird.xml
@@ -8,8 +8,8 @@
0
upright
false
- 0.0
- 1.0
+ 0
+ 1
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_formation.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_formation.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_formation.xml
@@ -53,8 +53,8 @@
0
upright
false
- 0.0
- 3.0
+ 0
+ 3
0.75
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_gaia.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_gaia.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_gaia.xml
@@ -23,8 +23,8 @@
0
upright
false
- 0.0
- 6.0
+ 0
+ 6
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_rubble.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_rubble.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_rubble.xml
@@ -12,8 +12,8 @@
0
upright
false
- 0.0
- 6.0
+ 0
+ 6
true
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure.xml
@@ -74,8 +74,8 @@
0
upright
false
- 0.0
- 6.0
+ 0
+ 6
1.0
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_territory_pull.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_territory_pull.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_territory_pull.xml
@@ -10,8 +10,8 @@
0
upright
false
- 0.0
- 6.0
+ 0
+ 6
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_trigger_point.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_trigger_point.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_trigger_point.xml
@@ -11,8 +11,8 @@
0
upright
false
- 0.0
- 6.0
+ 0
+ 6
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit.xml
@@ -70,7 +70,7 @@
pitch
false
0.0
- 6.0
+ 6
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_cavalry.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_cavalry.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_cavalry.xml
@@ -44,6 +44,9 @@
0
0
+
+ 4
+
150
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry.xml
@@ -29,6 +29,9 @@
8
10
+
+ 4
+
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml
@@ -24,6 +24,9 @@
30
20
+
+ 2
+
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_elephant.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_elephant.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_elephant.xml
@@ -13,6 +13,9 @@
260
+
+ 2
+
150
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_fauna.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_fauna.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_fauna.xml
@@ -18,6 +18,9 @@
food
+
+ 4
+
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive_elephant.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive_elephant.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive_elephant.xml
@@ -27,6 +27,9 @@
50
+
+ 2
+
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml
@@ -23,6 +23,9 @@
special/formations/wedge
+
+ 4
+
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_hero_elephant_melee.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_hero_elephant_melee.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_hero_elephant_melee.xml
@@ -31,6 +31,9 @@
Elephant Melee
+
+ 2
+
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship.xml
@@ -32,8 +32,8 @@
upright
true
- 0.0
- 3.0
+ 0
+ 3
4.0
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_quinquereme.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_quinquereme.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_quinquereme.xml
@@ -66,6 +66,9 @@
40
30
+
+ 2
+
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_trireme.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_trireme.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_trireme.xml
@@ -55,6 +55,9 @@
30
20
+
+ 2
+
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_siege.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_siege.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_siege.xml
@@ -31,6 +31,7 @@
pitch-roll
+ 2
4.0
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/support_elephant.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/support_elephant.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/support_elephant.xml
@@ -33,6 +33,7 @@
pitch
+ 2
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/plane.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/plane.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/plane.xml
@@ -54,9 +54,9 @@
upright
- 1.0
true
- 0.0
+ 0
+ 1
3.0
Index: ps/trunk/source/simulation2/components/CCmpPosition.cpp
===================================================================
--- ps/trunk/source/simulation2/components/CCmpPosition.cpp
+++ ps/trunk/source/simulation2/components/CCmpPosition.cpp
@@ -70,7 +70,8 @@
bool m_Floating;
entity_pos_t m_FloatDepth;
- float m_RotYSpeed; // maximum radians per second, used by InterpolatedRotY to follow RotY
+ // Maximum radians per second, used by InterpolatedRotY to follow RotY and the unitMotion.
+ fixed m_RotYSpeed;
// Dynamic state:
@@ -129,7 +130,7 @@
""
""
""
- ""
+ ""
""
"";
}
@@ -154,7 +155,7 @@
m_Floating = paramNode.GetChild("Floating").ToBool();
m_FloatDepth = paramNode.GetChild("FloatDepth").ToFixed();
- m_RotYSpeed = paramNode.GetChild("TurnRate").ToFixed().ToFloat();
+ m_RotYSpeed = paramNode.GetChild("TurnRate").ToFixed();
m_RotX = m_RotY = m_RotZ = entity_angle_t::FromInt(0);
m_InterpolatedRotX = m_InterpolatedRotY = m_InterpolatedRotZ = 0.f;
@@ -189,6 +190,7 @@
serialize.NumberFixed_Unbounded("rot x", m_RotX);
serialize.NumberFixed_Unbounded("rot y", m_RotY);
serialize.NumberFixed_Unbounded("rot z", m_RotZ);
+ serialize.NumberFixed_Unbounded("rot y speed", m_RotYSpeed);
serialize.NumberFixed_Unbounded("altitude", m_Y);
serialize.Bool("relative", m_RelativeToGround);
serialize.Bool("floating", m_Floating);
@@ -246,6 +248,7 @@
deserialize.NumberFixed_Unbounded("rot x", m_RotX);
deserialize.NumberFixed_Unbounded("rot y", m_RotY);
deserialize.NumberFixed_Unbounded("rot z", m_RotZ);
+ deserialize.NumberFixed_Unbounded("rot y speed", m_RotYSpeed);
deserialize.NumberFixed_Unbounded("altitude", m_Y);
deserialize.Bool("relative", m_RelativeToGround);
deserialize.Bool("floating", m_Floating);
@@ -536,6 +539,11 @@
return CFixedVector2D(m_PrevX, m_PrevZ);
}
+ virtual fixed GetTurnRate() const
+ {
+ return m_RotYSpeed;
+ }
+
virtual void TurnTo(entity_angle_t y)
{
if (m_TurretParent != INVALID_ENTITY)
@@ -780,13 +788,14 @@
if (rotY != m_InterpolatedRotY)
{
+ float rotYSpeed = m_RotYSpeed.ToFloat();
float delta = rotY - m_InterpolatedRotY;
// Wrap delta to -M_PI..M_PI
delta = fmodf(delta + (float)M_PI, 2*(float)M_PI); // range -2PI..2PI
if (delta < 0) delta += 2*(float)M_PI; // range 0..2PI
delta -= (float)M_PI; // range -M_PI..M_PI
// Clamp to max rate
- float deltaClamped = Clamp(delta, -m_RotYSpeed*msgData.deltaSimTime, +m_RotYSpeed*msgData.deltaSimTime);
+ float deltaClamped = Clamp(delta, -rotYSpeed*msgData.deltaSimTime, +rotYSpeed*msgData.deltaSimTime);
// Calculate new orientation, in a peculiar way in order to make sure the
// result gets close to m_orientation (rather than being n*2*M_PI out)
m_InterpolatedRotY = rotY + deltaClamped - delta;
Index: ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
===================================================================
--- ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
+++ ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
@@ -616,7 +616,7 @@
* This does not send actually change the position.
* @returns true if the move was obstructed.
*/
- bool PerformMove(fixed dt, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos) const;
+ bool PerformMove(fixed dt, const fixed& turnRate, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, entity_angle_t& angle);
/**
* Update other components on our speed.
@@ -872,28 +872,33 @@
return;
CFixedVector2D initialPos = cmpPosition->GetPosition2D();
+ entity_angle_t initialAngle = cmpPosition->GetRotation().Y;
- // Keep track of the current unit's position during the update
+ // Keep track of the current unit's position and rotation during the update.
CFixedVector2D pos = initialPos;
+ entity_angle_t angle = initialAngle;
// If we're chasing a potentially-moving unit and are currently close
// enough to its current position, and we can head in a straight line
// to it, then throw away our current path and go straight to it
bool wentStraight = TryGoingStraightToTarget(initialPos);
- bool wasObstructed = PerformMove(dt, m_ShortPath, m_LongPath, pos);
+ bool wasObstructed = PerformMove(dt, cmpPosition->GetTurnRate(), m_ShortPath, m_LongPath, pos, angle);
// Update our speed over this turn so that the visual actor shows the correct animation.
if (pos == initialPos)
+ {
+ if (angle != initialAngle)
+ cmpPosition->TurnTo(angle);
UpdateMovementState(fixed::Zero());
+ }
else
{
// Update the Position component after our movement (if we actually moved anywhere)
+ // When moving always set the angle in the direction of the movement.
CFixedVector2D offset = pos - initialPos;
-
- // Face towards the target
- entity_angle_t angle = atan2_approx(offset.X, offset.Y);
- cmpPosition->MoveAndTurnTo(pos.X,pos.Y, angle);
+ angle = atan2_approx(offset.X, offset.Y);
+ cmpPosition->MoveAndTurnTo(pos.X, pos.Y, angle);
// Calculate the mean speed over this past turn.
UpdateMovementState(offset.Length() / dt);
@@ -942,12 +947,18 @@
return false;
}
-bool CCmpUnitMotion::PerformMove(fixed dt, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos) const
+bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, entity_angle_t& angle)
{
// 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())
return true;
+ // Wrap the angle to (-Pi, Pi].
+ while (angle > entity_angle_t::Pi())
+ angle -= entity_angle_t::Pi() * 2;
+ while (angle < -entity_angle_t::Pi())
+ angle += entity_angle_t::Pi() * 2;
+
// TODO: there's some asymmetry here when units look at other
// units' positions - the result will depend on the order of execution.
// Maybe we should split the updates into multiple phases to minimise
@@ -957,26 +968,24 @@
ENSURE(cmpPathfinder);
fixed basicSpeed = m_Speed;
- // If in formation, run to keep up; otherwise just walk
+ // If in formation, run to keep up; otherwise just walk.
if (IsFormationMember())
basicSpeed = m_Speed.Multiply(m_RunMultiplier);
- // Find the speed factor of the underlying terrain
+ // Find the speed factor of the underlying terrain.
// (We only care about the tile we start on - it doesn't matter if we're moving
- // partially onto a much slower/faster tile)
- // TODO: Terrain-dependent speeds are not currently supported
+ // partially onto a much slower/faster tile).
+ // TODO: Terrain-dependent speeds are not currently supported.
fixed terrainSpeed = fixed::FromInt(1);
fixed maxSpeed = basicSpeed.Multiply(terrainSpeed);
- // We want to move (at most) maxSpeed*dt units from pos towards the next waypoint
-
fixed timeLeft = dt;
fixed zero = fixed::Zero();
while (timeLeft > zero)
{
- // If we ran out of path, we have to stop
+ // If we ran out of path, we have to stop.
if (shortPath.m_Waypoints.empty() && longPath.m_Waypoints.empty())
break;
@@ -987,11 +996,37 @@
target = CFixedVector2D(shortPath.m_Waypoints.back().x, shortPath.m_Waypoints.back().z);
CFixedVector2D offset = target - pos;
+ if (turnRate > zero)
+ {
+ fixed maxRotation = turnRate.Multiply(timeLeft);
+ fixed angleDiff = angle - atan2_approx(offset.X, offset.Y);
+ if (angleDiff != zero)
+ {
+ fixed absoluteAngleDiff = angleDiff.Absolute();
+ 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.
+ 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.
+ if (absoluteAngleDiff > maxRotation)
+ {
+ angle += maxRotation * direction;
+ if (angle * direction > entity_angle_t::Pi())
+ angle -= entity_angle_t::Pi() * 2 * direction;
+ break;
+ }
+ // Rotate towards the next waypoint and continue moving.
+ angle = atan2_approx(offset.X, offset.Y);
+ timeLeft = (maxRotation - absoluteAngleDiff) / turnRate;
+ }
+ }
- // Work out how far we can travel in timeLeft
+ // Work out how far we can travel in timeLeft.
fixed maxdist = maxSpeed.Multiply(timeLeft);
- // If the target is close, we can move there directly
+ // If the target is close, we can move there directly.
fixed offsetLength = offset.Length();
if (offsetLength <= maxdist)
{
@@ -999,7 +1034,7 @@
{
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;
if (shortPath.m_Waypoints.empty())
@@ -1011,13 +1046,13 @@
}
else
{
- // Error - path was obstructed
+ // Error - path was obstructed.
return true;
}
}
else
{
- // Not close enough, so just move in the right direction
+ // Not close enough, so just move in the right direction.
offset.Normalize(maxdist);
target = pos + offset;
Index: ps/trunk/source/simulation2/components/ICmpPosition.h
===================================================================
--- ps/trunk/source/simulation2/components/ICmpPosition.h
+++ ps/trunk/source/simulation2/components/ICmpPosition.h
@@ -185,6 +185,11 @@
virtual CFixedVector2D GetPreviousPosition2D() const = 0;
/**
+ * Returns the turn rate in radians per second.
+ */
+ virtual fixed GetTurnRate() const = 0;
+
+ /**
* Rotate smoothly to the given angle around the upwards axis.
* @param y clockwise radians from the +Z axis.
*/
Index: ps/trunk/source/simulation2/components/ICmpPosition.cpp
===================================================================
--- ps/trunk/source/simulation2/components/ICmpPosition.cpp
+++ ps/trunk/source/simulation2/components/ICmpPosition.cpp
@@ -42,6 +42,7 @@
DEFINE_INTERFACE_METHOD_CONST_0("GetPosition2D", CFixedVector2D, ICmpPosition, GetPosition2D)
DEFINE_INTERFACE_METHOD_CONST_0("GetPreviousPosition", CFixedVector3D, ICmpPosition, GetPreviousPosition)
DEFINE_INTERFACE_METHOD_CONST_0("GetPreviousPosition2D", CFixedVector2D, ICmpPosition, GetPreviousPosition2D)
+DEFINE_INTERFACE_METHOD_CONST_0("GetTurnRate", fixed, ICmpPosition, GetTurnRate)
DEFINE_INTERFACE_METHOD_1("TurnTo", void, ICmpPosition, TurnTo, entity_angle_t)
DEFINE_INTERFACE_METHOD_1("SetYRotation", void, ICmpPosition, SetYRotation, entity_angle_t)
DEFINE_INTERFACE_METHOD_2("SetXZRotation", void, ICmpPosition, SetXZRotation, entity_angle_t, entity_angle_t)
Index: ps/trunk/source/simulation2/components/tests/test_RangeManager.h
===================================================================
--- ps/trunk/source/simulation2/components/tests/test_RangeManager.h
+++ ps/trunk/source/simulation2/components/tests/test_RangeManager.h
@@ -62,6 +62,7 @@
virtual CFixedVector2D GetPosition2D() const { return CFixedVector2D(m_Pos.X, m_Pos.Z); }
virtual CFixedVector3D GetPreviousPosition() const { return CFixedVector3D(); }
virtual CFixedVector2D GetPreviousPosition2D() const { return CFixedVector2D(); }
+ virtual fixed GetTurnRate() const { return fixed::Zero(); }
virtual void TurnTo(entity_angle_t UNUSED(y)) { }
virtual void SetYRotation(entity_angle_t UNUSED(y)) { }
virtual void SetXZRotation(entity_angle_t UNUSED(x), entity_angle_t UNUSED(z)) { }