diff --git a/data/sql/updates/pending_db_world/rev_1725993194571320983.sql b/data/sql/updates/pending_db_world/rev_1725993194571320983.sql new file mode 100644 index 000000000..43df1ef85 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1725993194571320983.sql @@ -0,0 +1,47 @@ +-- +DROP TABLE IF EXISTS `vehicle_seat_addon`; +CREATE TABLE `vehicle_seat_addon` ( + `SeatEntry` INT(4) UNSIGNED NOT NULL COMMENT 'VehicleSeatEntry.dbc identifier', + `SeatOrientation` FLOAT(6) DEFAULT 0 COMMENT 'Seat Orientation override value', + `ExitParamX` FLOAT(10) DEFAULT 0, + `ExitParamY` FLOAT(10) DEFAULT 0, + `ExitParamZ` FLOAT(10) DEFAULT 0, + `ExitParamO` FLOAT(10) DEFAULT 0, + `ExitParamValue` TINYINT(1) DEFAULT 0, + PRIMARY KEY (`SeatEntry`) +); + +DELETE FROM `vehicle_seat_addon` WHERE `SeatEntry` IN (2726, 2727, 2728, 2729, 2730, 1472, 1473, 1474, 1475, 1476, 2764, 2765, 2767, 2768, 6446, 6447, 7326, 7327, 7328, 7329, 861, 862, 1682, 2097, 2172, 2178, 2179, 2180, 3690, 3691, 3692, 3129, 2772, 2771); +INSERT INTO `vehicle_seat_addon` (`SeatEntry`, `SeatOrientation`, `ExitParamX`, `ExitParamY`, `ExitParamZ`, `ExitParamO`, `ExitParamValue`) VALUES +(2764, 0.0, -2.0, 2.0, 0.0, 0.0, 1), -- 312 Traveler's Tundra Mammoth +(2765, 0.0, -2.0, -2.0, 0.0, 0.0, 1), -- 312 +(2767, 0.0, -2.0, 2.0, 0.0, 0.0, 1), -- 313 Traveler's Tundra Mammoth +(2768, 0.0, -2.0, -2.0, 0.0, 0.0, 1),-- 313 +(6446, 0.0, -1.0, 4.0, 3.0, 0.0, 1), -- 548 Stormwind Love Boat +(6447, 0.0, 1.0, 4.0, 3.0, 0.0, 1), -- 548 +(7326, 0.0, -1.0, 4.0, 3.0, 0.0, 1), -- 615 Darnassus Love Boat +(7327, 0.0, 1.0, 4.0, 3.0, 0.0, 1), -- 615 +(7328, 0.0, -1.0, 4.0, 3.0, 0.0, 1), -- 616 Undercity Love Boat +(7329, 0.0, 1.0, 4.0, 3.0, 0.0, 1), -- 616 +(861, 0.0, -2.0, 2.0, 0.0, 0.0, 1), -- 51 Ducal's Horse +(862, 0.0, -2.0, 3.0, 0.0, 0.0, 1), -- 51 +-- cmangos exclusive +(1682, 0.0, 6708.17, 5130.74, -19.388, 4.83608, 2), -- 118 Zeptek the Destroyer +(2097, 0.0, 12.0, 0.0, 4.0, 0.0, 1), -- 191 Gal'darah +(2172, 0.0, 40.0, 0.0, 0.0, 0.0, 1), -- 205 Gymer +(2178, 0.0, -3.3, 5.0, 0.0, 3.1326, 1), -- 209 Drakkari Rhino +(2179, 0.0, -5.9, -4.9, 0.0, 3.1326, 1), -- 209 +(2180, 0.0, -7.9, 0.02, 0.0, 3.1326, 1), -- 209 +-- acore exclusive +(3690, 0.0, 1776.0, -24.0, 448.75, 0.0, 2), -- 380 Kologarn right arm +(3691, 0.0, 1776.0, -24.0, 448.75, 0.0, 2), -- 380 +(3692, 0.0, 1776.0, -24.0, 448.75, 0.0, 2), -- 380 +(3129, 0.0, 0.0, -2.0, 0.0, 0.0, 1), -- 349 AT Mounts, dismount to the right +(2772, 0.0, -2.0, 2.0, 0.0, 0.0, 1), -- 315 Grand Ice Mammoth, Grand Black War Mammoth +(2771, 0.0, -2.0, -2.0, 0.0, 0.0, 1), -- 315 +-- Helmsman's coords are different on acore +(1472, 0.0, 2802.18, 7054.91, -0.6, 4.67, 2), -- 91 The Helmsman's Ship +(1473, 0.0, 2802.18, 7054.91, -0.6, 4.67, 2), -- 91 +(1474, 0.0, 2802.18, 7054.91, -0.6, 4.67, 2), -- 91 +(1475, 0.0, 2802.18, 7054.91, -0.6, 4.67, 2), -- 91 +(1476, 0.0, 2802.18, 7054.91, -0.6, 4.67, 2); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index edb198478..c1c23efb9 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -19756,6 +19756,8 @@ void Unit::_ExitVehicle(Position const* exitPosition) if (!m_vehicle) return; + // This should be done before dismiss, because there may be some aura removal + VehicleSeatAddon const* seatAddon = m_vehicle->GetSeatAddonForSeatOfPassenger(this); m_vehicle->RemovePassenger(this); Player* player = ToPlayer(); @@ -19764,7 +19766,6 @@ void Unit::_ExitVehicle(Position const* exitPosition) if (player && player->duel && player->duel->IsMounted) player->DuelComplete(DUEL_FLED); - // This should be done before dismiss, because there may be some aura removal Vehicle* vehicle = m_vehicle; Unit* vehicleBase = m_vehicle->GetBase(); m_vehicle = nullptr; @@ -19775,33 +19776,22 @@ void Unit::_ExitVehicle(Position const* exitPosition) SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT Position pos; - if (!exitPosition) // Exit position not specified - pos = vehicleBase->GetPosition(); // This should use passenger's current position, leaving it as it is now - // because we calculate positions incorrect (sometimes under map) - else + // If we ask for a specific exit position, use that one. Otherwise allow scripts to modify it + if (exitPosition) pos = *exitPosition; - - // HACK - VehicleEntry const* vehicleInfo = vehicle->GetVehicleInfo(); - if (vehicleInfo) + else { - if (vehicleInfo->m_ID == 380) // Kologarn right arm + // Set exit position to vehicle position and use the current orientation + pos = vehicleBase->GetPosition(); // This should use passenger's current position, leaving it as it is now + pos.SetOrientation(vehicleBase->GetOrientation()); + + // Change exit position based on seat entry addon data + if (seatAddon) { - pos.Relocate(1776.0f, -24.0f, 448.75f, 0.0f); - } - else if (vehicleInfo->m_ID == 91) // Helsman's Ship - { - pos.Relocate(2802.18f, 7054.91f, -0.6f, 4.67f); - } - else if (vehicleInfo->m_ID == 349) // AT Mounts, dismount to the right - { - float x = pos.GetPositionX() + 2.0f * cos(pos.GetOrientation() - M_PI / 2.0f); - float y = pos.GetPositionY() + 2.0f * std::sin(pos.GetOrientation() - M_PI / 2.0f); - float z = GetMapHeight(x, y, pos.GetPositionZ()); - if (z > INVALID_HEIGHT) - { - pos.Relocate(x, y, z); - } + if (seatAddon->ExitParameter == VehicleExitParameters::VehicleExitParamOffset) + pos.RelocateOffset({ seatAddon->ExitParameterX, seatAddon->ExitParameterY, seatAddon->ExitParameterZ, seatAddon->ExitParameterO }); + else if (seatAddon->ExitParameter == VehicleExitParameters::VehicleExitParamDest) + pos.Relocate({ seatAddon->ExitParameterX, seatAddon->ExitParameterY, seatAddon->ExitParameterZ, seatAddon->ExitParameterO }); } } @@ -19821,11 +19811,12 @@ void Unit::_ExitVehicle(Position const* exitPosition) } // xinef: hack for flameleviathan seat vehicle + VehicleEntry const* vehicleInfo = vehicle->GetVehicleInfo(); if (!vehicleInfo || vehicleInfo->m_ID != 341) { Movement::MoveSplineInit init(this); init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); - init.SetFacing(GetOrientation()); + init.SetFacing(vehicleBase->GetOrientation()); init.SetTransportExit(); init.Launch(); } @@ -19878,10 +19869,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) setDeathState(DeathState::JustDied); // If for other reason we as minion are exiting the vehicle (ejected, master dismounted) - unsummon else - { - SetVisible(false); ToTempSummon()->UnSummon(2000); // Approximation - } } if (player) diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index ca5bbbd34..0fa035b7f 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -34,15 +34,18 @@ Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) if (uint32 seatId = _vehicleInfo->m_seatID[i]) if (VehicleSeatEntry const* veSeat = sVehicleSeatStore.LookupEntry(seatId)) { - Seats.insert(std::make_pair(i, VehicleSeat(veSeat))); + VehicleSeatAddon const* addon = sObjectMgr->GetVehicleSeatAddon(seatId); + Seats.insert(std::make_pair(i, VehicleSeat(veSeat, addon))); if (veSeat->CanEnterOrExit()) ++_usableSeatNum; } } - // Ulduar demolisher - if (vehInfo->m_ID == 338) - ++_usableSeatNum; + // Set or remove correct flags based on available seats. Will overwrite db data (if wrong). + if (_usableSeatNum) + _me->SetNpcFlag((_me->IsPlayer() ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); + else + _me->RemoveNpcFlag((_me->IsPlayer() ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); InitMovementInfoForBase(); } @@ -230,6 +233,15 @@ Unit* Vehicle::GetPassenger(int8 seatId) const return ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger.Guid); } +VehicleSeatAddon const* Vehicle::GetSeatAddonForSeatOfPassenger(Unit const* passenger) const +{ + for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); itr++) + if (!itr->second.IsEmpty() && itr->second.Passenger.Guid == passenger->GetGUID()) + return itr->second.SeatAddon; + + return nullptr; +} + int8 Vehicle::GetNextEmptySeat(int8 seatId, bool next) const { SeatMap::const_iterator seat = Seats.find(seatId); @@ -356,12 +368,9 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) ASSERT(_usableSeatNum); --_usableSeatNum; if (!_usableSeatNum) - { - if (_me->IsPlayer()) - _me->RemoveNpcFlag(UNIT_NPC_FLAG_PLAYER_VEHICLE); - else - _me->RemoveNpcFlag(UNIT_NPC_FLAG_SPELLCLICK); - } + _me->RemoveNpcFlag(_me->IsPlayer() ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK); + else + _me->SetNpcFlag(_me->IsPlayer() ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK); } if (!_me || !_me->IsInWorld() || _me->IsDuringRemoveFromWorld()) @@ -376,7 +385,14 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) unit->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); VehicleSeatEntry const* veSeat = seat->second.SeatInfo; - unit->m_movementInfo.transport.pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); + VehicleSeatAddon const* veSeatAddon = seat->second.SeatAddon; + + float o = veSeatAddon ? veSeatAddon->SeatOrientationOffset : 0.f; + float x = veSeat->m_attachmentOffsetX; + float y = veSeat->m_attachmentOffsetY; + float z = veSeat->m_attachmentOffsetZ; + + unit->m_movementInfo.transport.pos.Relocate(x, y, z, o); unit->m_movementInfo.transport.time = 0; unit->m_movementInfo.transport.seat = seat->first; unit->m_movementInfo.transport.guid = _me->GetGUID(); @@ -410,16 +426,17 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) // also adds MOVEMENTFLAG_ROOT Movement::MoveSplineInit init(unit); init.DisableTransportPathTransformations(); - init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); + init.MoveTo(x, y, z, false, true); // Xinef: did not found anything unique in dbc, maybe missed something if (veSeat->m_ID == 3566 || veSeat->m_ID == 3567 || veSeat->m_ID == 3568 || veSeat->m_ID == 3570) { - float x = veSeat->m_attachmentOffsetX, y = veSeat->m_attachmentOffsetY, z = veSeat->m_attachmentOffsetZ, o; CalculatePassengerPosition(x, y, z, &o); init.SetFacing(_me->GetAngle(x, y)); } else - init.SetFacing(0.0f); + { + init.SetFacing(o); + } init.SetTransportEnter(); init.Launch(); diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index b7bb2bf1d..3d5115e7f 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -41,6 +41,7 @@ public: bool HasEmptySeat(int8 seatId) const; Unit* GetPassenger(int8 seatId) const; int8 GetNextEmptySeat(int8 seatId, bool next) const; + VehicleSeatAddon const* GetSeatAddonForSeatOfPassenger(Unit const* passenger) const; uint8 GetAvailableSeatCount() const; bool AddPassenger(Unit* passenger, int8 seatId = -1); diff --git a/src/server/game/Entities/Vehicle/VehicleDefines.h b/src/server/game/Entities/Vehicle/VehicleDefines.h index 227bce7a8..1f4e99e6c 100644 --- a/src/server/game/Entities/Vehicle/VehicleDefines.h +++ b/src/server/game/Entities/Vehicle/VehicleDefines.h @@ -56,6 +56,14 @@ enum VehicleSpells VEHICLE_SPELL_SHADE_CONTROL_END = 58664 }; +enum class VehicleExitParameters +{ + VehicleExitParamNone = 0, // provided parameters will be ignored + VehicleExitParamOffset = 1, // provided parameters will be used as offset values + VehicleExitParamDest = 2, // provided parameters will be used as absolute destination + VehicleExitParamMax +}; + enum VehicleNPCs { NPC_EIDOLON_WATCHER = 31110, @@ -74,9 +82,24 @@ struct PassengerInfo } }; +struct VehicleSeatAddon +{ + VehicleSeatAddon() { } + VehicleSeatAddon(float orientatonOffset, float exitX, float exitY, float exitZ, float exitO, uint8 param) : + SeatOrientationOffset(orientatonOffset), ExitParameterX(exitX), ExitParameterY(exitY), ExitParameterZ(exitZ), + ExitParameterO(exitO), ExitParameter(VehicleExitParameters(param)) { } + + float SeatOrientationOffset = 0.f; + float ExitParameterX = 0.f; + float ExitParameterY = 0.f; + float ExitParameterZ = 0.f; + float ExitParameterO = 0.f; + VehicleExitParameters ExitParameter = VehicleExitParameters::VehicleExitParamNone; +}; + struct VehicleSeat { - explicit VehicleSeat(VehicleSeatEntry const* seatInfo) : SeatInfo(seatInfo) + explicit VehicleSeat(VehicleSeatEntry const* seatInfo, VehicleSeatAddon const* seatAddon) : SeatInfo(seatInfo), SeatAddon(seatAddon) { Passenger.Reset(); } @@ -84,6 +107,7 @@ struct VehicleSeat [[nodiscard]] bool IsEmpty() const { return !Passenger.Guid; } VehicleSeatEntry const* SeatInfo; + VehicleSeatAddon const* SeatAddon; PassengerInfo Passenger; }; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index e19e6098d..6799ce780 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -3483,6 +3483,62 @@ void ObjectMgr::LoadVehicleAccessories() LOG_INFO("server.loading", " "); } +void ObjectMgr::LoadVehicleSeatAddon() +{ + uint32 oldMSTime = getMSTime(); + + _vehicleSeatAddonStore.clear(); // needed for reload case + + uint32 count = 0; + + // 0 1 2 3 4 5 6 + QueryResult result = WorldDatabase.Query("SELECT `SeatEntry`, `SeatOrientation`, `ExitParamX`, `ExitParamY`, `ExitParamZ`, `ExitParamO`, `ExitParamValue` FROM `vehicle_seat_addon`"); + + if (!result) + { + LOG_ERROR("server.loading", ">> Loaded 0 vehicle seat addons. DB table `vehicle_seat_addon` is empty."); + return; + } + + do + { + Field* fields = result->Fetch(); + + uint32 seatID = fields[0].Get(); + float orientation = fields[1].Get(); + float exitX = fields[2].Get(); + float exitY = fields[3].Get(); + float exitZ = fields[4].Get(); + float exitO = fields[5].Get(); + uint8 exitParam = fields[6].Get(); + + if (!sVehicleSeatStore.LookupEntry(seatID)) + { + LOG_ERROR("sql.sql", "Table `vehicle_seat_addon`: SeatID: %u does not exist in VehicleSeat.dbc. Skipping entry.", seatID); + continue; + } + + // Sanitizing values + if (orientation > float(M_PI * 2)) + { + LOG_ERROR("sql.sql", "Table `vehicle_seat_addon`: SeatID: %u is using invalid angle offset value (%f). Set Value to 0.", seatID, orientation); + orientation = 0.0f; + } + + if (exitParam >= AsUnderlyingType(VehicleExitParameters::VehicleExitParamMax)) + { + LOG_ERROR("sql.sql", "Table `vehicle_seat_addon`: SeatID: %u is using invalid exit parameter value (%u). Setting to 0 (none).", seatID, exitParam); + continue; + } + + _vehicleSeatAddonStore[seatID] = VehicleSeatAddon(orientation, exitX, exitY, exitZ, exitO, exitParam); + + ++count; + } while (result->NextRow()); + + LOG_INFO("server.loading", ">> Loaded %u Vehicle Seat Addon entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); +} + void ObjectMgr::LoadPetLevelInfo() { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 3c46a3564..994bddcbc 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -518,6 +518,7 @@ typedef std::map, ModuleString> ModuleStringConta typedef std::unordered_map AcoreStringContainer; typedef std::unordered_map GossipMenuItemsLocaleContainer; typedef std::unordered_map PointOfInterestLocaleContainer; +typedef std::unordered_map VehicleSeatAddonContainer; typedef std::multimap QuestRelations; typedef std::pair QuestRelationBounds; @@ -1052,6 +1053,7 @@ public: void LoadMailServerTemplates(); void LoadVehicleTemplateAccessories(); void LoadVehicleAccessories(); + void LoadVehicleSeatAddon(); void LoadGossipText(); @@ -1429,6 +1431,15 @@ public: [[nodiscard]] bool IsTransportMap(uint32 mapId) const { return _transportMaps.count(mapId) != 0; } + VehicleSeatAddon const* GetVehicleSeatAddon(uint32 seatId) const + { + VehicleSeatAddonContainer::const_iterator itr = _vehicleSeatAddonStore.find(seatId); + if (itr == _vehicleSeatAddonStore.end()) + return nullptr; + + return &itr->second; + } + [[nodiscard]] uint32 GetQuestMoneyReward(uint8 level, uint32 questMoneyDifficulty) const; void SendServerMail(Player* player, uint32 id, uint32 reqLevel, uint32 reqPlayTime, uint32 rewardMoneyA, uint32 rewardMoneyH, uint32 rewardItemA, uint32 rewardItemCountA, uint32 rewardItemH, uint32 rewardItemCountH, std::string subject, std::string body, uint8 active) const; private: @@ -1506,6 +1517,7 @@ private: VehicleAccessoryContainer _vehicleTemplateAccessoryStore; VehicleAccessoryContainer _vehicleAccessoryStore; + VehicleSeatAddonContainer _vehicleSeatAddonStore; LocaleConstant DBCLocaleIndex; diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index ef7560e76..ffdff117c 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -986,9 +986,6 @@ void WorldSession::HandleMoveRootAck(WorldPacket& recvData) mover->m_movementInfo = movementInfo; mover->UpdatePosition(movementInfo.pos); - WorldPacket data(MSG_MOVE_ROOT, 64); - WriteMovementInfo(&data, &movementInfo); - mover->SendMessageToSet(&data, _player); } void WorldSession::HandleMoveUnRootAck(WorldPacket& recvData) @@ -1031,7 +1028,4 @@ void WorldSession::HandleMoveUnRootAck(WorldPacket& recvData) mover->m_movementInfo = movementInfo; mover->UpdatePosition(movementInfo.pos); - WorldPacket data(MSG_MOVE_UNROOT, 64); - WriteMovementInfo(&data, &movementInfo); - mover->SendMessageToSet(&data, _player); } diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index ca47ac9fe..ac90ae214 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4986,10 +4986,6 @@ void SpellMgr::LoadSpellInfoCorrections() vse->m_flags &= ~VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE; vse = const_cast(sVehicleSeatStore.LookupEntry(4693)); // Siege Engine, Accessory vse->m_flags &= ~VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE; - vse = const_cast(sVehicleSeatStore.LookupEntry(3011)); // Salvaged Demolisher, Ulduar - not allow to change seats - vse->m_flags &= ~VEHICLE_SEAT_FLAG_CAN_SWITCH; - vse = const_cast(sVehicleSeatStore.LookupEntry(3077)); // Salvaged Demolisher Seat, Ulduar - not allow to change seats - vse->m_flags &= ~VEHICLE_SEAT_FLAG_CAN_SWITCH; // pussywizard: fix z offset for some vehicles: vse = const_cast(sVehicleSeatStore.LookupEntry(6206)); // Marrowgar - Bone Spike diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index dd71be528..01295f569 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1817,6 +1817,9 @@ void World::SetInitialWorldSettings() LOG_INFO("server.loading", "Loading Vehicle Accessories..."); sObjectMgr->LoadVehicleAccessories(); // must be after LoadCreatureTemplates() and LoadNPCSpellClickSpells() + LOG_INFO("server.loading", "Loading Vehicle Seat Addon Data..."); + sObjectMgr->LoadVehicleSeatAddon(); // must be after loading DBC + LOG_INFO("server.loading", "Loading SpellArea Data..."); // must be after quest load sSpellMgr->LoadSpellAreas();