diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h index 413e296f7..6b6ca61de 100644 --- a/src/game/DBCEnums.h +++ b/src/game/DBCEnums.h @@ -589,7 +589,7 @@ enum VehicleSeatFlags SEAT_FLAG_UNK18 = 0x00100000, SEAT_FLAG_UNK19 = 0x00200000, SEAT_FLAG_UNK20 = 0x00400000, // "RecHasVehicleEnterAnim" - SEAT_FLAG_UNK21 = 0x00800000, + SEAT_FLAG_UNK21 = 0x00800000, // Lua_IsUsingVehicleControls SEAT_FLAG_UNK22 = 0x01000000, // "EnableVehicleZoom" SEAT_FLAG_USABLE = 0x02000000, // Lua_CanExitVehicle SEAT_FLAG_CAN_SWITCH = 0x04000000, // Lua_CanSwitchVehicleSeats diff --git a/src/game/Object.cpp b/src/game/Object.cpp index fc5d2c856..816b02091 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -462,7 +462,7 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const if (updateFlags & UPDATEFLAG_VEHICLE) { *data << float(NormalizeOrientation(((WorldObject*)this)->GetOrientation())); - *data << uint32(((Unit*)this)->GetVehicleInfo()->GetEntry()->m_ID); // vehicle id + *data << uint32(((Unit*)this)->GetVehicleInfo()->GetVehicleEntry()->m_ID); // vehicle id } // used only with GO's, placeholder diff --git a/src/game/TransportSystem.cpp b/src/game/TransportSystem.cpp index be1602c14..7bad99f7b 100644 --- a/src/game/TransportSystem.cpp +++ b/src/game/TransportSystem.cpp @@ -103,9 +103,9 @@ void TransportBase::UpdateGlobalPositionOf(WorldObject* passenger, float lx, flo else m_owner->GetMap()->CreatureRelocation((Creature*)passenger, gx, gy, gz, go); - //// If passenger is vehicle - //if (((Unit*)passenger)->IsVehicle()) - // ((Unit*)passenger)->GetVehicleInfo()->UpdateGlobalPositions(); + // If passenger is vehicle + if (((Unit*)passenger)->IsVehicle()) + ((Unit*)passenger)->GetVehicleInfo()->UpdateGlobalPositions(); } // ToDo: Add gameobject relocation // ToDo: Add passenger relocation for MO transports diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 9b5c841d6..70afc9b6f 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -623,6 +623,10 @@ void Unit::Update(uint32 update_diff, uint32 p_time) setAttackTimer(OFF_ATTACK, (update_diff >= base_att ? 0 : base_att - update_diff)); } + // Update passenger positions if we are the first vehicle + if (IsVehicle() && !IsBoarded()) + m_vehicleInfo->Update(update_diff); + // update abilities available only for fraction of time UpdateReactives(update_diff); @@ -11482,7 +11486,7 @@ void Unit::SetVehicleId(uint32 entry) VehicleEntry const* ventry = sVehicleStore.LookupEntry(entry); MANGOS_ASSERT(ventry != NULL); - m_vehicleInfo = new VehicleInfo(ventry); + m_vehicleInfo = new VehicleInfo(this, ventry); m_updateFlag |= UPDATEFLAG_VEHICLE; } else diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index 9d4b70efe..f1fddda1b 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -16,14 +16,216 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/** + * @addtogroup TransportSystem + * @{ + * + * @file Vehicle.cpp + * This file contains the code needed for CMaNGOS to support vehicles + * Currently implemented + * - TODO Board + * - TODO Unboard + * - TODO Switch + * - CanBoard to check if a passenger can board a vehicle + * - Internal helper to control the available seats of a vehicle + */ + #include "Common.h" +#include "SharedDefines.h" +#include "ObjectGuid.h" #include "Log.h" +#include "Unit.h" +#include "Creature.h" #include "ObjectMgr.h" #include "Vehicle.h" -#include "Unit.h" #include "Util.h" +#include "movement/MoveSplineInit.h" +#include "movement/MoveSpline.h" +#include "MapManager.h" -VehicleInfo::VehicleInfo(VehicleEntry const* entry) : - m_vehicleEntry(entry) +/** + * Constructor of VehicleInfo + * + * @param owner MUST be provided owner of the vehicle (type Unit) + * @param vehicleEntry MUST be provided dbc-entry of the vehicle + * + * This function will initialise the VehicleInfo of the vehicle owner + * Also the seat-map is created here + */ +VehicleInfo::VehicleInfo(Unit* owner, VehicleEntry const* vehicleEntry) : TransportBase(owner), + m_vehicleEntry(vehicleEntry), + m_creatureSeats(0), + m_playerSeats(0) +{ + MANGOS_ASSERT(vehicleEntry); + + // Initial fill of available seats for the vehicle + for (uint8 i = 0; i < MAX_VEHICLE_SEAT; ++i) + { + if (uint32 seatId = vehicleEntry->m_seatID[i]) + { + if (VehicleSeatEntry const* seatEntry = sVehicleSeatStore.LookupEntry(seatId)) + { + m_vehicleSeats.insert(VehicleSeatMap::value_type(i, seatEntry)); + + if (IsUsableSeatForCreature(seatEntry->m_flags)) + m_creatureSeats |= 1 << i; + + if (IsUsableSeatForPlayer(seatEntry->m_flags)) + m_playerSeats |= 1 << i; + } + } + } +} + +/** + * This function will board a passenger onto a vehicle + * + * @param passenger MUST be provided. This Unit will be boarded onto the vehicles (if it checks out) + * @param seat Seat to which the passenger will be boarded (if can, elsewise an alternative will be selected if possible) + */ +void VehicleInfo::Board(Unit* passenger, uint8 seat) +{ + MANGOS_ASSERT(passenger); + + DEBUG_LOG("VehicleInfo::Board: Try to board passenger %s to seat %u", passenger->GetObjectGuid().GetString().c_str(), seat); +} + +/** + * This function will switch the seat of a passenger + * + * @param passenger MUST be provided. This Unit will change its seat on the vehicle + * @param seat Seat to which the passenger will be switched + */ +void VehicleInfo::SwitchSeat(Unit* passenger, uint8 seat) +{ + MANGOS_ASSERT(passenger); +} + +/** + * This function will Unboard a passenger + * + * @param passenger MUST be provided. This Unit will be unboarded from the vehicle + * @param changeVehicle If set, the passenger is expected to be directly boarded to another vehicle, + * and hence he will not be unboarded but only removed from this vehicle. + */ +void VehicleInfo::UnBoard(Unit* passenger, bool changeVehicle) +{ + MANGOS_ASSERT(passenger); + + DEBUG_LOG("VehicleInfo::Unboard: passenger: %s", passenger->GetObjectGuid().GetString().c_str()); +} + +/** + * This function will check if a passenger can be boarded + * + * @param passenger Unit that attempts to board onto a vehicle + */ +bool VehicleInfo::CanBoard(Unit* passenger) const +{ + if (!passenger) + return false; + + // Passenger is this vehicle + if (passenger == m_owner) + return false; + + // Check if we have at least one empty seat + if (!GetEmptySeats()) + return false; + + // Passenger is already boarded + if (m_passengers.find(passenger) != m_passengers.end()) + return false; + + // Check for empty player seats + if (passenger->GetTypeId() == TYPEID_PLAYER) + return GetEmptySeatsMask() & m_playerSeats; + + // Check for empty creature seats + return GetEmptySeatsMask() & m_creatureSeats; +} + +// Helper function to undo the turning of the vehicle to calculate a relative position of the passenger when boarding +void VehicleInfo::CalculateBoardingPositionOf(float gx, float gy, float gz, float go, float &lx, float &ly, float &lz, float &lo) +{ + NormalizeRotatedPosition(gx - m_owner->GetPositionX(), gy - m_owner->GetPositionY(), lx, ly); + + lz = gz - m_owner->GetPositionZ(); + lo = MapManager::NormalizeOrientation(go - m_owner->GetOrientation()); +} + +/* ************************************************************************************************ + * Helper function for seat control + * ***********************************************************************************************/ + +/// Get the Vehicle SeatEntry of a seat by position +VehicleSeatEntry const* VehicleInfo::GetSeatEntry(uint8 seat) const +{ + VehicleSeatMap::const_iterator itr = m_vehicleSeats.find(seat); + return itr != m_vehicleSeats.end() ? itr->second : NULL; +} + +/** + * This function will get a usable seat for a passenger + * + * @param passenger MUST be provided. Unit for which to try to get a free seat + * @param seat will contain an available seat if returned true + * @return return TRUE if and only if an available seat was found. In this case @seat will contain the id + */ +bool VehicleInfo::GetUsableSeatFor(Unit* passenger, uint8& seat) const +{ + MANGOS_ASSERT(passenger); + + uint8 possibleSeats = (passenger->GetTypeId() == TYPEID_PLAYER) ? (GetEmptySeatsMask() & m_playerSeats) : (GetEmptySeatsMask() & m_creatureSeats); + + // No usable seats available + if (!possibleSeats) + return false; + + // Start with 0 + seat = 0; + + for (uint8 i = 1; seat < MAX_VEHICLE_SEAT; i <<= 1, ++seat) + if (possibleSeats & i) + return true; + + return false; +} + +/// Returns if a @passenger could board onto @seat - @passenger MUST be provided +bool VehicleInfo::IsSeatAvailableFor(Unit* passenger, uint8 seat) const +{ + MANGOS_ASSERT(passenger); + + return seat < MAX_VEHICLE_SEAT && + (GetEmptySeatsMask() & (passenger->GetTypeId() == TYPEID_PLAYER ? m_playerSeats : m_creatureSeats) & (1 << seat)); +} + +/// Wrapper to collect all taken seats +uint8 VehicleInfo::GetTakenSeatsMask() const +{ + uint8 takenSeatsMask = 0; + + for (PassengerMap::const_iterator itr = m_passengers.begin(); itr != m_passengers.end(); ++itr) + takenSeatsMask |= 1 << itr->second->GetTransportSeat(); + + return takenSeatsMask; +} + +bool VehicleInfo:: IsUsableSeatForPlayer(uint32 seatFlags) const +{ + return seatFlags & SEAT_FLAG_USABLE; +} + +/// Add control and such modifiers to a passenger if required +void VehicleInfo::ApplySeatMods(Unit* passenger, uint32 seatFlags) { } + +/// Remove control and such modifiers to a passenger if they were added +void VehicleInfo::RemoveSeatMods(Unit* passenger, uint32 seatFlags) +{ +} + +/*! @} */ diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h index 69bf22366..f78787a65 100644 --- a/src/game/Vehicle.h +++ b/src/game/Vehicle.h @@ -16,24 +16,80 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/** + * @addtogroup TransportSystem to provide abstract support for transported entities + * The Transport System in MaNGOS consists of these files: + * - TransportSystem.h to provide the basic classes TransportBase and TransportInfo + * - TransportSystem.cpp which implements these classes + * - Vehicle.h as a vehicle is a transporter it will inherit itr transporter-information from TransportBase + * - Transports.h to implement the MOTransporter (subclas of gameobject) - Remains TODO + * as well of + * - impacts to various files + * + * @{ + * + * @file Vehicle.h + * This file contains the headers for the functionality required by Vehicles + * + */ + #ifndef MANGOSSERVER_VEHICLE_H #define MANGOSSERVER_VEHICLE_H #include "Common.h" -#include "ObjectGuid.h" -#include "Creature.h" -#include "Unit.h" -#include "SharedDefines.h" +#include "TransportSystem.h" + +class Unit; struct VehicleEntry; +struct VehicleSeatEntry; -class VehicleInfo +typedef std::map VehicleSeatMap; + +/** + * A class to provide support for each vehicle. This includes + * - Boarding and unboarding of passengers, including support to switch vehicles + * - Basic checks if a passenger can board + */ +class VehicleInfo : public TransportBase { - VehicleEntry const* m_vehicleEntry; public: - explicit VehicleInfo(VehicleEntry const* entry); + explicit VehicleInfo(Unit* owner, VehicleEntry const* vehicleEntry); - VehicleEntry const* GetEntry() const { return m_vehicleEntry; } + VehicleEntry const* GetVehicleEntry() const { return m_vehicleEntry; } + + void Board(Unit* passenger, uint8 seat); // Board a passenger to a vehicle + void SwitchSeat(Unit* passenger, uint8 seat); // Used to switch seats of a passenger + void UnBoard(Unit* passenger, bool changeVehicle); // Used to Unboard a passenger from a vehicle + + bool CanBoard(Unit* passenger) const; // Used to check if a Unit can board a vehicle + + private: + // Internal use to calculate the boarding position + void CalculateBoardingPositionOf(float gx, float gy, float gz, float go, float &lx, float &ly, float &lz, float &lo); + + // Seat information + VehicleSeatEntry const* GetSeatEntry(uint8 seat) const; + bool GetUsableSeatFor(Unit* passenger, uint8& seat) const; + bool IsSeatAvailableFor(Unit* passenger, uint8 seat) const; + + uint8 GetTakenSeatsMask() const; + uint8 GetEmptySeatsMask() const { return ~GetTakenSeatsMask(); } + uint8 GetEmptySeats() const { return m_vehicleSeats.size() - m_passengers.size(); } + + bool IsUsableSeatForPlayer(uint32 seatFlags) const; + bool IsUsableSeatForCreature(uint32 seatFlags) const { return true; } // special flag?, !IsUsableSeatForPlayer(seatFlags)? + + // Apply/ Remove Controlling of the vehicle + void ApplySeatMods(Unit* passenger, uint32 seatFlags); + void RemoveSeatMods(Unit* passenger, uint32 seatFlags); + + VehicleEntry const* m_vehicleEntry; + VehicleSeatMap m_vehicleSeats; ///< Stores the available seats of the vehicle (filled in constructor) + uint8 m_creatureSeats; ///< Mask that stores which seats are avaiable for creatures + uint8 m_playerSeats; ///< Mask that stores which seats are avaiable for players }; #endif + +/*! @} */ diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index dfa3d242c..54683d947 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "12220" + #define REVISION_NR "12221" #endif // __REVISION_NR_H__