Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
Show First 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | public: | ||||
// Dynamic state: | // Dynamic state: | ||||
entity_pos_t m_Clearance; | entity_pos_t m_Clearance; | ||||
// cached for efficiency | // cached for efficiency | ||||
fixed m_WalkSpeed, m_RunMultiplier; | fixed m_WalkSpeed, m_RunMultiplier; | ||||
bool m_Moving; | |||||
bool m_FacePointAfterMove; | bool m_FacePointAfterMove; | ||||
enum State | enum State | ||||
{ | { | ||||
/* | /* | ||||
* Not moving at all. | * Not moving at all. | ||||
*/ | */ | ||||
STATE_IDLE, | STATE_IDLE, | ||||
▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | return | ||||
"<text/>" | "<text/>" | ||||
"</element>"; | "</element>"; | ||||
} | } | ||||
virtual void Init(const CParamNode& paramNode) | virtual void Init(const CParamNode& paramNode) | ||||
{ | { | ||||
m_FormationController = paramNode.GetChild("FormationController").ToBool(); | m_FormationController = paramNode.GetChild("FormationController").ToBool(); | ||||
m_Moving = false; | |||||
m_FacePointAfterMove = true; | m_FacePointAfterMove = true; | ||||
m_WalkSpeed = m_TemplateWalkSpeed = m_Speed = paramNode.GetChild("WalkSpeed").ToFixed(); | m_WalkSpeed = m_TemplateWalkSpeed = m_Speed = paramNode.GetChild("WalkSpeed").ToFixed(); | ||||
m_SpeedMultiplier = fixed::FromInt(1); | m_SpeedMultiplier = fixed::FromInt(1); | ||||
m_CurSpeed = fixed::Zero(); | m_CurSpeed = fixed::Zero(); | ||||
m_RunMultiplier = m_TemplateRunMultiplier = fixed::FromInt(1); | m_RunMultiplier = m_TemplateRunMultiplier = fixed::FromInt(1); | ||||
if (paramNode.GetChild("RunMultiplier").IsOk()) | if (paramNode.GetChild("RunMultiplier").IsOk()) | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | void SerializeCommon(S& serialize) | ||||
serialize.NumberFixed_Unbounded("target pos y", m_MoveRequest.m_Position.Y); | serialize.NumberFixed_Unbounded("target pos y", m_MoveRequest.m_Position.Y); | ||||
serialize.NumberFixed_Unbounded("target min range", m_MoveRequest.m_MinRange); | serialize.NumberFixed_Unbounded("target min range", m_MoveRequest.m_MinRange); | ||||
serialize.NumberFixed_Unbounded("target max range", m_MoveRequest.m_MaxRange); | serialize.NumberFixed_Unbounded("target max range", m_MoveRequest.m_MaxRange); | ||||
serialize.NumberFixed_Unbounded("speed multiplier", m_SpeedMultiplier); | serialize.NumberFixed_Unbounded("speed multiplier", m_SpeedMultiplier); | ||||
serialize.NumberFixed_Unbounded("current speed", m_CurSpeed); | serialize.NumberFixed_Unbounded("current speed", m_CurSpeed); | ||||
serialize.Bool("moving", m_Moving); | |||||
serialize.Bool("facePointAfterMove", m_FacePointAfterMove); | serialize.Bool("facePointAfterMove", m_FacePointAfterMove); | ||||
serialize.NumberU8("tries", m_Tries, 0, 255); | serialize.NumberU8("tries", m_Tries, 0, 255); | ||||
SerializeVector<SerializeWaypoint>()(serialize, "long path", m_LongPath.m_Waypoints); | SerializeVector<SerializeWaypoint>()(serialize, "long path", m_LongPath.m_Waypoints); | ||||
SerializeVector<SerializeWaypoint>()(serialize, "short path", m_ShortPath.m_Waypoints); | SerializeVector<SerializeWaypoint>()(serialize, "short path", m_ShortPath.m_Waypoints); | ||||
SerializeGoal()(serialize, "goal", m_FinalGoal); | SerializeGoal()(serialize, "goal", m_FinalGoal); | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | public: | ||||
void UpdateMessageSubscriptions() | void UpdateMessageSubscriptions() | ||||
{ | { | ||||
bool needRender = m_DebugOverlayEnabled; | bool needRender = m_DebugOverlayEnabled; | ||||
GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_RenderSubmit, this, needRender); | GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_RenderSubmit, this, needRender); | ||||
} | } | ||||
virtual bool IsMoving() const | virtual bool IsMoving() const | ||||
{ | { | ||||
return m_Moving; | return m_MoveRequest.m_Type != MoveRequest::NONE; | ||||
} | } | ||||
virtual fixed GetSpeedMultiplier() const | virtual fixed GetSpeedMultiplier() const | ||||
{ | { | ||||
return m_SpeedMultiplier; | return m_SpeedMultiplier; | ||||
} | } | ||||
virtual void SetSpeedMultiplier(fixed multiplier) | virtual void SetSpeedMultiplier(fixed multiplier) | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | public: | ||||
virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange); | virtual bool MoveToTargetRange(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 FaceTowardsPoint(entity_pos_t x, entity_pos_t z); | ||||
virtual void StopMoving() | virtual void StopMoving() | ||||
{ | { | ||||
m_MoveRequest = MoveRequest(); | m_MoveRequest = MoveRequest(); | ||||
m_Moving = false; | |||||
m_ExpectedPathTicket = 0; | m_ExpectedPathTicket = 0; | ||||
m_State = STATE_STOPPING; | m_State = STATE_STOPPING; | ||||
m_PathState = PATHSTATE_NONE; | m_PathState = PATHSTATE_NONE; | ||||
m_LongPath.m_Waypoints.clear(); | m_LongPath.m_Waypoints.clear(); | ||||
m_ShortPath.m_Waypoints.clear(); | m_ShortPath.m_Waypoints.clear(); | ||||
} | } | ||||
virtual entity_pos_t GetUnitClearance() const | virtual entity_pos_t GetUnitClearance() const | ||||
Show All 31 Lines | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
CMessageMotionChanged msg(true); | CMessageMotionChanged msg(true); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
} | } | ||||
void MoveSucceeded() | void MoveSucceeded() | ||||
{ | { | ||||
m_Moving = false; | |||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
// No longer moving, so speed is 0. | // No longer moving, so speed is 0. | ||||
m_CurSpeed = fixed::Zero(); | m_CurSpeed = fixed::Zero(); | ||||
CMessageMotionChanged msg(false); | CMessageMotionChanged msg(false); | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | |||||
void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path) | void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path) | ||||
{ | { | ||||
// reset our state for sanity. | // reset our state for sanity. | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
m_Moving = false; | |||||
// Ignore obsolete path requests | // Ignore obsolete path requests | ||||
if (ticket != m_ExpectedPathTicket) | if (ticket != m_ExpectedPathTicket) | ||||
return; | return; | ||||
m_ExpectedPathTicket = 0; // we don't expect to get this result again | m_ExpectedPathTicket = 0; // we don't expect to get this result again | ||||
// Check that we are still able to do something with that path | // Check that we are still able to do something with that path | ||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | ||||
Show All 19 Lines | if (m_PathState == PATHSTATE_WAITING_REQUESTING_LONG || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG) | ||||
// close enough to the unit then we can probably get unstuck | // close enough to the unit then we can probably get unstuck | ||||
if (m_LongPath.m_Waypoints.empty()) | if (m_LongPath.m_Waypoints.empty()) | ||||
m_LongPath.m_Waypoints.emplace_back(Waypoint{ m_FinalGoal.x, m_FinalGoal.z }); | m_LongPath.m_Waypoints.emplace_back(Waypoint{ m_FinalGoal.x, m_FinalGoal.z }); | ||||
m_PathState = PATHSTATE_FOLLOWING; | m_PathState = PATHSTATE_FOLLOWING; | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(true); | cmpObstruction->SetMovingFlag(true); | ||||
m_Moving = true; | |||||
} | } | ||||
else if (m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) | else if (m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) | ||||
{ | { | ||||
m_ShortPath = path; | m_ShortPath = path; | ||||
// If there's no waypoints then we couldn't get near the target | // If there's no waypoints then we couldn't get near the target | ||||
if (m_ShortPath.m_Waypoints.empty()) | if (m_ShortPath.m_Waypoints.empty()) | ||||
{ | { | ||||
// If we're globally following a long path, try to remove the next waypoint, it might be obstructed | // If we're globally following a long path, try to remove the next waypoint, it might be obstructed | ||||
// If not, and we are not in a formation, retry | // If not, and we are not in a formation, retry | ||||
// unless we are close to our target and we don't have a target entity. | // unless we are close to our target and we don't have a target entity. | ||||
// This makes sure that units don't clump too much when they are not in a formation and tasked to move. | // This makes sure that units don't clump too much when they are not in a formation and tasked to move. | ||||
if (m_LongPath.m_Waypoints.size() > 1) | if (m_LongPath.m_Waypoints.size() > 1) | ||||
m_LongPath.m_Waypoints.pop_back(); | m_LongPath.m_Waypoints.pop_back(); | ||||
else if (IsFormationMember()) | else if (IsFormationMember()) | ||||
{ | { | ||||
m_Moving = false; | |||||
CMessageMotionChanged msg(true); | CMessageMotionChanged msg(true); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
return; | return; | ||||
} | } | ||||
CMessageMotionChanged msg(false); | CMessageMotionChanged msg(false); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
Show All 20 Lines | else if (m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) | ||||
// else we could, so reset our number of tries. | // else we could, so reset our number of tries. | ||||
m_Tries = 0; | m_Tries = 0; | ||||
m_PathState = PATHSTATE_FOLLOWING; | m_PathState = PATHSTATE_FOLLOWING; | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(true); | cmpObstruction->SetMovingFlag(true); | ||||
m_Moving = true; | |||||
} | } | ||||
else | else | ||||
LOGWARNING("unexpected PathResult (%u %d %d)", GetEntityId(), m_State, m_PathState); | LOGWARNING("unexpected PathResult (%u %d %d)", GetEntityId(), m_State, m_PathState); | ||||
} | } | ||||
void CCmpUnitMotion::Move(fixed dt) | void CCmpUnitMotion::Move(fixed dt) | ||||
{ | { | ||||
PROFILE("Move"); | PROFILE("Move"); | ||||
▲ Show 20 Lines • Show All 222 Lines • ▼ Show 20 Lines | if (m_PathState == PATHSTATE_FOLLOWING) | ||||
// otherwise continue following the formation next turn. | // otherwise continue following the formation next turn. | ||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity); | CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity); | ||||
if (cmpUnitMotion && !cmpUnitMotion->IsMoving()) | if (cmpUnitMotion && !cmpUnitMotion->IsMoving()) | ||||
{ | { | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
m_Moving = false; | |||||
CMessageMotionChanged msg(false); | CMessageMotionChanged msg(false); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); | CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); | ||||
▲ Show 20 Lines • Show All 236 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
// reset our state for sanity. | // reset our state for sanity. | ||||
m_ExpectedPathTicket = 0; | m_ExpectedPathTicket = 0; | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
m_Moving = false; | |||||
m_PathState = PATHSTATE_NONE; | m_PathState = PATHSTATE_NONE; | ||||
#if DISABLE_PATHFINDER | #if DISABLE_PATHFINDER | ||||
{ | { | ||||
CmpPtr<ICmpPathfinder> cmpPathfinder (GetSimContext(), SYSTEM_ENTITY); | CmpPtr<ICmpPathfinder> cmpPathfinder (GetSimContext(), SYSTEM_ENTITY); | ||||
CFixedVector2D goalPos = m_FinalGoal.NearestPointOnGoal(from); | CFixedVector2D goalPos = m_FinalGoal.NearestPointOnGoal(from); | ||||
m_LongPath.m_Waypoints.clear(); | m_LongPath.m_Waypoints.clear(); | ||||
m_ShortPath.m_Waypoints.clear(); | m_ShortPath.m_Waypoints.clear(); | ||||
▲ Show 20 Lines • Show All 383 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator