diff --git a/binaries/data/mods/_test.sim/simulation/templates/unit.xml b/binaries/data/mods/_test.sim/simulation/templates/unit.xml
index f3066ac95f..43bcab103d 100644
--- a/binaries/data/mods/_test.sim/simulation/templates/unit.xml
+++ b/binaries/data/mods/_test.sim/simulation/templates/unit.xml
@@ -10,6 +10,7 @@
0
upright
false
+ 6.0
diff --git a/binaries/data/mods/_test.sim/simulation/templates/unitobstruct.xml b/binaries/data/mods/_test.sim/simulation/templates/unitobstruct.xml
index d06e0018cf..5b3943ad07 100644
--- a/binaries/data/mods/_test.sim/simulation/templates/unitobstruct.xml
+++ b/binaries/data/mods/_test.sim/simulation/templates/unitobstruct.xml
@@ -10,6 +10,7 @@
0
upright
false
+ 6.0
diff --git a/binaries/data/mods/public/maps/scenarios/Flight_demo.pmp b/binaries/data/mods/public/maps/scenarios/Flight_demo.pmp
new file mode 100644
index 0000000000..965280b8f1
--- /dev/null
+++ b/binaries/data/mods/public/maps/scenarios/Flight_demo.pmp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:798c4237a9a9d17ed14e5413c0c6b62cb520e2de95fdc64acea11cfff4dee9d9
+size 656466
diff --git a/binaries/data/mods/public/maps/scenarios/Flight_demo.xml b/binaries/data/mods/public/maps/scenarios/Flight_demo.xml
new file mode 100644
index 0000000000..92403f2aed
--- /dev/null
+++ b/binaries/data/mods/public/maps/scenarios/Flight_demo.xml
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:132cd0d3ac1052b453a950a4827e46948e67d0f1a196b24dfc663db1c0ae0bda
+size 3732
diff --git a/binaries/data/mods/public/simulation/components/UnitAI.js b/binaries/data/mods/public/simulation/components/UnitAI.js
index a7fee3d37c..4b104d411b 100644
--- a/binaries/data/mods/public/simulation/components/UnitAI.js
+++ b/binaries/data/mods/public/simulation/components/UnitAI.js
@@ -1829,9 +1829,7 @@ UnitAI.prototype.FaceTowardsTarget = function(target)
{
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
if (cmpUnitMotion)
- {
- cmpPosition.TurnTo(angle);
- }
+ cmpUnitMotion.FaceTowardsPoint(pos.x, pos.z);
}
}
diff --git a/binaries/data/mods/public/simulation/components/UnitMotionFlying.js b/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
new file mode 100644
index 0000000000..70c556b6d2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/UnitMotionFlying.js
@@ -0,0 +1,196 @@
+// (A serious implementation of this might want to use C++ instead of JS
+// for performance; this is just for fun.)
+
+function UnitMotionFlying() {}
+
+UnitMotionFlying.prototype.Schema =
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+
+UnitMotionFlying.prototype.Init = function()
+{
+ this.hasTarget = false;
+ this.reachedTarget = false;
+ this.targetX = 0;
+ this.targetZ = 0;
+ this.targetMinRange = 0;
+ this.targetMaxRange = 0;
+ this.speed = 0;
+};
+
+UnitMotionFlying.prototype.OnUpdate = function(msg)
+{
+ var turnLength = msg.turnLength;
+
+ if (!this.hasTarget)
+ return;
+
+ var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
+ var pos = cmpPosition.GetPosition();
+ var angle = cmpPosition.GetRotation().y;
+
+ var canTurn = true;
+
+ // If we haven't reached max speed yet then we're still on the ground;
+ // otherwise we're taking off or flying
+ if (this.speed < this.template.MaxSpeed)
+ {
+ // Accelerate forwards
+ this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength*this.template.AccelRate);
+ canTurn = false;
+
+ // Clamp to ground if below it, or descend if above
+
+ var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
+ var ground = cmpTerrain.GetGroundLevel(pos.x, pos.z);
+
+ if (pos.y < ground)
+ pos.y = ground;
+ else if (pos.y > ground)
+ pos.y = Math.max(ground, pos.y - turnLength*this.template.ClimbRate);
+
+ cmpPosition.SetHeightFixed(pos.y);
+ }
+ else
+ {
+ // Climb/sink to max height above ground
+
+ var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
+ var ground = cmpTerrain.GetGroundLevel(pos.x, pos.z);
+
+ var targetHeight = ground + (+this.template.FlyingHeight);
+ if (pos.y < targetHeight)
+ pos.y = Math.min(targetHeight, pos.y + turnLength*this.template.ClimbRate);
+ else if (pos.y > targetHeight)
+ pos.y = Math.max(targetHeight, pos.y - turnLength*this.template.ClimbRate);
+
+ cmpPosition.SetHeightFixed(pos.y);
+ }
+
+ // If we're in range of the target then tell people that we've reached it
+ // (TODO: quantisation breaks this)
+ var distFromTarget = Math.sqrt(Math.pow(this.targetX - pos.x, 2) + Math.pow(this.targetZ - pos.z, 2));
+ if (!this.reachedTarget && this.targetMinRange <= distFromTarget && distFromTarget <= this.targetMaxRange)
+ {
+ this.reachedTarget = true;
+ Engine.PostMessage(this.entity, MT_MotionChanged, { "starting": false, "error": false });
+ }
+
+ // If we're facing away from the target, and are still fairly close to it,
+ // then carry on going straight so we overshoot in a straight line
+ var isBehindTarget = ((this.targetX - pos.x)*Math.sin(angle) + (this.targetZ - pos.z)*Math.cos(angle) < 0);
+ if (isBehindTarget && distFromTarget < this.template.MaxSpeed*this.template.OvershootTime)
+ {
+ // Overshoot the target: carry on straight
+ canTurn = false;
+ }
+
+ if (canTurn)
+ {
+ // Turn towards the target
+
+ var targetAngle = Math.atan2(this.targetX - pos.x, this.targetZ - pos.z);
+
+ var delta = targetAngle - angle;
+ // Wrap delta to -pi..pi
+ delta = (delta + Math.PI) % (2*Math.PI); // range -2pi..2pi
+ if (delta < 0) delta += 2*Math.PI; // range 0..2pi
+ delta -= Math.PI; // range -pi..pi
+ // Clamp to max rate
+ var deltaClamped = Math.min(Math.max(delta, -this.template.TurnRate*turnLength), this.template.TurnRate*turnLength);
+ // Calculate new orientation, in a peculiar way in order to make sure the
+ // result gets close to targetAngle (rather than being n*2*pi out)
+ angle = targetAngle + deltaClamped - delta;
+ }
+
+ pos.x += this.speed * turnLength * Math.sin(angle);
+ pos.z += this.speed * turnLength * Math.cos(angle);
+
+ cmpPosition.TurnTo(angle);
+ cmpPosition.MoveTo(pos.x, pos.z);
+};
+
+UnitMotionFlying.prototype.MoveToPointRange = function(x, z, minRange, maxRange)
+{
+ this.hasTarget = true;
+ this.reachedTarget = false;
+ this.targetX = x;
+ this.targetZ = z;
+ this.targetMinRange = minRange;
+ this.targetMaxRange = maxRange;
+
+ return true;
+};
+
+UnitMotionFlying.prototype.MoveToTargetRange = function(target, minRange, maxRange)
+{
+ var cmpTargetPosition = Engine.QueryInterface(target, IID_Position);
+ if (!cmpTargetPosition || !cmpTargetPosition.IsInWorld())
+ return false;
+
+ var targetPos = cmpTargetPosition.GetPosition2D();
+
+ this.hasTarget = true;
+ this.reachedTarget = false;
+ this.targetX = targetPos.x;
+ this.targetZ = targetPos.y;
+ this.targetMinRange = minRange;
+ this.targetMaxRange = maxRange;
+
+ return true;
+};
+
+UnitMotionFlying.prototype.IsInTargetRange = function(target, minRange, maxRange)
+{
+ var cmpTargetPosition = Engine.QueryInterface(target, IID_Position);
+ if (!cmpTargetPosition || !cmpTargetPosition.IsInWorld())
+ return false;
+
+ var targetPos = cmpTargetPosition.GetPosition2D();
+
+ var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
+ var pos = cmpPosition.GetPosition2D();
+
+ var distFromTarget = Math.sqrt(Math.pow(targetPos.x - pos.x, 2) + Math.pow(targetPos.y - pos.y, 2));
+ if (minRange <= distFromTarget && distFromTarget <= maxRange)
+ return true;
+
+ return false;
+};
+
+UnitMotionFlying.prototype.GetWalkSpeed = function()
+{
+ return +this.template.MaxSpeed;
+};
+
+UnitMotionFlying.prototype.GetRunSpeed = function()
+{
+ return this.GetWalkSpeed();
+};
+
+UnitMotionFlying.prototype.FaceTowardsPoint = function(x, z)
+{
+ // Ignore this - angle is controlled by the target-seeking code instead
+};
+
+UnitMotionFlying.prototype.SetDebugOverlay = function(enabled)
+{
+};
+
+Engine.RegisterComponentType(IID_UnitMotion, "UnitMotionFlying", UnitMotionFlying);
diff --git a/binaries/data/mods/public/simulation/templates/other/plane.xml b/binaries/data/mods/public/simulation/templates/other/plane.xml
new file mode 100644
index 0000000000..a12c1aaa2a
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/other/plane.xml
@@ -0,0 +1,36 @@
+
+
+
+ hele
+ Aeroplane
+ This may be anachronistic.
+
+
+ units/hellenes/siege_rock.xml
+
+
+
+
+ 1.57
+
+
+ 24.0
+ 8.0
+ 1.57
+ 2.0
+ 16.0
+ 3.0
+
+
+
+ 0.0
+ 100.0
+ 25.0
+ 48
+ 24
+ 50.0
+ 0
+ 1000
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/special/actor.xml b/binaries/data/mods/public/simulation/templates/special/actor.xml
index 4b87cd5c8c..ac3732ad3f 100644
--- a/binaries/data/mods/public/simulation/templates/special/actor.xml
+++ b/binaries/data/mods/public/simulation/templates/special/actor.xml
@@ -4,6 +4,7 @@
0
upright
false
+ 6.0
(should be overridden)
diff --git a/binaries/data/mods/public/simulation/templates/special/formation.xml b/binaries/data/mods/public/simulation/templates/special/formation.xml
index 98434a62eb..24484d2572 100644
--- a/binaries/data/mods/public/simulation/templates/special/formation.xml
+++ b/binaries/data/mods/public/simulation/templates/special/formation.xml
@@ -4,6 +4,7 @@
0
upright
false
+ 6.0
diff --git a/binaries/data/mods/public/simulation/templates/template_entity_full.xml b/binaries/data/mods/public/simulation/templates/template_entity_full.xml
index 52cc4797fe..10d6626870 100644
--- a/binaries/data/mods/public/simulation/templates/template_entity_full.xml
+++ b/binaries/data/mods/public/simulation/templates/template_entity_full.xml
@@ -6,6 +6,7 @@
0
upright
false
+ 6.0
diff --git a/binaries/data/mods/public/simulation/templates/template_entity_quasi.xml b/binaries/data/mods/public/simulation/templates/template_entity_quasi.xml
index fcf0a7d16d..f85ed76bae 100644
--- a/binaries/data/mods/public/simulation/templates/template_entity_quasi.xml
+++ b/binaries/data/mods/public/simulation/templates/template_entity_quasi.xml
@@ -6,5 +6,6 @@
0
upright
false
+ 6.0
diff --git a/source/simulation2/TypeList.h b/source/simulation2/TypeList.h
index ea3b3c045c..b86fb46128 100644
--- a/source/simulation2/TypeList.h
+++ b/source/simulation2/TypeList.h
@@ -127,6 +127,7 @@ COMPONENT(Terrain)
INTERFACE(UnitMotion)
COMPONENT(UnitMotion) // must be after Obstruction
+COMPONENT(UnitMotionScripted)
INTERFACE(Vision)
COMPONENT(Vision)
diff --git a/source/simulation2/components/CCmpPosition.cpp b/source/simulation2/components/CCmpPosition.cpp
index 6b01feabd7..ca63383536 100644
--- a/source/simulation2/components/CCmpPosition.cpp
+++ b/source/simulation2/components/CCmpPosition.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -68,6 +68,7 @@ public:
bool m_InWorld;
entity_pos_t m_X, m_Z, m_LastX, m_LastZ; // these values contain undefined junk if !InWorld
entity_pos_t m_YOffset;
+ bool m_RelativeToGround; // whether m_YOffset is relative to terrain/water plane, or an absolute height
entity_angle_t m_RotX, m_RotY, m_RotZ;
float m_InterpolatedRotY; // not serialized
@@ -80,6 +81,7 @@ public:
"upright"
"0.0"
"false"
+ "6.0"
""
""
""
@@ -93,6 +95,9 @@ public:
""
""
""
+ ""
+ ""
+ ""
"";
}
@@ -109,9 +114,10 @@ public:
m_InWorld = false;
m_YOffset = paramNode.GetChild("Altitude").ToFixed();
+ m_RelativeToGround = true;
m_Floating = paramNode.GetChild("Floating").ToBool();
- m_RotYSpeed = 6.f; // TODO: should get from template
+ m_RotYSpeed = paramNode.GetChild("TurnRate").ToFixed().ToFloat();
m_RotX = m_RotY = m_RotZ = entity_angle_t::FromInt(0);
m_InterpolatedRotY = 0;
@@ -137,6 +143,7 @@ public:
serialize.NumberFixed_Unbounded("rot y", m_RotY);
serialize.NumberFixed_Unbounded("rot z", m_RotZ);
serialize.NumberFixed_Unbounded("altitude", m_YOffset);
+ serialize.Bool("relative", m_RelativeToGround);
if (serialize.IsDebug())
{
@@ -168,6 +175,7 @@ public:
deserialize.NumberFixed_Unbounded("rot y", m_RotY);
deserialize.NumberFixed_Unbounded("rot z", m_RotZ);
deserialize.NumberFixed_Unbounded("altitude", m_YOffset);
+ deserialize.Bool("relative", m_RelativeToGround);
// TODO: should there be range checks on all these values?
m_InterpolatedRotY = m_RotY.ToFloat();
@@ -212,6 +220,7 @@ public:
virtual void SetHeightOffset(entity_pos_t dy)
{
m_YOffset = dy;
+ m_RelativeToGround = true;
AdvertisePositionChanges();
}
@@ -221,6 +230,12 @@ public:
return m_YOffset;
}
+ virtual void SetHeightFixed(entity_pos_t y)
+ {
+ m_YOffset = y;
+ m_RelativeToGround = false;
+ }
+
virtual bool IsFloating()
{
return m_Floating;
@@ -235,15 +250,18 @@ public:
}
entity_pos_t baseY;
- CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
- if (!cmpTerrain.null())
- baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
-
- if (m_Floating)
+ if (m_RelativeToGround)
{
- CmpPtr cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
- if (!cmpWaterMan.null())
- baseY = std::max(baseY, cmpWaterMan->GetWaterLevel(m_X, m_Z));
+ CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
+ if (!cmpTerrain.null())
+ baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
+
+ if (m_Floating)
+ {
+ CmpPtr cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
+ if (!cmpWaterMan.null())
+ baseY = std::max(baseY, cmpWaterMan->GetWaterLevel(m_X, m_Z));
+ }
}
return CFixedVector3D(m_X, baseY + m_YOffset, m_Z);
@@ -327,15 +345,18 @@ public:
GetInterpolatedPosition2D(frameOffset, x, z, rotY);
float baseY = 0;
- CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
- if (!cmpTerrain.null())
- baseY = cmpTerrain->GetExactGroundLevel(x, z);
-
- if (m_Floating || forceFloating)
+ if (m_RelativeToGround)
{
- CmpPtr cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
- if (!cmpWaterMan.null())
- baseY = std::max(baseY, cmpWaterMan->GetExactWaterLevel(x, z));
+ CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
+ if (!cmpTerrain.null())
+ baseY = cmpTerrain->GetExactGroundLevel(x, z);
+
+ if (m_Floating || forceFloating)
+ {
+ CmpPtr cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
+ if (!cmpWaterMan.null())
+ baseY = std::max(baseY, cmpWaterMan->GetExactWaterLevel(x, z));
+ }
}
float y = baseY + m_YOffset.ToFloat();
diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp
index 5980f4ea90..f1b82a6d9f 100644
--- a/source/simulation2/components/CCmpUnitMotion.cpp
+++ b/source/simulation2/components/CCmpUnitMotion.cpp
@@ -413,6 +413,8 @@ public:
virtual bool IsInTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange);
virtual void MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z);
+ virtual void FaceTowardsPoint(entity_pos_t x, entity_pos_t z);
+
virtual void StopMoving()
{
m_ExpectedPathTicket = 0;
@@ -522,7 +524,7 @@ private:
/**
* Rotate to face towards the target point, given the current pos
*/
- void FaceTowardsPoint(CFixedVector2D pos, entity_pos_t x, entity_pos_t z);
+ void FaceTowardsPointFromPos(CFixedVector2D pos, entity_pos_t x, entity_pos_t z);
/**
* Returns an appropriate obstruction filter for use with path requests.
@@ -901,7 +903,7 @@ void CCmpUnitMotion::Move(fixed dt)
StopMoving();
- FaceTowardsPoint(pos, m_FinalGoal.x, m_FinalGoal.z);
+ FaceTowardsPointFromPos(pos, m_FinalGoal.x, m_FinalGoal.z);
// TODO: if the goal was a square building, we ought to point towards the
// nearest point on the square, not towards its center
}
@@ -1033,7 +1035,17 @@ bool CCmpUnitMotion::PathIsShort(const ICmpPathfinder::Path& path, CFixedVector2
return true;
}
-void CCmpUnitMotion::FaceTowardsPoint(CFixedVector2D pos, entity_pos_t x, entity_pos_t z)
+void CCmpUnitMotion::FaceTowardsPoint(entity_pos_t x, entity_pos_t z)
+{
+ CmpPtr cmpPosition(GetSimContext(), GetEntityId());
+ if (cmpPosition.null() || !cmpPosition->IsInWorld())
+ return;
+
+ CFixedVector2D pos = cmpPosition->GetPosition2D();
+ FaceTowardsPointFromPos(pos, x, z);
+}
+
+void CCmpUnitMotion::FaceTowardsPointFromPos(CFixedVector2D pos, entity_pos_t x, entity_pos_t z)
{
CFixedVector2D target(x, z);
CFixedVector2D offset = target - pos;
@@ -1223,7 +1235,7 @@ bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos
else
{
// We're already in range - no need to move anywhere
- FaceTowardsPoint(pos, x, z);
+ FaceTowardsPointFromPos(pos, x, z);
return false;
}
@@ -1334,7 +1346,7 @@ bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange
else if (maxRange < entity_pos_t::Zero() || distance < maxRange)
{
// We're already in range - no need to move anywhere
- FaceTowardsPoint(pos, goal.x, goal.z);
+ FaceTowardsPointFromPos(pos, goal.x, goal.z);
return false;
}
else
@@ -1356,7 +1368,7 @@ bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange
if (circleDistance < maxRange)
{
// We're already in range - no need to move anywhere
- FaceTowardsPoint(pos, goal.x, goal.z);
+ FaceTowardsPointFromPos(pos, goal.x, goal.z);
return false;
}
diff --git a/source/simulation2/components/ICmpPosition.cpp b/source/simulation2/components/ICmpPosition.cpp
index d1f2217018..1e3c8b0efb 100644
--- a/source/simulation2/components/ICmpPosition.cpp
+++ b/source/simulation2/components/ICmpPosition.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -28,6 +28,7 @@ DEFINE_INTERFACE_METHOD_2("MoveTo", void, ICmpPosition, MoveTo, entity_pos_t, en
DEFINE_INTERFACE_METHOD_2("JumpTo", void, ICmpPosition, JumpTo, entity_pos_t, entity_pos_t)
DEFINE_INTERFACE_METHOD_1("SetHeightOffset", void, ICmpPosition, SetHeightOffset, entity_pos_t)
DEFINE_INTERFACE_METHOD_0("GetHeightOffset", entity_pos_t, ICmpPosition, GetHeightOffset)
+DEFINE_INTERFACE_METHOD_1("SetHeightFixed", void, ICmpPosition, SetHeightFixed, entity_pos_t)
DEFINE_INTERFACE_METHOD_0("IsFloating", bool, ICmpPosition, IsFloating)
DEFINE_INTERFACE_METHOD_0("GetPosition", CFixedVector3D, ICmpPosition, GetPosition)
DEFINE_INTERFACE_METHOD_0("GetPosition2D", CFixedVector2D, ICmpPosition, GetPosition2D)
diff --git a/source/simulation2/components/ICmpPosition.h b/source/simulation2/components/ICmpPosition.h
index 19f00d48d5..4a4b274534 100644
--- a/source/simulation2/components/ICmpPosition.h
+++ b/source/simulation2/components/ICmpPosition.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -84,6 +84,12 @@ public:
*/
virtual entity_pos_t GetHeightOffset() = 0;
+ /**
+ * Set the vertical position as a fixed, absolute value.
+ * Will stay at this height until the next call to SetHeightFixed or SetHeightOffset.
+ */
+ virtual void SetHeightFixed(entity_pos_t y) = 0;
+
/**
* Returns whether the entity floats on water.
*/
diff --git a/source/simulation2/components/ICmpUnitMotion.cpp b/source/simulation2/components/ICmpUnitMotion.cpp
index 431f205e99..ee9cad68f0 100644
--- a/source/simulation2/components/ICmpUnitMotion.cpp
+++ b/source/simulation2/components/ICmpUnitMotion.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -20,12 +20,14 @@
#include "ICmpUnitMotion.h"
#include "simulation2/system/InterfaceScripted.h"
+#include "simulation2/scripting/ScriptComponent.h"
BEGIN_INTERFACE_WRAPPER(UnitMotion)
DEFINE_INTERFACE_METHOD_4("MoveToPointRange", bool, ICmpUnitMotion, MoveToPointRange, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t)
DEFINE_INTERFACE_METHOD_3("IsInTargetRange", bool, ICmpUnitMotion, IsInTargetRange, entity_id_t, entity_pos_t, entity_pos_t)
DEFINE_INTERFACE_METHOD_3("MoveToTargetRange", bool, ICmpUnitMotion, MoveToTargetRange, entity_id_t, entity_pos_t, entity_pos_t)
DEFINE_INTERFACE_METHOD_3("MoveToFormationOffset", void, ICmpUnitMotion, MoveToFormationOffset, entity_id_t, entity_pos_t, entity_pos_t)
+DEFINE_INTERFACE_METHOD_2("FaceTowardsPoint", void, ICmpUnitMotion, FaceTowardsPoint, entity_pos_t, entity_pos_t)
DEFINE_INTERFACE_METHOD_0("StopMoving", void, ICmpUnitMotion, StopMoving)
DEFINE_INTERFACE_METHOD_1("SetSpeed", void, ICmpUnitMotion, SetSpeed, fixed)
DEFINE_INTERFACE_METHOD_0("GetWalkSpeed", fixed, ICmpUnitMotion, GetWalkSpeed)
@@ -33,3 +35,67 @@ DEFINE_INTERFACE_METHOD_0("GetRunSpeed", fixed, ICmpUnitMotion, GetRunSpeed)
DEFINE_INTERFACE_METHOD_1("SetUnitRadius", void, ICmpUnitMotion, SetUnitRadius, fixed)
DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpUnitMotion, SetDebugOverlay, bool)
END_INTERFACE_WRAPPER(UnitMotion)
+
+class CCmpUnitMotionScripted : public ICmpUnitMotion
+{
+public:
+ DEFAULT_SCRIPT_WRAPPER(UnitMotionScripted)
+
+ virtual bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange)
+ {
+ return m_Script.Call("MoveToPointRange", x, z, minRange, maxRange);
+ }
+
+ virtual bool IsInTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange)
+ {
+ return m_Script.Call("IsInTargetRange", target, minRange, maxRange);
+ }
+
+ virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange)
+ {
+ return m_Script.Call("MoveToTargetRange", target, minRange, maxRange);
+ }
+
+ virtual void MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z)
+ {
+ m_Script.CallVoid("MoveToFormationOffset", target, x, z);
+ }
+
+ virtual void FaceTowardsPoint(entity_pos_t x, entity_pos_t z)
+ {
+ m_Script.CallVoid("FaceTowardsPoint", x, z);
+ }
+
+ virtual void StopMoving()
+ {
+ m_Script.CallVoid("StopMoving");
+ }
+
+ virtual void SetSpeed(fixed speed)
+ {
+ m_Script.CallVoid("SetSpeed", speed);
+ }
+
+ virtual fixed GetWalkSpeed()
+ {
+ return m_Script.Call("GetWalkSpeed");
+ }
+
+ virtual fixed GetRunSpeed()
+ {
+ return m_Script.Call("GetRunSpeed");
+ }
+
+ virtual void SetUnitRadius(fixed radius)
+ {
+ m_Script.CallVoid("SetUnitRadius", radius);
+ }
+
+ virtual void SetDebugOverlay(bool enabled)
+ {
+ m_Script.CallVoid("SetDebugOverlay", enabled);
+ }
+
+};
+
+REGISTER_COMPONENT_SCRIPT_WRAPPER(UnitMotionScripted)
diff --git a/source/simulation2/components/ICmpUnitMotion.h b/source/simulation2/components/ICmpUnitMotion.h
index ce86efb91c..fa8c609779 100644
--- a/source/simulation2/components/ICmpUnitMotion.h
+++ b/source/simulation2/components/ICmpUnitMotion.h
@@ -67,6 +67,11 @@ public:
*/
virtual void MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z) = 0;
+ /**
+ * Turn to look towards the given point.
+ */
+ virtual void FaceTowardsPoint(entity_pos_t x, entity_pos_t z) = 0;
+
/**
* Stop moving immediately.
*/
diff --git a/source/simulation2/tests/test_CmpTemplateManager.h b/source/simulation2/tests/test_CmpTemplateManager.h
index f1d77d3684..7581b73fc0 100644
--- a/source/simulation2/tests/test_CmpTemplateManager.h
+++ b/source/simulation2/tests/test_CmpTemplateManager.h
@@ -83,7 +83,7 @@ public:
const CParamNode* preview = tempMan->LoadTemplate(ent2, "preview|unit", -1);
TS_ASSERT(preview != NULL);
TS_ASSERT_WSTR_EQUALS(preview->ToXML(),
- L"0uprightfalse"
+ L"0uprightfalse6.0"
L"true0false"
L"examplefalsefalse");
@@ -97,7 +97,7 @@ public:
L"falsefalse"
L""
L""
- L"0uprightfalse"
+ L"0uprightfalse6.0"
L"true0false"
L"examplefalsefalse");