Various external fixes - part 3
- ported commits from cmangos repositories - also: + fix Movement::MoveSpline::ComputePosition to return only positive angles + improved algorithm for finding a random reachable point on ground
This commit is contained in:
parent
78c5faed9d
commit
c7a96ab067
@ -2267,3 +2267,23 @@ uint32 GameObject::GetScriptId()
|
|||||||
{
|
{
|
||||||
return sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) ? sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) : sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, GetEntry());
|
return sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) ? sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, -int32(GetGUIDLow())) : sScriptMgr.GetBoundScriptId(SCRIPTED_GAMEOBJECT, GetEntry());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GameObject::GetInteractionDistance() const
|
||||||
|
{
|
||||||
|
float maxdist = INTERACTION_DISTANCE;
|
||||||
|
switch (GetGoType())
|
||||||
|
{
|
||||||
|
// TODO: find out how the client calculates the maximal usage distance to spellless working
|
||||||
|
// gameobjects like mailboxes - 10.0 is a just an abitrary choosen number
|
||||||
|
case GAMEOBJECT_TYPE_MAILBOX:
|
||||||
|
maxdist = 10.0f;
|
||||||
|
break;
|
||||||
|
case GAMEOBJECT_TYPE_FISHINGHOLE:
|
||||||
|
case GAMEOBJECT_TYPE_FISHINGNODE:
|
||||||
|
maxdist = 20.0f + CONTACT_DISTANCE; // max spell range
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return maxdist;
|
||||||
|
}
|
||||||
|
@ -697,6 +697,8 @@ class GameObject : public WorldObject
|
|||||||
void SetCapturePointSlider(float value, bool isLocked);
|
void SetCapturePointSlider(float value, bool isLocked);
|
||||||
float GetCapturePointSliderValue() const { return m_captureSlider; }
|
float GetCapturePointSliderValue() const { return m_captureSlider; }
|
||||||
|
|
||||||
|
float GetInteractionDistance() const; // Get the maximum distance for a GO to interact with
|
||||||
|
|
||||||
uint32 GetScriptId();
|
uint32 GetScriptId();
|
||||||
|
|
||||||
GridReference<GameObject>& GetGridRef() { return m_gridRef; }
|
GridReference<GameObject>& GetGridRef() { return m_gridRef; }
|
||||||
|
@ -2072,22 +2072,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameo
|
|||||||
{
|
{
|
||||||
if (uint32(go->GetGoType()) == gameobject_type || gameobject_type == MAX_GAMEOBJECT_TYPE)
|
if (uint32(go->GetGoType()) == gameobject_type || gameobject_type == MAX_GAMEOBJECT_TYPE)
|
||||||
{
|
{
|
||||||
float maxdist;
|
float maxdist = go->GetInteractionDistance();
|
||||||
switch (go->GetGoType())
|
|
||||||
{
|
|
||||||
// TODO: find out how the client calculates the maximal usage distance to spellless working
|
|
||||||
// gameobjects like mailboxes - 10.0 is a just an abitrary choosen number
|
|
||||||
case GAMEOBJECT_TYPE_MAILBOX:
|
|
||||||
maxdist = 10.0f;
|
|
||||||
break;
|
|
||||||
case GAMEOBJECT_TYPE_FISHINGHOLE:
|
|
||||||
maxdist = 20.0f + CONTACT_DISTANCE; // max spell range
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
maxdist = INTERACTION_DISTANCE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (go->IsWithinDistInMap(this, maxdist) && go->isSpawned())
|
if (go->IsWithinDistInMap(this, maxdist) && go->isSpawned())
|
||||||
{ return go; }
|
{ return go; }
|
||||||
|
|
||||||
|
@ -2213,25 +2213,39 @@ bool Map::GetReachableRandomPointOnGround(float& x, float& y, float& z, float ra
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// here we have a valid position but the point can have a big Z in some case
|
// here we have a valid position but the point can have a big Z in some case
|
||||||
// next code will check angle from 2 points
|
// next code will check angle from 2 points of view: x-axis and y-axis movement
|
||||||
// c
|
// c
|
||||||
// /|
|
// /|
|
||||||
// / |
|
// / |
|
||||||
// b/__|a
|
// b/__|a
|
||||||
|
|
||||||
// project vector to get only positive value
|
// project vector to get only positive value
|
||||||
float ab = fabs(x - i_x);
|
|
||||||
float ac = fabs(z - i_z);
|
float ac = fabs(z - i_z);
|
||||||
|
float delta = 0;
|
||||||
|
|
||||||
// slope represented by c angle (in radian)
|
// slope represented by b angle (in radian)
|
||||||
float slope = 0;
|
float slope = 0;
|
||||||
const float MAX_SLOPE_IN_RADIAN = 50.0f / 180.0f * M_PI_F; // 50(degree) max seem best value for walkable slope
|
const float MAX_SLOPE_IN_RADIAN = 50.0f / 180.0f * M_PI_F; // 50(degree) max seem best value for walkable slope
|
||||||
|
|
||||||
// check ab vector to avoid divide by 0
|
delta = fabs(x - i_x); // check x-axis movement
|
||||||
if (ab > 0.0f)
|
if (delta > 0.0f) // check to avoid divide by 0
|
||||||
{
|
{
|
||||||
// compute c angle and convert it from radian to degree
|
// compute slope
|
||||||
slope = atan(ac / ab);
|
slope = atan(ac / delta);
|
||||||
|
if (slope < MAX_SLOPE_IN_RADIAN)
|
||||||
|
{
|
||||||
|
x = i_x;
|
||||||
|
y = i_y;
|
||||||
|
z = i_z;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delta = fabs(y - i_y); // check y-axis movement
|
||||||
|
if (delta > 0.0f) // check to avoid divide by 0
|
||||||
|
{
|
||||||
|
// compute slope
|
||||||
|
slope = atan(ac / delta);
|
||||||
if (slope < MAX_SLOPE_IN_RADIAN)
|
if (slope < MAX_SLOPE_IN_RADIAN)
|
||||||
{
|
{
|
||||||
x = i_x;
|
x = i_x;
|
||||||
|
@ -256,10 +256,13 @@ void WorldSession::HandleGameObjectUseOpcode(WorldPacket& recv_data)
|
|||||||
if (!_player->IsSelfMover())
|
if (!_player->IsSelfMover())
|
||||||
{ return; }
|
{ return; }
|
||||||
|
|
||||||
GameObject* obj = GetPlayer()->GetMap()->GetGameObject(guid);
|
GameObject* obj = _player->GetMap()->GetGameObject(guid);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
{ return; }
|
{ return; }
|
||||||
|
|
||||||
|
if (!obj->IsWithinDistInMap(_player, obj->GetInteractionDistance()))
|
||||||
|
{ return; }
|
||||||
|
|
||||||
// Additional check preventing exploits (ie loot despawned chests)
|
// Additional check preventing exploits (ie loot despawned chests)
|
||||||
if (!obj->isSpawned())
|
if (!obj->isSpawned())
|
||||||
{
|
{
|
||||||
|
@ -47,14 +47,14 @@ void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket& recv_data)
|
|||||||
void WorldSession::SendTaxiStatus(ObjectGuid guid)
|
void WorldSession::SendTaxiStatus(ObjectGuid guid)
|
||||||
{
|
{
|
||||||
// cheating checks
|
// cheating checks
|
||||||
Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
|
Creature* unit = _player->GetMap()->GetCreature(guid);
|
||||||
if (!unit)
|
if (!unit)
|
||||||
{
|
{
|
||||||
DEBUG_LOG("WorldSession::SendTaxiStatus - %s not found or you can't interact with it.", guid.GetString().c_str());
|
DEBUG_LOG("WorldSession::SendTaxiStatus - %s not found or you can't interact with it.", guid.GetString().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 curloc = sObjectMgr.GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
|
uint32 curloc = sObjectMgr.GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), _player->GetTeam());
|
||||||
|
|
||||||
// not found nearest
|
// not found nearest
|
||||||
if (curloc == 0)
|
if (curloc == 0)
|
||||||
@ -64,7 +64,7 @@ void WorldSession::SendTaxiStatus(ObjectGuid guid)
|
|||||||
|
|
||||||
WorldPacket data(SMSG_TAXINODE_STATUS, 9);
|
WorldPacket data(SMSG_TAXINODE_STATUS, 9);
|
||||||
data << ObjectGuid(guid);
|
data << ObjectGuid(guid);
|
||||||
data << uint8(GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0);
|
data << uint8(_player->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0);
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
|
|
||||||
DEBUG_LOG("WORLD: Sent SMSG_TAXINODE_STATUS");
|
DEBUG_LOG("WORLD: Sent SMSG_TAXINODE_STATUS");
|
||||||
@ -78,7 +78,7 @@ void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket& recv_data)
|
|||||||
recv_data >> guid;
|
recv_data >> guid;
|
||||||
|
|
||||||
// cheating checks
|
// cheating checks
|
||||||
Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
|
Creature* unit = _player->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
|
||||||
if (!unit)
|
if (!unit)
|
||||||
{
|
{
|
||||||
DEBUG_LOG("WORLD: HandleTaxiQueryAvailableNodes - %s not found or you can't interact with him.", guid.GetString().c_str());
|
DEBUG_LOG("WORLD: HandleTaxiQueryAvailableNodes - %s not found or you can't interact with him.", guid.GetString().c_str());
|
||||||
@ -86,8 +86,8 @@ void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket& recv_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove fake death
|
// remove fake death
|
||||||
if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
|
if (_player->hasUnitState(UNIT_STAT_DIED))
|
||||||
{ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); }
|
{ _player->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); }
|
||||||
|
|
||||||
// unknown taxi node case
|
// unknown taxi node case
|
||||||
if (SendLearnNewTaxiNode(unit))
|
if (SendLearnNewTaxiNode(unit))
|
||||||
@ -100,7 +100,7 @@ void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket& recv_data)
|
|||||||
void WorldSession::SendTaxiMenu(Creature* unit)
|
void WorldSession::SendTaxiMenu(Creature* unit)
|
||||||
{
|
{
|
||||||
// find current node
|
// find current node
|
||||||
uint32 curloc = sObjectMgr.GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
|
uint32 curloc = sObjectMgr.GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), _player->GetTeam());
|
||||||
|
|
||||||
if (curloc == 0)
|
if (curloc == 0)
|
||||||
{ return; }
|
{ return; }
|
||||||
@ -111,7 +111,7 @@ void WorldSession::SendTaxiMenu(Creature* unit)
|
|||||||
data << uint32(1);
|
data << uint32(1);
|
||||||
data << unit->GetObjectGuid();
|
data << unit->GetObjectGuid();
|
||||||
data << uint32(curloc);
|
data << uint32(curloc);
|
||||||
GetPlayer()->m_taxi.AppendTaximaskTo(data, GetPlayer()->IsTaxiCheater());
|
_player->m_taxi.AppendTaximaskTo(data, _player->IsTaxiCheater());
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
|
|
||||||
DEBUG_LOG("WORLD: Sent SMSG_SHOWTAXINODES");
|
DEBUG_LOG("WORLD: Sent SMSG_SHOWTAXINODES");
|
||||||
@ -120,27 +120,27 @@ void WorldSession::SendTaxiMenu(Creature* unit)
|
|||||||
void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode)
|
void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode)
|
||||||
{
|
{
|
||||||
// remove fake death
|
// remove fake death
|
||||||
if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
|
if (_player->hasUnitState(UNIT_STAT_DIED))
|
||||||
{ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); }
|
{ _player->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); }
|
||||||
|
|
||||||
while (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
|
while (_player->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
|
||||||
{ GetPlayer()->GetMotionMaster()->MovementExpired(false); }
|
{ _player->GetMotionMaster()->MovementExpired(false); }
|
||||||
|
|
||||||
if (mountDisplayId)
|
if (mountDisplayId)
|
||||||
{ GetPlayer()->Mount(mountDisplayId); }
|
{ _player->Mount(mountDisplayId); }
|
||||||
|
|
||||||
GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path, pathNode);
|
_player->GetMotionMaster()->MoveTaxiFlight(path, pathNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldSession::SendLearnNewTaxiNode(Creature* unit)
|
bool WorldSession::SendLearnNewTaxiNode(Creature* unit)
|
||||||
{
|
{
|
||||||
// find current node
|
// find current node
|
||||||
uint32 curloc = sObjectMgr.GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
|
uint32 curloc = sObjectMgr.GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), _player->GetTeam());
|
||||||
|
|
||||||
if (curloc == 0)
|
if (curloc == 0)
|
||||||
{ return true; } // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result.
|
{ return true; } // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result.
|
||||||
|
|
||||||
if (GetPlayer()->m_taxi.SetTaximaskNode(curloc))
|
if (_player->m_taxi.SetTaximaskNode(curloc))
|
||||||
{
|
{
|
||||||
WorldPacket msg(SMSG_NEW_TAXI_PATH, 0);
|
WorldPacket msg(SMSG_NEW_TAXI_PATH, 0);
|
||||||
SendPacket(&msg);
|
SendPacket(&msg);
|
||||||
@ -174,7 +174,7 @@ void WorldSession::HandleActivateTaxiExpressOpcode(WorldPacket& recv_data)
|
|||||||
|
|
||||||
recv_data >> guid >> _totalcost >> node_count;
|
recv_data >> guid >> _totalcost >> node_count;
|
||||||
|
|
||||||
Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
|
Creature* npc = _player->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
|
||||||
if (!npc)
|
if (!npc)
|
||||||
{
|
{
|
||||||
DEBUG_LOG("WORLD: HandleActivateTaxiExpressOpcode - %s not found or you can't interact with it.", guid.GetString().c_str());
|
DEBUG_LOG("WORLD: HandleActivateTaxiExpressOpcode - %s not found or you can't interact with it.", guid.GetString().c_str());
|
||||||
@ -186,6 +186,13 @@ void WorldSession::HandleActivateTaxiExpressOpcode(WorldPacket& recv_data)
|
|||||||
{
|
{
|
||||||
uint32 node;
|
uint32 node;
|
||||||
recv_data >> node;
|
recv_data >> node;
|
||||||
|
|
||||||
|
if (!_player->m_taxi.IsTaximaskNodeKnown(node) && !_player->IsTaxiCheater())
|
||||||
|
{
|
||||||
|
SendActivateTaxiReply(ERR_TAXINOTVISITED);
|
||||||
|
recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
|
||||||
|
return;
|
||||||
|
}
|
||||||
nodes.push_back(node);
|
nodes.push_back(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +201,7 @@ void WorldSession::HandleActivateTaxiExpressOpcode(WorldPacket& recv_data)
|
|||||||
|
|
||||||
DEBUG_LOG("WORLD: Received opcode CMSG_ACTIVATETAXIEXPRESS from %d to %d" , nodes.front(), nodes.back());
|
DEBUG_LOG("WORLD: Received opcode CMSG_ACTIVATETAXIEXPRESS from %d to %d" , nodes.front(), nodes.back());
|
||||||
|
|
||||||
GetPlayer()->ActivateTaxiPathTo(nodes, npc);
|
_player->ActivateTaxiPathTo(nodes, npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data)
|
void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data)
|
||||||
@ -212,41 +219,41 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data)
|
|||||||
// 1) end taxi path in far (multi-node) flight
|
// 1) end taxi path in far (multi-node) flight
|
||||||
// 2) switch from one map to other in case multi-map taxi path
|
// 2) switch from one map to other in case multi-map taxi path
|
||||||
// we need process only (1)
|
// we need process only (1)
|
||||||
uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination();
|
uint32 curDest = _player->m_taxi.GetTaxiDestination();
|
||||||
if (!curDest)
|
if (!curDest)
|
||||||
{ return; }
|
{ return; }
|
||||||
|
|
||||||
TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
|
TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
|
||||||
|
|
||||||
// far teleport case
|
// far teleport case
|
||||||
if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId())
|
if (curDestNode && curDestNode->map_id != _player->GetMapId())
|
||||||
{
|
{
|
||||||
if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
|
if (_player->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
|
||||||
{
|
{
|
||||||
// short preparations to continue flight
|
// short preparations to continue flight
|
||||||
FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
|
FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(_player->GetMotionMaster()->top());
|
||||||
|
|
||||||
flight->Interrupt(*GetPlayer()); // will reset at map landing
|
flight->Interrupt(*_player); // will reset at map landing
|
||||||
|
|
||||||
flight->SetCurrentNodeAfterTeleport();
|
flight->SetCurrentNodeAfterTeleport();
|
||||||
TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()];
|
TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()];
|
||||||
flight->SkipCurrentNode();
|
flight->SkipCurrentNode();
|
||||||
|
|
||||||
GetPlayer()->TeleportTo(curDestNode->map_id, node.x, node.y, node.z, GetPlayer()->GetOrientation());
|
_player->TeleportTo(curDestNode->map_id, node.x, node.y, node.z, _player->GetOrientation());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination();
|
uint32 destinationnode = _player->m_taxi.NextTaxiDestination();
|
||||||
if (destinationnode > 0) // if more destinations to go
|
if (destinationnode > 0) // if more destinations to go
|
||||||
{
|
{
|
||||||
// current source node for next destination
|
// current source node for next destination
|
||||||
uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource();
|
uint32 sourcenode = _player->m_taxi.GetTaxiSource();
|
||||||
|
|
||||||
// Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path)
|
// Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path)
|
||||||
if (GetPlayer()->IsTaxiCheater())
|
if (_player->IsTaxiCheater())
|
||||||
{
|
{
|
||||||
if (GetPlayer()->m_taxi.SetTaximaskNode(sourcenode))
|
if (_player->m_taxi.SetTaximaskNode(sourcenode))
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_NEW_TAXI_PATH, 0);
|
WorldPacket data(SMSG_NEW_TAXI_PATH, 0);
|
||||||
_player->GetSession()->SendPacket(&data);
|
_player->GetSession()->SendPacket(&data);
|
||||||
@ -255,7 +262,7 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data)
|
|||||||
|
|
||||||
DEBUG_LOG("WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode);
|
DEBUG_LOG("WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode);
|
||||||
|
|
||||||
uint32 mountDisplayId = sObjectMgr.GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam());
|
uint32 mountDisplayId = sObjectMgr.GetTaxiMountDisplayId(sourcenode, _player->GetTeam());
|
||||||
|
|
||||||
uint32 path, cost;
|
uint32 path, cost;
|
||||||
sObjectMgr.GetTaxiPath(sourcenode, destinationnode, path, cost);
|
sObjectMgr.GetTaxiPath(sourcenode, destinationnode, path, cost);
|
||||||
@ -263,10 +270,10 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data)
|
|||||||
if (path && mountDisplayId)
|
if (path && mountDisplayId)
|
||||||
{ SendDoFlight(mountDisplayId, path, 1); } // skip start fly node
|
{ SendDoFlight(mountDisplayId, path, 1); } // skip start fly node
|
||||||
else
|
else
|
||||||
{ GetPlayer()->m_taxi.ClearTaxiDestinations(); } // clear problematic path and next
|
{ _player->m_taxi.ClearTaxiDestinations(); } // clear problematic path and next
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ GetPlayer()->m_taxi.ClearTaxiDestinations(); } // not destinations, clear source node
|
{ _player->m_taxi.ClearTaxiDestinations(); } // not destinations, clear source node
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recv_data)
|
void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recv_data)
|
||||||
@ -279,12 +286,19 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recv_data)
|
|||||||
|
|
||||||
recv_data >> guid >> nodes[0] >> nodes[1];
|
recv_data >> guid >> nodes[0] >> nodes[1];
|
||||||
DEBUG_LOG("WORLD: Received opcode CMSG_ACTIVATETAXI from %d to %d" , nodes[0], nodes[1]);
|
DEBUG_LOG("WORLD: Received opcode CMSG_ACTIVATETAXI from %d to %d" , nodes[0], nodes[1]);
|
||||||
Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
|
Creature* npc = _player->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
|
||||||
if (!npc)
|
if (!npc)
|
||||||
{
|
{
|
||||||
DEBUG_LOG("WORLD: HandleActivateTaxiOpcode - %s not found or you can't interact with it.", guid.GetString().c_str());
|
DEBUG_LOG("WORLD: HandleActivateTaxiOpcode - %s not found or you can't interact with it.", guid.GetString().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!_player->IsTaxiCheater())
|
||||||
GetPlayer()->ActivateTaxiPathTo(nodes, npc);
|
{
|
||||||
|
if (!_player->m_taxi.IsTaximaskNodeKnown(nodes[0]) || !_player->m_taxi.IsTaximaskNodeKnown(nodes[1]))
|
||||||
|
{
|
||||||
|
SendActivateTaxiReply(ERR_TAXINOTVISITED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_player->ActivateTaxiPathTo(nodes, npc);
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ namespace Movement
|
|||||||
spline.evaluate_derivative(point_Idx, u, hermite);
|
spline.evaluate_derivative(point_Idx, u, hermite);
|
||||||
c.orientation = atan2(hermite.y, hermite.x);
|
c.orientation = atan2(hermite.y, hermite.x);
|
||||||
}
|
}
|
||||||
|
c.orientation = G3D::wrap(c.orientation, 0.f, (float)G3D::twoPi());
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,33 +79,19 @@ namespace Movement
|
|||||||
|
|
||||||
void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data)
|
void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data)
|
||||||
{
|
{
|
||||||
uint32 pointCount = spline.getPointCount() - 3;
|
Movement::SplineBase::ControlArray const& pathPoint = spline.getPoints(); // get ref of whole path points array
|
||||||
uint32 last_idx = pointCount;
|
|
||||||
const Vector3* real_path = &spline.getPoint(1);
|
|
||||||
Vector3 destination = real_path[last_idx];
|
|
||||||
|
|
||||||
size_t lastIndexPos = data.wpos();
|
uint32 pathSize = spline.last() - spline.first() - 1; // -1 as we send destination first and last index is destination
|
||||||
data << last_idx;
|
MANGOS_ASSERT(pathSize >= 0); // should never be less than 0
|
||||||
|
|
||||||
|
Vector3 destination = pathPoint[spline.last()]; // destination of this path should be send right after path size
|
||||||
|
data << pathSize;
|
||||||
data << destination;
|
data << destination;
|
||||||
if (last_idx > 1)
|
|
||||||
|
for (uint32 i = spline.first(); i < spline.first() + pathSize; i++) // from first real index (this array contain also special data)
|
||||||
{
|
{
|
||||||
Vector3 offset;
|
Vector3 offset = destination - pathPoint[i]; // we have to send offset relative to destination instead of directly path point.
|
||||||
// first and last points already appended
|
data.appendPackXYZ(offset.x, offset.y, offset.z); // we have to pack x,y,z before send
|
||||||
for (uint32 i = 1; i < pointCount; ++i)
|
|
||||||
{
|
|
||||||
offset = destination - real_path[i];
|
|
||||||
// TODO: check if there is a better way to handle this like reworking path formatting to avoid generating such zero offset
|
|
||||||
// [-CLASSIC] The client freezes or crashes when it gets a zero offset.
|
|
||||||
// If the offset would be rounded to zero, skip it.
|
|
||||||
if (fabs(offset.x) < 0.25 && fabs(offset.y) < 0.25 && fabs(offset.z) < 0.25)
|
|
||||||
{
|
|
||||||
// Remove 1 from the counter that will be sent to the client.
|
|
||||||
last_idx--;
|
|
||||||
data.put(lastIndexPos, last_idx);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
data.appendPackXYZ(offset.x, offset.y, offset.z);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,17 +137,17 @@ namespace Movement
|
|||||||
|
|
||||||
data << splineFlags.raw();
|
data << splineFlags.raw();
|
||||||
|
|
||||||
if (splineFlags.final_angle)
|
if (splineFlags.final_point)
|
||||||
{
|
{
|
||||||
data << move_spline.facing.angle;
|
data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
|
||||||
}
|
}
|
||||||
else if (splineFlags.final_target)
|
else if (splineFlags.final_target)
|
||||||
{
|
{
|
||||||
data << move_spline.facing.target;
|
data << move_spline.facing.target;
|
||||||
}
|
}
|
||||||
else if (splineFlags.final_point)
|
else if (splineFlags.final_angle)
|
||||||
{
|
{
|
||||||
data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
|
data << move_spline.facing.angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
data << move_spline.timePassed();
|
data << move_spline.timePassed();
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 8f492dbbd39ddd79af2ce254f7dbf76b8564bf7a
|
Subproject commit cde7ea4a007a37347256cbbcb4f989145a7bb6d6
|
Loading…
x
Reference in New Issue
Block a user