From b38fc89db3643b9050713a605321e27470bc2a66 Mon Sep 17 00:00:00 2001 From: Aokromes Date: Thu, 14 Feb 2013 09:48:46 +0100 Subject: Scripts/Ulduar: Kologarn's gate should be open while in combat Source: personal experience and http://youtu.be/JcOiyNaKDlg?t=18s --- src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index d3c174841ee..125f66497bf 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -565,10 +565,6 @@ class instance_ulduar : public InstanceMapScript } HandleGameObject(KologarnBridgeGUID, false); } - if (state == IN_PROGRESS) - HandleGameObject(KologarnDoorGUID, false); - else - HandleGameObject(KologarnDoorGUID, true); break; case BOSS_HODIR: if (state == DONE) -- cgit v1.2.3 From 0267b5381396a1de48026cd1808999ef545d309f Mon Sep 17 00:00:00 2001 From: Roc13x Date: Fri, 15 Feb 2013 12:29:34 +0000 Subject: Core/Items: Fix logic in Player::AddItem Should send client the amount it gave you, not the amount it couldn't give you --- src/server/game/Entities/Player/Player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index bdf3f1780d2..c7c88ae0bbe 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -25484,7 +25484,7 @@ bool Player::AddItem(uint32 itemId, uint32 count) ItemPosCountVec dest; InventoryResult msg = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, count, &noSpaceForCount); if (msg != EQUIP_ERR_OK) - count = noSpaceForCount; + count -= noSpaceForCount; if (count == 0 || dest.empty()) { -- cgit v1.2.3 From f74b874e930a8e59ac07d21138fdeaef106d7aa9 Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 15 Feb 2013 18:08:15 +0100 Subject: Core/Auras: Allow auras that cannot create a separate stack for each caster to stack on one slot --- src/server/game/Entities/Unit/Unit.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e3a2430f63a..fd9eef3868b 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3147,7 +3147,9 @@ void Unit::DeMorph() Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, uint64 casterGUID /*= 0*/) { ASSERT(casterGUID || caster); - if (!casterGUID) + + // Check if these can stack anyway + if (!casterGUID && (newAura->IsChanneled() || newAura->AttributesEx3 & SPELL_ATTR3_STACK_FOR_DIFF_CASTERS)) casterGUID = caster->GetGUID(); // passive and Incanter's Absorption and auras with different type can stack with themselves any number of times -- cgit v1.2.3 From 60cef65b5ca5f9550360a23eeb71a2478ca5af71 Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Sat, 16 Feb 2013 02:11:42 +0100 Subject: Core/Vehicle: Make the passenger join event asynchronous Prevents a crash in the following scenario: Player 1 enters vehicle X Seat on vehicle X is taken by Player 2 Player 2 is removed from vehicle X Vehicle X dismisses (but player 1 did not even finish AddPasssenger call) Fixes #4271 --- src/server/game/Entities/Unit/Unit.h | 2 + src/server/game/Entities/Vehicle/Vehicle.cpp | 178 +++++++++++++++++---------- src/server/game/Entities/Vehicle/Vehicle.h | 27 +++- 3 files changed, 139 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 1a41c25d97c..62facf6a69e 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -332,6 +332,7 @@ class UnitAI; class Totem; class Transport; class Vehicle; +class VehicleJoinEvent; class TransportBase; class SpellCastTargets; @@ -2183,6 +2184,7 @@ class Unit : public WorldObject uint32 GetRedirectThreatPercent() { return _redirectThreadInfo.GetThreatPct(); } Unit* GetRedirectThreatTarget() { return _redirectThreadInfo.GetTargetGUID() ? GetUnit(*this, _redirectThreadInfo.GetTargetGUID()) : NULL; } + friend class VehicleJoinEvent; bool IsAIEnabled, NeedChangeAI; bool CreateVehicleKit(uint32 id, uint32 creatureEntry); void RemoveVehicleKit(); diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 96f2b6d73dd..b6e47f239db 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -30,9 +30,10 @@ #include "SpellInfo.h" #include "MoveSplineInit.h" #include "TemporarySummon.h" +#include "EventProcessor.h" Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) : -_me(unit), _vehicleInfo(vehInfo), _usableSeatNum(0), _creatureEntry(creatureEntry), _status(STATUS_NONE) +_me(unit), _vehicleInfo(vehInfo), UsableSeatNum(0), _creatureEntry(creatureEntry), _status(STATUS_NONE) { for (uint32 i = 0; i < MAX_VEHICLE_SEATS; ++i) { @@ -41,7 +42,7 @@ _me(unit), _vehicleInfo(vehInfo), _usableSeatNum(0), _creatureEntry(creatureEntr { Seats.insert(std::make_pair(i, VehicleSeat(veSeat))); if (veSeat->CanEnterOrExit()) - ++_usableSeatNum; + ++UsableSeatNum; } } @@ -123,10 +124,12 @@ void Vehicle::Uninstall() "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), _me->GetEntry()); return; } + _status = STATUS_UNINSTALLING; sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Uninstall Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow()); RemoveAllPassengers(); + if (GetBase()->GetTypeId() == TYPEID_UNIT) sScriptMgr->OnUninstall(this); } @@ -136,14 +139,14 @@ void Vehicle::Reset(bool evading /*= false*/) sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Reset Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow()); if (_me->GetTypeId() == TYPEID_PLAYER) { - if (_usableSeatNum) + if (UsableSeatNum) _me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); } else { ApplyAllImmunities(); InstallAllAccessories(evading); - if (_usableSeatNum) + if (UsableSeatNum) _me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); } @@ -215,6 +218,19 @@ void Vehicle::RemoveAllPassengers() // ASSERT(!itr->second.passenger); } +void Vehicle::RemovePendingPassengers() +{ + sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::RemovePendingPassengers. Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow()); + + /// Setting to_Abort to true will cause @VehicleJoinEvent::Abort to be executed on next @Unit::UpdateEvents call + /// This will properly "reset" the pending join process for the passenger. + while (VehicleJoinEvent* e = _pendingJoinEvents.front()) + { + e->to_Abort = true; + _pendingJoinEvents.pop_front(); + } +} + bool Vehicle::HasEmptySeat(int8 seatId) const { SeatMap::const_iterator seat = Seats.find(seatId); @@ -317,7 +333,17 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) if (unit->GetVehicle() != this) return false; + // The seat selection code may kick other passengers off the vehicle. + // While the validity of the following may be arguable, it is possible that when such a passenger + // exits the vehicle will dismiss. That's why the actual adding the passenger to the vehicle is scheduled + // asynchronously, so it can be cancelled easily in case the vehicle is uninstalled meanwhile. SeatMap::iterator seat; + sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle entry %u id %u dbguid %u seat %d", + unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first); + VehicleJoinEvent* e = new VehicleJoinEvent(this, unit, seat); + unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0)); + _pendingJoinEvents.push_back(e); + if (seatId < 0) // no specific seat requirement { for (seat = Seats.begin(); seat != Seats.end(); ++seat) @@ -325,13 +351,19 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) break; if (seat == Seats.end()) // no available seat + { + CancelJoinEvent(e); return false; + } } else { seat = Seats.find(seatId); if (seat == Seats.end()) + { + CancelJoinEvent(e); return false; + } if (seat->second.Passenger) { @@ -344,65 +376,6 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) ASSERT(!seat->second.Passenger); } - sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s enter vehicle entry %u id %u dbguid %u seat %d", unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first); - - seat->second.Passenger = unit->GetGUID(); - if (seat->second.SeatInfo->CanEnterOrExit()) - { - ASSERT(_usableSeatNum); - --_usableSeatNum; - if (!_usableSeatNum) - { - if (_me->GetTypeId() == TYPEID_PLAYER) - _me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); - else - _me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - } - } - - if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)) - unit->AddUnitState(UNIT_STATE_ONVEHICLE); - - unit->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); - VehicleSeatEntry const* veSeat = seat->second.SeatInfo; - unit->m_movementInfo.t_pos.m_positionX = veSeat->m_attachmentOffsetX; - unit->m_movementInfo.t_pos.m_positionY = veSeat->m_attachmentOffsetY; - unit->m_movementInfo.t_pos.m_positionZ = veSeat->m_attachmentOffsetZ; - unit->m_movementInfo.t_pos.SetOrientation(0); - unit->m_movementInfo.t_time = 0; // 1 for player - unit->m_movementInfo.t_seat = seat->first; - unit->m_movementInfo.t_guid = _me->GetGUID(); - - if (_me->GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER && - seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL) - ASSERT(_me->SetCharmedBy(unit, CHARM_TYPE_VEHICLE)) - - if (_me->IsInWorld()) - { - unit->SendClearTarget(); // SMSG_BREAK_TARGET - unit->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) - // also adds MOVEMENTFLAG_ROOT - Movement::MoveSplineInit init(unit); - init.DisableTransportPathTransformations(); - init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); - init.SetFacing(0.0f); - init.SetTransportEnter(); - init.Launch(); - - if (_me->GetTypeId() == TYPEID_UNIT) - { - if (_me->ToCreature()->IsAIEnabled) - _me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, true); - - // update all passenger's positions - //Passenger's spline OR vehicle movement will update positions - //RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation()); - } - } - - if (GetBase()->GetTypeId() == TYPEID_UNIT) - sScriptMgr->OnAddPassenger(this, unit, seatId); - return true; } @@ -419,14 +392,14 @@ void Vehicle::RemovePassenger(Unit* unit) seat->second.Passenger = 0; if (seat->second.SeatInfo->CanEnterOrExit()) { - if (!_usableSeatNum) + if (!UsableSeatNum) { if (_me->GetTypeId() == TYPEID_PLAYER) _me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); else _me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); } - ++_usableSeatNum; + ++UsableSeatNum; } unit->ClearUnitState(UNIT_STATE_ONVEHICLE); @@ -549,3 +522,78 @@ void Vehicle::CalculatePassengerOffset(float& x, float& y, float& z, float& o) y = (iny - inx * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation())); x = (inx + iny * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation())); } + +void Vehicle::CancelJoinEvent(VehicleJoinEvent* e) +{ + e->to_Abort = true; + _pendingJoinEvents.pop_back(); +} + +bool VehicleJoinEvent::Execute(uint64, uint32) +{ + ASSERT(Passenger->GetVehicle() == Target); + + Seat->second.Passenger = Passenger->GetGUID(); + if (Seat->second.SeatInfo->CanEnterOrExit()) + { + ASSERT(Target->UsableSeatNum); + --(Target->UsableSeatNum); + if (!Target->UsableSeatNum) + { + if (Target->GetBase()->GetTypeId() == TYPEID_PLAYER) + Target->GetBase()->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); + else + Target->GetBase()->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } + } + + if (Seat->second.SeatInfo->m_flags && !(Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)) + Passenger->AddUnitState(UNIT_STATE_ONVEHICLE); + + Passenger->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); + VehicleSeatEntry const* veSeat = Seat->second.SeatInfo; + Passenger->m_movementInfo.t_pos.m_positionX = veSeat->m_attachmentOffsetX; + Passenger->m_movementInfo.t_pos.m_positionY = veSeat->m_attachmentOffsetY; + Passenger->m_movementInfo.t_pos.m_positionZ = veSeat->m_attachmentOffsetZ; + Passenger->m_movementInfo.t_pos.SetOrientation(0.0f); + Passenger->m_movementInfo.t_time = 0; // 1 for player + Passenger->m_movementInfo.t_seat = Seat->first; + Passenger->m_movementInfo.t_guid = Target->GetBase()->GetGUID(); + + if (Target->GetBase()->GetTypeId() == TYPEID_UNIT && Passenger->GetTypeId() == TYPEID_PLAYER && + Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL) + ASSERT(Target->GetBase()->SetCharmedBy(Passenger, CHARM_TYPE_VEHICLE)) + + if (Target->GetBase()->IsInWorld()) + { + Passenger->SendClearTarget(); // SMSG_BREAK_TARGET + Passenger->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) + // also adds MOVEMENTFLAG_ROOT + Movement::MoveSplineInit init(Passenger); + init.DisableTransportPathTransformations(); + init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); + init.SetFacing(0.0f); + init.SetTransportEnter(); + init.Launch(); + + if (Target->GetBase()->GetTypeId() == TYPEID_UNIT) + { + if (Target->GetBase()->ToCreature()->IsAIEnabled) + Target->GetBase()->ToCreature()->AI()->PassengerBoarded(Passenger, Seat->first, true); + + // update all passenger's positions + //Passenger's spline OR vehicle movement will update positions + //RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation()); + } + } + + if (Target->GetBase()->GetTypeId() == TYPEID_UNIT) + sScriptMgr->OnAddPassenger(Target, Passenger, Seat->first); + + return true; +} + +void VehicleJoinEvent::Abort(uint64) +{ + Passenger->m_vehicle = NULL; +} diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 823fb72b8a8..f8fa7f9b64a 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -23,12 +23,12 @@ #include "Object.h" #include "VehicleDefines.h" #include "Unit.h" +#include struct VehicleEntry; - class Unit; - typedef std::set GuidSet; +class VehicleJoinEvent; class Vehicle : public TransportBase { @@ -54,6 +54,7 @@ class Vehicle : public TransportBase void RemovePassenger(Unit* passenger); void RelocatePassengers(); void RemoveAllPassengers(); + void RemovePendingPassengers(); void Dismiss(); void TeleportVehicle(float x, float y, float z, float ang); bool IsVehicleInUse() { return Seats.begin() != Seats.end(); } @@ -65,6 +66,10 @@ class Vehicle : public TransportBase VehicleSeatEntry const* GetSeatForPassenger(Unit* passenger); + protected: + friend class VehicleJoinEvent; + uint32 UsableSeatNum; // Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags + protected: friend bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry); Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry); @@ -91,9 +96,25 @@ class Vehicle : public TransportBase Unit* _me; VehicleEntry const* _vehicleInfo; GuidSet vehiclePlayers; - uint32 _usableSeatNum; // Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags + uint32 _creatureEntry; // Can be different than me->GetBase()->GetEntry() in case of players Status _status; Position m_lastShootPos; + + std::deque _pendingJoinEvents; + void CancelJoinEvent(VehicleJoinEvent* e); +}; + +class VehicleJoinEvent : public BasicEvent +{ + friend class Vehicle; + protected: + VehicleJoinEvent(Vehicle* v, Unit* u, SeatMap::iterator& itr) : Target(v), Passenger(u), Seat(itr) {} + bool Execute(uint64, uint32); + void Abort(uint64); + + Vehicle* Target; + Unit* Passenger; + SeatMap::iterator& Seat; }; #endif -- cgit v1.2.3 From 49e196e6b00fd10895d7bb47442266305fa7e0fa Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Sat, 16 Feb 2013 03:26:26 +0100 Subject: Misc/Spells: - Add some ulduar teleport pos for spells - Add target hack for ulduar teleport spells --- .../world/2013_02_16_01_world_spell_target_position.sql | 11 +++++++++++ src/server/game/Spells/SpellMgr.cpp | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 sql/updates/world/2013_02_16_01_world_spell_target_position.sql (limited to 'src') diff --git a/sql/updates/world/2013_02_16_01_world_spell_target_position.sql b/sql/updates/world/2013_02_16_01_world_spell_target_position.sql new file mode 100644 index 00000000000..c262ecf450f --- /dev/null +++ b/sql/updates/world/2013_02_16_01_world_spell_target_position.sql @@ -0,0 +1,11 @@ +DELETE FROM `spell_target_position` WHERE `id` IN (64014,64024,64025,64028,64029,64030,64031,64032,65042); +INSERT INTO `spell_target_position` (`id`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`) VALUES +(64014, 603, -705.9705, -92.55729, 430.8192, 0), +(64024, 603, 2086.224, -24.05382, 422.2889, 0), +(64025, 603, 2518.131, 2569.342, 412.6822, 0), +(64028, 603, 553.243, -12.30903, 410.5428, 0), +(64029, 603, 1859.563, -24.83773, 449.1945, 6.230825), +(64030, 603, 1497.989, -24.16162, 421.6254, 0.03490658), +(64031, 603, 926.2917, -11.44444, 418.9779, 0.01745329), +(64032, 603, 131.1389, -35.36806, 410.187, 0), +(65042, 603, 1855.073, -11.48785, 334.559, 5.532694); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index dbd4e3904ea..b40943ff266 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3371,6 +3371,17 @@ void SpellMgr::LoadDbcDataCorrections() case 64596: // Cosmic Smash (Algalon the Observer) spellInfo->rangeIndex = 6; // 100yd break; + case 64014: // Expedition Base Camp Teleport + case 64024: // Conservatory Teleport + case 64025: // Halls of Invention Teleport + case 64028: // Colossal Forge Teleport + case 64029: // Shattered Walkway Teleport + case 64030: // Antechamber Teleport + case 64031: // Scrapyard Teleport + case 64032: // Formation Grounds Teleport + case 65042: // Prison of Yogg-Saron Teleport + spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_DB; + break; // ENDOF ULDUAR SPELLS // // TRIAL OF THE CRUSADER SPELLS -- cgit v1.2.3 From 178134d86b5dd86119125bd079a8e4e6c47bb2a8 Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Sat, 16 Feb 2013 09:51:46 +0100 Subject: Core/Vehicles: Fix crash introduced in my previous change --- src/server/game/Entities/Vehicle/Vehicle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index b6e47f239db..5cbed1b3a64 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -339,7 +339,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) // asynchronously, so it can be cancelled easily in case the vehicle is uninstalled meanwhile. SeatMap::iterator seat; sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle entry %u id %u dbguid %u seat %d", - unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first); + unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), seatId); VehicleJoinEvent* e = new VehicleJoinEvent(this, unit, seat); unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0)); _pendingJoinEvents.push_back(e); -- cgit v1.2.3 From 1845ab791825f99b433ae4e961b467d0a509ac25 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 16 Feb 2013 15:40:47 +0100 Subject: Core/Auras: Only auras that are stackable to use the same slot --- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Spells/SpellInfo.cpp | 6 ++++++ src/server/game/Spells/SpellInfo.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index fd9eef3868b..0c51e0d15a9 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3149,7 +3149,7 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 ASSERT(casterGUID || caster); // Check if these can stack anyway - if (!casterGUID && (newAura->IsChanneled() || newAura->AttributesEx3 & SPELL_ATTR3_STACK_FOR_DIFF_CASTERS)) + if (!casterGUID && !newAura->IsStackableOnOneSlotWithDifferentCasters()) casterGUID = caster->GetGUID(); // passive and Incanter's Absorption and auras with different type can stack with themselves any number of times diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 91bff331160..9a9369bad28 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1030,6 +1030,12 @@ bool SpellInfo::IsMultiSlotAura() const return IsPassive() || Id == 55849 || Id == 40075 || Id == 44413; // Power Spark, Fel Flak Fire, Incanter's Absorption } +bool SpellInfo::IsStackableOnOneSlotWithDifferentCasters() const +{ + /// TODO: Re-verify meaning of SPELL_ATTR3_STACK_FOR_DIFF_CASTERS and update conditions here + return StackAmount > 1 && !IsChanneled() && !(AttributesEx3 & SPELL_ATTR3_STACK_FOR_DIFF_CASTERS); +} + bool SpellInfo::IsDeathPersistent() const { return AttributesEx3 & SPELL_ATTR3_DEATH_PERSISTENT; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 23682c3d48f..bbc5b61e282 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -392,6 +392,7 @@ public: bool IsStackableWithRanks() const; bool IsPassiveStackableWithRanks() const; bool IsMultiSlotAura() const; + bool IsStackableOnOneSlotWithDifferentCasters() const; bool IsDeathPersistent() const; bool IsRequiringDeadTarget() const; bool IsAllowingDeadTarget() const; -- cgit v1.2.3 From 35fc90c684caa8046c0b85c1a64776f7e7fb51fe Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Sat, 16 Feb 2013 16:12:24 +0100 Subject: Core/Vehicles: Fix another crash Fixes #9225 --- src/server/game/Entities/Vehicle/Vehicle.cpp | 5 ++++- src/server/game/Entities/Vehicle/Vehicle.h | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 5cbed1b3a64..4fb93a85fdf 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -340,7 +340,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) SeatMap::iterator seat; sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle entry %u id %u dbguid %u seat %d", unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), seatId); - VehicleJoinEvent* e = new VehicleJoinEvent(this, unit, seat); + VehicleJoinEvent* e = new VehicleJoinEvent(this, unit); unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0)); _pendingJoinEvents.push_back(e); @@ -355,6 +355,8 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) CancelJoinEvent(e); return false; } + + e->Seat = seat; } else { @@ -365,6 +367,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) return false; } + e->Seat = seat; if (seat->second.Passenger) { if (Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger)) diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index f8fa7f9b64a..25a68e0e511 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -109,12 +109,12 @@ class VehicleJoinEvent : public BasicEvent { friend class Vehicle; protected: - VehicleJoinEvent(Vehicle* v, Unit* u, SeatMap::iterator& itr) : Target(v), Passenger(u), Seat(itr) {} + VehicleJoinEvent(Vehicle* v, Unit* u) : Target(v), Passenger(u), Seat(Target->Seats.end()) {} bool Execute(uint64, uint32); void Abort(uint64); Vehicle* Target; Unit* Passenger; - SeatMap::iterator& Seat; + SeatMap::iterator Seat; }; #endif -- cgit v1.2.3 From 920cd0e9238be1a77d3583a3f01c16ce23dcc9e2 Mon Sep 17 00:00:00 2001 From: Gigatotem Date: Sat, 16 Feb 2013 16:42:17 +0000 Subject: Scripts/Blackwing Lair: Broodlord Lashlayer clean-up. --- .../BlackwingLair/boss_broodlord_lashlayer.cpp | 86 +++++++++++----------- 1 file changed, 45 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp index fa1ab5528ca..57519a5312c 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -32,12 +32,20 @@ enum Say SAY_LEASH = 1, }; +enum Events +{ + EVENT_CLEAVE = 1, + EVENT_MORTAL_STRIKE = 2, + EVENT_BLAST_WAVE = 3, + EVENT_KNOCK_BACK = 4, +}; + enum Spells { SPELL_CLEAVE = 26350, - SPELL_BLASTWAVE = 23331, - SPELL_MORTALSTRIKE = 24573, - SPELL_KNOCKBACK = 25778 + SPELL_BLAST_WAVE = 23331, + SPELL_MORTAL_STRIKE = 24573, + SPELL_KNOCK_BACK = 25778 }; class boss_broodlord : public CreatureScript @@ -54,17 +62,13 @@ public: { boss_broodlordAI(Creature* creature) : ScriptedAI(creature) {} - uint32 Cleave_Timer; - uint32 BlastWave_Timer; - uint32 MortalStrike_Timer; - uint32 KnockBack_Timer; - void Reset() { - Cleave_Timer = 8000; // These times are probably wrong - BlastWave_Timer = 12000; - MortalStrike_Timer = 20000; - KnockBack_Timer = 30000; + // These timers are probably wrong + events.ScheduleEvent(EVENT_CLEAVE, 8000); + events.ScheduleEvent(EVENT_BLAST_WAVE, 12000); + events.ScheduleEvent(EVENT_MORTAL_STRIKE, 20000); + events.ScheduleEvent(EVENT_KNOCK_BACK, 30000); } void EnterCombat(Unit* /*who*/) @@ -78,43 +82,43 @@ public: if (!UpdateVictim()) return; - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - // BlastWave - if (BlastWave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLASTWAVE); - BlastWave_Timer = urand(8000, 16000); - } else BlastWave_Timer -= diff; + if (EnterEvadeIfOutOfCombatArea(diff)) + Talk(SAY_LEASH); - //MortalStrike_Timer - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = urand(25000, 35000); - } else MortalStrike_Timer -= diff; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (KnockBack_Timer <= diff) + while (uint32 eventId = events.ExecuteEvent()) { - if (Unit* target = me->getVictim()) + switch (eventId) { - DoCast(target, SPELL_KNOCKBACK); - // Drop 50% aggro - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -50); + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, 8000); + break; + case EVENT_MORTAL_STRIKE: + DoCastVictim(SPELL_MORTAL_STRIKE); + events.ScheduleEvent(EVENT_MORTAL_STRIKE, 20000); + break; + case EVENT_BLAST_WAVE: + DoCastVictim(SPELL_BLAST_WAVE); + events.ScheduleEvent(EVENT_BLAST_WAVE, 12000); + break; + case EVENT_KNOCK_BACK: + DoCastVictim(SPELL_BLAST_WAVE); + // Drop 50% of threat + if (DoGetThreat(target)) + DoModifyThreatPercent(target, -50); + events.ScheduleEvent(EVENT_BLAST_WAVE, 12000); + break; + default: + break; } - - KnockBack_Timer = urand(15000, 30000); - } else KnockBack_Timer -= diff; + } if (EnterEvadeIfOutOfCombatArea(diff)) Talk(SAY_LEASH); - + DoMeleeAttackIfReady(); } }; -- cgit v1.2.3 From 2e08db9ce96d04db77b14fd3ea5bfd243755c967 Mon Sep 17 00:00:00 2001 From: Gigatotem Date: Sat, 16 Feb 2013 16:56:06 +0000 Subject: Scripts/BWL: Fix typo in recent commit. --- .../scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp index 57519a5312c..40155a317ce 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -109,7 +109,7 @@ public: // Drop 50% of threat if (DoGetThreat(target)) DoModifyThreatPercent(target, -50); - events.ScheduleEvent(EVENT_BLAST_WAVE, 12000); + events.ScheduleEvent(EVENT_KNOCK_BACK, 30000); break; default: break; -- cgit v1.2.3 From a614dd775c4a377aea038307701b197fa492b54d Mon Sep 17 00:00:00 2001 From: Nay Date: Sat, 16 Feb 2013 17:04:44 +0000 Subject: Say NO to whitespace --- src/server/game/Entities/Vehicle/Vehicle.cpp | 8 ++++---- src/server/game/Entities/Vehicle/Vehicle.h | 2 +- .../EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp | 2 +- src/server/scripts/Kalimdor/zone_desolace.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 4fb93a85fdf..7469e522ee0 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -338,7 +338,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) // exits the vehicle will dismiss. That's why the actual adding the passenger to the vehicle is scheduled // asynchronously, so it can be cancelled easily in case the vehicle is uninstalled meanwhile. SeatMap::iterator seat; - sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle entry %u id %u dbguid %u seat %d", + sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle entry %u id %u dbguid %u seat %d", unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), seatId); VehicleJoinEvent* e = new VehicleJoinEvent(this, unit); unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0)); @@ -525,7 +525,7 @@ void Vehicle::CalculatePassengerOffset(float& x, float& y, float& z, float& o) y = (iny - inx * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation())); x = (inx + iny * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation())); } - + void Vehicle::CancelJoinEvent(VehicleJoinEvent* e) { e->to_Abort = true; @@ -593,9 +593,9 @@ bool VehicleJoinEvent::Execute(uint64, uint32) if (Target->GetBase()->GetTypeId() == TYPEID_UNIT) sScriptMgr->OnAddPassenger(Target, Passenger, Seat->first); - return true; + return true; } - + void VehicleJoinEvent::Abort(uint64) { Passenger->m_vehicle = NULL; diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 25a68e0e511..dbdd021a384 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -96,7 +96,7 @@ class Vehicle : public TransportBase Unit* _me; VehicleEntry const* _vehicleInfo; GuidSet vehiclePlayers; - + uint32 _creatureEntry; // Can be different than me->GetBase()->GetEntry() in case of players Status _status; Position m_lastShootPos; diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp index 40155a317ce..1e1337da7c4 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -118,7 +118,7 @@ public: if (EnterEvadeIfOutOfCombatArea(diff)) Talk(SAY_LEASH); - + DoMeleeAttackIfReady(); } }; diff --git a/src/server/scripts/Kalimdor/zone_desolace.cpp b/src/server/scripts/Kalimdor/zone_desolace.cpp index 8dbeb989140..0c0de93b096 100644 --- a/src/server/scripts/Kalimdor/zone_desolace.cpp +++ b/src/server/scripts/Kalimdor/zone_desolace.cpp @@ -109,7 +109,7 @@ public: } } }; - + CreatureAI* GetAI(Creature* creature) const { return new npc_aged_dying_ancient_kodoAI(creature); -- cgit v1.2.3 From f95ce01b15ebf2dfb3fdb99c43c80cab909dbb47 Mon Sep 17 00:00:00 2001 From: Nay Date: Sat, 16 Feb 2013 17:12:10 +0000 Subject: Scripts/BWL: Fix build --- .../scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp index 1e1337da7c4..79a380ccce9 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -121,6 +121,9 @@ public: DoMeleeAttackIfReady(); } + + private: + EventMap events; /// @todo: change BWL to instance script and bosses to BossAI }; }; -- cgit v1.2.3 From 166a2092fd086953e0679d19e9b7d959c902a9ea Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Sat, 16 Feb 2013 18:15:32 +0100 Subject: Scripts/BWL: Fix build no. 2 --- .../BlackwingLair/boss_broodlord_lashlayer.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp index 79a380ccce9..1303f5c4f58 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -105,10 +105,13 @@ public: events.ScheduleEvent(EVENT_BLAST_WAVE, 12000); break; case EVENT_KNOCK_BACK: - DoCastVictim(SPELL_BLAST_WAVE); - // Drop 50% of threat - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -50); + if (Unit* target = me->getVictim()) + { + DoCast(target, SPELL_BLAST_WAVE); + // Drop 50% of threat + if (DoGetThreat(target)) + DoModifyThreatPercent(target, -50); + } events.ScheduleEvent(EVENT_KNOCK_BACK, 30000); break; default: -- cgit v1.2.3 From 6cfb5e13dc914fd4442891c460ffce5d36f8443f Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Sat, 16 Feb 2013 18:53:44 +0100 Subject: Core/Character: Rename engrish function --- src/server/game/Handlers/CharacterHandler.cpp | 2 +- src/server/game/World/World.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 817a7682678..b12893ff65f 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -727,7 +727,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData) std::string IP_str = GetRemoteAddress(); sLog->outInfo(LOG_FILTER_CHARACTER, "Account: %d, IP: %s deleted character: %s, GUID: %u, Level: %u", accountId, IP_str.c_str(), name.c_str(), GUID_LOPART(guid), level); sScriptMgr->OnPlayerDelete(guid); - sWorld->DeleteCharaceterNameData(GUID_LOPART(guid)); + sWorld->DeleteCharacterNameData(GUID_LOPART(guid)); if (sLog->ShouldLog(LOG_FILTER_PLAYER_DUMP, LOG_LEVEL_INFO)) // optimize GetPlayerDump call { diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 30021338c4e..b955af7d863 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -733,7 +733,7 @@ class World void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level); void UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE); void UpdateCharacterNameDataLevel(uint32 guid, uint8 level); - void DeleteCharaceterNameData(uint32 guid) { _characterNameDataMap.erase(guid); } + void DeleteCharacterNameData(uint32 guid) { _characterNameDataMap.erase(guid); } bool HasCharacterNameData(uint32 guid) { return _characterNameDataMap.find(guid) != _characterNameDataMap.end(); } uint32 GetCleaningFlags() const { return m_CleaningFlags; } -- cgit v1.2.3 From 17d0ea66605fed938b15442c703cce187b270323 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 16 Feb 2013 19:16:52 +0100 Subject: Core/Auras: Prevent saving vehicle auras to db for players as they require both caster and target to be in world (which cannot be guaranteed) --- src/server/game/Spells/Auras/SpellAuras.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 4500152133e..a218e238c6f 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -908,6 +908,10 @@ bool Aura::CanBeSaved() const if (HasEffectType(SPELL_AURA_OPEN_STABLE)) return false; + // Can't save vehicle auras, it requires both caster & target to be in world + if (HasEffectType(SPELL_AURA_CONTROL_VEHICLE)) + return false; + // Incanter's Absorbtion - considering the minimal duration and problems with aura stacking // we skip saving this aura // Also for some reason other auras put as MultiSlot crash core on keeping them after restart, -- cgit v1.2.3 From 2d861b71ce9753ffa4d899acdbb0ca44bcb13128 Mon Sep 17 00:00:00 2001 From: Nay Date: Sat, 16 Feb 2013 18:41:55 +0000 Subject: Core/SAI: Add actions to set/add/remove (104/105/106) gameobject flags --- src/server/game/AI/SmartScripts/SmartScript.cpp | 39 ++++++++++++++++++++++ src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 3 ++ src/server/game/AI/SmartScripts/SmartScriptMgr.h | 12 +++++-- 3 files changed, 51 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index e37b9e777d8..80388ce0be9 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2028,6 +2028,45 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u delete targets; break; } + case SMART_ACTION_SET_GO_FLAG: + { + ObjectList* targets = GetTargets(e, unit); + if (!targets) + break; + + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsGameObject(*itr)) + (*itr)->ToGameObject()->SetUInt32Value(GAMEOBJECT_FLAGS, e.action.goFlag.flag); + + delete targets; + break; + } + case SMART_ACTION_ADD_GO_FLAG: + { + ObjectList* targets = GetTargets(e, unit); + if (!targets) + break; + + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsGameObject(*itr)) + (*itr)->ToGameObject()->SetFlag(GAMEOBJECT_FLAGS, e.action.goFlag.flag); + + delete targets; + break; + } + case SMART_ACTION_REMOVE_GO_FLAG: + { + ObjectList* targets = GetTargets(e, unit); + if (!targets) + break; + + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsGameObject(*itr)) + (*itr)->ToGameObject()->RemoveFlag(GAMEOBJECT_FLAGS, e.action.goFlag.flag); + + delete targets; + break; + } default: sLog->outError(LOG_FILTER_SQL, "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); break; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 90534de327a..f140afe1295 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -907,6 +907,9 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_SET_HOME_POS: case SMART_ACTION_SET_HEALTH_REGEN: case SMART_ACTION_SET_ROOT: + case SMART_ACTION_SET_GO_FLAG: + case SMART_ACTION_ADD_GO_FLAG: + case SMART_ACTION_REMOVE_GO_FLAG: break; default: sLog->outError(LOG_FILTER_SQL, "SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 88f9ce4f6f4..133c227f825 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -426,7 +426,6 @@ enum SMART_ACTION SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue(+pct, -flat) SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to dismount) SMART_ACTION_SET_INGAME_PHASE_MASK = 44, // mask - SMART_ACTION_SET_DATA = 45, // Field, Data (only creature TODO) SMART_ACTION_MOVE_FORWARD = 46, // distance SMART_ACTION_SET_VISIBILITY = 47, // on/off @@ -449,7 +448,6 @@ enum SMART_ACTION SMART_ACTION_STORE_TARGET_LIST = 64, // varID, SMART_ACTION_WP_RESUME = 65, // none SMART_ACTION_SET_ORIENTATION = 66, // - SMART_ACTION_CREATE_TIMED_EVENT = 67, // id, InitialMin, InitialMax, RepeatMin(only if it repeats), RepeatMax(only if it repeats), chance SMART_ACTION_PLAYMOVIE = 68, // entry SMART_ACTION_MOVE_TO_POS = 69, // PointId, xyz @@ -487,8 +485,11 @@ enum SMART_ACTION SMART_ACTION_SET_HOME_POS = 101, // none SMART_ACTION_SET_HEALTH_REGEN = 102, // 0/1 SMART_ACTION_SET_ROOT = 103, // off/on + SMART_ACTION_SET_GO_FLAG = 104, // Flags + SMART_ACTION_ADD_GO_FLAG = 105, // Flags + SMART_ACTION_REMOVE_GO_FLAG = 106, // Flags - SMART_ACTION_END = 104 + SMART_ACTION_END = 107 }; struct SmartAction @@ -925,6 +926,11 @@ struct SmartAction uint32 root; } setRoot; + struct + { + uint32 flag; + } goFlag; + //! Note for any new future actions //! All parameters must have type uint32 -- cgit v1.2.3 From e49aaab6f624d5d824e195c11ef3bd0e809d8460 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 17 Feb 2013 02:10:08 +0100 Subject: Scripts/Icecrown Citadel: Improvements to Shadowmourne quest line --- .../2013_02_17_00_world_spell_script_names.sql | 14 ++++ src/server/game/Entities/Unit/Unit.cpp | 42 ---------- src/server/game/Spells/SpellMgr.cpp | 2 +- .../IcecrownCitadel/boss_blood_queen_lana_thel.cpp | 53 +++++++------ .../Northrend/IcecrownCitadel/boss_sindragosa.cpp | 92 ++++++++++++---------- .../Northrend/IcecrownCitadel/icecrown_citadel.h | 1 + .../IcecrownCitadel/instance_icecrown_citadel.cpp | 2 +- src/server/scripts/Spells/spell_item.cpp | 61 ++++++++------ 8 files changed, 132 insertions(+), 135 deletions(-) create mode 100644 sql/updates/world/2013_02_17_00_world_spell_script_names.sql (limited to 'src') diff --git a/sql/updates/world/2013_02_17_00_world_spell_script_names.sql b/sql/updates/world/2013_02_17_00_world_spell_script_names.sql new file mode 100644 index 00000000000..e47b22b1c6b --- /dev/null +++ b/sql/updates/world/2013_02_17_00_world_spell_script_names.sql @@ -0,0 +1,14 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_sindragosa_frost_breath'; +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_item_unsated_craving'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(69649,'spell_sindragosa_frost_breath'), +(71056,'spell_sindragosa_frost_breath'), +(71057,'spell_sindragosa_frost_breath'), +(71058,'spell_sindragosa_frost_breath'), +(73061,'spell_sindragosa_frost_breath'), +(73062,'spell_sindragosa_frost_breath'), +(73063,'spell_sindragosa_frost_breath'), +(73064,'spell_sindragosa_frost_breath'), +(71168,'spell_item_unsated_craving'); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=71952; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0c51e0d15a9..9223dfad533 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -8464,48 +8464,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg return false; break; } - // Shadow's Fate (Shadowmourne questline) - case 71169: - { - // Victim needs more checks so bugs, rats or summons can not be affected by the proc. - if (GetTypeId() != TYPEID_PLAYER || !victim || victim->GetTypeId() != TYPEID_UNIT || victim->GetCreatureType() == CREATURE_TYPE_CRITTER) - return false; - - Player* player = ToPlayer(); - if (player->GetQuestStatus(24547) == QUEST_STATUS_INCOMPLETE) - { - break; - } - else if (player->GetDifficulty(true) == RAID_DIFFICULTY_25MAN_NORMAL || player->GetDifficulty(true) == RAID_DIFFICULTY_25MAN_HEROIC) - { - uint32 spellId = 0; - uint32 questId = 0; - switch (victim->GetEntry()) - { - case 36678: // NPC: Professor Putricide - questId = 24749; // Quest: Unholy Infusion - spellId = 71516; // Spell: Shadow Infusion - break; - case 37955: // NPC: Blood-Queen Lana'thel - questId = 24756; // Quest: Blood Infusion - spellId = 72154; // Spell: Thirst Quenched - break; - case 36853: // NPC: Sindragosa - questId = 24757; // Quest: Frost Infusion - spellId = 72290; // Spell: Frost-Imbued Blade - break; - default: - return false; - } - - if (player->GetQuestStatus(questId) != QUEST_STATUS_INCOMPLETE || !player->HasAura(spellId)) - return false; - - break; - } - else - return false; - } } if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(trigger_spell_id)) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index b40943ff266..312189ffad8 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3475,7 +3475,7 @@ void SpellMgr::LoadDbcDataCorrections() case 71518: // Unholy Infusion Quest Credit (Professor Putricide) case 72934: // Blood Infusion Quest Credit (Blood-Queen Lana'thel) case 72289: // Frost Infusion Quest Credit (Sindragosa) - spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_50000_YARDS; // another missing radius + spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // another missing radius break; case 71708: // Empowered Flare (Blood Prince Council) case 72785: // Empowered Flare (Blood Prince Council) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index ab0c44aa6d0..4b1ccabe682 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -45,11 +45,13 @@ enum Spells SPELL_SHROUD_OF_SORROW = 70986, SPELL_FRENZIED_BLOODTHIRST_VISUAL = 71949, SPELL_VAMPIRIC_BITE = 71726, + SPELL_VAMPIRIC_BITE_DUMMY = 71837, SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR = 70879, SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL = 70872, SPELL_FRENZIED_BLOODTHIRST = 70877, SPELL_UNCONTROLLABLE_FRENZY = 70923, - SPELL_PRESENCE_OF_THE_DARKFALLEN = 71952, + SPELL_PRESENCE_OF_THE_DARKFALLEN = 70994, + SPELL_PRESENCE_OF_THE_DARKFALLEN_2 = 71952, SPELL_BLOOD_MIRROR_DAMAGE = 70821, SPELL_BLOOD_MIRROR_VISUAL = 71510, SPELL_BLOOD_MIRROR_DUMMY = 70838, @@ -88,6 +90,7 @@ uint32 const vampireAuras[3][MAX_DIFFICULTY] = #define ESSENCE_OF_BLOOD_QUEEN_PLR RAID_MODE(70879, 71525, 71530, 71531) #define FRENZIED_BLOODTHIRST RAID_MODE(70877, 71474, 70877, 71474) #define DELIRIOUS_SLASH RAID_MODE(71623, 71624, 71625, 71626) +#define PRESENCE_OF_THE_DARKFALLEN RAID_MODE(70994, 71962, 71963, 71964) enum Events { @@ -220,6 +223,7 @@ class boss_blood_queen_lana_thel : public CreatureScript instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DUMMY); instance->DoRemoveAurasDueToSpellOnPlayers(DELIRIOUS_SLASH); instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PACT_OF_THE_DARKFALLEN); + instance->DoRemoveAurasDueToSpellOnPlayers(PRESENCE_OF_THE_DARKFALLEN); } void DoAction(int32 const action) @@ -357,8 +361,11 @@ class boss_blood_queen_lana_thel : public CreatureScript { Unit* target = targets.front(); DoCast(target, SPELL_VAMPIRIC_BITE); + DoCastAOE(SPELL_VAMPIRIC_BITE_DUMMY, true); Talk(SAY_VAMPIRIC_BITE); _vampires.insert(target->GetGUID()); + target->CastSpell(target, SPELL_PRESENCE_OF_THE_DARKFALLEN, TRIGGERED_FULL_MASK); + target->CastSpell(target, SPELL_PRESENCE_OF_THE_DARKFALLEN_2, TRIGGERED_FULL_MASK); } break; } @@ -377,9 +384,10 @@ class boss_blood_queen_lana_thel : public CreatureScript _offtank->CastSpell(me->getVictim(), SPELL_BLOOD_MIRROR_DAMAGE, true); me->getVictim()->CastSpell(_offtank, SPELL_BLOOD_MIRROR_DUMMY, true); DoCastVictim(SPELL_BLOOD_MIRROR_VISUAL); - if (Item* shadowsEdge = _offtank->GetWeaponForAttack(BASE_ATTACK, true)) - if (!_offtank->HasAura(SPELL_THIRST_QUENCHED) && shadowsEdge->GetEntry() == ITEM_SHADOW_S_EDGE && !_offtank->HasAura(SPELL_GUSHING_WOUND)) - _offtank->CastSpell(_offtank, SPELL_GUSHING_WOUND, true); + if (Is25ManRaid() && _offtank->GetQuestStatus(QUEST_BLOOD_INFUSION) == QUEST_STATUS_INCOMPLETE && + _offtank->HasAura(SPELL_UNSATED_CRAVING) && !_offtank->HasAura(SPELL_THIRST_QUENCHED) && + !_offtank->HasAura(SPELL_GUSHING_WOUND)) + _offtank->CastSpell(_offtank, SPELL_GUSHING_WOUND, TRIGGERED_FULL_MASK); } } @@ -396,13 +404,7 @@ class boss_blood_queen_lana_thel : public CreatureScript { std::list targets; SelectRandomTarget(false, &targets); - uint32 targetCount = 2; - // do not combine these checks! we want it incremented TWICE when both conditions are met - if (IsHeroic()) - ++targetCount; - if (Is25ManRaid()) - ++targetCount; - Trinity::Containers::RandomResizeList(targets, targetCount); + Trinity::Containers::RandomResizeList(targets, Is25ManRaid() ? 3 : 2); if (targets.size() > 1) { Talk(SAY_PACT_OF_THE_DARKFALLEN); @@ -554,33 +556,36 @@ class spell_blood_queen_vampiric_bite : public SpellScriptLoader uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(SPELL_FRENZIED_BLOODTHIRST, GetCaster()); GetCaster()->RemoveAura(spellId, 0, 0, AURA_REMOVE_BY_ENEMY_SPELL); - GetCaster()->CastSpell(GetCaster(), SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR, true); - // Presence of the Darkfallen buff on Blood-Queen - if (GetCaster()->GetMap()->IsHeroic()) - GetCaster()->CastSpell(GetCaster(), SPELL_PRESENCE_OF_THE_DARKFALLEN, true); + GetCaster()->CastSpell(GetCaster(), SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR, TRIGGERED_FULL_MASK); + // Shadowmourne questline - if (GetCaster()->ToPlayer()->GetQuestStatus(QUEST_BLOOD_INFUSION) == QUEST_STATUS_INCOMPLETE) + if (Aura* aura = GetCaster()->GetAura(SPELL_GUSHING_WOUND)) { - if (Aura* aura = GetCaster()->GetAura(SPELL_GUSHING_WOUND)) + if (aura->GetStackAmount() == 3) { - if (aura->GetStackAmount() == 3) - { - GetCaster()->CastSpell(GetCaster(), SPELL_THIRST_QUENCHED, true); - GetCaster()->RemoveAura(aura); - } - else - GetCaster()->CastSpell(GetCaster(), SPELL_GUSHING_WOUND, true); + GetCaster()->CastSpell(GetCaster(), SPELL_THIRST_QUENCHED, TRIGGERED_FULL_MASK); + GetCaster()->RemoveAura(aura); } + else + GetCaster()->CastSpell(GetCaster(), SPELL_GUSHING_WOUND, TRIGGERED_FULL_MASK); } + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) if (Creature* bloodQueen = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_BLOOD_QUEEN_LANA_THEL))) bloodQueen->AI()->SetGUID(GetHitUnit()->GetGUID(), GUID_VAMPIRE); } + void HandlePresence(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_PRESENCE_OF_THE_DARKFALLEN, TRIGGERED_FULL_MASK); + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_PRESENCE_OF_THE_DARKFALLEN_2, TRIGGERED_FULL_MASK); + } + void Register() { OnCheckCast += SpellCheckCastFn(spell_blood_queen_vampiric_bite_SpellScript::CheckTarget); BeforeHit += SpellHitFn(spell_blood_queen_vampiric_bite_SpellScript::OnCast); + OnEffectHitTarget += SpellEffectFn(spell_blood_queen_vampiric_bite_SpellScript::HandlePresence, EFFECT_1, SPELL_EFFECT_TRIGGER_SPELL); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 1c6ed848158..5c7f575413a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -84,7 +84,9 @@ enum Spells SPELL_CONCUSSIVE_SHOCK = 71337, // Frost Infusion - SPELL_FROST_INFUSION_CREDIT = 72289 + SPELL_FROST_INFUSION_CREDIT = 72289, + SPELL_FROST_IMBUED_BLADE = 72290, + SPELL_FROST_INFUSION = 72292, }; enum Events @@ -147,11 +149,7 @@ enum MovementPoints enum Shadowmourne { - QUEST_FROST_INFUSION = 24757, - ITEM_SHADOW_S_EDGE = 49888, - - SPELL_FROST_INFUSION = 72292, - SPELL_FROST_IMBUED_BLADE = 72290, + QUEST_FROST_INFUSION = 24757 }; Position const RimefangFlyPos = {4413.309f, 2456.421f, 233.3795f, 2.890186f}; @@ -390,47 +388,10 @@ class boss_sindragosa : public CreatureScript void SpellHitTarget(Unit* target, SpellInfo const* spell) { if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(70127, me)) - { if (spellId == spell->Id) - { if (Aura const* mysticBuffet = target->GetAura(spell->Id)) _mysticBuffetStack = std::max(_mysticBuffetStack, mysticBuffet->GetStackAmount()); - return; - } - } - - // Frost Infusion - if (Player* player = target->ToPlayer()) - { - if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(_isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1, me)) - { - if (spellId == spell->Id) - { - Item* shadowsEdge = player->GetWeaponForAttack(BASE_ATTACK, true); - if (player->GetQuestStatus(QUEST_FROST_INFUSION) == QUEST_STATUS_INCOMPLETE && shadowsEdge) - { - if (!player->HasAura(SPELL_FROST_IMBUED_BLADE) && shadowsEdge->GetEntry() == ITEM_SHADOW_S_EDGE) - { - if (Aura* infusion = player->GetAura(SPELL_FROST_INFUSION)) - { - if (infusion->GetStackAmount() == 3) - { - player->CastSpell(player, SPELL_FROST_IMBUED_BLADE, true); - player->RemoveAura(infusion); - } - else - player->CastSpell(player, SPELL_FROST_INFUSION, true); - } - else - player->CastSpell(player, SPELL_FROST_INFUSION, true); - } - } - - return; - } - } - } } void UpdateAI(uint32 const diff) @@ -1155,6 +1116,50 @@ class spell_sindragosa_unchained_magic : public SpellScriptLoader } }; +class spell_sindragosa_frost_breath : public SpellScriptLoader +{ + public: + spell_sindragosa_frost_breath() : SpellScriptLoader("spell_sindragosa_frost_breath") { } + + class spell_sindragosa_frost_breath_SpellScript : public SpellScript + { + PrepareSpellScript(spell_sindragosa_frost_breath_SpellScript); + + void HandleInfusion() + { + Player* target = GetHitPlayer(); + if (!target) + return; + + if (target->GetQuestStatus(QUEST_FROST_INFUSION) != QUEST_STATUS_INCOMPLETE) + return; + + // Check if player has Shadow's Edge equipped and not ready for infusion + if (!target->HasAura(SPELL_UNSATED_CRAVING) || target->HasAura(SPELL_FROST_IMBUED_BLADE)) + return; + + Aura* infusion = target->GetAura(SPELL_FROST_INFUSION, target->GetGUID()); + if (infusion && infusion->GetStackAmount() >= 3) + { + target->RemoveAura(infusion); + target->CastSpell(target, SPELL_FROST_IMBUED_BLADE, TRIGGERED_FULL_MASK); + } + else + target->CastSpell(target, SPELL_FROST_INFUSION, TRIGGERED_FULL_MASK); + } + + void Register() + { + AfterHit += SpellHitFn(spell_sindragosa_frost_breath_SpellScript::HandleInfusion); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_sindragosa_frost_breath_SpellScript(); + } +}; + class spell_sindragosa_instability : public SpellScriptLoader { public: @@ -1577,6 +1582,7 @@ void AddSC_boss_sindragosa() new npc_sindragosa_trash(); new spell_sindragosa_s_fury(); new spell_sindragosa_unchained_magic(); + new spell_sindragosa_frost_breath(); new spell_sindragosa_instability(); new spell_sindragosa_frost_beacon(); new spell_sindragosa_ice_tomb(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index 1407568686f..887a31baf9a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -56,6 +56,7 @@ enum SharedSpells SPELL_FROSTMOURNE_TELEPORT_VISUAL = 73078, // Shadowmourne questline + SPELL_UNSATED_CRAVING = 71168, SPELL_SHADOWS_FATE = 71169 }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 462708360e3..593d9586156 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -435,7 +435,7 @@ class instance_icecrown_citadel : public InstanceMapScript // these 2 gates are functional only on 25man modes case GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_01: case GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_04: - if (instance->GetSpawnMode() & 1) + if (instance->Is25ManRaid()) AddDoor(go, true); break; case GO_LADY_DEATHWHISPER_ELEVATOR: diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index d57ed6e126b..c9c75cdb134 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -813,53 +813,65 @@ class spell_item_scroll_of_recall : public SpellScriptLoader enum ShadowsFate { SPELL_SOUL_FEAST = 71203, - QUEST_A_FEAST_OF_SOULS = 24547 }; -class spell_item_shadows_fate : public SpellScriptLoader +class spell_item_unsated_craving : public SpellScriptLoader { public: - spell_item_shadows_fate() : SpellScriptLoader("spell_item_shadows_fate") { } + spell_item_unsated_craving() : SpellScriptLoader("spell_item_unsated_craving") { } - class spell_item_shadows_fate_AuraScript : public AuraScript + class spell_item_unsated_craving_AuraScript : public AuraScript { - PrepareAuraScript(spell_item_shadows_fate_AuraScript); + PrepareAuraScript(spell_item_unsated_craving_AuraScript); - bool Validate(SpellInfo const* /*spellInfo*/) + bool CheckProc(ProcEventInfo& procInfo) { - if (!sSpellMgr->GetSpellInfo(SPELL_SOUL_FEAST)) + Unit* caster = procInfo.GetActor(); + if (!caster || caster->GetTypeId() != TYPEID_PLAYER) return false; - if (!sObjectMgr->GetQuestTemplate(QUEST_A_FEAST_OF_SOULS)) + + Unit* target = procInfo.GetActionTarget(); + if (!target || target->GetTypeId() != TYPEID_UNIT || target->GetCreatureType() == CREATURE_TYPE_CRITTER || target->isSummon()) return false; - return true; - } - bool Load() - { - _procTarget = NULL; return true; } - bool CheckProc(ProcEventInfo& /*eventInfo*/) + void Register() { - _procTarget = GetCaster(); - return _procTarget && _procTarget->GetTypeId() == TYPEID_PLAYER && _procTarget->ToPlayer()->GetQuestStatus(QUEST_A_FEAST_OF_SOULS) == QUEST_STATUS_INCOMPLETE; + DoCheckProc += AuraCheckProcFn(spell_item_unsated_craving_AuraScript::CheckProc); } + }; - void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/) + AuraScript* GetAuraScript() const + { + return new spell_item_unsated_craving_AuraScript(); + } +}; + +class spell_item_shadows_fate : public SpellScriptLoader +{ + public: + spell_item_shadows_fate() : SpellScriptLoader("spell_item_shadows_fate") { } + + class spell_item_shadows_fate_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_shadows_fate_AuraScript); + + void HandleProc(ProcEventInfo& procInfo) { - PreventDefaultAction(); - GetTarget()->CastSpell(_procTarget, SPELL_SOUL_FEAST, true); + Unit* caster = procInfo.GetActor(); + Unit* target = GetCaster(); + if (!caster || !target) + return; + + caster->CastSpell(target, SPELL_SOUL_FEAST, TRIGGERED_FULL_MASK); } void Register() { - DoCheckProc += AuraCheckProcFn(spell_item_shadows_fate_AuraScript::CheckProc); - OnEffectProc += AuraEffectProcFn(spell_item_shadows_fate_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + OnProc += AuraProcFn(spell_item_shadows_fate_AuraScript::HandleProc); } - - private: - Unit* _procTarget; }; AuraScript* GetAuraScript() const @@ -2481,6 +2493,7 @@ void AddSC_item_spell_scripts() new spell_item_piccolo_of_the_flaming_fire(); new spell_item_savory_deviate_delight(); new spell_item_scroll_of_recall(); + new spell_item_unsated_craving(); new spell_item_shadows_fate(); new spell_item_shadowmourne(); new spell_item_shadowmourne_soul_fragment(); -- cgit v1.2.3 From 863468ec433a47ded7be47b8c50037942dc8a15e Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 17 Feb 2013 02:11:13 +0100 Subject: Core/Auras: Always run all script hooks attached to the aura to prevent leaving aura script state stack in unbalanced state --- src/server/game/Spells/Auras/SpellAuras.cpp | 158 ++++++++++++++-------------- 1 file changed, 80 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index a218e238c6f..375f9ef067c 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -2096,16 +2096,17 @@ void Aura::LoadScripts() bool Aura::CallScriptCheckAreaTargetHandlers(Unit* target) { + bool result = true; for (std::list::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) { (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_AREA_TARGET); std::list::iterator hookItrEnd = (*scritr)->DoCheckAreaTarget.end(), hookItr = (*scritr)->DoCheckAreaTarget.begin(); for (; hookItr != hookItrEnd; ++hookItr) - if (!(*hookItr).Call(*scritr, target)) - return false; + result &= hookItr->Call(*scritr, target); + (*scritr)->_FinishScriptCall(); } - return true; + return result; } void Aura::CallScriptDispel(DispelInfo* dispelInfo) @@ -2115,7 +2116,8 @@ void Aura::CallScriptDispel(DispelInfo* dispelInfo) (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL); std::list::iterator hookItrEnd = (*scritr)->OnDispel.end(), hookItr = (*scritr)->OnDispel.begin(); for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr, dispelInfo); + hookItr->Call(*scritr, dispelInfo); + (*scritr)->_FinishScriptCall(); } } @@ -2127,7 +2129,8 @@ void Aura::CallScriptAfterDispel(DispelInfo* dispelInfo) (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL); std::list::iterator hookItrEnd = (*scritr)->AfterDispel.end(), hookItr = (*scritr)->AfterDispel.begin(); for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr, dispelInfo); + hookItr->Call(*scritr, dispelInfo); + (*scritr)->_FinishScriptCall(); } } @@ -2140,14 +2143,15 @@ bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplicati (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp); std::list::iterator effEndItr = (*scritr)->OnEffectApply.end(), effItr = (*scritr)->OnEffectApply.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, mode); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, mode); + if (!preventDefault) preventDefault = (*scritr)->_IsDefaultActionPrevented(); + (*scritr)->_FinishScriptCall(); } + return preventDefault; } @@ -2159,12 +2163,12 @@ bool Aura::CallScriptEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplicat (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp); std::list::iterator effEndItr = (*scritr)->OnEffectRemove.end(), effItr = (*scritr)->OnEffectRemove.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, mode); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, mode); + if (!preventDefault) preventDefault = (*scritr)->_IsDefaultActionPrevented(); + (*scritr)->_FinishScriptCall(); } return preventDefault; @@ -2177,10 +2181,9 @@ void Aura::CallScriptAfterEffectApplyHandlers(AuraEffect const* aurEff, AuraAppl (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY, aurApp); std::list::iterator effEndItr = (*scritr)->AfterEffectApply.end(), effItr = (*scritr)->AfterEffectApply.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, mode); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, mode); + (*scritr)->_FinishScriptCall(); } } @@ -2192,10 +2195,9 @@ void Aura::CallScriptAfterEffectRemoveHandlers(AuraEffect const* aurEff, AuraApp (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE, aurApp); std::list::iterator effEndItr = (*scritr)->AfterEffectRemove.end(), effItr = (*scritr)->AfterEffectRemove.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, mode); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, mode); + (*scritr)->_FinishScriptCall(); } } @@ -2208,14 +2210,15 @@ bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const* aurEff, AuraApplic (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC, aurApp); std::list::iterator effEndItr = (*scritr)->OnEffectPeriodic.end(), effItr = (*scritr)->OnEffectPeriodic.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff); + if (!preventDefault) preventDefault = (*scritr)->_IsDefaultActionPrevented(); + (*scritr)->_FinishScriptCall(); } + return preventDefault; } @@ -2226,10 +2229,9 @@ void Aura::CallScriptEffectUpdatePeriodicHandlers(AuraEffect* aurEff) (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC); std::list::iterator effEndItr = (*scritr)->OnEffectUpdatePeriodic.end(), effItr = (*scritr)->OnEffectUpdatePeriodic.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff); + (*scritr)->_FinishScriptCall(); } } @@ -2241,10 +2243,9 @@ void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32 & (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT); std::list::iterator effEndItr = (*scritr)->DoEffectCalcAmount.end(), effItr = (*scritr)->DoEffectCalcAmount.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, amount, canBeRecalculated); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, amount, canBeRecalculated); + (*scritr)->_FinishScriptCall(); } } @@ -2256,10 +2257,9 @@ void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool & (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC); std::list::iterator effEndItr = (*scritr)->DoEffectCalcPeriodic.end(), effItr = (*scritr)->DoEffectCalcPeriodic.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, isPeriodic, amplitude); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, isPeriodic, amplitude); + (*scritr)->_FinishScriptCall(); } } @@ -2271,10 +2271,9 @@ void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellM (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD); std::list::iterator effEndItr = (*scritr)->DoEffectCalcSpellMod.end(), effItr = (*scritr)->DoEffectCalcSpellMod.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, spellMod); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, spellMod); + (*scritr)->_FinishScriptCall(); } } @@ -2286,11 +2285,13 @@ void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication co (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp); std::list::iterator effEndItr = (*scritr)->OnEffectAbsorb.end(), effItr = (*scritr)->OnEffectAbsorb.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount); - } - defaultPrevented = (*scritr)->_IsDefaultActionPrevented(); + + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount); + + if (!defaultPrevented) + defaultPrevented = (*scritr)->_IsDefaultActionPrevented(); + (*scritr)->_FinishScriptCall(); } } @@ -2302,10 +2303,9 @@ void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplicati (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp); std::list::iterator effEndItr = (*scritr)->AfterEffectAbsorb.end(), effItr = (*scritr)->AfterEffectAbsorb.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount); + (*scritr)->_FinishScriptCall(); } } @@ -2317,10 +2317,9 @@ void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplicatio (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, aurApp); std::list::iterator effEndItr = (*scritr)->OnEffectManaShield.end(), effItr = (*scritr)->OnEffectManaShield.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount); + (*scritr)->_FinishScriptCall(); } } @@ -2332,10 +2331,9 @@ void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraAppli (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, aurApp); std::list::iterator effEndItr = (*scritr)->AfterEffectManaShield.end(), effItr = (*scritr)->AfterEffectManaShield.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount); + (*scritr)->_FinishScriptCall(); } } @@ -2347,26 +2345,27 @@ void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication con (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp); std::list::iterator effEndItr = (*scritr)->OnEffectSplit.end(), effItr = (*scritr)->OnEffectSplit.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, dmgInfo, splitAmount); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, dmgInfo, splitAmount); + (*scritr)->_FinishScriptCall(); } } bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo) { + bool result = true; for (std::list::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) { (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp); std::list::iterator hookItrEnd = (*scritr)->DoCheckProc.end(), hookItr = (*scritr)->DoCheckProc.begin(); for (; hookItr != hookItrEnd; ++hookItr) - if (!(*hookItr).Call(*scritr, eventInfo)) - return false; + result &= hookItr->Call(*scritr, eventInfo); + (*scritr)->_FinishScriptCall(); } - return true; + + return result; } bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo) @@ -2377,12 +2376,14 @@ bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEven (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp); std::list::iterator effEndItr = (*scritr)->DoPrepareProc.end(), effItr = (*scritr)->DoPrepareProc.begin(); for (; effItr != effEndItr; ++effItr) - (*effItr).Call(*scritr, eventInfo); + effItr->Call(*scritr, eventInfo); + + if (prepare) + prepare = !(*scritr)->_IsDefaultActionPrevented(); - if (prepare && (*scritr)->_IsDefaultActionPrevented()) - prepare = false; (*scritr)->_FinishScriptCall(); } + return prepare; } @@ -2393,7 +2394,8 @@ void Aura::CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp); std::list::iterator hookItrEnd = (*scritr)->OnProc.end(), hookItr = (*scritr)->OnProc.begin(); for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr, eventInfo); + hookItr->Call(*scritr, eventInfo); + (*scritr)->_FinishScriptCall(); } } @@ -2405,7 +2407,8 @@ void Aura::CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventI (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp); std::list::iterator hookItrEnd = (*scritr)->AfterProc.end(), hookItr = (*scritr)->AfterProc.begin(); for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr, eventInfo); + hookItr->Call(*scritr, eventInfo); + (*scritr)->_FinishScriptCall(); } } @@ -2418,12 +2421,12 @@ bool Aura::CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplicatio (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp); std::list::iterator effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, eventInfo); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, eventInfo); + if (!preventDefault) preventDefault = (*scritr)->_IsDefaultActionPrevented(); + (*scritr)->_FinishScriptCall(); } return preventDefault; @@ -2436,10 +2439,9 @@ void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraAppli (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp); std::list::iterator effEndItr = (*scritr)->AfterEffectProc.end(), effItr = (*scritr)->AfterEffectProc.begin(); for (; effItr != effEndItr; ++effItr) - { - if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - (*effItr).Call(*scritr, aurEff, eventInfo); - } + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, eventInfo); + (*scritr)->_FinishScriptCall(); } } -- cgit v1.2.3 From 6590cf4f9e3101a0406d900a5441c309de5697ce Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Sun, 17 Feb 2013 08:03:27 +0100 Subject: Core/Vehicles: Fix another crash Don't set Unit::m_vehicle until VehicleJoinEvent::Execute --- src/server/game/Entities/Unit/Unit.cpp | 10 +++------- src/server/game/Entities/Vehicle/Vehicle.cpp | 5 ++++- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 9223dfad533..f607e7930a6 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3149,7 +3149,7 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 ASSERT(casterGUID || caster); // Check if these can stack anyway - if (!casterGUID && !newAura->IsStackableOnOneSlotWithDifferentCasters()) + if (!casterGUID && (newAura->IsChanneled() || newAura->AttributesEx3 & SPELL_ATTR3_STACK_FOR_DIFF_CASTERS)) casterGUID = caster->GetGUID(); // passive and Incanter's Absorption and auras with different type can stack with themselves any number of times @@ -16599,13 +16599,9 @@ void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* a } ASSERT(!m_vehicle); - m_vehicle = vehicle; - if (!m_vehicle->AddPassenger(this, seatId)) - { - m_vehicle = NULL; - return; - } + + (void)vehicle->AddPassenger(this, seatId); } void Unit::ChangeSeat(int8 seatId, bool next) diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 7469e522ee0..58cf6773c59 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -535,6 +535,7 @@ void Vehicle::CancelJoinEvent(VehicleJoinEvent* e) bool VehicleJoinEvent::Execute(uint64, uint32) { ASSERT(Passenger->GetVehicle() == Target); + Passenger->m_vehicle = Target; Seat->second.Passenger = Passenger->GetGUID(); if (Seat->second.SeatInfo->CanEnterOrExit()) @@ -598,5 +599,7 @@ bool VehicleJoinEvent::Execute(uint64, uint32) void VehicleJoinEvent::Abort(uint64) { - Passenger->m_vehicle = NULL; + sLog->outDebug(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %i cancelled", + Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first); + // Passenger->m_vehicle = NULL; } -- cgit v1.2.3 From 608785c3a400a54b57b823a4eac07206640c1664 Mon Sep 17 00:00:00 2001 From: Alexei_Nech Date: Sun, 17 Feb 2013 14:08:41 +0200 Subject: declared WEATHER_STATE_FOG --- src/server/game/Weather/Weather.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/server/game/Weather/Weather.h b/src/server/game/Weather/Weather.h index 1fcd822d580..2645d3f2067 100644 --- a/src/server/game/Weather/Weather.h +++ b/src/server/game/Weather/Weather.h @@ -46,6 +46,7 @@ struct WeatherData enum WeatherState { WEATHER_STATE_FINE = 0, + WEATHER_STATE_FOG = 1, WEATHER_STATE_LIGHT_RAIN = 3, WEATHER_STATE_MEDIUM_RAIN = 4, WEATHER_STATE_HEAVY_RAIN = 5, -- cgit v1.2.3 From 0049e580ebb8fafc6341fd6c52bb028a8532bdbe Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Sun, 17 Feb 2013 14:48:14 +0100 Subject: Core/Auras: Restore part of 1845ab79 that was accidentally reverted --- src/server/game/Entities/Unit/Unit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f607e7930a6..29b3fe0383a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3149,7 +3149,7 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 ASSERT(casterGUID || caster); // Check if these can stack anyway - if (!casterGUID && (newAura->IsChanneled() || newAura->AttributesEx3 & SPELL_ATTR3_STACK_FOR_DIFF_CASTERS)) + if (!casterGUID && !newAura->IsStackableOnOneSlotWithDifferentCasters()) casterGUID = caster->GetGUID(); // passive and Incanter's Absorption and auras with different type can stack with themselves any number of times -- cgit v1.2.3 From d0799f3f88dcaee61ec3bd4c9321339fb808c28d Mon Sep 17 00:00:00 2001 From: Alexei_Nech Date: Sun, 17 Feb 2013 16:29:24 +0200 Subject: Update src/server/game/Weather/Weather.cpp --- src/server/game/Weather/Weather.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp index cd148712b55..64ee188a0d2 100644 --- a/src/server/game/Weather/Weather.cpp +++ b/src/server/game/Weather/Weather.cpp @@ -221,6 +221,9 @@ bool Weather::UpdateWeather() char const* wthstr; switch (state) { + case WEATHER_STATE_FOG: + wthstr = "fog"; + break; case WEATHER_STATE_LIGHT_RAIN: wthstr = "light rain"; break; -- cgit v1.2.3 From 6395c80e86ac3a5fef1d666c16f453f8e81beed3 Mon Sep 17 00:00:00 2001 From: click Date: Sun, 17 Feb 2013 20:28:55 +0100 Subject: Buildsystem: Disable building the nonfunctional meshextractor.tool (not in a production-state atm), it CAN however be built with with using the -DWITH_MESHEXTRACTOR flag (not documented as option, and will most probably change in the future) --- src/tools/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 49c17913c64..3adccf105de 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -12,4 +12,6 @@ add_subdirectory(map_extractor) add_subdirectory(vmap4_assembler) add_subdirectory(vmap4_extractor) add_subdirectory(mmaps_generator) -add_subdirectory(mesh_extractor) +if (WITH_MESHEXTRACTOR) + add_subdirectory(mesh_extractor) +endif() -- cgit v1.2.3 From 01fbbf3b9352b6dcbedb39711fc2edd137e9f5b9 Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Mon, 18 Feb 2013 00:39:58 +0100 Subject: Core/Vehicles: Refactor some parts of vehicle system - Fix a few crashes: Closes #9235 - Simplify and get rid of lots of redundant and silly code - Optimisations in Unit::ChangeSeat - More documentation --- src/server/game/Entities/Creature/Creature.cpp | 6 +- src/server/game/Entities/Unit/Unit.cpp | 43 +-- src/server/game/Entities/Vehicle/Vehicle.cpp | 461 ++++++++++++++++++------- src/server/game/Entities/Vehicle/Vehicle.h | 18 +- src/server/game/Handlers/MiscHandler.cpp | 3 +- 5 files changed, 368 insertions(+), 163 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 6208bcc4727..0bcb2d76055 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1270,14 +1270,14 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint3 if (!vehId) vehId = cinfo->VehicleId; - if (vehId && !CreateVehicleKit(vehId, Entry)) - vehId = 0; - Object::_Create(guidlow, Entry, vehId ? HIGHGUID_VEHICLE : HIGHGUID_UNIT); if (!UpdateEntry(Entry, team, data)) return false; + if (vehId && !CreateVehicleKit(vehId, Entry)) + vehId = 0; + return true; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 29b3fe0383a..53f9a948edf 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -11388,8 +11388,6 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry) { if (CreateVehicleKit(VehicleId, creatureEntry)) { - GetVehicleKit()->Reset(); - // Send others that we now have a vehicle WorldPacket data(SMSG_PLAYER_VEHICLE_DATA, GetPackGUID().size()+4); data.appendPackGUID(GetGUID()); @@ -15458,7 +15456,10 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au // dismount players when charmed if (GetTypeId() == TYPEID_PLAYER) - Dismount(); + RemoveAurasByType(SPELL_AURA_MOUNTED); + + if (charmer->GetTypeId() == TYPEID_PLAYER) + charmer->RemoveAurasByType(SPELL_AURA_MOUNTED); ASSERT(type != CHARM_TYPE_POSSESS || charmer->GetTypeId() == TYPEID_PLAYER); ASSERT((type == CHARM_TYPE_VEHICLE) == IsVehicle()); @@ -16581,26 +16582,9 @@ void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* a { if (vehicle->GetBase()->GetTypeId() == TYPEID_PLAYER && player->isInCombat()) return; - - InterruptNonMeleeSpells(false); - player->StopCastingCharm(); - player->StopCastingBindSight(); - Dismount(); - RemoveAurasByType(SPELL_AURA_MOUNTED); - - // drop flag at invisible in bg - if (Battleground* bg = player->GetBattleground()) - bg->EventPlayerDroppedFlag(player); - - WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); - player->GetSession()->SendPacket(&data); - - player->UnsummonPetTemporaryIfAny(); } ASSERT(!m_vehicle); - - (void)vehicle->AddPassenger(this, seatId); } @@ -16609,15 +16593,17 @@ void Unit::ChangeSeat(int8 seatId, bool next) if (!m_vehicle) return; - if (seatId < 0) - { - seatId = m_vehicle->GetNextEmptySeat(GetTransSeat(), next); - if (seatId < 0) - return; - } - else if (seatId == GetTransSeat() || !m_vehicle->HasEmptySeat(seatId)) + // Don't change if current and new seat are identical + if (seatId == GetTransSeat()) return; + SeatMap::const_iterator seat = (seatId < 0 ? m_vehicle->GetNextEmptySeat(GetTransSeat(), next) : m_vehicle->Seats.find(seatId)); + // The second part of the check will only return true if seatId >= 0. @Vehicle::GetNextEmptySeat makes sure of that. + if (seat == m_vehicle->Seats.end() || seat->second.Passenger) + return; + + // Todo: the functions below could be consolidated and refactored to take + // SeatMap::const_iterator as parameter, to save redundant map lookups. m_vehicle->RemovePassenger(this); if (!m_vehicle->AddPassenger(this, seatId)) ASSERT(false); @@ -16644,6 +16630,9 @@ void Unit::ExitVehicle(Position const* /*exitPosition*/) void Unit::_ExitVehicle(Position const* exitPosition) { + /// It's possible m_vehicle is NULL, when this function is called indirectly from @VehicleJoinEvent::Abort. + /// In that case it was not possible to add the passenger to the vehicle. The vehicle aura has already been removed + /// from the target in the aforementioned function and we don't need to do anything else at this point. if (!m_vehicle) return; diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 58cf6773c59..c80d161f3e2 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -31,6 +31,8 @@ #include "MoveSplineInit.h" #include "TemporarySummon.h" #include "EventProcessor.h" +#include "Player.h" +#include "Battleground.h" Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) : _me(unit), _vehicleInfo(vehInfo), UsableSeatNum(0), _creatureEntry(creatureEntry), _status(STATUS_NONE) @@ -46,6 +48,12 @@ _me(unit), _vehicleInfo(vehInfo), UsableSeatNum(0), _creatureEntry(creatureEntry } } + // Set or remove correct flags based on available seats. Will overwrite db data (if wrong). + if (UsableSeatNum) + _me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); + else + _me->RemoveFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); + InitMovementInfoForBase(); } @@ -57,6 +65,15 @@ Vehicle::~Vehicle() ASSERT(!itr->second.Passenger); } +/** + * @fn void Vehicle::Install() + * + * @brief Initializes power type for vehicle. Nothing more. + * + * @author Machiavelli + * @date 17-2-2013 + */ + void Vehicle::Install() { if (Creature* creature = _me->ToCreature()) @@ -115,10 +132,20 @@ void Vehicle::InstallAllAccessories(bool evading) InstallAccessory(itr->AccessoryEntry, itr->SeatId, itr->IsMinion, itr->SummonedType, itr->SummonTime); } +/** + * @fn void Vehicle::Uninstall() + * + * @brief Removes all passengers and sets status to STATUS_UNINSTALLING. + * No new passengers can be added to the vehicle after this call. + * + * @author Machiavelli + * @date 17-2-2013 + */ + void Vehicle::Uninstall() { /// @Prevent recursive uninstall call. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.) - if (_status == STATUS_UNINSTALLING) + if (_status == STATUS_UNINSTALLING && !GetBase()->HasUnitTypeMask(UNIT_MASK_MINION)) { sLog->outError(LOG_FILTER_VEHICLES, "Vehicle GuidLow: %u, Entry: %u attempts to uninstall, but already has STATUS_UNINSTALLING! " "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), _me->GetEntry()); @@ -129,31 +156,43 @@ void Vehicle::Uninstall() sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Uninstall Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow()); RemoveAllPassengers(); - if (GetBase()->GetTypeId() == TYPEID_UNIT) sScriptMgr->OnUninstall(this); } +/** + * @fn void Vehicle::Reset(bool evading ) + * + * @brief Reapplies immunities and reinstalls accessories. Only has effect for creatures. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param evading true if called from CreatureAI::EnterEvadeMode + */ + void Vehicle::Reset(bool evading /*= false*/) { - sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Reset Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow()); - if (_me->GetTypeId() == TYPEID_PLAYER) - { - if (UsableSeatNum) - _me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); - } - else - { - ApplyAllImmunities(); - InstallAllAccessories(evading); - if (UsableSeatNum) - _me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - } + if (GetBase()->GetTypeId() != TYPEID_UNIT) + return; - if (GetBase()->GetTypeId() == TYPEID_UNIT) - sScriptMgr->OnReset(this); + sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Reset (Entry: %u, GuidLow: %u, DBGuid: %u)", GetCreatureEntry(), _me->GetGUIDLow(), _me->ToCreature()->GetDBTableGUIDLow()); + + ApplyAllImmunities(); + InstallAllAccessories(evading); + + sScriptMgr->OnReset(this); } +/** + * @fn void Vehicle::ApplyAllImmunities() + * + * @brief Applies specific immunities that cannot be set in DB. + * + * @author Machiavelli + * @date 17-2-2013 + */ + void Vehicle::ApplyAllImmunities() { // This couldn't be done in DB, because some spells have MECHANIC_NONE @@ -202,10 +241,28 @@ void Vehicle::ApplyAllImmunities() } } +/** + * @fn void Vehicle::RemoveAllPassengers() + * + * @brief Removes all current and pending passengers from the vehicle. + * + * @author Machiavelli + * @date 17-2-2013 + */ + void Vehicle::RemoveAllPassengers() { sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::RemoveAllPassengers. Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow()); + /// Setting to_Abort to true will cause @VehicleJoinEvent::Abort to be executed on next @Unit::UpdateEvents call + /// This will properly "reset" the pending join process for the passenger. + while (_pendingJoinEvents.size()) + { + VehicleJoinEvent* e = _pendingJoinEvents.front(); + e->to_Abort = true; + _pendingJoinEvents.pop_front(); + } + // Passengers always cast an aura with SPELL_AURA_CONTROL_VEHICLE on the vehicle // We just remove the aura and the unapply handler will make the target leave the vehicle. // We don't need to iterate over Seats @@ -218,18 +275,18 @@ void Vehicle::RemoveAllPassengers() // ASSERT(!itr->second.passenger); } -void Vehicle::RemovePendingPassengers() -{ - sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::RemovePendingPassengers. Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow()); - - /// Setting to_Abort to true will cause @VehicleJoinEvent::Abort to be executed on next @Unit::UpdateEvents call - /// This will properly "reset" the pending join process for the passenger. - while (VehicleJoinEvent* e = _pendingJoinEvents.front()) - { - e->to_Abort = true; - _pendingJoinEvents.pop_front(); - } -} +/** + * @fn bool Vehicle::HasEmptySeat(int8 seatId) const + * + * @brief Checks if vehicle's seat specified by 'seatId' is empty. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param seatId Identifier for the seat. + * + * @return true if empty seat, false if not. + */ bool Vehicle::HasEmptySeat(int8 seatId) const { @@ -239,6 +296,19 @@ bool Vehicle::HasEmptySeat(int8 seatId) const return !seat->second.Passenger; } +/** + * @fn Unit* Vehicle::GetPassenger(int8 seatId) const + * + * @brief Gets a passenger on specified seat. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param seatId Seat to look on. + * + * @return null if it not found, else pointer to passenger if in world + */ + Unit* Vehicle::GetPassenger(int8 seatId) const { SeatMap::const_iterator seat = Seats.find(seatId); @@ -248,78 +318,105 @@ Unit* Vehicle::GetPassenger(int8 seatId) const return ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger); } -int8 Vehicle::GetNextEmptySeat(int8 seatId, bool next) const +/** + * @fn SeatMap::const_iterator Vehicle::GetNextEmptySeat(int8 seatId, bool next) const + * + * @brief Gets the next empty seat based on current seat. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param seatId Identifier for the current seat. + * @param next true if iterating forward, false means iterating backwards. + * + * @return The next empty seat. + */ + +SeatMap::const_iterator Vehicle::GetNextEmptySeat(int8 seatId, bool next) const { SeatMap::const_iterator seat = Seats.find(seatId); if (seat == Seats.end()) - return -1; + return seat; while (seat->second.Passenger || (!seat->second.SeatInfo->CanEnterOrExit() && !seat->second.SeatInfo->IsUsableByOverride())) { if (next) { - ++seat; - if (seat == Seats.end()) + if (++seat == Seats.end()) seat = Seats.begin(); } else { - if (seat == Seats.begin()) + if (seat-- == Seats.begin()) seat = Seats.end(); - --seat; } + // Make sure we don't loop indefinetly if (seat->first == seatId) - return -1; // no available seat + return Seats.end(); } - return seat->first; + return seat; } +/** + * @fn void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 type, + * uint32 summonTime) + * + * @brief Installs an accessory. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param entry The NPC entry of accessory. + * @param seatId Identifier for the seat to add the accessory to. + * @param minion true if accessory considered a 'minion'. Implies that the accessory will despawn when the vehicle despawns. + * Essentially that it has no life without the vehicle. Their fates are bound. + * @param type See enum @SummonType. + * @param summonTime Time after which the minion is despawned in case of a timed despawn @type specified. + */ + void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 type, uint32 summonTime) { /// @Prevent adding accessories when vehicle is uninstalling. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.) if (_status == STATUS_UNINSTALLING) { - sLog->outError(LOG_FILTER_VEHICLES, "Vehicle GuidLow: %u, Entry: %u attempts to install accessory Entry: %u on seat %d with STATUS_UNINSTALLING! " - "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), _me->GetEntry(), entry, (int32)seatId); + sLog->outError(LOG_FILTER_VEHICLES, "Vehicle (GuidLow: %u, DB GUID: %u, Entry: %u) attempts to install accessory (Entry: %u) on seat %i with STATUS_UNINSTALLING! " + "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), + (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(), entry, (int32)seatId); return; } - sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle: Installing accessory entry %u on vehicle entry %u (seat:%i)", entry, GetCreatureEntry(), seatId); - if (Unit* passenger = GetPassenger(seatId)) - { - // already installed - if (passenger->GetEntry() == entry) - { - ASSERT(passenger->GetTypeId() == TYPEID_UNIT); - if (_me->GetTypeId() == TYPEID_UNIT) - { - if (_me->ToCreature()->IsInEvadeMode() && passenger->ToCreature()->IsAIEnabled) - passenger->ToCreature()->AI()->EnterEvadeMode(); - return; - } - } - else - passenger->ExitVehicle(); // this should not happen - } + sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle (GuidLow: %u, DB Guid: %u, Entry %u): installing accessory (Entry: %u) on seat: %i", + _me->GetGUIDLow(), (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(), + entry, (int32)seatId); - if (TempSummon* accessory = _me->SummonCreature(entry, *_me, TempSummonType(type), summonTime)) - { - if (minion) - accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY); + TempSummon* accessory = _me->SummonCreature(entry, *_me, TempSummonType(type), summonTime); + ASSERT(accessory); - if (!_me->HandleSpellClick(accessory, seatId)) - { - accessory->UnSummon(); - return; - } + if (minion) + accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY); - if (GetBase()->GetTypeId() == TYPEID_UNIT) - sScriptMgr->OnInstallAccessory(this, accessory); - } + (void)_me->HandleSpellClick(accessory, seatId); + + /// If for some reason adding accessory to vehicle fails it will unsummon in + /// @VehicleJoinEvent::Abort } +/** + * @fn bool Vehicle::AddPassenger(Unit* unit, int8 seatId) + * + * @brief Attempts to add a passenger to the vehicle on 'seatId'. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param [in,out] The prospective passenger. + * @param seatId Identifier for the seat. Value of -1 indicates the next available seat. + * + * @return true if it succeeds, false if it fails. + */ + bool Vehicle::AddPassenger(Unit* unit, int8 seatId) { /// @Prevent adding passengers when vehicle is uninstalling. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.) @@ -330,16 +427,15 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) return false; } - if (unit->GetVehicle() != this) - return false; + sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle (entry: %u, vehicleId: %u, guid: %u (dbguid: %s) on seat %d", + unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), + (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : 0), seatId); // The seat selection code may kick other passengers off the vehicle. // While the validity of the following may be arguable, it is possible that when such a passenger // exits the vehicle will dismiss. That's why the actual adding the passenger to the vehicle is scheduled // asynchronously, so it can be cancelled easily in case the vehicle is uninstalled meanwhile. SeatMap::iterator seat; - sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle entry %u id %u dbguid %u seat %d", - unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), seatId); VehicleJoinEvent* e = new VehicleJoinEvent(this, unit); unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0)); _pendingJoinEvents.push_back(e); @@ -370,10 +466,9 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) e->Seat = seat; if (seat->second.Passenger) { - if (Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger)) - passenger->ExitVehicle(); - else - seat->second.Passenger = 0; + Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger); + ASSERT(passenger); + passenger->ExitVehicle(); } ASSERT(!seat->second.Passenger); @@ -382,6 +477,17 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) return true; } +/** + * @fn void Vehicle::RemovePassenger(Unit* unit) + * + * @brief Removes the passenger from the vehicle. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param [in,out] unit The passenger to remove.. + */ + void Vehicle::RemovePassenger(Unit* unit) { if (unit->GetVehicle() != this) @@ -390,20 +496,12 @@ void Vehicle::RemovePassenger(Unit* unit) SeatMap::iterator seat = GetSeatIteratorForPassenger(unit); ASSERT(seat != Seats.end()); - sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s exit vehicle entry %u id %u dbguid %u seat %d", unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first); + sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s exit vehicle entry %u id %u dbguid %u seat %d", + unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first); seat->second.Passenger = 0; - if (seat->second.SeatInfo->CanEnterOrExit()) - { - if (!UsableSeatNum) - { - if (_me->GetTypeId() == TYPEID_PLAYER) - _me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); - else - _me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - } - ++UsableSeatNum; - } + if (seat->second.SeatInfo->CanEnterOrExit() && ++UsableSeatNum) + _me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); unit->ClearUnitState(UNIT_STATE_ONVEHICLE); @@ -413,7 +511,7 @@ void Vehicle::RemovePassenger(Unit* unit) if (_me->IsInWorld()) { unit->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); - unit->m_movementInfo.t_pos.Relocate(0, 0, 0, 0); + unit->m_movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); unit->m_movementInfo.t_time = 0; unit->m_movementInfo.t_seat = 0; } @@ -429,7 +527,15 @@ void Vehicle::RemovePassenger(Unit* unit) sScriptMgr->OnRemovePassenger(this, unit); } -//! Must be called after m_base::Relocate +/** + * @fn void Vehicle::RelocatePassengers() + * + * @brief Relocate passengers. Must be called after m_base::Relocate + * + * @author Machiavelli + * @date 17-2-2013 + */ + void Vehicle::RelocatePassengers() { ASSERT(_me->GetMap()); @@ -449,16 +555,34 @@ void Vehicle::RelocatePassengers() } } +/** + * @fn void Vehicle::Dismiss() + * + * @brief Dismiss the vehicle. Removes passengers and despawns self. Only valid for creatures. + * + * @author Machiavelli + * @date 17-2-2013 + */ + void Vehicle::Dismiss() { if (GetBase()->GetTypeId() != TYPEID_UNIT) return; - sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Dismiss Entry: %u, GuidLow %u", _creatureEntry, _me->GetGUIDLow()); + sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Dismiss Entry: %u, GuidLow %u, DBGuid: %u", GetCreatureEntry(), _me->GetGUIDLow(), _me->ToCreature()->GetDBTableGUIDLow()); Uninstall(); GetBase()->ToCreature()->DespawnOrUnsummon(); } +/** + * @fn void Vehicle::InitMovementInfoForBase() + * + * @brief Sets correct MovementFlags2 based on VehicleFlags from DBC. + * + * @author Machiavelli + * @date 17-2-2013 + */ + void Vehicle::InitMovementInfoForBase() { uint32 vehicleFlags = GetVehicleInfo()->m_flags; @@ -475,6 +599,19 @@ void Vehicle::InitMovementInfoForBase() _me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_FULL_SPEED_PITCHING); } +/** + * @fn VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit* passenger) + * + * @brief Returns information on the seat of specified passenger, represented by the format in VehicleSeat.dbc + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param [in,out] The passenger for which we check the seat info. + * + * @return null if passenger not found on vehicle, else the DBC record for the seat. + */ + VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit* passenger) { SeatMap::iterator itr; @@ -485,6 +622,19 @@ VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit* passenger) return NULL; } +/** + * @fn SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger) + * + * @brief Gets seat iterator for specified passenger. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param [in,out] passenger Passenger to look up. + * + * @return The seat iterator for specified passenger if it's found on the vehicle. Otherwise Seats.end() (invalid iterator). + */ + SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger) { SeatMap::iterator itr; @@ -495,6 +645,17 @@ SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger) return Seats.end(); } +/** + * @fn uint8 Vehicle::GetAvailableSeatCount() const + * + * @brief Gets the available seat count. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @return The available seat count. + */ + uint8 Vehicle::GetAvailableSeatCount() const { uint8 ret = 0; @@ -526,17 +687,45 @@ void Vehicle::CalculatePassengerOffset(float& x, float& y, float& z, float& o) x = (inx + iny * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation())); } +/** + * @fn void Vehicle::CancelJoinEvent(VehicleJoinEvent* e) + * + * @brief Aborts delayed @VehicleJoinEvent objects. + * Implies that the related unit will not be boarding the vehicle after all. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param [in,out] e The VehicleJoinEvent* to process. + */ + void Vehicle::CancelJoinEvent(VehicleJoinEvent* e) { e->to_Abort = true; _pendingJoinEvents.pop_back(); } +/** + * @fn bool VehicleJoinEvent::Execute(uint64, uint32) + * + * @brief Actually adds the passenger @Passenger to vehicle @Target. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param parameter1 Unused + * @param parameter2 Unused. + * + * @return true, cannot fail. + * + */ + bool VehicleJoinEvent::Execute(uint64, uint32) { - ASSERT(Passenger->GetVehicle() == Target); - Passenger->m_vehicle = Target; + ASSERT(Passenger->IsInWorld()); + ASSERT(Target->GetBase()->IsInWorld()); + Passenger->m_vehicle = Target; Seat->second.Passenger = Passenger->GetGUID(); if (Seat->second.SeatInfo->CanEnterOrExit()) { @@ -551,55 +740,85 @@ bool VehicleJoinEvent::Execute(uint64, uint32) } } + Passenger->InterruptNonMeleeSpells(false); + + Player* player = Passenger->ToPlayer(); + if (player) + { + // drop flag + if (Battleground* bg = player->GetBattleground()) + bg->EventPlayerDroppedFlag(player); + + WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); + player->GetSession()->SendPacket(&data); + player->UnsummonPetTemporaryIfAny(); + } + if (Seat->second.SeatInfo->m_flags && !(Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)) Passenger->AddUnitState(UNIT_STATE_ONVEHICLE); Passenger->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); VehicleSeatEntry const* veSeat = Seat->second.SeatInfo; - Passenger->m_movementInfo.t_pos.m_positionX = veSeat->m_attachmentOffsetX; - Passenger->m_movementInfo.t_pos.m_positionY = veSeat->m_attachmentOffsetY; - Passenger->m_movementInfo.t_pos.m_positionZ = veSeat->m_attachmentOffsetZ; - Passenger->m_movementInfo.t_pos.SetOrientation(0.0f); + Passenger->m_movementInfo.t_pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); Passenger->m_movementInfo.t_time = 0; // 1 for player Passenger->m_movementInfo.t_seat = Seat->first; Passenger->m_movementInfo.t_guid = Target->GetBase()->GetGUID(); if (Target->GetBase()->GetTypeId() == TYPEID_UNIT && Passenger->GetTypeId() == TYPEID_PLAYER && Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL) - ASSERT(Target->GetBase()->SetCharmedBy(Passenger, CHARM_TYPE_VEHICLE)) + ASSERT(Target->GetBase()->SetCharmedBy(Passenger, CHARM_TYPE_VEHICLE)) // SMSG_CLIENT_CONTROL + + Passenger->SendClearTarget(); // SMSG_BREAK_TARGET + Passenger->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) + // also adds MOVEMENTFLAG_ROOT + + Movement::MoveSplineInit init(Passenger); + init.DisableTransportPathTransformations(); + init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); + init.SetFacing(0.0f); + init.SetTransportEnter(); + init.Launch(); - if (Target->GetBase()->IsInWorld()) + if (Target->GetBase()->GetTypeId() == TYPEID_UNIT) { - Passenger->SendClearTarget(); // SMSG_BREAK_TARGET - Passenger->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) - // also adds MOVEMENTFLAG_ROOT - Movement::MoveSplineInit init(Passenger); - init.DisableTransportPathTransformations(); - init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); - init.SetFacing(0.0f); - init.SetTransportEnter(); - init.Launch(); - - if (Target->GetBase()->GetTypeId() == TYPEID_UNIT) - { - if (Target->GetBase()->ToCreature()->IsAIEnabled) - Target->GetBase()->ToCreature()->AI()->PassengerBoarded(Passenger, Seat->first, true); - - // update all passenger's positions - //Passenger's spline OR vehicle movement will update positions - //RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation()); - } - } + if (Target->GetBase()->ToCreature()->IsAIEnabled) + Target->GetBase()->ToCreature()->AI()->PassengerBoarded(Passenger, Seat->first, true); - if (Target->GetBase()->GetTypeId() == TYPEID_UNIT) sScriptMgr->OnAddPassenger(Target, Passenger, Seat->first); + // Actually quite a redundant hook. Could just use OnAddPassenger and check for unit typemask inside script. + if (Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY)) + sScriptMgr->OnInstallAccessory(Target, Passenger->ToCreature()); + + // update all passenger's positions + //Passenger's spline OR vehicle movement will update positions + //RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation()); + } + return true; } +/** + * @fn void VehicleJoinEvent::Abort(uint64) + * + * @brief Aborts the event. Implies that unit @Passenger will not be boarding vehicle @Target after all. + * + * @author Machiavelli + * @date 17-2-2013 + * + * @param parameter1 Unused + */ + void VehicleJoinEvent::Abort(uint64) { sLog->outDebug(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %i cancelled", Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first); - // Passenger->m_vehicle = NULL; + + /// @SPELL_AURA_CONTROL_VEHICLE auras can be applied even when the passenger is not (yet) on the vehicle. + /// When this code is triggered it means that something went wrong in @Vehicle::AddPassenger, and we should remove + /// the aura manually. + Target->GetBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, Passenger->GetGUID()); + + if (Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY)) + Passenger->ToTempSummon()->UnSummon(); } diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index dbdd021a384..7ec0df8e533 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -46,7 +46,7 @@ class Vehicle : public TransportBase bool HasEmptySeat(int8 seatId) const; Unit* GetPassenger(int8 seatId) const; - int8 GetNextEmptySeat(int8 seatId, bool next) const; + SeatMap::const_iterator GetNextEmptySeat(int8 seatId, bool next) const; uint8 GetAvailableSeatCount() const; bool AddPassenger(Unit* passenger, int8 seatId = -1); @@ -54,7 +54,6 @@ class Vehicle : public TransportBase void RemovePassenger(Unit* passenger); void RelocatePassengers(); void RemoveAllPassengers(); - void RemovePendingPassengers(); void Dismiss(); void TeleportVehicle(float x, float y, float z, float ang); bool IsVehicleInUse() { return Seats.begin() != Seats.end(); } @@ -62,13 +61,13 @@ class Vehicle : public TransportBase void SetLastShootPos(Position const& pos) { m_lastShootPos.Relocate(pos); } Position GetLastShootPos() { return m_lastShootPos; } - SeatMap Seats; + SeatMap Seats; ///< The collection of all seats on the vehicle. Including vacant ones. VehicleSeatEntry const* GetSeatForPassenger(Unit* passenger); protected: friend class VehicleJoinEvent; - uint32 UsableSeatNum; // Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags + uint32 UsableSeatNum; ///< Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags protected: friend bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry); @@ -93,15 +92,14 @@ class Vehicle : public TransportBase /// This method transforms supplied global coordinates into local offsets void CalculatePassengerOffset(float& x, float& y, float& z, float& o); - Unit* _me; - VehicleEntry const* _vehicleInfo; + Unit* _me; ///< The underlying unit with the vehicle kit. Can be player or creature. + VehicleEntry const* _vehicleInfo; ///< DBC data for vehicle GuidSet vehiclePlayers; - uint32 _creatureEntry; // Can be different than me->GetBase()->GetEntry() in case of players - Status _status; + uint32 _creatureEntry; ///< Can be different than the entry of _me in case of players + Status _status; ///< Internal variable for sanity checks Position m_lastShootPos; - - std::deque _pendingJoinEvents; + std::deque _pendingJoinEvents; ///< Collection of delayed join events for prospective passengers void CancelJoinEvent(VehicleJoinEvent* e); }; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 6272f42ec8c..c7299be2853 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1587,8 +1587,7 @@ void WorldSession::HandleCancelMountAuraOpcode(WorldPacket& /*recvData*/) return; } - _player->Dismount(); - _player->RemoveAurasByType(SPELL_AURA_MOUNTED); + _player->RemoveAurasByType(SPELL_AURA_MOUNTED); // Calls Dismount() } void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData) -- cgit v1.2.3 From 9004d39c09081e40fc6b18a356f1c9d79bc76ee3 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Mon, 18 Feb 2013 00:56:25 +0100 Subject: Core: Whitespace cleanup --- src/server/game/Accounts/AccountMgr.cpp | 2 +- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Entities/Vehicle/Vehicle.cpp | 28 ++++++++++++++-------------- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index b1d0087c32c..036cff1902d 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -1,4 +1,4 @@ -/* + /* * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2009 MaNGOS * diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 53f9a948edf..fa7ef5189fb 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -16601,7 +16601,7 @@ void Unit::ChangeSeat(int8 seatId, bool next) // The second part of the check will only return true if seatId >= 0. @Vehicle::GetNextEmptySeat makes sure of that. if (seat == m_vehicle->Seats.end() || seat->second.Passenger) return; - + // Todo: the functions below could be consolidated and refactored to take // SeatMap::const_iterator as parameter, to save redundant map lookups. m_vehicle->RemovePassenger(this); diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index c80d161f3e2..c70d6413886 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -136,7 +136,7 @@ void Vehicle::InstallAllAccessories(bool evading) * @fn void Vehicle::Uninstall() * * @brief Removes all passengers and sets status to STATUS_UNINSTALLING. - * No new passengers can be added to the vehicle after this call. + * No new passengers can be added to the vehicle after this call. * * @author Machiavelli * @date 17-2-2013 @@ -177,7 +177,7 @@ void Vehicle::Reset(bool evading /*= false*/) return; sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Reset (Entry: %u, GuidLow: %u, DBGuid: %u)", GetCreatureEntry(), _me->GetGUIDLow(), _me->ToCreature()->GetDBTableGUIDLow()); - + ApplyAllImmunities(); InstallAllAccessories(evading); @@ -370,8 +370,8 @@ SeatMap::const_iterator Vehicle::GetNextEmptySeat(int8 seatId, bool next) const * * @param entry The NPC entry of accessory. * @param seatId Identifier for the seat to add the accessory to. - * @param minion true if accessory considered a 'minion'. Implies that the accessory will despawn when the vehicle despawns. - * Essentially that it has no life without the vehicle. Their fates are bound. + * @param minion true if accessory considered a 'minion'. Implies that the accessory will despawn when the vehicle despawns. + * Essentially that it has no life without the vehicle. Their fates are bound. * @param type See enum @SummonType. * @param summonTime Time after which the minion is despawned in case of a timed despawn @type specified. */ @@ -382,7 +382,7 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ if (_status == STATUS_UNINSTALLING) { sLog->outError(LOG_FILTER_VEHICLES, "Vehicle (GuidLow: %u, DB GUID: %u, Entry: %u) attempts to install accessory (Entry: %u) on seat %i with STATUS_UNINSTALLING! " - "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), + "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(), entry, (int32)seatId); return; } @@ -428,7 +428,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) } sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle (entry: %u, vehicleId: %u, guid: %u (dbguid: %s) on seat %d", - unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), + unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : 0), seatId); // The seat selection code may kick other passengers off the vehicle. @@ -496,7 +496,7 @@ void Vehicle::RemovePassenger(Unit* unit) SeatMap::iterator seat = GetSeatIteratorForPassenger(unit); ASSERT(seat != Seats.end()); - sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s exit vehicle entry %u id %u dbguid %u seat %d", + sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s exit vehicle entry %u id %u dbguid %u seat %d", unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first); seat->second.Passenger = 0; @@ -690,8 +690,8 @@ void Vehicle::CalculatePassengerOffset(float& x, float& y, float& z, float& o) /** * @fn void Vehicle::CancelJoinEvent(VehicleJoinEvent* e) * - * @brief Aborts delayed @VehicleJoinEvent objects. - * Implies that the related unit will not be boarding the vehicle after all. + * @brief Aborts delayed @VehicleJoinEvent objects. + * Implies that the related unit will not be boarding the vehicle after all. * * @author Machiavelli * @date 17-2-2013 @@ -717,7 +717,7 @@ void Vehicle::CancelJoinEvent(VehicleJoinEvent* e) * @param parameter2 Unused. * * @return true, cannot fail. - * + * */ bool VehicleJoinEvent::Execute(uint64, uint32) @@ -745,7 +745,7 @@ bool VehicleJoinEvent::Execute(uint64, uint32) Player* player = Passenger->ToPlayer(); if (player) { - // drop flag + // drop flag if (Battleground* bg = player->GetBattleground()) bg->EventPlayerDroppedFlag(player); @@ -771,7 +771,7 @@ bool VehicleJoinEvent::Execute(uint64, uint32) Passenger->SendClearTarget(); // SMSG_BREAK_TARGET Passenger->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) // also adds MOVEMENTFLAG_ROOT - + Movement::MoveSplineInit init(Passenger); init.DisableTransportPathTransformations(); init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); @@ -814,11 +814,11 @@ void VehicleJoinEvent::Abort(uint64) sLog->outDebug(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %i cancelled", Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first); - /// @SPELL_AURA_CONTROL_VEHICLE auras can be applied even when the passenger is not (yet) on the vehicle. + /// @SPELL_AURA_CONTROL_VEHICLE auras can be applied even when the passenger is not (yet) on the vehicle. /// When this code is triggered it means that something went wrong in @Vehicle::AddPassenger, and we should remove /// the aura manually. Target->GetBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, Passenger->GetGUID()); - + if (Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY)) Passenger->ToTempSummon()->UnSummon(); } -- cgit v1.2.3 From cc8d5a3aca73698455e636c47a46244b09f2bc5c Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Mon, 18 Feb 2013 02:20:42 +0100 Subject: Core/Vehicles: Prevent infinite loop in VehicleJoinEvent:Abort --- src/server/game/Entities/Vehicle/Vehicle.cpp | 5 +++++ src/server/game/Entities/Vehicle/Vehicle.h | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index c70d6413886..9dd25577fe1 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -811,6 +811,11 @@ bool VehicleJoinEvent::Execute(uint64, uint32) void VehicleJoinEvent::Abort(uint64) { + // Prevent recursion + if (_executedAbort) + return; + + _executedAbort = true; sLog->outDebug(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %i cancelled", Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first); diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 7ec0df8e533..01b8a0c581f 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -107,12 +107,15 @@ class VehicleJoinEvent : public BasicEvent { friend class Vehicle; protected: - VehicleJoinEvent(Vehicle* v, Unit* u) : Target(v), Passenger(u), Seat(Target->Seats.end()) {} + VehicleJoinEvent(Vehicle* v, Unit* u) : Target(v), Passenger(u), Seat(Target->Seats.end()), _executedAbort(false) {} bool Execute(uint64, uint32); void Abort(uint64); Vehicle* Target; Unit* Passenger; SeatMap::iterator Seat; + + private: + bool _executedAbort; }; #endif -- cgit v1.2.3 From 2144f0fd8e4c93aa9f2fc8d5630db2899171879d Mon Sep 17 00:00:00 2001 From: Shauren Date: Mon, 18 Feb 2013 12:23:46 +0100 Subject: Core/Scripts: Correct orders of parameters used in OnGroupChangeLeader script hook --- src/server/game/Groups/Group.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index eb2d33c63a0..fe06c172e3f 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -634,7 +634,7 @@ void Group::ChangeLeader(uint64 guid) if (!player) return; - sScriptMgr->OnGroupChangeLeader(this, m_leaderGuid, guid); + sScriptMgr->OnGroupChangeLeader(this, guid, m_leaderGuid); if (!isBGGroup() && !isBFGroup()) { -- cgit v1.2.3 From 87d4e8c0673c6482b27bd2135a1e3c04874eb0ca Mon Sep 17 00:00:00 2001 From: Nay Date: Mon, 18 Feb 2013 00:45:18 +0000 Subject: Core/Config: Change CONFIG_EVENT_ANNOUNCE from int to bool Also correct the description of BeepAtStart, it works in Windows as well --- src/server/game/Events/GameEventMgr.cpp | 14 ++++---------- src/server/game/World/World.cpp | 2 +- src/server/game/World/World.h | 2 +- src/server/worldserver/worldserver.conf.dist | 2 +- 4 files changed, 7 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index de3038cef1e..95ed06bff37 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -1102,14 +1102,8 @@ void GameEventMgr::UnApplyEvent(uint16 event_id) void GameEventMgr::ApplyNewEvent(uint16 event_id) { - switch (sWorld->getIntConfig(CONFIG_EVENT_ANNOUNCE)) - { - case 0: // disable - break; - case 1: // announce events - sWorld->SendWorldText(LANG_EVENTMESSAGE, mGameEvent[event_id].description.c_str()); - break; - } + if (sWorld->getBoolConfig(CONFIG_EVENT_ANNOUNCE)) + sWorld->SendWorldText(LANG_EVENTMESSAGE, mGameEvent[event_id].description.c_str()); sLog->outInfo(LOG_FILTER_GAMEEVENTS, "GameEvent %u \"%s\" started.", event_id, mGameEvent[event_id].description.c_str()); @@ -1331,7 +1325,7 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate) itr->second.equipement_id_prev = creature->GetCurrentEquipmentId(); itr->second.modelid_prev = creature->GetDisplayId(); creature->LoadEquipment(itr->second.equipment_id, true); - if (itr->second.modelid >0 && itr->second.modelid_prev != itr->second.modelid) + if (itr->second.modelid > 0 && itr->second.modelid_prev != itr->second.modelid) { CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(itr->second.modelid); if (minfo) @@ -1346,7 +1340,7 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate) else { creature->LoadEquipment(itr->second.equipement_id_prev, true); - if (itr->second.modelid_prev >0 && itr->second.modelid_prev != itr->second.modelid) + if (itr->second.modelid_prev > 0 && itr->second.modelid_prev != itr->second.modelid) { CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(itr->second.modelid_prev); if (minfo) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index d02ba402c53..d8eec66ea07 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -955,7 +955,7 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = ConfigMgr::GetIntDefault("ChatFlood.MessageDelay", 1); m_int_configs[CONFIG_CHATFLOOD_MUTE_TIME] = ConfigMgr::GetIntDefault("ChatFlood.MuteTime", 10); - m_int_configs[CONFIG_EVENT_ANNOUNCE] = ConfigMgr::GetIntDefault("Event.Announce", 0); + m_bool_configs[CONFIG_EVENT_ANNOUNCE] = ConfigMgr::GetIntDefault("Event.Announce", false); m_float_configs[CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS] = ConfigMgr::GetFloatDefault("CreatureFamilyFleeAssistanceRadius", 30.0f); m_float_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS] = ConfigMgr::GetFloatDefault("CreatureFamilyAssistanceRadius", 10.0f); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index b955af7d863..612078f17bf 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -166,6 +166,7 @@ enum WorldBoolConfigs CONFIG_ENABLE_MMAPS, CONFIG_WINTERGRASP_ENABLE, CONFIG_UI_QUESTLEVELS_IN_DIALOGS, // Should we add quest levels to the title in the NPC dialogs? + CONFIG_EVENT_ANNOUNCE, BOOL_CONFIG_VALUE_COUNT }; @@ -253,7 +254,6 @@ enum WorldIntConfigs CONFIG_CHATFLOOD_MESSAGE_COUNT, CONFIG_CHATFLOOD_MESSAGE_DELAY, CONFIG_CHATFLOOD_MUTE_TIME, - CONFIG_EVENT_ANNOUNCE, CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY, CONFIG_CREATURE_FAMILY_FLEE_DELAY, CONFIG_WORLD_BOSS_LEVEL_DIFF, diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index e519a53a5af..dfc7e83f250 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1054,7 +1054,7 @@ Event.Announce = 0 # # BeepAtStart -# Description: Beep when the world server finished starting (Unix/Linux systems). +# Description: Beep when the world server finished starting. # Default: 1 - (Enabled) # 0 - (Disabled) -- cgit v1.2.3 From 028c72a9f2c606e8af391d284931c60247ad0160 Mon Sep 17 00:00:00 2001 From: Nay Date: Mon, 18 Feb 2013 12:24:18 +0000 Subject: Core/NPCs: Refactor equipments - creature_template.equipment_id deleted - creature_equip_template.entry == creature_template.entry - id field added to creature_equip_template -> PK(entry, id) - id field in creature_equip_template starts at 1 - creature.equipment_id references id of creature_equip_template - creature.equipment_id = 0 means no equipment at all (default 1) - creature.equipment_id = -1 means pick a random equipment from creature_equip_template - add equipment info to .npc info command While table creature_equip_template got bigger in size, this system is easier to mantain and allows creatures to have a random template from a group of equipments --- .../world/2013_02_18_00_world_misc_equip.sql | 73 +++++++++++++++++++ .../world/2013_02_18_01_world_trinity_string.sql | 3 + src/server/game/AI/ScriptedAI/ScriptedCreature.cpp | 4 +- src/server/game/AI/SmartScripts/SmartScript.cpp | 15 ++-- src/server/game/Entities/Creature/Creature.cpp | 20 +++--- src/server/game/Entities/Creature/Creature.h | 17 +++-- src/server/game/Events/GameEventMgr.cpp | 20 +++--- src/server/game/Events/GameEventMgr.h | 4 +- src/server/game/Globals/ObjectMgr.cpp | 82 +++++++++++++--------- src/server/game/Globals/ObjectMgr.h | 2 +- src/server/game/Miscellaneous/Language.h | 3 +- src/server/game/Spells/SpellEffects.cpp | 2 +- src/server/game/World/World.cpp | 6 +- src/server/scripts/Commands/cs_npc.cpp | 1 + src/server/scripts/Commands/cs_reload.cpp | 7 +- .../EasternKingdoms/ScarletEnclave/chapter1.cpp | 6 +- .../EasternKingdoms/ScarletEnclave/chapter2.cpp | 2 +- .../SerpentShrine/boss_leotheras_the_blind.cpp | 8 +-- .../Database/Implementation/WorldDatabase.cpp | 2 +- 19 files changed, 186 insertions(+), 91 deletions(-) create mode 100644 sql/updates/world/2013_02_18_00_world_misc_equip.sql create mode 100644 sql/updates/world/2013_02_18_01_world_trinity_string.sql (limited to 'src') diff --git a/sql/updates/world/2013_02_18_00_world_misc_equip.sql b/sql/updates/world/2013_02_18_00_world_misc_equip.sql new file mode 100644 index 00000000000..a5964cd883b --- /dev/null +++ b/sql/updates/world/2013_02_18_00_world_misc_equip.sql @@ -0,0 +1,73 @@ +-- creature_template.equipment_id deleted +-- creature_equip_template.entry == creature_template.entry +-- id field added to creature_equip_template -> PK(entry, id) +-- id field in creature_equip_template starts at 1 +-- creature.equipment_id references id of creature_equip_template +-- creature.equipment_id = 0 means no equipment at all (default 1) +-- creature.equipment_id = -1 means pick a random equipment from creature_equip_template + +-- Diff_entries should use the same template of the normal entry +UPDATE `creature_template` SET `equipment_id` = 0 WHERE `name` LIKE '%(1)' OR `name` LIKE '%(2)' OR `name` LIKE '%(3)' OR `name` LIKE '%(4)'; + +-- Delete unused templates +DROP TABLE IF EXISTS `temp_c_e`; +CREATE TABLE IF NOT EXISTS `temp_c_e` (`entry` mediumint(8)); +ALTER TABLE `temp_c_e` ADD INDEX `ind` (`entry`); +INSERT INTO `temp_c_e` SELECT `equipment_id` FROM `creature_template` WHERE `equipment_id` != 0 UNION + SELECT `equipment_id` FROM `creature` WHERE `equipment_id` != 0 UNION + SELECT `equipment_id` FROM `game_event_model_equip` WHERE `equipment_id` != 0; +DELETE FROM `creature_equip_template` WHERE `entry` NOT IN (SELECT `entry` FROM `temp_c_e`); +DROP TABLE `temp_c_e`; + +-- Create temporary table to hold the values of creature_equip_template with converted entry +DROP TABLE IF EXISTS `creature_equip_template2`; +CREATE TABLE IF NOT EXISTS `creature_equip_template2` ( + `entry` mediumint(8) unsigned NOT NULL DEFAULT '0', + `id` tinyint(3) unsigned NOT NULL DEFAULT '1', + `itemEntry1` mediumint(8) unsigned NOT NULL DEFAULT '0', + `itemEntry2` mediumint(8) unsigned NOT NULL DEFAULT '0', + `itemEntry3` mediumint(8) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`entry`, `id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `creature_equip_template2` (`entry`, `id`, `itemEntry1`, `itemEntry2`, `itemEntry3`) + SELECT `creature_template`.`entry`, 1, `itemEntry1`, `itemEntry2`, `itemEntry3` + FROM `creature_template` + JOIN `creature_equip_template` ON `creature_equip_template`.`entry` = `equipment_id` + WHERE `equipment_id` != 0; + +INSERT IGNORE INTO `creature_equip_template2` (`entry`, `id`, `itemEntry1`, `itemEntry2`, `itemEntry3`) + SELECT `id`, 2, `itemEntry1`, `itemEntry2`, `itemEntry3` + FROM `creature` + JOIN `creature_equip_template` ON `creature_equip_template`.`entry` = `equipment_id` + WHERE `equipment_id` != 0; + +DROP TABLE `creature_equip_template`; +RENAME TABLE `creature_equip_template2` TO `creature_equip_template`; + +UPDATE `creature` SET `equipment_id` = 2 WHERE `equipment_id` != 0; +UPDATE `creature` SET `equipment_id` = 1 WHERE `equipment_id` = 0; + +-- From game_event_model_equip +UPDATE `creature` SET `equipment_id` = 1 WHERE `guid` IN (12088, 12093, 12095, 79670, 79675, 79676, 79690, 79792, 79807, 79814); +UPDATE `game_event_model_equip` SET `equipment_id` = 2 WHERE `guid` IN (12088, 12093, 12095, 79670, 79675, 79676, 79690, 79792, 79807, 79814); +DELETE FROM `creature_equip_template` WHERE `entry` IN (1976, 23585, 424) AND `id`=2; +INSERT INTO `creature_equip_template` (`entry`, `id`, `itemEntry1`, `itemEntry2`, `itemEntry3`) VALUES +(1976, 2, 2715, 143, 0), +(23585, 2, 2715, 143, 0), +(424, 2, 2715, 143, 0); + +-- ALTER TABLE `creature_equip_template` CHANGE `entry` `entry` mediumint(8) unsigned NOT NULL; +-- ALTER TABLE `creature_equip_template` ADD `id` tinyint(3) unsigned NOT NULL DEFAULT '1' AFTER `entry`; +-- ALTER TABLE `creature_equip_template` DROP INDEX `PRIMARY`, ADD PRIMARY KEY (`entry`, `id`); +ALTER TABLE `creature_template` DROP `equipment_id`; +ALTER TABLE `creature` CHANGE `equipment_id` `equipment_id` tinyint(3) unsigned NOT NULL DEFAULT '1'; +ALTER TABLE `game_event_model_equip` CHANGE `equipment_id` `equipment_id` tinyint(3) unsigned NOT NULL DEFAULT '1'; + +-- Conversion from SAI +UPDATE `smart_scripts` SET `action_param1` = 1 WHERE `entryorguid` = 2523901 AND `source_type` = 9 AND `id` = 3; +UPDATE `smart_scripts` SET `action_param1` = 0 WHERE `entryorguid` = 2523900 AND `source_type` = 9 AND `id` = 2; +UPDATE `smart_scripts` SET `action_param1` = 2 WHERE `entryorguid` = 32720 AND `source_type` = 0 AND `id` = 0; +DELETE FROM `creature_equip_template` WHERE `entry` = 25239 AND `id`=1; +INSERT INTO `creature_equip_template` (`entry`, `id`, `itemEntry1`, `itemEntry2`, `itemEntry3`) VALUES +(25239, 1, 6829, 0, 0); diff --git a/sql/updates/world/2013_02_18_01_world_trinity_string.sql b/sql/updates/world/2013_02_18_01_world_trinity_string.sql new file mode 100644 index 00000000000..84d28222fe7 --- /dev/null +++ b/sql/updates/world/2013_02_18_01_world_trinity_string.sql @@ -0,0 +1,3 @@ +DELETE FROM `trinity_string` WHERE `entry` = 5036; +INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES +(5036, 'EquipmentId: %u (Original: %u).'); diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index 6c947d11f07..2da40f287a5 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -370,9 +370,7 @@ void ScriptedAI::SetEquipmentSlots(bool loadDefault, int32 mainHand /*= EQUIP_NO { if (loadDefault) { - if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(me->GetEntry())) - me->LoadEquipment(creatureInfo->equipmentId, true); - + me->LoadEquipment(me->GetOriginalEquipmentId(), true); return; } diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 80388ce0be9..bc94169687c 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -1459,15 +1459,16 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (Creature* npc = (*itr)->ToCreature()) { uint32 slot[3]; - if (e.action.equip.entry) + int8 equipId = (int8)e.action.equip.entry; + if (equipId) { - EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(e.action.equip.entry); + EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(npc->GetEntry(), equipId); if (!einfo) { - sLog->outError(LOG_FILTER_SQL, "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info entry %u", e.action.equip.entry); + sLog->outError(LOG_FILTER_SQL, "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id %u for creature %u", equipId, npc->GetEntry()); return; } - npc->SetCurrentEquipmentId(e.action.equip.entry); + npc->SetCurrentEquipmentId(equipId); slot[0] = einfo->ItemEntry[0]; slot[1] = einfo->ItemEntry[1]; slot[2] = einfo->ItemEntry[2]; @@ -1478,11 +1479,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u slot[1] = e.action.equip.slot2; slot[2] = e.action.equip.slot3; } - if (!e.action.equip.mask || e.action.equip.mask & 1) + if (!e.action.equip.mask || (e.action.equip.mask & 1)) npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, slot[0]); - if (!e.action.equip.mask || e.action.equip.mask & 2) + if (!e.action.equip.mask || (e.action.equip.mask & 2)) npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, slot[1]); - if (!e.action.equip.mask || e.action.equip.mask & 4) + if (!e.action.equip.mask || (e.action.equip.mask & 4)) npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, slot[2]); } } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 0bcb2d76055..9b991393c6e 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -145,7 +145,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapCreature(), lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0), m_lootRecipient(0), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(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_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(1), m_originalEquipmentId(1), 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_path_id(0), m_formation(NULL) { @@ -323,8 +323,8 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data // Load creature equipment if (!data || data->equipmentId == 0) // use default from the template - LoadEquipment(cinfo->equipmentId); - else if (data && data->equipmentId != -1) // override, -1 means no equipment + LoadEquipment(GetOriginalEquipmentId()); + else if (data && data->equipmentId != 0) // override, 0 means no equipment LoadEquipment(data->equipmentId); SetName(normalInfo->Name); // at normal entry always @@ -1089,7 +1089,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) data.mapid = mapid; data.phaseMask = phaseMask; data.displayid = displayId; - data.equipmentId = GetEquipmentId(); + data.equipmentId = GetCurrentEquipmentId(); data.posX = GetPositionX(); data.posY = GetPositionY(); data.posZ = GetPositionZMinusOffset(); @@ -1124,7 +1124,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) stmt->setUInt8(index++, spawnMask); stmt->setUInt16(index++, uint16(GetPhaseMask())); stmt->setUInt32(index++, displayId); - stmt->setInt32(index++, int32(GetEquipmentId())); + stmt->setInt32(index++, int32(GetCurrentEquipmentId())); stmt->setFloat(index++, GetPositionX()); stmt->setFloat(index++, GetPositionY()); stmt->setFloat(index++, GetPositionZ()); @@ -1355,24 +1355,24 @@ bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap) return true; } -void Creature::LoadEquipment(uint32 equip_entry, bool force) +void Creature::LoadEquipment(int8 id, bool force /*= true*/) { - if (equip_entry == 0) + if (id == 0) { if (force) { - for (uint8 i = 0; i < 3; ++i) + for (uint8 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i) SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0); m_equipmentId = 0; } return; } - EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(equip_entry); + EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(GetEntry(), id); if (!einfo) return; - m_equipmentId = equip_entry; + m_equipmentId = id; for (uint8 i = 0; i < 3; ++i) SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, einfo->ItemEntry[i]); } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index efc4e44798f..827de8bfcef 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -136,7 +136,6 @@ struct CreatureTemplate uint32 questItems[MAX_CREATURE_QUEST_ITEMS]; uint32 movementId; bool RegenHealth; - uint32 equipmentId; uint32 MechanicImmuneMask; uint32 flags_extra; uint32 ScriptID; @@ -236,7 +235,8 @@ struct EquipmentInfo }; // Benchmarked: Faster than std::map (insert/find) -typedef UNORDERED_MAP EquipmentInfoContainer; +typedef UNORDERED_MAP EquipmentInfoContainerInternal; +typedef UNORDERED_MAP EquipmentInfoContainer; // from `creature` table struct CreatureData @@ -246,7 +246,7 @@ struct CreatureData uint16 mapid; uint16 phaseMask; uint32 displayid; - int32 equipmentId; + int8 equipmentId; float posX; float posY; float posZ; @@ -454,13 +454,12 @@ class Creature : public Unit, public GridObject, public MapCreature bool Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry, uint32 vehId, uint32 team, float x, float y, float z, float ang, const CreatureData* data = NULL); bool LoadCreaturesAddon(bool reload = false); void SelectLevel(const CreatureTemplate* cinfo); - void LoadEquipment(uint32 equip_entry, bool force=false); + void LoadEquipment(int8 id = 1, bool force = false); uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; } void Update(uint32 time); // overwrited Unit::Update void GetRespawnPosition(float &x, float &y, float &z, float* ori = NULL, float* dist =NULL) const; - uint32 GetEquipmentId() const { return GetCreatureTemplate()->equipmentId; } void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } uint32 GetCorpseDelay() const { return m_corpseDelay; } @@ -558,8 +557,11 @@ class Creature : public Unit, public GridObject, public MapCreature void UpdateMaxPower(Powers power); void UpdateAttackPowerAndDamage(bool ranged = false); void UpdateDamagePhysical(WeaponAttackType attType); + + uint8 GetOriginalEquipmentId() const { return m_originalEquipmentId; } uint32 GetCurrentEquipmentId() { return m_equipmentId; } - void SetCurrentEquipmentId(uint32 entry) { m_equipmentId = entry; } + void SetCurrentEquipmentId(uint8 id) { m_equipmentId = id; } + float GetSpellDamageMod(int32 Rank); VendorItemData const* GetVendorItems() const; @@ -754,7 +756,8 @@ class Creature : public Unit, public GridObject, public MapCreature void Regenerate(Powers power); MovementGeneratorType m_defaultMovementType; uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid - uint32 m_equipmentId; + uint8 m_equipmentId; + uint8 m_originalEquipmentId; bool m_AlreadyCallAssistance; bool m_AlreadySearchedAssistance; diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index 95ed06bff37..3fc1345f444 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -450,8 +450,8 @@ void GameEventMgr::LoadFromDB() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 - QueryResult result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.eventEntry, game_event_model_equip.modelid, game_event_model_equip.equipment_id " + // 0 1 2 3 4 + QueryResult result = WorldDatabase.Query("SELECT creature.guid, creature.id, game_event_model_equip.eventEntry, game_event_model_equip.modelid, game_event_model_equip.equipment_id " "FROM creature JOIN game_event_model_equip ON creature.guid=game_event_model_equip.guid"); if (!result) @@ -466,7 +466,8 @@ void GameEventMgr::LoadFromDB() Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); - uint16 event_id = fields[1].GetUInt8(); + uint32 entry = fields[1].GetUInt32(); + uint16 event_id = fields[2].GetUInt8(); if (event_id >= mGameEventModelEquip.size()) { @@ -476,17 +477,18 @@ void GameEventMgr::LoadFromDB() ModelEquipList& equiplist = mGameEventModelEquip[event_id]; ModelEquip newModelEquipSet; - newModelEquipSet.modelid = fields[2].GetUInt32(); - newModelEquipSet.equipment_id = fields[3].GetUInt32(); + newModelEquipSet.modelid = fields[3].GetUInt32(); + newModelEquipSet.equipment_id = fields[4].GetUInt8(); newModelEquipSet.equipement_id_prev = 0; newModelEquipSet.modelid_prev = 0; if (newModelEquipSet.equipment_id > 0) { - if (!sObjectMgr->GetEquipmentInfo(newModelEquipSet.equipment_id)) + int8 equipId = static_cast(newModelEquipSet.equipment_id); + if (!sObjectMgr->GetEquipmentInfo(entry, equipId)) { - sLog->outError(LOG_FILTER_SQL, "Table `game_event_model_equip` have creature (Guid: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", - guid, newModelEquipSet.equipment_id); + sLog->outError(LOG_FILTER_SQL, "Table `game_event_model_equip` have creature (Guid: %u, entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", + guid, entry, newModelEquipSet.equipment_id); continue; } } @@ -1363,7 +1365,7 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate) sObjectMgr->GetCreatureModelRandomGender(&displayID); if (data2->equipmentId == 0) - itr->second.equipement_id_prev = cinfo->equipmentId; + itr->second.equipement_id_prev = 1; else if (data2->equipmentId != -1) itr->second.equipement_id_prev = data->equipmentId; itr->second.modelid_prev = displayID; diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h index d15b3e48dc9..4175e57f28a 100644 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -73,9 +73,9 @@ struct GameEventData struct ModelEquip { uint32 modelid; - uint32 equipment_id; uint32 modelid_prev; - uint32 equipement_id_prev; + uint8 equipment_id; + uint8 equipement_id_prev; }; struct NPCVendorEntry diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 1dd824759c9..f21de9cbfa7 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -404,8 +404,8 @@ void ObjectMgr::LoadCreatureTemplates() "spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, " // 68 69 70 71 72 73 74 75 76 77 78 "InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, " - // 79 80 81 82 83 84 - " questItem6, movementId, RegenHealth, equipment_id, mechanic_immune_mask, flags_extra, ScriptName " + // 79 80 81 82 83 84 + " questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName " "FROM creature_template;"); if (!result) @@ -500,10 +500,9 @@ void ObjectMgr::LoadCreatureTemplates() creatureTemplate.movementId = fields[80].GetUInt32(); creatureTemplate.RegenHealth = fields[81].GetBool(); - creatureTemplate.equipmentId = fields[82].GetUInt32(); - creatureTemplate.MechanicImmuneMask = fields[83].GetUInt32(); - creatureTemplate.flags_extra = fields[84].GetUInt32(); - creatureTemplate.ScriptID = GetScriptId(fields[85].GetCString()); + creatureTemplate.MechanicImmuneMask = fields[82].GetUInt32(); + creatureTemplate.flags_extra = fields[83].GetUInt32(); + creatureTemplate.ScriptID = GetScriptId(fields[84].GetCString()); ++count; } @@ -858,15 +857,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) const_cast(cInfo)->MovementType = IDLE_MOTION_TYPE; } - if (cInfo->equipmentId > 0) // 0 no equipment - { - if (!GetEquipmentInfo(cInfo->equipmentId)) - { - sLog->outError(LOG_FILTER_SQL, "Table `creature_template` lists creature (Entry: %u) with `equipment_id` %u not found in table `creature_equip_template`, set to no equipment.", cInfo->Entry, cInfo->equipmentId); - const_cast(cInfo)->equipmentId = 0; - } - } - /// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc if (cInfo->scale <= 0.0f) { @@ -986,11 +976,28 @@ CreatureAddon const* ObjectMgr::GetCreatureTemplateAddon(uint32 entry) return NULL; } -EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry) +EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry, int8& id) { EquipmentInfoContainer::const_iterator itr = _equipmentInfoStore.find(entry); - if (itr != _equipmentInfoStore.end()) - return &(itr->second); + if (itr == _equipmentInfoStore.end()) + return NULL; + + if (itr->second.empty()) + return NULL; + + if (id == -1) // select a random element + { + EquipmentInfoContainerInternal::const_iterator ritr = itr->second.begin(); + std::advance(ritr, urand(0u, itr->second.size())); + id = std::distance(itr->second.begin(), ritr) + 1; + return &ritr->second; + } + else + { + EquipmentInfoContainerInternal::const_iterator itr2 = itr->second.find(id); + if (itr2 != itr->second.end()) + return &itr2->second; + } return NULL; } @@ -999,7 +1006,8 @@ void ObjectMgr::LoadEquipmentTemplates() { uint32 oldMSTime = getMSTime(); - QueryResult result = WorldDatabase.Query("SELECT entry, itemEntry1, itemEntry2, itemEntry3 FROM creature_equip_template"); + // 0 1 2 3 4 + QueryResult result = WorldDatabase.Query("SELECT entry, id, itemEntry1, itemEntry2, itemEntry3 FROM creature_equip_template"); if (!result) { @@ -1012,13 +1020,21 @@ void ObjectMgr::LoadEquipmentTemplates() { Field* fields = result->Fetch(); - uint16 entry = fields[0].GetUInt16(); + uint32 entry = fields[0].GetUInt32(); + + if (!sObjectMgr->GetCreatureTemplate(entry)) + { + sLog->outError(LOG_FILTER_SQL, "Creature template (Entry: %u) does not exist but has a record in `creature_equip_template`", entry); + continue; + } + + uint8 id = fields[1].GetUInt8(); - EquipmentInfo& equipmentInfo = _equipmentInfoStore[entry]; + EquipmentInfo& equipmentInfo = _equipmentInfoStore[entry][id]; - equipmentInfo.ItemEntry[0] = fields[1].GetUInt32(); - equipmentInfo.ItemEntry[1] = fields[2].GetUInt32(); - equipmentInfo.ItemEntry[2] = fields[3].GetUInt32(); + equipmentInfo.ItemEntry[0] = fields[2].GetUInt32(); + equipmentInfo.ItemEntry[1] = fields[3].GetUInt32(); + equipmentInfo.ItemEntry[2] = fields[4].GetUInt32(); for (uint8 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i) { @@ -1029,8 +1045,8 @@ void ObjectMgr::LoadEquipmentTemplates() if (!dbcItem) { - sLog->outError(LOG_FILTER_SQL, "Unknown item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u, forced to 0.", - equipmentInfo.ItemEntry[i], i+1, entry); + sLog->outError(LOG_FILTER_SQL, "Unknown item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u and id=%u, forced to 0.", + equipmentInfo.ItemEntry[i], i+1, entry, id); equipmentInfo.ItemEntry[i] = 0; continue; } @@ -1045,8 +1061,8 @@ void ObjectMgr::LoadEquipmentTemplates() dbcItem->InventoryType != INVTYPE_THROWN && dbcItem->InventoryType != INVTYPE_RANGEDRIGHT) { - sLog->outError(LOG_FILTER_SQL, "Item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u is not equipable in a hand, forced to 0.", - equipmentInfo.ItemEntry[i], i+1, entry); + sLog->outError(LOG_FILTER_SQL, "Item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u and id = %u is not equipable in a hand, forced to 0.", + equipmentInfo.ItemEntry[i], i+1, entry, id); equipmentInfo.ItemEntry[i] = 0; } } @@ -1493,13 +1509,13 @@ void ObjectMgr::LoadCreatures() if (!ok) continue; - // -1 no equipment, 0 use default - if (data.equipmentId > 0) + // -1 random, 0 no equipment, 1 is default (may or may not have equipment) + if (data.equipmentId != 0) { - if (!GetEquipmentInfo(data.equipmentId)) + if (!GetEquipmentInfo(data.id, data.equipmentId) && data.equipmentId != 1) { sLog->outError(LOG_FILTER_SQL, "Table `creature` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", data.id, data.equipmentId); - data.equipmentId = -1; + data.equipmentId = 1; } } @@ -1673,7 +1689,7 @@ uint32 ObjectMgr::AddCreData(uint32 entry, uint32 /*team*/, uint32 mapId, float data.id = entry; data.mapid = mapId; data.displayid = 0; - data.equipmentId = cInfo->equipmentId; + data.equipmentId = 1; data.posX = x; data.posY = y; data.posZ = z; diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 9339684964c..88496fa9d6e 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -663,7 +663,7 @@ class ObjectMgr CreatureModelInfo const* GetCreatureModelRandomGender(uint32* displayID); static uint32 ChooseDisplayId(uint32 team, const CreatureTemplate* cinfo, const CreatureData* data = NULL); static void ChooseCreatureFlags(const CreatureTemplate* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, const CreatureData* data = NULL); - EquipmentInfo const* GetEquipmentInfo(uint32 entry); + EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id); CreatureAddon const* GetCreatureAddon(uint32 lowguid); CreatureAddon const* GetCreatureTemplateAddon(uint32 entry); ItemTemplate const* GetItemTemplate(uint32 entry); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 5868b60b722..28f7a2cb8a0 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1033,7 +1033,8 @@ enum TrinityStrings LANG_COMMAND_NO_ACHIEVEMENT_CRITERIA_FOUND = 5033, LANG_COMMAND_NO_OUTDOOR_PVP_FORUND = 5034, LANG_CALL_FOR_HELP = 5035, - // Room for more Trinity strings 5036-9999 + LANG_NPCINFO_EQUIPMENT = 5036, + // Room for more Trinity strings 5037-9999 // Level requirement notifications LANG_SAY_REQ = 6604, diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 93e4b2e4771..f5504f8b7c1 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3902,7 +3902,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) unitTarget->CastSpell(unitTarget, iTmpSpellId, true); Creature* npc = unitTarget->ToCreature(); - npc->LoadEquipment(npc->GetEquipmentId()); + npc->LoadEquipment(); return; } // Emblazon Runeblade diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index d8eec66ea07..29ecdbb033e 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1405,12 +1405,12 @@ void World::SetInitialWorldSettings() sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creature Model Based Info Data..."); sObjectMgr->LoadCreatureModelInfo(); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Equipment templates..."); - sObjectMgr->LoadEquipmentTemplates(); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creature templates..."); sObjectMgr->LoadCreatureTemplates(); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Equipment templates..."); // must be after LoadCreatureTemplates + sObjectMgr->LoadEquipmentTemplates(); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creature template addons..."); sObjectMgr->LoadCreatureTemplateAddons(); diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 7ccd5ed1177..818a17438bf 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -645,6 +645,7 @@ public: handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), target->GetGUIDLow(), faction, npcflags, Entry, displayid, nativeid); handler->PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel()); + handler->PSendSysMessage(LANG_NPCINFO_EQUIPMENT, target->GetCurrentEquipmentId(), target->GetOriginalEquipmentId()); handler->PSendSysMessage(LANG_NPCINFO_HEALTH, target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth()); handler->PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction()); handler->PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(), curRespawnDelayStr.c_str()); diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 43c2001fbf7..b2542d6a668 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -508,10 +508,9 @@ public: cInfo->questItems[5] = fields[78].GetUInt32(); cInfo->movementId = fields[79].GetUInt32(); cInfo->RegenHealth = fields[80].GetBool(); - cInfo->equipmentId = fields[81].GetUInt32(); - cInfo->MechanicImmuneMask = fields[82].GetUInt32(); - cInfo->flags_extra = fields[83].GetUInt32(); - cInfo->ScriptID = sObjectMgr->GetScriptId(fields[84].GetCString()); + cInfo->MechanicImmuneMask = fields[81].GetUInt32(); + cInfo->flags_extra = fields[82].GetUInt32(); + cInfo->ScriptID = sObjectMgr->GetScriptId(fields[83].GetCString()); sObjectMgr->CheckCreatureTemplate(cInfo); } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index 96293c635d6..14321873b0d 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -102,10 +102,8 @@ public: npc_unworthy_initiateAI(Creature* creature) : ScriptedAI(creature) { me->SetReactState(REACT_PASSIVE); - if (!me->GetEquipmentId()) - if (const CreatureTemplate* info = sObjectMgr->GetCreatureTemplate(28406)) - if (info->equipmentId) - const_cast(me->GetCreatureTemplate())->equipmentId = info->equipmentId; + if (!me->GetCurrentEquipmentId()) + me->SetCurrentEquipmentId(me->GetOriginalEquipmentId()); } uint64 playerGUID; diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp index f508266434b..7e2515c42a7 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp @@ -237,7 +237,7 @@ public: case 2: me->SetStandState(UNIT_STAND_STATE_STAND); DoCast(me, SPELL_KOLTIRA_TRANSFORM); - me->LoadEquipment(me->GetEquipmentId()); + me->LoadEquipment(); break; case 3: SetEscortPaused(true); diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp index 2c8d067a865..37bad9c4e4f 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp @@ -316,7 +316,7 @@ public: me->SetDisplayId(MODEL_NIGHTELF); // and reseting equipment - me->LoadEquipment(me->GetEquipmentId()); + me->LoadEquipment(); if (instance && instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) { @@ -410,7 +410,7 @@ public: if (me->HasAura(AURA_BANISH)) return; - me->LoadEquipment(me->GetEquipmentId()); + me->LoadEquipment(); } void UpdateAI(const uint32 diff) @@ -558,7 +558,7 @@ public: { //switch to nightelf form me->SetDisplayId(MODEL_NIGHTELF); - me->LoadEquipment(me->GetEquipmentId()); + me->LoadEquipment(); CastConsumingMadness(); DespawnDemon(); @@ -589,7 +589,7 @@ public: Talk(SAY_FINAL_FORM); me->SetDisplayId(MODEL_NIGHTELF); - me->LoadEquipment(me->GetEquipmentId()); + me->LoadEquipment(); } } }; diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index b807736f47b..89f3cf8fdce 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -78,7 +78,7 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_INS_CREATURE_TRANSPORT, "INSERT INTO creature_transport (guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO) values (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(WORLD_UPD_CREATURE_TRANSPORT_EMOTE, "UPDATE creature_transport SET emote = ? WHERE transport_entry = ? AND guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH); - PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, equipment_id, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH); + PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationCountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH); -- cgit v1.2.3 From 4fc7fcae3311c7c6f8ad18235e120ecf9ff187a0 Mon Sep 17 00:00:00 2001 From: Spp Date: Mon, 18 Feb 2013 14:49:59 +0100 Subject: Core/RBAC: Add config option to set comma separated list of groups to add by default - Allows to reduce the rows in rbac_account_groups --- src/server/game/Accounts/AccountMgr.cpp | 18 ++++++++++++++---- src/server/game/Accounts/AccountMgr.h | 4 +++- src/server/game/Accounts/RBAC.cpp | 5 +++++ src/server/game/Accounts/RBAC.h | 2 +- src/server/worldserver/worldserver.conf.dist | 8 ++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 036cff1902d..bd560c8266e 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -56,7 +56,7 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass RBACData* rbac = new RBACData(GetId(username), username, -1); // No need to Load From DB, as it's new data - RBACGroupContainer const& groupsToAdd = _defaultGroups[0]; // 0: Default sec level + RBACGroupContainer const& groupsToAdd = _defaultSecGroups[0]; // 0: Default sec level for (RBACGroupContainer::const_iterator it = groupsToAdd.begin(); it != groupsToAdd.end(); ++it) rbac->AddGroup(*it, -1); @@ -426,13 +426,23 @@ void AccountMgr::LoadRBAC() uint8 secId = field[0].GetUInt8(); if (lastSecId != secId) - groups = &_defaultGroups[secId]; + groups = &_defaultSecGroups[secId]; groups->insert(field[1].GetUInt32()); } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u permission definitions, %u role definitions and %u group definitions in %u ms", count1, count2, count3, GetMSTimeDiffToNow(oldMSTime)); + + // Load default groups to be added to any RBAC Object. + std::string defaultGroups = ConfigMgr::GetStringDefault("RBAC.DefaultGroups", ""); + Tokenizer tokens(defaultGroups, ','); + for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) + if (uint32 groupId = atoi(*itr)) + { + sLog->outError(LOG_FILTER_LFG, "Adding default group %u", groupId); + _defaultGroups.insert(groupId); + } } void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 securityLevel, int32 realmId) @@ -459,7 +469,7 @@ void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 sec uint8 secLevel = field[0].GetUInt8(); int32 realmId = field[1].GetUInt32(); - RBACGroupContainer const& groupsToRemove = _defaultGroups[secLevel]; + RBACGroupContainer const& groupsToRemove = _defaultSecGroups[secLevel]; for (RBACGroupContainer::const_iterator it = groupsToRemove.begin(); it != groupsToRemove.end(); ++it) rbac->RemoveGroup(*it, realmId); } @@ -467,7 +477,7 @@ void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 sec } // Add new groups depending on the new security Level - RBACGroupContainer const& groupsToAdd = _defaultGroups[securityLevel]; + RBACGroupContainer const& groupsToAdd = _defaultSecGroups[securityLevel]; for (RBACGroupContainer::const_iterator it = groupsToAdd.begin(); it != groupsToAdd.end(); ++it) rbac->AddGroup(*it, realmId); diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h index 90c533ca5fa..440e012f1fc 100644 --- a/src/server/game/Accounts/AccountMgr.h +++ b/src/server/game/Accounts/AccountMgr.h @@ -77,12 +77,14 @@ class AccountMgr RBACGroupsContainer const& GetRBACGroupList() const { return _groups; } RBACRolesContainer const& GetRBACRoleList() const { return _roles; } RBACPermissionsContainer const& GetRBACPermissionList() const { return _permissions; } + RBACGroupContainer const& GetRBACDefaultGroups() const { return _defaultGroups; } private: RBACPermissionsContainer _permissions; RBACRolesContainer _roles; RBACGroupsContainer _groups; - RBACDefaultSecurityGroupContainer _defaultGroups; + RBACDefaultSecurityGroupContainer _defaultSecGroups; + RBACGroupContainer _defaultGroups; }; #define sAccountMgr ACE_Singleton::instance() diff --git a/src/server/game/Accounts/RBAC.cpp b/src/server/game/Accounts/RBAC.cpp index 4a069df05cd..121c9faae76 100644 --- a/src/server/game/Accounts/RBAC.cpp +++ b/src/server/game/Accounts/RBAC.cpp @@ -296,6 +296,11 @@ void RBACData::LoadFromDB() while (result->NextRow()); } + // Add default groups + RBACGroupContainer const& groups = sAccountMgr->GetRBACDefaultGroups(); + for (RBACGroupContainer::const_iterator itr = groups.begin(); itr != groups.end(); ++itr) + AddGroup(*itr); + // Force calculation of permissions, it wasn't performed at load time // while adding groups, roles and permissions CalculateNewPermissions(); diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index d2c76b71801..f6e494e7b70 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -135,7 +135,7 @@ class RBACGroup: public RBACObject RBACRoleContainer _roles; ///> Set of Roles }; -/* +/** * @name RBACData * @brief Contains all needed information about the acccount * diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index dfc7e83f250..069c027d139 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1119,6 +1119,14 @@ DBC.EnforceItemAttributes = 1 AccountInstancesPerHour = 5 +# +# RBAC.DefaultGroups +# Description: Comma separated list of groups to be added to any account +# Check auth.rbac_groups for correct ids +# Default: "" (No group) + +RBAC.DefaultGroups = "" + # ################################################################################################### -- cgit v1.2.3 From 1c745dfe16787f9b51310c07b5b3c6801e9592e5 Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Mon, 18 Feb 2013 16:19:16 +0100 Subject: Core/Vehicles: Fix a few issues - Fix position desync issue Closes #9073 - Fix a crash related to passenger's EventProcessor, thanks to Shauren - Fix crash related to charminfo - Make compiler happier about certain things --- src/server/game/Entities/Player/Player.h | 6 ++++++ src/server/game/Entities/Vehicle/Vehicle.cpp | 20 ++++++++------------ src/server/game/Entities/Vehicle/Vehicle.h | 5 +---- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 5 +---- 4 files changed, 16 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 64980b9551e..362b6aca631 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -28,6 +28,7 @@ #include "QuestDef.h" #include "SpellMgr.h" #include "Unit.h" +#include "Opcodes.h" #include #include @@ -1628,6 +1629,11 @@ class Player : public Unit, public GridObject return mMitems.erase(id) ? true : false; } + void SendOnCancelExpectedVehicleRideAura() + { + WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); + GetSession()->SendPacket(&data); + } void PetSpellInitialize(); void CharmSpellInitialize(); void PossessSpellInitialize(); diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 9dd25577fe1..8b4516ca47a 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -35,7 +35,7 @@ #include "Battleground.h" Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) : -_me(unit), _vehicleInfo(vehInfo), UsableSeatNum(0), _creatureEntry(creatureEntry), _status(STATUS_NONE) +UsableSeatNum(0), _me(unit), _vehicleInfo(vehInfo), _creatureEntry(creatureEntry), _status(STATUS_NONE) { for (uint32 i = 0; i < MAX_VEHICLE_SEATS; ++i) { @@ -429,7 +429,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle (entry: %u, vehicleId: %u, guid: %u (dbguid: %s) on seat %d", unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), - (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : 0), seatId); + (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : 0), (int32)seatId); // The seat selection code may kick other passengers off the vehicle. // While the validity of the following may be arguable, it is possible that when such a passenger @@ -749,8 +749,9 @@ bool VehicleJoinEvent::Execute(uint64, uint32) if (Battleground* bg = player->GetBattleground()) bg->EventPlayerDroppedFlag(player); - WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); - player->GetSession()->SendPacket(&data); + player->StopCastingCharm(); + player->StopCastingBindSight(); + player->SendOnCancelExpectedVehicleRideAura(); player->UnsummonPetTemporaryIfAny(); } @@ -774,7 +775,7 @@ bool VehicleJoinEvent::Execute(uint64, uint32) Movement::MoveSplineInit init(Passenger); init.DisableTransportPathTransformations(); - init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); + init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ, false, true); init.SetFacing(0.0f); init.SetTransportEnter(); init.Launch(); @@ -811,11 +812,6 @@ bool VehicleJoinEvent::Execute(uint64, uint32) void VehicleJoinEvent::Abort(uint64) { - // Prevent recursion - if (_executedAbort) - return; - - _executedAbort = true; sLog->outDebug(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %i cancelled", Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first); @@ -824,6 +820,6 @@ void VehicleJoinEvent::Abort(uint64) /// the aura manually. Target->GetBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, Passenger->GetGUID()); - if (Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY)) - Passenger->ToTempSummon()->UnSummon(); + if (Passenger->IsInWorld() && Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY)) + Passenger->ToCreature()->DespawnOrUnsummon(); } diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 01b8a0c581f..7ec0df8e533 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -107,15 +107,12 @@ class VehicleJoinEvent : public BasicEvent { friend class Vehicle; protected: - VehicleJoinEvent(Vehicle* v, Unit* u) : Target(v), Passenger(u), Seat(Target->Seats.end()), _executedAbort(false) {} + VehicleJoinEvent(Vehicle* v, Unit* u) : Target(v), Passenger(u), Seat(Target->Seats.end()) {} bool Execute(uint64, uint32); void Abort(uint64); Vehicle* Target; Unit* Passenger; SeatMap::iterator Seat; - - private: - bool _executedAbort; }; #endif diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index d6b19e6010a..a51d591f54c 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5296,10 +5296,7 @@ void AuraEffect::HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode, target->SendMessageToSet(&data, true); if (apply) - { - data.Initialize(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); - target->ToPlayer()->GetSession()->SendPacket(&data); - } + target->ToPlayer()->SendOnCancelExpectedVehicleRideAura(); } void AuraEffect::HandlePreventResurrection(AuraApplication const* aurApp, uint8 mode, bool apply) const -- cgit v1.2.3