Core/Movement: Implement spline movement subsystem.
Spline movement controls movements of server-side controlled units (monster movement, taxi movement, etc). Proper implementation of effects such as charge, jump, cyclic movement will rely on it. However, need improve our states system before. Technical changes: * Added linear, catmullrom and bezier3 splines which based on client's algorthims. They can be reused for proper transport position interpolation. * Precission increased. There are no more position desync issues since client's position calculation formulas used. * Now possible to move by paths with multiple points, send whole path to client. -- Original author of research and implementation: SilverIce. Massive kudos. Original port for Trinity (ref #4629) Chaplain and Venugh With the following incremental fixes during my review: - Restore flightmaster end grid pre-loading - Fix uninitialized Creature::m_path_id - Add missing trinity_string entries for .movegens command - Fix a bug in WaypointMovementGenerator that would trigger unexpected pausing at waypoints for various amounts of time Known issues: - Errors like WaypointMovementGenerator::LoadPath creature XXX (Entry: YYYYY GUID: ZZZZZZ) doesn't have waypoint path id: 0. This is caused by bad DB data. This commit didn't "break" it. Do not forget to re-run CMake before compiling.
This commit is contained in:
@@ -48,6 +48,8 @@
|
||||
#include "Vehicle.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "Group.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
// apply implementation of the singletons
|
||||
|
||||
TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
|
||||
@@ -143,7 +145,7 @@ m_PlayerDamageReq(0), m_lootMoney(0), m_lootRecipient(0), m_lootRecipientGroup(0
|
||||
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
|
||||
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false),
|
||||
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
|
||||
m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL)
|
||||
m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL), m_path_id(0)
|
||||
{
|
||||
m_regenTimer = CREATURE_REGEN_INTERVAL;
|
||||
m_valuesCount = UNIT_END;
|
||||
@@ -332,6 +334,7 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data
|
||||
SetSpeed(MOVE_FLIGHT, 1.0f); // using 1.0 rate
|
||||
|
||||
SetFloatValue(OBJECT_FIELD_SCALE_X, cinfo->scale);
|
||||
SetLevitate(canFly());
|
||||
|
||||
// checked at loading
|
||||
m_defaultMovementType = MovementGeneratorType(cinfo->MovementType);
|
||||
@@ -435,6 +438,17 @@ void Creature::Update(uint32 diff)
|
||||
m_vehicleKit->Reset();
|
||||
}
|
||||
|
||||
if (IsInWater())
|
||||
{
|
||||
if (canSwim())
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (canWalk())
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
|
||||
}
|
||||
|
||||
switch (m_deathState)
|
||||
{
|
||||
case JUST_ALIVED:
|
||||
@@ -472,9 +486,7 @@ void Creature::Update(uint32 diff)
|
||||
}
|
||||
case CORPSE:
|
||||
{
|
||||
m_Events.Update(diff);
|
||||
_UpdateSpells(diff);
|
||||
|
||||
Unit::Update(diff);
|
||||
// deathstate changed on spells update, prevent problems
|
||||
if (m_deathState != CORPSE)
|
||||
break;
|
||||
@@ -565,9 +577,6 @@ void Creature::Update(uint32 diff)
|
||||
m_regenTimer = CREATURE_REGEN_INTERVAL;
|
||||
break;
|
||||
}
|
||||
case DEAD_FALLING:
|
||||
GetMotionMaster()->UpdateMotion(diff);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -945,7 +954,8 @@ void Creature::AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint3
|
||||
|
||||
m_startMove = getMSTime();
|
||||
m_moveTime = time;*/
|
||||
SendMonsterMove(x, y, z, time);
|
||||
float speed = GetDistance(x, y, z) / ((float)time * 0.001f);
|
||||
MonsterMoveWithSpeed(x, y, z, speed);
|
||||
}
|
||||
|
||||
Player* Creature::GetLootRecipient() const
|
||||
@@ -1507,8 +1517,8 @@ void Creature::setDeathState(DeathState s)
|
||||
if (m_formation && m_formation->getLeader() == this)
|
||||
m_formation->FormationReset(true);
|
||||
|
||||
if ((canFly() || IsFlying()) && FallGround())
|
||||
return;
|
||||
if ((canFly() || IsFlying()))
|
||||
i_motionMaster.MoveFall();
|
||||
|
||||
Unit::setDeathState(CORPSE);
|
||||
}
|
||||
@@ -1520,7 +1530,7 @@ void Creature::setDeathState(DeathState s)
|
||||
SetLootRecipient(NULL);
|
||||
ResetPlayerDamageReq();
|
||||
CreatureTemplate const* cinfo = GetCreatureInfo();
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
SetWalk(true);
|
||||
if (GetCreatureInfo()->InhabitType & INHABIT_AIR)
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING);
|
||||
if (GetCreatureInfo()->InhabitType & INHABIT_WATER)
|
||||
@@ -1536,24 +1546,6 @@ void Creature::setDeathState(DeathState s)
|
||||
}
|
||||
}
|
||||
|
||||
bool Creature::FallGround()
|
||||
{
|
||||
// Let's abort after we called this function one time
|
||||
if (getDeathState() == DEAD_FALLING)
|
||||
return false;
|
||||
|
||||
float x, y, z;
|
||||
GetPosition(x, y, z);
|
||||
// use larger distance for vmap height search than in most other cases
|
||||
float ground_Z = GetMap()->GetHeight(x, y, z, true, MAX_FALL_DISTANCE);
|
||||
if (fabs(ground_Z - z) < 0.1f)
|
||||
return false;
|
||||
|
||||
GetMotionMaster()->MoveFall(ground_Z, EVENT_FALL_GROUND);
|
||||
Unit::setDeathState(DEAD_FALLING);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Creature::Respawn(bool force)
|
||||
{
|
||||
DestroyForNearbyPlayers();
|
||||
@@ -2415,3 +2407,25 @@ bool Creature::IsDungeonBoss() const
|
||||
CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(GetEntry());
|
||||
return cinfo && (cinfo->flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS);
|
||||
}
|
||||
|
||||
void Creature::SetWalk(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
else
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9);
|
||||
data.append(GetPackGUID());
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Creature::SetLevitate(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
|
||||
else
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
|
||||
data.append(GetPackGUID());
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
@@ -520,6 +520,9 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
|
||||
void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type);
|
||||
CreatureAI* AI() const { return (CreatureAI*)i_AI; }
|
||||
|
||||
void SetWalk(bool enable);
|
||||
void SetLevitate(bool enable);
|
||||
|
||||
uint32 GetShieldBlockValue() const //dunno mob block value
|
||||
{
|
||||
return (getLevel()/2 + uint32(GetStat(STAT_STRENGTH)/20));
|
||||
@@ -573,7 +576,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
|
||||
const char* GetNameForLocaleIdx(LocaleConstant locale_idx) const;
|
||||
|
||||
void setDeathState(DeathState s); // override virtual Unit::setDeathState
|
||||
bool FallGround();
|
||||
|
||||
bool LoadFromDB(uint32 guid, Map* map) { return LoadCreatureFromDB(guid, map, false); }
|
||||
bool LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap = true);
|
||||
|
||||
@@ -212,10 +212,12 @@ void CreatureGroup::FormationReset(bool dismiss)
|
||||
|
||||
void CreatureGroup::LeaderMoveTo(float x, float y, float z)
|
||||
{
|
||||
//! To do: This should probably get its own movement generator or use WaypointMovementGenerator.
|
||||
//! If the leader's path is known, member's path can be plotted as well using formation offsets.
|
||||
if (!m_leader)
|
||||
return;
|
||||
|
||||
float pathangle = atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x);
|
||||
float pathangle = atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x);
|
||||
|
||||
for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
|
||||
@@ -1869,4 +1869,4 @@ void GameObject::SetLootState(LootState s)
|
||||
{
|
||||
m_lootState = s;
|
||||
AI()->OnStateChanged(s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "TemporarySummon.h"
|
||||
#include "Totem.h"
|
||||
#include "OutdoorPvPMgr.h"
|
||||
#include "MovementPacketBuilder.h"
|
||||
|
||||
uint32 GuidHigh2TypeId(uint32 guid_hi)
|
||||
{
|
||||
@@ -312,78 +313,17 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const
|
||||
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_WALK);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_RUN);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_SWIM_BACK);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_SWIM);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_RUN_BACK);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_SWIM);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_SWIM_BACK);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT_BACK);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_TURN_RATE);
|
||||
*data << ((Unit*)this)->GetSpeed(MOVE_PITCH_RATE);
|
||||
|
||||
const Player* player = ToPlayer();
|
||||
|
||||
// 0x08000000
|
||||
if (player && player->isInFlight())
|
||||
{
|
||||
uint32 flags3 = SPLINEFLAG_GLIDE;
|
||||
|
||||
*data << uint32(flags3); // splines flag?
|
||||
|
||||
if (flags3 & 0x20000) // may be orientation
|
||||
{
|
||||
*data << (float)0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags3 & 0x8000) // probably x, y, z coords there
|
||||
{
|
||||
*data << (float)0;
|
||||
*data << (float)0;
|
||||
*data << (float)0;
|
||||
}
|
||||
|
||||
if (flags3 & 0x10000) // probably guid there
|
||||
{
|
||||
*data << uint64(0);
|
||||
}
|
||||
}
|
||||
|
||||
FlightPathMovementGenerator *fmg =
|
||||
(FlightPathMovementGenerator*)(player->GetMotionMaster()->top());
|
||||
TaxiPathNodeList const& path = fmg->GetPath();
|
||||
|
||||
float x, y, z;
|
||||
player->GetPosition(x, y, z);
|
||||
|
||||
uint32 inflighttime = uint32(path.GetPassedLength(fmg->GetCurrentNode(), x, y, z) * 32);
|
||||
uint32 traveltime = uint32(path.GetTotalLength() * 32);
|
||||
|
||||
*data << uint32(inflighttime); // passed move time?
|
||||
*data << uint32(traveltime); // full move time?
|
||||
*data << uint32(0); // ticks count?
|
||||
|
||||
*data << float(0); // added in 3.1
|
||||
*data << float(0); // added in 3.1
|
||||
*data << float(0); // added in 3.1
|
||||
|
||||
*data << uint32(0); // added in 3.1
|
||||
|
||||
uint32 poscount = uint32(path.size());
|
||||
*data << uint32(poscount); // points count
|
||||
|
||||
for (uint32 i = 0; i < poscount; ++i)
|
||||
{
|
||||
*data << float(path[i].x);
|
||||
*data << float(path[i].y);
|
||||
*data << float(path[i].z);
|
||||
}
|
||||
|
||||
*data << uint8(0); // added in 3.0.8
|
||||
|
||||
*data << float(path[poscount-1].x);
|
||||
*data << float(path[poscount-1].y);
|
||||
*data << float(path[poscount-1].z);
|
||||
}
|
||||
if (((Unit*)this)->m_movementInfo.GetMovementFlags() & MOVEMENTFLAG_SPLINE_ENABLED)
|
||||
Movement::PacketBuilder::WriteCreate(*((Unit*)this)->movespline, *data);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -487,7 +427,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const
|
||||
// 0x200
|
||||
if (flags & UPDATEFLAG_ROTATION)
|
||||
{
|
||||
*data << uint64(((GameObject*)this)->GetRotation());
|
||||
*data << int64(((GameObject*)this)->GetRotation());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1595,6 +1535,70 @@ void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
|
||||
z = new_z+ 0.05f; // just to be sure that we are not a few pixel under the surface
|
||||
}
|
||||
|
||||
void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
|
||||
{
|
||||
switch (GetTypeId())
|
||||
{
|
||||
case TYPEID_UNIT:
|
||||
{
|
||||
// non fly unit don't must be in air
|
||||
// non swim unit must be at ground (mostly speedup, because it don't must be in water and water level check less fast
|
||||
if (!((Creature const*)this)->canFly())
|
||||
{
|
||||
bool canSwim = ((Creature const*)this)->canSwim();
|
||||
float ground_z = z;
|
||||
float max_z = canSwim
|
||||
? GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK))
|
||||
: ((ground_z = GetBaseMap()->GetHeight(x, y, z, true)));
|
||||
if (max_z > INVALID_HEIGHT)
|
||||
{
|
||||
if (z > max_z)
|
||||
z = max_z;
|
||||
else if (z < ground_z)
|
||||
z = ground_z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float ground_z = GetBaseMap()->GetHeight(x, y, z, true);
|
||||
if (z < ground_z)
|
||||
z = ground_z;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPEID_PLAYER:
|
||||
{
|
||||
// for server controlled moves playr work same as creature (but it can always swim)
|
||||
if (!((Player const*)this)->canFly())
|
||||
{
|
||||
float ground_z = z;
|
||||
float max_z = GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK));
|
||||
if (max_z > INVALID_HEIGHT)
|
||||
{
|
||||
if (z > max_z)
|
||||
z = max_z;
|
||||
else if (z < ground_z)
|
||||
z = ground_z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float ground_z = GetBaseMap()->GetHeight(x, y, z, true);
|
||||
if (z < ground_z)
|
||||
z = ground_z;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
float ground_z = GetBaseMap()->GetHeight(x, y, z, true);
|
||||
if(ground_z > INVALID_HEIGHT)
|
||||
z = ground_z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Position::IsPositionValid() const
|
||||
{
|
||||
return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, m_orientation);
|
||||
@@ -2033,7 +2037,8 @@ void Unit::BuildHeartBeatMsg(WorldPacket* data) const
|
||||
|
||||
void WorldObject::SendMessageToSet(WorldPacket* data, bool self)
|
||||
{
|
||||
SendMessageToSetInRange(data, GetVisibilityRange(), self);
|
||||
if (IsInWorld())
|
||||
SendMessageToSetInRange(data, GetVisibilityRange(), self);
|
||||
}
|
||||
|
||||
void WorldObject::SendMessageToSetInRange(WorldPacket* data, float dist, bool /*self*/)
|
||||
|
||||
@@ -497,7 +497,9 @@ struct MovementInfo
|
||||
}
|
||||
|
||||
uint32 GetMovementFlags() { return flags; }
|
||||
void SetMovementFlags(uint32 flag) { flags = flag; }
|
||||
void AddMovementFlag(uint32 flag) { flags |= flag; }
|
||||
void RemoveMovementFlag(uint32 flag) { flags &= ~flag; }
|
||||
bool HasMovementFlag(uint32 flag) const { return flags & flag; }
|
||||
|
||||
uint16 GetExtraMovementFlags() { return flags2; }
|
||||
@@ -615,6 +617,7 @@ class WorldObject : public Object, public WorldLocation
|
||||
return (m_valuesCount > UNIT_FIELD_COMBATREACH) ? m_floatValues[UNIT_FIELD_COMBATREACH] : DEFAULT_WORLD_OBJECT_SIZE;
|
||||
}
|
||||
void UpdateGroundPositionZ(float x, float y, float &z) const;
|
||||
void UpdateAllowedPositionZ(float x, float y, float &z) const;
|
||||
|
||||
void GetRandomPoint(const Position &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const;
|
||||
void GetRandomPoint(const Position &srcPos, float distance, Position &pos) const
|
||||
|
||||
@@ -2101,6 +2101,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
|
||||
// reset movement flags at teleport, because player will continue move with these flags after teleport
|
||||
SetUnitMovementFlags(0);
|
||||
DisableSpline();
|
||||
|
||||
if (m_transport)
|
||||
{
|
||||
@@ -5148,43 +5149,10 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FallMode = 0 implies that the player is dying, or already dead, and the proper death state will be set.
|
||||
* = 1 simply causes the player to plummet towards the ground, and not suffer any damage.
|
||||
* = 2 causes the player to plummet towards the ground, and causes falling damage, regardless
|
||||
* of any auras that might of prevented fall damage.
|
||||
*/
|
||||
bool Player::FallGround(uint8 FallMode)
|
||||
{
|
||||
// Let's abort after we called this function one time
|
||||
if (getDeathState() == DEAD_FALLING && FallMode == 0)
|
||||
return false;
|
||||
|
||||
float x, y, z;
|
||||
GetPosition(x, y, z);
|
||||
float ground_Z = GetMap()->GetHeight(x, y, z);
|
||||
float z_diff = 0.0f;
|
||||
if ((z_diff = fabs(ground_Z - z)) < 0.1f)
|
||||
return false;
|
||||
|
||||
GetMotionMaster()->MoveFall(ground_Z, EVENT_FALL_GROUND);
|
||||
|
||||
// Below formula for falling damage is from Player::HandleFall
|
||||
if (FallMode == 2 && z_diff >= 14.57f)
|
||||
{
|
||||
uint32 damage = std::min(GetMaxHealth(), (uint32)((0.018f * z_diff - 0.2426f) * GetMaxHealth() * sWorld->getRate(RATE_DAMAGE_FALL)));
|
||||
if (damage)
|
||||
EnvironmentalDamage(DAMAGE_FALL, damage);
|
||||
}
|
||||
else if (FallMode == 0)
|
||||
Unit::setDeathState(DEAD_FALLING);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Player::KillPlayer()
|
||||
{
|
||||
if (IsFlying() && !GetTransport())
|
||||
FallGround();
|
||||
i_motionMaster.MoveFall();
|
||||
|
||||
SetMovement(MOVE_ROOT);
|
||||
|
||||
@@ -21474,8 +21442,6 @@ void Player::SendInitialVisiblePackets(Unit* target)
|
||||
SendAurasForTarget(target);
|
||||
if (target->isAlive())
|
||||
{
|
||||
if (target->GetMotionMaster()->GetCurrentMovementGeneratorType() != IDLE_MOTION_TYPE)
|
||||
target->SendMonsterMoveWithSpeedToCurrentDestination(this);
|
||||
if (target->HasUnitState(UNIT_STAT_MELEE_ATTACKING) && target->getVictim())
|
||||
target->SendMeleeAttackStart(target->getVictim());
|
||||
}
|
||||
|
||||
@@ -1964,7 +1964,6 @@ class Player : public Unit, public GridObject<Player>
|
||||
Corpse* GetCorpse() const;
|
||||
void SpawnCorpseBones();
|
||||
void CreateCorpse();
|
||||
bool FallGround(uint8 FallMode = 0);
|
||||
void KillPlayer();
|
||||
uint32 GetResurrectionSpellId();
|
||||
void ResurrectPlayer(float restore_percent, bool applySickness = false);
|
||||
|
||||
@@ -45,16 +45,16 @@
|
||||
#include "InstanceSaveMgr.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Path.h"
|
||||
#include "CreatureGroups.h"
|
||||
#include "PetAI.h"
|
||||
#include "PassiveAI.h"
|
||||
#include "Traveller.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "Vehicle.h"
|
||||
#include "Transport.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "MoveSpline.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -62,9 +62,9 @@ float baseMoveSpeed[MAX_MOVE_TYPE] =
|
||||
{
|
||||
2.5f, // MOVE_WALK
|
||||
7.0f, // MOVE_RUN
|
||||
2.5f, // MOVE_RUN_BACK
|
||||
4.5f, // MOVE_RUN_BACK
|
||||
4.722222f, // MOVE_SWIM
|
||||
4.5f, // MOVE_SWIM_BACK
|
||||
2.5f, // MOVE_SWIM_BACK
|
||||
3.141594f, // MOVE_TURN_RATE
|
||||
7.0f, // MOVE_FLIGHT
|
||||
4.5f, // MOVE_FLIGHT_BACK
|
||||
@@ -73,9 +73,9 @@ float baseMoveSpeed[MAX_MOVE_TYPE] =
|
||||
float playerBaseMoveSpeed[MAX_MOVE_TYPE] = {
|
||||
2.5f, // MOVE_WALK
|
||||
7.0f, // MOVE_RUN
|
||||
2.5f, // MOVE_RUN_BACK
|
||||
4.5f, // MOVE_RUN_BACK
|
||||
4.722222f, // MOVE_SWIM
|
||||
4.5f, // MOVE_SWIM_BACK
|
||||
2.5f, // MOVE_SWIM_BACK
|
||||
3.141594f, // MOVE_TURN_RATE
|
||||
7.0f, // MOVE_FLIGHT
|
||||
4.5f, // MOVE_FLIGHT_BACK
|
||||
@@ -148,7 +148,7 @@ Unit::Unit(bool isWorldObject): WorldObject(isWorldObject),
|
||||
m_movedPlayer(NULL), m_lastSanctuaryTime(0), IsAIEnabled(false), NeedChangeAI(false),
|
||||
m_ControlledByPlayer(false), i_AI(NULL), i_disabledAI(NULL), m_procDeep(0),
|
||||
m_removedAurasCount(0), i_motionMaster(this), m_ThreatManager(this), m_vehicle(NULL),
|
||||
m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this)
|
||||
m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this), movespline(new Movement::MoveSpline())
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default:4355)
|
||||
@@ -280,6 +280,7 @@ Unit::~Unit()
|
||||
|
||||
delete m_charmInfo;
|
||||
delete m_vehicleKit;
|
||||
delete movespline;
|
||||
|
||||
ASSERT(!m_duringRemoveFromWorld);
|
||||
ASSERT(!m_attacking);
|
||||
@@ -346,6 +347,7 @@ void Unit::Update(uint32 p_time)
|
||||
ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, HealthAbovePct(75));
|
||||
}
|
||||
|
||||
UpdateSplineMovement(p_time);
|
||||
i_motionMaster.UpdateMotion(p_time);
|
||||
}
|
||||
|
||||
@@ -357,151 +359,46 @@ bool Unit::haveOffhandWeapon() const
|
||||
return m_canDualWield;
|
||||
}
|
||||
|
||||
void Unit::SendMonsterMoveWithSpeedToCurrentDestination(Player* player)
|
||||
void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed)
|
||||
{
|
||||
float x, y, z;
|
||||
if (GetMotionMaster()->GetDestination(x, y, z))
|
||||
SendMonsterMoveWithSpeed(x, y, z, 0, player);
|
||||
Movement::MoveSplineInit init(*this);
|
||||
init.MoveTo(x,y,z);
|
||||
init.SetVelocity(speed);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime, Player* player)
|
||||
void Unit::UpdateSplineMovement(uint32 t_diff)
|
||||
{
|
||||
if (!transitTime)
|
||||
enum{
|
||||
POSITION_UPDATE_DELAY = 400,
|
||||
};
|
||||
|
||||
if (movespline->Finalized())
|
||||
return;
|
||||
|
||||
movespline->updateState(t_diff);
|
||||
bool arrived = movespline->Finalized();
|
||||
|
||||
if (arrived)
|
||||
DisableSpline();
|
||||
|
||||
m_movesplineTimer.Update(t_diff);
|
||||
if (m_movesplineTimer.Passed() || arrived)
|
||||
{
|
||||
m_movesplineTimer.Reset(POSITION_UPDATE_DELAY);
|
||||
Movement::Location loc = movespline->ComputePosition();
|
||||
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
Traveller<Player> traveller(*(Player*)this);
|
||||
transitTime = traveller.GetTotalTrevelTimeTo(x, y, z);
|
||||
}
|
||||
((Player*)this)->UpdatePosition(loc.x,loc.y,loc.z,loc.orientation);
|
||||
else
|
||||
{
|
||||
Traveller<Creature> traveller(*ToCreature());
|
||||
transitTime = traveller.GetTotalTrevelTimeTo(x, y, z);
|
||||
}
|
||||
GetMap()->CreatureRelocation((Creature*)this,loc.x,loc.y,loc.z,loc.orientation);
|
||||
}
|
||||
//float orientation = (float)atan2((double)dy, (double)dx);
|
||||
SendMonsterMove(x, y, z, transitTime, player);
|
||||
}
|
||||
|
||||
void Unit::SetFacing(float ori, WorldObject* obj)
|
||||
void Unit::DisableSpline()
|
||||
{
|
||||
SetOrientation(obj ? GetAngle(obj) : ori);
|
||||
|
||||
WorldPacket data(SMSG_MONSTER_MOVE, (1+12+4+1+(obj ? 8 : 4)+4+4+4+12+GetPackGUID().size()));
|
||||
data.append(GetPackGUID());
|
||||
data << uint8(0); // unk
|
||||
data << GetPositionX() << GetPositionY() << GetPositionZ();
|
||||
data << getMSTime();
|
||||
if (obj)
|
||||
{
|
||||
data << uint8(SPLINETYPE_FACING_TARGET);
|
||||
data << uint64(obj->GetGUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
data << uint8(SPLINETYPE_FACING_ANGLE);
|
||||
data << ori;
|
||||
}
|
||||
data << uint32(SPLINEFLAG_NONE);
|
||||
data << uint32(0); // move time 0
|
||||
data << uint32(1); // one point
|
||||
data << GetPositionX() << GetPositionY() << GetPositionZ();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Unit::SendMonsterStop(bool on_death)
|
||||
{
|
||||
WorldPacket data(SMSG_MONSTER_MOVE, (17 + GetPackGUID().size()));
|
||||
data.append(GetPackGUID());
|
||||
data << uint8(0); // new in 3.1
|
||||
data << GetPositionX() << GetPositionY() << GetPositionZ();
|
||||
data << getMSTime();
|
||||
|
||||
if (on_death == true)
|
||||
{
|
||||
data << uint8(0);
|
||||
data << uint32((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) ? SPLINEFLAG_FLYING : SPLINEFLAG_WALKING);
|
||||
data << uint32(0); // Time in between points
|
||||
data << uint32(1); // 1 single waypoint
|
||||
data << GetPositionX() << GetPositionY() << GetPositionZ();
|
||||
}
|
||||
else
|
||||
data << uint8(1);
|
||||
|
||||
SendMessageToSet(&data, true);
|
||||
|
||||
ClearUnitState(UNIT_STAT_MOVE);
|
||||
}
|
||||
|
||||
void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player)
|
||||
{
|
||||
WorldPacket data(SMSG_MONSTER_MOVE, 1+12+4+1+4+4+4+12+GetPackGUID().size());
|
||||
data.append(GetPackGUID());
|
||||
|
||||
data << uint8(0); // new in 3.1
|
||||
data << GetPositionX() << GetPositionY() << GetPositionZ();
|
||||
data << getMSTime();
|
||||
|
||||
data << uint8(0);
|
||||
data << uint32((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) ? SPLINEFLAG_FLYING : SPLINEFLAG_WALKING);
|
||||
data << Time; // Time in between points
|
||||
data << uint32(1); // 1 single waypoint
|
||||
data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B
|
||||
|
||||
if (player)
|
||||
player->GetSession()->SendPacket(&data);
|
||||
else
|
||||
SendMessageToSet(&data, true);
|
||||
|
||||
AddUnitState(UNIT_STAT_MOVE);
|
||||
}
|
||||
|
||||
void Unit::SendMonsterMove(MonsterMoveData const& moveData, Player* player)
|
||||
{
|
||||
WorldPacket data(SMSG_MONSTER_MOVE, GetPackGUID().size() + 1 + 12 + 4 + 1 + 4 + 8 + 4 + 4 + 12);
|
||||
data.append(GetPackGUID());
|
||||
|
||||
data << uint8(0); // new in 3.1
|
||||
data << GetPositionX() << GetPositionY() << GetPositionZ();
|
||||
data << getMSTime();
|
||||
|
||||
data << uint8(0);
|
||||
data << moveData.SplineFlag;
|
||||
|
||||
if (moveData.SplineFlag & SPLINEFLAG_ANIMATIONTIER)
|
||||
{
|
||||
data << uint8(moveData.AnimationState);
|
||||
data << uint32(0);
|
||||
}
|
||||
|
||||
data << moveData.Time;
|
||||
|
||||
if (moveData.SplineFlag & SPLINEFLAG_TRAJECTORY)
|
||||
{
|
||||
data << moveData.SpeedZ;
|
||||
data << uint32(0); // walk time after jump
|
||||
}
|
||||
|
||||
data << uint32(1); // waypoint count
|
||||
data << moveData.DestLocation.GetPositionX();
|
||||
data << moveData.DestLocation.GetPositionY();
|
||||
data << moveData.DestLocation.GetPositionZ();
|
||||
|
||||
if (player)
|
||||
player->GetSession()->SendPacket(&data);
|
||||
else
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player* player)
|
||||
{
|
||||
MonsterMoveData data;
|
||||
data.DestLocation.Relocate(NewPosX, NewPosY, NewPosZ);
|
||||
data.SplineFlag = MoveFlags;
|
||||
data.Time = time;
|
||||
data.SpeedZ = speedZ;
|
||||
|
||||
SendMonsterMove(data, player);
|
||||
m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD));
|
||||
movespline->_Interrupt();
|
||||
}
|
||||
|
||||
void Unit::SendMonsterMoveExitVehicle(Position const* newPos)
|
||||
@@ -3106,17 +3003,6 @@ bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const
|
||||
return IsWithinDistInMap(target, distance) && !HasInArc(2 * M_PI - arc, target);
|
||||
}
|
||||
|
||||
void Unit::SetFacingToObject(WorldObject* pObject)
|
||||
{
|
||||
// update orientation at server
|
||||
SetOrientation(GetAngle(pObject));
|
||||
|
||||
// and client
|
||||
WorldPacket data;
|
||||
BuildHeartBeatMsg(&data);
|
||||
SendMessageToSet(&data, false);
|
||||
}
|
||||
|
||||
bool Unit::isInAccessiblePlaceFor(Creature const* c) const
|
||||
{
|
||||
if (IsInWater())
|
||||
@@ -12744,7 +12630,7 @@ void Unit::setDeathState(DeathState s)
|
||||
ClearDiminishings();
|
||||
GetMotionMaster()->Clear(false);
|
||||
GetMotionMaster()->MoveIdle();
|
||||
SendMonsterStop(true);
|
||||
StopMoving();
|
||||
// without this when removing IncreaseMaxHealth aura player may stuck with 1 hp
|
||||
// do not why since in IncreaseMaxHealth currenthealth is checked
|
||||
SetHealth(0);
|
||||
@@ -13565,7 +13451,7 @@ void Unit::SetHealth(uint32 val)
|
||||
{
|
||||
if (getDeathState() == JUST_DIED)
|
||||
val = 0;
|
||||
else if (GetTypeId() == TYPEID_PLAYER && (getDeathState() == DEAD || getDeathState() == DEAD_FALLING))
|
||||
else if (GetTypeId() == TYPEID_PLAYER && getDeathState() == DEAD)
|
||||
val = 1;
|
||||
else
|
||||
{
|
||||
@@ -14682,22 +14568,20 @@ void Unit::StopMoving()
|
||||
{
|
||||
ClearUnitState(UNIT_STAT_MOVING);
|
||||
|
||||
// send explicit stop packet
|
||||
// rely on vmaps here because for example stormwind is in air
|
||||
//float z = sMapMgr->GetBaseMap(GetMapId())->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true);
|
||||
//if (fabs(GetPositionZ() - z) < 2.0f)
|
||||
// Relocate(GetPositionX(), GetPositionY(), z);
|
||||
//Relocate(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
// not need send any packets if not in world
|
||||
if (!IsInWorld())
|
||||
return;
|
||||
|
||||
if (!(GetUnitMovementFlags() & MOVEMENTFLAG_ONTRANSPORT))
|
||||
SendMonsterStop();
|
||||
Movement::MoveSplineInit init(*this);
|
||||
init.SetFacing(GetOrientation());
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
void Unit::SendMovementFlagUpdate()
|
||||
{
|
||||
WorldPacket data;
|
||||
BuildHeartBeatMsg(&data);
|
||||
SendMessageToSet(&data, false);
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
bool Unit::IsSitState() const
|
||||
@@ -17097,7 +16981,7 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
|
||||
WorldPacket data2;
|
||||
BuildHeartBeatMsg(&data2);
|
||||
SendMessageToSet(&data2, false);
|
||||
SendMessageToSet(&data2, true);
|
||||
|
||||
if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
|
||||
if (((Minion*)vehicle->GetBase())->GetOwner() == this)
|
||||
@@ -17116,25 +17000,6 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
|
||||
void Unit::BuildMovementPacket(ByteBuffer *data) const
|
||||
{
|
||||
switch (GetTypeId())
|
||||
{
|
||||
case TYPEID_UNIT:
|
||||
if (canFly())
|
||||
const_cast<Unit*>(this)->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
|
||||
break;
|
||||
case TYPEID_PLAYER:
|
||||
// remove unknown, unused etc flags for now
|
||||
const_cast<Unit*>(this)->RemoveUnitMovementFlag(MOVEMENTFLAG_SPLINE_ENABLED);
|
||||
if (isInFlight())
|
||||
{
|
||||
WPAssert(const_cast<Unit*>(this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE);
|
||||
const_cast<Unit*>(this)->AddUnitMovementFlag(MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_SPLINE_ENABLED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*data << uint32(GetUnitMovementFlags()); // movement flags
|
||||
*data << uint16(m_movementInfo.flags2); // 2.3.0
|
||||
*data << uint32(getMSTime()); // time
|
||||
@@ -17198,13 +17063,13 @@ void Unit::SetFlying(bool apply)
|
||||
|
||||
void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool casting /*= false*/)
|
||||
{
|
||||
DisableSpline();
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
ToPlayer()->TeleportTo(GetMapId(), x, y, z, orientation, TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : 0));
|
||||
else
|
||||
{
|
||||
// FIXME: this interrupts spell visual
|
||||
DestroyForNearbyPlayers();
|
||||
UpdatePosition(x, y, z, orientation, true);
|
||||
SendMovementFlagUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17486,3 +17351,26 @@ bool CharmInfo::IsReturning()
|
||||
{
|
||||
return m_isReturning;
|
||||
}
|
||||
|
||||
void Unit::SetInFront(Unit const* target)
|
||||
{
|
||||
if (!HasUnitState(UNIT_STAT_CANNOT_TURN))
|
||||
SetOrientation(GetAngle(target));
|
||||
}
|
||||
|
||||
void Unit::SetFacingTo(float ori)
|
||||
{
|
||||
Movement::MoveSplineInit init(*this);
|
||||
init.SetFacing(ori);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
void Unit::SetFacingToObject(WorldObject* pObject)
|
||||
{
|
||||
// never face when already moving
|
||||
if (!IsStopped())
|
||||
return;
|
||||
|
||||
// TODO: figure out under what conditions creature will move towards object instead of facing it where it currently is.
|
||||
SetFacingTo(GetAngle(pObject));
|
||||
}
|
||||
|
||||
@@ -465,7 +465,6 @@ enum DeathState
|
||||
CORPSE = 2,
|
||||
DEAD = 3,
|
||||
JUST_ALIVED = 4,
|
||||
DEAD_FALLING= 5
|
||||
};
|
||||
|
||||
enum UnitState
|
||||
@@ -493,13 +492,22 @@ enum UnitState
|
||||
UNIT_STAT_MOVE = 0x00100000,
|
||||
UNIT_STAT_ROTATING = 0x00200000,
|
||||
UNIT_STAT_EVADE = 0x00400000,
|
||||
UNIT_STAT_ROAMING_MOVE = 0x00800000,
|
||||
UNIT_STAT_CONFUSED_MOVE = 0x01000000,
|
||||
UNIT_STAT_FLEEING_MOVE = 0x02000000,
|
||||
UNIT_STAT_CHASE_MOVE = 0x04000000,
|
||||
UNIT_STAT_FOLLOW_MOVE = 0x08000000,
|
||||
UNIT_STAT_UNATTACKABLE = (UNIT_STAT_IN_FLIGHT | UNIT_STAT_ONVEHICLE),
|
||||
UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE),
|
||||
//UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE),
|
||||
// for real move using movegen check and stop (except unstoppable flight)
|
||||
UNIT_STAT_MOVING = UNIT_STAT_ROAMING_MOVE | UNIT_STAT_CONFUSED_MOVE | UNIT_STAT_FLEEING_MOVE| UNIT_STAT_CHASE_MOVE | UNIT_STAT_FOLLOW_MOVE ,
|
||||
UNIT_STAT_CONTROLLED = (UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING),
|
||||
UNIT_STAT_LOST_CONTROL = (UNIT_STAT_CONTROLLED | UNIT_STAT_JUMPING | UNIT_STAT_CHARGING),
|
||||
UNIT_STAT_SIGHTLESS = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_EVADE),
|
||||
UNIT_STAT_CANNOT_AUTOATTACK = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CASTING),
|
||||
UNIT_STAT_CANNOT_TURN = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_ROTATING),
|
||||
// stay by different reasons
|
||||
UNIT_STAT_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_DISTRACTED,
|
||||
UNIT_STAT_ALL_STATE = 0xffffffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT)
|
||||
};
|
||||
|
||||
@@ -719,59 +727,18 @@ enum MovementFlags2
|
||||
MOVEMENTFLAG2_UNK15 = 0x00004000,
|
||||
MOVEMENTFLAG2_UNK16 = 0x00008000,
|
||||
};
|
||||
|
||||
enum SplineFlags
|
||||
{
|
||||
SPLINEFLAG_NONE = 0x00000000,
|
||||
SPLINEFLAG_FORWARD = 0x00000001,
|
||||
SPLINEFLAG_BACKWARD = 0x00000002,
|
||||
SPLINEFLAG_STRAFE_LEFT = 0x00000004,
|
||||
SPLINEFLAG_STRAFE_RIGHT = 0x00000008,
|
||||
SPLINEFLAG_LEFT = 0x00000010,
|
||||
SPLINEFLAG_RIGHT = 0x00000020,
|
||||
SPLINEFLAG_PITCH_UP = 0x00000040,
|
||||
SPLINEFLAG_PITCH_DOWN = 0x00000080,
|
||||
SPLINEFLAG_DONE = 0x00000100,
|
||||
SPLINEFLAG_FALLING = 0x00000200,
|
||||
SPLINEFLAG_NO_SPLINE = 0x00000400,
|
||||
SPLINEFLAG_TRAJECTORY = 0x00000800,
|
||||
SPLINEFLAG_WALKING = 0x00001000,
|
||||
SPLINEFLAG_FLYING = 0x00002000,
|
||||
SPLINEFLAG_KNOCKBACK = 0x00004000,
|
||||
SPLINEFLAG_FINAL_POINT = 0x00008000,
|
||||
SPLINEFLAG_FINAL_TARGET = 0x00010000,
|
||||
SPLINEFLAG_FINAL_FACING = 0x00020000,
|
||||
SPLINEFLAG_CATMULL_ROM = 0x00040000,
|
||||
SPLINEFLAG_UNKNOWN20 = 0x00080000,
|
||||
SPLINEFLAG_UNKNOWN21 = 0x00100000,
|
||||
SPLINEFLAG_ANIMATIONTIER = 0x00200000,
|
||||
SPLINEFLAG_UNKNOWN23 = 0x00400000,
|
||||
SPLINEFLAG_TRANSPORT = 0x00800000,
|
||||
SPLINEFLAG_EXIT_VEHICLE = 0x01000000,
|
||||
SPLINEFLAG_UNKNOWN26 = 0x02000000,
|
||||
SPLINEFLAG_UNKNOWN27 = 0x04000000,
|
||||
SPLINEFLAG_UNKNOWN28 = 0x08000000,
|
||||
SPLINEFLAG_UNKNOWN29 = 0x10000000,
|
||||
SPLINEFLAG_ANIMATION = 0x20000000,
|
||||
SPLINEFLAG_UNKNOWN31 = 0x40000000,
|
||||
SPLINEFLAG_UNKNOWN32 = 0x80000000,
|
||||
|
||||
SPLINEFLAG_GLIDE = SPLINEFLAG_WALKING | SPLINEFLAG_FLYING,
|
||||
};
|
||||
|
||||
enum SplineMode
|
||||
{
|
||||
SPLINEMODE_LINEAR = 0,
|
||||
SPLINEMODE_CATMULL_ROM = 1,
|
||||
SPLINEMODE_BEZIER3 = 2
|
||||
SPLINEFLAG_WALKMODE = 0x00001000,
|
||||
SPLINEFLAG_FLYING = 0x00002000,
|
||||
SPLINEFLAG_TRANSPORT = 0x00800000,
|
||||
SPLINEFLAG_EXIT_VEHICLE = 0x01000000,
|
||||
};
|
||||
|
||||
enum SplineType
|
||||
{
|
||||
SPLINETYPE_NORMAL = 0,
|
||||
SPLINETYPE_STOP = 1,
|
||||
SPLINETYPE_FACING_SPOT = 2,
|
||||
SPLINETYPE_FACING_TARGET = 3,
|
||||
SPLINETYPE_FACING_ANGLE = 4
|
||||
SPLINETYPE_FACING_ANGLE = 4,
|
||||
};
|
||||
|
||||
enum UnitTypeMask
|
||||
@@ -789,6 +756,10 @@ enum UnitTypeMask
|
||||
UNIT_MASK_ACCESSORY = 0x00000200,
|
||||
};
|
||||
|
||||
namespace Movement{
|
||||
class MoveSpline;
|
||||
}
|
||||
|
||||
enum DiminishingLevels
|
||||
{
|
||||
DIMINISHING_LEVEL_1 = 0,
|
||||
@@ -1628,20 +1599,18 @@ class Unit : public WorldObject
|
||||
void JumpTo(float speedXY, float speedZ, bool forward = true);
|
||||
void JumpTo(WorldObject* obj, float speedZ);
|
||||
|
||||
void SetFacing(float ori, WorldObject* obj = NULL);
|
||||
void SendMonsterStop(bool on_death = false);
|
||||
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player = NULL);
|
||||
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player* player = NULL);
|
||||
void SendMonsterMove(MonsterMoveData const& moveData, Player* receiver = NULL);
|
||||
void MonsterMoveWithSpeed(float x, float y, float z, float speed);
|
||||
//void SetFacing(float ori, WorldObject* obj = NULL);
|
||||
void SendMonsterMoveExitVehicle(Position const* newPos);
|
||||
//void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL);
|
||||
void SendMonsterMoveTransport(Unit* vehicleOwner);
|
||||
void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL);
|
||||
void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL);
|
||||
void SendMovementFlagUpdate();
|
||||
bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_LEVITATING);}
|
||||
bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);}
|
||||
|
||||
template<typename PathElem, typename PathNode>
|
||||
void SendMonsterMoveByPath(Path<PathElem, PathNode> const& path, uint32 start, uint32 end);
|
||||
void SetInFront(Unit const* target);
|
||||
void SetFacingTo(float ori);
|
||||
void SetFacingToObject(WorldObject* pObject);
|
||||
|
||||
void SendChangeCurrentVictimOpcode(HostileReference* pHostileReference);
|
||||
void SendClearThreatListOpcode();
|
||||
@@ -1951,13 +1920,7 @@ class Unit : public WorldObject
|
||||
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
|
||||
|
||||
bool isInFrontInMap(Unit const* target, float distance, float arc = M_PI) const;
|
||||
void SetInFront(Unit const* target)
|
||||
{
|
||||
if (!HasUnitState(UNIT_STAT_CANNOT_TURN))
|
||||
SetOrientation(GetAngle(target));
|
||||
}
|
||||
bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const;
|
||||
void SetFacingToObject(WorldObject* pObject);
|
||||
|
||||
// Visibility system
|
||||
bool IsVisible() const { return (m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GM) > SEC_PLAYER) ? false : true; }
|
||||
@@ -2232,6 +2195,9 @@ class Unit : public WorldObject
|
||||
SetUInt64Value(UNIT_FIELD_TARGET, 0);
|
||||
}
|
||||
|
||||
// Movement info
|
||||
Movement::MoveSpline * movespline;
|
||||
|
||||
protected:
|
||||
explicit Unit (bool isWorldObject);
|
||||
|
||||
@@ -2303,6 +2269,8 @@ class Unit : public WorldObject
|
||||
|
||||
bool IsAlwaysVisibleFor(WorldObject const* seer) const;
|
||||
bool IsAlwaysDetectableFor(WorldObject const* seer) const;
|
||||
|
||||
void DisableSpline();
|
||||
private:
|
||||
bool IsTriggeredAtSpellProcEvent(Unit* pVictim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent);
|
||||
bool HandleDummyAuraProc(Unit* pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
|
||||
@@ -2316,6 +2284,8 @@ class Unit : public WorldObject
|
||||
bool HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura);
|
||||
bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura);
|
||||
|
||||
void UpdateSplineMovement(uint32 t_diff);
|
||||
|
||||
// player or player's pet
|
||||
float GetCombatRatingReduction(CombatRating cr) const;
|
||||
uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const;
|
||||
@@ -2330,6 +2300,7 @@ class Unit : public WorldObject
|
||||
uint32 m_state; // Even derived shouldn't modify
|
||||
uint32 m_CombatTimer;
|
||||
uint32 m_lastManaUse; // msecs
|
||||
TimeTrackerSmall m_movesplineTimer;
|
||||
|
||||
Diminishing m_Diminishing;
|
||||
// Manage all Units that are threatened by us
|
||||
@@ -2382,31 +2353,4 @@ namespace Trinity
|
||||
const bool m_ascending;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Elem, typename Node>
|
||||
inline void Unit::SendMonsterMoveByPath(Path<Elem, Node> const& path, uint32 start, uint32 end)
|
||||
{
|
||||
uint32 traveltime = uint32(path.GetTotalLength(start, end) * 32);
|
||||
uint32 pathSize = end - start;
|
||||
WorldPacket data(SMSG_MONSTER_MOVE, (GetPackGUID().size()+1+4+4+4+4+1+4+4+4+pathSize*4*3));
|
||||
data.append(GetPackGUID());
|
||||
data << uint8(0);
|
||||
data << GetPositionX();
|
||||
data << GetPositionY();
|
||||
data << GetPositionZ();
|
||||
data << uint32(getMSTime());
|
||||
data << uint8(0);
|
||||
data << uint32(((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) || isInFlight()) ? (SPLINEFLAG_FLYING|SPLINEFLAG_WALKING) : SPLINEFLAG_WALKING);
|
||||
data << uint32(traveltime);
|
||||
data << uint32(pathSize);
|
||||
|
||||
for (uint32 i = start; i < end; ++i)
|
||||
{
|
||||
data << float(path[i].x);
|
||||
data << float(path[i].y);
|
||||
data << float(path[i].z);
|
||||
}
|
||||
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user