Unit Motion - wrap target state into a struct
These variables together held the state for the target of UnitMotion, as set by the MoveTo[X] family of functions. Wrapping them in a struct reduces the chances that one will accidentally forget to reset part of the state and makes it explicit in-code that these are grouped together. Calling StopMoving() resets this target, which wasn't before and left the component in an incoherent state. Differential Revision: https://code.wildfiregames.com/D1887 This was SVN commit r22352.
This commit is contained in:
parent
4fda917f46
commit
4a15cc3b9f
@ -227,11 +227,25 @@ public:
|
|||||||
|
|
||||||
u32 m_ExpectedPathTicket; // asynchronous request ID we're waiting for, or 0 if none
|
u32 m_ExpectedPathTicket; // asynchronous request ID we're waiting for, or 0 if none
|
||||||
|
|
||||||
entity_id_t m_TargetEntity;
|
struct MoveRequest {
|
||||||
CFixedVector2D m_TargetPos;
|
enum Type {
|
||||||
CFixedVector2D m_TargetOffset;
|
NONE,
|
||||||
entity_pos_t m_TargetMinRange;
|
POINT,
|
||||||
entity_pos_t m_TargetMaxRange;
|
ENTITY,
|
||||||
|
OFFSET
|
||||||
|
} m_Type = NONE;
|
||||||
|
entity_id_t m_Entity = INVALID_ENTITY;
|
||||||
|
CFixedVector2D m_Position;
|
||||||
|
entity_pos_t m_MinRange, m_MaxRange;
|
||||||
|
|
||||||
|
// For readability
|
||||||
|
CFixedVector2D GetOffset() const { return m_Position; };
|
||||||
|
|
||||||
|
MoveRequest() = default;
|
||||||
|
MoveRequest(CFixedVector2D pos, entity_pos_t minRange, entity_pos_t maxRange) : m_Type(POINT), m_Position(pos), m_MinRange(minRange), m_MaxRange(maxRange) {};
|
||||||
|
MoveRequest(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange) : m_Type(ENTITY), m_Entity(target), m_MinRange(minRange), m_MaxRange(maxRange) {};
|
||||||
|
MoveRequest(entity_id_t target, CFixedVector2D offset) : m_Type(OFFSET), m_Entity(target), m_Position(offset) {};
|
||||||
|
} m_MoveRequest;
|
||||||
|
|
||||||
// If the entity moves, it will do so at m_WalkSpeed * m_SpeedMultiplier.
|
// If the entity moves, it will do so at m_WalkSpeed * m_SpeedMultiplier.
|
||||||
fixed m_SpeedMultiplier;
|
fixed m_SpeedMultiplier;
|
||||||
@ -309,8 +323,6 @@ public:
|
|||||||
|
|
||||||
m_Tries = 0;
|
m_Tries = 0;
|
||||||
|
|
||||||
m_TargetEntity = INVALID_ENTITY;
|
|
||||||
|
|
||||||
m_FinalGoal.type = PathGoal::POINT;
|
m_FinalGoal.type = PathGoal::POINT;
|
||||||
|
|
||||||
m_DebugOverlayEnabled = false;
|
m_DebugOverlayEnabled = false;
|
||||||
@ -330,13 +342,12 @@ public:
|
|||||||
|
|
||||||
serialize.NumberU32_Unbounded("ticket", m_ExpectedPathTicket);
|
serialize.NumberU32_Unbounded("ticket", m_ExpectedPathTicket);
|
||||||
|
|
||||||
serialize.NumberU32_Unbounded("target entity", m_TargetEntity);
|
SerializeU8_Enum<MoveRequest::Type, MoveRequest::Type::OFFSET>()(serialize, "target type", m_MoveRequest.m_Type);
|
||||||
serialize.NumberFixed_Unbounded("target pos x", m_TargetPos.X);
|
serialize.NumberU32_Unbounded("target entity", m_MoveRequest.m_Entity);
|
||||||
serialize.NumberFixed_Unbounded("target pos y", m_TargetPos.Y);
|
serialize.NumberFixed_Unbounded("target pos x", m_MoveRequest.m_Position.X);
|
||||||
serialize.NumberFixed_Unbounded("target offset x", m_TargetOffset.X);
|
serialize.NumberFixed_Unbounded("target pos y", m_MoveRequest.m_Position.Y);
|
||||||
serialize.NumberFixed_Unbounded("target offset y", m_TargetOffset.Y);
|
serialize.NumberFixed_Unbounded("target min range", m_MoveRequest.m_MinRange);
|
||||||
serialize.NumberFixed_Unbounded("target min range", m_TargetMinRange);
|
serialize.NumberFixed_Unbounded("target max range", m_MoveRequest.m_MaxRange);
|
||||||
serialize.NumberFixed_Unbounded("target max range", m_TargetMaxRange);
|
|
||||||
|
|
||||||
serialize.NumberFixed_Unbounded("speed multiplier", m_SpeedMultiplier);
|
serialize.NumberFixed_Unbounded("speed multiplier", m_SpeedMultiplier);
|
||||||
|
|
||||||
@ -510,6 +521,7 @@ public:
|
|||||||
|
|
||||||
virtual void StopMoving()
|
virtual void StopMoving()
|
||||||
{
|
{
|
||||||
|
m_MoveRequest = MoveRequest();
|
||||||
m_Moving = false;
|
m_Moving = false;
|
||||||
m_ExpectedPathTicket = 0;
|
m_ExpectedPathTicket = 0;
|
||||||
m_State = STATE_STOPPING;
|
m_State = STATE_STOPPING;
|
||||||
@ -536,7 +548,7 @@ private:
|
|||||||
|
|
||||||
entity_id_t GetGroup() const
|
entity_id_t GetGroup() const
|
||||||
{
|
{
|
||||||
return IsFormationMember() ? m_TargetEntity : GetEntityId();
|
return IsFormationMember() ? m_MoveRequest.m_Entity : GetEntityId();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasValidPath() const
|
bool HasValidPath() const
|
||||||
@ -1001,7 +1013,7 @@ void CCmpUnitMotion::Move(fixed dt)
|
|||||||
// We've reached our assigned position. If the controller
|
// We've reached our assigned position. If the controller
|
||||||
// is idle, send a notification in case it should disband,
|
// is idle, send a notification in case it should disband,
|
||||||
// otherwise continue following the formation next turn.
|
// otherwise continue following the formation next turn.
|
||||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity);
|
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity);
|
||||||
if (cmpUnitMotion && !cmpUnitMotion->IsMoving())
|
if (cmpUnitMotion && !cmpUnitMotion->IsMoving())
|
||||||
{
|
{
|
||||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle());
|
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle());
|
||||||
@ -1016,10 +1028,9 @@ void CCmpUnitMotion::Move(fixed dt)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check if target was reached in case of a moving target
|
|
||||||
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
|
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
|
||||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity);
|
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity);
|
||||||
if (!cmpUnitMotion || cmpObstructionManager->IsInTargetRange(GetEntityId(), m_TargetEntity, m_TargetMinRange, m_TargetMaxRange, false))
|
if (!cmpUnitMotion || cmpObstructionManager->IsInTargetRange(GetEntityId(), m_MoveRequest.m_Entity, m_MoveRequest.m_MinRange, m_MoveRequest.m_MaxRange, false))
|
||||||
{
|
{
|
||||||
m_State = STATE_IDLE;
|
m_State = STATE_IDLE;
|
||||||
MoveSucceeded();
|
MoveSucceeded();
|
||||||
@ -1046,32 +1057,29 @@ void CCmpUnitMotion::Move(fixed dt)
|
|||||||
|
|
||||||
bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out) const
|
bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out) const
|
||||||
{
|
{
|
||||||
if (m_TargetEntity == INVALID_ENTITY)
|
if (m_MoveRequest.m_Entity == INVALID_ENTITY)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TargetEntity);
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_MoveRequest.m_Entity);
|
||||||
if (!cmpPosition || !cmpPosition->IsInWorld())
|
if (!cmpPosition || !cmpPosition->IsInWorld())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_TargetOffset.IsZero())
|
if (m_MoveRequest.m_Type == MoveRequest::OFFSET)
|
||||||
{
|
|
||||||
// No offset, just return the position directly
|
|
||||||
out = cmpPosition->GetPosition2D();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// There is an offset, so compute it relative to orientation
|
// There is an offset, so compute it relative to orientation
|
||||||
entity_angle_t angle = cmpPosition->GetRotation().Y;
|
entity_angle_t angle = cmpPosition->GetRotation().Y;
|
||||||
CFixedVector2D offset = m_TargetOffset.Rotate(angle);
|
CFixedVector2D offset = m_MoveRequest.GetOffset().Rotate(angle);
|
||||||
out = cmpPosition->GetPosition2D() + offset;
|
out = cmpPosition->GetPosition2D() + offset;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
out = cmpPosition->GetPosition2D();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCmpUnitMotion::TryGoingStraightToGoalPoint(const CFixedVector2D& from)
|
bool CCmpUnitMotion::TryGoingStraightToGoalPoint(const CFixedVector2D& from)
|
||||||
{
|
{
|
||||||
// Make sure the goal is a point (and not a point-like target like a formation controller)
|
// Make sure the goal is a point (and not a point-like target like a formation controller)
|
||||||
if (m_FinalGoal.type != PathGoal::POINT || m_TargetEntity != INVALID_ENTITY)
|
if (m_MoveRequest.m_Type != MoveRequest::POINT)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Fail if the goal is too far away
|
// Fail if the goal is too far away
|
||||||
@ -1164,7 +1172,7 @@ bool CCmpUnitMotion::CheckTargetMovement(const CFixedVector2D& from, entity_pos_
|
|||||||
if (cmpOwnership)
|
if (cmpOwnership)
|
||||||
{
|
{
|
||||||
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
|
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
|
||||||
if (cmpRangeManager && cmpRangeManager->GetLosVisibility(m_TargetEntity, cmpOwnership->GetOwner()) == ICmpRangeManager::VIS_HIDDEN)
|
if (cmpRangeManager && cmpRangeManager->GetLosVisibility(m_MoveRequest.m_Entity, cmpOwnership->GetOwner()) == ICmpRangeManager::VIS_HIDDEN)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1180,9 +1188,9 @@ bool CCmpUnitMotion::CheckTargetMovement(const CFixedVector2D& from, entity_pos_
|
|||||||
|
|
||||||
void CCmpUnitMotion::UpdateFinalGoal()
|
void CCmpUnitMotion::UpdateFinalGoal()
|
||||||
{
|
{
|
||||||
if (m_TargetEntity == INVALID_ENTITY)
|
if (m_MoveRequest.m_Type != MoveRequest::ENTITY || m_MoveRequest.m_Type != MoveRequest::OFFSET)
|
||||||
return;
|
return;
|
||||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity);
|
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity);
|
||||||
if (!cmpUnitMotion)
|
if (!cmpUnitMotion)
|
||||||
return;
|
return;
|
||||||
if (IsFormationMember())
|
if (IsFormationMember())
|
||||||
@ -1196,7 +1204,7 @@ void CCmpUnitMotion::UpdateFinalGoal()
|
|||||||
|
|
||||||
bool CCmpUnitMotion::CloseEnoughFromDestinationToStop(const CFixedVector2D& from) const
|
bool CCmpUnitMotion::CloseEnoughFromDestinationToStop(const CFixedVector2D& from) const
|
||||||
{
|
{
|
||||||
if (m_TargetEntity != INVALID_ENTITY || m_FinalGoal.DistanceToPoint(from) > SHORT_PATH_GOAL_RADIUS)
|
if (m_MoveRequest.m_Type != MoveRequest::POINT || m_FinalGoal.DistanceToPoint(from) > SHORT_PATH_GOAL_RADIUS)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1250,7 +1258,7 @@ void CCmpUnitMotion::FaceTowardsPointFromPos(const CFixedVector2D& pos, entity_p
|
|||||||
|
|
||||||
ControlGroupMovementObstructionFilter CCmpUnitMotion::GetObstructionFilter(bool noTarget) const
|
ControlGroupMovementObstructionFilter CCmpUnitMotion::GetObstructionFilter(bool noTarget) const
|
||||||
{
|
{
|
||||||
entity_id_t group = noTarget ? m_TargetEntity : GetGroup();
|
entity_id_t group = noTarget ? m_MoveRequest.m_Entity : GetGroup();
|
||||||
return ControlGroupMovementObstructionFilter(ShouldAvoidMovingUnits(), group);
|
return ControlGroupMovementObstructionFilter(ShouldAvoidMovingUnits(), group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1414,10 +1422,7 @@ bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_State = STATE_INDIVIDUAL_PATH;
|
m_State = STATE_INDIVIDUAL_PATH;
|
||||||
m_TargetEntity = target;
|
m_MoveRequest = MoveRequest(CFixedVector2D(x, z), minRange, maxRange);
|
||||||
m_TargetOffset = CFixedVector2D();
|
|
||||||
m_TargetMinRange = minRange;
|
|
||||||
m_TargetMaxRange = maxRange;
|
|
||||||
m_FinalGoal = goal;
|
m_FinalGoal = goal;
|
||||||
m_Tries = 0;
|
m_Tries = 0;
|
||||||
|
|
||||||
@ -1584,10 +1589,7 @@ bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_State = STATE_INDIVIDUAL_PATH;
|
m_State = STATE_INDIVIDUAL_PATH;
|
||||||
m_TargetEntity = target;
|
m_MoveRequest = MoveRequest(target, minRange, maxRange);
|
||||||
m_TargetOffset = CFixedVector2D();
|
|
||||||
m_TargetMinRange = minRange;
|
|
||||||
m_TargetMaxRange = maxRange;
|
|
||||||
m_FinalGoal = goal;
|
m_FinalGoal = goal;
|
||||||
m_Tries = 0;
|
m_Tries = 0;
|
||||||
|
|
||||||
@ -1610,10 +1612,7 @@ void CCmpUnitMotion::MoveToFormationOffset(entity_id_t target, entity_pos_t x, e
|
|||||||
goal.z = pos.Y;
|
goal.z = pos.Y;
|
||||||
|
|
||||||
m_State = STATE_FORMATIONMEMBER_PATH;
|
m_State = STATE_FORMATIONMEMBER_PATH;
|
||||||
m_TargetEntity = target;
|
m_MoveRequest = MoveRequest(target, CFixedVector2D(x, z));
|
||||||
m_TargetOffset = CFixedVector2D(x, z);
|
|
||||||
m_TargetMinRange = entity_pos_t::Zero();
|
|
||||||
m_TargetMaxRange = entity_pos_t::Zero();
|
|
||||||
m_FinalGoal = goal;
|
m_FinalGoal = goal;
|
||||||
m_Tries = 0;
|
m_Tries = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user