Fix bug with gather-near-position.

Use the max range for attacking.

This was SVN commit r12915.
This commit is contained in:
leper 2012-12-02 17:25:23 +00:00
parent a4f27dc3e0
commit 5806ed94e1
6 changed files with 115 additions and 20 deletions

View File

@ -188,6 +188,23 @@ Formation.prototype.TestAllMemberFunction = function(funcname, args)
return true;
};
Formation.prototype.GetMaxAttackRangeFunction = function(target)
{
var result = 0;
var range = 0;
for each (var ent in this.members)
{
var cmpAttack = Engine.QueryInterface(ent, IID_Attack);
if (!cmpAttack)
continue;
range = cmpAttack.GetRange(cmpAttack.GetBestAttackAgainst(target));
if (range.max > result)
result = range.max;
}
return result;
};
/**
* Set all members to form up into the formation shape.
* If moveCenter is true, the formation center will be reinitialised

View File

@ -613,7 +613,14 @@ var UnitFsmSpec = {
// Only used by other orders to walk there in formation
"Order.WalkToTargetRange": function(msg) {
if(this.MoveToTargetRangeExplicit(this.order.data.target, this.order.data.min, this.order.data.max))
if (this.MoveToTargetRangeExplicit(this.order.data.target, this.order.data.min, this.order.data.max))
this.SetNextState("WALKING");
else
this.FinishOrder();
},
"Order.WalkToPointRange": function(msg) {
if (this.MoveToPointRange(this.order.data.x, this.order.data.z, this.order.data.min, this.order.data.max))
this.SetNextState("WALKING");
else
this.FinishOrder();
@ -626,20 +633,21 @@ var UnitFsmSpec = {
},
"Order.Attack": function(msg) {
// TODO: on what should we base this range?
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
var maxRange = cmpFormation.GetMaxAttackRangeFunction(msg.data.target);
// Check if we are already in range, otherwise walk there
if (!this.CheckTargetRangeExplicit(msg.data.target, 0, 20))
if (!this.CheckTargetRangeExplicit(msg.data.target, 0, maxRange))
{
if (!this.TargetIsAlive(msg.data.target))
// The target was destroyed
this.FinishOrder();
else
// Out of range; move there in formation
this.PushOrderFront("WalkToTargetRange", { "target": msg.data.target, "min": 0, "max": 20 });
this.PushOrderFront("WalkToTargetRange", { "target": msg.data.target, "min": 0, "max": maxRange });
return;
}
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
// We don't want to rearrange the formation if the individual units are carrying
// out a task and one of the members dies/leaves the formation.
cmpFormation.SetRearrange(false);
@ -699,14 +707,10 @@ var UnitFsmSpec = {
"Order.GatherNearPosition": function(msg) {
// TODO: on what should we base this range?
// Check if we are already in range, otherwise walk there
if (!this.CheckTargetRangeExplicit(msg.data.target, 0, 20))
if (!this.CheckPointRangeExplicit(msg.data.x, msg.data.z, 0, 20))
{
if (!this.TargetIsAlive(msg.data.target))
// The target was destroyed
this.FinishOrder();
else
// Out of range; move there in formation
this.PushOrderFront("WalkToTargetRange", { "target": msg.data.target, "min": 0, "max": 20 });
// Out of range; move there in formation
this.PushOrderFront("WalkToPointRange", { "x": msg.data.x, "z": msg.data.z, "min": 0, "max": 20 });
return;
}
@ -2979,6 +2983,12 @@ UnitAI.prototype.MoveToTargetRangeExplicit = function(target, min, max)
return cmpUnitMotion.MoveToTargetRange(target, min, max);
};
UnitAI.prototype.CheckPointRangeExplicit = function(x, z, min, max)
{
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
return cmpUnitMotion.IsInPointRange(x, z, min, max);
};
UnitAI.prototype.CheckTargetRange = function(target, iid, type)
{
var cmpRanged = Engine.QueryInterface(this.entity, iid);
@ -3306,6 +3316,7 @@ UnitAI.prototype.ComputeWalkingDistance = function()
switch (order.type)
{
case "Walk":
case "WalkToPointRange":
case "MoveIntoFormation":
case "GatherNearPosition":
// Add the distance to the target point

View File

@ -156,6 +156,18 @@ UnitMotionFlying.prototype.MoveToTargetRange = function(target, minRange, maxRan
return true;
};
UnitMotionFlying.prototype.IsInPointRange = function(x, y, minRange, maxRange)
{
var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
var pos = cmpPosition.GetPosition2D();
var distFromTarget = Math.sqrt(Math.pow(x - pos.x, 2) + Math.pow(y - pos.y, 2));
if (minRange <= distFromTarget && distFromTarget <= maxRange)
return true;
return false;
};
UnitMotionFlying.prototype.IsInTargetRange = function(target, minRange, maxRange)
{
var cmpTargetPosition = Engine.QueryInterface(target, IID_Position);
@ -164,14 +176,7 @@ UnitMotionFlying.prototype.IsInTargetRange = function(target, minRange, maxRange
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;
return this.IsInPointRange(targetPos.x, targetPos.y, minRange, maxRange);
};
UnitMotionFlying.prototype.GetWalkSpeed = function()

View File

@ -423,6 +423,7 @@ public:
}
virtual bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange);
virtual bool IsInPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange);
virtual bool MoveToTargetRange(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);
@ -1320,6 +1321,55 @@ bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos
return true;
}
bool CCmpUnitMotion::IsInPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange)
{
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
if (!cmpPosition || !cmpPosition->IsInWorld())
return false;
CFixedVector2D pos = cmpPosition->GetPosition2D();
bool hasObstruction = false;
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
ICmpObstructionManager::ObstructionSquare obstruction;
if (cmpObstructionManager)
hasObstruction = cmpObstructionManager->FindMostImportantObstruction(GetObstructionFilter(true), x, z, m_Radius, obstruction);
if (minRange.IsZero() && maxRange.IsZero() && hasObstruction)
{
// Handle the non-ranged mode:
CFixedVector2D halfSize(obstruction.hw, obstruction.hh);
entity_pos_t distance = Geometry::DistanceToSquare(pos - CFixedVector2D(obstruction.x, obstruction.z), obstruction.u, obstruction.v, halfSize);
// See if we're too close to the target square
if (distance < minRange)
return false;
// See if we're close enough to the target square
if (maxRange < entity_pos_t::Zero() || distance <= maxRange)
return true;
return false;
}
else
{
entity_pos_t distance = (pos - CFixedVector2D(x, z)).Length();
if (distance < minRange)
{
return false;
}
else if (maxRange >= entity_pos_t::Zero() && distance > maxRange)
{
return false;
}
else
{
return true;
}
}
}
bool CCmpUnitMotion::ShouldTreatTargetAsCircle(entity_pos_t range, entity_pos_t hw, entity_pos_t hh, entity_pos_t circleRadius)
{
// Given a square, plus a target range we should reach, the shape at that distance

View File

@ -24,6 +24,7 @@
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("IsInPointRange", bool, ICmpUnitMotion, IsInPointRange, 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)
@ -47,6 +48,11 @@ public:
return m_Script.Call<bool>("MoveToPointRange", x, z, minRange, maxRange);
}
virtual bool IsInPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange)
{
return m_Script.Call<bool>("IsInPointRange", 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);

View File

@ -46,6 +46,12 @@ public:
*/
virtual bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange) = 0;
/**
* Determine wether the givven point is within the given range, using the same measurement
* as MoveToPointRange.
*/
virtual bool IsInPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange) = 0;
/**
* Determine whether the target is within the given range, using the same measurement
* as MoveToTargetRange.