Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
Show First 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | enum PathState | ||||
PATHSTATE_FOLLOWING_REQUESTING_SHORT, | PATHSTATE_FOLLOWING_REQUESTING_SHORT, | ||||
PATHSTATE_MAX | PATHSTATE_MAX | ||||
}; | }; | ||||
u8 m_PathState; | u8 m_PathState; | ||||
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; | ||||
// This caches the resulting speed from m_WalkSpeed * m_SpeedMultiplier for convenience. | // This caches the resulting speed from m_WalkSpeed * m_SpeedMultiplier for convenience. | ||||
fixed m_Speed; | fixed m_Speed; | ||||
// Current mean speed (over the last turn). | // Current mean speed (over the last turn). | ||||
fixed m_CurSpeed; | fixed m_CurSpeed; | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | virtual void Init(const CParamNode& paramNode) | ||||
m_State = STATE_IDLE; | 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_TargetEntity = INVALID_ENTITY; | |||||
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("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); | ||||
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); | ||||
serialize.NumberFixed_Unbounded("current speed", m_CurSpeed); | serialize.NumberFixed_Unbounded("current speed", m_CurSpeed); | ||||
serialize.Bool("moving", m_Moving); | serialize.Bool("moving", m_Moving); | ||||
serialize.Bool("facePointAfterMove", m_FacePointAfterMove); | serialize.Bool("facePointAfterMove", m_FacePointAfterMove); | ||||
▲ Show 20 Lines • Show All 157 Lines • ▼ Show 20 Lines | public: | ||||
virtual bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange); | virtual bool MoveToPointRange(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 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_Moving = false; | 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(); | ||||
} | } | ||||
Show All 10 Lines | private: | ||||
bool IsFormationMember() const | bool IsFormationMember() const | ||||
{ | { | ||||
return m_State == STATE_FORMATIONMEMBER_PATH; | return m_State == STATE_FORMATIONMEMBER_PATH; | ||||
} | } | ||||
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 | ||||
{ | { | ||||
return m_PathState == PATHSTATE_FOLLOWING | return m_PathState == PATHSTATE_FOLLOWING | ||||
|| m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG | || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG | ||||
|| m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT; | || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 448 Lines • ▼ Show 20 Lines | if (m_PathState == PATHSTATE_FOLLOWING) | ||||
// If we're not currently computing any new paths: | // If we're not currently computing any new paths: | ||||
if (m_LongPath.m_Waypoints.empty() && m_ShortPath.m_Waypoints.empty()) | if (m_LongPath.m_Waypoints.empty() && m_ShortPath.m_Waypoints.empty()) | ||||
{ | { | ||||
if (IsFormationMember()) | if (IsFormationMember()) | ||||
{ | { | ||||
// 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()); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
m_Moving = false; | m_Moving = false; | ||||
CMessageMotionChanged msg(false); | CMessageMotionChanged msg(false); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
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(); | ||||
if (m_FacePointAfterMove) | if (m_FacePointAfterMove) | ||||
FaceTowardsPointFromPos(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 | // TODO: if the goal was a square building, we ought to point towards the | ||||
// nearest point on the square, not towards its center | // nearest point on the square, not towards its center | ||||
Show All 10 Lines | if (m_PathState == PATHSTATE_FOLLOWING) | ||||
CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA); | CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
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 | ||||
CFixedVector2D goalPos(m_FinalGoal.x, m_FinalGoal.z); | CFixedVector2D goalPos(m_FinalGoal.x, m_FinalGoal.z); | ||||
if ((goalPos - from).CompareLength(DIRECT_PATH_RANGE) > 0) | if ((goalPos - from).CompareLength(DIRECT_PATH_RANGE) > 0) | ||||
return false; | return false; | ||||
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); | CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | bool CCmpUnitMotion::CheckTargetMovement(const CFixedVector2D& from, entity_pos_t minDelta) | ||||
// Fail if the target is no longer visible to this entity's owner | // Fail if the target is no longer visible to this entity's owner | ||||
// (in which case we'll continue moving to its last known location, | // (in which case we'll continue moving to its last known location, | ||||
// unless it comes back into view before we reach that location) | // unless it comes back into view before we reach that location) | ||||
CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle()); | CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle()); | ||||
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; | ||||
} | } | ||||
// The target moved and we need to update our current path; | // The target moved and we need to update our current path; | ||||
// change the goal here and expect our caller to start the path request | // change the goal here and expect our caller to start the path request | ||||
m_FinalGoal.x = targetPos.X; | m_FinalGoal.x = targetPos.X; | ||||
m_FinalGoal.z = targetPos.Y; | m_FinalGoal.z = targetPos.Y; | ||||
RequestLongPath(from, m_FinalGoal); | RequestLongPath(from, m_FinalGoal); | ||||
m_PathState = PATHSTATE_FOLLOWING_REQUESTING_LONG; | m_PathState = PATHSTATE_FOLLOWING_REQUESTING_LONG; | ||||
return true; | return true; | ||||
} | } | ||||
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()) | ||||
return; | return; | ||||
CFixedVector2D targetPos; | CFixedVector2D targetPos; | ||||
if (!ComputeTargetPosition(targetPos)) | if (!ComputeTargetPosition(targetPos)) | ||||
return; | return; | ||||
m_FinalGoal.x = targetPos.X; | m_FinalGoal.x = targetPos.X; | ||||
m_FinalGoal.z = targetPos.Y; | m_FinalGoal.z = targetPos.Y; | ||||
} | } | ||||
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; | ||||
} | } | ||||
bool CCmpUnitMotion::PathIsShort(const WaypointPath& path, const CFixedVector2D& from, entity_pos_t minDistance) const | bool CCmpUnitMotion::PathIsShort(const WaypointPath& path, const CFixedVector2D& from, entity_pos_t minDistance) const | ||||
{ | { | ||||
CFixedVector2D prev = from; | CFixedVector2D prev = from; | ||||
entity_pos_t distLeft = minDistance; | entity_pos_t distLeft = minDistance; | ||||
Show All 37 Lines | if (!offset.IsZero()) | ||||
if (!cmpPosition) | if (!cmpPosition) | ||||
return; | return; | ||||
cmpPosition->TurnTo(angle); | cmpPosition->TurnTo(angle); | ||||
} | } | ||||
} | } | ||||
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); | ||||
} | } | ||||
void CCmpUnitMotion::BeginPathing(const CFixedVector2D& from, const PathGoal& goal) | void CCmpUnitMotion::BeginPathing(const CFixedVector2D& from, const PathGoal& goal) | ||||
{ | { | ||||
// reset our state for sanity. | // reset our state for sanity. | ||||
▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | else | ||||
// We're already in range - no need to move anywhere | // We're already in range - no need to move anywhere | ||||
if (m_FacePointAfterMove) | if (m_FacePointAfterMove) | ||||
FaceTowardsPointFromPos(pos, x, z); | FaceTowardsPointFromPos(pos, x, z); | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
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; | ||||
BeginPathing(pos, goal); | BeginPathing(pos, goal); | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | else | ||||
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_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; | ||||
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_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; | ||||
BeginPathing(pos, goal); | BeginPathing(pos, goal); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 45 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator