@@ -78,7 +78,12 @@ void PacketHandlingHelper::AddPacket(const WorldPacket& packet)
7878 */
7979PlayerbotAI::PlayerbotAI () : PlayerbotAIBase(), bot(NULL ), aiObjectContext(NULL ),
8080 currentEngine(NULL ), chatHelper(this ), chatFilter(this ), accountId(0 ), security(NULL ), master(NULL ), currentState(BOT_STATE_NON_COMBAT),
81- m_eatingUntil(0 ), m_drinkingUntil(0 )
81+ m_eatingUntil(0 ), m_drinkingUntil(0 ),
82+ m_isJumping(false ), m_jumpStartTime(0 ),
83+ m_jumpStartX(0 .f), m_jumpStartY(0 .f), m_jumpStartZ(0 .f),
84+ m_jumpSinAngle(0 .f), m_jumpCosAngle(1 .f), m_jumpXYSpeed(0 .f),
85+ m_pendingJump(false ), m_jumpRequestTime(0 ),
86+ m_jumpTargetX(0 .f), m_jumpTargetY(0 .f), m_jumpTargetZ(0 .f), m_jumpTargetO(0 .f)
8287{
8388 for (int i = 0 ; i < BOT_STATE_MAX; i++)
8489 {
@@ -92,7 +97,12 @@ PlayerbotAI::PlayerbotAI() : PlayerbotAIBase(), bot(NULL), aiObjectContext(NULL)
9297 */
9398PlayerbotAI::PlayerbotAI (Player* bot) :
9499 PlayerbotAIBase(), chatHelper(this ), chatFilter(this ), security(bot), master(NULL ),
95- m_eatingUntil(0 ), m_drinkingUntil(0 )
100+ m_eatingUntil(0 ), m_drinkingUntil(0 ),
101+ m_isJumping(false ), m_jumpStartTime(0 ),
102+ m_jumpStartX(0 .f), m_jumpStartY(0 .f), m_jumpStartZ(0 .f),
103+ m_jumpSinAngle(0 .f), m_jumpCosAngle(1 .f), m_jumpXYSpeed(0 .f),
104+ m_pendingJump(false ), m_jumpRequestTime(0 ),
105+ m_jumpTargetX(0 .f), m_jumpTargetY(0 .f), m_jumpTargetZ(0 .f), m_jumpTargetO(0 .f)
96106{
97107 this ->bot = bot;
98108
@@ -162,6 +172,132 @@ PlayerbotAI::~PlayerbotAI()
162172 }
163173}
164174
175+ static const float BOT_JUMP_VELOCITY = 7 .9557f ;
176+ static const float BOT_JUMP_GRAVITY = 19 .2911f ;
177+
178+ void PlayerbotAI::RequestJump ()
179+ {
180+ if (m_pendingJump || m_isJumping)
181+ return ;
182+
183+ Player* master = GetMaster ();
184+ if (!master)
185+ return ;
186+
187+ m_jumpTargetX = master->GetPositionX ();
188+ m_jumpTargetY = master->GetPositionY ();
189+ m_jumpTargetZ = master->GetPositionZ ();
190+ m_jumpTargetO = master->GetOrientation ();
191+ m_pendingJump = true ;
192+ m_jumpRequestTime = getMSTime ();
193+ }
194+
195+ void PlayerbotAI::StartJump (bool forward, float orientation)
196+ {
197+ if (m_isJumping || bot->IsDead ())
198+ return ;
199+
200+ bot->GetMotionMaster ()->Clear ();
201+ bot->GetMotionMaster ()->MoveIdle ();
202+
203+ m_jumpStartTime = getMSTime ();
204+ m_jumpStartX = bot->GetPositionX ();
205+ m_jumpStartY = bot->GetPositionY ();
206+ m_jumpStartZ = bot->GetPositionZ ();
207+
208+ float o = (orientation >= 0 .f ) ? orientation : bot->GetOrientation ();
209+ m_jumpCosAngle = cosf (o);
210+ m_jumpSinAngle = sinf (o);
211+ m_jumpXYSpeed = forward ? bot->GetSpeed (MOVE_RUN) : 0 .f ;
212+ m_isJumping = true ;
213+
214+ bot->SetFallInformation (0 , m_jumpStartZ);
215+
216+ bot->m_movementInfo .SetMovementFlags (MOVEFLAG_FALLING);
217+ if (forward)
218+ bot->m_movementInfo .AddMovementFlag (MOVEFLAG_FORWARD);
219+ bot->m_movementInfo .SetFallTime (0 );
220+ bot->m_movementInfo .SetJumpInfo (-BOT_JUMP_VELOCITY, m_jumpCosAngle, m_jumpSinAngle, m_jumpXYSpeed);
221+ bot->m_movementInfo .ChangePosition (m_jumpStartX, m_jumpStartY, m_jumpStartZ, o);
222+ bot->m_movementInfo .UpdateTime (m_jumpStartTime);
223+
224+ WorldPacket data (MSG_MOVE_JUMP, 64 );
225+ data << bot->GetPackGUID ();
226+ bot->m_movementInfo .Write (data);
227+ bot->SendMessageToSet (&data, false );
228+ }
229+
230+ void PlayerbotAI::UpdateJump ()
231+ {
232+ if (m_pendingJump && !m_isJumping)
233+ {
234+ if (getMSTime () - m_jumpRequestTime > 10000 )
235+ {
236+ m_pendingJump = false ;
237+ }
238+ else
239+ {
240+ float dx = m_jumpTargetX - bot->GetPositionX ();
241+ float dy = m_jumpTargetY - bot->GetPositionY ();
242+ float dist2d = sqrtf (dx * dx + dy * dy);
243+ if (dist2d <= 0 .5f )
244+ {
245+ m_pendingJump = false ;
246+ StartJump (true , m_jumpTargetO);
247+ }
248+ else
249+ {
250+ bot->GetMotionMaster ()->MovePoint (0 , m_jumpTargetX, m_jumpTargetY, m_jumpTargetZ);
251+ }
252+ }
253+ return ;
254+ }
255+
256+ if (!m_isJumping)
257+ return ;
258+
259+ uint32 now = getMSTime ();
260+ uint32 fallTimeMs = now - m_jumpStartTime;
261+ float t = fallTimeMs / 1000 .f ;
262+
263+ float z = m_jumpStartZ + BOT_JUMP_VELOCITY * t - 0 .5f * BOT_JUMP_GRAVITY * t * t;
264+ float x = m_jumpStartX + m_jumpCosAngle * m_jumpXYSpeed * t;
265+ float y = m_jumpStartY + m_jumpSinAngle * m_jumpXYSpeed * t;
266+
267+ float maxDuration = 2 .f * BOT_JUMP_VELOCITY / BOT_JUMP_GRAVITY * 1000 .f + 100 .f ;
268+ bool landed = fallTimeMs > 200 && ((z <= m_jumpStartZ + 0 .05f ) || (float (fallTimeMs) >= maxDuration));
269+
270+ bot->m_movementInfo .UpdateTime (now);
271+ bot->m_movementInfo .SetFallTime (fallTimeMs);
272+ bot->m_movementInfo .ChangePosition (x, y, z, bot->GetOrientation ());
273+
274+ if (landed)
275+ {
276+ m_isJumping = false ;
277+
278+ float landZ = m_jumpStartZ;
279+ if (Map* map = bot->GetMap ())
280+ {
281+ float terrainZ = map->GetHeight (x, y, z > m_jumpStartZ ? z : m_jumpStartZ);
282+ if (terrainZ > INVALID_HEIGHT)
283+ landZ = terrainZ;
284+ }
285+
286+ bot->m_movementInfo .RemoveMovementFlag (MovementFlags (MOVEFLAG_FALLING | MOVEFLAG_FORWARD));
287+ bot->m_movementInfo .ChangePosition (x, y, landZ, bot->GetOrientation ());
288+
289+ WorldPacket data (MSG_MOVE_FALL_LAND, 64 );
290+ data << bot->GetPackGUID ();
291+ bot->m_movementInfo .Write (data);
292+ bot->SendMessageToSet (&data, false );
293+
294+ bot->SetFallInformation (fallTimeMs, landZ);
295+ bot->GetMotionMaster ()->Clear ();
296+ bot->GetMotionMaster ()->MoveIdle ();
297+ bot->GetMap ()->PlayerRelocation (bot, x, y, landZ, bot->GetOrientation ());
298+ }
299+ }
300+
165301void PlayerbotAI::UpdateAI (uint32 elapsed)
166302{
167303 if (bot->IsBeingTeleported ())
@@ -206,6 +342,9 @@ void PlayerbotAI::UpdateAI(uint32 elapsed)
206342 }
207343 }
208344
345+ if (m_isJumping || m_pendingJump)
346+ UpdateJump ();
347+
209348 PlayerbotAIBase::UpdateAI (elapsed);
210349}
211350
0 commit comments