Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
Show First 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | public: | ||||
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_FacePointAfterMove; | bool m_FacePointAfterMove; | ||||
enum State | |||||
{ | |||||
/* | |||||
* Not moving at all. | |||||
*/ | |||||
STATE_IDLE, | |||||
/* | |||||
* Not moving at all. Will go to IDLE next turn. | |||||
* (This one-turn delay is a hack to fix animation timings.) | |||||
*/ | |||||
STATE_STOPPING, | |||||
/* | |||||
* Member of a formation. | |||||
* Pathing to the target (depending on m_PathState). | |||||
* Target is m_TargetEntity plus m_TargetOffset. | |||||
*/ | |||||
STATE_FORMATIONMEMBER_PATH, | |||||
/* | |||||
* Individual unit or formation controller. | |||||
* Pathing to the target (depending on m_PathState). | |||||
* Target is m_TargetPos, m_TargetMinRange, m_TargetMaxRange; | |||||
* if m_TargetEntity is not INVALID_ENTITY then m_TargetPos is tracking it. | |||||
*/ | |||||
STATE_INDIVIDUAL_PATH, | |||||
STATE_MAX | |||||
}; | |||||
u8 m_State; | |||||
enum PathState | enum PathState | ||||
{ | { | ||||
/* | /* | ||||
* There is no path. | * There is no path. | ||||
* (This should only happen in IDLE and STOPPING.) | * (This should only happen in IDLE and STOPPING.) | ||||
*/ | */ | ||||
PATHSTATE_NONE, | PATHSTATE_NONE, | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | if (cmpPathfinder) | ||||
m_PassClass = cmpPathfinder->GetPassabilityClass(m_PassClassName); | m_PassClass = cmpPathfinder->GetPassabilityClass(m_PassClassName); | ||||
m_Clearance = cmpPathfinder->GetClearance(m_PassClass); | m_Clearance = cmpPathfinder->GetClearance(m_PassClass); | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetUnitClearance(m_Clearance); | cmpObstruction->SetUnitClearance(m_Clearance); | ||||
} | } | ||||
m_State = STATE_IDLE; | |||||
m_PathState = PATHSTATE_NONE; | m_PathState = PATHSTATE_NONE; | ||||
m_ExpectedPathTicket = 0; | m_ExpectedPathTicket = 0; | ||||
m_Tries = 0; | m_Tries = 0; | ||||
m_FinalGoal.type = PathGoal::POINT; | m_FinalGoal.type = PathGoal::POINT; | ||||
m_DebugOverlayEnabled = false; | m_DebugOverlayEnabled = false; | ||||
} | } | ||||
virtual void Deinit() | virtual void Deinit() | ||||
{ | { | ||||
} | } | ||||
template<typename S> | template<typename S> | ||||
void SerializeCommon(S& serialize) | void SerializeCommon(S& serialize) | ||||
{ | { | ||||
serialize.NumberU8("state", m_State, 0, STATE_MAX-1); | |||||
serialize.NumberU8("path state", m_PathState, 0, PATHSTATE_MAX-1); | serialize.NumberU8("path state", m_PathState, 0, PATHSTATE_MAX-1); | ||||
serialize.StringASCII("pass class", m_PassClassName, 0, 64); | serialize.StringASCII("pass class", m_PassClassName, 0, 64); | ||||
serialize.NumberU32_Unbounded("ticket", m_ExpectedPathTicket); | serialize.NumberU32_Unbounded("ticket", m_ExpectedPathTicket); | ||||
SerializeU8_Enum<MoveRequest::Type, MoveRequest::Type::OFFSET>()(serialize, "target type", m_MoveRequest.m_Type); | SerializeU8_Enum<MoveRequest::Type, MoveRequest::Type::OFFSET>()(serialize, "target type", m_MoveRequest.m_Type); | ||||
serialize.NumberU32_Unbounded("target entity", m_MoveRequest.m_Entity); | serialize.NumberU32_Unbounded("target entity", m_MoveRequest.m_Entity); | ||||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | virtual void StopMoving() | ||||
{ | { | ||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | ||||
if (cmpPosition && cmpPosition->IsInWorld()) | if (cmpPosition && cmpPosition->IsInWorld()) | ||||
FaceTowardsPointFromPos(cmpPosition->GetPosition2D(), m_FinalGoal.x, m_FinalGoal.z); | FaceTowardsPointFromPos(cmpPosition->GetPosition2D(), m_FinalGoal.x, m_FinalGoal.z); | ||||
} | } | ||||
m_MoveRequest = MoveRequest(); | m_MoveRequest = MoveRequest(); | ||||
m_ExpectedPathTicket = 0; | m_ExpectedPathTicket = 0; | ||||
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 | ||||
{ | { | ||||
return m_Clearance; | return m_Clearance; | ||||
} | } | ||||
private: | private: | ||||
bool ShouldAvoidMovingUnits() const | bool ShouldAvoidMovingUnits() const | ||||
{ | { | ||||
return !m_FormationController; | return !m_FormationController; | ||||
} | } | ||||
bool IsFormationMember() const | bool IsFormationMember() const | ||||
{ | { | ||||
return m_State == STATE_FORMATIONMEMBER_PATH; | // TODO: this really shouldn't be what we are checking for. | ||||
return m_MoveRequest.m_Type == MoveRequest::OFFSET; | |||||
} | } | ||||
entity_id_t GetGroup() const | entity_id_t GetGroup() const | ||||
{ | { | ||||
return IsFormationMember() ? m_MoveRequest.m_Entity : GetEntityId(); | return IsFormationMember() ? m_MoveRequest.m_Entity : GetEntityId(); | ||||
} | } | ||||
bool HasValidPath() const | bool HasValidPath() const | ||||
▲ Show 20 Lines • Show All 232 Lines • ▼ Show 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; | ||||
} | } | ||||
else | else | ||||
LOGWARNING("unexpected PathResult (%u %d %d)", GetEntityId(), m_State, m_PathState); | LOGWARNING("unexpected PathResult (%u %d)", GetEntityId(), m_PathState); | ||||
} | } | ||||
void CCmpUnitMotion::Move(fixed dt) | void CCmpUnitMotion::Move(fixed dt) | ||||
{ | { | ||||
PROFILE("Move"); | PROFILE("Move"); | ||||
if (m_State == STATE_STOPPING) | // If we were idle and will still be, we can return. | ||||
{ | // TODO: this will need to be removed if pushing is implemented. | ||||
m_State = STATE_IDLE; | if (m_CurSpeed == fixed::Zero() && m_MoveRequest.m_Type == MoveRequest::NONE) | ||||
MoveSucceeded(); | |||||
m_CurSpeed = fixed::Zero(); | |||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | |||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(false); | |||||
return; | |||||
} | |||||
if (m_State == STATE_IDLE) | |||||
return; | return; | ||||
if (PossiblyAtDestination()) | if (PossiblyAtDestination()) | ||||
MoveSucceeded(); | MoveSucceeded(); | ||||
else if (!TargetHasValidPosition()) | else if (!TargetHasValidPosition()) | ||||
{ | { | ||||
// Scrap waypoints - we don't know where to go. | // Scrap waypoints - we don't know where to go. | ||||
// If the move request remains unchanged and the target again has a valid position later on, | // If the move request remains unchanged and the target again has a valid position later on, | ||||
▲ Show 20 Lines • Show All 590 Lines • ▼ Show 20 Lines | else if (maxRange >= entity_pos_t::Zero() && distance > maxRange) | ||||
// If maxRange was abnormally small, | // If maxRange was abnormally small, | ||||
// collapse the circle into a point | // collapse the circle into a point | ||||
if (goal.hw <= entity_pos_t::Zero()) | if (goal.hw <= entity_pos_t::Zero()) | ||||
goal.type = PathGoal::POINT; | goal.type = PathGoal::POINT; | ||||
} | } | ||||
} | } | ||||
m_State = STATE_INDIVIDUAL_PATH; | |||||
m_MoveRequest = MoveRequest(CFixedVector2D(x, z), minRange, maxRange); | m_MoveRequest = MoveRequest(CFixedVector2D(x, z), minRange, maxRange); | ||||
m_FinalGoal = goal; | m_FinalGoal = goal; | ||||
m_Tries = 0; | m_Tries = 0; | ||||
BeginPathing(pos, goal); | BeginPathing(pos, goal); | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | else | ||||
goal.u = obstruction.u; | goal.u = obstruction.u; | ||||
goal.v = obstruction.v; | goal.v = obstruction.v; | ||||
entity_pos_t delta = std::max(goalDistance, m_Clearance + entity_pos_t::FromInt(TERRAIN_TILE_SIZE)/16); // ensure it's far enough to not intersect the building itself | entity_pos_t delta = std::max(goalDistance, m_Clearance + entity_pos_t::FromInt(TERRAIN_TILE_SIZE)/16); // ensure it's far enough to not intersect the building itself | ||||
goal.hw = obstruction.hw + delta; | goal.hw = obstruction.hw + delta; | ||||
goal.hh = obstruction.hh + delta; | goal.hh = obstruction.hh + delta; | ||||
} | } | ||||
} | } | ||||
m_State = STATE_INDIVIDUAL_PATH; | |||||
m_MoveRequest = MoveRequest(target, minRange, maxRange); | m_MoveRequest = MoveRequest(target, minRange, maxRange); | ||||
m_FinalGoal = goal; | m_FinalGoal = goal; | ||||
m_Tries = 0; | m_Tries = 0; | ||||
BeginPathing(pos, goal); | BeginPathing(pos, goal); | ||||
return true; | return true; | ||||
} | } | ||||
void CCmpUnitMotion::MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z) | void CCmpUnitMotion::MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z) | ||||
{ | { | ||||
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), target); | CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), target); | ||||
if (!cmpPosition || !cmpPosition->IsInWorld()) | if (!cmpPosition || !cmpPosition->IsInWorld()) | ||||
return; | return; | ||||
CFixedVector2D pos = cmpPosition->GetPosition2D(); | CFixedVector2D pos = cmpPosition->GetPosition2D(); | ||||
PathGoal goal; | PathGoal goal; | ||||
goal.type = PathGoal::POINT; | goal.type = PathGoal::POINT; | ||||
goal.x = pos.X; | goal.x = pos.X; | ||||
goal.z = pos.Y; | goal.z = pos.Y; | ||||
m_State = STATE_FORMATIONMEMBER_PATH; | |||||
m_MoveRequest = MoveRequest(target, CFixedVector2D(x, z)); | m_MoveRequest = MoveRequest(target, CFixedVector2D(x, z)); | ||||
m_FinalGoal = goal; | m_FinalGoal = goal; | ||||
m_Tries = 0; | m_Tries = 0; | ||||
BeginPathing(pos, goal); | BeginPathing(pos, goal); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 46 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator