mirror of
https://github.com/mangosfour/server.git
synced 2025-12-28 04:37:04 +00:00
208 lines
7.1 KiB
C++
208 lines
7.1 KiB
C++
/*
|
|
* This code is part of MaNGOS. Contributor & Copyright details are in AUTHORS/THANKS.
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
/*
|
|
* @addtogroup TransportSystem
|
|
* @{
|
|
*
|
|
* @file TransportSystem.cpp
|
|
* This file contains the code needed for MaNGOS to provide abstract support for transported entities
|
|
* Currently implemented
|
|
* - Calculating between local and global coords
|
|
* - Abstract storage of passengers (added by BoardPassenger, UnboardPassenger)
|
|
*/
|
|
|
|
#include "TransportSystem.h"
|
|
#include "Unit.h"
|
|
#include "Vehicle.h"
|
|
#include "MapManager.h"
|
|
|
|
/* **************************************** TransportBase ****************************************/
|
|
|
|
TransportBase::TransportBase(WorldObject* owner) :
|
|
m_owner(owner),
|
|
m_lastPosition(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation()),
|
|
m_sinO(sin(m_lastPosition.o)),
|
|
m_cosO(cos(m_lastPosition.o)),
|
|
m_updatePositionsTimer(500)
|
|
{
|
|
MANGOS_ASSERT(m_owner);
|
|
}
|
|
|
|
TransportBase::~TransportBase()
|
|
{
|
|
MANGOS_ASSERT(m_passengers.size() == 0);
|
|
}
|
|
|
|
// Update every now and then (after some change of transporter's position)
|
|
// This is used to calculate global positions (which don't have to be exact, they are only required for some server-side calculations
|
|
void TransportBase::Update(uint32 diff)
|
|
{
|
|
if (m_updatePositionsTimer < diff)
|
|
{
|
|
if (fabs(m_owner->GetPositionX() - m_lastPosition.x) +
|
|
fabs(m_owner->GetPositionY() - m_lastPosition.y) +
|
|
fabs(m_owner->GetPositionZ() - m_lastPosition.z) > 1.0f ||
|
|
NormalizeOrientation(m_owner->GetOrientation() - m_lastPosition.o) > 0.01f)
|
|
UpdateGlobalPositions();
|
|
|
|
m_updatePositionsTimer = 500;
|
|
}
|
|
else
|
|
m_updatePositionsTimer -= diff;
|
|
}
|
|
|
|
// Update the global positions of all passengers
|
|
void TransportBase::UpdateGlobalPositions()
|
|
{
|
|
Position pos(m_owner->GetPositionX(), m_owner->GetPositionY(),
|
|
m_owner->GetPositionZ(), m_owner->GetOrientation());
|
|
|
|
// Calculate new direction multipliers
|
|
if (NormalizeOrientation(pos.o - m_lastPosition.o) > 0.01f)
|
|
{
|
|
m_sinO = sin(pos.o);
|
|
m_cosO = cos(pos.o);
|
|
}
|
|
|
|
// Update global positions
|
|
for (PassengerMap::const_iterator itr = m_passengers.begin(); itr != m_passengers.end(); ++itr)
|
|
UpdateGlobalPositionOf(itr->first, itr->second->GetLocalPositionX(), itr->second->GetLocalPositionY(),
|
|
itr->second->GetLocalPositionZ(), itr->second->GetLocalOrientation());
|
|
|
|
m_lastPosition = pos;
|
|
}
|
|
|
|
// Update the global position of a passenger
|
|
void TransportBase::UpdateGlobalPositionOf(WorldObject* passenger, float lx, float ly, float lz, float lo) const
|
|
{
|
|
float gx, gy, gz, go;
|
|
CalculateGlobalPositionOf(lx, ly, lz, lo, gx, gy, gz, go);
|
|
|
|
if (passenger->GetTypeId() == TYPEID_PLAYER || passenger->GetTypeId() == TYPEID_UNIT)
|
|
{
|
|
if (passenger->GetTypeId() == TYPEID_PLAYER)
|
|
{
|
|
m_owner->GetMap()->PlayerRelocation((Player*)passenger, gx, gy, gz, go);
|
|
}
|
|
else
|
|
m_owner->GetMap()->CreatureRelocation((Creature*)passenger, gx, gy, gz, go);
|
|
|
|
// If passenger is vehicle
|
|
if (((Unit*)passenger)->IsVehicle())
|
|
((Unit*)passenger)->GetVehicleInfo()->UpdateGlobalPositions();
|
|
}
|
|
// ToDo: Add gameobject relocation
|
|
// ToDo: Add passenger relocation for MO transports
|
|
}
|
|
|
|
// This rotates the vector (lx, ly) by transporter->orientation
|
|
void TransportBase::RotateLocalPosition(float lx, float ly, float& rx, float& ry) const
|
|
{
|
|
rx = lx * m_cosO - ly * m_sinO;
|
|
ry = lx * m_sinO + ly * m_cosO;
|
|
}
|
|
|
|
// This rotates the vector (rx, ry) by -transporter->orientation
|
|
void TransportBase::NormalizeRotatedPosition(float rx, float ry, float& lx, float& ly) const
|
|
{
|
|
lx = rx * -m_cosO - ry * -m_sinO;
|
|
ly = rx * -m_sinO + ry * -m_cosO;
|
|
}
|
|
|
|
// Calculate a global position of local positions based on this transporter
|
|
void TransportBase::CalculateGlobalPositionOf(float lx, float ly, float lz, float lo, float& gx, float& gy, float& gz, float& go) const
|
|
{
|
|
RotateLocalPosition(lx, ly, gx, gy);
|
|
gx += m_owner->GetPositionX();
|
|
gy += m_owner->GetPositionY();
|
|
|
|
gz = lz + m_owner->GetPositionZ();
|
|
go = NormalizeOrientation(lo + m_owner->GetOrientation());
|
|
}
|
|
|
|
// Helper function to check if a unit is boarded onto this transporter (or a transporter boarded onto this) recursively
|
|
bool TransportBase::HasOnBoard(WorldObject const* passenger) const
|
|
{
|
|
MANGOS_ASSERT(passenger);
|
|
|
|
// For efficiency we go down from the (possible) passenger until we reached our owner, or until we reached no passenger
|
|
// Note, this will not catch, if self and passenger are boarded onto the same transporter (as it should not)
|
|
while (passenger->IsBoarded())
|
|
{
|
|
// pasenger is boarded onto this
|
|
if (passenger->GetTransportInfo()->GetTransport() == m_owner)
|
|
return true;
|
|
else
|
|
passenger = passenger->GetTransportInfo()->GetTransport();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void TransportBase::BoardPassenger(WorldObject* passenger, float lx, float ly, float lz, float lo, uint8 seat)
|
|
{
|
|
TransportInfo* transportInfo = new TransportInfo(passenger, this, lx, ly, lz, lo, seat);
|
|
|
|
// Insert our new passenger
|
|
m_passengers.insert(PassengerMap::value_type(passenger, transportInfo));
|
|
|
|
// The passenger needs fast access to transportInfo
|
|
passenger->SetTransportInfo(transportInfo);
|
|
}
|
|
|
|
void TransportBase::UnBoardPassenger(WorldObject* passenger)
|
|
{
|
|
PassengerMap::iterator itr = m_passengers.find(passenger);
|
|
|
|
if (itr == m_passengers.end())
|
|
return;
|
|
|
|
// Set passengers transportInfo to NULL
|
|
passenger->SetTransportInfo(NULL);
|
|
|
|
// Delete transportInfo
|
|
delete itr->second;
|
|
|
|
// Unboard finally
|
|
m_passengers.erase(itr);
|
|
}
|
|
|
|
/* **************************************** TransportInfo ****************************************/
|
|
|
|
TransportInfo::TransportInfo(WorldObject* owner, TransportBase* transport, float lx, float ly, float lz, float lo, uint8 seat) :
|
|
m_owner(owner),
|
|
m_transport(transport),
|
|
m_localPosition(lx, ly, lz, lo),
|
|
m_seat(seat)
|
|
{
|
|
MANGOS_ASSERT(owner && m_transport);
|
|
}
|
|
|
|
void TransportInfo::SetLocalPosition(float lx, float ly, float lz, float lo)
|
|
{
|
|
m_localPosition.x = lx;
|
|
m_localPosition.y = ly;
|
|
m_localPosition.z = lz;
|
|
m_localPosition.o = lo;
|
|
|
|
// Update global position
|
|
m_transport->UpdateGlobalPositionOf(m_owner, lx, ly, lz, lo);
|
|
}
|
|
|
|
/*! @} */
|