1 #include "PathElevatorComponent.h"
2 #include "PhysicsComponent.h"
3 #include "PositionComponent.h"
4 
5 #include "../../GameApp/BaseGameApp.h"
6 #include "../../GameApp/BaseGameLogic.h"
7 
8 #include "../../Events/EventMgr.h"
9 #include "../../Events/Events.h"
10 
11 const char* PathElevatorComponent::g_Name = "PathElevatorComponent";
12 
PathElevatorComponent()13 PathElevatorComponent::PathElevatorComponent()
14     :
15     m_CurrentDirection(Direction_None),
16     m_StepTime(0),
17     m_StepElapsedDistance(0.0),
18     m_CurrentStepDefIdx(0),
19     m_pPhysics(nullptr)
20 {
21 
22 }
23 
VInit(TiXmlElement * pData)24 bool PathElevatorComponent::VInit(TiXmlElement* pData)
25 {
26     assert(pData != NULL);
27 
28     m_Properties.LoadFromXml(pData, true);
29 
30     assert(m_Properties.speed > DBL_EPSILON);
31     assert(m_Properties.elevatorPath.size() >= 2);
32 
33     m_pPhysics = g_pApp->GetGameLogic()->VGetGamePhysics();
34     assert(m_pPhysics != nullptr);
35 
36     /*LOG("Speed: " + ToStr(m_Properties.speed));
37     int i = 0;
38     for (auto def : m_Properties.elevatorPath)
39     {
40         if (!def.isWaiting)
41         {
42         LOG("[" + ToStr(i++) + "]: " + ToStr((int)def.direction) + " -> " + ToStr(def.stepDeltaDistance));
43         }
44         else
45         {
46         LOG("[" + ToStr(i++) + "]: " + ToStr(def.isWaiting) + " -> " + ToStr(def.waitMsTime));
47         }
48     }*/
49 
50     return true;
51 }
52 
VPostInit()53 void PathElevatorComponent::VPostInit()
54 {
55     auto pPC = MakeStrongPtr(m_pOwner->GetComponent<PositionComponent>());
56     assert(pPC != nullptr);
57 
58     m_LastPosition = pPC->GetPosition();
59 
60     int i = 0;
61     Point previousStepPosition = pPC->GetPosition();
62     for (ElevatorStepDef& elevatorStep : m_Properties.elevatorPath)
63     {
64         //assert(elevatorStep.direction != Direction_None && "PathElevator waiting not supported at the moment");
65         if (elevatorStep.direction != Direction_None)
66         {
67             Point dirSpeed = CalculateSpeed(1.0, elevatorStep.direction);
68             Point deltaStep(dirSpeed.x * elevatorStep.stepDeltaDistance, dirSpeed.y * elevatorStep.stepDeltaDistance);
69 
70             elevatorStep.destinationPosition = previousStepPosition + deltaStep;
71 
72             previousStepPosition = elevatorStep.destinationPosition;
73         }
74     }
75 
76     m_CurrentStepDef = m_Properties.elevatorPath[m_CurrentStepDefIdx];
77 
78     // From px/s to m/s
79     m_Properties.speed *= g_pApp->GetGlobalOptions()->platformSpeedModifier;
80 
81     m_CurrentSpeed = CalculateSpeed(m_Properties.speed, m_CurrentStepDef.direction);
82     m_pPhysics->VSetLinearSpeed(m_pOwner->GetGUID(), m_CurrentSpeed);
83 }
84 
VUpdate(uint32 msDiff)85 void PathElevatorComponent::VUpdate(uint32 msDiff)
86 {
87     if (m_CurrentStepDef.isWaiting)
88     {
89         m_StepTime += msDiff;
90         if (m_StepTime >= m_CurrentStepDef.waitMsTime)
91         {
92             ChangeToNextStep();
93         }
94     }
95 }
96 
CalculateSpeed(double speed,Direction dir)97 Point PathElevatorComponent::CalculateSpeed(double speed, Direction dir)
98 {
99     Point calculatedSpeed;
100 
101     switch (dir)
102     {
103         case Direction_Up: calculatedSpeed.Set(0, -1.0 * speed); break;
104         case Direction_Up_Right: calculatedSpeed.Set(speed, -1.0 * speed); break;
105         case Direction_Right: calculatedSpeed.Set(speed, 0); break;
106         case Direction_Down_Right: calculatedSpeed.Set(speed, speed); break;
107         case Direction_Down: calculatedSpeed.Set(0, speed); break;
108         case Direction_Down_Left: calculatedSpeed.Set(-1.0 * speed, speed); break;
109         case Direction_Left: calculatedSpeed.Set(-1.0 * speed, 0); break;
110         case Direction_Up_Left: calculatedSpeed.Set(-1.0 * speed, -1.0 * speed); break;
111         case Direction_None: calculatedSpeed.Set(0.0, 0.0); break;
112         default: assert(false);
113     }
114 
115     if (dir != Direction_None)
116     {
117         assert(!calculatedSpeed.IsZeroXY());
118     }
119 
120     return calculatedSpeed;
121 }
122 
ChangeToNextStep()123 void PathElevatorComponent::ChangeToNextStep()
124 {
125     if (m_CurrentStepDefIdx == m_Properties.elevatorPath.size() - 1)
126     {
127         m_CurrentStepDefIdx = 0;
128     }
129     else
130     {
131         m_CurrentStepDefIdx++;
132     }
133 
134     m_CurrentStepDef = m_Properties.elevatorPath[m_CurrentStepDefIdx];
135 
136     if (m_CurrentStepDef.direction == Direction_None)
137     {
138         m_CurrentSpeed.Set(0.0, 0.0);
139         m_pPhysics->VSetLinearSpeed(m_pOwner->GetGUID(), m_CurrentSpeed);
140     }
141     else
142     {
143         m_CurrentSpeed = CalculateSpeed(m_Properties.speed, m_CurrentStepDef.direction);
144         m_pPhysics->VSetLinearSpeed(m_pOwner->GetGUID(), m_CurrentSpeed);
145     }
146 
147     m_StepTime = 0;
148     m_StepElapsedDistance = 0;
149 }
150 
ShouldChangeDirection(const Point & newPosition)151 bool PathElevatorComponent::ShouldChangeDirection(const Point& newPosition)
152 {
153     // It should change position if it is past its X destination or Y destination
154     Point speedDirection = CalculateSpeed(1.0f, m_CurrentStepDef.direction);
155 
156     // Elevator is moving Up
157     if ((speedDirection.y < (-1.0 * DBL_EPSILON) && (newPosition.y < m_CurrentStepDef.destinationPosition.y)))
158     {
159         return true;
160     }
161     // Elevator is moving Down
162     else if ((speedDirection.y > DBL_EPSILON) && (newPosition.y > m_CurrentStepDef.destinationPosition.y))
163     {
164         return true;
165     }
166     // Elevator is moving Left
167     if ((speedDirection.x < (-1.0 * DBL_EPSILON) && (newPosition.x < m_CurrentStepDef.destinationPosition.x)))
168     {
169         return true;
170     }
171     // Elevator is moving Right
172     else if ((speedDirection.x > DBL_EPSILON) && (newPosition.x > m_CurrentStepDef.destinationPosition.x))
173     {
174         return true;
175     }
176 
177     return false;
178 }
179 
AddCarriedBody(b2Body * pBody)180 void PathElevatorComponent::AddCarriedBody(b2Body* pBody)
181 {
182     for (auto iter = m_CarriedBodiesList.begin(); iter != m_CarriedBodiesList.end(); ++iter)
183     {
184         if ((*iter) == pBody)
185         {
186             m_CarriedBodiesList.erase(iter);
187             return;
188         }
189     }
190 }
191 
RemoveCarriedBody(b2Body * pBody)192 void PathElevatorComponent::RemoveCarriedBody(b2Body* pBody)
193 {
194 
195 }
196 
OnMoved(Point newPosition)197 void PathElevatorComponent::OnMoved(Point newPosition)
198 {
199     Point positionDelta = Point(newPosition.x - m_LastPosition.x, newPosition.y - m_LastPosition.y);
200 
201     m_StepElapsedDistance += max(fabs(positionDelta.x), fabs(positionDelta.y));
202     if (ShouldChangeDirection(newPosition))
203     {
204         ChangeToNextStep();
205     }
206 
207     if (m_CarriedBodiesList.empty())
208     {
209         m_LastPosition = newPosition;
210         return;
211     }
212 
213     if (fabs(m_CurrentSpeed.x) < DBL_EPSILON)
214     {
215         return;
216     }
217 
218 
219     std::vector<b2Body*> uniqueCarriedBodies = m_CarriedBodiesList;
220     std::sort(uniqueCarriedBodies.begin(), uniqueCarriedBodies.end());
221     uniqueCarriedBodies.erase(std::unique(uniqueCarriedBodies.begin(), uniqueCarriedBodies.end()), uniqueCarriedBodies.end());
222     for (b2Body* pCarriedBody : uniqueCarriedBodies)
223     {
224         if (pCarriedBody->GetType() == b2_dynamicBody)
225         {
226             Actor* pActor = (Actor*)pCarriedBody->GetUserData();
227             assert(pActor);
228 
229             shared_ptr<PhysicsComponent> pPhysicsComponent =
230                 MakeStrongPtr(pActor->GetComponent<PhysicsComponent>(PhysicsComponent::g_Name));
231 
232             // Provide sanity check
233             if (pPhysicsComponent && pPhysicsComponent->GetNumFootContacts() == 0)
234             {
235                 RemoveCarriedBody(pCarriedBody);
236                 continue;
237             }
238 
239             if (pPhysicsComponent)
240             {
241                 pPhysicsComponent->SetExternalSourceSpeed(m_CurrentSpeed);
242             }
243         }
244     }
245 
246     m_LastPosition = newPosition;
247 }