mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
Initial project location adjustment
This commit is contained in:
parent
11641a8bd7
commit
9d20fe2b32
244 changed files with 0 additions and 0 deletions
422
src/game/MotionGenerators/WaypointMovementGenerator.cpp
Normal file
422
src/game/MotionGenerators/WaypointMovementGenerator.cpp
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
/**
|
||||
* MaNGOS is a full featured server for World of Warcraft, supporting
|
||||
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
|
||||
*
|
||||
* Copyright (C) 2005-2014 MaNGOS project <http://getmangos.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
|
||||
* and lore are copyrighted by Blizzard Entertainment, Inc.
|
||||
*/
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "WaypointMovementGenerator.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "WaypointManager.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "movement/MoveSplineInit.h"
|
||||
#include "movement/MoveSpline.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
//-----------------------------------------------//
|
||||
void WaypointMovementGenerator<Creature>::LoadPath(Creature& creature)
|
||||
{
|
||||
DETAIL_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "LoadPath: loading waypoint path for %s", creature.GetGuidStr().c_str());
|
||||
|
||||
i_path = sWaypointMgr.GetPath(creature.GetGUIDLow());
|
||||
|
||||
// We may LoadPath() for several occasions:
|
||||
|
||||
// 1: When creature.MovementType=2
|
||||
// 1a) Path is selected by creature.guid == creature_movement.id
|
||||
// 1b) Path for 1a) does not exist and then use path from creature.GetEntry() == creature_movement_template.entry
|
||||
|
||||
// 2: When creature_template.MovementType=2
|
||||
// 2a) Creature is summoned and has creature_template.MovementType=2
|
||||
// Creators need to be sure that creature_movement_template is always valid for summons.
|
||||
// Mob that can be summoned anywhere should not have creature_movement_template for example.
|
||||
|
||||
// No movement found for guid
|
||||
if (!i_path)
|
||||
{
|
||||
i_path = sWaypointMgr.GetPathTemplate(creature.GetEntry());
|
||||
|
||||
// No movement found for entry
|
||||
if (!i_path)
|
||||
{
|
||||
sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u) doesn't have waypoint path",
|
||||
creature.GetName(), creature.GetEntry(), creature.GetGUIDLow());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the i_currentNode to point to the first node
|
||||
if (i_path->empty())
|
||||
return;
|
||||
i_currentNode = i_path->begin()->first;
|
||||
m_lastReachedWaypoint = 0;
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::Initialize(Creature& creature)
|
||||
{
|
||||
creature.addUnitState(UNIT_STAT_ROAMING);
|
||||
creature.clearUnitState(UNIT_STAT_WAYPOINT_PAUSED);
|
||||
|
||||
LoadPath(creature);
|
||||
|
||||
StartMoveNow(creature);
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::Finalize(Creature& creature)
|
||||
{
|
||||
creature.clearUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE);
|
||||
creature.SetWalk(!creature.hasUnitState(UNIT_STAT_RUNNING_STATE), false);
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::Interrupt(Creature& creature)
|
||||
{
|
||||
creature.InterruptMoving();
|
||||
creature.clearUnitState(UNIT_STAT_ROAMING | UNIT_STAT_ROAMING_MOVE);
|
||||
creature.SetWalk(!creature.hasUnitState(UNIT_STAT_RUNNING_STATE), false);
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::Reset(Creature& creature)
|
||||
{
|
||||
creature.addUnitState(UNIT_STAT_ROAMING);
|
||||
StartMove(creature);
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
|
||||
{
|
||||
if (!i_path || i_path->empty())
|
||||
return;
|
||||
|
||||
m_lastReachedWaypoint = i_currentNode;
|
||||
|
||||
if (m_isArrivalDone)
|
||||
return;
|
||||
|
||||
creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||
m_isArrivalDone = true;
|
||||
|
||||
WaypointPath::const_iterator currPoint = i_path->find(i_currentNode);
|
||||
MANGOS_ASSERT(currPoint != i_path->end());
|
||||
WaypointNode const& node = currPoint->second;
|
||||
|
||||
if (node.script_id)
|
||||
{
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature movement start script %u at point %u for %s.", node.script_id, i_currentNode, creature.GetGuidStr().c_str());
|
||||
creature.GetMap()->ScriptsStart(sCreatureMovementScripts, node.script_id, &creature, &creature);
|
||||
}
|
||||
|
||||
// We have reached the destination and can process behavior
|
||||
if (WaypointBehavior* behavior = node.behavior)
|
||||
{
|
||||
if (behavior->emote != 0)
|
||||
creature.HandleEmote(behavior->emote);
|
||||
|
||||
if (behavior->spell != 0)
|
||||
creature.CastSpell(&creature, behavior->spell, false);
|
||||
|
||||
if (behavior->model1 != 0)
|
||||
creature.SetDisplayId(behavior->model1);
|
||||
|
||||
if (behavior->textid[0])
|
||||
{
|
||||
// Not only one text is set
|
||||
if (behavior->textid[1])
|
||||
{
|
||||
// Select one from max 5 texts (0 and 1 already checked)
|
||||
int i = 2;
|
||||
for (; i < MAX_WAYPOINT_TEXT; ++i)
|
||||
{
|
||||
if (!behavior->textid[i])
|
||||
break;
|
||||
}
|
||||
|
||||
creature.MonsterSay(behavior->textid[rand() % i], LANG_UNIVERSAL);
|
||||
}
|
||||
else
|
||||
creature.MonsterSay(behavior->textid[0], LANG_UNIVERSAL);
|
||||
}
|
||||
}
|
||||
|
||||
// Inform script
|
||||
MovementInform(creature);
|
||||
Stop(node.delay);
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::StartMoveNow(Creature& creature)
|
||||
{
|
||||
i_nextMoveTime.Reset(0);
|
||||
StartMove(creature);
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::StartMove(Creature& creature)
|
||||
{
|
||||
if (!i_path || i_path->empty())
|
||||
return;
|
||||
|
||||
if (Stopped(creature))
|
||||
return;
|
||||
|
||||
if (!creature.isAlive() || creature.hasUnitState(UNIT_STAT_NOT_MOVE))
|
||||
return;
|
||||
|
||||
WaypointPath::const_iterator currPoint = i_path->find(i_currentNode);
|
||||
MANGOS_ASSERT(currPoint != i_path->end());
|
||||
|
||||
if (WaypointBehavior* behavior = currPoint->second.behavior)
|
||||
{
|
||||
if (behavior->model2 != 0)
|
||||
creature.SetDisplayId(behavior->model2);
|
||||
creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
}
|
||||
|
||||
if (m_isArrivalDone)
|
||||
{
|
||||
++currPoint;
|
||||
if (currPoint == i_path->end())
|
||||
currPoint = i_path->begin();
|
||||
|
||||
i_currentNode = currPoint->first;
|
||||
}
|
||||
|
||||
m_isArrivalDone = false;
|
||||
|
||||
creature.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||
|
||||
WaypointNode const& nextNode = currPoint->second;;
|
||||
Movement::MoveSplineInit init(creature);
|
||||
init.MoveTo(nextNode.x, nextNode.y, nextNode.z, true);
|
||||
|
||||
if (nextNode.orientation != 100 && nextNode.delay != 0)
|
||||
init.SetFacing(nextNode.orientation);
|
||||
creature.SetWalk(!creature.hasUnitState(UNIT_STAT_RUNNING_STATE) && !creature.IsLevitating(), false);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
bool WaypointMovementGenerator<Creature>::Update(Creature& creature, const uint32& diff)
|
||||
{
|
||||
// Waypoint movement can be switched on/off
|
||||
// This is quite handy for escort quests and other stuff
|
||||
if (creature.hasUnitState(UNIT_STAT_NOT_MOVE))
|
||||
{
|
||||
creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// prevent a crash at empty waypoint path.
|
||||
if (!i_path || i_path->empty())
|
||||
{
|
||||
creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Stopped(creature))
|
||||
{
|
||||
if (CanMove(diff, creature))
|
||||
StartMove(creature);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (creature.IsStopped())
|
||||
Stop(STOP_TIME_FOR_PLAYER);
|
||||
else if (creature.movespline->Finalized())
|
||||
{
|
||||
OnArrived(creature);
|
||||
StartMove(creature);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::MovementInform(Creature& creature)
|
||||
{
|
||||
if (creature.AI())
|
||||
creature.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
|
||||
}
|
||||
|
||||
bool WaypointMovementGenerator<Creature>::GetResetPosition(Creature&, float& x, float& y, float& z) const
|
||||
{
|
||||
// prevent a crash at empty waypoint path.
|
||||
if (!i_path || i_path->empty())
|
||||
return false;
|
||||
|
||||
WaypointPath::const_iterator lastPoint = i_path->find(m_lastReachedWaypoint);
|
||||
// Special case: Before the first waypoint is reached, m_lastReachedWaypoint is set to 0 (which may not be contained in i_path)
|
||||
if (!m_lastReachedWaypoint && lastPoint == i_path->end())
|
||||
return false;
|
||||
|
||||
MANGOS_ASSERT(lastPoint != i_path->end());
|
||||
|
||||
x = lastPoint->second.x; y = lastPoint->second.y; z = lastPoint->second.z;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WaypointMovementGenerator<Creature>::Stopped(Creature& u)
|
||||
{
|
||||
return !i_nextMoveTime.Passed() || u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED);
|
||||
}
|
||||
|
||||
bool WaypointMovementGenerator<Creature>::CanMove(int32 diff, Creature& u)
|
||||
{
|
||||
i_nextMoveTime.Update(diff);
|
||||
if (i_nextMoveTime.Passed() && u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED))
|
||||
i_nextMoveTime.Reset(1);
|
||||
|
||||
return i_nextMoveTime.Passed() && !u.hasUnitState(UNIT_STAT_WAYPOINT_PAUSED);
|
||||
}
|
||||
|
||||
void WaypointMovementGenerator<Creature>::AddToWaypointPauseTime(int32 waitTimeDiff)
|
||||
{
|
||||
if (!i_nextMoveTime.Passed())
|
||||
{
|
||||
// Prevent <= 0, the code in Update requires to catch the change from moving to not moving
|
||||
int32 newWaitTime = i_nextMoveTime.GetExpiry() + waitTimeDiff;
|
||||
i_nextMoveTime.Reset(newWaitTime > 0 ? newWaitTime : 1);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------//
|
||||
uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
|
||||
{
|
||||
if (i_currentNode >= i_path->size())
|
||||
return i_path->size();
|
||||
|
||||
uint32 curMapId = (*i_path)[i_currentNode].mapid;
|
||||
|
||||
for (uint32 i = i_currentNode; i < i_path->size(); ++i)
|
||||
{
|
||||
if ((*i_path)[i].mapid != curMapId)
|
||||
return i;
|
||||
}
|
||||
|
||||
return i_path->size();
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::Initialize(Player& player)
|
||||
{
|
||||
Reset(player);
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::Finalize(Player& player)
|
||||
{
|
||||
// remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack)
|
||||
player.clearUnitState(UNIT_STAT_TAXI_FLIGHT);
|
||||
|
||||
player.Unmount();
|
||||
player.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
||||
|
||||
if (player.m_taxi.empty())
|
||||
{
|
||||
player.getHostileRefManager().setOnlineOfflineState(true);
|
||||
if (player.pvpInfo.inHostileArea)
|
||||
player.CastSpell(&player, 2479, true);
|
||||
|
||||
// update z position to ground and orientation for landing point
|
||||
// this prevent cheating with landing point at lags
|
||||
// when client side flight end early in comparison server side
|
||||
player.StopMoving(true);
|
||||
}
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::Interrupt(Player& player)
|
||||
{
|
||||
player.clearUnitState(UNIT_STAT_TAXI_FLIGHT);
|
||||
}
|
||||
|
||||
#define PLAYER_FLIGHT_SPEED 32.0f
|
||||
|
||||
void FlightPathMovementGenerator::Reset(Player& player)
|
||||
{
|
||||
player.getHostileRefManager().setOnlineOfflineState(false);
|
||||
player.addUnitState(UNIT_STAT_TAXI_FLIGHT);
|
||||
player.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
|
||||
|
||||
Movement::MoveSplineInit init(player);
|
||||
uint32 end = GetPathAtMapEnd();
|
||||
for (uint32 i = GetCurrentNode(); i != end; ++i)
|
||||
{
|
||||
G3D::Vector3 vertice((*i_path)[i].x, (*i_path)[i].y, (*i_path)[i].z);
|
||||
init.Path().push_back(vertice);
|
||||
}
|
||||
init.SetFirstPointId(GetCurrentNode());
|
||||
init.SetFly();
|
||||
init.SetSmooth();
|
||||
init.SetWalk(true);
|
||||
init.SetVelocity(PLAYER_FLIGHT_SPEED);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
bool FlightPathMovementGenerator::Update(Player& player, const uint32& diff)
|
||||
{
|
||||
uint32 pointId = (uint32)player.movespline->currentPathIdx();
|
||||
if (pointId > i_currentNode)
|
||||
{
|
||||
bool departureEvent = true;
|
||||
do
|
||||
{
|
||||
DoEventIfAny(player, (*i_path)[i_currentNode], departureEvent);
|
||||
if (pointId == i_currentNode)
|
||||
break;
|
||||
i_currentNode += (uint32)departureEvent;
|
||||
departureEvent = !departureEvent;
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
return i_currentNode < (i_path->size() - 1);
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
|
||||
{
|
||||
if (i_path->empty())
|
||||
return;
|
||||
|
||||
uint32 map0 = (*i_path)[0].mapid;
|
||||
|
||||
for (size_t i = 1; i < i_path->size(); ++i)
|
||||
{
|
||||
if ((*i_path)[i].mapid != map0)
|
||||
{
|
||||
i_currentNode = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlightPathMovementGenerator::DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure)
|
||||
{
|
||||
if (uint32 eventid = departure ? node.departureEventID : node.arrivalEventID)
|
||||
{
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.index, node.path, player.GetName());
|
||||
StartEvents_Event(player.GetMap(), eventid, &player, &player, departure);
|
||||
}
|
||||
}
|
||||
|
||||
bool FlightPathMovementGenerator::GetResetPosition(Player&, float& x, float& y, float& z) const
|
||||
{
|
||||
const TaxiPathNodeEntry& node = (*i_path)[i_currentNode];
|
||||
x = node.x; y = node.y; z = node.z;
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue