forked from 0ad/0ad
# Add experimental fighter planes.
This was SVN commit r9605.
This commit is contained in:
parent
1357000401
commit
2c58b07223
@ -10,6 +10,7 @@
|
||||
<Altitude>0</Altitude>
|
||||
<Anchor>upright</Anchor>
|
||||
<Floating>false</Floating>
|
||||
<TurnRate>6.0</TurnRate>
|
||||
</Position>
|
||||
<UnitAI/>
|
||||
</Entity>
|
||||
|
@ -10,6 +10,7 @@
|
||||
<Altitude>0</Altitude>
|
||||
<Anchor>upright</Anchor>
|
||||
<Floating>false</Floating>
|
||||
<TurnRate>6.0</TurnRate>
|
||||
</Position>
|
||||
<UnitAI/>
|
||||
<Footprint>
|
||||
|
BIN
binaries/data/mods/public/maps/scenarios/Flight_demo.pmp
(Stored with Git LFS)
Normal file
BIN
binaries/data/mods/public/maps/scenarios/Flight_demo.pmp
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/Flight_demo.xml
(Stored with Git LFS)
Normal file
BIN
binaries/data/mods/public/maps/scenarios/Flight_demo.xml
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
<Anchor>upright</Anchor>
|
||||
<Floating>false</Floating>
|
||||
<TurnRate>6.0</TurnRate>
|
||||
</Position>
|
||||
<VisualActor>
|
||||
<Actor>(should be overridden)</Actor>
|
||||
|
@ -4,6 +4,7 @@
|
||||
<Altitude>0</Altitude>
|
||||
<Anchor>upright</Anchor>
|
||||
<Floating>false</Floating>
|
||||
<TurnRate>6.0</TurnRate>
|
||||
</Position>
|
||||
<Formation/>
|
||||
<UnitAI>
|
||||
|
@ -6,6 +6,7 @@
|
||||
<Altitude>0</Altitude>
|
||||
<Anchor>upright</Anchor>
|
||||
<Floating>false</Floating>
|
||||
<TurnRate>6.0</TurnRate>
|
||||
</Position>
|
||||
<Selectable/>
|
||||
</Entity>
|
||||
|
@ -6,5 +6,6 @@
|
||||
<Altitude>0</Altitude>
|
||||
<Anchor>upright</Anchor>
|
||||
<Floating>false</Floating>
|
||||
<TurnRate>6.0</TurnRate>
|
||||
</Position>
|
||||
</Entity>
|
||||
|
@ -127,6 +127,7 @@ COMPONENT(Terrain)
|
||||
|
||||
INTERFACE(UnitMotion)
|
||||
COMPONENT(UnitMotion) // must be after Obstruction
|
||||
COMPONENT(UnitMotionScripted)
|
||||
|
||||
INTERFACE(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.
|
||||
*
|
||||
* 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:
|
||||
"<Anchor>upright</Anchor>"
|
||||
"<Altitude>0.0</Altitude>"
|
||||
"<Floating>false</Floating>"
|
||||
"<TurnRate>6.0</TurnRate>"
|
||||
"</a:example>"
|
||||
"<element name='Anchor' a:help='Automatic rotation to follow the slope of terrain'>"
|
||||
"<choice>"
|
||||
@ -93,6 +95,9 @@ public:
|
||||
"</element>"
|
||||
"<element name='Floating' a:help='Whether the entity floats on water'>"
|
||||
"<data type='boolean'/>"
|
||||
"</element>"
|
||||
"<element name='TurnRate' a:help='Maximum graphical rotation speed around Y axis, in radians per second'>"
|
||||
"<ref name='positiveDecimal'/>"
|
||||
"</element>";
|
||||
}
|
||||
|
||||
@ -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<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
||||
if (!cmpTerrain.null())
|
||||
baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
|
||||
|
||||
if (m_Floating)
|
||||
if (m_RelativeToGround)
|
||||
{
|
||||
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
|
||||
if (!cmpWaterMan.null())
|
||||
baseY = std::max(baseY, cmpWaterMan->GetWaterLevel(m_X, m_Z));
|
||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
||||
if (!cmpTerrain.null())
|
||||
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);
|
||||
@ -327,15 +345,18 @@ public:
|
||||
GetInterpolatedPosition2D(frameOffset, x, z, rotY);
|
||||
|
||||
float baseY = 0;
|
||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
||||
if (!cmpTerrain.null())
|
||||
baseY = cmpTerrain->GetExactGroundLevel(x, z);
|
||||
|
||||
if (m_Floating || forceFloating)
|
||||
if (m_RelativeToGround)
|
||||
{
|
||||
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
|
||||
if (!cmpWaterMan.null())
|
||||
baseY = std::max(baseY, cmpWaterMan->GetExactWaterLevel(x, z));
|
||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
||||
if (!cmpTerrain.null())
|
||||
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();
|
||||
|
@ -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<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 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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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<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;
|
||||
|
||||
/**
|
||||
* Turn to look towards the given point.
|
||||
*/
|
||||
virtual void FaceTowardsPoint(entity_pos_t x, entity_pos_t z) = 0;
|
||||
|
||||
/**
|
||||
* Stop moving immediately.
|
||||
*/
|
||||
|
@ -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"<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"<VisualActor><Actor>example</Actor><SilhouetteDisplay>false</SilhouetteDisplay><SilhouetteOccluder>false</SilhouetteOccluder></VisualActor>");
|
||||
|
||||
@ -97,7 +97,7 @@ public:
|
||||
L"<DisableBlockMovement>false</DisableBlockMovement><DisableBlockPathfinding>false</DisableBlockPathfinding>"
|
||||
L"<Unit radius=\"4\"></Unit>"
|
||||
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"<VisualActor><Actor>example</Actor><SilhouetteDisplay>false</SilhouetteDisplay><SilhouetteOccluder>false</SilhouetteOccluder></VisualActor>");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user