mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-07-28 13:53:01 +00:00
# Add experimental fighter planes.
This was SVN commit r9605.
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
<Altitude>0</Altitude>
|
<Altitude>0</Altitude>
|
||||||
<Anchor>upright</Anchor>
|
<Anchor>upright</Anchor>
|
||||||
<Floating>false</Floating>
|
<Floating>false</Floating>
|
||||||
|
<TurnRate>6.0</TurnRate>
|
||||||
</Position>
|
</Position>
|
||||||
<UnitAI/>
|
<UnitAI/>
|
||||||
</Entity>
|
</Entity>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
<Altitude>0</Altitude>
|
<Altitude>0</Altitude>
|
||||||
<Anchor>upright</Anchor>
|
<Anchor>upright</Anchor>
|
||||||
<Floating>false</Floating>
|
<Floating>false</Floating>
|
||||||
|
<TurnRate>6.0</TurnRate>
|
||||||
</Position>
|
</Position>
|
||||||
<UnitAI/>
|
<UnitAI/>
|
||||||
<Footprint>
|
<Footprint>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -1829,9 +1829,7 @@ UnitAI.prototype.FaceTowardsTarget = function(target)
|
|||||||
{
|
{
|
||||||
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
|
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
|
||||||
if (cmpUnitMotion)
|
if (cmpUnitMotion)
|
||||||
{
|
cmpUnitMotion.FaceTowardsPoint(pos.x, pos.z);
|
||||||
cmpPosition.TurnTo(angle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 =
|
||||||
|
"<element name='MaxSpeed'>" +
|
||||||
|
"<ref name='nonNegativeDecimal'/>" +
|
||||||
|
"</element>" +
|
||||||
|
"<element name='AccelRate'>" +
|
||||||
|
"<ref name='nonNegativeDecimal'/>" +
|
||||||
|
"</element>" +
|
||||||
|
"<element name='TurnRate'>" +
|
||||||
|
"<ref name='nonNegativeDecimal'/>" +
|
||||||
|
"</element>" +
|
||||||
|
"<element name='OvershootTime'>" +
|
||||||
|
"<ref name='nonNegativeDecimal'/>" +
|
||||||
|
"</element>" +
|
||||||
|
"<element name='FlyingHeight'>" +
|
||||||
|
"<data type='decimal'/>" +
|
||||||
|
"</element>" +
|
||||||
|
"<element name='ClimbRate'>" +
|
||||||
|
"<ref name='nonNegativeDecimal'/>" +
|
||||||
|
"</element>";
|
||||||
|
|
||||||
|
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);
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Entity parent="template_unit">
|
||||||
|
<Identity>
|
||||||
|
<Civ>hele</Civ>
|
||||||
|
<SpecificName>Aeroplane</SpecificName>
|
||||||
|
<History>This may be anachronistic.</History>
|
||||||
|
</Identity>
|
||||||
|
<VisualActor>
|
||||||
|
<Actor>units/hellenes/siege_rock.xml</Actor> <!-- only using this because its flaming projectiles look nice -->
|
||||||
|
</VisualActor>
|
||||||
|
<Obstruction disable=""/>
|
||||||
|
<UnitMotion disable=""/>
|
||||||
|
<Position>
|
||||||
|
<TurnRate>1.57</TurnRate>
|
||||||
|
</Position>
|
||||||
|
<UnitMotionFlying>
|
||||||
|
<MaxSpeed>24.0</MaxSpeed>
|
||||||
|
<AccelRate>8.0</AccelRate>
|
||||||
|
<TurnRate>1.57</TurnRate>
|
||||||
|
<OvershootTime>2.0</OvershootTime>
|
||||||
|
<FlyingHeight>16.0</FlyingHeight>
|
||||||
|
<ClimbRate>3.0</ClimbRate>
|
||||||
|
</UnitMotionFlying>
|
||||||
|
<Attack>
|
||||||
|
<Ranged>
|
||||||
|
<Hack>0.0</Hack>
|
||||||
|
<Pierce>100.0</Pierce>
|
||||||
|
<Crush>25.0</Crush>
|
||||||
|
<MaxRange>48</MaxRange>
|
||||||
|
<MinRange>24</MinRange>
|
||||||
|
<ProjectileSpeed>50.0</ProjectileSpeed>
|
||||||
|
<PrepareTime>0</PrepareTime>
|
||||||
|
<RepeatTime>1000</RepeatTime>
|
||||||
|
</Ranged>
|
||||||
|
</Attack>
|
||||||
|
</Entity>
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
<Altitude>0</Altitude>
|
<Altitude>0</Altitude>
|
||||||
<Anchor>upright</Anchor>
|
<Anchor>upright</Anchor>
|
||||||
<Floating>false</Floating>
|
<Floating>false</Floating>
|
||||||
|
<TurnRate>6.0</TurnRate>
|
||||||
</Position>
|
</Position>
|
||||||
<VisualActor>
|
<VisualActor>
|
||||||
<Actor>(should be overridden)</Actor>
|
<Actor>(should be overridden)</Actor>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<Altitude>0</Altitude>
|
<Altitude>0</Altitude>
|
||||||
<Anchor>upright</Anchor>
|
<Anchor>upright</Anchor>
|
||||||
<Floating>false</Floating>
|
<Floating>false</Floating>
|
||||||
|
<TurnRate>6.0</TurnRate>
|
||||||
</Position>
|
</Position>
|
||||||
<Formation/>
|
<Formation/>
|
||||||
<UnitAI>
|
<UnitAI>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<Altitude>0</Altitude>
|
<Altitude>0</Altitude>
|
||||||
<Anchor>upright</Anchor>
|
<Anchor>upright</Anchor>
|
||||||
<Floating>false</Floating>
|
<Floating>false</Floating>
|
||||||
|
<TurnRate>6.0</TurnRate>
|
||||||
</Position>
|
</Position>
|
||||||
<Selectable/>
|
<Selectable/>
|
||||||
</Entity>
|
</Entity>
|
||||||
|
|||||||
@@ -6,5 +6,6 @@
|
|||||||
<Altitude>0</Altitude>
|
<Altitude>0</Altitude>
|
||||||
<Anchor>upright</Anchor>
|
<Anchor>upright</Anchor>
|
||||||
<Floating>false</Floating>
|
<Floating>false</Floating>
|
||||||
|
<TurnRate>6.0</TurnRate>
|
||||||
</Position>
|
</Position>
|
||||||
</Entity>
|
</Entity>
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ COMPONENT(Terrain)
|
|||||||
|
|
||||||
INTERFACE(UnitMotion)
|
INTERFACE(UnitMotion)
|
||||||
COMPONENT(UnitMotion) // must be after Obstruction
|
COMPONENT(UnitMotion) // must be after Obstruction
|
||||||
|
COMPONENT(UnitMotionScripted)
|
||||||
|
|
||||||
INTERFACE(Vision)
|
INTERFACE(Vision)
|
||||||
COMPONENT(Vision)
|
COMPONENT(Vision)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010 Wildfire Games.
|
/* Copyright (C) 2011 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@@ -68,6 +68,7 @@ public:
|
|||||||
bool m_InWorld;
|
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_X, m_Z, m_LastX, m_LastZ; // these values contain undefined junk if !InWorld
|
||||||
entity_pos_t m_YOffset;
|
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;
|
entity_angle_t m_RotX, m_RotY, m_RotZ;
|
||||||
float m_InterpolatedRotY; // not serialized
|
float m_InterpolatedRotY; // not serialized
|
||||||
@@ -80,6 +81,7 @@ public:
|
|||||||
"<Anchor>upright</Anchor>"
|
"<Anchor>upright</Anchor>"
|
||||||
"<Altitude>0.0</Altitude>"
|
"<Altitude>0.0</Altitude>"
|
||||||
"<Floating>false</Floating>"
|
"<Floating>false</Floating>"
|
||||||
|
"<TurnRate>6.0</TurnRate>"
|
||||||
"</a:example>"
|
"</a:example>"
|
||||||
"<element name='Anchor' a:help='Automatic rotation to follow the slope of terrain'>"
|
"<element name='Anchor' a:help='Automatic rotation to follow the slope of terrain'>"
|
||||||
"<choice>"
|
"<choice>"
|
||||||
@@ -93,6 +95,9 @@ public:
|
|||||||
"</element>"
|
"</element>"
|
||||||
"<element name='Floating' a:help='Whether the entity floats on water'>"
|
"<element name='Floating' a:help='Whether the entity floats on water'>"
|
||||||
"<data type='boolean'/>"
|
"<data type='boolean'/>"
|
||||||
|
"</element>"
|
||||||
|
"<element name='TurnRate' a:help='Maximum graphical rotation speed around Y axis, in radians per second'>"
|
||||||
|
"<ref name='positiveDecimal'/>"
|
||||||
"</element>";
|
"</element>";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,9 +114,10 @@ public:
|
|||||||
m_InWorld = false;
|
m_InWorld = false;
|
||||||
|
|
||||||
m_YOffset = paramNode.GetChild("Altitude").ToFixed();
|
m_YOffset = paramNode.GetChild("Altitude").ToFixed();
|
||||||
|
m_RelativeToGround = true;
|
||||||
m_Floating = paramNode.GetChild("Floating").ToBool();
|
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_RotX = m_RotY = m_RotZ = entity_angle_t::FromInt(0);
|
||||||
m_InterpolatedRotY = 0;
|
m_InterpolatedRotY = 0;
|
||||||
@@ -137,6 +143,7 @@ public:
|
|||||||
serialize.NumberFixed_Unbounded("rot y", m_RotY);
|
serialize.NumberFixed_Unbounded("rot y", m_RotY);
|
||||||
serialize.NumberFixed_Unbounded("rot z", m_RotZ);
|
serialize.NumberFixed_Unbounded("rot z", m_RotZ);
|
||||||
serialize.NumberFixed_Unbounded("altitude", m_YOffset);
|
serialize.NumberFixed_Unbounded("altitude", m_YOffset);
|
||||||
|
serialize.Bool("relative", m_RelativeToGround);
|
||||||
|
|
||||||
if (serialize.IsDebug())
|
if (serialize.IsDebug())
|
||||||
{
|
{
|
||||||
@@ -168,6 +175,7 @@ public:
|
|||||||
deserialize.NumberFixed_Unbounded("rot y", m_RotY);
|
deserialize.NumberFixed_Unbounded("rot y", m_RotY);
|
||||||
deserialize.NumberFixed_Unbounded("rot z", m_RotZ);
|
deserialize.NumberFixed_Unbounded("rot z", m_RotZ);
|
||||||
deserialize.NumberFixed_Unbounded("altitude", m_YOffset);
|
deserialize.NumberFixed_Unbounded("altitude", m_YOffset);
|
||||||
|
deserialize.Bool("relative", m_RelativeToGround);
|
||||||
// TODO: should there be range checks on all these values?
|
// TODO: should there be range checks on all these values?
|
||||||
|
|
||||||
m_InterpolatedRotY = m_RotY.ToFloat();
|
m_InterpolatedRotY = m_RotY.ToFloat();
|
||||||
@@ -212,6 +220,7 @@ public:
|
|||||||
virtual void SetHeightOffset(entity_pos_t dy)
|
virtual void SetHeightOffset(entity_pos_t dy)
|
||||||
{
|
{
|
||||||
m_YOffset = dy;
|
m_YOffset = dy;
|
||||||
|
m_RelativeToGround = true;
|
||||||
|
|
||||||
AdvertisePositionChanges();
|
AdvertisePositionChanges();
|
||||||
}
|
}
|
||||||
@@ -221,6 +230,12 @@ public:
|
|||||||
return m_YOffset;
|
return m_YOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void SetHeightFixed(entity_pos_t y)
|
||||||
|
{
|
||||||
|
m_YOffset = y;
|
||||||
|
m_RelativeToGround = false;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool IsFloating()
|
virtual bool IsFloating()
|
||||||
{
|
{
|
||||||
return m_Floating;
|
return m_Floating;
|
||||||
@@ -235,15 +250,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
entity_pos_t baseY;
|
entity_pos_t baseY;
|
||||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
if (m_RelativeToGround)
|
||||||
if (!cmpTerrain.null())
|
|
||||||
baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
|
|
||||||
|
|
||||||
if (m_Floating)
|
|
||||||
{
|
{
|
||||||
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
|
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
||||||
if (!cmpWaterMan.null())
|
if (!cmpTerrain.null())
|
||||||
baseY = std::max(baseY, cmpWaterMan->GetWaterLevel(m_X, m_Z));
|
baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
|
||||||
|
|
||||||
|
if (m_Floating)
|
||||||
|
{
|
||||||
|
CmpPtr<ICmpWaterManager> 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);
|
return CFixedVector3D(m_X, baseY + m_YOffset, m_Z);
|
||||||
@@ -327,15 +345,18 @@ public:
|
|||||||
GetInterpolatedPosition2D(frameOffset, x, z, rotY);
|
GetInterpolatedPosition2D(frameOffset, x, z, rotY);
|
||||||
|
|
||||||
float baseY = 0;
|
float baseY = 0;
|
||||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
if (m_RelativeToGround)
|
||||||
if (!cmpTerrain.null())
|
|
||||||
baseY = cmpTerrain->GetExactGroundLevel(x, z);
|
|
||||||
|
|
||||||
if (m_Floating || forceFloating)
|
|
||||||
{
|
{
|
||||||
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
|
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
||||||
if (!cmpWaterMan.null())
|
if (!cmpTerrain.null())
|
||||||
baseY = std::max(baseY, cmpWaterMan->GetExactWaterLevel(x, z));
|
baseY = cmpTerrain->GetExactGroundLevel(x, z);
|
||||||
|
|
||||||
|
if (m_Floating || forceFloating)
|
||||||
|
{
|
||||||
|
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
|
||||||
|
if (!cmpWaterMan.null())
|
||||||
|
baseY = std::max(baseY, cmpWaterMan->GetExactWaterLevel(x, z));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float y = baseY + m_YOffset.ToFloat();
|
float y = baseY + m_YOffset.ToFloat();
|
||||||
|
|||||||
@@ -413,6 +413,8 @@ public:
|
|||||||
virtual bool IsInTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange);
|
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 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()
|
virtual void StopMoving()
|
||||||
{
|
{
|
||||||
m_ExpectedPathTicket = 0;
|
m_ExpectedPathTicket = 0;
|
||||||
@@ -522,7 +524,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Rotate to face towards the target point, given the current pos
|
* 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.
|
* Returns an appropriate obstruction filter for use with path requests.
|
||||||
@@ -901,7 +903,7 @@ void CCmpUnitMotion::Move(fixed dt)
|
|||||||
|
|
||||||
StopMoving();
|
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
|
// TODO: if the goal was a square building, we ought to point towards the
|
||||||
// nearest point on the square, not towards its center
|
// nearest point on the square, not towards its center
|
||||||
}
|
}
|
||||||
@@ -1033,7 +1035,17 @@ bool CCmpUnitMotion::PathIsShort(const ICmpPathfinder::Path& path, CFixedVector2
|
|||||||
return true;
|
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<ICmpPosition> 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 target(x, z);
|
||||||
CFixedVector2D offset = target - pos;
|
CFixedVector2D offset = target - pos;
|
||||||
@@ -1223,7 +1235,7 @@ bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We're already in range - no need to move anywhere
|
// We're already in range - no need to move anywhere
|
||||||
FaceTowardsPoint(pos, x, z);
|
FaceTowardsPointFromPos(pos, x, z);
|
||||||
return false;
|
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)
|
else if (maxRange < entity_pos_t::Zero() || distance < maxRange)
|
||||||
{
|
{
|
||||||
// We're already in range - no need to move anywhere
|
// We're already in range - no need to move anywhere
|
||||||
FaceTowardsPoint(pos, goal.x, goal.z);
|
FaceTowardsPointFromPos(pos, goal.x, goal.z);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1356,7 +1368,7 @@ bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange
|
|||||||
if (circleDistance < maxRange)
|
if (circleDistance < maxRange)
|
||||||
{
|
{
|
||||||
// We're already in range - no need to move anywhere
|
// We're already in range - no need to move anywhere
|
||||||
FaceTowardsPoint(pos, goal.x, goal.z);
|
FaceTowardsPointFromPos(pos, goal.x, goal.z);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010 Wildfire Games.
|
/* Copyright (C) 2011 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 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_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_1("SetHeightOffset", void, ICmpPosition, SetHeightOffset, entity_pos_t)
|
||||||
DEFINE_INTERFACE_METHOD_0("GetHeightOffset", entity_pos_t, ICmpPosition, GetHeightOffset)
|
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("IsFloating", bool, ICmpPosition, IsFloating)
|
||||||
DEFINE_INTERFACE_METHOD_0("GetPosition", CFixedVector3D, ICmpPosition, GetPosition)
|
DEFINE_INTERFACE_METHOD_0("GetPosition", CFixedVector3D, ICmpPosition, GetPosition)
|
||||||
DEFINE_INTERFACE_METHOD_0("GetPosition2D", CFixedVector2D, ICmpPosition, GetPosition2D)
|
DEFINE_INTERFACE_METHOD_0("GetPosition2D", CFixedVector2D, ICmpPosition, GetPosition2D)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010 Wildfire Games.
|
/* Copyright (C) 2011 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@@ -84,6 +84,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual entity_pos_t GetHeightOffset() = 0;
|
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.
|
* Returns whether the entity floats on water.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010 Wildfire Games.
|
/* Copyright (C) 2011 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@@ -20,12 +20,14 @@
|
|||||||
#include "ICmpUnitMotion.h"
|
#include "ICmpUnitMotion.h"
|
||||||
|
|
||||||
#include "simulation2/system/InterfaceScripted.h"
|
#include "simulation2/system/InterfaceScripted.h"
|
||||||
|
#include "simulation2/scripting/ScriptComponent.h"
|
||||||
|
|
||||||
BEGIN_INTERFACE_WRAPPER(UnitMotion)
|
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_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("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("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_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_0("StopMoving", void, ICmpUnitMotion, StopMoving)
|
||||||
DEFINE_INTERFACE_METHOD_1("SetSpeed", void, ICmpUnitMotion, SetSpeed, fixed)
|
DEFINE_INTERFACE_METHOD_1("SetSpeed", void, ICmpUnitMotion, SetSpeed, fixed)
|
||||||
DEFINE_INTERFACE_METHOD_0("GetWalkSpeed", fixed, ICmpUnitMotion, GetWalkSpeed)
|
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("SetUnitRadius", void, ICmpUnitMotion, SetUnitRadius, fixed)
|
||||||
DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpUnitMotion, SetDebugOverlay, bool)
|
DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpUnitMotion, SetDebugOverlay, bool)
|
||||||
END_INTERFACE_WRAPPER(UnitMotion)
|
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<bool>("MoveToPointRange", x, z, minRange, maxRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsInTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange)
|
||||||
|
{
|
||||||
|
return m_Script.Call<bool>("IsInTargetRange", target, minRange, maxRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange)
|
||||||
|
{
|
||||||
|
return m_Script.Call<bool>("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<fixed>("GetWalkSpeed");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual fixed GetRunSpeed()
|
||||||
|
{
|
||||||
|
return m_Script.Call<fixed>("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)
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z) = 0;
|
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.
|
* Stop moving immediately.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public:
|
|||||||
const CParamNode* preview = tempMan->LoadTemplate(ent2, "preview|unit", -1);
|
const CParamNode* preview = tempMan->LoadTemplate(ent2, "preview|unit", -1);
|
||||||
TS_ASSERT(preview != NULL);
|
TS_ASSERT(preview != NULL);
|
||||||
TS_ASSERT_WSTR_EQUALS(preview->ToXML(),
|
TS_ASSERT_WSTR_EQUALS(preview->ToXML(),
|
||||||
L"<Position><Altitude>0</Altitude><Anchor>upright</Anchor><Floating>false</Floating></Position>"
|
L"<Position><Altitude>0</Altitude><Anchor>upright</Anchor><Floating>false</Floating><TurnRate>6.0</TurnRate></Position>"
|
||||||
L"<Vision><AlwaysVisible>true</AlwaysVisible><Range>0</Range><RetainInFog>false</RetainInFog></Vision>"
|
L"<Vision><AlwaysVisible>true</AlwaysVisible><Range>0</Range><RetainInFog>false</RetainInFog></Vision>"
|
||||||
L"<VisualActor><Actor>example</Actor><SilhouetteDisplay>false</SilhouetteDisplay><SilhouetteOccluder>false</SilhouetteOccluder></VisualActor>");
|
L"<VisualActor><Actor>example</Actor><SilhouetteDisplay>false</SilhouetteDisplay><SilhouetteOccluder>false</SilhouetteOccluder></VisualActor>");
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ public:
|
|||||||
L"<DisableBlockMovement>false</DisableBlockMovement><DisableBlockPathfinding>false</DisableBlockPathfinding>"
|
L"<DisableBlockMovement>false</DisableBlockMovement><DisableBlockPathfinding>false</DisableBlockPathfinding>"
|
||||||
L"<Unit radius=\"4\"></Unit>"
|
L"<Unit radius=\"4\"></Unit>"
|
||||||
L"</Obstruction>"
|
L"</Obstruction>"
|
||||||
L"<Position><Altitude>0</Altitude><Anchor>upright</Anchor><Floating>false</Floating></Position>"
|
L"<Position><Altitude>0</Altitude><Anchor>upright</Anchor><Floating>false</Floating><TurnRate>6.0</TurnRate></Position>"
|
||||||
L"<Vision><AlwaysVisible>true</AlwaysVisible><Range>0</Range><RetainInFog>false</RetainInFog></Vision>"
|
L"<Vision><AlwaysVisible>true</AlwaysVisible><Range>0</Range><RetainInFog>false</RetainInFog></Vision>"
|
||||||
L"<VisualActor><Actor>example</Actor><SilhouetteDisplay>false</SilhouetteDisplay><SilhouetteOccluder>false</SilhouetteOccluder></VisualActor>");
|
L"<VisualActor><Actor>example</Actor><SilhouetteDisplay>false</SilhouetteDisplay><SilhouetteOccluder>false</SilhouetteOccluder></VisualActor>");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user