diff options
author | Vincent-Michael <Vincent_Michael@gmx.de> | 2013-06-30 00:36:03 +0200 |
---|---|---|
committer | Vincent-Michael <Vincent_Michael@gmx.de> | 2013-06-30 00:36:03 +0200 |
commit | 676c7341d69bc93e95f147608635655fd91c79b9 (patch) | |
tree | 934a1bae2a8c791aad0bde4fe4acd04ecc7e2bf4 /src | |
parent | 83066a200202d7a487d11389e73173c1db0c391e (diff) | |
parent | 718fc5bfc94bdfa8c94a5ed646f31305ab2b08bd (diff) |
Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Conflicts:
src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
Diffstat (limited to 'src')
37 files changed, 2508 insertions, 1622 deletions
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index 85dd9cca90c..85088bbeff4 100644 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -328,7 +328,7 @@ void VehicleAI::CheckConditions(const uint32 diff) if (!conditions.empty()) { for (SeatMap::iterator itr = m_vehicle->Seats.begin(); itr != m_vehicle->Seats.end(); ++itr) - if (Unit* passenger = ObjectAccessor::GetUnit(*m_vehicle->GetBase(), itr->second.Passenger)) + if (Unit* passenger = ObjectAccessor::GetUnit(*m_vehicle->GetBase(), itr->second.Passenger.Guid)) { if (Player* player = passenger->ToPlayer()) { diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 2abc526134c..86c246ff387 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -475,7 +475,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (IsUnit(*itr)) if (Vehicle* vehicle = (*itr)->ToUnit()->GetVehicleKit()) for (SeatMap::iterator it = vehicle->Seats.begin(); it != vehicle->Seats.end(); ++it) - if (Player* player = ObjectAccessor::FindPlayer(it->second.Passenger)) + if (Player* player = ObjectAccessor::FindPlayer(it->second.Passenger.Guid)) player->AreaExploredOrEventHappens(e.action.quest.quest); if (IsPlayer(*itr)) @@ -783,7 +783,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u // Special handling for vehicles if (Vehicle* vehicle = unit->GetVehicleKit()) for (SeatMap::iterator it = vehicle->Seats.begin(); it != vehicle->Seats.end(); ++it) - if (Player* player = ObjectAccessor::FindPlayer(it->second.Passenger)) + if (Player* player = ObjectAccessor::FindPlayer(it->second.Passenger.Guid)) player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); break; } @@ -915,7 +915,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (IsUnit(*itr)) if (Vehicle* vehicle = (*itr)->ToUnit()->GetVehicleKit()) for (SeatMap::iterator it = vehicle->Seats.begin(); it != vehicle->Seats.end(); ++it) - if (Player* player = ObjectAccessor::FindPlayer(it->second.Passenger)) + if (Player* player = ObjectAccessor::FindPlayer(it->second.Passenger.Guid)) player->RewardPlayerAndGroupAtEvent(e.action.killedMonster.creature, player); if (!IsPlayer(*itr)) diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 1daf69f0b5f..11ca372625a 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -506,7 +506,7 @@ enum VehicleSeatFlags VEHICLE_SEAT_FLAG_UNK18 = 0x00020000, // Needs research and support (28 vehicles): Allow entering vehicles while keeping specific permanent(?) auras that impose visuals (states like beeing under freeze/stun mechanic, emote state animations). VEHICLE_SEAT_FLAG_HAS_VEH_EXIT_ANIM_VOLUNTARY_EXIT = 0x00040000, VEHICLE_SEAT_FLAG_HAS_VEH_EXIT_ANIM_FORCED_EXIT = 0x00080000, - VEHICLE_SEAT_FLAG_UNK21 = 0x00100000, + VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE = 0x00100000, VEHICLE_SEAT_FLAG_UNK22 = 0x00200000, VEHICLE_SEAT_FLAG_REC_HAS_VEHICLE_ENTER_ANIM = 0x00400000, VEHICLE_SEAT_FLAG_IS_USING_VEHICLE_CONTROLS = 0x00800000, // Lua_IsUsingVehicleControls diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 5d0c56d8d01..45b8cb38da2 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -15771,7 +15771,7 @@ void Unit::ChangeSeat(int8 seatId, bool next) 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) + if (seat == m_vehicle->Seats.end() || !seat->second.IsEmpty()) return; AuraEffect* rideVehicleEffect = NULL; @@ -16426,7 +16426,7 @@ void Unit::OutDebugInfo() const { o << "Passenger List: "; for (SeatMap::iterator itr = GetVehicleKit()->Seats.begin(); itr != GetVehicleKit()->Seats.end(); ++itr) - if (Unit* passenger = ObjectAccessor::GetUnit(*GetVehicleBase(), itr->second.Passenger)) + if (Unit* passenger = ObjectAccessor::GetUnit(*GetVehicleBase(), itr->second.Passenger.Guid)) o << passenger->GetGUID() << ", "; TC_LOG_INFO(LOG_FILTER_UNITS, "%s", o.str().c_str()); } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 8eee9264582..bd4b5b85de6 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -516,7 +516,6 @@ enum UnitState UNIT_STATE_POSSESSED = 0x00010000, UNIT_STATE_CHARGING = 0x00020000, UNIT_STATE_JUMPING = 0x00040000, - UNIT_STATE_ONVEHICLE = 0x00080000, UNIT_STATE_MOVE = 0x00100000, UNIT_STATE_ROTATING = 0x00200000, UNIT_STATE_EVADE = 0x00400000, @@ -526,7 +525,7 @@ enum UnitState UNIT_STATE_CHASE_MOVE = 0x04000000, UNIT_STATE_FOLLOW_MOVE = 0x08000000, UNIT_STATE_IGNORE_PATHFINDING = 0x10000000, // do not use pathfinding in any MovementGenerator - UNIT_STATE_UNATTACKABLE = (UNIT_STATE_IN_FLIGHT | UNIT_STATE_ONVEHICLE), + UNIT_STATE_UNATTACKABLE = UNIT_STATE_IN_FLIGHT, // for real move using movegen check and stop (except unstoppable flight) UNIT_STATE_MOVING = UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE, UNIT_STATE_CONTROLLED = (UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING), diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index f690160b464..8dbe08990c5 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -62,7 +62,7 @@ Vehicle::~Vehicle() /// @Uninstall must be called before this. ASSERT(_status == STATUS_UNINSTALLING); for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr) - ASSERT(!itr->second.Passenger); + ASSERT(itr->second.IsEmpty()); } /** @@ -299,7 +299,7 @@ bool Vehicle::HasEmptySeat(int8 seatId) const SeatMap::const_iterator seat = Seats.find(seatId); if (seat == Seats.end()) return false; - return !seat->second.Passenger; + return seat->second.IsEmpty(); } /** @@ -321,7 +321,7 @@ Unit* Vehicle::GetPassenger(int8 seatId) const if (seat == Seats.end()) return NULL; - return ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger); + return ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger.Guid); } /** @@ -344,7 +344,7 @@ SeatMap::const_iterator Vehicle::GetNextEmptySeat(int8 seatId, bool next) const if (seat == Seats.end()) return seat; - while (seat->second.Passenger || (!seat->second.SeatInfo->CanEnterOrExit() && !seat->second.SeatInfo->IsUsableByOverride())) + while (!seat->second.IsEmpty() || (!seat->second.SeatInfo->CanEnterOrExit() && !seat->second.SeatInfo->IsUsableByOverride())) { if (next) { @@ -449,7 +449,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) if (seatId < 0) // no specific seat requirement { for (seat = Seats.begin(); seat != Seats.end(); ++seat) - if (!seat->second.Passenger && (seat->second.SeatInfo->CanEnterOrExit() || seat->second.SeatInfo->IsUsableByOverride())) + if (seat->second.IsEmpty() && (seat->second.SeatInfo->CanEnterOrExit() || seat->second.SeatInfo->IsUsableByOverride())) break; if (seat == Seats.end()) // no available seat @@ -472,14 +472,14 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) e->Seat = seat; _pendingJoinEvents.push_back(e); - if (seat->second.Passenger) + if (!seat->second.IsEmpty()) { - Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger); + Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger.Guid); ASSERT(passenger); passenger->ExitVehicle(); } - ASSERT(!seat->second.Passenger); + ASSERT(seat->second.IsEmpty()); } return true; @@ -507,11 +507,14 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit) TC_LOG_DEBUG(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() && ++UsableSeatNum) _me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); - unit->ClearUnitState(UNIT_STATE_ONVEHICLE); + // Remove UNIT_FLAG_NOT_SELECTABLE if passenger did not have it before entering vehicle + if (seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE && !seat->second.Passenger.IsUnselectable) + unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + seat->second.Passenger.Reset(); if (_me->GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER && seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL) _me->RemoveCharmedBy(unit); @@ -549,7 +552,7 @@ void Vehicle::RelocatePassengers() // not sure that absolute position calculation is correct, it must depend on vehicle pitch angle for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr) { - if (Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), itr->second.Passenger)) + if (Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), itr->second.Passenger.Guid)) { ASSERT(passenger->IsInWorld()); @@ -576,7 +579,7 @@ void Vehicle::RelocatePassengers() bool Vehicle::IsVehicleInUse() const { for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr) - if (itr->second.Passenger) + if (!itr->second.IsEmpty()) return true; return false; @@ -623,7 +626,7 @@ void Vehicle::InitMovementInfoForBase() VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit const* passenger) const { for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr) - if (itr->second.Passenger == passenger->GetGUID()) + if (itr->second.Passenger.Guid == passenger->GetGUID()) return itr->second.SeatInfo; return NULL; @@ -646,7 +649,7 @@ SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger) { SeatMap::iterator itr; for (itr = Seats.begin(); itr != Seats.end(); ++itr) - if (itr->second.Passenger == passenger->GetGUID()) + if (itr->second.Passenger.Guid == passenger->GetGUID()) return itr; return Seats.end(); @@ -668,7 +671,7 @@ uint8 Vehicle::GetAvailableSeatCount() const uint8 ret = 0; SeatMap::const_iterator itr; for (itr = Seats.begin(); itr != Seats.end(); ++itr) - if (!itr->second.Passenger && (itr->second.SeatInfo->CanEnterOrExit() || itr->second.SeatInfo->IsUsableByOverride())) + if (itr->second.IsEmpty() && (itr->second.SeatInfo->CanEnterOrExit() || itr->second.SeatInfo->IsUsableByOverride())) ++ret; return ret; @@ -804,7 +807,8 @@ bool VehicleJoinEvent::Execute(uint64, uint32) Target->RemovePendingEventsForPassenger(Passenger); Passenger->SetVehicle(Target); - Seat->second.Passenger = Passenger->GetGUID(); + Seat->second.Passenger.Guid = Passenger->GetGUID(); + Seat->second.Passenger.IsUnselectable = Passenger->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); if (Seat->second.SeatInfo->CanEnterOrExit()) { ASSERT(Target->UsableSeatNum); @@ -834,8 +838,8 @@ bool VehicleJoinEvent::Execute(uint64, uint32) player->UnsummonPetTemporaryIfAny(); } - if (Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_HIDE_PASSENGER) - Passenger->AddUnitState(UNIT_STATE_ONVEHICLE); + if (Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE) + Passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); VehicleSeatEntry const* veSeat = Seat->second.SeatInfo; Passenger->m_movementInfo.transport.pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); diff --git a/src/server/game/Entities/Vehicle/VehicleDefines.h b/src/server/game/Entities/Vehicle/VehicleDefines.h index 55c47df86ad..802e63346c1 100644 --- a/src/server/game/Entities/Vehicle/VehicleDefines.h +++ b/src/server/game/Entities/Vehicle/VehicleDefines.h @@ -75,11 +75,29 @@ enum VehicleSpells VEHICLE_SPELL_PARACHUTE = 45472 }; +struct PassengerInfo +{ + uint64 Guid; + bool IsUnselectable; + + void Reset() + { + Guid = 0; + IsUnselectable = false; + } +}; + struct VehicleSeat { - explicit VehicleSeat(VehicleSeatEntry const* seatInfo) : SeatInfo(seatInfo), Passenger(0) {} + explicit VehicleSeat(VehicleSeatEntry const* seatInfo) : SeatInfo(seatInfo) + { + Passenger.Reset(); + } + + bool IsEmpty() const { return !Passenger.Guid; } + VehicleSeatEntry const* SeatInfo; - uint64 Passenger; + PassengerInfo Passenger; }; struct VehicleAccessory diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index f644047b298..e2fae8a8042 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -129,17 +129,17 @@ void AddSC_boss_gyth(); void AddSC_boss_rend_blackhand(); void AddSC_instance_blackrock_spire(); void AddSC_boss_razorgore(); //Blackwing lair -void AddSC_boss_vael(); +void AddSC_boss_vaelastrasz(); void AddSC_boss_broodlord(); void AddSC_boss_firemaw(); void AddSC_boss_ebonroc(); void AddSC_boss_flamegor(); void AddSC_boss_chromaggus(); void AddSC_boss_nefarian(); -void AddSC_boss_victor_nefarius(); -void AddSC_boss_mr_smite(); +void AddSC_instance_blackwing_lair(); void AddSC_deadmines(); //Deadmines void AddSC_instance_deadmines(); +void AddSC_boss_mr_smite(); void AddSC_gnomeregan(); //Gnomeregan void AddSC_instance_gnomeregan(); void AddSC_boss_attumen(); //Karazhan @@ -771,16 +771,16 @@ void AddEasternKingdomsScripts() AddSC_boss_rend_blackhand(); AddSC_instance_blackrock_spire(); AddSC_boss_razorgore(); //Blackwing lair - AddSC_boss_vael(); + AddSC_boss_vaelastrasz(); AddSC_boss_broodlord(); AddSC_boss_firemaw(); AddSC_boss_ebonroc(); AddSC_boss_flamegor(); AddSC_boss_chromaggus(); AddSC_boss_nefarian(); - AddSC_boss_victor_nefarius(); - AddSC_boss_mr_smite(); + AddSC_instance_blackwing_lair(); AddSC_deadmines(); //Deadmines + AddSC_boss_mr_smite(); AddSC_instance_deadmines(); AddSC_gnomeregan(); //Gnomeregan AddSC_instance_gnomeregan(); diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h b/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h index 82500ab90b0..ccd96ef81d2 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h @@ -18,25 +18,38 @@ #ifndef DEF_BLACKROCK_SPIRE_H #define DEF_BLACKROCK_SPIRE_H -enum Data +uint32 const EncounterCount = 22; + +#define BRSScriptName "instance_blackrock_spire" + +enum DataTypes { - DATA_OMOKK, - DATA_SHADOW_HUNTER_VOSHGAJIN, - DATA_WARMASTER_VOONE, - DATA_MOTHER_SMOLDERWEB, - DATA_UROK_DOOMHOWL, // not scripted - DATA_QUARTERMASTER_ZIGRIS, - DATA_GIZRUL_THE_SLAVENER, // not scripted - DATA_HALYCON, - DATA_OVERLORD_WYRMTHALAK, - DATA_PYROGAURD_EMBERSEER, - DATA_WARCHIEF_REND_BLACKHAND, - DATA_GYTH, - DATA_THE_BEAST, - DATA_GENERAL_DRAKKISATH, - DATA_DRAGONSPIRE_ROOM, + DATA_OMOKK = 0, + DATA_SHADOW_HUNTER_VOSHGAJIN = 1, + DATA_WARMASTER_VOONE = 2, + DATA_MOTHER_SMOLDERWEB = 3, + DATA_UROK_DOOMHOWL = 4, // not scripted + DATA_QUARTERMASTER_ZIGRIS = 5, + DATA_GIZRUL_THE_SLAVENER = 6, // not scripted + DATA_HALYCON = 7, + DATA_OVERLORD_WYRMTHALAK = 8, + DATA_PYROGAURD_EMBERSEER = 9, + DATA_WARCHIEF_REND_BLACKHAND = 10, + DATA_GYTH = 11, + DATA_THE_BEAST = 12, + DATA_GENERAL_DRAKKISATH = 13, + // Extra + DATA_DRAGONSPIRE_ROOM = 14, + DATA_HALL_RUNE_1 = 15, + DATA_HALL_RUNE_2 = 16, + DATA_HALL_RUNE_3 = 17, + DATA_HALL_RUNE_4 = 18, + DATA_HALL_RUNE_5 = 19, + DATA_HALL_RUNE_6 = 20, + DATA_HALL_RUNE_7 = 21 }; -enum Npc + +enum CreaturesIds { NPC_OMOKK = 9196, NPC_SHADOW_HUNTER_VOSHGAJIN = 9236, @@ -55,22 +68,23 @@ enum Npc NPC_BLACKHAND_DREADWEAVER = 9817, NPC_BLACKHAND_SUMMONER = 9818, NPC_BLACKHAND_VETERAN = 9819, + NPC_BLACKHAND_INCARCERATOR = 10316, + NPC_LORD_VICTOR_NEFARIUS = 10162, + NPC_REND_BLACKHAND = 10429 }; enum AdditionalData { SPELL_SUMMON_ROOKERY_WHELP = 15745, - MAX_ENCOUNTER = 14, - MAX_DRAGONSPIRE_HALL_RUNES = 7, EVENT_PYROGUARD_EMBERSEER = 4884, - AREATRIGGER_ENTER_UBRS = 2046, - AREATRIGGER_STADIUM = 2026, + AREATRIGGER = 1, + AREATRIGGER_DRAGONSPIRE_HALL = 2046, + AREATRIGGER_BLACKROCK_STADIUM = 2026 }; -enum GameObjects +enum GameObjectsIds { GO_WHELP_SPAWNER = 175622, // trap spawned by go id 175124 - // Doors GO_EMBERSEER_IN = 175244, // First door to Pyroguard Emberseer GO_DOORS = 175705, // Second door to Pyroguard Emberseer @@ -80,16 +94,15 @@ enum GameObjects GO_GYTH_EXIT_DOOR = 175186, GO_DRAKKISATH_DOOR_1 = 175946, GO_DRAKKISATH_DOOR_2 = 175947, - - // Runes - GO_ROOM_1_RUNE = 175197, - GO_ROOM_2_RUNE = 175199, - GO_ROOM_3_RUNE = 175195, - GO_ROOM_4_RUNE = 175200, - GO_ROOM_5_RUNE = 175198, - GO_ROOM_6_RUNE = 175196, - GO_ROOM_7_RUNE = 175194, - + // Runes in dragonspire hall + GO_HALL_RUNE_1 = 175197, + GO_HALL_RUNE_2 = 175199, + GO_HALL_RUNE_3 = 175195, + GO_HALL_RUNE_4 = 175200, + GO_HALL_RUNE_5 = 175198, + GO_HALL_RUNE_6 = 175196, + GO_HALL_RUNE_7 = 175194, + // Runes in emberseers room GO_EMBERSEER_RUNE_1 = 175266, GO_EMBERSEER_RUNE_2 = 175267, GO_EMBERSEER_RUNE_3 = 175268, @@ -97,7 +110,8 @@ enum GameObjects GO_EMBERSEER_RUNE_5 = 175270, GO_EMBERSEER_RUNE_6 = 175271, GO_EMBERSEER_RUNE_7 = 175272, + // For Gyth event + GO_DR_PORTCULLIS = 175185 }; #endif - diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_drakkisath.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_drakkisath.cpp index c480e3115e2..dfd808041bd 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_drakkisath.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_drakkisath.cpp @@ -41,11 +41,6 @@ class boss_drakkisath : public CreatureScript public: boss_drakkisath() : CreatureScript("boss_drakkisath") { } - CreatureAI* GetAI(Creature* creature) const - { - return new boss_drakkisathAI(creature); - } - struct boss_drakkisathAI : public BossAI { boss_drakkisathAI(Creature* creature) : BossAI(creature, DATA_GENERAL_DRAKKISATH) {} @@ -58,10 +53,10 @@ public: void EnterCombat(Unit* /*who*/) { _EnterCombat(); - events.ScheduleEvent(EVENT_FIRE_NOVA, 6 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_CLEAVE, 8 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_CONFLIGURATION, 15 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_THUNDERCLAP, 17 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_FIRE_NOVA, 6000); + events.ScheduleEvent(EVENT_CLEAVE, 8000); + events.ScheduleEvent(EVENT_CONFLIGURATION, 15000); + events.ScheduleEvent(EVENT_THUNDERCLAP, 17000); } void JustDied(Unit* /*killer*/) @@ -85,25 +80,30 @@ public: { case EVENT_FIRE_NOVA: DoCastVictim(SPELL_FIRENOVA); - events.ScheduleEvent(EVENT_FIRE_NOVA, 10 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_FIRE_NOVA, 10000); break; case EVENT_CLEAVE: DoCastVictim(SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, 8 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_CLEAVE, 8000); break; case EVENT_CONFLIGURATION: DoCastVictim(SPELL_CONFLIGURATION); - events.ScheduleEvent(EVENT_CONFLIGURATION, 18 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_CONFLIGURATION, 18000); break; case EVENT_THUNDERCLAP: DoCastVictim(SPELL_THUNDERCLAP); - events.ScheduleEvent(EVENT_THUNDERCLAP, 20 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_THUNDERCLAP, 20000); break; } } DoMeleeAttackIfReady(); } }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_drakkisathAI(creature); + } }; void AddSC_boss_drakkisath() diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_gyth.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_gyth.cpp index e1cce4f319e..75e9ad6a140 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_gyth.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_gyth.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -22,30 +21,21 @@ enum Spells { - SPELL_CORROSIVE_ACID = 20667, - SPELL_FREEZE = 18763, - SPELL_FLAMEBREATH = 20712, - SPELL_SELF_ROOT_FOREVER = 33356, -}; - -enum Adds -{ - MODEL_REND_ON_DRAKE = 9723, /// @todo use creature_template 10459 instead of its modelid - NPC_RAGE_TALON_FIRE_TONG = 10372, - NPC_CHROMATIC_WHELP = 10442, - NPC_CHROMATIC_DRAGONSPAWN = 10447, - NPC_BLACKHAND_ELITE = 10317, + SPELL_REND_MOUNTS = 16167, // Change model + SPELL_CORROSIVE_ACID = 16359, // Combat (self cast) + SPELL_FLAMEBREATH = 16390, // Combat (Self cast) + SPELL_FREEZE = 16350, // Combat (Self cast) + SPELL_KNOCK_AWAY = 10101, // Combat + SPELL_SUMMON_REND = 16328 // Summons Rend near death }; enum Events { - EVENT_SUMMON_REND = 1, - EVENT_AGGRO = 2, - EVENT_SUMMON_DRAGON_PACK = 3, - EVENT_SUMMON_ORC_PACK = 4, - EVENT_CORROSIVE_ACID = 5, - EVENT_FREEZE = 6, - EVENT_FLAME_BREATH = 7, + EVENT_CORROSIVE_ACID = 1, + EVENT_FREEZE = 2, + EVENT_FLAME_BREATH = 3, + EVENT_KNOCK_AWAY = 4, + EVENT_SUMMONED = 5, }; class boss_gyth : public CreatureScript @@ -55,10 +45,7 @@ public: struct boss_gythAI : public BossAI { - boss_gythAI(Creature* creature) : BossAI(creature, DATA_GYTH) - { - DoCast(me, SPELL_SELF_ROOT_FOREVER); - } + boss_gythAI(Creature* creature) : BossAI(creature, DATA_GYTH) { } bool SummonedRend; @@ -66,17 +53,21 @@ public: { _Reset(); SummonedRend = false; - //Invisible for event start - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (instance->GetBossState(DATA_GYTH) == IN_PROGRESS) + { + instance->SetBossState(DATA_GYTH, DONE); + me->DespawnOrUnsummon(); + } } void EnterCombat(Unit* /*who*/) { _EnterCombat(); - events.ScheduleEvent(EVENT_SUMMON_DRAGON_PACK, 3 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SUMMON_ORC_PACK, 60 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_AGGRO, 60 * IN_MILLISECONDS); + + events.ScheduleEvent(EVENT_CORROSIVE_ACID, urand(8000, 16000)); + events.ScheduleEvent(EVENT_FREEZE, urand(8000, 16000)); + events.ScheduleEvent(EVENT_FLAME_BREATH, urand(8000, 16000)); + events.ScheduleEvent(EVENT_FLAME_BREATH, urand(12000, 18000)); } void JustDied(Unit* /*killer*/) @@ -84,12 +75,9 @@ public: _JustDied(); } - void SummonCreatureWithRandomTarget(uint32 creatureId, uint8 count) + void IsSummonedBy(Unit* /*summoner*/) { - for (uint8 n = 0; n < count; n++) - if (Unit* Summoned = me->SummonCreature(creatureId, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 240 * IN_MILLISECONDS)) - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true)) - Summoned->AddThreat(target, 250.0f); + events.ScheduleEvent(EVENT_SUMMONED, 8000); } void UpdateAI(uint32 diff) @@ -97,70 +85,40 @@ public: if (!UpdateVictim()) return; - if (!SummonedRend && HealthBelowPct(11)) + if (!SummonedRend && HealthBelowPct(5)) { - events.ScheduleEvent(EVENT_SUMMON_REND, 8 * IN_MILLISECONDS); + DoCast(me, SPELL_SUMMON_REND); + me->RemoveAura(SPELL_REND_MOUNTS); SummonedRend = true; } events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { - case EVENT_SUMMON_REND: - // Summon Rend and Change model to normal Gyth - // Interrupt any spell casting - me->InterruptNonMeleeSpells(false); - // Gyth model - me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); - me->SummonCreature(NPC_WARCHIEF_REND_BLACKHAND, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_CORROSIVE_ACID, 8 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_FREEZE, 11 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_FLAME_BREATH, 4 * IN_MILLISECONDS); - events.CancelEvent(EVENT_SUMMON_REND); - break; - case EVENT_AGGRO: - me->SetVisible(true); - me->SetDisplayId(MODEL_REND_ON_DRAKE); - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - events.CancelEvent(EVENT_AGGRO); - break; - // Summon Dragon pack. 2 Dragons and 3 Whelps - case EVENT_SUMMON_DRAGON_PACK: - for (uint8 i = 0; i < urand(0, 3) + 2; ++i) - { - SummonCreatureWithRandomTarget(NPC_RAGE_TALON_FIRE_TONG, 2); - SummonCreatureWithRandomTarget(NPC_CHROMATIC_WHELP, 3); - } - events.CancelEvent(EVENT_SUMMON_DRAGON_PACK); - break; - // Summon Orc pack. 1 Orc Handler 1 Elite Dragonkin and 3 Whelps - case EVENT_SUMMON_ORC_PACK: - for (uint8 i = 0; i < urand (0, 5) + 2; ++i) - { - SummonCreatureWithRandomTarget(NPC_CHROMATIC_DRAGONSPAWN, 1); - SummonCreatureWithRandomTarget(NPC_BLACKHAND_ELITE, 1); - SummonCreatureWithRandomTarget(NPC_CHROMATIC_WHELP, 3); - } - events.CancelEvent(EVENT_SUMMON_ORC_PACK); + case EVENT_SUMMONED: + DoCast(me, SPELL_REND_MOUNTS); + // Load Path break; case EVENT_CORROSIVE_ACID: - DoCastVictim(SPELL_CORROSIVE_ACID); - events.ScheduleEvent(EVENT_CORROSIVE_ACID, 7 * IN_MILLISECONDS); + DoCast(me, SPELL_CORROSIVE_ACID); + events.ScheduleEvent(EVENT_CORROSIVE_ACID, urand(10000, 16000)); break; case EVENT_FREEZE: - DoCastVictim(SPELL_FREEZE); - events.ScheduleEvent(EVENT_FREEZE, 16 * IN_MILLISECONDS); + DoCast(me, SPELL_FREEZE); + events.ScheduleEvent(EVENT_FREEZE, urand(10000, 16000)); break; case EVENT_FLAME_BREATH: - DoCastVictim(SPELL_FLAMEBREATH); - events.ScheduleEvent(EVENT_FLAME_BREATH, 10500); + DoCast(me, SPELL_FLAMEBREATH); + events.ScheduleEvent(EVENT_FLAME_BREATH, urand(10000, 16000)); + break; + case EVENT_KNOCK_AWAY: + DoCastVictim(SPELL_KNOCK_AWAY); + events.ScheduleEvent(EVENT_KNOCK_AWAY, urand(14000, 20000)); + break; + default: break; } } diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp index 44a27e6938f..24a1fbad457 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,8 +15,11 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "ObjectMgr.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "Player.h" +#include "Spell.h" #include "blackrock_spire.h" enum Text @@ -31,108 +33,395 @@ enum Text enum Spells { SPELL_ENCAGED_EMBERSEER = 15282, // Self on spawn - SPELL_FIRE_SHIELD_TRIGGER = 13377, // Self on spawn missing from 335 dbc + SPELL_FIRE_SHIELD_TRIGGER = 13377, // Self on spawn missing from 335 dbc triggers SPELL_FIRE_SHIELD every 3 sec + SPELL_FIRE_SHIELD = 13376, // Triggered by SPELL_FIRE_SHIELD_TRIGGER SPELL_FREEZE_ANIM = 16245, // Self on event start SPELL_EMBERSEER_GROWING = 16048, // Self on event start + SPELL_EMBERSEER_GROWING_TRIGGER = 16049, // Triggered by SPELL_EMBERSEER_GROWING SPELL_EMBERSEER_FULL_STRENGTH = 16047, // Emberseer Full Strength SPELL_FIRENOVA = 23462, // Combat SPELL_FLAMEBUFFET = 23341, // Combat - SPELL_PYROBLAST = 17274 // Combat + SPELL_PYROBLAST = 17274, // Combat + // Blackhand Incarcerator Spells + SPELL_ENCAGE_EMBERSEER = 15281, // Emberseer on spawn + SPELL_STRIKE = 15580, // Combat + SPELL_ENCAGE = 16045, // Combat + // Cast on player by altar + SPELL_EMBERSEER_OBJECT_VISUAL = 16532 }; enum Events { - EVENT_FIRENOVA = 1, - EVENT_FLAMEBUFFET = 2, - EVENT_PYROBLAST = 3 + // Respawn + EVENT_RESPAWN = 1, + // Pre fight + EVENT_PRE_FIGHT_1 = 2, + EVENT_PRE_FIGHT_2 = 3, + // Combat + EVENT_FIRENOVA = 4, + EVENT_FLAMEBUFFET = 5, + EVENT_PYROBLAST = 6, + // Hack due to trigger spell not in dbc + EVENT_FIRE_SHIELD = 7, + // Make sure all players have aura from altar + EVENT_PLAYER_CHECK = 8, + EVENT_ENTER_COMBAT = 9 }; - class boss_pyroguard_emberseer : public CreatureScript { public: boss_pyroguard_emberseer() : CreatureScript("boss_pyroguard_emberseer") { } - CreatureAI* GetAI(Creature* creature) const - { - return new boss_pyroguard_emberseerAI(creature); - } - struct boss_pyroguard_emberseerAI : public BossAI { boss_pyroguard_emberseerAI(Creature* creature) : BossAI(creature, DATA_PYROGAURD_EMBERSEER) {} void Reset() { - if (instance->GetBossState(DATA_PYROGAURD_EMBERSEER) == IN_PROGRESS) - OpenDoors(false); - // respawn any dead Blackhand Incarcerators - DoCast(me, SPELL_ENCAGED_EMBERSEER); - //DoCast(me, SPELL_FIRE_SHIELD_TRIGGER); - _Reset(); + if (instance) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); + events.Reset(); + // Apply auras on spawn and reset + // DoCast(me, SPELL_FIRE_SHIELD_TRIGGER); // Need to find this in old DBC if possible + + instance->SetBossState(DATA_PYROGAURD_EMBERSEER, NOT_STARTED); + me->RemoveAura(SPELL_EMBERSEER_FULL_STRENGTH); + me->RemoveAura(SPELL_EMBERSEER_GROWING); + me->RemoveAura(SPELL_EMBERSEER_GROWING_TRIGGER); + events.ScheduleEvent(EVENT_RESPAWN, 1000); + // Hack for missing trigger spell + events.ScheduleEvent(EVENT_FIRE_SHIELD, 3000); + + // Open doors on reset + if (instance->GetBossState(DATA_PYROGAURD_EMBERSEER) == IN_PROGRESS) + OpenDoors(false); // Opens 2 entrance doors + } + } + + void SetData(uint32 /*type*/, uint32 data) + { + switch (data) + { + case 1: + events.ScheduleEvent(EVENT_PLAYER_CHECK, 5000); + break; + case 2: + // Close these two doors on Blackhand Incarcerators aggro + if (GameObject* door1 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_IN))) + if (door1->GetGoState() == GO_STATE_ACTIVE) + door1->SetGoState(GO_STATE_READY); + if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetData64(GO_DOORS))) + if (door2->GetGoState() == GO_STATE_ACTIVE) + door2->SetGoState(GO_STATE_READY); + break; + case 3: + Reset(); + break; + default: + break; + } } void EnterCombat(Unit* /*who*/) { - _EnterCombat(); - events.ScheduleEvent(EVENT_FIRENOVA, 6 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_FLAMEBUFFET, 3 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_PYROBLAST, 14 * IN_MILLISECONDS); + // ### TODO Check combat timing ### + events.ScheduleEvent(EVENT_FIRENOVA, 6000); + events.ScheduleEvent(EVENT_FLAMEBUFFET, 3000); + events.ScheduleEvent(EVENT_PYROBLAST, 14000); } void JustDied(Unit* /*killer*/) { - OpenDoors(true); - _JustDied(); + if (instance) + { + // Activate all the runes + UpdateRunes(GO_STATE_READY); + // Opens all 3 doors + OpenDoors(true); + // Complete encounter + instance->SetBossState(DATA_PYROGAURD_EMBERSEER, DONE); + } + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + { + if (spell->Id == SPELL_ENCAGE_EMBERSEER) + { + if (!me->GetAuraCount(SPELL_ENCAGED_EMBERSEER)) + me->CastSpell(me, SPELL_ENCAGED_EMBERSEER); + } + + if (spell->Id == SPELL_EMBERSEER_GROWING_TRIGGER) + { + if (me->GetAuraCount(SPELL_EMBERSEER_GROWING_TRIGGER) == 10) + Talk(EMOTE_TEN_STACK); + + if (me->GetAuraCount(SPELL_EMBERSEER_GROWING_TRIGGER) == 20) + { + me->RemoveAura(SPELL_ENCAGED_EMBERSEER); + me->RemoveAura(SPELL_FREEZE_ANIM); + me->CastSpell(me, SPELL_EMBERSEER_FULL_STRENGTH); + Talk(EMOTE_FREE_OF_BONDS); + Talk(YELL_FREE_OF_BONDS); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); + events.ScheduleEvent(EVENT_ENTER_COMBAT, 2000); + } + } } void OpenDoors(bool Boss_Killed) { + // These two doors reopen on reset or boss kill if (GameObject* door1 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_IN))) door1->SetGoState(GO_STATE_ACTIVE); if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetData64(GO_DOORS))) door2->SetGoState(GO_STATE_ACTIVE); + + // This door opens on boss kill if (Boss_Killed) if (GameObject* door3 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_OUT))) door3->SetGoState(GO_STATE_ACTIVE); } - void UpdateAI(uint32 diff) + void UpdateRunes(GOState state) { - if (!UpdateVictim()) - return; + if (instance) + { + // update all runes + if (GameObject* rune1 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_RUNE_1))) + rune1->SetGoState(state); + if (GameObject* rune2 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_RUNE_2))) + rune2->SetGoState(state); + if (GameObject* rune3 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_RUNE_3))) + rune3->SetGoState(state); + if (GameObject* rune4 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_RUNE_4))) + rune4->SetGoState(state); + if (GameObject* rune5 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_RUNE_5))) + rune5->SetGoState(state); + if (GameObject* rune6 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_RUNE_6))) + rune6->SetGoState(state); + if (GameObject* rune7 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_RUNE_7))) + rune7->SetGoState(state); + } + } + void UpdateAI(uint32 diff) + { events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { + case EVENT_RESPAWN: + { + // Respawn all Blackhand Incarcerators + std::list<Creature*> creatureList; + GetCreatureListWithEntryInGrid(creatureList, me, NPC_BLACKHAND_INCARCERATOR, 35.0f); + for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + if (Creature* creatureList = *itr) + { + if (!creatureList->IsAlive()) + { + creatureList->Respawn(); + } + creatureList->AI()->SetData(1, 2); + } + break; + } + case EVENT_PRE_FIGHT_1: + { + // Set data on all Blackhand Incarcerators + std::list<Creature*> creatureList; + GetCreatureListWithEntryInGrid(creatureList, me, NPC_BLACKHAND_INCARCERATOR, 35.0f); + for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + { + if (Creature* creatureList = *itr) + creatureList->AI()->SetData(1, 1); + } + events.ScheduleEvent(EVENT_PRE_FIGHT_2, 32000); + break; + } + case EVENT_PRE_FIGHT_2: + me->CastSpell(me, SPELL_FREEZE_ANIM); + me->CastSpell(me, SPELL_EMBERSEER_GROWING); + Talk(EMOTE_ONE_STACK); + break; + case EVENT_FIRE_SHIELD: + // #### Spell isn't doing any damage ??? #### + DoCast(me, SPELL_FIRE_SHIELD); + events.ScheduleEvent(EVENT_FIRE_SHIELD, 3000); + break; + case EVENT_PLAYER_CHECK: + { + // Check to see if all players in instance have aura SPELL_EMBERSEER_START before starting event + bool _hasAura = true; + Map::PlayerList const &players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (Player* player = itr->GetSource()->ToPlayer()) + if (!player->HasAura(SPELL_EMBERSEER_OBJECT_VISUAL)) + _hasAura = false; + + if (_hasAura) + { + events.ScheduleEvent(EVENT_PRE_FIGHT_1, 1000); + instance->SetBossState(DATA_PYROGAURD_EMBERSEER, IN_PROGRESS); + } + break; + } + case EVENT_ENTER_COMBAT: + AttackStart(me->SelectNearestPlayer(30.0f)); + break; case EVENT_FIRENOVA: - DoCastVictim(SPELL_FIRENOVA); - events.ScheduleEvent(EVENT_FIRENOVA, 6 * IN_MILLISECONDS); + if (UpdateVictim()) + { + DoCast(me, SPELL_FIRENOVA); + events.ScheduleEvent(EVENT_FIRENOVA, 6000); + } break; case EVENT_FLAMEBUFFET: - DoCastVictim(SPELL_FLAMEBUFFET); - events.ScheduleEvent(EVENT_FLAMEBUFFET, 14 * IN_MILLISECONDS); + if (UpdateVictim()) + { + DoCast(me, SPELL_FLAMEBUFFET); + events.ScheduleEvent(EVENT_FLAMEBUFFET, 14000); + } break; case EVENT_PYROBLAST: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_PYROBLAST); - events.ScheduleEvent(EVENT_PYROBLAST, 15 * IN_MILLISECONDS); + if (UpdateVictim()) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_PYROBLAST); + events.ScheduleEvent(EVENT_PYROBLAST, 15000); + } + break; + default: break; } } + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_pyroguard_emberseerAI(creature); + } +}; + +/*#### +## npc_blackhand_incarcerator +####*/ + +enum IncarceratorEvents +{ + // OOC + EVENT_ENCAGED_EMBERSEER = 1, + // Combat + EVENT_STRIKE = 2, + EVENT_ENCAGE = 3 +}; + +class npc_blackhand_incarcerator : public CreatureScript +{ +public: + npc_blackhand_incarcerator() : CreatureScript("npc_blackhand_incarcerator") { } + + struct npc_blackhand_incarceratorAI : public ScriptedAI + { + npc_blackhand_incarceratorAI(Creature* creature) : ScriptedAI(creature) {} + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true)) + Emberseer->AI()->SetData(1, 3); + } + + void JustDied(Unit* /*killer*/) + { + me->DespawnOrUnsummon(10000); + } + + void SetData(uint32 data, uint32 value) + { + if (data == 1 && value == 1) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + _events.CancelEvent(EVENT_ENCAGED_EMBERSEER); + } + + if (data == 1 && value == 2) + { + _events.ScheduleEvent(EVENT_ENCAGED_EMBERSEER, 5000); + } + } + + void EnterCombat(Unit* /*who*/) + { + // Used to close doors + if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true)) + Emberseer->AI()->SetData(1, 2); + me->CallForHelp(60.0f); + _events.ScheduleEvent(EVENT_STRIKE, urand(8000, 16000)); + _events.ScheduleEvent(EVENT_ENCAGE, urand(10000, 20000)); + me->CallForHelp(60.0f); // double call because not all are aggroing on first call. + } + + void UpdateAI(uint32 diff) + { + _events.Update(diff); + + if (!UpdateVictim()) + { + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ENCAGED_EMBERSEER: + if(me->GetPositionX() == me->GetHomePosition().GetPositionX()) + if(!me->HasAura(SPELL_ENCAGE_EMBERSEER)) + if (Creature* Emberseer = me->FindNearestCreature(NPC_PYROGAURD_EMBERSEER, 30.0f, true)) + DoCast(Emberseer, SPELL_ENCAGE_EMBERSEER); + break; + } + } + return; + } + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_STRIKE: + DoCastVictim(SPELL_STRIKE, true); + _events.ScheduleEvent(EVENT_STRIKE, urand(14000, 23000)); + break; + case EVENT_ENCAGE: + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), EVENT_ENCAGE, true); + _events.ScheduleEvent(EVENT_ENCAGE, urand(6000, 12000)); + break; + default: + break; + } + } DoMeleeAttackIfReady(); } + + private: + EventMap _events; }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_blackhand_incarceratorAI(creature); + } }; void AddSC_boss_pyroguard_emberseer() { new boss_pyroguard_emberseer(); + new npc_blackhand_incarcerator(); } diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_rend_blackhand.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_rend_blackhand.cpp index 34bcedf91d7..4297ac591f7 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_rend_blackhand.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_rend_blackhand.cpp @@ -18,20 +18,107 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "Player.h" #include "blackrock_spire.h" enum Spells { - SPELL_WHIRLWIND = 26038, - SPELL_CLEAVE = 20691, - SPELL_THUNDERCLAP = 23931, //Not sure if he cast this spell + SPELL_WHIRLWIND = 13736, // sniffed + SPELL_CLEAVE = 15284, + SPELL_MORTAL_STRIKE = 16856, + SPELL_FRENZY = 8269, + SPELL_KNOCKDOWN = 13360 // On spawn during Gyth fight }; +enum Says +{ + // Rend Blackhand + SAY_BLACKHAND_1 = 0, + SAY_BLACKHAND_2 = 1, + EMOTE_BLACKHAND_DISMOUNT = 2, + // Victor Nefarius + SAY_NEFARIUS_1 = 0, + SAY_NEFARIUS_2 = 1, + SAY_NEFARIUS_3 = 2, + SAY_NEFARIUS_4 = 3, + SAY_NEFARIUS_5 = 4, + SAY_NEFARIUS_6 = 5, + SAY_NEFARIUS_7 = 6, + SAY_NEFARIUS_8 = 7, + SAY_NEFARIUS_9 = 8, + SAY_NEFARIUS_10 = 9, +}; + +enum Adds +{ + NPC_CHROMATIC_WHELP = 10442, + NPC_CHROMATIC_DRAGONSPAWN = 10447, + NPC_BLACKHAND_DRAGON_HANDLER = 10742 +}; +/* +struct Wave +{ + uint32 entry; + float x_pos; + float y_pos; + float z_pos; + float o_pos; +}; + +static Wave Wave2[]= // 22 sec +{ + { 10447, 209.8637f, -428.2729f, 110.9877f, 0.6632251f }, + { 10442, 209.3122f, -430.8724f, 110.9814f, 2.9147f }, + { 10442, 211.3309f, -425.9111f, 111.0006f, 1.727876f } +}; + +static Wave Wave3[]= // 60 sec +{ + { 10742, 208.6493f, -424.5787f, 110.9872f, 5.8294f }, + { 10447, 203.9482f, -428.9446f, 110.982f, 4.677482f }, + { 10442, 203.3441f, -426.8668f, 110.9772f, 4.712389f }, + { 10442, 206.3079f, -424.7509f, 110.9943f, 4.08407f } +}; + +static Wave Wave4[]= // 49 sec +{ + { 10742, 212.3541f, -412.6826f, 111.0352f, 5.88176f }, + { 10447, 212.5754f, -410.2841f, 111.0296f, 2.740167f }, + { 10442, 212.3449f, -414.8659f, 111.0348f, 2.356194f }, + { 10442, 210.6568f, -412.1552f, 111.0124f, 0.9773844f } +}; + +static Wave Wave5[]= // 60 sec +{ + { 10742, 210.2188f, -410.6686f, 111.0211f, 5.8294f }, + { 10447, 209.4078f, -414.13f, 111.0264f, 4.677482f }, + { 10442, 208.0858f, -409.3145f, 111.0118f, 4.642576f }, + { 10442, 207.9811f, -413.0728f, 111.0098f, 5.288348f }, + { 10442, 208.0854f, -412.1505f, 111.0057f, 4.08407f } +}; + +static Wave Wave6[]= // 27 sec +{ + { 10742, 213.9138f, -426.512f, 111.0013f, 3.316126f }, + { 10447, 213.7121f, -429.8102f, 110.9888f, 1.413717f }, + { 10447, 213.7157f, -424.4268f, 111.009f, 3.001966f }, + { 10442, 210.8935f, -423.913f, 111.0125f, 5.969026f }, + { 10442, 212.2642f, -430.7648f, 110.9807f, 5.934119f } +}; +*/ enum Events { EVENT_WHIRLWIND = 1, EVENT_CLEAVE = 2, - EVENT_THUNDERCLAP = 3, + EVENT_MORTAL_STRIKE = 3, + + EVENT_GYTH_1 = 5, + EVENT_GYTH_2 = 6, + EVENT_GYTH_3 = 7, + EVENT_GYTH_4 = 8, + EVENT_GYTH_5 = 9, + EVENT_GYTH_6 = 10, + EVENT_PORTCULLIS = 11, }; class boss_rend_blackhand : public CreatureScript @@ -39,35 +126,104 @@ class boss_rend_blackhand : public CreatureScript public: boss_rend_blackhand() : CreatureScript("boss_rend_blackhand") { } - CreatureAI* GetAI(Creature* creature) const - { - return new boss_rend_blackhandAI(creature); - } - struct boss_rend_blackhandAI : public BossAI { - boss_rend_blackhandAI(Creature* creature) : BossAI(creature, DATA_WARCHIEF_REND_BLACKHAND) {} + boss_rend_blackhandAI(Creature* creature) : BossAI(creature, DATA_WARCHIEF_REND_BLACKHAND) { } void Reset() { _Reset(); + _gythEvent = false; + _victorGUID = 0; + _portcullisGUID = 0; } void EnterCombat(Unit* /*who*/) { _EnterCombat(); - events.ScheduleEvent(EVENT_WHIRLWIND, 20 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_CLEAVE, 5 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_THUNDERCLAP, 9 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_WHIRLWIND, 13000); + events.ScheduleEvent(EVENT_CLEAVE, 15000); + events.ScheduleEvent(EVENT_MORTAL_STRIKE, 17000); } void JustDied(Unit* /*killer*/) { _JustDied(); + // Do data set on victor + } + + void SetData(uint32 type, uint32 data) + { + if (instance && type == AREATRIGGER && data == AREATRIGGER_BLACKROCK_STADIUM) + { + if (!_gythEvent) + { + _gythEvent = true; + + if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 5.0f, true)) + _victorGUID = victor->GetGUID(); + + if (GameObject* portcullis = me->FindNearestGameObject(GO_DR_PORTCULLIS, 50.0f)) + _portcullisGUID = portcullis->GetGUID(); + + if (Creature* victor = me->GetCreature(*me, _victorGUID)) + { + if (Unit* player = victor->SelectNearestPlayer(40.0f)) + { + victor->SetInFront(player); + victor->SendMovementFlagUpdate(); + } + } + } + + events.ScheduleEvent(EVENT_GYTH_1, 1000); + } } void UpdateAI(uint32 diff) { + if (_gythEvent) + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_GYTH_1: + if (Creature* victor = me->GetCreature(*me, _victorGUID)) + victor->AI()->Talk(SAY_NEFARIUS_1); + events.ScheduleEvent(EVENT_GYTH_2, 4000); + break; + case EVENT_GYTH_2: + if (Creature* victor = me->GetCreature(*me, _victorGUID)) + victor->HandleEmoteCommand(EMOTE_ONESHOT_POINT); + events.ScheduleEvent(EVENT_GYTH_3, 4000); + break; + case EVENT_GYTH_3: + if (Creature* victor = me->GetCreature(*me, _victorGUID)) + victor->AI()->Talk(SAY_NEFARIUS_2); + events.ScheduleEvent(EVENT_PORTCULLIS, 2000); + events.ScheduleEvent(EVENT_GYTH_4, 4000); + break; + case EVENT_GYTH_4: + if (Creature* victor = me->GetCreature(*me, _victorGUID)) + { + victor->SetInFront(me); + victor->SendMovementFlagUpdate(); + } + break; + case EVENT_PORTCULLIS: + if (GameObject* portcullis = me->FindNearestGameObject(GO_DR_PORTCULLIS, 50.0f)) + portcullis->UseDoorOrButton(); + // move wave + break; + default: + break; + } + } + } + if (!UpdateVictim()) return; @@ -81,22 +237,32 @@ public: switch (eventId) { case EVENT_WHIRLWIND: - DoCastVictim(SPELL_WHIRLWIND); - events.ScheduleEvent(EVENT_WHIRLWIND, 18 * IN_MILLISECONDS); + DoCast(SPELL_WHIRLWIND); + events.ScheduleEvent(EVENT_WHIRLWIND, urand(13000, 18000)); break; case EVENT_CLEAVE: DoCastVictim(SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, 10 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_CLEAVE, 10000); break; - case EVENT_THUNDERCLAP: - DoCastVictim(SPELL_THUNDERCLAP); - events.ScheduleEvent(EVENT_THUNDERCLAP, 16 * IN_MILLISECONDS); + case EVENT_MORTAL_STRIKE: + DoCastVictim(SPELL_MORTAL_STRIKE); + events.ScheduleEvent(EVENT_MORTAL_STRIKE, 16000); break; } } DoMeleeAttackIfReady(); } + private: + bool _gythEvent; + uint64 _victorGUID; + uint64 _portcullisGUID; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_rend_blackhandAI(creature); + } }; void AddSC_boss_rend_blackhand() diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp index 06ba0036ef3..7b80f75255a 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp @@ -15,50 +15,37 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "ObjectMgr.h" #include "ScriptMgr.h" +#include "ObjectDefines.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "InstanceScript.h" #include "ScriptedCreature.h" #include "blackrock_spire.h" +uint32 const DragonspireRunes[7] = { GO_HALL_RUNE_1, GO_HALL_RUNE_2, GO_HALL_RUNE_3, GO_HALL_RUNE_4, GO_HALL_RUNE_5, GO_HALL_RUNE_6, GO_HALL_RUNE_7 }; + +uint32 const DragonspireMobs[3] = { NPC_BLACKHAND_DREADWEAVER, NPC_BLACKHAND_SUMMONER, NPC_BLACKHAND_VETERAN }; + +enum EventIds +{ + EVENT_DARGONSPIRE_ROOM_STORE = 1, + EVENT_DARGONSPIRE_ROOM_CHECK = 2 +}; + class instance_blackrock_spire : public InstanceMapScript { public: - instance_blackrock_spire() : InstanceMapScript("instance_blackrock_spire", 229) { } - - InstanceScript* GetInstanceScript(InstanceMap* map) const - { - return new instance_blackrock_spireMapScript(map); - } + instance_blackrock_spire() : InstanceMapScript(BRSScriptName, 229) { } struct instance_blackrock_spireMapScript : public InstanceScript { - instance_blackrock_spireMapScript(InstanceMap* map) : InstanceScript(map) {} - - uint32 encounter[MAX_ENCOUNTER]; - std::string m_strInstData; - uint64 HighlordOmokk; - uint64 ShadowHunterVoshgajin; - uint64 WarMasterVoone; - uint64 MotherSmolderweb; - uint64 UrokDoomhowl; - uint64 QuartermasterZigris; - uint64 GizrultheSlavener; - uint64 Halycon; - uint64 OverlordWyrmthalak; - uint64 PyroguardEmberseer; - uint64 WarchiefRendBlackhand; - uint64 Gyth; - uint64 TheBeast; - uint64 GeneralDrakkisath; - uint64 go_emberseerin; - uint64 go_doors; - uint64 go_emberseerout; - uint64 go_roomrunes[MAX_DRAGONSPIRE_HALL_RUNES]; - uint8 Runemaxprotectors[MAX_DRAGONSPIRE_HALL_RUNES]; - uint8 Runeprotectorsdead[MAX_DRAGONSPIRE_HALL_RUNES]; - - void Initialize() + instance_blackrock_spireMapScript(InstanceMap* map) : InstanceScript(map) { - SetBossNumber(MAX_ENCOUNTER); + SetBossNumber(EncounterCount); HighlordOmokk = 0; ShadowHunterVoshgajin = 0; WarMasterVoone = 0; @@ -76,16 +63,7 @@ public: go_emberseerin = 0; go_doors = 0; go_emberseerout = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (encounter[i] == IN_PROGRESS) - return true; - } - return false; + go_blackrockaltar = 0; } void OnCreatureCreate(Creature* creature) @@ -121,6 +99,8 @@ public: break; case NPC_PYROGAURD_EMBERSEER: PyroguardEmberseer = creature->GetGUID(); + if (GetBossState(DATA_PYROGAURD_EMBERSEER) == DONE) + creature->DisappearAndDie(); break; case NPC_WARCHIEF_REND_BLACKHAND: WarchiefRendBlackhand = creature->GetGUID(); @@ -150,33 +130,88 @@ public: break; case GO_EMBERSEER_IN: go_emberseerin = go->GetGUID(); + if (GetBossState(DATA_DRAGONSPIRE_ROOM) == DONE) + HandleGameObject(0, true, go); break; case GO_DOORS: go_doors = go->GetGUID(); + if (GetBossState(DATA_DRAGONSPIRE_ROOM) == DONE) + HandleGameObject(0, true, go); break; case GO_EMBERSEER_OUT: go_emberseerout = go->GetGUID(); + if (GetBossState(DATA_PYROGAURD_EMBERSEER) == DONE) + HandleGameObject(0, true, go); break; - case GO_ROOM_1_RUNE: + case GO_HALL_RUNE_1: go_roomrunes[0] = go->GetGUID(); + if (GetBossState(DATA_HALL_RUNE_1) == DONE) + HandleGameObject(0, false, go); break; - case GO_ROOM_2_RUNE: + case GO_HALL_RUNE_2: go_roomrunes[1] = go->GetGUID(); + if (GetBossState(DATA_HALL_RUNE_2) == DONE) + HandleGameObject(0, false, go); break; - case GO_ROOM_3_RUNE: + case GO_HALL_RUNE_3: go_roomrunes[2] = go->GetGUID(); + if (GetBossState(DATA_HALL_RUNE_3) == DONE) + HandleGameObject(0, false, go); break; - case GO_ROOM_4_RUNE: + case GO_HALL_RUNE_4: go_roomrunes[3] = go->GetGUID(); + if (GetBossState(DATA_HALL_RUNE_4) == DONE) + HandleGameObject(0, false, go); break; - case GO_ROOM_5_RUNE: + case GO_HALL_RUNE_5: go_roomrunes[4] = go->GetGUID(); + if (GetBossState(DATA_HALL_RUNE_5) == DONE) + HandleGameObject(0, false, go); break; - case GO_ROOM_6_RUNE: + case GO_HALL_RUNE_6: go_roomrunes[5] = go->GetGUID(); + if (GetBossState(DATA_HALL_RUNE_6) == DONE) + HandleGameObject(0, false, go); break; - case GO_ROOM_7_RUNE: + case GO_HALL_RUNE_7: go_roomrunes[6] = go->GetGUID(); + if (GetBossState(DATA_HALL_RUNE_7) == DONE) + HandleGameObject(0, false, go); + break; + case GO_EMBERSEER_RUNE_1: + go_emberseerrunes[0] = go->GetGUID(); + if (GetBossState(DATA_PYROGAURD_EMBERSEER) == DONE) + HandleGameObject(0, false, go); + break; + case GO_EMBERSEER_RUNE_2: + go_emberseerrunes[1] = go->GetGUID(); + if (GetBossState(DATA_PYROGAURD_EMBERSEER) == DONE) + HandleGameObject(0, false, go); + break; + case GO_EMBERSEER_RUNE_3: + go_emberseerrunes[2] = go->GetGUID(); + if (GetBossState(DATA_PYROGAURD_EMBERSEER) == DONE) + HandleGameObject(0, false, go); + break; + case GO_EMBERSEER_RUNE_4: + go_emberseerrunes[3] = go->GetGUID(); + if (GetBossState(DATA_PYROGAURD_EMBERSEER) == DONE) + HandleGameObject(0, false, go); + break; + case GO_EMBERSEER_RUNE_5: + go_emberseerrunes[4] = go->GetGUID(); + if (GetBossState(DATA_PYROGAURD_EMBERSEER) == DONE) + HandleGameObject(0, false, go); + break; + case GO_EMBERSEER_RUNE_6: + go_emberseerrunes[5] = go->GetGUID(); + if (GetBossState(DATA_PYROGAURD_EMBERSEER) == DONE) + HandleGameObject(0, false, go); + break; + case GO_EMBERSEER_RUNE_7: + go_emberseerrunes[6] = go->GetGUID(); + if (GetBossState(DATA_PYROGAURD_EMBERSEER) == DONE) + HandleGameObject(0, false, go); break; } } @@ -202,6 +237,7 @@ public: case DATA_GYTH: case DATA_THE_BEAST: case DATA_GENERAL_DRAKKISATH: + case DATA_DRAGONSPIRE_ROOM: break; default: break; @@ -216,8 +252,26 @@ public: { case EVENT_PYROGUARD_EMBERSEER: if (GetBossState(DATA_PYROGAURD_EMBERSEER) == NOT_STARTED) - SetBossState(DATA_PYROGAURD_EMBERSEER, IN_PROGRESS); + { + if (Creature* Emberseer = instance->GetCreature(PyroguardEmberseer)) + Emberseer->AI()->SetData(1, 1); + } + break; + default: break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch (type) + { + case AREATRIGGER: + if (data == AREATRIGGER_DRAGONSPIRE_HALL) + { + if (GetBossState(DATA_DRAGONSPIRE_ROOM) != DONE) + Events.ScheduleEvent(EVENT_DARGONSPIRE_ROOM_STORE, 1000); + } default: break; } @@ -229,57 +283,215 @@ public: { case DATA_OMOKK: return HighlordOmokk; + break; case DATA_SHADOW_HUNTER_VOSHGAJIN: return ShadowHunterVoshgajin; + break; case DATA_WARMASTER_VOONE: return WarMasterVoone; + break; case DATA_MOTHER_SMOLDERWEB: return MotherSmolderweb; + break; case DATA_UROK_DOOMHOWL: return UrokDoomhowl; + break; case DATA_QUARTERMASTER_ZIGRIS: return QuartermasterZigris; + break; case DATA_GIZRUL_THE_SLAVENER: return GizrultheSlavener; + break; case DATA_HALYCON: return Halycon; + break; case DATA_OVERLORD_WYRMTHALAK: return OverlordWyrmthalak; + break; case DATA_PYROGAURD_EMBERSEER: return PyroguardEmberseer; + break; case DATA_WARCHIEF_REND_BLACKHAND: return WarchiefRendBlackhand; + break; case DATA_GYTH: return Gyth; + break; case DATA_THE_BEAST: return TheBeast; + break; case DATA_GENERAL_DRAKKISATH: return GeneralDrakkisath; + break; case GO_EMBERSEER_IN: return go_emberseerin; + break; case GO_DOORS: return go_doors; + break; case GO_EMBERSEER_OUT: return go_emberseerout; - case GO_ROOM_1_RUNE: + break; + case GO_HALL_RUNE_1: return go_roomrunes[0]; - case GO_ROOM_2_RUNE: + break; + case GO_HALL_RUNE_2: return go_roomrunes[1]; - case GO_ROOM_3_RUNE: + break; + case GO_HALL_RUNE_3: return go_roomrunes[2]; - case GO_ROOM_4_RUNE: + break; + case GO_HALL_RUNE_4: return go_roomrunes[3]; - case GO_ROOM_5_RUNE: + break; + case GO_HALL_RUNE_5: return go_roomrunes[4]; - case GO_ROOM_6_RUNE: + break; + case GO_HALL_RUNE_6: return go_roomrunes[5]; - case GO_ROOM_7_RUNE: + break; + case GO_HALL_RUNE_7: return go_roomrunes[6]; + break; + case GO_EMBERSEER_RUNE_1: + return go_emberseerrunes[0]; + break; + case GO_EMBERSEER_RUNE_2: + return go_emberseerrunes[1]; + break; + case GO_EMBERSEER_RUNE_3: + return go_emberseerrunes[2]; + break; + case GO_EMBERSEER_RUNE_4: + return go_emberseerrunes[3]; + break; + case GO_EMBERSEER_RUNE_5: + return go_emberseerrunes[4]; + break; + case GO_EMBERSEER_RUNE_6: + return go_emberseerrunes[5]; + break; + case GO_EMBERSEER_RUNE_7: + return go_emberseerrunes[6]; + break; } - return 0; } + void Update(uint32 diff) + { + Events.Update(diff); + + while (uint32 eventId = Events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DARGONSPIRE_ROOM_STORE: + Dragonspireroomstore(); + Events.ScheduleEvent(EVENT_DARGONSPIRE_ROOM_CHECK, 3000); + break; + case EVENT_DARGONSPIRE_ROOM_CHECK: + Dragonspireroomcheck(); + if ((GetBossState(DATA_DRAGONSPIRE_ROOM) != DONE)) + Events.ScheduleEvent(EVENT_DARGONSPIRE_ROOM_CHECK, 3000); + break; + default: + break; + } + } + } + + void Dragonspireroomstore() + { + uint8 creaturecount; + + for (uint8 i = 0; i < 7; ++i) + { + creaturecount = 0; + + if (GameObject* rune = instance->GetGameObject(go_roomrunes[i])) + { + for (uint8 ii = 0; ii < 3; ++ii) + { + std::list<Creature*> creatureList; + GetCreatureListWithEntryInGrid(creatureList, rune, DragonspireMobs[ii], 15.0f); + for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + { + if (Creature* creatureList = *itr) + { + runecreaturelist[i] [creaturecount] = creatureList->GetGUID(); + ++creaturecount; + } + } + } + } + } + } + + void Dragonspireroomcheck() + { + Creature* mob = NULL; + GameObject* rune = NULL; + + for (uint8 i = 0; i < 7; ++i) + { + bool _mobAlive = false; + rune = instance->GetGameObject(go_roomrunes[i]); + if (rune && rune->GetGoState() == GO_STATE_ACTIVE) + { + for (uint8 ii = 0; ii < 5; ++ii) + { + mob = instance->GetCreature(runecreaturelist[i][ii]); + if (mob && mob->IsAlive()) + _mobAlive = true; + } + } + + if (!_mobAlive && rune->GetGoState() == GO_STATE_ACTIVE) + { + HandleGameObject(0, false, rune); + + switch (rune->GetEntry()) + { + case GO_HALL_RUNE_1: + SetBossState(DATA_HALL_RUNE_1, DONE); + break; + case GO_HALL_RUNE_2: + SetBossState(DATA_HALL_RUNE_2, DONE); + break; + case GO_HALL_RUNE_3: + SetBossState(DATA_HALL_RUNE_3, DONE); + break; + case GO_HALL_RUNE_4: + SetBossState(DATA_HALL_RUNE_4, DONE); + break; + case GO_HALL_RUNE_5: + SetBossState(DATA_HALL_RUNE_5, DONE); + break; + case GO_HALL_RUNE_6: + SetBossState(DATA_HALL_RUNE_6, DONE); + break; + case GO_HALL_RUNE_7: + SetBossState(DATA_HALL_RUNE_7, DONE); + break; + default: + break; + } + } + } + + if (GetBossState(DATA_HALL_RUNE_1) == DONE && GetBossState(DATA_HALL_RUNE_2) == DONE && GetBossState(DATA_HALL_RUNE_3) == DONE && + GetBossState(DATA_HALL_RUNE_4) == DONE && GetBossState(DATA_HALL_RUNE_5) == DONE && GetBossState(DATA_HALL_RUNE_6) == DONE && + GetBossState(DATA_HALL_RUNE_7) == DONE) + { + SetBossState(DATA_DRAGONSPIRE_ROOM, DONE); + if (GameObject* door1 = instance->GetGameObject(go_emberseerin)) + HandleGameObject(0, true, door1); + if (GameObject* door2 = instance->GetGameObject(go_doors)) + HandleGameObject(0, true, door2); + } + } + std::string GetSaveData() { OUT_SAVE_INST_DATA; @@ -308,22 +520,109 @@ public: if (dataHead1 == 'B' && dataHead2 == 'S') { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + for (uint8 i = 0; i < EncounterCount; ++i) { uint32 tmpState; loadStream >> tmpState; if (tmpState == IN_PROGRESS || tmpState > SPECIAL) tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); } } + else + OUT_LOAD_INST_DATA_FAIL; OUT_LOAD_INST_DATA_COMPLETE; } + + protected: + EventMap Events; + uint32 encounter[EncounterCount]; + std::string m_strInstData; + uint64 HighlordOmokk; + uint64 ShadowHunterVoshgajin; + uint64 WarMasterVoone; + uint64 MotherSmolderweb; + uint64 UrokDoomhowl; + uint64 QuartermasterZigris; + uint64 GizrultheSlavener; + uint64 Halycon; + uint64 OverlordWyrmthalak; + uint64 PyroguardEmberseer; + uint64 WarchiefRendBlackhand; + uint64 Gyth; + uint64 TheBeast; + uint64 GeneralDrakkisath; + uint64 go_emberseerin; + uint64 go_doors; + uint64 go_emberseerout; + uint64 go_blackrockaltar; + uint64 go_roomrunes[7]; + uint64 go_emberseerrunes[7]; + uint64 runecreaturelist[7] [5]; }; + InstanceScript* GetInstanceScript(InstanceMap* map) const + { + return new instance_blackrock_spireMapScript(map); + } +}; + +/*##### +# at_dragonspire_hall +#####*/ + +class at_dragonspire_hall : public AreaTriggerScript +{ +public: + at_dragonspire_hall() : AreaTriggerScript("at_dragonspire_hall") { } + + bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) + { + if (player && player->IsAlive()) + { + if (InstanceScript* instance = player->GetInstanceScript()) + { + instance->SetData(AREATRIGGER, AREATRIGGER_DRAGONSPIRE_HALL); + return true; + } + } + + return false; + } +}; + +/*##### +# at_blackrock_stadium +#####*/ + +class at_blackrock_stadium : public AreaTriggerScript +{ +public: + at_blackrock_stadium() : AreaTriggerScript("at_blackrock_stadium") { } + + bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) + { + if (player && player->IsAlive()) + { + InstanceScript* instance = player->GetInstanceScript(); + if (!instance) + return false; + + if (Creature* rend = player->FindNearestCreature(NPC_REND_BLACKHAND, 50.0f)) + { + rend->AI()->SetData(AREATRIGGER, AREATRIGGER_BLACKROCK_STADIUM); + return true; + } + } + + return false; + } }; void AddSC_instance_blackrock_spire() { new instance_blackrock_spire(); + new at_dragonspire_hall(); + new at_blackrock_stadium(); } diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/blackwing_lair.h b/src/server/scripts/EasternKingdoms/BlackwingLair/blackwing_lair.h new file mode 100644 index 00000000000..acdbf0cd483 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/blackwing_lair.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DEF_BLACKWING_LAIR_H +#define DEF_BLACKWING_LAIR_H + +uint32 const EncounterCount = 8; + +#define BRLScriptName "instance_blackwing_lair" + +enum BWLEncounter +{ + BOSS_RAZORGORE = 0, + BOSS_VAELASTRAZ = 1, + BOSS_BROODLORD = 2, + BOSS_FIREMAW = 3, + BOSS_EBONROC = 4, + BOSS_FLAMEGOR = 5, + BOSS_CHROMAGGUS = 6, + BOSS_NEFARIAN = 7 +}; + +enum CreatureIds +{ + NPC_RAZORGORE = 12435, + NPC_BLACKWING_DRAGON = 12422, + NPC_BLACKWING_TASKMASTER = 12458, + NPC_BLACKWING_LEGIONAIRE = 12416, + NPC_BLACKWING_WARLOCK = 12459, + NPC_VAELASTRAZ = 13020, + NPC_BROODLORD = 12017, + NPC_FIRENAW = 11983, + NPC_EBONROC = 14601, + NPC_FLAMEGOR = 11981, + NPC_CHROMAGGUS = 14020, + NPC_VICTOR_NEFARIUS = 10162, + NPC_NEFARIAN = 11583 +}; + +enum BWLData64 +{ + DATA_RAZORGORE_THE_UNTAMED = 1, + DATA_VAELASTRAZ_THE_CORRUPT, + DATA_BROODLORD_LASHLAYER, + DATA_FIRENAW, + DATA_EBONROC, + DATA_FLAMEGOR, + DATA_CHROMAGGUS, + DATA_LORD_VICTOR_NEFARIUS, + DATA_NEFARIAN +}; + +enum BWLEvents +{ + EVENT_RAZOR_SPAWN = 1, + EVENT_RAZOR_PHASE_TWO = 2, + EVENT_RESPAWN_NEFARIUS = 3 +}; + +enum BWLMisc +{ + // Razorgore Egg Event + ACTION_PHASE_TWO = 1, + DATA_EGG_EVENT +}; + +#endif
\ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp index 5c05d365e00..d4a9d81fdb0 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -16,36 +16,31 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Broodlord_Lashlayer -SD%Complete: 100 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "blackwing_lair.h" enum Say { SAY_AGGRO = 0, - SAY_LEASH = 1, + SAY_LEASH = 1 }; -enum Events +enum Spells { - EVENT_CLEAVE = 1, - EVENT_MORTAL_STRIKE = 2, - EVENT_BLAST_WAVE = 3, - EVENT_KNOCK_BACK = 4, + SPELL_CLEAVE = 26350, + SPELL_BLASTWAVE = 23331, + SPELL_MORTALSTRIKE = 24573, + SPELL_KNOCKBACK = 25778 }; -enum Spells +enum Events { - SPELL_CLEAVE = 26350, - SPELL_BLAST_WAVE = 23331, - SPELL_MORTAL_STRIKE = 24573, - SPELL_KNOCK_BACK = 25778 + EVENT_CLEAVE = 1, + EVENT_BLASTWAVE = 2, + EVENT_MORTALSTRIKE = 3, + EVENT_KNOCKBACK = 4, + EVENT_CHECK = 5 }; class boss_broodlord : public CreatureScript @@ -53,28 +48,26 @@ class boss_broodlord : public CreatureScript public: boss_broodlord() : CreatureScript("boss_broodlord") { } - CreatureAI* GetAI(Creature* creature) const - { - return new boss_broodlordAI (creature); - } - - struct boss_broodlordAI : public ScriptedAI + struct boss_broodlordAI : public BossAI { - boss_broodlordAI(Creature* creature) : ScriptedAI(creature) {} - - void Reset() - { - // 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); - } + boss_broodlordAI(Creature* creature) : BossAI(creature, BOSS_BROODLORD) { } void EnterCombat(Unit* /*who*/) { + if (instance->GetBossState(BOSS_VAELASTRAZ) != DONE) + { + EnterEvadeMode(); + return; + } + + _EnterCombat(); Talk(SAY_AGGRO); - DoZoneInCombat(); + + events.ScheduleEvent(EVENT_CLEAVE, 8000); + events.ScheduleEvent(EVENT_BLASTWAVE, 12000); + events.ScheduleEvent(EVENT_MORTALSTRIKE, 20000); + events.ScheduleEvent(EVENT_KNOCKBACK, 30000); + events.ScheduleEvent(EVENT_CHECK, 1000); } void UpdateAI(uint32 diff) @@ -82,11 +75,7 @@ public: if (!UpdateVictim()) return; - if (EnterEvadeIfOutOfCombatArea(diff)) - Talk(SAY_LEASH); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + events.Update(diff); while (uint32 eventId = events.ExecuteEvent()) { @@ -94,40 +83,41 @@ public: { case EVENT_CLEAVE: DoCastVictim(SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, 8000); + events.ScheduleEvent(EVENT_CLEAVE, 7000); + break; + case EVENT_BLASTWAVE: + DoCastVictim(SPELL_BLASTWAVE); + events.ScheduleEvent(EVENT_BLASTWAVE, urand(8000, 16000)); break; - case EVENT_MORTAL_STRIKE: - DoCastVictim(SPELL_MORTAL_STRIKE); - events.ScheduleEvent(EVENT_MORTAL_STRIKE, 20000); + case EVENT_MORTALSTRIKE: + DoCastVictim(SPELL_MORTALSTRIKE); + events.ScheduleEvent(EVENT_MORTALSTRIKE, urand(25000, 35000)); break; - case EVENT_BLAST_WAVE: - DoCastVictim(SPELL_BLAST_WAVE); - events.ScheduleEvent(EVENT_BLAST_WAVE, 12000); + case EVENT_KNOCKBACK: + DoCastVictim(SPELL_KNOCKBACK); + if (DoGetThreat(me->GetVictim())) + DoModifyThreatPercent(me->GetVictim(), -50); + events.ScheduleEvent(EVENT_KNOCKBACK, urand(15000, 30000)); break; - case EVENT_KNOCK_BACK: - if (Unit* target = me->GetVictim()) + case EVENT_CHECK: + if (me->GetDistance(me->GetHomePosition()) > 150.0f) { - DoCast(target, SPELL_BLAST_WAVE); - // Drop 50% of threat - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -50); + Talk(SAY_LEASH); + EnterEvadeMode(); } - events.ScheduleEvent(EVENT_KNOCK_BACK, 30000); - break; - default: + events.ScheduleEvent(EVENT_CHECK, 1000); break; } } - if (EnterEvadeIfOutOfCombatArea(diff)) - Talk(SAY_LEASH); - DoMeleeAttackIfReady(); } - - private: - EventMap events; /// @todo: change BWL to instance script and bosses to BossAI }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_broodlordAI (creature); + } }; void AddSC_boss_broodlord() diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_chromaggus.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_chromaggus.cpp index 9698d8c147f..b6eb97ac64c 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_chromaggus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_chromaggus.cpp @@ -16,15 +16,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Chromaggus -SD%Complete: 95 -SDComment: Chromatic Mutation disabled due to lack of core support -SDCategory: Blackwing Lair -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "Player.h" +#include "blackwing_lair.h" enum Emotes { @@ -34,22 +29,22 @@ enum Emotes enum Spells { - //These spells are actually called elemental shield - //What they do is decrease all damage by 75% then they increase - //One school of damage by 1100% + // These spells are actually called elemental shield + // What they do is decrease all damage by 75% then they increase + // One school of damage by 1100% SPELL_FIRE_VULNERABILITY = 22277, SPELL_FROST_VULNERABILITY = 22278, SPELL_SHADOW_VULNERABILITY = 22279, SPELL_NATURE_VULNERABILITY = 22280, SPELL_ARCANE_VULNERABILITY = 22281, - //Other spells + // Other spells SPELL_INCINERATE = 23308, //Incinerate 23308, 23309 SPELL_TIMELAPSE = 23310, //Time lapse 23310, 23311(old threat mod that was removed in 2.01) SPELL_CORROSIVEACID = 23313, //Corrosive Acid 23313, 23314 SPELL_IGNITEFLESH = 23315, //Ignite Flesh 23315, 23316 SPELL_FROSTBURN = 23187, //Frost burn 23187, 23189 - //Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them - //Since Scripted spells arn't coded I'll just write a function that does the same thing + // Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them + // Since Scripted spells arn't coded I'll just write a function that does the same thing SPELL_BROODAF_BLUE = 23153, //Blue affliction 23153 SPELL_BROODAF_BLACK = 23154, //Black affliction 23154 SPELL_BROODAF_RED = 23155, //Red affliction 23155 (23168 on death) @@ -60,27 +55,31 @@ enum Spells SPELL_ENRAGE = 28747 }; +enum Events +{ + EVENT_SHIMMER = 1, + EVENT_BREATH_1 = 2, + EVENT_BREATH_2 = 3, + EVENT_AFFLICTION = 4, + EVENT_FRENZY = 5 +}; + class boss_chromaggus : public CreatureScript { public: boss_chromaggus() : CreatureScript("boss_chromaggus") { } - CreatureAI* GetAI(Creature* creature) const + struct boss_chromaggusAI : public BossAI { - return new boss_chromaggusAI (creature); - } - - struct boss_chromaggusAI : public ScriptedAI - { - boss_chromaggusAI(Creature* creature) : ScriptedAI(creature) + boss_chromaggusAI(Creature* creature) : BossAI(creature, BOSS_CHROMAGGUS) { - //Select the 2 breaths that we are going to use until despawned - //5 possiblities for the first breath, 4 for the second, 20 total possiblites - //This way we don't end up casting 2 of the same breath - //TL TL would be stupid + // Select the 2 breaths that we are going to use until despawned + // 5 possiblities for the first breath, 4 for the second, 20 total possiblites + // This way we don't end up casting 2 of the same breath + // TL TL would be stupid switch (urand(0, 19)) { - //B1 - Incin + // B1 - Incin case 0: Breath1_Spell = SPELL_INCINERATE; Breath2_Spell = SPELL_TIMELAPSE; @@ -98,7 +97,7 @@ public: Breath2_Spell = SPELL_FROSTBURN; break; - //B1 - TL + // B1 - TL case 4: Breath1_Spell = SPELL_TIMELAPSE; Breath2_Spell = SPELL_INCINERATE; @@ -174,117 +173,97 @@ public: EnterEvadeMode(); } - uint32 Breath1_Spell; - uint32 Breath2_Spell; - uint32 CurrentVurln_Spell; - - uint32 Shimmer_Timer; - uint32 Breath1_Timer; - uint32 Breath2_Timer; - uint32 Affliction_Timer; - uint32 Frenzy_Timer; - bool Enraged; - void Reset() { - CurrentVurln_Spell = 0; //We use this to store our last vulnerabilty spell so we can remove it later - - Shimmer_Timer = 0; //Time till we change vurlnerabilites - Breath1_Timer = 30000; //First breath is 30 seconds - Breath2_Timer = 60000; //Second is 1 minute so that we can alternate - Affliction_Timer = 10000; //This is special - 5 seconds means that we cast this on 1 player every 5 sconds - Frenzy_Timer = 15000; + _Reset(); + CurrentVurln_Spell = 0; // We use this to store our last vulnerabilty spell so we can remove it later Enraged = false; } - void EnterCombat(Unit* /*who*/) {} + void EnterCombat(Unit* /*who*/) + { + if (instance && instance->GetBossState(BOSS_FLAMEGOR) != DONE) + { + EnterEvadeMode(); + return; + } + _EnterCombat(); + + events.ScheduleEvent(EVENT_SHIMMER, 0); + events.ScheduleEvent(EVENT_BREATH_1, 30000); + events.ScheduleEvent(EVENT_BREATH_2, 60000); + events.ScheduleEvent(EVENT_AFFLICTION, 10000); + events.ScheduleEvent(EVENT_FRENZY, 15000); + } void UpdateAI(uint32 diff) { if (!UpdateVictim()) return; - //Shimmer_Timer Timer - if (Shimmer_Timer <= diff) - { - //Remove old vulnerabilty spell - if (CurrentVurln_Spell) - me->RemoveAurasDueToSpell(CurrentVurln_Spell); - - //Cast new random vulnerabilty on self - uint32 spell = RAND(SPELL_FIRE_VULNERABILITY, SPELL_FROST_VULNERABILITY, - SPELL_SHADOW_VULNERABILITY, SPELL_NATURE_VULNERABILITY, SPELL_ARCANE_VULNERABILITY); - - DoCast(me, spell); - CurrentVurln_Spell = spell; + events.Update(diff); - Talk(EMOTE_SHIMMER); - Shimmer_Timer = 45000; - } else Shimmer_Timer -= diff; - - //Breath1_Timer - if (Breath1_Timer <= diff) - { - DoCastVictim(Breath1_Spell); - Breath1_Timer = 60000; - } else Breath1_Timer -= diff; - - //Breath2_Timer - if (Breath2_Timer <= diff) - { - DoCastVictim(Breath2_Spell); - Breath2_Timer = 60000; - } else Breath2_Timer -= diff; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - //Affliction_Timer - if (Affliction_Timer <= diff) + while (uint32 eventId = events.ExecuteEvent()) { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) + switch (eventId) { - if ((*i) && (*i)->GetSource()) - { - if (Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid())) + case EVENT_SHIMMER: { - //Cast affliction - DoCast(unit, RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, - SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN), true); - - //Chromatic mutation if target is effected by all afflictions - if (unit->HasAura(SPELL_BROODAF_BLUE) - && unit->HasAura(SPELL_BROODAF_BLACK) - && unit->HasAura(SPELL_BROODAF_RED) - && unit->HasAura(SPELL_BROODAF_BRONZE) - && unit->HasAura(SPELL_BROODAF_GREEN)) + // Remove old vulnerabilty spell + if (CurrentVurln_Spell) + me->RemoveAurasDueToSpell(CurrentVurln_Spell); + + // Cast new random vulnerabilty on self + uint32 spell = RAND(SPELL_FIRE_VULNERABILITY, SPELL_FROST_VULNERABILITY, SPELL_SHADOW_VULNERABILITY, SPELL_NATURE_VULNERABILITY, SPELL_ARCANE_VULNERABILITY); + DoCast(me, spell); + CurrentVurln_Spell = spell; + Talk(EMOTE_SHIMMER); + events.ScheduleEvent(EVENT_SHIMMER, 45000); + break; + } + case EVENT_BREATH_1: + DoCastVictim(Breath1_Spell); + events.ScheduleEvent(EVENT_BREATH_1, 60000); + break; + case EVENT_BREATH_2: + DoCastVictim(Breath2_Spell); + events.ScheduleEvent(EVENT_BREATH_2, 60000); + break; + case EVENT_AFFLICTION: + { + Map::PlayerList const &players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { - //target->RemoveAllAuras(); - //DoCast(target, SPELL_CHROMATIC_MUT_1); - - //Chromatic mutation is causing issues - //Assuming it is caused by a lack of core support for Charm - //So instead we instant kill our target - - //WORKAROUND - if (unit->GetTypeId() == TYPEID_PLAYER) - unit->CastSpell(unit, 5, false); + if (Player* player = itr->GetSource()->ToPlayer()) + { + DoCast(player, RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN), true); + + if (player->HasAura(SPELL_BROODAF_BLUE) && + player->HasAura(SPELL_BROODAF_BLACK) && + player->HasAura(SPELL_BROODAF_RED) && + player->HasAura(SPELL_BROODAF_BRONZE) && + player->HasAura(SPELL_BROODAF_GREEN)) + { + DoCast(player, SPELL_CHROMATIC_MUT_1); + } + + } } } - } + events.ScheduleEvent(EVENT_AFFLICTION, 10000); + break; + case EVENT_FRENZY: + DoCast(me, SPELL_FRENZY); + events.ScheduleEvent(EVENT_FRENZY, urand(10000, 15000)); + break; } + } - Affliction_Timer = 10000; - } else Affliction_Timer -= diff; - - //Frenzy_Timer - if (Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - Talk(EMOTE_FRENZY); - Frenzy_Timer = urand(10000, 15000); - } else Frenzy_Timer -= diff; - - //Enrage if not already enraged and below 20% + // Enrage if not already enraged and below 20% if (!Enraged && HealthBelowPct(20)) { DoCast(me, SPELL_ENRAGE); @@ -293,7 +272,18 @@ public: DoMeleeAttackIfReady(); } + + private: + uint32 Breath1_Spell; + uint32 Breath2_Spell; + uint32 CurrentVurln_Spell; + bool Enraged; }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_chromaggusAI (creature); + } }; void AddSC_boss_chromaggus() diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp index 04b99c76105..7d21825851a 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp @@ -16,54 +16,45 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Ebonroc -SD%Complete: 50 -SDComment: Shadow of Ebonroc needs core support -SDCategory: Blackwing Lair -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "blackwing_lair.h" + +enum Spells +{ + SPELL_SHADOWFLAME = 22539, + SPELL_WINGBUFFET = 23339, + SPELL_SHADOWOFEBONROC = 23340 +}; -#define SPELL_SHADOWFLAME 22539 -#define SPELL_WINGBUFFET 23339 -#define SPELL_SHADOWOFEBONROC 23340 -#define SPELL_HEAL 41386 //The Heal spell of his Shadow -#define SPELL_THRASH 3391 +enum Events +{ + EVENT_SHADOWFLAME = 1, + EVENT_WINGBUFFET = 2, + EVENT_SHADOWOFEBONROC = 3 +}; class boss_ebonroc : public CreatureScript { public: boss_ebonroc() : CreatureScript("boss_ebonroc") { } - CreatureAI* GetAI(Creature* creature) const - { - return new boss_ebonrocAI (creature); - } - - struct boss_ebonrocAI : public ScriptedAI + struct boss_ebonrocAI : public BossAI { - boss_ebonrocAI(Creature* creature) : ScriptedAI(creature) {} - - uint32 ShadowFlame_Timer; - uint32 WingBuffet_Timer; - uint32 ShadowOfEbonroc_Timer; - uint32 Heal_Timer; - uint32 Thrash_Timer; - - void Reset() - { - ShadowFlame_Timer = 15000; //These times are probably wrong - WingBuffet_Timer = 30000; - ShadowOfEbonroc_Timer = 45000; - Heal_Timer = 1000; - Thrash_Timer = 10000; - } + boss_ebonrocAI(Creature* creature) : BossAI(creature, BOSS_EBONROC) { } void EnterCombat(Unit* /*who*/) { - DoZoneInCombat(); + if (instance && instance->GetBossState(BOSS_BROODLORD) != DONE) + { + EnterEvadeMode(); + return; + } + _EnterCombat(); + + events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); + events.ScheduleEvent(EVENT_WINGBUFFET, 30000); + events.ScheduleEvent(EVENT_SHADOWOFEBONROC, urand(8000, 10000)); } void UpdateAI(uint32 diff) @@ -71,46 +62,38 @@ public: if (!UpdateVictim()) return; - //Shadowflame Timer - if (ShadowFlame_Timer <= diff) - { - DoCastVictim(SPELL_SHADOWFLAME); - ShadowFlame_Timer = urand(12000, 15000); - } else ShadowFlame_Timer -= diff; - - //Thrash Timer - if (Thrash_Timer <= diff) - { - DoCastVictim(SPELL_THRASH); - Thrash_Timer = urand(10000, 15000); - } else Thrash_Timer -= diff; - - //Wing Buffet Timer - if (WingBuffet_Timer <= diff) - { - DoCastVictim(SPELL_WINGBUFFET); - WingBuffet_Timer = 25000; - } else WingBuffet_Timer -= diff; + events.Update(diff); - //Shadow of Ebonroc Timer - if (ShadowOfEbonroc_Timer <= diff) - { - DoCastVictim(SPELL_SHADOWOFEBONROC); - ShadowOfEbonroc_Timer = urand(25000, 350000); - } else ShadowOfEbonroc_Timer -= diff; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (me->GetVictim() && me->GetVictim()->HasAura(SPELL_SHADOWOFEBONROC)) + while (uint32 eventId = events.ExecuteEvent()) { - if (Heal_Timer <= diff) + switch (eventId) { - DoCast(me, SPELL_HEAL); - Heal_Timer = urand(1000, 3000); - } else Heal_Timer -= diff; + case EVENT_SHADOWFLAME: + DoCastVictim(SPELL_SHADOWFLAME); + events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); + break; + case EVENT_WINGBUFFET: + DoCastVictim(SPELL_WINGBUFFET); + events.ScheduleEvent(EVENT_WINGBUFFET, 30000); + break; + case EVENT_SHADOWOFEBONROC: + DoCastVictim(SPELL_SHADOWOFEBONROC); + events.ScheduleEvent(EVENT_SHADOWOFEBONROC, urand(8000, 10000)); + break; + } } DoMeleeAttackIfReady(); } }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_ebonrocAI (creature); + } }; void AddSC_boss_ebonroc() diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_firemaw.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_firemaw.cpp index 60564ea1acb..b32db2be450 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_firemaw.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_firemaw.cpp @@ -16,48 +16,45 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Firemaw -SD%Complete: 100 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "blackwing_lair.h" -#define SPELL_SHADOWFLAME 22539 -#define SPELL_WINGBUFFET 23339 -#define SPELL_FLAMEBUFFET 23341 +enum Spells +{ + SPELL_SHADOWFLAME = 22539, + SPELL_WINGBUFFET = 23339, + SPELL_FLAMEBUFFET = 23341 +}; + +enum Events +{ + EVENT_SHADOWFLAME = 1, + EVENT_WINGBUFFET = 2, + EVENT_FLAMEBUFFET = 3 +}; class boss_firemaw : public CreatureScript { public: boss_firemaw() : CreatureScript("boss_firemaw") { } - CreatureAI* GetAI(Creature* creature) const - { - return new boss_firemawAI (creature); - } - - struct boss_firemawAI : public ScriptedAI + struct boss_firemawAI : public BossAI { - boss_firemawAI(Creature* creature) : ScriptedAI(creature) {} - - uint32 ShadowFlame_Timer; - uint32 WingBuffet_Timer; - uint32 FlameBuffet_Timer; - - void Reset() - { - ShadowFlame_Timer = 30000; //These times are probably wrong - WingBuffet_Timer = 24000; - FlameBuffet_Timer = 5000; - } + boss_firemawAI(Creature* creature) : BossAI(creature, BOSS_FIREMAW) { } void EnterCombat(Unit* /*who*/) { - DoZoneInCombat(); + if (instance && instance->GetBossState(BOSS_BROODLORD) != DONE) + { + EnterEvadeMode(); + return; + } + _EnterCombat(); + + events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); + events.ScheduleEvent(EVENT_WINGBUFFET, 30000); + events.ScheduleEvent(EVENT_FLAMEBUFFET, 5000); } void UpdateAI(uint32 diff) @@ -65,35 +62,40 @@ public: if (!UpdateVictim()) return; - //ShadowFlame_Timer - if (ShadowFlame_Timer <= diff) - { - DoCastVictim(SPELL_SHADOWFLAME); - ShadowFlame_Timer = urand(15000, 18000); - } else ShadowFlame_Timer -= diff; + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - //WingBuffet_Timer - if (WingBuffet_Timer <= diff) + while (uint32 eventId = events.ExecuteEvent()) { - if (Unit* target = me->GetVictim()) + switch (eventId) { - DoCast(target, SPELL_WINGBUFFET); - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -75); + case EVENT_SHADOWFLAME: + DoCastVictim(SPELL_SHADOWFLAME); + events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); + break; + case EVENT_WINGBUFFET: + DoCastVictim(SPELL_WINGBUFFET); + if (DoGetThreat(me->GetVictim())) + DoModifyThreatPercent(me->GetVictim(), -75); + events.ScheduleEvent(EVENT_WINGBUFFET, 30000); + break; + case EVENT_FLAMEBUFFET: + DoCastVictim(SPELL_FLAMEBUFFET); + events.ScheduleEvent(EVENT_FLAMEBUFFET, 5000); + break; } - WingBuffet_Timer = 25000; - } else WingBuffet_Timer -= diff; - - //FlameBuffet_Timer - if (FlameBuffet_Timer <= diff) - { - DoCastVictim(SPELL_FLAMEBUFFET); - FlameBuffet_Timer = 5000; - } else FlameBuffet_Timer -= diff; + } DoMeleeAttackIfReady(); } }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_firemawAI (creature); + } }; void AddSC_boss_firemaw() diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_flamegor.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_flamegor.cpp index 5035c1e9c89..f5a3cd3e45f 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_flamegor.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_flamegor.cpp @@ -16,15 +16,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Flamegor -SD%Complete: 100 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "blackwing_lair.h" enum Emotes { @@ -35,7 +29,14 @@ enum Spells { SPELL_SHADOWFLAME = 22539, SPELL_WINGBUFFET = 23339, - SPELL_FRENZY = 23342 //This spell periodically triggers fire nova + SPELL_FRENZY = 23342 //This spell periodically triggers fire nova +}; + +enum Events +{ + EVENT_SHADOWFLAME = 1, + EVENT_WINGBUFFET = 2, + EVENT_FRENZY = 3 }; class boss_flamegor : public CreatureScript @@ -43,29 +44,22 @@ class boss_flamegor : public CreatureScript public: boss_flamegor() : CreatureScript("boss_flamegor") { } - CreatureAI* GetAI(Creature* creature) const + struct boss_flamegorAI : public BossAI { - return new boss_flamegorAI (creature); - } - - struct boss_flamegorAI : public ScriptedAI - { - boss_flamegorAI(Creature* creature) : ScriptedAI(creature) {} - - uint32 ShadowFlame_Timer; - uint32 WingBuffet_Timer; - uint32 Frenzy_Timer; - - void Reset() - { - ShadowFlame_Timer = 21000; //These times are probably wrong - WingBuffet_Timer = 35000; - Frenzy_Timer = 10000; - } + boss_flamegorAI(Creature* creature) : BossAI(creature, BOSS_FLAMEGOR) { } void EnterCombat(Unit* /*who*/) { - DoZoneInCombat(); + if (instance && instance->GetBossState(BOSS_BROODLORD) != DONE) + { + EnterEvadeMode(); + return; + } + _EnterCombat(); + + events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); + events.ScheduleEvent(EVENT_WINGBUFFET, 30000); + events.ScheduleEvent(EVENT_FRENZY, 10000); } void UpdateAI(uint32 diff) @@ -73,36 +67,41 @@ public: if (!UpdateVictim()) return; - //ShadowFlame_Timer - if (ShadowFlame_Timer <= diff) - { - DoCastVictim(SPELL_SHADOWFLAME); - ShadowFlame_Timer = urand(15000, 22000); - } else ShadowFlame_Timer -= diff; + events.Update(diff); - //WingBuffet_Timer - if (WingBuffet_Timer <= diff) + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - if (Unit* target = me->GetVictim()) + switch (eventId) { - DoCast(target, SPELL_WINGBUFFET); - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -75); + case EVENT_SHADOWFLAME: + DoCastVictim(SPELL_SHADOWFLAME); + events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); + break; + case EVENT_WINGBUFFET: + DoCastVictim(SPELL_WINGBUFFET); + if (DoGetThreat(me->GetVictim())) + DoModifyThreatPercent(me->GetVictim(), -75); + events.ScheduleEvent(EVENT_WINGBUFFET, 30000); + break; + case EVENT_FRENZY: + Talk(EMOTE_FRENZY); + DoCast(me, SPELL_FRENZY); + events.ScheduleEvent(EVENT_FRENZY, urand(8000, 10000)); + break; } - WingBuffet_Timer = 25000; - } else WingBuffet_Timer -= diff; - - //Frenzy_Timer - if (Frenzy_Timer <= diff) - { - Talk(EMOTE_FRENZY); - DoCast(me, SPELL_FRENZY); - Frenzy_Timer = urand(8000, 10000); - } else Frenzy_Timer -= diff; + } DoMeleeAttackIfReady(); } }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_flamegorAI (creature); + } }; void AddSC_boss_flamegor() diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_nefarian.cpp index 77da6e54df0..fde21c63840 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_nefarian.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_nefarian.cpp @@ -16,225 +16,476 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Nefarian -SD%Complete: 80 -SDComment: Some issues with class calls effecting more than one class -SDCategory: Blackwing Lair -EndScriptData */ - #include "ScriptMgr.h" +#include "ScriptedGossip.h" #include "ScriptedCreature.h" +#include "blackwing_lair.h" +#include "Player.h" + +enum Events +{ + // Victor Nefarius + EVENT_SPAWN_ADD = 1, + EVENT_SHADOW_BOLT = 2, + EVENT_FEAR = 3, + EVENT_MIND_CONTROL = 4, + // Nefarian + EVENT_SHADOWFLAME = 5, + EVENT_VEILOFSHADOW = 6, + EVENT_CLEAVE = 7, + EVENT_TAILLASH = 8, + EVENT_CLASSCALL = 9 +}; + +enum Says +{ + SAY_GAMESBEGIN_1 = 11, + SAY_GAMESBEGIN_2 = 12, + // SAY_VAEL_INTRO = 13, Not used - when he corrupts Vaelastrasz + + // Nefarian + SAY_RANDOM = 0, + SAY_RAISE_SKELETONS = 1, + SAY_SLAY = 2, + SAY_DEATH = 3, + + SAY_MAGE = 4, + SAY_WARRIOR = 5, + SAY_DRUID = 6, + SAY_PRIEST = 7, + SAY_PALADIN = 8, + SAY_SHAMAN = 9, + SAY_WARLOCK = 10, + SAY_HUNTER = 11, + SAY_ROGUE = 12, + SAY_DEATH_KNIGHT = 13 +}; -enum Say +enum Gossip { - SAY_RANDOM = 0, - SAY_RAISE_SKELETONS = 1, - SAY_SLAY = 2, - SAY_DEATH = 3, - - SAY_MAGE = 4, - SAY_WARRIOR = 5, - SAY_DRUID = 6, - SAY_PRIEST = 7, - SAY_PALADIN = 8, - SAY_SHAMAN = 9, - SAY_WARLOCK = 10, - SAY_HUNTER = 11, - SAY_ROGUE = 12, + GOSSIP_ID = 21332, + GOSSIP_OPTION_ID = 0 +}; + +enum Creatures +{ + NPC_BRONZE_DRAKANOID = 14263, + NPC_BLUE_DRAKANOID = 14261, + NPC_RED_DRAKANOID = 14264, + NPC_GREEN_DRAKANOID = 14262, + NPC_BLACK_DRAKANOID = 14265, + NPC_CHROMATIC_DRAKANOID = 14302, + NPC_BONE_CONSTRUCT = 14605 }; enum Spells { - SPELL_SHADOWFLAME_INITIAL = 22972, + // Victor Nefarius + // UBRS Spells + SPELL_CHROMATIC_CHAOS = 16337, // Self Cast hits 10339 + SPELL_VAELASTRASZZ_SPAWN = 16354, // Self Cast Depawn one sec after + // BWL Spells + SPELL_SHADOWBOLT = 22677, + SPELL_SHADOWBOLT_VOLLEY = 22665, + SPELL_SHADOW_COMMAND = 22667, + SPELL_FEAR = 22678, + + SPELL_NEFARIANS_BARRIER = 22663, + + // Nefarian + SPELL_SHADOWFLAME_INITIAL = 22992, SPELL_SHADOWFLAME = 22539, SPELL_BELLOWINGROAR = 22686, SPELL_VEILOFSHADOW = 7068, SPELL_CLEAVE = 20691, SPELL_TAILLASH = 23364, - SPELL_BONECONTRUST = 23363, //23362, 23361 - SPELL_MAGE = 23410, //wild magic - SPELL_WARRIOR = 23397, //beserk + SPELL_MAGE = 23410, // wild magic + SPELL_WARRIOR = 23397, // beserk SPELL_DRUID = 23398, // cat form SPELL_PRIEST = 23401, // corrupted healing - SPELL_PALADIN = 23418, //syphon blessing - SPELL_SHAMAN = 23425, //totems - SPELL_WARLOCK = 23427, //infernals - SPELL_HUNTER = 23436, //bow broke - SPELL_ROGUE = 23414 //Paralise + SPELL_PALADIN = 23418, // syphon blessing + SPELL_SHAMAN = 23425, // totems + SPELL_WARLOCK = 23427, // infernals + SPELL_HUNTER = 23436, // bow broke + SPELL_ROGUE = 23414, // Paralise + SPELL_DEATH_KNIGHT = 49576 // Death Grip + +// 19484 +// 22664 +// 22674 +// 22666 }; -class boss_nefarian : public CreatureScript +Position const DrakeSpawnLoc[2] = // drakonid +{ + {-7591.151855f, -1204.051880f, 476.800476f, 3.0f}, + {-7514.598633f, -1150.448853f, 476.796570f, 3.0f} +}; + +Position const NefarianLoc[2] = +{ + {-7449.763672f, -1387.816040f, 526.783691f, 3.0f}, // nefarian spawn + {-7535.456543f, -1279.562500f, 476.798706f, 3.0f} // nefarian move +}; + +uint32 const Entry[5] = {NPC_BRONZE_DRAKANOID, NPC_BLUE_DRAKANOID, NPC_RED_DRAKANOID, NPC_GREEN_DRAKANOID, NPC_BLACK_DRAKANOID}; + +class boss_victor_nefarius : public CreatureScript { public: - boss_nefarian() : CreatureScript("boss_nefarian") { } + boss_victor_nefarius() : CreatureScript("boss_victor_nefarius") { } + + struct boss_victor_nefariusAI : public BossAI + { + boss_victor_nefariusAI(Creature* creature) : BossAI(creature, BOSS_NEFARIAN) { } + + void Reset() + { + if (me->GetMapId() == 469) + { + if (!me->FindNearestCreature(NPC_NEFARIAN, 1000.0f, true)) + _Reset(); + SpawnedAdds = 0; + + me->SetVisible(true); + me->SetPhaseMask(1, true); + me->SetUInt32Value(UNIT_NPC_FLAGS, 1); + me->setFaction(35); + me->SetStandState(UNIT_STAND_STATE_SIT_HIGH_CHAIR); + me->RemoveAura(SPELL_NEFARIANS_BARRIER); + } + } + + void JustReachedHome() + { + Reset(); + } + + void BeginEvent(Player* target) + { + _EnterCombat(); + + Talk(SAY_GAMESBEGIN_2); + + me->setFaction(103); + me->SetUInt32Value(UNIT_NPC_FLAGS, 0); + DoCast(me, SPELL_NEFARIANS_BARRIER); + me->SetStandState(UNIT_STAND_STATE_STAND); + AttackStart(target); + events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(3000, 10000)); + events.ScheduleEvent(EVENT_FEAR, urand(10000, 20000)); + //events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000)); + events.ScheduleEvent(EVENT_SPAWN_ADD, 10000); + } + + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) + { + if (summon->GetEntry() != NPC_NEFARIAN) + { + summon->UpdateEntry(NPC_BONE_CONSTRUCT); + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summon->SetReactState(REACT_PASSIVE); + summon->SetStandState(UNIT_STAND_STATE_DEAD); + } + } + + void JustSummoned(Creature* /*summon*/) {} + + void UpdateAI(uint32 diff) + { + // Only do this if we haven't spawned nefarian yet + if (UpdateVictim() && SpawnedAdds <= 42) + { + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SHADOW_BOLT: + switch (urand(0, 1)) + { + case 0: + DoCastVictim(SPELL_SHADOWBOLT_VOLLEY); + break; + case 1: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true)) + DoCast(target, SPELL_SHADOWBOLT); + break; + } + DoResetThreat(); + events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(3000, 10000)); + break; + case EVENT_FEAR: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true)) + DoCast(target, SPELL_FEAR); + events.ScheduleEvent(EVENT_FEAR, urand(10000, 20000)); + break; + case EVENT_MIND_CONTROL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true)) + DoCast(target, SPELL_SHADOW_COMMAND); + events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000)); + break; + case EVENT_SPAWN_ADD: + for (uint8 i=0; i<2; ++i) + { + uint32 CreatureID; + if (urand(0, 2) == 0) + CreatureID = NPC_CHROMATIC_DRAKANOID; + else + CreatureID = Entry[urand(0, 4)]; + if (Creature* dragon = me->SummonCreature(CreatureID, DrakeSpawnLoc[i])) + { + dragon->setFaction(103); + dragon->AI()->AttackStart(me->GetVictim()); + } + + if (++SpawnedAdds >= 42) + { + if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianLoc[0])) + { + nefarian->setActive(true); + nefarian->SetCanFly(true); + nefarian->SetDisableGravity(true); + nefarian->AI()->DoCastAOE(SPELL_SHADOWFLAME_INITIAL); + nefarian->GetMotionMaster()->MovePoint(1, NefarianLoc[1]); + } + events.CancelEvent(EVENT_MIND_CONTROL); + events.CancelEvent(EVENT_FEAR); + events.CancelEvent(EVENT_SHADOW_BOLT); + me->SetVisible(false); + return; + } + } + events.ScheduleEvent(EVENT_SPAWN_ADD, 4000); + break; + } + } + } + } + + void sGossipSelect(Player* player, uint32 sender, uint32 action) + { + if (sender == GOSSIP_ID && action == GOSSIP_OPTION_ID) + { + player->CLOSE_GOSSIP_MENU(); + Talk(SAY_GAMESBEGIN_1); + BeginEvent(player); + } + } + + private: + uint32 SpawnedAdds; + }; CreatureAI* GetAI(Creature* creature) const { - return new boss_nefarianAI (creature); + return new boss_victor_nefariusAI (creature); } +}; - struct boss_nefarianAI : public ScriptedAI - { - boss_nefarianAI(Creature* creature) : ScriptedAI(creature) {} - - uint32 ShadowFlame_Timer; - uint32 BellowingRoar_Timer; - uint32 VeilOfShadow_Timer; - uint32 Cleave_Timer; - uint32 TailLash_Timer; - uint32 ClassCall_Timer; - bool Phase3; +class boss_nefarian : public CreatureScript +{ +public: + boss_nefarian() : CreatureScript("boss_nefarian") { } - uint32 DespawnTimer; + struct boss_nefarianAI : public BossAI + { + boss_nefarianAI(Creature* creature) : BossAI(creature, BOSS_NEFARIAN) { } void Reset() { - ShadowFlame_Timer = 12000; // These times are probably wrong - BellowingRoar_Timer = 30000; - VeilOfShadow_Timer = 15000; - Cleave_Timer = 7000; - TailLash_Timer = 10000; - ClassCall_Timer = 35000; // 35-40 seconds Phase3 = false; - - DespawnTimer = 5000; + canDespawn = false; + DespawnTimer = 30000; } - void KilledUnit(Unit* Victim) + void JustReachedHome() { - if (rand()%5) - return; + canDespawn = true; + } - Talk(SAY_SLAY, Victim->GetGUID()); + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOWFLAME, 12000); + events.ScheduleEvent(EVENT_FEAR, urand(25000, 35000)); + events.ScheduleEvent(EVENT_VEILOFSHADOW, urand(25000, 35000)); + events.ScheduleEvent(EVENT_CLEAVE, 7000); + //events.ScheduleEvent(EVENT_TAILLASH, 10000); + events.ScheduleEvent(EVENT_CLASSCALL, urand(30000, 35000)); + Talk(SAY_RANDOM); } - void JustDied(Unit* /*killer*/) + void JustDied(Unit* /*Killer*/) { + _JustDied(); Talk(SAY_DEATH); } - void EnterCombat(Unit* who) + void KilledUnit(Unit* victim) { - Talk(SAY_RANDOM); + if (rand()%5) + return; - DoCast(who, SPELL_SHADOWFLAME_INITIAL); - DoZoneInCombat(); + Talk(SAY_SLAY, victim->GetGUID()); } - void UpdateAI(uint32 diff) + void MovementInform(uint32 type, uint32 id) { - if (DespawnTimer <= diff) - { - if (!UpdateVictim()) - me->DespawnOrUnsummon(); - DespawnTimer = 5000; - } else DespawnTimer -= diff; - - if (!UpdateVictim()) + if (type != POINT_MOTION_TYPE) return; - //ShadowFlame_Timer - if (ShadowFlame_Timer <= diff) + if (id == 1) { - DoCastVictim(SPELL_SHADOWFLAME); - ShadowFlame_Timer = 12000; - } else ShadowFlame_Timer -= diff; + me->SetInCombatWithZone(); + if (me->GetVictim()) + AttackStart(me->GetVictim()); + } + } - //BellowingRoar_Timer - if (BellowingRoar_Timer <= diff) + void UpdateAI(uint32 diff) + { + if (canDespawn && DespawnTimer <= diff) { - DoCastVictim(SPELL_BELLOWINGROAR); - BellowingRoar_Timer = 30000; - } else BellowingRoar_Timer -= diff; + if (instance) + instance->SetBossState(BOSS_NEFARIAN, FAIL); - //VeilOfShadow_Timer - if (VeilOfShadow_Timer <= diff) - { - DoCastVictim(SPELL_VEILOFSHADOW); - VeilOfShadow_Timer = 15000; - } else VeilOfShadow_Timer -= diff; + std::list<Creature*> constructList; + me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f); + for (std::list<Creature*>::const_iterator itr = constructList.begin(); itr != constructList.end(); ++itr) + (*itr)->DespawnOrUnsummon(); - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCastVictim(SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; + } else DespawnTimer -= diff; - //TailLash_Timer - if (TailLash_Timer <= diff) - { - //Cast NYI since we need a better check for behind target - //DoCastVictim(SPELL_TAILLASH); + if (!UpdateVictim()) + return; - TailLash_Timer = 10000; - } else TailLash_Timer -= diff; + if (canDespawn) + canDespawn = false; - //ClassCall_Timer - if (ClassCall_Timer <= diff) - { - //Cast a random class call - //On official it is based on what classes are currently on the hostil list - //but we can't do that yet so just randomly call one + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - switch (urand(0, 8)) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - case 0: - Talk(SAY_MAGE); - DoCast(me, SPELL_MAGE); - break; - case 1: - Talk(SAY_WARRIOR); - DoCast(me, SPELL_WARRIOR); - break; - case 2: - Talk(SAY_DRUID); - DoCast(me, SPELL_DRUID); + case EVENT_SHADOWFLAME: + DoCastVictim(SPELL_SHADOWFLAME); + events.ScheduleEvent(EVENT_SHADOWFLAME, 12000); break; - case 3: - Talk(SAY_PRIEST); - DoCast(me, SPELL_PRIEST); + case EVENT_FEAR: + DoCastVictim(SPELL_BELLOWINGROAR); + events.ScheduleEvent(EVENT_FEAR, urand(25000, 35000)); break; - case 4: - Talk(SAY_PALADIN); - DoCast(me, SPELL_PALADIN); + case EVENT_VEILOFSHADOW: + DoCastVictim(SPELL_VEILOFSHADOW); + events.ScheduleEvent(EVENT_VEILOFSHADOW, urand(25000, 35000)); break; - case 5: - Talk(SAY_SHAMAN); - DoCast(me, SPELL_SHAMAN); + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, 7000); break; - case 6: - Talk(SAY_WARLOCK); - DoCast(me, SPELL_WARLOCK); + case EVENT_TAILLASH: + // Cast NYI since we need a better check for behind target + DoCastVictim(SPELL_TAILLASH); + events.ScheduleEvent(EVENT_TAILLASH, 10000); break; - case 7: - Talk(SAY_HUNTER); - DoCast(me, SPELL_HUNTER); - break; - case 8: - Talk(SAY_ROGUE); - DoCast(me, SPELL_ROGUE); + case EVENT_CLASSCALL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + switch (target->getClass()) + { + case CLASS_MAGE: + Talk(SAY_MAGE); + DoCast(me, SPELL_MAGE); + break; + case CLASS_WARRIOR: + Talk(SAY_WARRIOR); + DoCast(me, SPELL_WARRIOR); + break; + case CLASS_DRUID: + Talk(SAY_DRUID); + DoCast(target, SPELL_DRUID); + break; + case CLASS_PRIEST: + Talk(SAY_PRIEST); + DoCast(me, SPELL_PRIEST); + break; + case CLASS_PALADIN: + Talk(SAY_PALADIN); + DoCast(me, SPELL_PALADIN); + break; + case CLASS_SHAMAN: + Talk(SAY_SHAMAN); + DoCast(me, SPELL_SHAMAN); + break; + case CLASS_WARLOCK: + Talk(SAY_WARLOCK); + DoCast(me, SPELL_WARLOCK); + break; + case CLASS_HUNTER: + Talk(SAY_HUNTER); + DoCast(me, SPELL_HUNTER); + break; + case CLASS_ROGUE: + Talk(SAY_ROGUE); + DoCast(me, SPELL_ROGUE); + break; + case CLASS_DEATH_KNIGHT: + Talk(SAY_DEATH_KNIGHT); + DoCast(me, SPELL_DEATH_KNIGHT); + break; + default: + break; + } + events.ScheduleEvent(EVENT_CLASSCALL, urand(30000, 35000)); break; } + } - ClassCall_Timer = 35000 + (rand() % 5000); - } else ClassCall_Timer -= diff; - - //Phase3 begins when we are below X health + // Phase3 begins when health below 20 pct if (!Phase3 && HealthBelowPct(20)) { + std::list<Creature*> constructList; + me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f); + for (std::list<Creature*>::const_iterator itr = constructList.begin(); itr != constructList.end(); ++itr) + if ((*itr) && !(*itr)->IsAlive()) + { + (*itr)->Respawn(); + (*itr)->SetInCombatWithZone(); + (*itr)->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + (*itr)->SetReactState(REACT_AGGRESSIVE); + (*itr)->SetStandState(UNIT_STAND_STATE_STAND); + } + Phase3 = true; Talk(SAY_RAISE_SKELETONS); } DoMeleeAttackIfReady(); } + + private: + bool canDespawn; + uint32 DespawnTimer; + bool Phase3; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_nefarianAI (creature); + } }; void AddSC_boss_nefarian() { + new boss_victor_nefarius(); new boss_nefarian(); } diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_razorgore.cpp index 369e97ca99a..6e20b58a6d6 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_razorgore.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_razorgore.cpp @@ -16,17 +16,11 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Razorgore -SD%Complete: 50 -SDComment: Needs additional review. Phase 1 NYI (Grethok the Controller) -SDCategory: Blackwing Lair -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" - -//Razorgore Phase 2 Script +#include "SpellScript.h" +#include "blackwing_lair.h" +#include "Player.h" enum Say { @@ -38,47 +32,84 @@ enum Say enum Spells { + SPELL_MINDCONTROL = 42013, + SPELL_CHANNEL = 45537, + SPELL_EGG_DESTROY = 19873, + SPELL_CLEAVE = 22540, SPELL_WARSTOMP = 24375, SPELL_FIREBALLVOLLEY = 22425, SPELL_CONFLAGRATION = 23023 }; +enum Summons +{ + NPC_ELITE_DRACHKIN = 12422, + NPC_ELITE_WARRIOR = 12458, + NPC_WARRIOR = 12416, + NPC_MAGE = 12420, + NPC_WARLOCK = 12459, + + GO_EGG = 177807 +}; + +enum EVENTS +{ + EVENT_CLEAVE = 1, + EVENT_STOMP = 2, + EVENT_FIREBALL = 3, + EVENT_CONFLAGRATION = 4 +}; + class boss_razorgore : public CreatureScript { public: boss_razorgore() : CreatureScript("boss_razorgore") { } - CreatureAI* GetAI(Creature* creature) const + struct boss_razorgoreAI : public BossAI { - return new boss_razorgoreAI (creature); - } + boss_razorgoreAI(Creature* creature) : BossAI(creature, BOSS_RAZORGORE) { } - struct boss_razorgoreAI : public ScriptedAI - { - boss_razorgoreAI(Creature* creature) : ScriptedAI(creature) {} + void Reset() + { + _Reset(); - uint32 Cleave_Timer; - uint32 WarStomp_Timer; - uint32 FireballVolley_Timer; - uint32 Conflagration_Timer; + secondPhase = false; + if (instance) + instance->SetData(DATA_EGG_EVENT, NOT_STARTED); + } - void Reset() + void JustDied(Unit* /*killer*/) { - Cleave_Timer = 15000; //These times are probably wrong - WarStomp_Timer = 35000; - FireballVolley_Timer = 7000; - Conflagration_Timer = 12000; + _JustDied(); + Talk(SAY_DEATH); + + if (instance) + instance->SetData(DATA_EGG_EVENT, NOT_STARTED); } - void EnterCombat(Unit* /*who*/) + void DoChangePhase() { - DoZoneInCombat(); + events.ScheduleEvent(EVENT_CLEAVE, 15000); + events.ScheduleEvent(EVENT_STOMP, 35000); + events.ScheduleEvent(EVENT_FIREBALL, 7000); + events.ScheduleEvent(EVENT_CONFLAGRATION, 12000); + + secondPhase = true; + me->RemoveAllAuras(); + me->SetHealth(me->GetMaxHealth()); } - void JustDied(Unit* /*killer*/) + void DoAction(int32 action) { - Talk(SAY_DEATH); + if (action == ACTION_PHASE_TWO) + DoChangePhase(); + } + + void DamageTaken(Unit* /*who*/, uint32& damage) + { + if (!secondPhase) + damage = 0; } void UpdateAI(uint32 diff) @@ -86,50 +117,97 @@ public: if (!UpdateVictim()) return; - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCastVictim(SPELL_CLEAVE); - Cleave_Timer = urand(7000, 10000); - } else Cleave_Timer -= diff; + events.Update(diff); - //WarStomp_Timer - if (WarStomp_Timer <= diff) - { - DoCastVictim(SPELL_WARSTOMP); - WarStomp_Timer = urand(15000, 25000); - } else WarStomp_Timer -= diff; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - //FireballVolley_Timer - if (FireballVolley_Timer <= diff) + while (uint32 eventId = events.ExecuteEvent()) { - DoCastVictim(SPELL_FIREBALLVOLLEY); - FireballVolley_Timer = urand(12000, 15000); - } else FireballVolley_Timer -= diff; + switch (eventId) + { + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, urand(7000, 10000)); + break; + case EVENT_STOMP: + DoCastVictim(SPELL_WARSTOMP); + events.ScheduleEvent(EVENT_STOMP, urand(15000, 25000)); + break; + case EVENT_FIREBALL: + DoCastVictim(SPELL_FIREBALLVOLLEY); + events.ScheduleEvent(EVENT_FIREBALL, urand(12000, 15000)); + break; + case EVENT_CONFLAGRATION: + DoCastVictim(SPELL_CONFLAGRATION); + if (me->GetVictim() && me->GetVictim()->HasAura(SPELL_CONFLAGRATION)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + me->TauntApply(target); + events.ScheduleEvent(EVENT_CONFLAGRATION, 30000); + break; + } + } + DoMeleeAttackIfReady(); + } - //Conflagration_Timer - if (Conflagration_Timer <= diff) - { - DoCastVictim(SPELL_CONFLAGRATION); - //We will remove this threat reduction and add an aura check. + private: + bool secondPhase; + }; - //if (DoGetThreat(me->GetVictim())) - //DoModifyThreatPercent(me->GetVictim(), -50); + CreatureAI* GetAI(Creature* creature) const + { + return new boss_razorgoreAI (creature); + } +}; - Conflagration_Timer = 12000; - } else Conflagration_Timer -= diff; +class go_orb_of_domination : public GameObjectScript +{ +public: + go_orb_of_domination() : GameObjectScript("go_orb_of_domination") { } - // Aura Check. If the gamer is affected by confliguration we attack a random gamer. - if (me->GetVictim() && me->GetVictim()->HasAura(SPELL_CONFLAGRATION)) - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - me->TauntApply(target); + bool OnGossipHello(Player* player, GameObject* go) + { + if (InstanceScript* instance = go->GetInstanceScript()) + if (instance->GetData(DATA_EGG_EVENT) != DONE) + if (Creature* razor = Unit::GetCreature(*go, instance ? instance->GetData64(DATA_RAZORGORE_THE_UNTAMED) : 0)) + { + razor->Attack(player, true); + player->CastSpell(razor, SPELL_MINDCONTROL); + } + return true; + } +}; - DoMeleeAttackIfReady(); +class spell_egg_event : public SpellScriptLoader +{ + public: + spell_egg_event() : SpellScriptLoader("spell_egg_event") { } + + class spell_egg_eventSpellScript : public SpellScript + { + PrepareSpellScript(spell_egg_eventSpellScript); + + void HandleOnHit() + { + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + instance->SetData(DATA_EGG_EVENT, SPECIAL); + } + + void Register() + { + OnHit += SpellHitFn(spell_egg_eventSpellScript::HandleOnHit); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_egg_eventSpellScript(); } - }; }; void AddSC_boss_razorgore() { new boss_razorgore(); + new go_orb_of_domination(); + new spell_egg_event(); } diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp index dfa0f42f4a6..e7626c92ec0 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp @@ -16,37 +16,49 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Vaelastrasz -SD%Complete: 75 -SDComment: Burning Adrenaline not correctly implemented in core -SDCategory: Blackwing Lair -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "blackwing_lair.h" #include "ScriptedGossip.h" #include "Player.h" enum Says { - SAY_LINE1 = 0, - SAY_LINE2 = 1, - SAY_LINE3 = 2, - SAY_HALFLIFE = 3, - SAY_KILLTARGET = 4 + SAY_LINE1 = 0, + SAY_LINE2 = 1, + SAY_LINE3 = 2, + SAY_HALFLIFE = 3, + SAY_KILLTARGET = 4 }; -#define GOSSIP_ITEM "Start Event <Needs Gossip Text>" +enum Gossip +{ + GOSSIP_ID = 21334, +}; enum Spells { - SPELL_ESSENCEOFTHERED = 23513, - SPELL_FLAMEBREATH = 23461, - SPELL_FIRENOVA = 23462, - SPELL_TAILSWIPE = 15847, - SPELL_BURNINGADRENALINE = 23620, - SPELL_CLEAVE = 20684 //Chain cleave is most likely named something different and contains a dummy effect + SPELL_ESSENCEOFTHERED = 23513, + SPELL_FLAMEBREATH = 23461, + SPELL_FIRENOVA = 23462, + SPELL_TAILSWIPE = 15847, + SPELL_BURNINGADRENALINE = 23620, + SPELL_CLEAVE = 20684 //Chain cleave is most likely named something different and contains a dummy effect +}; + +enum Events +{ + EVENT_SPEECH_1 = 1, + EVENT_SPEECH_2 = 2, + EVENT_SPEECH_3 = 3, + EVENT_SPEECH_4 = 4, + EVENT_ESSENCEOFTHERED = 5, + EVENT_FLAMEBREATH = 6, + EVENT_FIRENOVA = 7, + EVENT_TAILSWIPE = 8, + EVENT_CLEAVE = 9, + EVENT_BURNINGADRENALINE_CASTER = 10, + EVENT_BURNINGADRENALINE_TANK = 11 }; class boss_vaelastrasz : public CreatureScript @@ -54,89 +66,47 @@ class boss_vaelastrasz : public CreatureScript public: boss_vaelastrasz() : CreatureScript("boss_vaelastrasz") { } - void SendDefaultMenu(Player* player, Creature* creature, uint32 action) + struct boss_vaelAI : public BossAI { - if (action == GOSSIP_ACTION_INFO_DEF + 1) //Fight time - { - player->CLOSE_GOSSIP_MENU(); - CAST_AI(boss_vaelastrasz::boss_vaelAI, creature->AI())->BeginSpeech(player); - } - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - if (sender == GOSSIP_SENDER_MAIN) - SendDefaultMenu(player, creature, action); - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(907, creature->GetGUID()); - - return true; - } - - CreatureAI* GetAI(Creature* creature) const - { - return new boss_vaelAI (creature); - } - - struct boss_vaelAI : public ScriptedAI - { - boss_vaelAI(Creature* creature) : ScriptedAI(creature) + boss_vaelAI(Creature* creature) : BossAI(creature, BOSS_VAELASTRAZ) { creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); creature->setFaction(35); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } - uint64 PlayerGUID; - uint32 SpeechTimer; - uint32 SpeechNum; - uint32 Cleave_Timer; - uint32 FlameBreath_Timer; - uint32 FireNova_Timer; - uint32 BurningAdrenalineCaster_Timer; - uint32 BurningAdrenalineTank_Timer; - uint32 TailSwipe_Timer; - bool HasYelled; - bool DoingSpeech; - void Reset() { + _Reset(); + + me->SetStandState(UNIT_STAND_STATE_DEAD); PlayerGUID = 0; - SpeechTimer = 0; - SpeechNum = 0; - Cleave_Timer = 8000; // These times are probably wrong - FlameBreath_Timer = 11000; - BurningAdrenalineCaster_Timer = 15000; - BurningAdrenalineTank_Timer = 45000; - FireNova_Timer = 5000; - TailSwipe_Timer = 20000; + HasYelled = false; - DoingSpeech = false; } - void BeginSpeech(Unit* target) + void EnterCombat(Unit* /*who*/) { - //Stand up and begin speach - PlayerGUID = target->GetGUID(); + _EnterCombat(); - //10 seconds - Talk(SAY_LINE1); + DoCast(me, SPELL_ESSENCEOFTHERED); + me->SetHealth(me->CountPctFromMaxHealth(30)); + // now drop damage requirement to be able to take loot + me->ResetPlayerDamageReq(); - SpeechTimer = 10000; - SpeechNum = 0; - DoingSpeech = true; + events.ScheduleEvent(EVENT_CLEAVE, 10000); + events.ScheduleEvent(EVENT_FLAMEBREATH, 15000); + events.ScheduleEvent(EVENT_FIRENOVA, 20000); + events.ScheduleEvent(EVENT_TAILSWIPE, 11000); + events.ScheduleEvent(EVENT_BURNINGADRENALINE_CASTER, 15000); + events.ScheduleEvent(EVENT_BURNINGADRENALINE_TANK, 45000); + } + void BeginSpeech(Unit* target) + { + PlayerGUID = target->GetGUID(); me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.ScheduleEvent(EVENT_SPEECH_1, 1000); } void KilledUnit(Unit* victim) @@ -147,54 +117,95 @@ public: Talk(SAY_KILLTARGET, victim->GetGUID()); } - void EnterCombat(Unit* /*who*/) - { - DoCast(me, SPELL_ESSENCEOFTHERED); - DoZoneInCombat(); - me->SetHealth(me->CountPctFromMaxHealth(30)); - // now drop damage requirement to be able to take loot - me->ResetPlayerDamageReq(); - } - void UpdateAI(uint32 diff) { - //Speech - if (DoingSpeech) + events.Update(diff); + + // Speech + if (!UpdateVictim()) { - if (SpeechTimer <= diff) + while (uint32 eventId = events.ExecuteEvent()) { - switch (SpeechNum) + switch (eventId) { - case 0: - //16 seconds till next line + case EVENT_SPEECH_1: + Talk(SAY_LINE1); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->HandleEmoteCommand(EMOTE_ONESHOT_TALK); + events.ScheduleEvent(EVENT_SPEECH_2, 12000); + break; + case EVENT_SPEECH_2: Talk(SAY_LINE2); - SpeechTimer = 16000; - ++SpeechNum; + me->HandleEmoteCommand(EMOTE_ONESHOT_TALK); + events.ScheduleEvent(EVENT_SPEECH_3, 12000); break; - case 1: - //This one is actually 16 seconds but we only go to 10 seconds because he starts attacking after he says "I must fight this!" + case EVENT_SPEECH_3: Talk(SAY_LINE3); - SpeechTimer = 10000; - ++SpeechNum; + me->HandleEmoteCommand(EMOTE_ONESHOT_TALK); + events.ScheduleEvent(EVENT_SPEECH_4, 16000); break; - case 2: + case EVENT_SPEECH_4: me->setFaction(103); if (PlayerGUID && Unit::GetUnit(*me, PlayerGUID)) - { - AttackStart(Unit::GetUnit(*me, PlayerGUID)); - DoCast(me, SPELL_ESSENCEOFTHERED); - } - SpeechTimer = 0; - DoingSpeech = false; + AttackStart(Unit::GetUnit(*me, PlayerGUID));; break; } - } else SpeechTimer -= diff; + } + return; } - //Return since we have no target - if (!UpdateVictim()) + if (me->HasUnitState(UNIT_STATE_CASTING)) return; + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CLEAVE: + events.ScheduleEvent(EVENT_CLEAVE, 15000); + DoCastVictim(SPELL_CLEAVE); + break; + case EVENT_FLAMEBREATH: + DoCastVictim(SPELL_FLAMEBREATH); + events.ScheduleEvent(EVENT_FLAMEBREATH, urand(8000, 14000)); + break; + case EVENT_FIRENOVA: + DoCastVictim(SPELL_FIRENOVA); + events.ScheduleEvent(EVENT_FIRENOVA, 15000); + break; + case EVENT_TAILSWIPE: + //Only cast if we are behind + /*if (!me->HasInArc(M_PI, me->GetVictim())) + { + DoCast(me->GetVictim(), SPELL_TAILSWIPE); + }*/ + events.ScheduleEvent(EVENT_TAILSWIPE, 15000); + break; + case EVENT_BURNINGADRENALINE_CASTER: + { + Unit* target = NULL; + + uint8 i = 0; + while (i < 3) // max 3 tries to get a random target with power_mana + { + ++i; + target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); // not aggro leader + if (target && target->getPowerType() == POWER_MANA) + i = 3; + } + if (target) // cast on self (see below) + target->CastSpell(target, SPELL_BURNINGADRENALINE, true); + } + events.ScheduleEvent(EVENT_BURNINGADRENALINE_CASTER, 15000); + break; + case EVENT_BURNINGADRENALINE_TANK: + // have the victim cast the spell on himself otherwise the third effect aura will be applied to Vael instead of the player + me->GetVictim()->CastSpell(me->GetVictim(), SPELL_BURNINGADRENALINE, true); + events.ScheduleEvent(EVENT_BURNINGADRENALINE_TANK, 45000); + break; + } + } + // Yell if hp lower than 15% if (HealthBelowPct(15) && !HasYelled) { @@ -202,74 +213,30 @@ public: HasYelled = true; } - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCastVictim(SPELL_CLEAVE); - Cleave_Timer = 15000; - } else Cleave_Timer -= diff; - - //FlameBreath_Timer - if (FlameBreath_Timer <= diff) - { - DoCastVictim(SPELL_FLAMEBREATH); - FlameBreath_Timer = urand(4000, 8000); - } else FlameBreath_Timer -= diff; - - //BurningAdrenalineCaster_Timer - if (BurningAdrenalineCaster_Timer <= diff) - { - Unit* target = NULL; - - uint8 i = 0; - while (i < 3) // max 3 tries to get a random target with power_mana - { - ++i; - target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); //not aggro leader - if (target && target->getPowerType() == POWER_MANA) - i = 3; - } - if (target) // cast on self (see below) - target->CastSpell(target, SPELL_BURNINGADRENALINE, 1); - - BurningAdrenalineCaster_Timer = 15000; - } else BurningAdrenalineCaster_Timer -= diff; - - //BurningAdrenalineTank_Timer - if (BurningAdrenalineTank_Timer <= diff) - { - // have the victim cast the spell on himself otherwise the third effect aura will be applied - // to Vael instead of the player - me->GetVictim()->CastSpell(me->GetVictim(), SPELL_BURNINGADRENALINE, 1); - - BurningAdrenalineTank_Timer = 45000; - } else BurningAdrenalineTank_Timer -= diff; - - //FireNova_Timer - if (FireNova_Timer <= diff) - { - DoCastVictim(SPELL_FIRENOVA); - FireNova_Timer = 5000; - } else FireNova_Timer -= diff; + DoMeleeAttackIfReady(); + } - //TailSwipe_Timer - if (TailSwipe_Timer <= diff) + void sGossipSelect(Player* player, uint32 sender, uint32 action) + { + if (sender == GOSSIP_ID && action == 0) { - //Only cast if we are behind - /*if (!me->HasInArc(M_PI, me->GetVictim())) - { - DoCastVictim(SPELL_TAILSWIPE); - }*/ - - TailSwipe_Timer = 20000; - } else TailSwipe_Timer -= diff; - - DoMeleeAttackIfReady(); + player->CLOSE_GOSSIP_MENU(); + BeginSpeech(player); + } } + + private: + uint64 PlayerGUID; + bool HasYelled; }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_vaelAI (creature); + } }; -void AddSC_boss_vael() +void AddSC_boss_vaelastrasz() { new boss_vaelastrasz(); } diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_victor_nefarius.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_victor_nefarius.cpp deleted file mode 100644 index ebaca31cbef..00000000000 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_victor_nefarius.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* ScriptData -SDName: Boss_Victor_Nefarius -SD%Complete: 75 -SDComment: Missing some text, Vael beginning event, and spawns Nef in wrong place -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptMgr.h" -#include "ScriptedCreature.h" -#include "ScriptedGossip.h" -#include "Player.h" - -enum Says -{ - SAY_GAMESBEGIN_1 = 0, - SAY_GAMESBEGIN_2 = 1, - //SAY_VAEL_INTRO = 2, Not used - when he corrupts Vaelastrasz -}; - -#define GOSSIP_ITEM_1 "I've made no mistakes." -#define GOSSIP_ITEM_2 "You have lost your mind, Nefarius. You speak in riddles." -#define GOSSIP_ITEM_3 "Please do." - -enum Creatures -{ - CREATURE_BRONZE_DRAKANOID = 14263, - CREATURE_BLUE_DRAKANOID = 14261, - CREATURE_RED_DRAKANOID = 14264, - CREATURE_GREEN_DRAKANOID = 14262, - CREATURE_BLACK_DRAKANOID = 14265, - - CREATURE_CHROMATIC_DRAKANOID = 14302, - CREATURE_NEFARIAN = 11583 -}; - -#define ADD_X1 -7591.151855f -#define ADD_X2 -7514.598633f -#define ADD_Y1 -1204.051880f -#define ADD_Y2 -1150.448853f -#define ADD_Z1 476.800476f -#define ADD_Z2 476.796570f - -#define NEF_X -7445 -#define NEF_Y -1332 -#define NEF_Z 536 - -#define HIDE_X -7592 -#define HIDE_Y -1264 -#define HIDE_Z 481 - -enum Spells -{ - SPELL_SHADOWBOLT = 21077, - SPELL_FEAR = 26070 -}; - -//This script is complicated -//Instead of morphing Victor Nefarius we will have him control phase 1 -//And then have him spawn "Nefarian" for phase 2 -//When phase 2 starts Victor Nefarius will go into hiding and stop attacking -//If Nefarian despawns because he killed the players then this guy will EnterEvadeMode -//and allow players to start the event over -//If nefarian dies then he will kill himself then he will kill himself in his hiding place -//To prevent players from doing the event twice - -class boss_victor_nefarius : public CreatureScript -{ -public: - boss_victor_nefarius() : CreatureScript("boss_victor_nefarius") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->SEND_GOSSIP_MENU(7198, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - player->SEND_GOSSIP_MENU(7199, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->CLOSE_GOSSIP_MENU(); - creature->AI()->Talk(SAY_GAMESBEGIN_1); - CAST_AI(boss_victor_nefarius::boss_victor_nefariusAI, creature->AI())->BeginEvent(player); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(7134, creature->GetGUID()); - return true; - } - - CreatureAI* GetAI(Creature* creature) const - { - return new boss_victor_nefariusAI (creature); - } - - struct boss_victor_nefariusAI : public ScriptedAI - { - boss_victor_nefariusAI(Creature* creature) : ScriptedAI(creature) - { - NefarianGUID = 0; - switch (urand(0, 19)) - { - case 0: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 1: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 2: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 3: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 4: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 5: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 6: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 7: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 8: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 9: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 10: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 11: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 12: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 13: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 14: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 15: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 16: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 17: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 18: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 19: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - } - } - - uint32 SpawnedAdds; - uint32 AddSpawnTimer; - uint32 ShadowBoltTimer; - uint32 FearTimer; - uint32 MindControlTimer; - uint32 ResetTimer; - uint32 DrakType1; - uint32 DrakType2; - uint64 NefarianGUID; - uint32 NefCheckTime; - - void Reset() - { - SpawnedAdds = 0; - AddSpawnTimer = 10000; - ShadowBoltTimer = 5000; - FearTimer = 8000; - ResetTimer = 900000; // On official it takes him 15 minutes(900 seconds) to reset. We are only doing 1 minute to make testing easier - NefarianGUID = 0; - NefCheckTime = 2000; - - me->SetUInt32Value(UNIT_NPC_FLAGS, 1); - me->setFaction(35); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void BeginEvent(Player* target) - { - Talk(SAY_GAMESBEGIN_2); - - //Trinity::Singleton<MapManager>::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); - /* - list <Player*>::const_iterator i = sMapMgr->GetMap(me->GetMapId(), me)->GetPlayers().begin(); - - for (i = sMapMgr->GetMap(me->GetMapId(), me)->GetPlayers().begin(); i != sMapMgr->GetMap(me->GetMapId(), me)->GetPlayers().end(); ++i) - { - AttackStart((*i)); - } - */ - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); - me->setFaction(103); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - AttackStart(target); - } - - void EnterCombat(Unit* /*who*/) - { - } - - void MoveInLineOfSight(Unit* who) - { - //We simply use this function to find players until we can use map->GetPlayers() - - if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsHostileTo(who)) - { - //Add them to our threat list - me->AddThreat(who, 0.0f); - } - } - - void UpdateAI(uint32 diff) - { - if (!UpdateVictim()) - return; - - //Only do this if we haven't spawned nef yet - if (SpawnedAdds < 42) - { - //ShadowBoltTimer - if (ShadowBoltTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_SHADOWBOLT); - - ShadowBoltTimer = urand(3000, 10000); - } else ShadowBoltTimer -= diff; - - //FearTimer - if (FearTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_FEAR); - - FearTimer = 10000 + (rand()%10000); - } else FearTimer -= diff; - - //Add spawning mechanism - if (AddSpawnTimer <= diff) - { - //Spawn 2 random types of creatures at the 2 locations - uint32 CreatureID; - Creature* Spawned = NULL; - Unit* target = NULL; - - //1 in 3 chance it will be a chromatic - if (urand(0, 2) == 0) - CreatureID = CREATURE_CHROMATIC_DRAKANOID; - else - CreatureID = DrakType1; - - ++SpawnedAdds; - - //Spawn Creature and force it to start attacking a random target - Spawned = me->SummonCreature(CreatureID, ADD_X1, ADD_Y1, ADD_Z1, 5.000f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target && Spawned) - { - Spawned->AI()->AttackStart(target); - Spawned->setFaction(103); - } - - //1 in 3 chance it will be a chromatic - if (urand(0, 2) == 0) - CreatureID = CREATURE_CHROMATIC_DRAKANOID; - else - CreatureID = DrakType2; - - ++SpawnedAdds; - - Spawned = me->SummonCreature(CreatureID, ADD_X2, ADD_Y2, ADD_Z2, 5.000f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target && Spawned) - { - Spawned->AI()->AttackStart(target); - Spawned->setFaction(103); - } - - //Begin phase 2 by spawning Nefarian and what not - if (SpawnedAdds >= 42) - { - //Teleport Victor Nefarius way out of the map - //sMapMgr->GetMap(me->GetMapId(), me)->CreatureRelocation(me, 0, 0, -5000, 0); - - //Interrupt any spell casting - me->InterruptNonMeleeSpells(false); - - //Root self - DoCast(me, 33356); - - //Make super invis - DoCast(me, 8149); - - //Teleport self to a hiding spot (this causes errors in the Trinity log but no real issues) - DoTeleportTo(HIDE_X, HIDE_Y, HIDE_Z); - me->AddUnitState(UNIT_STATE_FLEEING); - - //Spawn nef and have him attack a random target - Creature* Nefarian = me->SummonCreature(CREATURE_NEFARIAN, NEF_X, NEF_Y, NEF_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target && Nefarian) - { - Nefarian->AI()->AttackStart(target); - Nefarian->setFaction(103); - NefarianGUID = Nefarian->GetGUID(); - } - else TC_LOG_ERROR(LOG_FILTER_TSCR, "Blackwing Lair: Unable to spawn nefarian properly."); - } - - AddSpawnTimer = 4000; - } else AddSpawnTimer -= diff; - } - else if (NefarianGUID) - { - if (NefCheckTime <= diff) - { - Unit* Nefarian = Unit::GetCreature((*me), NefarianGUID); - - //If nef is dead then we die to so the players get out of combat - //and cannot repeat the event - if (!Nefarian || !Nefarian->IsAlive()) - { - NefarianGUID = 0; - me->DespawnOrUnsummon(); - } - - NefCheckTime = 2000; - } else NefCheckTime -= diff; - } - } - }; -}; - -void AddSC_boss_victor_nefarius() -{ - new boss_victor_nefarius(); -} diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/instance_blackwing_lair.cpp index 279375be228..e0a813a6590 100644 --- a/src/server/scripts/EasternKingdoms/BlackwingLair/instance_blackwing_lair.cpp +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/instance_blackwing_lair.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,12 +15,341 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance_Blackwing_Lair -SD%Complete: 0 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - #include "ScriptMgr.h" -#include "InstanceScript.h" +#include "ScriptedCreature.h" +#include "PassiveAI.h" +#include "blackwing_lair.h" +#include "Player.h" + +/* +Blackwing Lair Encounter: +1 - boss_razorgore.cpp +2 - boss_vaelastrasz.cpp +3 - boss_broodlord_lashlayer.cpp +4 - boss_firemaw.cpp +5 - boss_ebonroc.cpp +6 - boss_flamegor.cpp +7 - boss_chromaggus.cpp +8 - boss_nefarian.cpp +*/ + +Position const SummonPosition[8] = +{ + {-7661.207520f, -1043.268188f, 407.199554f, 6.280452f}, + {-7644.145020f, -1065.628052f, 407.204956f, 0.501492f}, + {-7624.260742f, -1095.196899f, 407.205017f, 0.544694f}, + {-7608.501953f, -1116.077271f, 407.199921f, 0.816443f}, + {-7531.841797f, -1063.765381f, 407.199615f, 2.874187f}, + {-7547.319336f, -1040.971924f, 407.205078f, 3.789175f}, + {-7568.547852f, -1013.112488f, 407.204926f, 3.773467f}, + {-7584.175781f, -989.6691289f, 407.199585f, 4.527447f}, +}; + +uint32 const Entry[5] = {12422, 12458, 12416, 12420, 12459}; + +class instance_blackwing_lair : public InstanceMapScript +{ +public: + instance_blackwing_lair() : InstanceMapScript(BRLScriptName, 469) { } + + struct instance_blackwing_lair_InstanceMapScript : public InstanceScript + { + instance_blackwing_lair_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + } + + void Initialize() + { + // Razorgore + EggCount = 0; + RazorgoreTheUntamedGUID = 0; + RazorgoreDoorGUID = 0; + EggList.clear(); + // Vaelastrasz the Corrupt + VaelastraszTheCorruptGUID = 0; + VaelastraszDoorGUID = 0; + // Broodlord Lashlayer + BroodlordLashlayerGUID = 0; + BroodlordDoorGUID = 0; + // 3 Dragons + FiremawGUID = 0; + EbonrocGUID = 0; + FlamegorGUID = 0; + ChrommagusDoorGUID = 0; + // Chormaggus + ChromaggusGUID = 0; + NefarianDoorGUID = 0; + // Nefarian + LordVictorNefariusGUID = 0; + NefarianGUID = 0; + } + + void OnCreatureCreate(Creature* creature) + { + switch (creature->GetEntry()) + { + case NPC_RAZORGORE: + RazorgoreTheUntamedGUID = creature->GetGUID(); + break; + case NPC_BLACKWING_DRAGON: + case NPC_BLACKWING_TASKMASTER: + case NPC_BLACKWING_LEGIONAIRE: + case NPC_BLACKWING_WARLOCK: + if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID)) + razor->AI()->JustSummoned(creature); + break; + case NPC_VAELASTRAZ: + VaelastraszTheCorruptGUID = creature->GetGUID(); + break; + case NPC_BROODLORD: + BroodlordLashlayerGUID = creature->GetGUID(); + break; + case NPC_FIRENAW: + FiremawGUID = creature->GetGUID(); + break; + case NPC_EBONROC: + EbonrocGUID = creature->GetGUID(); + break; + case NPC_FLAMEGOR: + FlamegorGUID = creature->GetGUID(); + break; + case NPC_CHROMAGGUS: + ChromaggusGUID = creature->GetGUID(); + break; + case NPC_VICTOR_NEFARIUS: + LordVictorNefariusGUID = creature->GetGUID(); + break; + case NPC_NEFARIAN: + NefarianGUID = creature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* go) + { + switch (go->GetEntry()) + { + case 177807: // Egg + if (GetBossState(BOSS_FIREMAW) == DONE) + go->SetPhaseMask(2, true); + else + EggList.push_back(go->GetGUID()); + break; + case 175946: // Door + RazorgoreDoorGUID = go->GetGUID(); + HandleGameObject(0, GetBossState(BOSS_RAZORGORE) == DONE, go); + break; + case 175185: // Door + VaelastraszDoorGUID = go->GetGUID(); + HandleGameObject(0, GetBossState(BOSS_VAELASTRAZ) == DONE, go); + break; + case 180424: // Door + BroodlordDoorGUID = go->GetGUID(); + HandleGameObject(0, GetBossState(BOSS_BROODLORD) == DONE, go); + break; + case 185483: // Door + ChrommagusDoorGUID = go->GetGUID(); + HandleGameObject(0, GetBossState(BOSS_FIREMAW) == DONE && GetBossState(BOSS_EBONROC) == DONE && GetBossState(BOSS_FLAMEGOR) == DONE, go); + break; + case 181125: // Door + NefarianDoorGUID = go->GetGUID(); + HandleGameObject(0, GetBossState(BOSS_CHROMAGGUS) == DONE, go); + break; + } + } + + void OnGameObjectRemove(GameObject* go) + { + if (go->GetEntry() == 177807) // Egg + EggList.remove(go->GetGUID()); + } + + bool SetBossState(uint32 type, EncounterState state) + { + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) + { + case BOSS_RAZORGORE: + HandleGameObject(RazorgoreDoorGUID, state == DONE); + if (state == DONE) + { + for (std::list<uint64>::const_iterator itr = EggList.begin(); itr != EggList.end(); ++itr) + if (GameObject* egg = instance->GetGameObject((*itr))) + egg->SetPhaseMask(2, true); + } + SetData(DATA_EGG_EVENT, NOT_STARTED); + break; + case BOSS_VAELASTRAZ: + HandleGameObject(VaelastraszDoorGUID, state == DONE); + break; + case BOSS_BROODLORD: + HandleGameObject(BroodlordDoorGUID, state == DONE); + break; + case BOSS_FIREMAW: + case BOSS_EBONROC: + case BOSS_FLAMEGOR: + HandleGameObject(ChrommagusDoorGUID, GetBossState(BOSS_FIREMAW) == DONE && GetBossState(BOSS_EBONROC) == DONE && GetBossState(BOSS_FLAMEGOR) == DONE); + break; + case BOSS_CHROMAGGUS: + HandleGameObject(NefarianDoorGUID, state == DONE); + break; + case BOSS_NEFARIAN: + switch (state) + { + case NOT_STARTED: + if (Creature* nefarian = instance->GetCreature(NefarianGUID)) + nefarian->DespawnOrUnsummon(); + break; + case FAIL: + _events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15*IN_MILLISECONDS*MINUTE); + SetBossState(BOSS_NEFARIAN, NOT_STARTED); + break; + default: + break; + } + break; + } + return true; + } + + uint64 GetData64(uint32 id) const + { + switch (id) + { + case DATA_RAZORGORE_THE_UNTAMED: return RazorgoreTheUntamedGUID; + case DATA_VAELASTRAZ_THE_CORRUPT: return VaelastraszTheCorruptGUID; + case DATA_BROODLORD_LASHLAYER: return BroodlordLashlayerGUID; + case DATA_FIRENAW: return FiremawGUID; + case DATA_EBONROC: return EbonrocGUID; + case DATA_FLAMEGOR: return FlamegorGUID; + case DATA_CHROMAGGUS: return ChromaggusGUID; + case DATA_LORD_VICTOR_NEFARIUS: return LordVictorNefariusGUID; + case DATA_NEFARIAN: return NefarianGUID; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + if (type == DATA_EGG_EVENT) + { + switch (data) + { + case IN_PROGRESS: + _events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45*IN_MILLISECONDS); + EggEvent = data; + EggCount = 0; + break; + case NOT_STARTED: + _events.CancelEvent(EVENT_RAZOR_SPAWN); + EggEvent = data; + EggCount = 0; + break; + case SPECIAL: + if (++EggCount == 15) + { + if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID)) + { + SetData(DATA_EGG_EVENT, DONE); + razor->RemoveAurasDueToSpell(42013); // MindControl + DoRemoveAurasDueToSpellOnPlayers(42013); + } + _events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, IN_MILLISECONDS); + _events.CancelEvent(EVENT_RAZOR_SPAWN); + } + if (EggEvent == NOT_STARTED) + SetData(DATA_EGG_EVENT, IN_PROGRESS); + break; + } + } + } + + void OnUnitDeath(Unit* unit) + { + //! HACK, needed because of buggy CreatureAI after charm + if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(BOSS_RAZORGORE) != DONE) + SetBossState(BOSS_RAZORGORE, DONE); + } + + void Update(uint32 diff) + { + if (_events.Empty()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_RAZOR_SPAWN: + for (uint8 i = urand(2, 5); i > 0 ; --i) + if (Creature* summon = instance->SummonCreature(Entry[urand(0, 4)], SummonPosition[urand(0, 7)])) + summon->SetInCombatWithZone(); + _events.ScheduleEvent(EVENT_RAZOR_SPAWN, urand(12, 17)*IN_MILLISECONDS); + break; + case EVENT_RAZOR_PHASE_TWO: + _events.CancelEvent(EVENT_RAZOR_SPAWN); + if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID)) + razor->AI()->DoAction(ACTION_PHASE_TWO); + break; + case EVENT_RESPAWN_NEFARIUS: + if (Creature* nefarius = instance->GetCreature(LordVictorNefariusGUID)) + { + nefarius->SetPhaseMask(1, true); + nefarius->setActive(true); + nefarius->Respawn(); + nefarius->GetMotionMaster()->MoveTargetedHome(); + } + break; + } + } + } + + protected: + // Misc + EventMap _events; + // Razorgore + uint8 EggCount; + uint32 EggEvent; + uint64 RazorgoreTheUntamedGUID; + uint64 RazorgoreDoorGUID; + std::list<uint64> EggList; + + // Vaelastrasz the Corrupt + uint64 VaelastraszTheCorruptGUID; + uint64 VaelastraszDoorGUID; + + // Broodlord Lashlayer + uint64 BroodlordLashlayerGUID; + uint64 BroodlordDoorGUID; + + // 3 Dragons + uint64 FiremawGUID; + uint64 EbonrocGUID; + uint64 FlamegorGUID; + uint64 ChrommagusDoorGUID; + + // Chormaggus + uint64 ChromaggusGUID; + uint64 NefarianDoorGUID; + + // Nefarian + uint64 LordVictorNefariusGUID; + uint64 NefarianGUID; + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const + { + return new instance_blackwing_lair_InstanceMapScript(map); + } +}; + +void AddSC_instance_blackwing_lair() +{ + new instance_blackwing_lair(); +} diff --git a/src/server/scripts/EasternKingdoms/CMakeLists.txt b/src/server/scripts/EasternKingdoms/CMakeLists.txt index 0737972c5b3..37cd2359923 100644 --- a/src/server/scripts/EasternKingdoms/CMakeLists.txt +++ b/src/server/scripts/EasternKingdoms/CMakeLists.txt @@ -171,7 +171,7 @@ set(scripts_STAT_SRCS EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp EasternKingdoms/BlackwingLair/boss_nefarian.cpp EasternKingdoms/BlackwingLair/boss_flamegor.cpp - EasternKingdoms/BlackwingLair/boss_victor_nefarius.cpp + EasternKingdoms/BlackwingLair/blackwing_lair.h EasternKingdoms/zone_blasted_lands.cpp EasternKingdoms/zone_stormwind_city.cpp EasternKingdoms/ZulAman/boss_halazzi.cpp diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp index 535d9a4425b..525f71b7d01 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp @@ -21,8 +21,14 @@ enum Spells { - SPELL_POISON_CLOUD = 3815, - SPELL_FRENZIED_RAGE = 3490 + SPELL_POISON_CLOUD = 3815, + SPELL_FRENZIED_RAGE = 3490 +}; + +enum Events +{ + EVENT_POISON_CLOUD = 1, + EVENT_FRENZIED_RAGE = 2 }; class boss_aku_mai : public CreatureScript @@ -30,41 +36,25 @@ class boss_aku_mai : public CreatureScript public: boss_aku_mai() : CreatureScript("boss_aku_mai") { } - CreatureAI* GetAI(Creature* creature) const + struct boss_aku_maiAI : public BossAI { - return new boss_aku_maiAI (creature); - } - - struct boss_aku_maiAI : public ScriptedAI - { - boss_aku_maiAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } - - uint32 poisonCloudTimer; - bool IsEnraged; - - InstanceScript* instance; + boss_aku_maiAI(Creature* creature) : BossAI(creature, TYPE_AKU_MAI) { } void Reset() { - poisonCloudTimer = urand(5000, 9000); IsEnraged = false; - if (instance) - instance->SetData(TYPE_AKU_MAI, NOT_STARTED); + _Reset(); } void EnterCombat(Unit* /*who*/) { - if (instance) - instance->SetData(TYPE_AKU_MAI, IN_PROGRESS); + events.ScheduleEvent(EVENT_POISON_CLOUD, urand(5000, 9000)); + _EnterCombat(); } void JustDied(Unit* /*killer*/) { - if (instance) - instance->SetData(TYPE_AKU_MAI, DONE); + _JustDied(); } void UpdateAI(uint32 diff) @@ -72,21 +62,38 @@ public: if (!UpdateVictim()) return; - if (poisonCloudTimer < diff) - { - DoCastVictim(SPELL_POISON_CLOUD); - poisonCloudTimer = urand(25000, 50000); - } else poisonCloudTimer -= diff; + events.Update(diff); if (!IsEnraged && HealthBelowPct(30)) + events.ScheduleEvent(EVENT_FRENZIED_RAGE, 100); + + while (uint32 eventId = events.ExecuteEvent()) { - DoCast(me, SPELL_FRENZIED_RAGE); - IsEnraged = true; + switch (eventId) + { + case EVENT_POISON_CLOUD: + DoCastVictim(SPELL_POISON_CLOUD); + events.ScheduleEvent(EVENT_POISON_CLOUD, urand(25000, 50000)); + break; + case EVENT_FRENZIED_RAGE: + DoCast(me, SPELL_FRENZIED_RAGE); + IsEnraged = true; + break; + default: + break; + } } - DoMeleeAttackIfReady(); } + + private: + bool IsEnraged; }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_aku_maiAI (creature); + } }; void AddSC_boss_aku_mai() diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp index 498a4368168..39428e07fd8 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp @@ -135,12 +135,12 @@ public: } DoMeleeAttackIfReady(); } - - CreatureAI* GetAI(Creature* creature) const - { - return new boss_aeonusAI (creature); - } }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_aeonusAI (creature); + } }; void AddSC_boss_aeonus() diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp index d02dc0dd359..bd217ce51ee 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp @@ -140,12 +140,12 @@ public: DoMeleeAttackIfReady(); } - - CreatureAI* GetAI(Creature* creature) const - { - return new boss_chrono_lord_dejaAI (creature); - } }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_chrono_lord_dejaAI (creature); + } }; void AddSC_boss_chrono_lord_deja() diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp index 8ded2388083..f679fa4ee62 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp @@ -138,13 +138,12 @@ public: } DoMeleeAttackIfReady(); } - - CreatureAI* GetAI(Creature* creature) const - { - return new boss_temporusAI (creature); - } }; + CreatureAI* GetAI(Creature* creature) const + { + return new boss_temporusAI (creature); + } }; void AddSC_boss_temporus() diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 8fa4e030243..41892694055 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -467,10 +467,6 @@ class npc_bone_spike : public CreatureScript init.DisableTransportPathTransformations(); init.MoveTo(-0.02206125f, -0.02132235f, 5.514783f, false); init.Launch(); - - /// @WORKAROUND - Clear ON VEHICLE state to allow healing (Invalid target errors) - /// Current rule for applying this state is questionable (seatFlags & VEHICLE_SEAT_FLAG_ALLOW_TURNING ???) - passenger->ClearUnitState(UNIT_STATE_ONVEHICLE); } void UpdateAI(uint32 diff) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index bec1a32e2e8..00d1aac8e76 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -1632,7 +1632,7 @@ class FlameLeviathanPursuedTargetSelector //! Vehicle must be in use by player bool playerFound = false; for (SeatMap::const_iterator itr = vehicle->Seats.begin(); itr != vehicle->Seats.end() && !playerFound; ++itr) - if (IS_PLAYER_GUID(itr->second.Passenger)) + if (IS_PLAYER_GUID(itr->second.Passenger.Guid)) playerFound = true; return !playerFound; @@ -1690,9 +1690,9 @@ class spell_pursue : public SpellScriptLoader for (SeatMap::const_iterator itr = caster->GetVehicleKit()->Seats.begin(); itr != caster->GetVehicleKit()->Seats.end(); ++itr) { - if (IS_PLAYER_GUID(itr->second.Passenger)) + if (IS_PLAYER_GUID(itr->second.Passenger.Guid)) { - caster->AI()->Talk(EMOTE_PURSUE, itr->second.Passenger); + caster->AI()->Talk(EMOTE_PURSUE, itr->second.Passenger.Guid); return; } } diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index aa6c53c188b..bf8a454f9e5 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -26,129 +26,19 @@ #include "Player.h" #include "WorldSession.h" -/*###### -## npc_agnetta_tyrsdottar -######*/ - -#define GOSSIP_AGNETTA "Skip the warmup, sister... or are you too scared to face soemeone your own size?" - -enum eAgnetta -{ - QUEST_ITS_THAT_YOUR_GOBLIN = 12969, - FACTION_HOSTILE_AT1 = 45, - SAY_AGGRO = 0 -}; - -class npc_agnetta_tyrsdottar : public CreatureScript -{ -public: - npc_agnetta_tyrsdottar() : CreatureScript("npc_agnetta_tyrsdottar") { } - - struct npc_agnetta_tyrsdottarAI : public ScriptedAI - { - npc_agnetta_tyrsdottarAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() - { - me->RestoreFaction(); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_agnetta_tyrsdottarAI(creature); - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (player->GetQuestStatus(QUEST_ITS_THAT_YOUR_GOBLIN) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_AGNETTA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(13691, creature->GetGUID()); - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - creature->AI()->Talk(SAY_AGGRO); - player->CLOSE_GOSSIP_MENU(); - creature->setFaction(FACTION_HOSTILE_AT1); - creature->AI()->AttackStart(player); - } - - return true; - } -}; - -/*###### -## npc_frostborn_scout -######*/ - -#define GOSSIP_ITEM1 "Are you okay? I've come to take you back to Frosthold if you can stand." -#define GOSSIP_ITEM2 "I'm sorry that I didn't get here sooner. What happened?" -#define GOSSIP_ITEM3 "I'll go get some help. Hang in there." - -enum eFrostbornScout -{ - QUEST_MISSING_SCOUTS = 12864 -}; - -class npc_frostborn_scout : public CreatureScript -{ -public: - npc_frostborn_scout() : CreatureScript("npc_frostborn_scout") { } - - bool OnGossipHello(Player* player, Creature* creature) - { - - if (player->GetQuestStatus(QUEST_MISSING_SCOUTS) == QUEST_STATUS_INCOMPLETE) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->PlayerTalkClass->SendGossipMenu(13611, creature->GetGUID()); - } - - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->PlayerTalkClass->SendGossipMenu(13612, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - player->PlayerTalkClass->SendGossipMenu(13613, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->PlayerTalkClass->SendGossipMenu(13614, creature->GetGUID()); - player->AreaExploredOrEventHappens(QUEST_MISSING_SCOUTS); - break; - } - - return true; - } -}; - ///////////////////// ///npc_injured_goblin ///////////////////// -enum eInjuredGoblin +enum InjuredGoblinMiner { QUEST_BITTER_DEPARTURE = 12832, SAY_QUEST_ACCEPT = 0, - SAY_END_WP_REACHED = 1 + SAY_END_WP_REACHED = 1, + GOSSIP_ID = 9859, + GOSSIP_OPTION_ID = 0 }; -#define GOSSIP_ITEM_1 "I am ready, lets get you out of here" - class npc_injured_goblin : public CreatureScript { public: @@ -193,6 +83,16 @@ public: return; DoMeleeAttackIfReady(); } + + void sGossipSelect(Player* player, uint32 sender, uint32 action) + { + if (sender == GOSSIP_ID && action == GOSSIP_OPTION_ID) + { + player->CLOSE_GOSSIP_MENU(); + me->setFaction(113); + npc_escortAI::Start(true, true, player->GetGUID()); + } + } }; CreatureAI* GetAI(Creature* creature) const @@ -200,21 +100,6 @@ public: return new npc_injured_goblinAI(creature); } - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_BITTER_DEPARTURE) == QUEST_STATUS_INCOMPLETE) - { - player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->PlayerTalkClass->SendGossipMenu(9999999, creature->GetGUID()); - } - else - player->SEND_GOSSIP_MENU(999999, creature->GetGUID()); - return true; - } - bool OnQuestAccept(Player* /*player*/, Creature* creature, Quest const* quest) { if (quest->GetQuestId() == QUEST_BITTER_DEPARTURE) @@ -222,19 +107,6 @@ public: return false; } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - npc_escortAI* pEscortAI = CAST_AI(npc_injured_goblin::npc_injured_goblinAI, creature->AI()); - - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - pEscortAI->Start(true, true, player->GetGUID()); - creature->setFaction(113); - } - return true; - } }; /*###### @@ -323,10 +195,8 @@ public: if (!freed) return; - if (!me->HasUnitState(UNIT_STATE_ONVEHICLE)) - { + if (!me->GetVehicle()) me->DespawnOrUnsummon(); - } } void SpellHit(Unit* caster, const SpellInfo* spell) @@ -589,8 +459,6 @@ class spell_close_rift : public SpellScriptLoader void AddSC_storm_peaks() { - new npc_agnetta_tyrsdottar(); - new npc_frostborn_scout(); new npc_injured_goblin(); new npc_roxi_ramrocket(); new npc_brunnhildar_prisoner(); diff --git a/src/server/shared/SystemConfig.h b/src/server/shared/SystemConfig.h index a6076273522..c3e54763ff0 100644 --- a/src/server/shared/SystemConfig.h +++ b/src/server/shared/SystemConfig.h @@ -34,7 +34,7 @@ #if PLATFORM == PLATFORM_WINDOWS # ifdef _WIN64 -# define _FULLVERSION _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Win64, "_BUILD_DIRECTIVE ")" +# define _FULLVERSION _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Win64, " _BUILD_DIRECTIVE ")" # else # define _FULLVERSION _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Win32, " _BUILD_DIRECTIVE ")" # endif diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index d4192571454..9dfdf95643d 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -518,8 +518,8 @@ namespace MMAP config.walkableRadius = m_bigBaseUnit ? 1 : 2; config.borderSize = config.walkableRadius + 3; config.maxEdgeLen = VERTEX_PER_TILE + 1; // anything bigger than tileSize - config.walkableHeight = m_bigBaseUnit ? 2 : 4; - config.walkableClimb = m_bigBaseUnit ? 1 : 2; // keep less than walkableHeight + config.walkableHeight = m_bigBaseUnit ? 3 : 6; + config.walkableClimb = m_bigBaseUnit ? 2 : 4; // keep less than walkableHeight config.minRegionArea = rcSqr(60); config.mergeRegionArea = rcSqr(50); config.maxSimplificationError = 1.8f; // eliminates most jagged edges (tiny polygons) diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index f929da63f56..baa340b75bd 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -130,7 +130,6 @@ Vec3D fixCoordSystem2(Vec3D v) } ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile) - : model(NULL), d1(0), w(0.0f) { float ff[3]; f.read(&id, 4); @@ -138,7 +137,8 @@ ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID pos = fixCoords(Vec3D(ff[0], ff[1], ff[2])); f.read(ff, 12); rot = Vec3D(ff[0], ff[1], ff[2]); - f.read(&scale, 4); + f.read(&scale, 2); + f.read(&flags, 2); // scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float? sc = scale / 1024.0f; diff --git a/src/tools/vmap4_extractor/model.h b/src/tools/vmap4_extractor/model.h index a45da99d762..f73efa9fe80 100644 --- a/src/tools/vmap4_extractor/model.h +++ b/src/tools/vmap4_extractor/model.h @@ -53,14 +53,12 @@ public: class ModelInstance { public: - Model* model; - uint32 id; Vec3D pos, rot; - unsigned int d1, scale; - float w, sc; + uint16 scale, flags; + float sc; - ModelInstance() : model(NULL), id(0), d1(0), scale(0), w(0.0f), sc(0.0f) {} + ModelInstance() : id(0), scale(0), flags(0), sc(0.0f) {} ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile); }; |