diff options
Diffstat (limited to 'src')
80 files changed, 3189 insertions, 1171 deletions
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h index f4555649210..fbc8675cc47 100644 --- a/src/server/game/AI/CoreAI/GameObjectAI.h +++ b/src/server/game/AI/CoreAI/GameObjectAI.h @@ -53,7 +53,8 @@ class GameObjectAI virtual uint64 GetData64(uint32 /*id*/) { return 0; } virtual void SetData(uint32 /*id*/, uint32 /*value*/) {} virtual void OnGameEvent(bool /*start*/, uint16 /*eventId*/) {} - virtual void OnStateChanged(uint32 /*state*/, Unit* /*unit*/) { } + virtual void OnStateChanged(uint32 /*state*/, Unit* /*unit*/) {} + virtual void EventInform(uint32 /*eventId*/) {} }; class NullGameObjectAI : public GameObjectAI diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 160b406a6ea..97ae0581a18 100755 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -532,3 +532,19 @@ bool PetAI::CanAttack(Unit* target) // default, though we shouldn't ever get here return false; } + +void PetAI::ReceiveEmote(Player* player, uint32 emote) +{ + if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID()) + switch (emote) + { + case TEXT_EMOTE_COWER: + if (me->isPet() && me->ToPet()->IsPetGhoul()) + me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + break; + case TEXT_EMOTE_ANGRY: + if (me->isPet() && me->ToPet()->IsPetGhoul()) + me->HandleEmoteCommand(EMOTE_ONESHOT_COWER); + break; + } +} diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h index ed3e2305556..8e5311fa000 100755 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -42,6 +42,7 @@ class PetAI : public CreatureAI void MovementInform(uint32 moveType, uint32 data); void OwnerDamagedBy(Unit* attacker); void OwnerAttacked(Unit* target); + void ReceiveEmote(Player* player, uint32 textEmote); private: bool _isVisible(Unit*) const; diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp index 517e55af457..a863f2f89cf 100755 --- a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp +++ b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp @@ -204,12 +204,17 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() temp.raw.param3 = fields[8].GetInt32(); temp.raw.param4 = fields[9].GetInt32(); + CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id); //Creature does not exist in database - if (!sObjectMgr->GetCreatureTemplate(temp.creature_id)) + if (!cInfo) { - sLog->outErrorDb("CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, temp.creature_id); + sLog->outErrorDb("CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, creature_id); continue; } + + // Only on the first script + if (cInfo->AIName != "EventAI" && m_CreatureEventAI_Event_Map[creature_id].empty()) + sLog->outErrorDb("Creature entry %u has EventAI scripts, but its AIName is not 'EventAI' - possible AI-mismatch?", temp.creature_id); //No chance of this event occuring if (temp.event_chance == 0) @@ -735,18 +740,6 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() } while (result->NextRow()); - for (CreatureEventAI_Event_Map::const_iterator itr = m_CreatureEventAI_Event_Map.begin(); itr != m_CreatureEventAI_Event_Map.end(); ++itr) - { - if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(itr->first)) - { - if (cInfo->AIName != "EventAI") - { - sLog->outErrorDb("Creature entry %u has EventAI scripts, but its AIName is not 'EventAI', changing to EventAI", itr->first); - const_cast<CreatureTemplate*>(cInfo)->AIName = "EventAI"; - } - } - } - sLog->outString(">> Loaded %u CreatureEventAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 08f1b18ffad..98b5c0a6ba3 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -937,6 +937,11 @@ void SmartGameObjectAI::OnStateChanged(uint32 state, Unit* unit) GetScript()->ProcessEventsFor(SMART_EVENT_GO_STATE_CHANGED, unit, state); } +void SmartGameObjectAI::EventInform(uint32 eventId) +{ + GetScript()->ProcessEventsFor(SMART_EVENT_GO_EVENT_INFORM, NULL, eventId); +} + class SmartTrigger : public AreaTriggerScript { public: diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index 435aa176d4d..3a3a7dc9510 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -235,30 +235,31 @@ class SmartAI : public CreatureAI class SmartGameObjectAI : public GameObjectAI { -public: - SmartGameObjectAI(GameObject* g) : GameObjectAI(g), go(g) {} - ~SmartGameObjectAI() {} - - void UpdateAI(uint32 diff); - void InitializeAI(); - void Reset(); - SmartScript* GetScript() { return &mScript; } - static int Permissible(const GameObject* g); - - bool GossipHello(Player* player); - bool GossipSelect(Player* player, uint32 sender, uint32 action); - bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/); - bool QuestAccept(Player* player, Quest const* quest); - bool QuestReward(Player* player, Quest const* quest, uint32 opt); - uint32 GetDialogStatus(Player* /*player*/); - void Destroyed(Player* player, uint32 eventId); - void SetData(uint32 id, uint32 value); - void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker); - void OnGameEvent(bool start, uint16 eventId); - void OnStateChanged(uint32 state, Unit* unit); - -protected: - GameObject* const go; - SmartScript mScript; + public: + SmartGameObjectAI(GameObject* g) : GameObjectAI(g), go(g) {} + ~SmartGameObjectAI() {} + + void UpdateAI(uint32 diff); + void InitializeAI(); + void Reset(); + SmartScript* GetScript() { return &mScript; } + static int Permissible(const GameObject* g); + + bool GossipHello(Player* player); + bool GossipSelect(Player* player, uint32 sender, uint32 action); + bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/); + bool QuestAccept(Player* player, Quest const* quest); + bool QuestReward(Player* player, Quest const* quest, uint32 opt); + uint32 GetDialogStatus(Player* /*player*/); + void Destroyed(Player* player, uint32 eventId); + void SetData(uint32 id, uint32 value); + void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker); + void OnGameEvent(bool start, uint16 eventId); + void OnStateChanged(uint32 state, Unit* unit); + void EventInform(uint32 eventId); + + protected: + GameObject* const go; + SmartScript mScript; }; #endif diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 01a9b777358..1b414029366 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -160,9 +160,6 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { case SMART_ACTION_TALK: { - if (!me) - break; - ObjectList* targets = GetTargets(e, unit); Creature* talker = me; Player* targetPlayer = NULL; @@ -185,6 +182,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u delete targets; } + if (!talker) + break; + mTalkerEntry = talker->GetEntry(); mLastTextID = e.action.talk.textGroupID; mTextTimer = e.action.talk.duration; @@ -789,7 +789,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!IsUnit((*itr))) continue; - (*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); + if (e.action.removeAura.spell == 0) + (*itr)->ToUnit()->RemoveAllAuras(); + else + (*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); + sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: Unit %u, spell %u", (*itr)->GetGUIDLow(), e.action.removeAura.spell); } @@ -2016,16 +2020,16 @@ void SmartScript::InstallTemplate(SmartScriptHolder const& e) if (!go) return; //store hostage as id1 - AddEvent(SMART_EVENT_GOSSIP_HELLO, 0, 0, 0, 0, 0, SMART_ACTION_STORE_TARGET_LIST, 1, 0, 0, 0, 0, 0, SMART_TARGET_CLOSEST_CREATURE, e.action.installTtemplate.param1, 10, 0, 0); + AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, SMART_ACTION_STORE_TARGET_LIST, 1, 0, 0, 0, 0, 0, SMART_TARGET_CLOSEST_CREATURE, e.action.installTtemplate.param1, 10, 0, 0); //store invoker as id2 - AddEvent(SMART_EVENT_GOSSIP_HELLO, 0, 0, 0, 0, 0, SMART_ACTION_STORE_TARGET_LIST, 2, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0); + AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, SMART_ACTION_STORE_TARGET_LIST, 2, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0); //signal hostage - AddEvent(SMART_EVENT_GOSSIP_HELLO, 0, 0, 0, 0, 0, SMART_ACTION_SET_DATA, 0, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 1, 0, 0, 0); + AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, SMART_ACTION_SET_DATA, 0, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 1, 0, 0, 0); //when hostage raeched end point, give credit to invoker if (e.action.installTtemplate.param2) AddEvent(SMART_EVENT_DATA_SET, 0, 0, 0, 0, 0, SMART_ACTION_CALL_KILLEDMONSTER, e.action.installTtemplate.param1, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 2, 0, 0, 0); else - AddEvent(SMART_EVENT_GOSSIP_HELLO, 0, 0, 0, 0, 0, SMART_ACTION_CALL_KILLEDMONSTER, e.action.installTtemplate.param1, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 2, 0, 0, 0); + AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, SMART_ACTION_CALL_KILLEDMONSTER, e.action.installTtemplate.param1, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 2, 0, 0, 0); break; } case SMARTAI_TEMPLATE_BASIC: @@ -2119,12 +2123,20 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* case SMART_TARGET_INVOKER_PARTY: if (trigger) { - l->push_back(trigger); if (Player* player = trigger->ToPlayer()) + { if (Group* group = player->GetGroup()) + { for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next()) if (Player* member = groupRef->getSource()) l->push_back(member); + } + // We still add the player to the list if there is no group. If we do + // this even if there is a group (thus the else-check), it will add the + // same player to the list twice. We don't want that to happen. + else + l->push_back(trigger); + } } break; case SMART_TARGET_CREATURE_RANGE: @@ -2759,6 +2771,13 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui ProcessAction(e, unit, var0, var1); break; } + case SMART_EVENT_GO_EVENT_INFORM: + { + if (e.event.eventInform.eventId != var0) + return; + ProcessAction(e, NULL, var0); + break; + } default: sLog->outErrorDb("SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType()); break; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index a7149f37480..bf84f39747a 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -533,6 +533,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) break; } case SMART_EVENT_GO_STATE_CHANGED: + case SMART_EVENT_GO_EVENT_INFORM: case SMART_EVENT_TIMED_EVENT_TRIGGERED: case SMART_EVENT_INSTANCE_PLAYER_ENTER: case SMART_EVENT_TRANSPORT_RELOCATE: @@ -709,7 +710,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; break; case SMART_ACTION_REMOVEAURASFROMSPELL: - if (!IsSpellValid(e, e.action.removeAura.spell)) + if (e.action.removeAura.spell != 0 && !IsSpellValid(e, e.action.removeAura.spell)) return false; break; case SMART_ACTION_RANDOM_PHASE: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index c23e288f66d..b82d0724f53 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -153,9 +153,10 @@ enum SMART_EVENT SMART_EVENT_IS_BEHIND_TARGET = 67, //1 // cooldownMin, CooldownMax SMART_EVENT_GAME_EVENT_START = 68, //1 // game_event.Entry SMART_EVENT_GAME_EVENT_END = 69, //1 // game_event.Entry - SMART_EVENT_GO_STATE_CHANGED = 70, // go state + SMART_EVENT_GO_STATE_CHANGED = 70, //1 // go state + SMART_EVENT_GO_EVENT_INFORM = 71, //1 // eventId - SMART_EVENT_END = 71, + SMART_EVENT_END = 72, }; struct SmartEvent @@ -352,6 +353,11 @@ struct SmartEvent struct { + uint32 eventId; + } eventInform; + + struct + { uint32 param1; uint32 param2; uint32 param3; @@ -398,7 +404,7 @@ enum SMART_ACTION SMART_ACTION_FLEE_FOR_ASSIST = 25, // With Emote SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // QuestID SMART_ACTION_CALL_CASTEDCREATUREORGO = 27, // CreatureId, SpellId - SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid + SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid, 0 removes all auras SMART_ACTION_FOLLOW = 29, // Distance (0 = default), Angle (0 = default), EndCreatureEntry, credit, creditType (0monsterkill, 1event) SMART_ACTION_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3... SMART_ACTION_RANDOM_PHASE_RANGE = 31, // PhaseMin, PhaseMax @@ -1166,7 +1172,7 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] = {SMART_EVENT_GAME_EVENT_START, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_GAME_EVENT_END, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_GO_STATE_CHANGED, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, - + {SMART_EVENT_GO_EVENT_INFORM, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, }; enum SmartEventFlags diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index c589edcee7a..85bbd2f3b89 100755 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -850,12 +850,8 @@ void Battleground::EndBattleground(uint32 winner) if (team == winner) { // update achievement BEFORE personal rating update - if (ArenaTeamMember* member = winner_arena_team->GetMember(player->GetGUID())) - { - uint32 rating = player->GetArenaPersonalRating(winner_arena_team->GetSlot()); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, - rating ? rating : 1); - } + uint32 rating = player->GetArenaPersonalRating(winner_arena_team->GetSlot()); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1); winner_arena_team->MemberWon(player, loser_matchmaker_rating, winner_matchmaker_change); } diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp index 30562bb9662..4b2f1c5e7bb 100755 --- a/src/server/game/Chat/Commands/Level3.cpp +++ b/src/server/game/Chat/Commands/Level3.cpp @@ -1144,15 +1144,20 @@ bool ChatHandler::HandleLookupQuestCommand(const char *args) { QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); - if (status == QUEST_STATUS_COMPLETE) + switch (status) { - if (target->GetQuestRewardStatus(qinfo->GetQuestId())) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); - else + case QUEST_STATUS_COMPLETE: statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + break; + case QUEST_STATUS_INCOMPLETE: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + break; + case QUEST_STATUS_REWARDED: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + break; + default: + break; } - else if (status == QUEST_STATUS_INCOMPLETE) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); } if (m_session) @@ -1187,15 +1192,20 @@ bool ChatHandler::HandleLookupQuestCommand(const char *args) { QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); - if (status == QUEST_STATUS_COMPLETE) + switch (status) { - if (target->GetQuestRewardStatus(qinfo->GetQuestId())) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); - else + case QUEST_STATUS_COMPLETE: statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + break; + case QUEST_STATUS_INCOMPLETE: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + break; + case QUEST_STATUS_REWARDED: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + break; + default: + break; } - else if (status == QUEST_STATUS_INCOMPLETE) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); } if (m_session) diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 23578a55816..e73480cb4de 100755 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -416,16 +416,27 @@ enum SummonPropFlags enum VehicleSeatFlags { + VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_ENTER = 0x00000001, + VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_RIDE = 0x00000002, + VEHICLE_SEAT_FLAG_SHOULD_USE_VEH_SEAT_EXIT_ANIM_ON_VOLUNTARY_EXIT = 0x00000008, VEHICLE_SEAT_FLAG_HIDE_PASSENGER = 0x00000200, // Passenger is hidden - VEHICLE_SEAT_FLAG_UNK1 = 0x00000400, // needed for CGCamera__SyncFreeLookFacing + VEHICLE_SEAT_FLAG_ALLOW_TURNING = 0x00000400, // needed for CGCamera__SyncFreeLookFacing VEHICLE_SEAT_FLAG_CAN_CONTROL = 0x00000800, // Lua_UnitInVehicleControlSeat VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL = 0x00001000, // Can cast spells with SPELL_AURA_MOUNTED from seat (possibly 4.x only, 0 seats on 3.3.5a) VEHICLE_SEAT_FLAG_UNCONTROLLED = 0x00002000, // can override !& VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT VEHICLE_SEAT_FLAG_CAN_ATTACK = 0x00004000, // Can attack, cast spells and use items from vehicle + VEHICLE_SEAT_FLAG_SHOULD_USE_VEH_SEAT_EXIT_ANIMN_ON_FORCED_EXIT = 0x00008000, + VEHICLE_SEAT_FLAG_HAS_VEH_EXIT_ANIM_VOLUNTARY_EXIT = 0x00040000, + VEHICLE_SEAT_FLAG_HAS_VEH_EXIT_ANIM_FORCED_EXIT = 0x00080000, + VEHICLE_SEAT_FLAG_REC_HAS_VEHICLE_ENTER_ANIM = 0x00400000, + VEHICLE_SEAT_FLAG_ENABLE_VEHICLE_ZOOM = 0x01000000, VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT = 0x02000000, // Lua_CanExitVehicle - can enter and exit at free will VEHICLE_SEAT_FLAG_CAN_SWITCH = 0x04000000, // Lua_CanSwitchVehicleSeats + VEHICLE_SEAT_FLAG_HAS_START_WARITING_FOR_VEH_TRANSITION_ANIM_ENTER = 0x08000000, + VEHICLE_SEAT_FLAG_HAS_START_WARITING_FOR_VEH_TRANSITION_ANIM_EXIT = 0x10000000, VEHICLE_SEAT_FLAG_CAN_CAST = 0x20000000, // Lua_UnitHasVehicleUI VEHICLE_SEAT_FLAG_UNK2 = 0x40000000, // checked in conjunction with 0x800 in CastSpell2 + VEHICLE_SEAT_FLAG_ALLOWS_INTERACTION = 0x80000000, }; enum VehicleSeatFlagsB @@ -437,6 +448,7 @@ enum VehicleSeatFlagsB VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 = 0x00000040, VEHICLE_SEAT_FLAG_B_USABLE_FORCED_3 = 0x00000100, VEHICLE_SEAT_FLAG_B_USABLE_FORCED_4 = 0x02000000, + VEHICLE_SEAT_FLAG_B_CAN_SWITCH = 0x04000000, VEHICLE_SEAT_FLAG_B_VEHICLE_PLAYERFRAME_UI = 0x80000000, // Lua_UnitHasVehiclePlayerFrameUI - actually checked for flagsb &~ 0x80000000 }; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 47c298d7467..a5ff89136b8 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -1417,6 +1417,10 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) waitTimesMap[(*it)->GetGUID()] = int32(joinTime - itQueue->second->joinTime); } + // Set the dungeon difficulty + LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(pProposal->dungeonId); + ASSERT(dungeon); + // Create a new group (if needed) LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_GROUP_FOUND); Group* grp = pProposal->groupLowGuid ? sGroupMgr->GetGroupByGUID(pProposal->groupLowGuid) : NULL; @@ -1427,6 +1431,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) Group* group = player->GetGroup(); if (sendUpdate) player->GetSession()->SendLfgUpdateProposal(proposalId, pProposal); + if (group) { player->GetSession()->SendLfgUpdateParty(updateData); @@ -1478,14 +1483,16 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) break; } } + m_teleport.push_back(pguid); grp->SetLfgRoles(pguid, pProposal->players[pguid]->role); SetState(pguid, LFG_STATE_DUNGEON); + + // Add the cooldown spell if queued for a random dungeon + if (dungeon->type == LFG_TYPE_RANDOM) + player->CastSpell(player, LFG_SPELL_DUNGEON_COOLDOWN, false); } - // Set the dungeon difficulty - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(pProposal->dungeonId); - ASSERT(dungeon); grp->SetDungeonDifficulty(Difficulty(dungeon->difficulty)); uint64 gguid = grp->GetGUID(); SetDungeon(gguid, dungeon->Entry()); @@ -1626,6 +1633,7 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string reas { if (!grp) return; + uint64 gguid = grp->GetGUID(); SetState(gguid, LFG_STATE_BOOT); @@ -1635,7 +1643,6 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string reas pBoot->reason = reason; pBoot->victim = victim; pBoot->votedNeeded = GetVotesNeeded(gguid); - PlayerSet players; // Set votes for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) @@ -1651,15 +1658,11 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string reas else { pBoot->votes[guid] = LFG_ANSWER_PENDING; // Other members need to vote - players.insert(plrg); + plrg->GetSession()->SendLfgBootPlayer(pBoot); } } } - // Notify players - for (PlayerSet::const_iterator it = players.begin(); it != players.end(); ++it) - (*it)->GetSession()->SendLfgBootPlayer(pBoot); - m_Boots[grp->GetLowGUID()] = pBoot; } @@ -1748,14 +1751,7 @@ void LFGMgr::UpdateBoot(Player* player, bool accept) void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false*/) { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::TeleportPlayer: [" UI64FMTD "] is being teleported %s", player->GetGUID(), out ? "out" : "in"); - if (out) - { - player->RemoveAurasDueToSpell(LFG_SPELL_LUCK_OF_THE_DRAW); - player->TeleportToBGEntryPoint(); - return; - } - // TODO Add support for LFG_TELEPORTERROR_FATIGUE LfgTeleportError error = LFG_TELEPORTERROR_OK; Group* grp = player->GetGroup(); @@ -1765,10 +1761,25 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* error = LFG_TELEPORTERROR_PLAYER_DEAD; else if (player->IsFalling() || player->HasUnitState(UNIT_STATE_JUMPING)) error = LFG_TELEPORTERROR_FALLING; + else if (player->IsMirrorTimerActive(FATIGUE_TIMER)) + error = LFG_TELEPORTERROR_FATIGUE; else { - uint64 gguid = grp->GetGUID(); - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(GetDungeon(gguid)); + LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(GetDungeon(grp->GetGUID())); + + if (out) + { + // Player needs to be inside the LFG dungeon to be able to teleport out + if (dungeon && player->GetMapId() == uint32(dungeon->map)) + { + player->RemoveAurasDueToSpell(LFG_SPELL_LUCK_OF_THE_DRAW); + player->TeleportToBGEntryPoint(); + } + else + player->GetSession()->SendLfgTeleportError(LFG_TELEPORTERROR_DONT_REPORT); // Not sure which error message to send + + return; + } if (!dungeon) error = LFG_TELEPORTERROR_INVALID_LOCATION; @@ -1817,7 +1828,7 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* if (error == LFG_TELEPORTERROR_OK) { - if (!player->GetMap()->IsDungeon() && !player->GetMap()->IsRaid()) + if (!player->GetMap()->IsDungeon()) player->SetBattlegroundEntryPoint(); if (player->isInFlight()) diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index d10902b9553..f21818deb64 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -68,6 +68,7 @@ enum LfgTeleportError LFG_TELEPORTERROR_OK = 0, // Internal use LFG_TELEPORTERROR_PLAYER_DEAD = 1, LFG_TELEPORTERROR_FALLING = 2, + LFG_TELEPORTERROR_DONT_REPORT = 3, LFG_TELEPORTERROR_FATIGUE = 4, LFG_TELEPORTERROR_INVALID_LOCATION = 6 }; diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 6175addfae2..1fa7fe0ca9f 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -117,13 +117,14 @@ void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod meth return; } + uint32 state = sLFGMgr->GetState(gguid); sLFGMgr->ClearState(guid); sLFGMgr->SetState(guid, LFG_STATE_NONE); if (Player* player = ObjectAccessor::FindPlayer(guid)) { + if (method == GROUP_REMOVEMETHOD_LEAVE && state != LFG_STATE_FINISHED_DUNGEON && player->HasAura(LFG_SPELL_DUNGEON_COOLDOWN)) + player->CastSpell(player, LFG_SPELL_DUNGEON_DESERTER, false); /* - if (method == GROUP_REMOVEMETHOD_LEAVE) - // Add deserter flag else if (group->isLfgKickActive()) // Update internal kick cooldown of kicked */ @@ -134,7 +135,7 @@ void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod meth sLFGMgr->TeleportPlayer(player, true); } - if (sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON)// Need more players to finish the dungeon + if (state != LFG_STATE_FINISHED_DUNGEON)// Need more players to finish the dungeon sLFGMgr->OfferContinue(group); } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index e8ec686daf5..07e8e37e82a 100755 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -486,7 +486,7 @@ void Creature::Update(uint32 diff) break; uint64 dbtableHighGuid = MAKE_NEW_GUID(m_DBTableGuid, GetEntry(), HIGHGUID_UNIT); - time_t linkedRespawntime = sObjectMgr->GetLinkedRespawnTime(dbtableHighGuid, GetMap()->GetInstanceId()); + time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid); if (!linkedRespawntime) // Can respawn Respawn(); else // the master is dead @@ -1303,7 +1303,7 @@ bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap) m_respawnDelay = data->spawntimesecs; m_deathState = ALIVE; - m_respawnTime = sObjectMgr->GetCreatureRespawnTime(m_DBTableGuid, GetInstanceId()); + m_respawnTime = GetMap()->GetCreatureRespawnTime(m_DBTableGuid); if (m_respawnTime) // respawn on Update { m_deathState = DEAD; @@ -1398,7 +1398,7 @@ void Creature::DeleteFromDB() return; } - sObjectMgr->RemoveCreatureRespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveCreatureRespawnTime(m_DBTableGuid); sObjectMgr->DeleteCreatureData(m_DBTableGuid); SQLTransaction trans = WorldDatabase.BeginTransaction(); @@ -1598,7 +1598,7 @@ void Creature::Respawn(bool force) if (getDeathState() == DEAD) { if (m_DBTableGuid) - sObjectMgr->RemoveCreatureRespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveCreatureRespawnTime(m_DBTableGuid); sLog->outStaticDebug("Respawning creature %s (GuidLow: %u, Full GUID: " UI64FMTD " Entry: %u)", GetName(), GetGUIDLow(), GetGUID(), GetEntry()); m_respawnTime = 0; @@ -2013,7 +2013,7 @@ void Creature::SaveRespawnTime() if (isSummon() || !m_DBTableGuid || (m_creatureData && !m_creatureData->dbData)) return; - sObjectMgr->SaveCreatureRespawnTime(m_DBTableGuid, GetInstanceId(), m_respawnTime); + GetMap()->SaveCreatureRespawnTime(m_DBTableGuid, m_respawnTime); } // this should not be called by petAI or diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index 829eb73bf80..537bbd9c099 100755 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -36,6 +36,7 @@ class TempSummon : public Creature Unit* GetSummoner() const; uint64 GetSummonerGUID() { return m_summonerGUID; } TempSummonType const& GetSummonType() { return m_type; } + uint32 GetTimer() { return m_timer; } const SummonPropertiesEntry* const m_Properties; private: diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 5101d01899d..1d9958a6524 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -338,7 +338,7 @@ void GameObject::Update(uint32 diff) if (m_respawnTime <= now) // timer expired { uint64 dbtableHighGuid = MAKE_NEW_GUID(m_DBTableGuid, GetEntry(), HIGHGUID_GAMEOBJECT); - time_t linkedRespawntime = sObjectMgr->GetLinkedRespawnTime(dbtableHighGuid, GetMap()->GetInstanceId()); + time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid); if (linkedRespawntime) // Can't respawn, the master is dead { uint64 targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid); @@ -761,13 +761,13 @@ bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap) else { m_respawnDelayTime = data->spawntimesecs; - m_respawnTime = sObjectMgr->GetGORespawnTime(m_DBTableGuid, map->GetInstanceId()); + m_respawnTime = GetMap()->GetGORespawnTime(m_DBTableGuid); // ready to respawn if (m_respawnTime && m_respawnTime <= time(NULL)) { m_respawnTime = 0; - sObjectMgr->RemoveGORespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveGORespawnTime(m_DBTableGuid); } } } @@ -788,7 +788,7 @@ bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap) void GameObject::DeleteFromDB() { - sObjectMgr->RemoveGORespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveGORespawnTime(m_DBTableGuid); sObjectMgr->DeleteGOData(m_DBTableGuid); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT); @@ -863,7 +863,7 @@ Unit* GameObject::GetOwner() const void GameObject::SaveRespawnTime() { if (m_goData && m_goData->dbData && m_respawnTime > time(NULL) && m_spawnedByDefault) - sObjectMgr->SaveGORespawnTime(m_DBTableGuid, GetInstanceId(), m_respawnTime); + GetMap()->SaveGORespawnTime(m_DBTableGuid, m_respawnTime); } bool GameObject::IsAlwaysVisibleFor(WorldObject const* seer) const @@ -908,7 +908,7 @@ void GameObject::Respawn() if (m_spawnedByDefault && m_respawnTime > 0) { m_respawnTime = time(NULL); - sObjectMgr->RemoveGORespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveGORespawnTime(m_DBTableGuid); } } @@ -1711,7 +1711,13 @@ bool GameObject::IsInRange(float x, float y, float z, float radius) const void GameObject::EventInform(uint32 eventId) { - if (eventId && m_zoneScript) + if (!eventId) + return; + + if (AI()) + AI()->EventInform(eventId); + + if (m_zoneScript) m_zoneScript->ProcessEvent(this, eventId); } diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 64b780bb6c3..5a6a5799fee 100755 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -34,11 +34,11 @@ #define CONTACT_DISTANCE 0.5f #define INTERACTION_DISTANCE 5.0f #define ATTACK_DISTANCE 5.0f -#define MAX_VISIBILITY_DISTANCE 500.0f // max distance for visible objects +#define MAX_VISIBILITY_DISTANCE SIZE_OF_GRIDS // max distance for visible objects #define SIGHT_RANGE_UNIT 50.0f -#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents -#define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards -#define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards +#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents +#define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards +#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards #define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects #define DEFAULT_COMBAT_REACH 1.5f diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 1b1a6c0f62d..3475817816d 100755 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -164,6 +164,7 @@ class Pet : public Guardian bool HaveInDiet(ItemTemplate const* item) const; uint32 GetCurrentFoodBenefitLevel(uint32 itemlevel); void SetDuration(int32 dur) { m_duration = dur; } + int32 GetDuration() { return m_duration; } /* bool UpdateStats(Stats stat); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4cf6d4ad979..42d342cbcf9 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3322,7 +3322,7 @@ void Player::SendInitialSpells() uint16 spellCooldowns = m_spellCooldowns.size(); data << uint16(spellCooldowns); - for (SpellCooldowns::const_iterator itr=m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr) + for (SpellCooldowns::const_iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr) { SpellInfo const* sEntry = sSpellMgr->GetSpellInfo(itr->first); if (!sEntry) @@ -9103,7 +9103,6 @@ void Player::SendLoot(uint64 guid, LootType loot_type) loot->loot_type = loot_type; WorldPacket data(SMSG_LOOT_RESPONSE, (9+50)); // we guess size - data << uint64(guid); data << uint8(loot_type); data << LootView(*loot, this, permission); @@ -13555,9 +13554,9 @@ void Player::SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2, uint } case EQUIP_ERR_EVENT_AUTOEQUIP_BIND_CONFIRM: // no idea about this one... { - data << uint64(0); - data << uint32(0); - data << uint64(0); + data << uint64(0); // item guid + data << uint32(0); // slot + data << uint64(0); // container break; } case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED: @@ -14242,7 +14241,7 @@ void Player::SendNewItem(Item* item, uint32 count, bool received, bool created, data << uint64(GetGUID()); // player GUID data << uint32(received); // 0=looted, 1=from npc data << uint32(created); // 0=received, 1=created - data << uint32(1); // always 0x01 (probably meant to be count of listed items) + data << uint32(1); // bool print error to chat data << uint8(item->GetBagSlot()); // bagslot // item slot, but when added to stack: 0xFFFFFFFF data << uint32((item->GetCount() == count) ? item->GetSlot() : -1); @@ -20121,8 +20120,10 @@ void Player::PetSpellInitialize() WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1); data << uint64(pet->GetGUID()); data << uint16(pet->GetCreatureTemplate()->family); // creature family (required for pet talents) - data << uint32(0); - data << uint8(pet->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); + data << uint32(pet->GetDuration()); + data << uint8(pet->GetReactState()); + data << uint8(charmInfo->GetCommandState()); + data << uint16(0); // Flags, mostly unknown // action bar loop charmInfo->BuildActionBar(&data); @@ -20155,22 +20156,33 @@ void Player::PetSpellInitialize() for (CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr) { - time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0; - - data << uint32(itr->first); // spellid - data << uint16(0); // spell category? - data << uint32(cooldown); // cooldown - data << uint32(0); // category cooldown - } + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); + if (!spellInfo) + { + data << uint32(0); + data << uint16(0); + data << uint32(0); + data << uint32(0); + continue; + } - for (CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureCategoryCooldowns.begin(); itr != pet->m_CreatureCategoryCooldowns.end(); ++itr) - { time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0; + data << uint32(itr->first); // spell ID - data << uint32(itr->first); // spellid - data << uint16(0); // spell category? - data << uint32(0); // cooldown - data << uint32(cooldown); // category cooldown + CreatureSpellCooldowns::const_iterator categoryitr = pet->m_CreatureCategoryCooldowns.find(spellInfo->Category); + if (categoryitr != pet->m_CreatureCategoryCooldowns.end()) + { + time_t categoryCooldown = (categoryitr->second > curTime) ? (categoryitr->second - curTime) * IN_MILLISECONDS : 0; + data << uint16(spellInfo->Category); // spell category + data << uint32(cooldown); // spell cooldown + data << uint32(categoryCooldown); // category cooldown + } + else + { + data << uint16(0); + data << uint32(cooldown); + data << uint32(0); + } } GetSession()->SendPacket(&data); @@ -20206,24 +20218,24 @@ void Player::PossessSpellInitialize() void Player::VehicleSpellInitialize() { - Creature* veh = GetVehicleCreatureBase(); - if (!veh) + Creature* vehicle = GetVehicleCreatureBase(); + if (!vehicle) return; - uint8 cooldownCount = veh->m_CreatureSpellCooldowns.size() + veh->m_CreatureCategoryCooldowns.size(); + uint8 cooldownCount = vehicle->m_CreatureSpellCooldowns.size(); WorldPacket data(SMSG_PET_SPELLS, 8 + 2 + 4 + 4 + 4 * 10 + 1 + 1 + cooldownCount * (4 + 2 + 4 + 4)); - data << uint64(veh->GetGUID()); - data << uint16(veh->GetCreatureTemplate()->family); - data << uint32(0); - // The following three segments are read as one uint32 - data << uint8(veh->GetReactState()); - data << uint8(0); // CommandState? - data << uint16(0); // unk + data << uint64(vehicle->GetGUID()); // Guid + data << uint16(0); // Pet Family (0 for all vehicles) + data << uint32(vehicle->isSummon() ? vehicle->ToTempSummon()->GetTimer() : 0); // Duration + // The following three segments are read by the client as one uint32 + data << uint8(vehicle->GetReactState()); // React State + data << uint8(0); // Command State + data << uint16(0x800); // DisableActions (set for all vehicles) for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) { - uint32 spellId = veh->m_spells[i]; + uint32 spellId = vehicle->m_spells[i]; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) { @@ -20231,54 +20243,59 @@ void Player::VehicleSpellInitialize() continue; } - ConditionList conditions = sConditionMgr->GetConditionsForVehicleSpell(veh->GetEntry(), spellId); - if (!sConditionMgr->IsObjectMeetToConditions(this, veh, conditions)) + ConditionList conditions = sConditionMgr->GetConditionsForVehicleSpell(vehicle->GetEntry(), spellId); + if (!sConditionMgr->IsObjectMeetToConditions(this, vehicle, conditions)) { - sLog->outDebug(LOG_FILTER_CONDITIONSYS, "VehicleSpellInitialize: conditions not met for Vehicle entry %u spell %u", veh->ToCreature()->GetEntry(), spellId); + sLog->outDebug(LOG_FILTER_CONDITIONSYS, "VehicleSpellInitialize: conditions not met for Vehicle entry %u spell %u", vehicle->ToCreature()->GetEntry(), spellId); data << uint16(0) << uint8(0) << uint8(i+8); continue; } if (spellInfo->IsPassive()) - { - veh->CastSpell(veh, spellId, true); - data << uint16(0) << uint8(0) << uint8(i+8); - } - else - data << uint32(MAKE_UNIT_ACTION_BUTTON(spellId, i+8)); + vehicle->CastSpell(vehicle, spellId, true); + + data << uint32(MAKE_UNIT_ACTION_BUTTON(spellId, i+8)); } for (uint32 i = CREATURE_MAX_SPELLS; i < MAX_SPELL_CONTROL_BAR; ++i) - data << uint16(0) << uint8(0) << uint8(i+8); + data << uint32(0); - data << uint8(0); - /*if (v23 > 0) - { - for (uint32 i = 0; i < v23; ++i) - data << uint32(v16); // Some spellid? - }*/ + data << uint8(0); // Auras? // Cooldowns - data << cooldownCount; + data << uint8(cooldownCount); time_t now = sWorld->GetGameTime(); - CreatureSpellCooldowns::const_iterator itr; - for (itr = veh->m_CreatureSpellCooldowns.begin(); itr != veh->m_CreatureSpellCooldowns.end(); ++itr) - { - time_t cooldown = (itr->second > now) ? (itr->second - now) * IN_MILLISECONDS : 0; - data << uint32(itr->first); // SpellId - data << uint16(0); // unk - data << uint32(cooldown); // spell cooldown - data << uint32(0); // category cooldown - } - for (itr = veh->m_CreatureCategoryCooldowns.begin(); itr != veh->m_CreatureCategoryCooldowns.end(); ++itr) + for (CreatureSpellCooldowns::const_iterator itr = vehicle->m_CreatureSpellCooldowns.begin(); itr != vehicle->m_CreatureSpellCooldowns.end(); ++itr) { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); + if (!spellInfo) + { + data << uint32(0); + data << uint16(0); + data << uint32(0); + data << uint32(0); + continue; + } + time_t cooldown = (itr->second > now) ? (itr->second - now) * IN_MILLISECONDS : 0; - data << uint32(itr->first); // SpellId - data << uint16(0); // unk - data << uint32(0); // spell cooldown - data << uint32(cooldown); // category cooldown + data << uint32(itr->first); // spell ID + + CreatureSpellCooldowns::const_iterator categoryitr = vehicle->m_CreatureCategoryCooldowns.find(spellInfo->Category); + if (categoryitr != vehicle->m_CreatureCategoryCooldowns.end()) + { + time_t categoryCooldown = (categoryitr->second > now) ? (categoryitr->second - now) * IN_MILLISECONDS : 0; + data << uint16(spellInfo->Category); // spell category + data << uint32(cooldown); // spell cooldown + data << uint32(categoryCooldown); // category cooldown + } + else + { + data << uint16(0); + data << uint32(cooldown); + data << uint32(0); + } } GetSession()->SendPacket(&data); @@ -20317,7 +20334,7 @@ void Player::CharmSpellInitialize() if (charm->GetTypeId() != TYPEID_PLAYER) data << uint8(charm->ToCreature()->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); else - data << uint8(0) << uint8(0) << uint16(0); + data << uint32(0); charmInfo->BuildActionBar(&data); @@ -22299,8 +22316,8 @@ void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint3 data << uint32(time); if (type == RAID_INSTANCE_WELCOME) { - data << uint8(0); // is your (1) - data << uint8(0); // is extended (1), ignored if prev field is 0 + data << uint8(0); // is locked + data << uint8(0); // is extended, ignored if prev field is 0 } GetSession()->SendPacket(&data); } @@ -23345,7 +23362,7 @@ Player* Player::GetNextRandomRaidMember(float radius) PartyResult Player::CanUninviteFromGroup() const { - const Group* grp = GetGroup(); + Group const* grp = GetGroup(); if (!grp) return ERR_NOT_IN_GROUP; @@ -23368,8 +23385,12 @@ PartyResult Player::CanUninviteFromGroup() const if (grp->isRollLootActive()) return ERR_PARTY_LFG_BOOT_LOOT_ROLLS; + // TODO: Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer. + for (GroupReference const* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + if (itr->getSource() && itr->getSource()->isInCombat()) + return ERR_PARTY_LFG_BOOT_IN_COMBAT; + /* Missing support for these types - return ERR_PARTY_LFG_BOOT_IN_COMBAT; // also have a cooldown (some secs after combat finish return ERR_PARTY_LFG_BOOT_COOLDOWN_S; return ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S; */ diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index ed887994bca..b0cbb5c7927 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1970,6 +1970,7 @@ class Player : public Unit, public GridObject<Player> StopMirrorTimer(BREATH_TIMER); StopMirrorTimer(FIRE_TIMER); } + bool IsMirrorTimerActive(MirrorTimerType type) { return m_MirrorTimer[type] == getMaxTimer(type); } void SetMovement(PlayerMovementType pType); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index c90b86f2349..daa8c1e05de 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -424,50 +424,6 @@ void Unit::DisableSpline() movespline->_Interrupt(); } -void Unit::SendMonsterMoveExitVehicle(Position const* newPos) -{ - WorldPacket data(SMSG_MONSTER_MOVE, 1+12+4+1+4+4+4+12+GetPackGUID().size()); - data.append(GetPackGUID()); - - data << uint8(GetTypeId() == TYPEID_PLAYER ? 1 : 0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40) - data << GetPositionX() << GetPositionY() << GetPositionZ(); - data << getMSTime(); - - data << uint8(SPLINETYPE_FACING_ANGLE); - data << float(GetOrientation()); // guess - data << uint32(SPLINEFLAG_EXIT_VEHICLE); - data << uint32(0); // Time in between points - data << uint32(1); // 1 single waypoint - data << newPos->GetPositionX(); - data << newPos->GetPositionY(); - data << newPos->GetPositionZ(); - - SendMessageToSet(&data, true); -} - -void Unit::SendMonsterMoveTransport(Unit* vehicleOwner) -{ - // TODO: Turn into BuildMonsterMoveTransport packet and allow certain variables (for npc movement aboard vehicles) - WorldPacket data(SMSG_MONSTER_MOVE_TRANSPORT, GetPackGUID().size()+vehicleOwner->GetPackGUID().size() + 47); - data.append(GetPackGUID()); - data.append(vehicleOwner->GetPackGUID()); - data << int8(GetTransSeat()); - data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40) - data << GetPositionX() - vehicleOwner->GetPositionX(); - data << GetPositionY() - vehicleOwner->GetPositionY(); - data << GetPositionZ() - vehicleOwner->GetPositionZ(); - data << uint32(getMSTime()); // should be an increasing constant that indicates movement packet count - data << uint8(SPLINETYPE_FACING_ANGLE); - data << GetTransOffsetO(); // facing angle? - data << uint32(SPLINEFLAG_TRANSPORT); - data << uint32(GetTransTime()); // move time - data << uint32(1); // amount of waypoints - data << uint32(0); // waypoint X - data << uint32(0); // waypoint Y - data << uint32(0); // waypoint Z - SendMessageToSet(&data, true); -} - void Unit::resetAttackTimer(WeaponAttackType type) { m_attackTimer[type] = uint32(GetAttackTime(type) * m_modAttackSpeedPct[type]); @@ -2509,12 +2465,12 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) // Chance resist debuff if (!spell->IsPositive()) { - bool bNegativeAura = false; + bool bNegativeAura = true; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (spell->Effects[i].ApplyAuraName != 0) + if (spell->Effects[i].ApplyAuraName == 0) { - bNegativeAura = true; + bNegativeAura = false; break; } } @@ -2937,9 +2893,11 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell) InterruptSpell(CURRENT_AUTOREPEAT_SPELL); m_AutoRepeatFirstCast = true; } - AddUnitState(UNIT_STATE_CASTING); - } break; + if (pSpell->m_spellInfo->CalcCastTime(this) > 0) + AddUnitState(UNIT_STATE_CASTING); + break; + } case CURRENT_CHANNELED_SPELL: { // channel spells always break generic non-delayed and any channeled spells @@ -2951,8 +2909,9 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell) m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != 75) InterruptSpell(CURRENT_AUTOREPEAT_SPELL); AddUnitState(UNIT_STATE_CASTING); - } break; + break; + } case CURRENT_AUTOREPEAT_SPELL: { // only Auto Shoot does not break anything @@ -2964,12 +2923,11 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell) } // special action: set first cast flag m_AutoRepeatFirstCast = true; - } break; + break; + } default: - { - // other spell types don't break anything now - } break; + break; // other spell types don't break anything now } // current spell (if it is still here) may be safely deleted now @@ -14567,6 +14525,11 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u if (procSpell && (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check takeCharges = true; break; + case SPELL_AURA_SPELL_MAGNET: + // Skip Melee hits and targets with magnet aura + if (procSpell && (triggeredByAura->GetBase()->GetUnitOwner()->ToUnit() == ToUnit())) // Magnet + takeCharges = true; + break; case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT: case SPELL_AURA_MOD_POWER_COST_SCHOOL: // Skip melee hits and spells ws wrong school or zero cost @@ -16308,7 +16271,7 @@ Creature* Unit::GetVehicleCreatureBase() const uint64 Unit::GetTransGUID() const { if (GetVehicle()) - return GetVehicle()->GetBase()->GetGUID(); + return GetVehicleBase()->GetGUID(); if (GetTransport()) return GetTransport()->GetGUID(); @@ -17171,11 +17134,12 @@ void Unit::_ExitVehicle(Position const* exitPosition) Vehicle* vehicle = m_vehicle; m_vehicle = NULL; - SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT + SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT Position pos; - if (!exitPosition) // Exit position not specified - vehicle->GetBase()->GetPosition(&pos); + if (!exitPosition) // Exit position not specified + vehicle->GetBase()->GetPosition(&pos); // This should use passenger's current position, leaving it as it is now + // because we calculate positions incorrect (sometimes under map) else pos = *exitPosition; @@ -17190,14 +17154,17 @@ void Unit::_ExitVehicle(Position const* exitPosition) SendMessageToSet(&data, false); } - SendMonsterMoveExitVehicle(&pos); - Relocate(&pos); + Movement::MoveSplineInit init(*this); + init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); + init.SetFacing(GetOrientation()); + init.SetTransportExit(); + init.Launch(); + + //GetMotionMaster()->MoveFall(); // Enable this once passenger positions are calculater properly (see above) if (Player* player = ToPlayer()) player->ResummonPetTemporaryUnSummonedIfAny(); - SendMovementFlagUpdate(); - if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION)) if (((Minion*)vehicle->GetBase())->GetOwner() == this) vehicle->Dismiss(); @@ -17593,6 +17560,7 @@ void Unit::SetInFront(Unit const* target) void Unit::SetFacingTo(float ori) { Movement::MoveSplineInit init(*this); + init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); init.SetFacing(ori); init.Launch(); } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index f246f595dec..9b63de0cdb8 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -735,19 +735,6 @@ enum MovementFlags2 MOVEMENTFLAG2_UNK16 = 0x00008000, }; -enum SplineFlags -{ - SPLINEFLAG_WALKMODE = 0x00001000, - SPLINEFLAG_FLYING = 0x00002000, - SPLINEFLAG_TRANSPORT = 0x00800000, - SPLINEFLAG_EXIT_VEHICLE = 0x01000000, -}; - -enum SplineType -{ - SPLINETYPE_FACING_ANGLE = 4, -}; - enum UnitTypeMask { UNIT_MASK_NONE = 0x00000000, @@ -1629,9 +1616,7 @@ class Unit : public WorldObject void MonsterMoveWithSpeed(float x, float y, float z, float speed); //void SetFacing(float ori, WorldObject* obj = NULL); - void SendMonsterMoveExitVehicle(Position const* newPos); //void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); - void SendMonsterMoveTransport(Unit* vehicleOwner); void SendMovementFlagUpdate(); /*! These methods send the same packet to the client in apply and unapply case. diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index c297ce1e792..710821f2f24 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -28,6 +28,7 @@ #include "ZoneScript.h" #include "SpellMgr.h" #include "SpellInfo.h" +#include "MoveSplineInit.h" Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) : _me(unit), _vehicleInfo(vehInfo), _usableSeatNum(0), _creatureEntry(creatureEntry) { @@ -338,7 +339,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) } } - if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_UNK1)) + if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)) unit->AddUnitState(UNIT_STATE_ONVEHICLE); unit->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); @@ -364,7 +365,12 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) unit->SendClearTarget(); // SMSG_BREAK_TARGET unit->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) // also adds MOVEMENTFLAG_ROOT - unit->SendMonsterMoveTransport(_me); // SMSG_MONSTER_MOVE_TRANSPORT + Movement::MoveSplineInit init(*unit); + init.DisableTransportPathTransformations(); + init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); + init.SetFacing(0.0f); + init.SetTransportEnter(); + init.Launch(); if (_me->GetTypeId() == TYPEID_UNIT) { @@ -372,7 +378,8 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) _me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, true); // update all passenger's positions - RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation()); + //Passenger's spline OR vehicle movement will update positions + //RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation()); } } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index df6018faf39..65f2ccff476 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1872,71 +1872,6 @@ void ObjectMgr::RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data } } -void ObjectMgr::LoadCreatureRespawnTimes() -{ - uint32 oldMSTime = getMSTime(); - - uint32 count = 0; - - PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CREATURE_RESPAWNS)); - if (!result) - { - sLog->outString(">> Loaded 0 creature respawn time."); - sLog->outString(); - return; - } - - do - { - Field* fields = result->Fetch(); - - uint32 loguid = fields[0].GetUInt32(); - uint32 respawn_time = fields[1].GetUInt32(); - uint32 instance = fields[2].GetUInt32(); - - _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = time_t(respawn_time); - - ++count; - } while (result->NextRow()); - - sLog->outString(">> Loaded %lu creature respawn times in %u ms", (unsigned long)_creatureRespawnTimes.size(), GetMSTimeDiffToNow(oldMSTime)); - sLog->outString(); -} - -void ObjectMgr::LoadGameobjectRespawnTimes() -{ - uint32 oldMSTime = getMSTime(); - - // Remove outdated data - CharacterDatabase.DirectExecute("DELETE FROM gameobject_respawn WHERE respawnTime <= UNIX_TIMESTAMP(NOW())"); - - uint32 count = 0; - - PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_GO_RESPAWNS)); - if (!result) - { - sLog->outString(">> Loaded 0 gameobject respawn times. DB table `gameobject_respawn` is empty!"); - sLog->outString(); - return; - } - - do - { - Field* fields = result->Fetch(); - - uint32 loguid = fields[0].GetUInt32(); - uint32 respawn_time = fields[1].GetUInt32(); - uint32 instance = fields[2].GetUInt32(); - - _goRespawnTimes[MAKE_PAIR64(loguid, instance)] = time_t(respawn_time); - - ++count; - } while (result->NextRow()); - - sLog->outString(); - sLog->outString(">> Loaded %lu gameobject respawn times in %u ms", (unsigned long)_goRespawnTimes.size(), GetMSTimeDiffToNow(oldMSTime)); -} - Player* ObjectMgr::GetPlayerByLowGUID(uint32 lowguid) const { uint64 guid = MAKE_NEW_GUID(lowguid, 0, HIGHGUID_PLAYER); @@ -7172,44 +7107,6 @@ void ObjectMgr::LoadNPCSpellClickSpells() sLog->outString(); } -void ObjectMgr::SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t) -{ - if (!t) - { - // Delete only - RemoveCreatureRespawnTime(loguid, instance); - return; - } - - // This function can be called from various map threads concurrently - { - _creatureRespawnTimesMutex.acquire(); - _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = t; - _creatureRespawnTimesMutex.release(); - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CREATURE_RESPAWN); - stmt->setUInt32(0, loguid); - stmt->setUInt32(1, uint32(t)); - stmt->setUInt32(2, instance); - CharacterDatabase.Execute(stmt); -} - -void ObjectMgr::RemoveCreatureRespawnTime(uint32 loguid, uint32 instance) -{ - // This function can be called from various map threads concurrently - { - _creatureRespawnTimesMutex.acquire(); - _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = 0; - _creatureRespawnTimesMutex.release(); - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN); - stmt->setUInt32(0, loguid); - stmt->setUInt32(1, instance); - CharacterDatabase.Execute(stmt); -} - void ObjectMgr::DeleteCreatureData(uint32 guid) { // remove mapid*cellid -> guid_set map @@ -7220,81 +7117,6 @@ void ObjectMgr::DeleteCreatureData(uint32 guid) _creatureDataStore.erase(guid); } -void ObjectMgr::SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t) -{ - if (!t) - { - // Delete only - RemoveGORespawnTime(loguid, instance); - return; - } - - // This function can be called from different map threads concurrently - { - _goRespawnTimesMutex.acquire(); - _goRespawnTimes[MAKE_PAIR64(loguid, instance)] = t; - _goRespawnTimesMutex.release(); - } - - PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GO_RESPAWN); - stmt->setUInt32(0, loguid); - stmt->setUInt64(1, uint64(t)); - stmt->setUInt32(2, instance); - CharacterDatabase.Execute(stmt); -} - -void ObjectMgr::RemoveGORespawnTime(uint32 loguid, uint32 instance) -{ - // This function can be called from different map threads concurrently - { - _goRespawnTimesMutex.acquire(); - _goRespawnTimes[MAKE_PAIR64(loguid, instance)] = 0; - _goRespawnTimesMutex.release(); - } - - PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN); - stmt->setUInt32(0, loguid); - stmt->setUInt32(1, instance); - CharacterDatabase.Execute(stmt); -} - -void ObjectMgr::DeleteRespawnTimeForInstance(uint32 instance) -{ - // This function can be called from different map threads concurrently - RespawnTimes::iterator next; - - { - _goRespawnTimesMutex.acquire(); - for (RespawnTimes::iterator itr = _goRespawnTimes.begin(); itr != _goRespawnTimes.end(); itr = next) - { - next = itr; - ++next; - - if (GUID_HIPART(itr->first) == instance) - _goRespawnTimes.erase(itr); - } - _goRespawnTimesMutex.release(); - } - { - _creatureRespawnTimesMutex.acquire(); - for (RespawnTimes::iterator itr = _creatureRespawnTimes.begin(); itr != _creatureRespawnTimes.end(); itr = next) - { - next = itr; - ++next; - - if (GUID_HIPART(itr->first) == instance) - _creatureRespawnTimes.erase(itr); - } - _creatureRespawnTimesMutex.release(); - } - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE); - stmt->setUInt32(0, instance); - CharacterDatabase.Execute(stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN_BY_INSTANCE); - stmt->setUInt32(0, instance); - CharacterDatabase.Execute(stmt); -} - void ObjectMgr::DeleteGOData(uint32 guid) { // remove mapid*cellid -> guid_set map diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index f81e7f1f074..97c2f0234ba 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -367,8 +367,6 @@ struct CellObjectGuids typedef UNORDERED_MAP<uint32/*cell_id*/, CellObjectGuids> CellObjectGuidsMap; typedef UNORDERED_MAP<uint32/*(mapid, spawnMode) pair*/, CellObjectGuidsMap> MapObjectGuids; -typedef UNORDERED_MAP<uint64/*(instance, guid) pair*/, time_t> RespawnTimes; - // Trinity string ranges #define MIN_TRINITY_STRING_ID 1 // 'trinity_string' #define MAX_TRINITY_STRING_ID 2000000000 @@ -854,13 +852,11 @@ class ObjectMgr void LoadCreatures(); void LoadLinkedRespawn(); bool SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid); - void LoadCreatureRespawnTimes(); void LoadCreatureAddons(); void LoadCreatureModelInfo(); void LoadEquipmentTemplates(); void LoadGameObjectLocales(); void LoadGameobjects(); - void LoadGameobjectRespawnTimes(); void LoadItemTemplates(); void LoadItemLocales(); void LoadItemSetNames(); @@ -1048,36 +1044,6 @@ class ObjectMgr void AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance); void DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid); - time_t GetLinkedRespawnTime(uint64 guid, uint32 instance) - { - uint64 linkedGuid = GetLinkedRespawnGuid(guid); - switch (GUID_HIPART(linkedGuid)) - { - case HIGHGUID_UNIT: - return GetCreatureRespawnTime(GUID_LOPART(linkedGuid), instance); - case HIGHGUID_GAMEOBJECT: - return GetGORespawnTime(GUID_LOPART(linkedGuid), instance); - default: - return 0; - } - } - - time_t GetCreatureRespawnTime(uint32 loguid, uint32 instance) - { - TRINITY_GUARD(ACE_Thread_Mutex, _creatureRespawnTimesMutex); - return _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)]; - } - void SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t); - void RemoveCreatureRespawnTime(uint32 loguid, uint32 instance); - time_t GetGORespawnTime(uint32 loguid, uint32 instance) - { - TRINITY_GUARD(ACE_Thread_Mutex, _goRespawnTimesMutex); - return _goRespawnTimes[MAKE_PAIR64(loguid, instance)]; - } - void SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t); - void RemoveGORespawnTime(uint32 loguid, uint32 instance); - void DeleteRespawnTimeForInstance(uint32 instance); - // grid objects void AddCreatureToGrid(uint32 guid, CreatureData const* data); void RemoveCreatureFromGrid(uint32 guid, CreatureData const* data); @@ -1307,10 +1273,6 @@ class ObjectMgr TrinityStringLocaleContainer _trinityStringLocaleStore; GossipMenuItemsLocaleContainer _gossipMenuItemsLocaleStore; PointOfInterestLocaleContainer _pointOfInterestLocaleStore; - RespawnTimes _creatureRespawnTimes; - ACE_Thread_Mutex _creatureRespawnTimesMutex; - RespawnTimes _goRespawnTimes; - ACE_Thread_Mutex _goRespawnTimesMutex; CacheVendorItemContainer _cacheVendorItemStore; CacheTrainerSpellContainer _cacheTrainerSpellStore; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index c7648bf1ccc..3a6390cd83a 100755 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -525,7 +525,7 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV roll->playerVote.erase(itr2); - CountRollVote(guid, roll->itemGUID, GetMembersCount()-1, MAX_ROLL_TYPE); + CountRollVote(guid, roll->itemGUID, MAX_ROLL_TYPE); } // Update subgroups @@ -732,7 +732,7 @@ void Group::SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r) WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4+4+1)); data << uint64(r.itemGUID); // guid of rolled item data << uint32(mapid); // 3.3.3 mapid - data << uint32(r.totalPlayersRolling); // maybe the number of players rolling for it??? + data << uint32(r.itemSlot); // itemslot data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for data << uint32(r.itemRandomSuffix); // randomSuffix data << uint32(r.itemRandomPropId); // item random property ID @@ -759,7 +759,7 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, WorldPacket data(SMSG_LOOT_START_ROLL, (8 + 4 + 4 + 4 + 4 + 4 + 4 + 1)); data << uint64(r.itemGUID); // guid of rolled item data << uint32(mapId); // 3.3.3 mapid - data << uint32(r.totalPlayersRolling); // maybe the number of players rolling for it??? + data << uint32(r.itemSlot); // itemslot data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for data << uint32(r.itemRandomSuffix); // randomSuffix data << uint32(r.itemRandomPropId); // item random property ID @@ -773,20 +773,20 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, p->GetSession()->SendPacket(&data); } -void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +void Group::SendLootRoll(uint64 sourceGuid, uint64 targetGuid, uint8 rollNumber, uint8 rollType, Roll const& roll) { WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1+1)); - data << uint64(SourceGuid); // guid of the item rolled - data << uint32(0); // unknown, maybe amount of players - data << uint64(TargetGuid); - data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for - data << uint32(r.itemRandomSuffix); // randomSuffix - data << uint32(r.itemRandomPropId); // Item random property ID - data << uint8(RollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number - data << uint8(RollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll - data << uint8(0); // auto pass on NeedBeforeGreed loot because player cannot use the object + data << uint64(sourceGuid); // guid of the item rolled + data << uint32(roll.itemSlot); // slot + data << uint64(targetGuid); + data << uint32(roll.itemid); // the itemEntryId for the item that shall be rolled for + data << uint32(roll.itemRandomSuffix); // randomSuffix + data << uint32(roll.itemRandomPropId); // Item random property ID + data << uint8(rollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number + data << uint8(rollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll + data << uint8(0); // 1: "You automatically passed on: %s because you cannot loot that item." - Possibly used in need befor greed - for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr != r.playerVote.end(); ++itr) + for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr) { Player* p = ObjectAccessor::FindPlayer(itr->first); if (!p || !p->GetSession()) @@ -797,19 +797,19 @@ void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, } } -void Group::SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +void Group::SendLootRollWon(uint64 sourceGuid, uint64 targetGuid, uint8 rollNumber, uint8 rollType, Roll const& roll) { WorldPacket data(SMSG_LOOT_ROLL_WON, (8+4+4+4+4+8+1+1)); - data << uint64(SourceGuid); // guid of the item rolled - data << uint32(0); // unknown, maybe amount of players - data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for - data << uint32(r.itemRandomSuffix); // randomSuffix - data << uint32(r.itemRandomPropId); // Item random property - data << uint64(TargetGuid); // guid of the player who won. - data << uint8(RollNumber); // rollnumber realted to SMSG_LOOT_ROLL - data << uint8(RollType); // Rolltype related to SMSG_LOOT_ROLL + data << uint64(sourceGuid); // guid of the item rolled + data << uint32(roll.itemSlot); // slot + data << uint32(roll.itemid); // the itemEntryId for the item that shall be rolled for + data << uint32(roll.itemRandomSuffix); // randomSuffix + data << uint32(roll.itemRandomPropId); // Item random property + data << uint64(targetGuid); // guid of the player who won. + data << uint8(rollNumber); // rollnumber realted to SMSG_LOOT_ROLL + data << uint8(rollType); // rollType related to SMSG_LOOT_ROLL - for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr != r.playerVote.end(); ++itr) + for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr) { Player* p = ObjectAccessor::FindPlayer(itr->first); if (!p || !p->GetSession()) @@ -820,11 +820,11 @@ void Group::SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumb } } -void Group::SendLootAllPassed(uint32 numberOfPlayers, Roll const& roll) +void Group::SendLootAllPassed(Roll const& roll) { WorldPacket data(SMSG_LOOT_ALL_PASSED, (8+4+4+4+4)); data << uint64(roll.itemGUID); // Guid of the item rolled - data << uint32(numberOfPlayers); // The number of players rolling for it + data << uint32(roll.itemSlot); // Item loot slot data << uint32(roll.itemid); // The itemEntryId for the item that shall be rolled for data << uint32(roll.itemRandomPropId); // Item random property ID data << uint32(roll.itemRandomSuffix); // Item random suffix ID @@ -1067,7 +1067,7 @@ void Group::MasterLoot(Loot* /*loot*/, WorldObject* pLootedObject) } } -void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choice) +void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint8 Choice) { Rolls::iterator rollI = GetRoll(Guid); if (rollI == RollId.end()) @@ -1108,7 +1108,7 @@ void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers } if (roll->totalPass + roll->totalNeed + roll->totalGreed >= roll->totalPlayersRolling) - CountTheRoll(rollI, NumberOfPlayers); + CountTheRoll(rollI); } //called when roll timer expires @@ -1117,7 +1117,7 @@ void Group::EndRoll(Loot* pLoot) for (Rolls::iterator itr = RollId.begin(); itr != RollId.end();) { if ((*itr)->getLoot() == pLoot) { - CountTheRoll(itr, GetMembersCount()); //i don't have to edit player votes, who didn't vote ... he will pass + CountTheRoll(itr); //i don't have to edit player votes, who didn't vote ... he will pass itr = RollId.begin(); } else @@ -1125,7 +1125,7 @@ void Group::EndRoll(Loot* pLoot) } } -void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers) +void Group::CountTheRoll(Rolls::iterator rollI) { Roll* roll = *rollI; if (!roll->isValid()) // is loot already deleted ? @@ -1248,7 +1248,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers) } else { - SendLootAllPassed(NumberOfPlayers, *roll); + SendLootAllPassed(*roll); // remove is_blocked so that the item is lootable by all players LootItem* item = &(roll->getLoot()->items[roll->itemSlot]); @@ -2076,20 +2076,6 @@ bool Group::HasFreeSlotSubGroup(uint8 subgroup) const return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAXGROUPSIZE); } -Group::MemberSlotList const& Group::GetMemberSlots() const -{ - return m_memberSlots; -} - -GroupReference* Group::GetFirstMember() -{ - return m_memberMgr.getFirst(); -} - -uint32 Group::GetMembersCount() const -{ - return m_memberSlots.size(); -} uint8 Group::GetMemberGroup(uint64 guid) const { diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 03f946cd3b6..e5f174c4230 100755 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -230,9 +230,11 @@ class Group bool SameSubGroup(Player const* member1, Player const* member2) const; bool HasFreeSlotSubGroup(uint8 subgroup) const; - MemberSlotList const& GetMemberSlots() const; - GroupReference* GetFirstMember(); - uint32 GetMembersCount() const; + MemberSlotList const& GetMemberSlots() const { return m_memberSlots; } + GroupReference* GetFirstMember() { return m_memberMgr.getFirst(); } + GroupReference const* GetFirstMember() const { return m_memberMgr.getFirst(); } + uint32 GetMembersCount() const { return m_memberSlots.size(); } + uint8 GetMemberGroup(uint64 guid) const; void ConvertToLFG(); @@ -276,14 +278,14 @@ class Group void SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, bool canNeed, Roll const& r); void SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); void SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); - void SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r); + void SendLootAllPassed(Roll const& roll); void SendLooter(Creature* creature, Player* pLooter); void GroupLoot(Loot* loot, WorldObject* pLootedObject); void NeedBeforeGreed(Loot* loot, WorldObject* pLootedObject); void MasterLoot(Loot* loot, WorldObject* pLootedObject); Rolls::iterator GetRoll(uint64 Guid); - void CountTheRoll(Rolls::iterator roll, uint32 NumberOfPlayers); - void CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise); + void CountTheRoll(Rolls::iterator roll); + void CountRollVote(uint64 playerGUID, uint64 Guid, uint8 Choise); void EndRoll(Loot* loot); // related to disenchant rolls diff --git a/src/server/game/Groups/GroupRefManager.h b/src/server/game/Groups/GroupRefManager.h index 9bcc05f8724..d9fef8611de 100755 --- a/src/server/game/Groups/GroupRefManager.h +++ b/src/server/game/Groups/GroupRefManager.h @@ -28,7 +28,8 @@ class GroupReference; class GroupRefManager : public RefManager<Group, Player> { public: - GroupReference* getFirst() { return ((GroupReference*) RefManager<Group, Player>::getFirst()); } + GroupReference* getFirst() { return ((GroupReference*)RefManager<Group, Player>::getFirst()); } + GroupReference const* getFirst() const { return ((GroupReference const*)RefManager<Group, Player>::getFirst()); } }; #endif diff --git a/src/server/game/Groups/GroupReference.h b/src/server/game/Groups/GroupReference.h index 2048fd9cb0d..7960dd21035 100755 --- a/src/server/game/Groups/GroupReference.h +++ b/src/server/game/Groups/GroupReference.h @@ -35,6 +35,7 @@ class GroupReference : public Reference<Group, Player> GroupReference() : Reference<Group, Player>(), iSubGroup(0) {} ~GroupReference() { unlink(); } GroupReference* next() { return (GroupReference*)Reference<Group, Player>::next(); } + GroupReference const* next() const { return (GroupReference const*)Reference<Group, Player>::next(); } uint8 getSubGroup() const { return iSubGroup; } void setSubGroup(uint8 pSubGroup) { iSubGroup = pSubGroup; } }; diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp index 9a3e756dda3..49027bdf497 100755 --- a/src/server/game/Handlers/AuthHandler.cpp +++ b/src/server/game/Handlers/AuthHandler.cpp @@ -31,7 +31,7 @@ void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos) if (!shortForm) { packet << uint32(queuePos); // Queue position - packet << uint8(0); // Unk 3.3.0 + packet << uint8(0); // Realm has a free character migration - bool } SendPacket(&packet); diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index de8dc2b90f6..18435263b2e 100755 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -429,24 +429,20 @@ void WorldSession::HandleLootMethodOpcode(WorldPacket & recv_data) group->SendUpdate(); } -void WorldSession::HandleLootRoll(WorldPacket &recv_data) +void WorldSession::HandleLootRoll(WorldPacket& recvData) { + uint64 guid; + uint32 itemSlot; + uint8 rollType; + recvData >> guid; // guid of the item rolled + recvData >> itemSlot; + recvData >> rollType; // 0: pass, 1: need, 2: greed + Group* group = GetPlayer()->GetGroup(); if (!group) - { - recv_data.rfinish(); return; - } - uint64 Guid; - uint32 NumberOfPlayers; - uint8 rollType; - recv_data >> Guid; //guid of the item rolled - recv_data >> NumberOfPlayers; - recv_data >> rollType; //0: pass, 1: need, 2: greed - - // everything's fine, do it - group->CountRollVote(GetPlayer()->GetGUID(), Guid, NumberOfPlayers, rollType); + group->CountRollVote(GetPlayer()->GetGUID(), guid, rollType); switch (rollType) { diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index 8e4b41a9be4..339c7a44d9f 100755 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -220,16 +220,18 @@ void WorldSession::HandleLootOpcode(WorldPacket & recv_data) GetPlayer()->InterruptNonMeleeSpells(false); } -void WorldSession::HandleLootReleaseOpcode(WorldPacket & recv_data) +void WorldSession::HandleLootReleaseOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT_RELEASE"); // cheaters can modify lguid to prevent correct apply loot release code and re-loot // use internal stored guid - recv_data.read_skip<uint64>(); // guid; + uint64 guid; + recvData >> guid; if (uint64 lguid = GetPlayer()->GetLootGUID()) - DoLootRelease(lguid); + if (lguid == guid) + DoLootRelease(lguid); } void WorldSession::DoLootRelease(uint64 lguid) diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 8484ac52d27..11f0857ca2b 100755 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -494,7 +494,7 @@ void WorldSession::HandleZoneUpdateOpcode(WorldPacket & recv_data) uint32 newZone; recv_data >> newZone; - sLog->outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd ZONE_UPDATE: %u", newZone); // use server size data uint32 newzone, newarea; @@ -730,7 +730,7 @@ void WorldSession::HandleBugOpcode(WorldPacket & recv_data) void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) { - sLog->outDetail("WORLD: Received CMSG_RECLAIM_CORPSE"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_RECLAIM_CORPSE"); uint64 guid; recv_data >> guid; @@ -767,7 +767,7 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data) { - sLog->outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_RESURRECT_RESPONSE"); uint64 guid; uint8 status; @@ -938,7 +938,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data) void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) { - sLog->outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); uint32 type, timestamp, decompressedSize; recv_data >> type >> timestamp >> decompressedSize; @@ -993,7 +993,7 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) { - sLog->outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); uint32 type; recv_data >> type; @@ -1072,18 +1072,18 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) void WorldSession::HandleCompleteCinematic(WorldPacket & /*recv_data*/) { - sLog->outStaticDebug("WORLD: Player is watching cinema"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_COMPLETE_CINEMATIC"); } void WorldSession::HandleNextCinematicCamera(WorldPacket & /*recv_data*/) { - sLog->outStaticDebug("WORLD: Which movie to play"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_NEXT_CINEMATIC_CAMERA"); } void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) { /* WorldSession::Update(getMSTime());*/ - sLog->outStaticDebug("WORLD: Time Lag/Synchronization Resent/Update"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_TIME_SKIPPED"); uint64 guid; recv_data.readPackGUID(guid); @@ -1105,7 +1105,7 @@ void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) void WorldSession::HandleFeatherFallAck(WorldPacket &recv_data) { - sLog->outStaticDebug("WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); // no used recv_data.rfinish(); // prevent warnings spam @@ -1193,13 +1193,17 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) { uint64 guid; recv_data >> guid; - sLog->outStaticDebug("Inspected guid is " UI64FMTD, guid); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_INSPECT"); _player->SetSelection(guid); Player* player = ObjectAccessor::FindPlayer(guid); - if (!player) // wrong player + if (!player) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_INSPECT: No player found from GUID: " UI64FMTD, guid); return; + } uint32 talent_points = 0x47; uint32 guid_size = player->GetPackGUID().wpos(); @@ -1230,7 +1234,7 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) if (!player) { - sLog->outError("InspectHonorStats: WTF, player not found..."); + sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_INSPECT_HONOR_STATS: No player found from GUID: " UI64FMTD, guid); return; } @@ -1246,10 +1250,6 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) { - // write in client console: worldport 469 452 6454 2536 180 or /console worldport 469 452 6454 2536 180 - // Received opcode CMSG_WORLD_TELEPORT - // Time is ***, map=469, x=452.000000, y=6454.000000, z=2536.000000, orient=3.141593 - uint32 time; uint32 mapid; float PositionX; @@ -1264,20 +1264,20 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) recv_data >> PositionZ; recv_data >> Orientation; // o (3.141593 = 180 degrees) - //sLog->outDebug("Received opcode CMSG_WORLD_TELEPORT"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_WORLD_TELEPORT"); + if (GetPlayer()->isInFlight()) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Player '%s' (GUID: %u) in flight, ignore worldport command.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); return; } - sLog->outStaticDebug("Time %u sec, map=%u, x=%f, y=%f, z=%f, orient=%f", time/1000, mapid, PositionX, PositionY, PositionZ, Orientation); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_WORLD_TELEPORT: Player = %s, Time = %u, map = %u, x = %f, y = %f, z = %f, o = %f", GetPlayer()->GetName(), time, mapid, PositionX, PositionY, PositionZ, Orientation); if (AccountMgr::IsAdminAccount(GetSecurity())) GetPlayer()->TeleportTo(mapid, PositionX, PositionY, PositionZ, Orientation); else SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received worldport command from player %s", GetPlayer()->GetName()); } void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index c271a43462a..ff9030f04d5 100755 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -295,16 +295,42 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) } // if we boarded a transport, add us to it - if (plrMover && !plrMover->GetTransport()) + if (plrMover) { - // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list - for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) + if (!plrMover->GetTransport()) { - if ((*iter)->GetGUID() == movementInfo.t_guid) + // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list + for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { - plrMover->m_transport = (*iter); - (*iter)->AddPassenger(plrMover); - break; + if ((*iter)->GetGUID() == movementInfo.t_guid) + { + plrMover->m_transport = *iter; + (*iter)->AddPassenger(plrMover); + break; + } + } + } + else if (plrMover->GetTransport()->GetGUID() != movementInfo.t_guid) + { + bool foundNewTransport = false; + plrMover->m_transport->RemovePassenger(plrMover); + for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) + { + if ((*iter)->GetGUID() == movementInfo.t_guid) + { + foundNewTransport = true; + plrMover->m_transport = *iter; + (*iter)->AddPassenger(plrMover); + break; + } + } + + if (!foundNewTransport) + { + plrMover->m_transport = NULL; + movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); + movementInfo.t_time = 0; + movementInfo.t_seat = -1; } } } diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index e54bee96b8b..321c0ada247 100755 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -339,9 +339,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid if (unit_target2->GetTypeId() == TYPEID_PLAYER) pet->SendUpdateToPlayer((Player*)unit_target2); } + if (Unit* powner = pet->GetCharmerOrOwner()) if (powner->GetTypeId() == TYPEID_PLAYER) - pet->SendUpdateToPlayer(powner->ToPlayer()); + pet->SendUpdateToPlayer(powner->ToPlayer()); + result = SPELL_CAST_OK; } @@ -741,7 +743,7 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { - sLog->outDetail("WORLD: CMSG_PET_CAST_SPELL"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_PET_CAST_SPELL"); uint64 guid; uint8 castCount; diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index 628cdbbdd5e..4fb90bed10b 100755 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -113,7 +113,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) ObjectMgr::GetLocaleString(cl->SubName, loc_idx, SubName); } } - sLog->outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry); // guess size WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100); data << uint32(entry); // creature entry @@ -179,7 +179,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) ObjectMgr::GetLocaleString(gl->CastBarCaption, loc_idx, CastBarCaption); } } - sLog->outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry); WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 150); data << uint32(entry); data << uint32(info->type); @@ -209,7 +209,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) { - sLog->outDetail("WORLD: Received MSG_CORPSE_QUERY"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_CORPSE_QUERY"); Corpse* corpse = GetPlayer()->GetCorpse(); @@ -264,7 +264,7 @@ void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) uint64 guid; recv_data >> textID; - sLog->outDetail("WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); recv_data >> guid; GetPlayer()->SetSelection(guid); @@ -344,7 +344,7 @@ void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) /// Only _static_ data is sent in this packet !!! void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data) { - sLog->outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PAGE_TEXT_QUERY"); uint32 pageID; recv_data >> pageID; diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index 34fed5e9a97..d13c2fb0956 100755 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -324,7 +324,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data) // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) { - if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(quest, true)) + if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true)) { _player->AddQuest(nextQuest, object); if (_player->CanCompleteQuest(nextQuest->GetQuestId())) @@ -343,7 +343,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data) // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) { - if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(quest, true)) + if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true)) { _player->AddQuest(nextQuest, object); if (_player->CanCompleteQuest(nextQuest->GetQuestId())) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 1affdf0aff7..c02bb43a353 100755 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -99,7 +99,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) return; } - sLog->outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, castCount: %u, spellId: %u, Item: %u, glyphIndex: %u, data length = %i", bagIndex, slot, castCount, spellId, pItem->GetEntry(), glyphIndex, (uint32)recvPacket.size()); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, castCount: %u, spellId: %u, Item: %u, glyphIndex: %u, data length = %i", bagIndex, slot, castCount, spellId, pItem->GetEntry(), glyphIndex, (uint32)recvPacket.size()); ItemTemplate const* proto = pItem->GetTemplate(); if (!proto) @@ -175,7 +175,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) { - sLog->outDetail("WORLD: CMSG_OPEN_ITEM packet, data length = %i", (uint32)recvPacket.size()); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_OPEN_ITEM packet, data length = %i", (uint32)recvPacket.size()); Player* pUser = _player; @@ -658,13 +658,16 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket) recvPacket >> z; Unit* caster = ObjectAccessor::GetUnit(*_player, casterGuid); - Spell* spell = caster ? caster->FindCurrentSpellBySpellId(spellId) : NULL; - if (spell && spell->m_targets.HasDst()) - { - Position pos = *spell->m_targets.GetDstPos(); - pos.Relocate(x, y, z); - spell->m_targets.ModDst(pos); - } + if (!caster) + return; + + Spell* spell = caster->FindCurrentSpellBySpellId(spellId); + if (!spell || !spell->m_targets.HasDst()) + return; + + Position pos = *spell->m_targets.GetDstPos(); + pos.Relocate(x, y, z); + spell->m_targets.ModDst(pos); WorldPacket data(SMSG_SET_PROJECTILE_POSITION, 21); data << uint64(casterGuid); @@ -672,5 +675,5 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket) data << float(x); data << float(y); data << float(z); - SendPacket(&data); + caster->SendMessageToSet(&data, true); } diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 8078a91d082..59bb86cb68e 100755 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -543,7 +543,10 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId) if (iMap && iMap->IsDungeon()) ((InstanceMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY); - sObjectMgr->DeleteRespawnTimeForInstance(instanceId); // even if map is not loaded + if (iMap) + iMap->DeleteRespawnTimes(); + else + Map::DeleteRespawnTimesInDB(mapid, instanceId); // Free up the instance id and allow it to be reused sMapMgr->FreeInstanceId(instanceId); diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index a5ad46c9ec4..53b560e0b77 100755 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -358,7 +358,12 @@ bool LootItem::AllowedForPlayer(Player const* player) const // check quest requirements if (!(pProto->FlagsCu & ITEM_FLAGS_CU_IGNORE_QUEST_STATUS) && ((needs_quest || (pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE)) && !player->HasQuestForItem(itemid))) - return false; + if (Group const* group = player->GetGroup()) + { + if (pProto->Flags & ITEM_PROTO_FLAG_PARTY_LOOT || ((pProto->Flags & ITEM_PROTO_FLAG_PARTY_LOOT) == 0 && (group->GetLootMethod() != MASTER_LOOT || group->GetLooterGuid() != player->GetGUID()))) + return false; + } + else return false; return true; } @@ -889,6 +894,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) } LootSlotType slotType = lv.permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT; + LootSlotType partySlotType = lv.permission == MASTER_PERMISSION ? LOOT_SLOT_TYPE_MASTER : (lv.permission == GROUP_PERMISSION ? LOOT_SLOT_TYPE_ROLL_ONGOING : slotType); QuestItemMap const& lootPlayerQuestItems = l.GetPlayerQuestItems(); QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUIDLow()); if (q_itr != lootPlayerQuestItems.end()) @@ -901,7 +907,10 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { b << uint8(l.items.size() + (qi - q_list->begin())); b << item; - b << uint8(slotType); + if (!item.freeforall) + b << uint8(partySlotType); + else + b << uint8(slotType); ++itemsShown; } } @@ -919,7 +928,10 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { b << uint8(fi->index); b << item; - b << uint8(slotType); + if (!item.freeforall) + b << uint8(partySlotType); + else + b << uint8(slotType); ++itemsShown; } } @@ -937,7 +949,10 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { b << uint8(ci->index); b << item; - b << uint8(slotType); + if (!item.freeforall) + b << uint8(partySlotType); + else + b << uint8(slotType); ++itemsShown; } } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 162dd12d121..82659e32016 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2632,7 +2632,7 @@ void InstanceMap::UnloadAll() ASSERT(!HavePlayers()); if (m_resetAfterUnload == true) - sObjectMgr->DeleteRespawnTimeForInstance(GetInstanceId()); + DeleteRespawnTimes(); Map::UnloadAll(); } @@ -2781,3 +2781,134 @@ void Map::UpdateIteratorBack(Player* player) if (m_mapRefIter == player->GetMapRef()) m_mapRefIter = m_mapRefIter->nocheck_prev(); } + +void Map::SaveCreatureRespawnTime(uint32 dbGuid, time_t respawnTime) +{ + if (!respawnTime) + { + // Delete only + RemoveCreatureRespawnTime(dbGuid); + return; + } + + _creatureRespawnTimes[dbGuid] = respawnTime; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CREATURE_RESPAWN); + stmt->setUInt32(0, dbGuid); + stmt->setUInt32(1, uint32(respawnTime)); + stmt->setUInt16(2, GetId()); + stmt->setUInt32(3, GetInstanceId()); + CharacterDatabase.Execute(stmt); +} + +void Map::RemoveCreatureRespawnTime(uint32 dbGuid) +{ + _creatureRespawnTimes.erase(dbGuid); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN); + stmt->setUInt32(0, dbGuid); + stmt->setUInt16(1, GetId()); + stmt->setUInt32(2, GetInstanceId()); + CharacterDatabase.Execute(stmt); +} + +void Map::SaveGORespawnTime(uint32 dbGuid, time_t respawnTime) +{ + if (!respawnTime) + { + // Delete only + RemoveGORespawnTime(dbGuid); + return; + } + + _goRespawnTimes[dbGuid] = respawnTime; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GO_RESPAWN); + stmt->setUInt32(0, dbGuid); + stmt->setUInt32(1, uint32(respawnTime)); + stmt->setUInt16(2, GetId()); + stmt->setUInt32(3, GetInstanceId()); + CharacterDatabase.Execute(stmt); +} + +void Map::RemoveGORespawnTime(uint32 dbGuid) +{ + _goRespawnTimes.erase(dbGuid); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN); + stmt->setUInt32(0, dbGuid); + stmt->setUInt16(1, GetId()); + stmt->setUInt32(2, GetInstanceId()); + CharacterDatabase.Execute(stmt); +} + +void Map::LoadRespawnTimes() +{ + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CREATURE_RESPAWNS); + stmt->setUInt16(0, GetId()); + stmt->setUInt32(1, GetInstanceId()); + if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) + { + do + { + Field* fields = result->Fetch(); + uint32 loguid = fields[0].GetUInt32(); + uint32 respawnTime = fields[1].GetUInt32(); + + _creatureRespawnTimes[loguid] = time_t(respawnTime); + } while (result->NextRow()); + } + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GO_RESPAWNS); + stmt->setUInt16(0, GetId()); + stmt->setUInt32(1, GetInstanceId()); + if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) + { + do + { + Field* fields = result->Fetch(); + uint32 loguid = fields[0].GetUInt32(); + uint32 respawnTime = fields[1].GetUInt32(); + + _goRespawnTimes[loguid] = time_t(respawnTime); + } while (result->NextRow()); + } +} + +void Map::DeleteRespawnTimes() +{ + _creatureRespawnTimes.clear(); + _goRespawnTimes.clear(); + + DeleteRespawnTimesInDB(GetId(), GetInstanceId()); +} + +void Map::DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId) +{ + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE); + stmt->setUInt16(0, mapId); + stmt->setUInt32(1, instanceId); + CharacterDatabase.Execute(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN_BY_INSTANCE); + stmt->setUInt16(0, mapId); + stmt->setUInt32(1, instanceId); + CharacterDatabase.Execute(stmt); +} + +time_t Map::GetLinkedRespawnTime(uint64 guid) const +{ + uint64 linkedGuid = sObjectMgr->GetLinkedRespawnGuid(guid); + switch (GUID_HIPART(linkedGuid)) + { + case HIGHGUID_UNIT: + return GetCreatureRespawnTime(GUID_LOPART(linkedGuid)); + case HIGHGUID_GAMEOBJECT: + return GetGORespawnTime(GUID_LOPART(linkedGuid)); + default: + break; + } + + return time_t(0); +} + diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 6ba08646f25..214f50e6d3c 100755 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -443,6 +443,38 @@ class Map : public GridRefManager<NGridType> void Insert(const GameObjectModel& mdl) { _dynamicTree.insert(mdl); } bool Contains(const GameObjectModel& mdl) const { return _dynamicTree.contains(mdl);} bool getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist); + + /* + RESPAWN TIMES + */ + time_t GetLinkedRespawnTime(uint64 guid) const; + time_t GetCreatureRespawnTime(uint32 dbGuid) const + { + UNORDERED_MAP<uint32 /*dbGUID*/, time_t>::const_iterator itr = _creatureRespawnTimes.find(dbGuid); + if (itr != _creatureRespawnTimes.end()) + return itr->second; + + return time_t(0); + } + + time_t GetGORespawnTime(uint32 dbGuid) const + { + UNORDERED_MAP<uint32 /*dbGUID*/, time_t>::const_iterator itr = _goRespawnTimes.find(dbGuid); + if (itr != _goRespawnTimes.end()) + return itr->second; + + return time_t(0); + } + + void SaveCreatureRespawnTime(uint32 dbGuid, time_t respawnTime); + void RemoveCreatureRespawnTime(uint32 dbGuid); + void SaveGORespawnTime(uint32 dbGuid, time_t respawnTime); + void RemoveGORespawnTime(uint32 dbGuid); + void LoadRespawnTimes(); + void DeleteRespawnTimes(); + + static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId); + private: void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); @@ -488,6 +520,7 @@ class Map : public GridRefManager<NGridType> void ScriptsProcess(); void UpdateActiveCells(const float &x, const float &y, const uint32 t_diff); + protected: void SetUnloadReferenceLock(const GridCoord &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); } @@ -570,6 +603,9 @@ class Map : public GridRefManager<NGridType> else m_activeNonPlayers.erase(obj); } + + UNORDERED_MAP<uint32 /*dbGUID*/, time_t> _creatureRespawnTimes; + UNORDERED_MAP<uint32 /*dbGUID*/, time_t> _goRespawnTimes; }; enum InstanceResetMethod diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 5543251e115..2c1bdb00834 100755 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -211,6 +211,8 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this); ASSERT(map->IsDungeon()); + map->LoadRespawnTimes(); + bool load_data = save != NULL; map->CreateInstanceData(load_data); diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index eb09538721d..e9de3ae001f 100755 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -110,6 +110,7 @@ Map* MapManager::CreateBaseMap(uint32 id) else { map = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); + map->LoadRespawnTimes(); } i_maps[id] = map; } diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index 1049325237a..106c2189c65 100755 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -71,7 +71,7 @@ class MapManager void SetMapUpdateInterval(uint32 t) { - if (t > MIN_MAP_UPDATE_DELAY) + if (t < MIN_MAP_UPDATE_DELAY) t = MIN_MAP_UPDATE_DELAY; i_timer.SetInterval(t); diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h index 33973064e09..cfc2fdee450 100644 --- a/src/server/game/Movement/Spline/MoveSplineFlag.h +++ b/src/server/game/Movement/Spline/MoveSplineFlag.h @@ -34,43 +34,43 @@ namespace Movement { public: enum eFlags{ - None = 0x00000000, - // x00-xFF(first byte) used as animation Ids storage in pair with Animation flag - Done = 0x00000100, - Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag - No_Spline = 0x00000400, - Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag - Walkmode = 0x00001000, - Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation - OrientationFixed = 0x00004000, // Model orientation fixed - Final_Point = 0x00008000, - Final_Target = 0x00010000, - Final_Angle = 0x00020000, - Catmullrom = 0x00040000, // Used Catmullrom interpolation mode - Cyclic = 0x00080000, // Movement by cycled spline - Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done - Animation = 0x00200000, // Plays animation after some time passed - Frozen = 0x00400000, // Will never arrive - Unknown5 = 0x00800000, - Unknown6 = 0x01000000, - Unknown7 = 0x02000000, - Unknown8 = 0x04000000, + None = 0x00000000, + // x00-xFF(first byte) used as animation Ids storage in pair with Animation flag + Done = 0x00000100, + Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag + No_Spline = 0x00000400, + Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag + Walkmode = 0x00001000, + Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation + OrientationFixed = 0x00004000, // Model orientation fixed + Final_Point = 0x00008000, + Final_Target = 0x00010000, + Final_Angle = 0x00020000, + Catmullrom = 0x00040000, // Used Catmullrom interpolation mode + Cyclic = 0x00080000, // Movement by cycled spline + Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done + Animation = 0x00200000, // Plays animation after some time passed + Frozen = 0x00400000, // Will never arrive + TransportEnter = 0x00800000, + TransportExit = 0x01000000, + Unknown7 = 0x02000000, + Unknown8 = 0x04000000, OrientationInversed = 0x08000000, - Unknown10 = 0x10000000, - Unknown11 = 0x20000000, - Unknown12 = 0x40000000, - Unknown13 = 0x80000000, + Unknown10 = 0x10000000, + Unknown11 = 0x20000000, + Unknown12 = 0x40000000, + Unknown13 = 0x80000000, // Masks - Mask_Final_Facing = Final_Point | Final_Target | Final_Angle, + Mask_Final_Facing = Final_Point | Final_Target | Final_Angle, // animation ids stored here, see AnimType enum, used with Animation flag - Mask_Animations = 0xFF, + Mask_Animations = 0xFF, // flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done, // CatmullRom interpolation mode used - Mask_CatmullRom = Flying | Catmullrom, + Mask_CatmullRom = Flying | Catmullrom, // Unused, not suported flags - Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown5|Unknown6|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13, + Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13, }; inline uint32& raw() { return (uint32&)*this;} @@ -98,14 +98,16 @@ namespace Movement void operator &= (uint32 f) { raw() &= f;} void operator |= (uint32 f) { raw() |= f;} - void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations|Falling|Parabolic)) | Animation|anim;} - void EnableParabolic() { raw() = (raw() & ~(Mask_Animations|Falling|Animation)) | Parabolic;} - void EnableFalling() { raw() = (raw() & ~(Mask_Animations|Parabolic|Animation)) | Falling;} + void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations | Falling | Parabolic)) | Animation | anim; } + void EnableParabolic() { raw() = (raw() & ~(Mask_Animations | Falling | Animation)) | Parabolic; } + void EnableFalling() { raw() = (raw() & ~(Mask_Animations | Parabolic | Animation)) | Falling; } void EnableFlying() { raw() = (raw() & ~Catmullrom) | Flying; } void EnableCatmullRom() { raw() = (raw() & ~Flying) | Catmullrom; } - void EnableFacingPoint() { raw() = (raw() & ~Mask_Final_Facing) | Final_Point;} - void EnableFacingAngle() { raw() = (raw() & ~Mask_Final_Facing) | Final_Angle;} - void EnableFacingTarget() { raw() = (raw() & ~Mask_Final_Facing) | Final_Target;} + void EnableFacingPoint() { raw() = (raw() & ~Mask_Final_Facing) | Final_Point; } + void EnableFacingAngle() { raw() = (raw() & ~Mask_Final_Facing) | Final_Angle; } + void EnableFacingTarget() { raw() = (raw() & ~Mask_Final_Facing) | Final_Target; } + void EnableTransportEnter() { raw() = (raw() & ~TransportExit) | TransportEnter; } + void EnableTransportExit() { raw() = (raw() & ~TransportEnter) | TransportExit; } uint8 animId : 8; bool done : 1; @@ -123,8 +125,8 @@ namespace Movement bool enter_cycle : 1; bool animation : 1; bool frozen : 1; - bool unknown5 : 1; - bool unknown6 : 1; + bool transportEnter: 1; + bool transportExit : 1; bool unknown7 : 1; bool unknown8 : 1; bool orientationInversed : 1; diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index b8440e06076..c539dd3cc39 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -62,7 +62,8 @@ namespace Movement bool transport = false; Location real_position(unit.GetPositionX(), unit.GetPositionY(), unit.GetPositionZMinusOffset(), unit.GetOrientation()); - if (unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes + if (unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit.GetTransGUID()) { transport = true; real_position.x = unit.GetTransOffsetX(); @@ -108,13 +109,7 @@ namespace Movement data.append(unit.GetPackGUID()); if (transport) { - if (unit.GetVehicle()) - data.appendPackGUID(unit.GetVehicleBase()->GetGUID()); - else if (unit.GetTransport()) - data.appendPackGUID(unit.GetTransGUID()); - else - data << uint8(0); - + data.appendPackGUID(unit.GetTransGUID()); data << int8(unit.GetTransSeat()); } @@ -124,6 +119,8 @@ namespace Movement MoveSplineInit::MoveSplineInit(Unit& m) : unit(m) { + // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes + args.TransformForTransport = unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit.GetTransGUID(); // mix existing state into new args.flags.walkmode = unit.m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING); args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY|MOVEMENTFLAG_DISABLE_GRAVITY)); @@ -132,12 +129,19 @@ namespace Movement void MoveSplineInit::SetFacing(const Unit * target) { args.flags.EnableFacingTarget(); - //args.facing.target = target->GetObjectGuid().GetRawValue(); - args.facing.target = target->GetUInt64Value(OBJECT_FIELD_GUID); + args.facing.target = target->GetGUID(); } void MoveSplineInit::SetFacing(float angle) { + if (args.TransformForTransport) + { + if (Unit* vehicle = unit.GetVehicleBase()) + angle -= vehicle->GetOrientation(); + else if (Transport* transport = unit.GetTransport()) + angle -= transport->GetOrientation(); + } + args.facing.angle = G3D::wrap(angle, 0.f, (float)G3D::twoPi()); args.flags.EnableFacingAngle(); } @@ -146,13 +150,13 @@ namespace Movement { args.path_Idx_offset = 0; args.path.resize(2); - TransportPathTransform transform(unit); + TransportPathTransform transform(unit, args.TransformForTransport); args.path[1] = transform(dest); } Vector3 TransportPathTransform::operator()(Vector3 input) { - if (_owner.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + if (_transformForTransport) { if (Unit* vehicle = _owner.GetVehicleBase()) { @@ -169,5 +173,4 @@ namespace Movement return input; } - } diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index b1b08d97cfa..ef847809ac8 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -37,11 +37,13 @@ namespace Movement class TransportPathTransform { public: - TransportPathTransform(Unit& owner) : _owner(owner) { } + TransportPathTransform(Unit& owner, bool transformForTransport) + : _owner(owner), _transformForTransport(transformForTransport) { } Vector3 operator()(Vector3 input); private: Unit& _owner; + bool _transformForTransport; }; /* Initializes and launches spline movement @@ -107,6 +109,12 @@ namespace Movement /* Enables falling mode. Disabled by default */ void SetFall(); + /* Enters transport. Disabled by default + */ + void SetTransportEnter(); + /* Exits transport. Disabled by default + */ + void SetTransportExit(); /* Inverses unit model orientation. Disabled by default */ void SetOrientationInversed(); @@ -123,31 +131,36 @@ namespace Movement PointsArray& Path() { return args.path; } + /* Disables transport coordinate transformations for cases where raw offsets are available + */ + void DisableTransportPathTransformations(); protected: MoveSplineInitArgs args; Unit& unit; }; - inline void MoveSplineInit::SetFly() { args.flags.EnableFlying();} + inline void MoveSplineInit::SetFly() { args.flags.EnableFlying(); } inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable;} inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom();} inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true;} inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();} inline void MoveSplineInit::SetVelocity(float vel) { args.velocity = vel; args.HasVelocity = true; } inline void MoveSplineInit::SetOrientationInversed() { args.flags.orientationInversed = true;} + inline void MoveSplineInit::SetTransportEnter() { args.flags.EnableTransportEnter(); } + inline void MoveSplineInit::SetTransportExit() { args.flags.EnableTransportExit(); } inline void MoveSplineInit::SetOrientationFixed(bool enable) { args.flags.orientationFixed = enable;} inline void MoveSplineInit::MovebyPath(const PointsArray& controls, int32 path_offset) { args.path_Idx_offset = path_offset; args.path.resize(controls.size()); - std::transform(controls.begin(), controls.end(), args.path.begin(), TransportPathTransform(unit)); + std::transform(controls.begin(), controls.end(), args.path.begin(), TransportPathTransform(unit, args.TransformForTransport)); } inline void MoveSplineInit::MoveTo(float x, float y, float z) { - Vector3 v(x,y,z); + Vector3 v(x, y, z); MoveTo(v); } @@ -166,10 +179,14 @@ namespace Movement inline void MoveSplineInit::SetFacing(Vector3 const& spot) { - args.facing.f.x = spot.x; - args.facing.f.y = spot.y; - args.facing.f.z = spot.z; + TransportPathTransform transform(unit, args.TransformForTransport); + Vector3 finalSpot = transform(spot); + args.facing.f.x = finalSpot.x; + args.facing.f.y = finalSpot.y; + args.facing.f.z = finalSpot.z; args.flags.EnableFacingPoint(); } + + inline void MoveSplineInit::DisableTransportPathTransformations() { args.TransformForTransport = false; } } #endif // TRINITYSERVER_MOVESPLINEINIT_H diff --git a/src/server/game/Movement/Spline/MoveSplineInitArgs.h b/src/server/game/Movement/Spline/MoveSplineInitArgs.h index 74409c9562b..de02b35d0a0 100644 --- a/src/server/game/Movement/Spline/MoveSplineInitArgs.h +++ b/src/server/game/Movement/Spline/MoveSplineInitArgs.h @@ -42,7 +42,8 @@ namespace Movement struct MoveSplineInitArgs { MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0), - velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f), HasVelocity(false) + velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f), + HasVelocity(false), TransformForTransport(true) { path.reserve(path_capacity); } @@ -57,6 +58,7 @@ namespace Movement uint32 splineId; float initialOrientation; bool HasVelocity; + bool TransformForTransport; /** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */ bool Validate() const; diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp index 465fca75030..dfdd4fc4ffc 100755 --- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp @@ -166,8 +166,10 @@ bool OPvPCapturePoint::DelCreature(uint32 type) //if (Map* map = sMapMgr->FindMap(cr->GetMapId())) // map->Remove(cr, false); // delete respawn time for this creature - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN_BY_GUID); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN); stmt->setUInt32(0, guid); + stmt->setUInt16(1, cr->GetMapId()); + stmt->setUInt32(2, 0); // instance id, always 0 for world maps CharacterDatabase.Execute(stmt); cr->AddObjectToRemoveList(); diff --git a/src/server/game/Server/Protocol/PacketLog.cpp b/src/server/game/Server/Protocol/PacketLog.cpp new file mode 100644 index 00000000000..cb6dcdbdb9e --- /dev/null +++ b/src/server/game/Server/Protocol/PacketLog.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008-2012 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/>. + */ + +#include "PacketLog.h" +#include "Config.h" +#include "ByteBuffer.h" +#include "WorldPacket.h" + +PacketLog::PacketLog() : _file(NULL) +{ + Initialize(); +} + +PacketLog::~PacketLog() +{ + if (_file) + fclose(_file); + + _file = NULL; +} + +void PacketLog::Initialize() +{ + std::string logsDir = ConfigMgr::GetStringDefault("LogsDir", ""); + + if (!logsDir.empty()) + if ((logsDir.at(logsDir.length()-1) != '/') && (logsDir.at(logsDir.length()-1) != '\\')) + logsDir.push_back('/'); + + std::string logname = ConfigMgr::GetStringDefault("PacketLogFile", ""); + if (!logname.empty()) + _file = fopen((logsDir + logname).c_str(), "wb"); +} + +void PacketLog::LogPacket(WorldPacket const& packet, Direction direction) +{ + ByteBuffer data(4+4+4+1+packet.size()); + data << int32(packet.GetOpcode()); + data << int32(packet.size()); + data << uint32(time(NULL)); + data << uint8(direction); + + for (uint32 i = 0; i < packet.size(); i++) + data << const_cast<WorldPacket&>(packet)[i]; + + fwrite(data.contents(), 1, data.size(), _file); + fflush(_file); +} diff --git a/src/server/game/Server/Protocol/WorldLog.h b/src/server/game/Server/Protocol/PacketLog.h index fb344f195de..b899daae198 100755..100644 --- a/src/server/game/Server/Protocol/WorldLog.h +++ b/src/server/game/Server/Protocol/PacketLog.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * 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,46 +15,36 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/// \addtogroup u2w -/// @{ -/// \file - -#ifndef TRINITY_WORLDLOG_H -#define TRINITY_WORLDLOG_H +#ifndef TRINITY_PACKETLOG_H +#define TRINITY_PACKETLOG_H #include "Common.h" #include <ace/Singleton.h> -#include "Errors.h" -#include <stdarg.h> +enum Direction +{ + CLIENT_TO_SERVER, + SERVER_TO_CLIENT +}; + +class WorldPacket; -/// %Log packets to a file -class WorldLog +class PacketLog { - friend class ACE_Singleton<WorldLog, ACE_Thread_Mutex>; + friend class ACE_Singleton<PacketLog, ACE_Thread_Mutex>; private: - WorldLog(); - ~WorldLog(); - WorldLog(const WorldLog &); - WorldLog& operator=(const WorldLog &); - ACE_Thread_Mutex Lock; + PacketLog(); + ~PacketLog(); public: void Initialize(); - /// Is the world logger active? - bool LogWorld(void) const { return (i_file != NULL); } - /// %Log to the file - void outLog(char const* fmt, ...); - void outTimestampLog(char const* fmt, ...); + bool CanLogPacket() const { return (_file != NULL); } + void LogPacket(WorldPacket const& packet, Direction direction); private: - FILE* i_file; - - bool m_dbWorld; + FILE* _file; }; -#define sWorldLog ACE_Singleton<WorldLog, ACE_Thread_Mutex>::instance() +#define sPacketLog ACE_Singleton<PacketLog, ACE_Thread_Mutex>::instance() #endif -/// @} - diff --git a/src/server/game/Server/Protocol/WorldLog.cpp b/src/server/game/Server/Protocol/WorldLog.cpp deleted file mode 100755 index 38b13dff095..00000000000 --- a/src/server/game/Server/Protocol/WorldLog.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * 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/>. - */ - -/** \file - \ingroup u2w -*/ - -#include "WorldLog.h" -#include "Config.h" -#include "Log.h" -#include "DatabaseWorkerPool.h" - -WorldLog::WorldLog() : i_file(NULL) -{ - Initialize(); -} - -WorldLog::~WorldLog() -{ - if (i_file != NULL) - fclose(i_file); - - i_file = NULL; -} - -/// Open the log file (if specified so in the configuration file) -void WorldLog::Initialize() -{ - std::string logsDir = ConfigMgr::GetStringDefault("LogsDir", ""); - - if (!logsDir.empty()) - { - if ((logsDir.at(logsDir.length()-1) != '/') && (logsDir.at(logsDir.length()-1) != '\\')) - logsDir.push_back('/'); - } - - std::string logname = ConfigMgr::GetStringDefault("WorldLogFile", ""); - if (!logname.empty()) - { - i_file = fopen((logsDir+logname).c_str(), "w"); - } - - m_dbWorld = ConfigMgr::GetBoolDefault("LogDB.World", false); // can be VERY heavy if enabled -} - -void WorldLog::outTimestampLog(char const* fmt, ...) -{ - if (LogWorld()) - { - TRINITY_GUARD(ACE_Thread_Mutex, Lock); - ASSERT(i_file); - - Log::outTimestamp(i_file); - va_list args; - va_start(args, fmt); - vfprintf(i_file, fmt, args); - //fprintf(i_file, "\n"); - va_end(args); - - fflush(i_file); - } - - if (sLog->GetLogDB() && m_dbWorld) - { - va_list ap2; - va_start(ap2, fmt); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); - sLog->outDB(LOG_TYPE_WORLD, nnew_str); - va_end(ap2); - } -} - -void WorldLog::outLog(char const* fmt, ...) -{ - if (LogWorld()) - { - TRINITY_GUARD(ACE_Thread_Mutex, Lock); - ASSERT(i_file); - - va_list args; - va_start(args, fmt); - vfprintf(i_file, fmt, args); - //fprintf(i_file, "\n"); - va_end(args); - - fflush(i_file); - } - - if (sLog->GetLogDB() && m_dbWorld) - { - va_list ap2; - va_start(ap2, fmt); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); - sLog->outDB(LOG_TYPE_WORLD, nnew_str); - va_end(ap2); - } -} diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 7756e686388..81ec5495421 100755 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -208,7 +208,7 @@ void WorldSession::QueuePacket(WorldPacket* new_packet) /// Logging helper for unexpected opcodes void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char* status, const char *reason) { - sLog->outError("SESSION (account: %u, guidlow: %u, char: %s): received unexpected opcode %s (0x%.4X, status: %s) %s", + sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION (account: %u, guidlow: %u, char: %s): received unexpected opcode %s (0x%.4X, status: %s) %s", GetAccountId(), m_GUIDLow, _player ? _player->GetName() : "<none>", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode(), status, reason); } @@ -216,7 +216,7 @@ void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char* status, /// Logging helper for unexpected opcodes void WorldSession::LogUnprocessedTail(WorldPacket* packet) { - sLog->outError("SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", + sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode(), uint32(packet->rpos()), uint32(packet->wpos())); packet->print_storage(); } @@ -334,7 +334,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) LogUnprocessedTail(packet); break; case STATUS_NEVER: - sLog->outError("SESSION (account: %u, guidlow: %u, char: %s): received not allowed opcode %s (0x%.4X)", + sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION (account: %u, guidlow: %u, char: %s): received not allowed opcode %s (0x%.4X)", GetAccountId(), m_GUIDLow, _player ? _player->GetName() : "<none>", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); break; diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 64137dfe7c7..74e414a43a9 100755 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -42,7 +42,7 @@ #include "WorldSession.h" #include "WorldSocketMgr.h" #include "Log.h" -#include "WorldLog.h" +#include "PacketLog.h" #include "ScriptMgr.h" #include "AccountMgr.h" @@ -152,7 +152,7 @@ const std::string& WorldSocket::GetRemoteAddress (void) const return m_Address; } -int WorldSocket::SendPacket(const WorldPacket& pct) +int WorldSocket::SendPacket(WorldPacket const& pct) { ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); @@ -160,24 +160,8 @@ int WorldSocket::SendPacket(const WorldPacket& pct) return -1; // Dump outgoing packet. - if (sWorldLog->LogWorld()) - { - sWorldLog->outTimestampLog ("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", - (uint32) get_handle(), - pct.size(), - LookupOpcodeName (pct.GetOpcode()), - pct.GetOpcode()); - - uint32 p = 0; - while (p < pct.size()) - { - for (uint32 j = 0; j < 16 && p < pct.size(); j++) - sWorldLog->outLog("%.2X ", const_cast<WorldPacket&>(pct)[p++]); - - sWorldLog->outLog("\n"); - } - sWorldLog->outLog("\n"); - } + if (sPacketLog->CanLogPacket()) + sPacketLog->LogPacket(pct, SERVER_TO_CLIENT); // Create a copy of the original packet; this is to avoid issues if a hook modifies it. sScriptMgr->OnPacketSend(this, WorldPacket(pct)); @@ -674,7 +658,7 @@ int WorldSocket::schedule_wakeup_output (GuardType& g) return 0; } -int WorldSocket::ProcessIncoming (WorldPacket* new_pct) +int WorldSocket::ProcessIncoming(WorldPacket* new_pct) { ACE_ASSERT (new_pct); @@ -687,24 +671,8 @@ int WorldSocket::ProcessIncoming (WorldPacket* new_pct) return -1; // Dump received packet. - if (sWorldLog->LogWorld()) - { - sWorldLog->outTimestampLog ("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", - (uint32) get_handle(), - new_pct->size(), - LookupOpcodeName (new_pct->GetOpcode()), - new_pct->GetOpcode()); - - uint32 p = 0; - while (p < new_pct->size()) - { - for (uint32 j = 0; j < 16 && p < new_pct->size(); j++) - sWorldLog->outLog ("%.2X ", (*new_pct)[p++]); - - sWorldLog->outLog ("\n"); - } - sWorldLog->outLog ("\n"); - } + if (sPacketLog->CanLogPacket()) + sPacketLog->LogPacket(*new_pct, CLIENT_TO_SERVER); try { @@ -955,6 +923,8 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) sha.UpdateBigNumbers (&k, NULL); sha.Finalize(); + std::string address = GetRemoteAddress(); + if (memcmp (sha.GetDigest(), digest, 20)) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); @@ -962,13 +932,11 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) SendPacket(packet); - sLog->outError("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); + sLog->outError("WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, account.c_str(), address.c_str()); return -1; } - std::string address = GetRemoteAddress(); - - sLog->outStaticDebug ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", + sLog->outStaticDebug("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", account.c_str(), address.c_str()); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 05114c8bc07..849a7136ea8 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3368,41 +3368,244 @@ void AuraEffect::HandleModStateImmunityMask(AuraApplication const* aurApp, uint8 return; Unit* target = aurApp->GetTarget(); + std::list <AuraType> aura_immunity_list; + uint32 mechanic_immunity_list; + int32 miscVal = GetMiscValue(); - std::list <AuraType> immunity_list; - if (GetMiscValue() & (1<<10)) - immunity_list.push_back(SPELL_AURA_MOD_STUN); - if (GetMiscValue() & (1<<1)) - immunity_list.push_back(SPELL_AURA_TRANSFORM); - - // These flag can be recognized wrong: - if (GetMiscValue() & (1<<6)) - immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); - if (GetMiscValue() & (1<<0)) - immunity_list.push_back(SPELL_AURA_MOD_ROOT); - if (GetMiscValue() & (1<<2)) - immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); - if (GetMiscValue() & (1<<9)) - immunity_list.push_back(SPELL_AURA_MOD_FEAR); - - // an exception for Bladestorm - if ((GetMiscValue() & (1<<7)) && (GetId() != 46924)) - immunity_list.push_back(SPELL_AURA_MOD_DISARM); - - // apply immunities - for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter) - target->ApplySpellImmune(GetId(), IMMUNITY_STATE, *iter, apply); + switch (miscVal) + { + case 96: + case 1615: + { + if (GetAmount()) + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 679: + { + if (GetId() == 57742) + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 1557: + { + if (GetId() == 64187) + { + mechanic_immunity_list = (1 << MECHANIC_STUN); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + } + else + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 1614: + case 1694: + { + target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_TAUNT); + break; + } + case 1630: + { + if (!GetAmount()) + { + target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_TAUNT); + } + else + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 477: + case 1733: + { + if (!GetAmount()) + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK_DEST, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 878: + { + if (GetAmount() == 1) + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_DISORIENTED) | (1 << MECHANIC_FREEZE); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + } + break; + } + default: + break; + } - // Patch 3.0.3 Bladestorm now breaks all snares and roots on the warrior when activated. - if (apply && GetId() == 46924) + if (aura_immunity_list.size() == 0) { - target->RemoveAurasByType(SPELL_AURA_MOD_ROOT); - target->RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); + if (miscVal & (1<<10)) + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + if (miscVal & (1<<1)) + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + + // These flag can be recognized wrong: + if (miscVal & (1<<6)) + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + if (miscVal & (1<<0)) + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + if (miscVal & (1<<2)) + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + if (miscVal & (1<<9)) + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + if (miscVal & (1<<7)) + aura_immunity_list.push_back(SPELL_AURA_MOD_DISARM); } + // apply immunities + for (std::list <AuraType>::iterator iter = aura_immunity_list.begin(); iter != aura_immunity_list.end(); ++iter) + target->ApplySpellImmune(GetId(), IMMUNITY_STATE, *iter, apply); + if (apply && GetSpellInfo()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY) - for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter) + { + target->RemoveAurasWithMechanic(mechanic_immunity_list, AURA_REMOVE_BY_DEFAULT, GetId()); + for (std::list <AuraType>::iterator iter = aura_immunity_list.begin(); iter != aura_immunity_list.end(); ++iter) target->RemoveAurasByType(*iter); + } } void AuraEffect::HandleModMechanicImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 58a89f75fd3..b51a3e8ee73 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2547,12 +2547,31 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA return SPELL_MISS_EVADE; // For delayed spells immunity may be applied between missile launch and hit - check immunity for that case + if (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo))) + return SPELL_MISS_IMMUNE; + // disable effects to which unit is immune + SpellMissInfo returnVal = SPELL_MISS_IMMUNE; for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) - if (effectMask & (1 << effectNumber) && unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber)) - effectMask &= ~(1 << effectNumber); - if (!effectMask || (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo)))) - return SPELL_MISS_IMMUNE; + { + if (effectMask & (1 << effectNumber)) + if (unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber)) + effectMask &= ~(1 << effectNumber); + else if (m_spellInfo->Effects[effectNumber].IsAura() && !m_spellInfo->IsPositiveEffect(effectNumber)) + { + int32 debuff_resist_chance = unit->GetMaxPositiveAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(m_spellInfo->Dispel)); + debuff_resist_chance += unit->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(m_spellInfo->Dispel)); + + if (debuff_resist_chance > 0) + if (irand(0,10000) <= (debuff_resist_chance * 100)) + { + effectMask &= ~(1 << effectNumber); + returnVal = SPELL_MISS_RESIST; + } + } + } + if (!effectMask) + return returnVal; PrepareScriptHitHandlers(); CallScriptBeforeHitHandlers(); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 17e79501d16..0d5dac8f8e0 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3317,6 +3317,14 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) fixed_bonus += (aur->GetStackAmount() - 1) * CalculateDamage(2, unitTarget); } } + if (m_spellInfo->SpellFamilyFlags[0] & 0x8000000) // Mocking Blow + { + if (unitTarget->IsImmunedToSpellEffect(m_spellInfo,EFFECT_1) || unitTarget->GetTypeId() == TYPEID_PLAYER) + { + m_damage = 0; + return; + } + } break; } case SPELLFAMILY_ROGUE: diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index a931f759163..7995087f2c1 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -450,6 +450,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const if (!basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION && _spellInfo->SpellLevel) && Effect != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE && Effect != SPELL_EFFECT_KNOCK_BACK && + Effect != SPELL_EFFECT_ADD_EXTRA_ATTACKS && ApplyAuraName != SPELL_AURA_MOD_SPEED_ALWAYS && ApplyAuraName != SPELL_AURA_MOD_SPEED_NOT_STACK && ApplyAuraName != SPELL_AURA_MOD_INCREASE_SPEED && diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 06e4978eb58..d9459b11ba1 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3045,6 +3045,9 @@ void SpellMgr::LoadDbcDataCorrections() case 48246: // Ball of Flame spellInfo->MaxAffectedTargets = 1; break; + case 36384: // Skartax Purple Beam + spellInfo->MaxAffectedTargets = 2; + break; case 41376: // Spite case 39992: // Needle Spine case 29576: // Multi-Shot @@ -3084,7 +3087,7 @@ void SpellMgr::LoadDbcDataCorrections() case 50312: // Unholy Frenzy spellInfo->MaxAffectedTargets = 15; break; - case 33711: //Murmur's Touch + case 33711: // Murmur's Touch case 38794: spellInfo->MaxAffectedTargets = 1; spellInfo->EffectTriggerSpell[0] = 33760; @@ -3238,6 +3241,9 @@ void SpellMgr::LoadDbcDataCorrections() spellInfo->EffectDieSides[0] = 0; // was 1, that should probably mean seat 0, but instead it's treated as spell 1 spellInfo->EffectBasePoints[0] = 52391; // Ride Vehicle (forces seat 0) break; + case 45602: // Ride Carpet + spellInfo->EffectBasePoints[EFFECT_0] = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)" + break; case 64745: // Item - Death Knight T8 Tank 4P Bonus case 64936: // Item - Warrior T8 Protection 4P Bonus spellInfo->EffectBasePoints[0] = 100; // 100% chance of procc'ing, not -10% (chance calculated in PrepareTriggersExecutedOnHit) diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp index 0734e0a0f63..cc1c2ff50c6 100644 --- a/src/server/game/Warden/Warden.cpp +++ b/src/server/game/Warden/Warden.cpp @@ -188,7 +188,11 @@ std::string Warden::Penalty(WardenCheck* check /*= NULL*/) std::string accountName; AccountMgr::GetName(_session->GetAccountId(), accountName); std::stringstream banReason; - banReason << "Warden Anticheat Violation: " << check->Comment << " (CheckId: " << check->CheckId << ")"; + banReason << "Warden Anticheat Violation"; + // Check can be NULL, for example if the client sent a wrong signature in the warden packet (CHECKSUM FAIL) + if (check) + banReason << ": " << check->Comment << " (CheckId: " << check->CheckId << ")"; + sWorld->BanAccount(BAN_ACCOUNT, accountName, duration.str(), banReason.str(),"Server"); return "Ban"; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index fa4943ce625..3aee1dc429e 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1411,15 +1411,9 @@ void World::SetInitialWorldSettings() sLog->outString("Loading Creature Addon Data..."); sObjectMgr->LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures() - sLog->outString("Loading Creature Respawn Data..."); // must be after PackInstances() - sObjectMgr->LoadCreatureRespawnTimes(); - sLog->outString("Loading Gameobject Data..."); sObjectMgr->LoadGameobjects(); - sLog->outString("Loading Gameobject Respawn Data..."); // must be after PackInstances() - sObjectMgr->LoadGameobjectRespawnTimes(); - sLog->outString("Loading Creature Linked Respawn..."); sObjectMgr->LoadLinkedRespawn(); // must be after LoadCreatures(), LoadGameObjects() diff --git a/src/server/scripts/Kalimdor/winterspring.cpp b/src/server/scripts/Kalimdor/winterspring.cpp index a02156ee110..2c4da0fdf7c 100644 --- a/src/server/scripts/Kalimdor/winterspring.cpp +++ b/src/server/scripts/Kalimdor/winterspring.cpp @@ -18,15 +18,13 @@ /* ScriptData SDName: Winterspring -SD%Complete: 90 -SDComment: Quest support: 5126 (Loraxs' tale missing proper gossip items text). Vendor Rivern Frostwind. Obtain Cache of Mau'ari +SD%Complete: Almost Completely Emptied +SDComment: Vendor Rivern Frostwind. SDCategory: Winterspring EndScriptData */ /* ContentData -npc_lorax npc_rivern_frostwind -npc_witch_doctor_mauari EndContentData */ #include "ScriptMgr.h" @@ -34,71 +32,6 @@ EndContentData */ #include "ScriptedGossip.h" /*###### -## npc_lorax -######*/ - -#define GOSSIP_HL "Talk to me" - -#define GOSSIP_SL1 "What do you do here?" -#define GOSSIP_SL2 "I can help you" -#define GOSSIP_SL3 "What deal?" -#define GOSSIP_SL4 "Then what happened?" -#define GOSSIP_SL5 "He is not safe, i'll make sure of that." - -class npc_lorax : public CreatureScript -{ -public: - npc_lorax() : CreatureScript("npc_lorax") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(3759, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(3760, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(3761, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - player->SEND_GOSSIP_MENU(3762, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - player->SEND_GOSSIP_MENU(3763, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - player->CLOSE_GOSSIP_MENU(); - player->AreaExploredOrEventHappens(5126); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(5126) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } - -}; - -/*###### ## npc_rivern_frostwind ######*/ @@ -131,49 +64,7 @@ public: }; -/*###### -## npc_witch_doctor_mauari -######*/ - -#define GOSSIP_HWDM "I'd like you to make me a new Cache of Mau'ari please." - -class npc_witch_doctor_mauari : public CreatureScript -{ -public: - npc_witch_doctor_mauari() : CreatureScript("npc_witch_doctor_mauari") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - player->CLOSE_GOSSIP_MENU(); - creature->CastSpell(player, 16351, false); - } - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestRewardStatus(975)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HWDM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(3377, creature->GetGUID()); - } - else - player->SEND_GOSSIP_MENU(3375, creature->GetGUID()); - - return true; - } -}; - void AddSC_winterspring() { - new npc_lorax(); new npc_rivern_frostwind(); - new npc_witch_doctor_mauari(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 734639a8b51..9baf6ba7a00 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -651,7 +651,7 @@ class npc_spinestalker : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData64(DATA_SINDRAGOSA_FROSTWYRMS, me->GetGUID()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -674,13 +674,12 @@ class npc_spinestalker : public CreatureScript void JustRespawned() { ScriptedAI::JustRespawned(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData64(DATA_SINDRAGOSA_FROSTWYRMS, me->GetGUID()); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) { _events.Reset(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0); } void DoAction(int32 const action) @@ -778,7 +777,7 @@ class npc_rimefang : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData64(DATA_SINDRAGOSA_FROSTWYRMS, me->GetGUID()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -801,13 +800,12 @@ class npc_rimefang : public CreatureScript void JustRespawned() { ScriptedAI::JustRespawned(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData64(DATA_SINDRAGOSA_FROSTWYRMS, me->GetGUID()); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) { _events.Reset(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0); } void DoAction(int32 const action) @@ -934,7 +932,8 @@ class npc_sindragosa_trash : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(_frostwyrmId, 1); // this cannot be in Reset because reset also happens on evade + if (me->GetEntry() == NPC_FROSTWING_WHELP) + _instance->SetData64(_frostwyrmId, me->GetGUID()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -956,13 +955,8 @@ class npc_sindragosa_trash : public CreatureScript ScriptedAI::JustRespawned(); // Increase add count - _instance->SetData(_frostwyrmId, 1); // this cannot be in Reset because reset also happens on evade - } - - void JustDied(Unit* /*killer*/) - { - // Decrease add count - _instance->SetData(_frostwyrmId, 0); + if (me->GetEntry() == NPC_FROSTWING_WHELP) + _instance->SetData64(_frostwyrmId, me->GetGUID()); // this cannot be in Reset because reset also happens on evade } void SetData(uint32 type, uint32 data) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index cb83efc748f..288fde28c38 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -89,6 +89,13 @@ WeeklyQuest const WeeklyQuestData[WeeklyNPCs] = {NPC_VALITHRIA_DREAMWALKER_QUEST, {QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_10, QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25}}, // Respite for a Tormented Soul }; +enum FrostwyrmFlags +{ + FLAG_SPINESTALKER_SUMMONED = 0x01, + FLAG_RIMEFANG_SUMMONED = 0x02, + FLAG_SINDRAGOSA_SUMMONED = 0x04, +}; + class instance_icecrown_citadel : public InstanceMapScript { public: @@ -138,9 +145,6 @@ class instance_icecrown_citadel : public InstanceMapScript FrozenThroneEdgeGUID = 0; FrozenThroneWindGUID = 0; FrozenThroneWarningGUID = 0; - FrostwyrmCount = 0; - SpinestalkerTrashCount = 0; - RimefangTrashCount = 0; IsBonedEligible = true; IsOozeDanceEligible = true; IsNauseaEligible = true; @@ -148,6 +152,7 @@ class instance_icecrown_citadel : public InstanceMapScript ColdflameJetsState = NOT_STARTED; BloodQuickeningState = NOT_STARTED; BloodQuickeningMinutes = 0; + FrostwyrmFlags = 0; } void FillInitialWorldStates(WorldPacket& data) @@ -279,9 +284,13 @@ class instance_icecrown_citadel : public InstanceMapScript break; case NPC_SPINESTALKER: SpinestalkerGUID = creature->GetGUID(); + if (!creature->isAlive()) + FrostwyrmFlags |= FLAG_SPINESTALKER_SUMMONED; break; case NPC_RIMEFANG: RimefangGUID = creature->GetGUID(); + if (!creature->isAlive()) + FrostwyrmFlags |= FLAG_RIMEFANG_SUMMONED; break; case NPC_THE_LICH_KING: TheLichKingGUID = creature->GetGUID(); @@ -347,6 +356,56 @@ class instance_icecrown_citadel : public InstanceMapScript if (Creature* crok = instance->GetCreature(CrokScourgebaneGUID)) crok->AI()->SetGUID(creature->GetGUID(), ACTION_VRYKUL_DEATH); break; + case NPC_FROSTWING_WHELP: + if (creature->AI()->GetData(1/*DATA_FROSTWYRM_OWNER*/) == DATA_SPINESTALKER) + { + if (FrostwyrmFlags & FLAG_SPINESTALKER_SUMMONED) + return; + + SpinestalkerTrash.erase(creature->GetGUID()); + if (SpinestalkerTrash.empty()) + { + FrostwyrmFlags |= FLAG_SPINESTALKER_SUMMONED; + if (Creature* spinestalk = instance->GetCreature(SpinestalkerGUID)) + spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); + } + } + else + { + if (FrostwyrmFlags & FLAG_RIMEFANG_SUMMONED) + return; + + RimefangTrash.erase(creature->GetGUID()); + if (RimefangTrash.empty()) + { + FrostwyrmFlags |= FLAG_RIMEFANG_SUMMONED; + if (Creature* spinestalk = instance->GetCreature(RimefangGUID)) + spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); + } + } + break; + case NPC_RIMEFANG: + case NPC_SPINESTALKER: + { + if (FrostwyrmFlags & FLAG_SINDRAGOSA_SUMMONED) + return; + + if (instance->IsHeroic() && !HeroicAttempts) + return; + + if (GetBossState(DATA_SINDRAGOSA) == DONE) + return; + + FrostwyrmGUIDs.erase(creature->GetGUID()); + if (FrostwyrmGUIDs.empty()) + { + FrostwyrmFlags |= FLAG_SINDRAGOSA_SUMMONED; + instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); + if (Creature* boss = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos)) + boss->AI()->DoAction(ACTION_START_FROSTWYRM); + } + break; + } default: break; } @@ -538,11 +597,17 @@ class instance_icecrown_citadel : public InstanceMapScript switch (type) { case DATA_SINDRAGOSA_FROSTWYRMS: - return FrostwyrmCount; + if (FrostwyrmFlags & FLAG_SINDRAGOSA_SUMMONED) + return 255; + return FrostwyrmGUIDs.size(); case DATA_SPINESTALKER: - return SpinestalkerTrashCount; + if (FrostwyrmFlags & FLAG_SPINESTALKER_SUMMONED) + return 255; + return SpinestalkerTrash.size(); case DATA_RIMEFANG: - return RimefangTrashCount; + if (FrostwyrmFlags & FLAG_RIMEFANG_SUMMONED) + return 255; + return RimefangTrash.size(); case DATA_COLDFLAME_JETS: return ColdflameJetsState; case DATA_TEAM_IN_INSTANCE: @@ -741,6 +806,9 @@ class instance_icecrown_citadel : public InstanceMapScript sindra->DespawnOrUnsummon(); } } + // Reached when loading from DB + if (state == DONE) + FrostwyrmFlags |= FLAG_SINDRAGOSA_SUMMONED; break; case DATA_THE_LICH_KING: { @@ -798,89 +866,17 @@ class instance_icecrown_citadel : public InstanceMapScript IsOrbWhispererEligible = data ? true : false; break; case DATA_SINDRAGOSA_FROSTWYRMS: - { - if (FrostwyrmCount == 255) - return; - - if (instance->IsHeroic() && !HeroicAttempts) - return; - - if (GetBossState(DATA_SINDRAGOSA) == DONE) - return; - - switch (data) - { - case 0: - if (FrostwyrmCount) - { - --FrostwyrmCount; - if (!FrostwyrmCount) - { - instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); - if (Creature* boss = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos)) - boss->AI()->DoAction(ACTION_START_FROSTWYRM); - } - } - break; - case 1: - ++FrostwyrmCount; - break; - default: - FrostwyrmCount = data; - break; - } + if (data == 255) + FrostwyrmFlags |= FLAG_SINDRAGOSA_SUMMONED; break; - } case DATA_SPINESTALKER: - { - if (SpinestalkerTrashCount == 255) - return; - - switch (data) - { - case 0: - if (SpinestalkerTrashCount) - { - --SpinestalkerTrashCount; - if (!SpinestalkerTrashCount) - if (Creature* spinestalk = instance->GetCreature(SpinestalkerGUID)) - spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); - } - break; - case 1: - ++SpinestalkerTrashCount; - break; - default: - SpinestalkerTrashCount = data; - break; - } + if (data == 255) + FrostwyrmFlags |= FLAG_SPINESTALKER_SUMMONED; break; - } case DATA_RIMEFANG: - { - if (RimefangTrashCount == 255) - return; - - switch (data) - { - case 0: - if (RimefangTrashCount) - { - --RimefangTrashCount; - if (!RimefangTrashCount) - if (Creature* rime = instance->GetCreature(RimefangGUID)) - rime->AI()->DoAction(ACTION_START_FROSTWYRM); - } - break; - case 1: - ++RimefangTrashCount; - break; - default: - RimefangTrashCount = data; - break; - } + if (data == 255) + FrostwyrmFlags |= FLAG_RIMEFANG_SUMMONED; break; - } case DATA_COLDFLAME_JETS: ColdflameJetsState = data; if (ColdflameJetsState == DONE) @@ -922,6 +918,22 @@ class instance_icecrown_citadel : public InstanceMapScript } } + void SetData64(uint32 id, uint64 data) + { + switch (id) + { + case DATA_SINDRAGOSA_FROSTWYRMS: + FrostwyrmGUIDs.insert(data); + break; + case DATA_SPINESTALKER: + SpinestalkerTrash.insert(data); + break; + case DATA_RIMEFANG: + RimefangTrash.insert(data); + break; + } + } + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) { switch (criteria_id) @@ -1289,12 +1301,13 @@ class instance_icecrown_citadel : public InstanceMapScript uint64 PillarsUnchainedGUID; uint32 TeamInInstance; uint32 ColdflameJetsState; - uint32 FrostwyrmCount; - uint32 SpinestalkerTrashCount; - uint32 RimefangTrashCount; + std::set<uint64> FrostwyrmGUIDs; + std::set<uint64> SpinestalkerTrash; + std::set<uint64> RimefangTrash; uint32 BloodQuickeningState; uint32 HeroicAttempts; uint16 BloodQuickeningMinutes; + uint16 FrostwyrmFlags; bool IsBonedEligible; bool IsOozeDanceEligible; bool IsNauseaEligible; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp index c7091b42c5a..a2044854672 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp @@ -170,7 +170,11 @@ enum AchievementCredits ACHIEV_MUST_DECONSTRUCT_FASTER = 21027, }; -#define HEART_VEHICLE_SEAT 0 +enum VehicleSeats +{ + HEART_VEHICLE_SEAT_NORMAL = 0, + HEART_VEHICLE_SEAT_EXPOSED = 1, +}; /*------------------------------------------------------- * @@ -198,6 +202,8 @@ class boss_xt002 : public CreatureScript _Reset(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + DoCast(me, SPELL_STAND); _healthRecovered = false; _gravityBombCasualty = false; @@ -356,15 +362,16 @@ class boss_xt002 : public CreatureScript me->AttackStop(); me->SetReactState(REACT_PASSIVE); - Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT) : NULL; + Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT_NORMAL) : NULL; if (heart) { heart->CastSpell(heart, SPELL_HEART_OVERLOAD, false); heart->CastSpell(me, SPELL_HEART_LIGHTNING_TETHER, false); heart->CastSpell(heart, SPELL_HEART_HEAL_TO_FULL, true); heart->CastSpell(heart, SPELL_EXPOSED_HEART, false); // Channeled - - heart->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + heart->ChangeSeat(HEART_VEHICLE_SEAT_EXPOSED, true); + heart->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + heart->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); } events.CancelEvent(EVENT_SEARING_LIGHT); @@ -392,11 +399,13 @@ class boss_xt002 : public CreatureScript events.RescheduleEvent(EVENT_GRAVITY_BOMB, TIMER_GRAVITY_BOMB); events.RescheduleEvent(EVENT_TYMPANIC_TANTRUM, urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX)); - Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT) : NULL; + Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT_EXPOSED) : NULL; if (!heart) return; - heart->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + heart->ChangeSeat(HEART_VEHICLE_SEAT_NORMAL, false); + heart->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + heart->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); heart->RemoveAurasDueToSpell(SPELL_EXPOSED_HEART); if (!_hardMode) @@ -425,43 +434,39 @@ class boss_xt002 : public CreatureScript * XT-002 HEART * *///---------------------------------------------------- + class mob_xt002_heart : public CreatureScript { public: mob_xt002_heart() : CreatureScript("mob_xt002_heart") { } - CreatureAI* GetAI(Creature* creature) const + struct mob_xt002_heartAI : public Scripted_NoMovementAI { - return new mob_xt002_heartAI(creature); - } - - struct mob_xt002_heartAI : public ScriptedAI - { - mob_xt002_heartAI(Creature* creature) : ScriptedAI(creature) + mob_xt002_heartAI(Creature* creature) : Scripted_NoMovementAI(creature), + _instance(creature->GetInstanceScript()) { - _instance = creature->GetInstanceScript(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_PASSIVE); } - void DamageTaken(Unit* /*pDone*/, uint32 &damage) + void UpdateAI(uint32 const /*diff*/) { } + + void JustDied(Unit* /*killer*/) { - Creature* xt002 = me->GetCreature(*me, _instance->GetData64(BOSS_XT002)); + Creature* xt002 = _instance ? me->GetCreature(*me, _instance->GetData64(BOSS_XT002)) : NULL; if (!xt002 || !xt002->AI()) return; - if (damage >= me->GetHealth()) - { - xt002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetMaxHealth()); - xt002->AI()->DoAction(ACTION_ENTER_HARD_MODE); - damage = 0; - } + xt002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetHealth()); + xt002->AI()->DoAction(ACTION_ENTER_HARD_MODE); } - private: - InstanceScript* _instance; - uint32 _damageTaken; + private: + InstanceScript* _instance; }; + + CreatureAI* GetAI(Creature* creature) const + { + return new mob_xt002_heartAI(creature); + } }; /*------------------------------------------------------- @@ -915,7 +920,7 @@ class spell_xt002_heart_overload_periodic : public SpellScriptLoader { uint8 a = urand(0, 4); uint32 spellId = spells[a]; - toyPile->CastSpell(toyPile, spellId, true); + toyPile->CastSpell(toyPile, spellId, true, NULL, NULL, instance->GetData64(BOSS_XT002)); } } } diff --git a/src/server/scripts/Northrend/dragonblight.cpp b/src/server/scripts/Northrend/dragonblight.cpp index 4cbe280a9f2..1b339b24549 100644 --- a/src/server/scripts/Northrend/dragonblight.cpp +++ b/src/server/scripts/Northrend/dragonblight.cpp @@ -69,7 +69,106 @@ public: } }; +/*###### +## Quest Strengthen the Ancients (12096|12092) +######*/ + +enum StrengthenAncientsMisc +{ + SAY_WALKER_FRIENDLY = 0, + SAY_WALKER_ENEMY = 1, + SAY_LOTHALOR = 0, + + SPELL_CREATE_ITEM_BARK = 47550, + SPELL_CONFUSED = 47044, + + NPC_LOTHALOR = 26321, + + FACTION_WALKER_ENEMY = 14, +}; + +class spell_q12096_q12092_dummy : public SpellScriptLoader // Strengthen the Ancients: On Interact Dummy to Woodlands Walker +{ +public: + spell_q12096_q12092_dummy() : SpellScriptLoader("spell_q12096_q12092_dummy") { } + + class spell_q12096_q12092_dummy_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12096_q12092_dummy_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + uint32 roll = rand() % 2; + + Creature* tree = GetHitCreature(); + Player* player = GetCaster()->ToPlayer(); + + if (!tree || !player) + return; + + tree->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + + if (roll == 1) // friendly version + { + tree->CastSpell(player, SPELL_CREATE_ITEM_BARK); + tree->AI()->Talk(SAY_WALKER_FRIENDLY, player->GetGUID()); + tree->DespawnOrUnsummon(1000); + } + else if (roll == 0) // enemy version + { + tree->AI()->Talk(SAY_WALKER_ENEMY, player->GetGUID()); + tree->setFaction(FACTION_WALKER_ENEMY); + tree->Attack(player, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12096_q12092_dummy_SpellScript(); + } +}; + +class spell_q12096_q12092_bark : public SpellScriptLoader // Bark of the Walkers +{ +public: + spell_q12096_q12092_bark() : SpellScriptLoader("spell_q12096_q12092_bark") { } + + class spell_q12096_q12092_bark_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12096_q12092_bark_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Creature* lothalor = GetHitCreature(); + if (!lothalor || lothalor->GetEntry() != NPC_LOTHALOR) + return; + + lothalor->AI()->Talk(SAY_LOTHALOR); + lothalor->RemoveAura(SPELL_CONFUSED); + lothalor->DespawnOrUnsummon(4000); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_bark_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12096_q12092_bark_SpellScript(); + } +}; + void AddSC_dragonblight() { new npc_alexstrasza_wr_gate; + new spell_q12096_q12092_dummy; + new spell_q12096_q12092_bark; } diff --git a/src/server/scripts/Outland/netherstorm.cpp b/src/server/scripts/Outland/netherstorm.cpp index afc18c71b92..16dac13d1a9 100644 --- a/src/server/scripts/Outland/netherstorm.cpp +++ b/src/server/scripts/Outland/netherstorm.cpp @@ -777,10 +777,10 @@ public: PlayerGUID = who->GetGUID(); } - void SpellHit(Unit* /*caster*/, const SpellInfo* /*spell*/) - { - DoCast(me, SPELL_DE_MATERIALIZE); - } + //void SpellHit(Unit* /*caster*/, const SpellInfo* /*spell*/) + //{ + // DoCast(me, SPELL_DE_MATERIALIZE); + //} void UpdateAI(const uint32 diff) { diff --git a/src/server/scripts/Spells/CMakeLists.txt b/src/server/scripts/Spells/CMakeLists.txt index 04dcee9287c..2bb695bd8a9 100644 --- a/src/server/scripts/Spells/CMakeLists.txt +++ b/src/server/scripts/Spells/CMakeLists.txt @@ -24,6 +24,7 @@ set(scripts_STAT_SRCS Spells/spell_paladin.cpp Spells/spell_item.cpp Spells/spell_holiday.cpp + Spells/spell_pet.cpp ) message(" -> Prepared: Spells") diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 36dcb53ad00..c33ca548d73 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -381,6 +381,13 @@ class spell_dk_scourge_strike : public SpellScriptLoader class spell_dk_scourge_strike_SpellScript : public SpellScript { PrepareSpellScript(spell_dk_scourge_strike_SpellScript); + float multiplier; + + bool Load() + { + multiplier = 1.0f; + return true; + } bool Validate(SpellInfo const* /*spellEntry*/) { @@ -393,8 +400,15 @@ class spell_dk_scourge_strike : public SpellScriptLoader { Unit* caster = GetCaster(); if (Unit* unitTarget = GetHitUnit()) + multiplier = (GetEffectValue() * unitTarget->GetDiseasesByCaster(caster->GetGUID()) / 100.f); + } + + void HandleAfterHit() + { + Unit* caster = GetCaster(); + if (Unit* unitTarget = GetHitUnit()) { - int32 bp = CalculatePctN(GetHitDamage(), GetEffectValue() * unitTarget->GetDiseasesByCaster(caster->GetGUID())); + int32 bp = GetHitDamage() * multiplier; caster->CastCustomSpell(unitTarget, DK_SPELL_SCOURGE_STRIKE_TRIGGERED, &bp, NULL, NULL, true); } } @@ -402,6 +416,7 @@ class spell_dk_scourge_strike : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_dk_scourge_strike_SpellScript::HandleDummy, EFFECT_2, SPELL_EFFECT_DUMMY); + AfterHit += SpellHitFn(spell_dk_scourge_strike_SpellScript::HandleAfterHit); } }; diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index e23e21cf2cd..5b65d0ca763 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -660,22 +660,16 @@ class spell_pvp_trinket_wotf_shared_cd : public SpellScriptLoader return true; } - void HandleScript(SpellEffIndex /*effIndex*/) + void HandleScript() { - Player* caster = GetCaster()->ToPlayer(); - SpellInfo const* spellInfo = GetSpellInfo(); - caster->AddSpellCooldown(spellInfo->Id, 0, time(NULL) + sSpellMgr->GetSpellInfo(SPELL_WILL_OF_THE_FORSAKEN_COOLDOWN_TRIGGER)->GetRecoveryTime() / IN_MILLISECONDS); - WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+4); - data << uint64(caster->GetGUID()); - data << uint8(0); - data << uint32(spellInfo->Id); - data << uint32(0); - caster->GetSession()->SendPacket(&data); + // This is only needed because spells cast from spell_linked_spell are triggered by default + // Spell::SendSpellCooldown() skips all spells with TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD + GetCaster()->ToPlayer()->AddSpellAndCategoryCooldowns(GetSpellInfo(), GetCastItem() ? GetCastItem()->GetEntry() : 0, GetSpell()); } void Register() { - OnEffectHit += SpellEffectFn(spell_pvp_trinket_wotf_shared_cd_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + AfterCast += SpellCastFn(spell_pvp_trinket_wotf_shared_cd_SpellScript::HandleScript); } }; @@ -2697,7 +2691,7 @@ public: { PrepareSpellScript(spell_gen_touch_the_nightmare_SpellScript); - void HandleDamageCalc(SpellEffIndex effIndex) + void HandleDamageCalc(SpellEffIndex /*effIndex*/) { uint32 bp = GetCaster()->GetMaxHealth() * 0.3f; SetHitDamage(bp); diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp new file mode 100644 index 00000000000..6ed0f18c785 --- /dev/null +++ b/src/server/scripts/Spells/spell_pet.cpp @@ -0,0 +1,1752 @@ +/* + * Copyright (C) 2008-2012 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/>. + */ + +/* + * Scripts for spells with SPELLFAMILY_DEATHKNIGHT and SPELLFAMILY_GENERIC spells used by deathknight players. + * Ordered alphabetically using scriptname. + * Scriptnames of files in this file should be prefixed with "spell_dk_". + */ + +#include "ScriptMgr.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "Unit.h" +#include "Player.h" +#include "Pet.h" + +enum HunterPetCalculate +{ + SPELL_TAMED_PET_PASSIVE_06 = 19591, + SPELL_TAMED_PET_PASSIVE_07 = 20784, + SPELL_TAMED_PET_PASSIVE_08 = 34666, + SPELL_TAMED_PET_PASSIVE_09 = 34667, + SPELL_TAMED_PET_PASSIVE_10 = 34675, + SPELL_HUNTER_PET_SCALING_01 = 34902, + SPELL_HUNTER_PET_SCALING_02 = 34903, + SPELL_HUNTER_PET_SCALING_03 = 34904, + SPELL_HUNTER_PET_SCALING_04 = 61017, + SPELL_HUNTER_ANIMAL_HANDLER = 34453, +}; + +enum WarlockPetCalculate +{ + SPELL_PET_PASSIVE_CRIT = 35695, + SPELL_PET_PASSIVE_DAMAGE_TAKEN = 35697, + SPELL_WARLOCK_PET_SCALING_01 = 34947, + SPELL_WARLOCK_PET_SCALING_02 = 34956, + SPELL_WARLOCK_PET_SCALING_03 = 34957, + SPELL_WARLOCK_PET_SCALING_04 = 34958, + SPELL_WARLOCK_PET_SCALING_05 = 61013, + ENTRY_FELGUARD = 17252, + ENTRY_VOIDWALKER = 1860, + ENTRY_FELHUNTER = 417, + ENTRY_SUCCUBUS = 1863, + ENTRY_IMP = 416, + SPELL_WARLOCK_GLYPH_OF_VOIDWALKER = 56247, +}; + +enum DKPetCalculate +{ + SPELL_DEATH_KNIGHT_RUNE_WEAPON_02 = 51906, + SPELL_DEATH_KNIGHT_PET_SCALING_01 = 54566, + SPELL_DEATH_KNIGHT_PET_SCALING_02 = 51996, + SPELL_DEATH_KNIGHT_PET_SCALING_03 = 61697, + SPELL_NIGHT_OF_THE_DEAD = 55620, + ENTRY_ARMY_OF_THE_DEAD_GHOUL = 24207, + SPELL_DEATH_KNIGHT_GLYPH_OF_GHOUL = 58686, +}; + +enum ShamanPetCalculate +{ + SPELL_FERAL_SPIRIT_PET_UNK_01 = 35674, + SPELL_FERAL_SPIRIT_PET_UNK_02 = 35675, + SPELL_FERAL_SPIRIT_PET_UNK_03 = 35676, + SPELL_FERAL_SPIRIT_PET_SCALING_04 = 61783, +}; + +enum MiscPetCalculate +{ + SPELL_MAGE_PET_PASSIVE_ELEMENTAL = 44559, + SPELL_PET_HEALTH_SCALING = 61679, + SPELL_PET_UNK_01 = 67561, + SPELL_PET_UNK_02 = 67557, +}; + +class spell_gen_pet_calculate : public SpellScriptLoader +{ + public: + spell_gen_pet_calculate() : SpellScriptLoader("spell_gen_pet_calculate") { } + + class spell_gen_pet_calculate_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_pet_calculate_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountCritSpell(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritSpell = 0.0f; + // Crit from Intellect + CritSpell += owner->GetSpellCritFromIntellect(); + // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE + CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit spell from spell crit ratings + CritSpell += owner->GetRatingBonusValue(CR_CRIT_SPELL); + + amount += int32(CritSpell); + } + } + + void CalculateAmountCritMelee(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritMelee = 0.0f; + // Crit from Agility + CritMelee += owner->GetMeleeCritFromAgility(); + // Increase crit from SPELL_AURA_MOD_WEAPON_CRIT_PERCENT + CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit melee from melee crit ratings + CritMelee += owner->GetRatingBonusValue(CR_CRIT_MELEE); + + amount += int32(CritMelee); + } + } + + void CalculateAmountMeleeHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + // Increase hit melee from meele hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_MELEE); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void CalculateAmountExpertise(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float Expertise = 0.0f; + // Increase hit from SPELL_AURA_MOD_EXPERTISE + Expertise += owner->GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE); + // Increase Expertise from Expertise ratings + Expertise += owner->GetRatingBonusValue(CR_EXPERTISE); + + amount += int32(Expertise); + } + } + + void Register() + { + switch (m_scriptSpellId) + { + case SPELL_TAMED_PET_PASSIVE_06: + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountCritMelee, EFFECT_0, SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountCritSpell, EFFECT_1, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + break; + case SPELL_PET_PASSIVE_CRIT: + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountCritSpell, EFFECT_0, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountCritMelee, EFFECT_1, SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + break; + case SPELL_WARLOCK_PET_SCALING_05: + case SPELL_HUNTER_PET_SCALING_04: + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountExpertise, EFFECT_2, SPELL_AURA_MOD_EXPERTISE); + break; + case SPELL_DEATH_KNIGHT_PET_SCALING_03: +// case SPELL_SHAMAN_PET_HIT: + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + break; + default: + break; + } + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_pet_calculate_AuraScript(); + } +}; + +class spell_warl_pet_scaling_01 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_01() : SpellScriptLoader("spell_warl_pet_scaling_01") { } + + class spell_warl_pet_scaling_01_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_01_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + _tempBonus = 0; + return true; + } + + void CalculateStaminaAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = CalculatePctN(owner->GetStat(STAT_STAMINA), 75); + + amount += ownerBonus; + } + } + + void ApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (_tempBonus) + { + PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(pet->GetEntry(), pet->getLevel()); + uint32 healthMod = 0; + uint32 baseHealth = pInfo->health; + switch (pet->GetEntry()) + { + case ENTRY_IMP: + healthMod = uint32(_tempBonus * 8.4f); + break; + case ENTRY_FELGUARD: + case ENTRY_VOIDWALKER: + healthMod = _tempBonus * 11; + break; + case ENTRY_SUCCUBUS: + healthMod = uint32(_tempBonus * 9.1f); + break; + case ENTRY_FELHUNTER: + healthMod = uint32(_tempBonus * 9.5f); + break; + default: + healthMod = 0; + break; + } + if (healthMod) + pet->ToPet()->SetCreateHealth(baseHealth + healthMod); + } + } + + void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + { + PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(pet->GetEntry(), pet->getLevel()); + pet->ToPet()->SetCreateHealth(pInfo->health); + } + } + + void CalculateAttackPowerAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + + if (Unit* owner = pet->ToPet()->GetOwner()) + { + int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE); + int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW); + int32 maximum = (fire > shadow) ? fire : shadow; + if (maximum < 0) + maximum = 0; + float bonusAP = maximum * 0.57f; + + amount += bonusAP; + + // Glyph of felguard + if (pet->GetEntry() == ENTRY_FELGUARD) + { + if (AuraEffect* aurEffect = owner->GetAuraEffect(56246, EFFECT_0)) + { + float base_attPower = pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT); + amount += CalculatePctN(amount+base_attPower, aurEffect->GetAmount()); + } + } + } + } + + void CalculateDamageDoneAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + //the damage bonus used for pets is either fire or shadow damage, whatever is higher + int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE); + int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW); + int32 maximum = (fire > shadow) ? fire : shadow; + float bonusDamage = 0.0f; + + if (maximum > 0) + bonusDamage = maximum * 0.15f; + + amount += bonusDamage; + } + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_warl_pet_scaling_01_AuraScript::RemoveEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_warl_pet_scaling_01_AuraScript::ApplyEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_01_AuraScript::CalculateStaminaAmount, EFFECT_0, SPELL_AURA_MOD_STAT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_01_AuraScript::CalculateAttackPowerAmount, EFFECT_1, SPELL_AURA_MOD_ATTACK_POWER); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_01_AuraScript::CalculateDamageDoneAmount, EFFECT_2, SPELL_AURA_MOD_DAMAGE_DONE); + } + + private: + uint32 _tempBonus; + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_01_AuraScript(); + } +}; + +class spell_warl_pet_scaling_02 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_02() : SpellScriptLoader("spell_warl_pet_scaling_02") { } + + class spell_warl_pet_scaling_02_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_02_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + _tempBonus = 0; + return true; + } + + void CalculateIntellectAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetStat(STAT_INTELLECT), 30); + + amount += ownerBonus; + _tempBonus = ownerBonus; + } + } + + void ApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (_tempBonus) + { + PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(pet->GetEntry(), pet->getLevel()); + uint32 manaMod = 0; + uint32 baseMana = pInfo->mana; + switch (pet->GetEntry()) + { + case ENTRY_IMP: + manaMod = uint32(_tempBonus * 4.9f); + break; + case ENTRY_VOIDWALKER: + case ENTRY_SUCCUBUS: + case ENTRY_FELHUNTER: + case ENTRY_FELGUARD: + manaMod = uint32(_tempBonus * 11.5f); + break; + default: + manaMod = 0; + break; + } + if (manaMod) + pet->ToPet()->SetCreateMana(baseMana + manaMod); + } + } + + void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + { + PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(pet->GetEntry(), pet->getLevel()); + pet->ToPet()->SetCreateMana(pInfo->mana); + } + } + + void CalculateArmorAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetArmor(), 35); + amount += ownerBonus; + } + } + + void CalculateFireResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_FIRE), 40); + amount += ownerBonus; + } + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_warl_pet_scaling_02_AuraScript::RemoveEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_warl_pet_scaling_02_AuraScript::ApplyEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_02_AuraScript::CalculateIntellectAmount, EFFECT_0, SPELL_AURA_MOD_STAT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_02_AuraScript::CalculateArmorAmount, EFFECT_1, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_02_AuraScript::CalculateFireResistanceAmount, EFFECT_2, SPELL_AURA_MOD_RESISTANCE); + } + + private: + uint32 _tempBonus; + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_02_AuraScript(); + } +}; + +class spell_warl_pet_scaling_03 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_03() : SpellScriptLoader("spell_warl_pet_scaling_03") { } + + class spell_warl_pet_scaling_03_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_03_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateFrostResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_FROST), 40); + amount += ownerBonus; + } + } + + void CalculateArcaneResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_ARCANE), 40); + amount += ownerBonus; + } + } + + void CalculateNatureResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_NATURE), 40); + amount += ownerBonus; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_03_AuraScript::CalculateFrostResistanceAmount, EFFECT_0, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_03_AuraScript::CalculateArcaneResistanceAmount, EFFECT_1, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_03_AuraScript::CalculateNatureResistanceAmount, EFFECT_2, SPELL_AURA_MOD_RESISTANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_03_AuraScript(); + } +}; + + +class spell_warl_pet_scaling_04 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_04() : SpellScriptLoader("spell_warl_pet_scaling_04") { } + + class spell_warl_pet_scaling_04_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_04_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateShadowResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_SHADOW), 40); + amount += ownerBonus; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_04_AuraScript::CalculateShadowResistanceAmount, EFFECT_0, SPELL_AURA_MOD_RESISTANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_04_AuraScript(); + } +}; + +class spell_warl_pet_scaling_05 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_05() : SpellScriptLoader("spell_warl_pet_scaling_05") { } + + class spell_warl_pet_scaling_05_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_05_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void CalculateAmountExpertise(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float Expertise = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + Expertise += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + Expertise += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(Expertise); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_05_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_05_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_05_AuraScript::CalculateAmountExpertise, EFFECT_2, SPELL_AURA_MOD_EXPERTISE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_05_AuraScript(); + } +}; + +class spell_warl_pet_passive : public SpellScriptLoader +{ +public: + spell_warl_pet_passive() : SpellScriptLoader("spell_warl_pet_passive") { } + + class spell_warl_pet_passive_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_passive_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountCritSpell(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritSpell = 0.0f; + // Crit from Intellect + CritSpell += owner->GetSpellCritFromIntellect(); + // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE + CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit spell from spell crit ratings + CritSpell += owner->GetRatingBonusValue(CR_CRIT_SPELL); + + if (AuraApplication* improvedDemonicTacticsApp = owner->GetAuraApplicationOfRankedSpell(54347)) + if (Aura* improvedDemonicTactics = improvedDemonicTacticsApp->GetBase()) + if (AuraEffect* improvedDemonicTacticsEffect = improvedDemonicTactics->GetEffect(EFFECT_0)) + amount += CalculatePctN(CritSpell, improvedDemonicTacticsEffect->GetAmount()); + } + } + + void CalculateAmountCritMelee(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritMelee = 0.0f; + // Crit from Agility + CritMelee += owner->GetMeleeCritFromAgility(); + // Increase crit from SPELL_AURA_MOD_WEAPON_CRIT_PERCENT + CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit melee from melee crit ratings + CritMelee += owner->GetRatingBonusValue(CR_CRIT_MELEE); + + if (AuraApplication* improvedDemonicTacticsApp = owner->GetAuraApplicationOfRankedSpell(54347)) + if (Aura* improvedDemonicTactics = improvedDemonicTacticsApp->GetBase()) + if (AuraEffect* improvedDemonicTacticsEffect = improvedDemonicTactics->GetEffect(EFFECT_0)) + amount += CalculatePctN(CritMelee, improvedDemonicTacticsEffect->GetAmount()); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_AuraScript::CalculateAmountCritSpell, EFFECT_0, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_AuraScript::CalculateAmountCritMelee, EFFECT_1, SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_passive_AuraScript(); + } +}; +// this doesnt actually fit in here +class spell_warl_pet_passive_damage_done : public SpellScriptLoader +{ +public: + spell_warl_pet_passive_damage_done() : SpellScriptLoader("spell_warl_pet_passive_damage_done") { } + + class spell_warl_pet_passive_damage_done_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_passive_damage_done_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountDamageDone(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + switch (GetCaster()->GetEntry()) + { + case ENTRY_VOIDWALKER: + amount += -16; + break; + case ENTRY_FELHUNTER: + amount += -20; + break; + case ENTRY_SUCCUBUS: + case ENTRY_FELGUARD: + amount += 5; + break; + } + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_damage_done_AuraScript::CalculateAmountDamageDone, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_damage_done_AuraScript::CalculateAmountDamageDone, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_passive_damage_done_AuraScript(); + } +}; + +class spell_warl_pet_passive_voidwalker : public SpellScriptLoader +{ +public: + spell_warl_pet_passive_voidwalker() : SpellScriptLoader("spell_warl_pet_passive_voidwalker") { } + + class spell_warl_pet_passive_voidwalker_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_passive_voidwalker_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + if (AuraEffect* aurEffect = owner->GetAuraEffect(SPELL_WARLOCK_GLYPH_OF_VOIDWALKER, EFFECT_0)) + amount += aurEffect->GetAmount(); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_voidwalker_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_passive_voidwalker_AuraScript(); + } +}; + + +class spell_sha_pet_scaling_04 : public SpellScriptLoader +{ +public: + spell_sha_pet_scaling_04() : SpellScriptLoader("spell_sha_pet_scaling_04") { } + + class spell_sha_pet_scaling_04_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_pet_scaling_04_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + // Increase hit melee from meele hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_MELEE); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_sha_pet_scaling_04_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_sha_pet_scaling_04_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_sha_pet_scaling_04_AuraScript(); + } +}; + +class spell_hun_pet_scaling_01 : public SpellScriptLoader +{ +public: + spell_hun_pet_scaling_01() : SpellScriptLoader("spell_hun_pet_scaling_01") { } + + class spell_hun_pet_scaling_01_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_scaling_01_AuraScript); + + void CalculateStaminaAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float mod = 0.45f; + float ownerBonus = 0.0f; + + PetSpellMap::const_iterator itr = (pet->ToPet()->m_spells.find(62758)); // Wild Hunt rank 1 + if (itr == pet->ToPet()->m_spells.end()) + itr = pet->ToPet()->m_spells.find(62762); // Wild Hunt rank 2 + + if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + AddPctN(mod, spellInfo->Effects[EFFECT_0].CalcValue()); + } + + ownerBonus = owner->GetStat(STAT_STAMINA)*mod; + + amount += ownerBonus; + } + } + + void ApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (_tempHealth) + pet->SetHealth(_tempHealth); + } + + void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + _tempHealth = pet->GetHealth(); + } + + void CalculateAttackPowerAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float mod = 1.0f; //Hunter contribution modifier + float bonusAP = 0.0f; + + PetSpellMap::const_iterator itr = (pet->ToPet()->m_spells.find(62758)); // Wild Hunt rank 1 + if (itr == pet->ToPet()->m_spells.end()) + itr = pet->ToPet()->m_spells.find(62762); // Wild Hunt rank 2 + + if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + mod += CalculatePctN(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); + } + + bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod; + + amount += bonusAP; + } + } + + void CalculateDamageDoneAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float mod = 1.0f; //Hunter contribution modifier + float bonusDamage = 0.0f; + + PetSpellMap::const_iterator itr = (pet->ToPet()->m_spells.find(62758)); // Wild Hunt rank 1 + if (itr == pet->ToPet()->m_spells.end()) + itr = pet->ToPet()->m_spells.find(62762); // Wild Hunt rank 2 + + if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + mod += CalculatePctN(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); + } + + bonusDamage = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod; + + amount += bonusDamage; + } + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_hun_pet_scaling_01_AuraScript::RemoveEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_hun_pet_scaling_01_AuraScript::ApplyEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_01_AuraScript::CalculateStaminaAmount, EFFECT_0, SPELL_AURA_MOD_STAT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_01_AuraScript::CalculateAttackPowerAmount, EFFECT_1, SPELL_AURA_MOD_ATTACK_POWER); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_01_AuraScript::CalculateDamageDoneAmount, EFFECT_2, SPELL_AURA_MOD_DAMAGE_DONE); + } + + private: + uint32 _tempHealth; + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_scaling_01_AuraScript(); + } +}; + +class spell_hun_pet_scaling_02 : public SpellScriptLoader +{ +public: + spell_hun_pet_scaling_02() : SpellScriptLoader("spell_hun_pet_scaling_02") { } + + class spell_hun_pet_scaling_02_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_scaling_02_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateFrostResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_FROST), 40); + + amount += ownerBonus; + } + } + + void CalculateFireResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_FIRE), 40); + + amount += ownerBonus; + } + } + + void CalculateNatureResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_NATURE), 40); + + amount += ownerBonus; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_02_AuraScript::CalculateFrostResistanceAmount, EFFECT_1, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_02_AuraScript::CalculateFireResistanceAmount, EFFECT_0, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_02_AuraScript::CalculateNatureResistanceAmount, EFFECT_2, SPELL_AURA_MOD_RESISTANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_scaling_02_AuraScript(); + } +}; + +class spell_hun_pet_scaling_03 : public SpellScriptLoader +{ +public: + spell_hun_pet_scaling_03() : SpellScriptLoader("spell_hun_pet_scaling_03") { } + + class spell_hun_pet_scaling_03_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_scaling_03_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateShadowResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_SHADOW), 40); + + amount += ownerBonus; + } + } + + void CalculateArcaneResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_ARCANE), 40); + + amount += ownerBonus; + } + } + + void CalculateArmorAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetArmor(), 35); + + amount += ownerBonus; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_03_AuraScript::CalculateShadowResistanceAmount, EFFECT_0, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_03_AuraScript::CalculateArcaneResistanceAmount, EFFECT_1, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_03_AuraScript::CalculateArmorAmount, EFFECT_2, SPELL_AURA_MOD_RESISTANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_scaling_03_AuraScript(); + } +}; + +class spell_hun_pet_scaling_04 : public SpellScriptLoader +{ +public: + spell_hun_pet_scaling_04() : SpellScriptLoader("spell_hun_pet_scaling_04") { } + + class spell_hun_pet_scaling_04_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_scaling_04_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + // Increase hit melee from meele hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_MELEE); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void CalculateAmountExpertise(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float Expertise = 0.0f; + // Increase hit from SPELL_AURA_MOD_EXPERTISE + Expertise += owner->GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE); + // Increase Expertise from Expertise ratings + Expertise += owner->GetRatingBonusValue(CR_EXPERTISE); + + amount += int32(Expertise); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_04_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_04_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_04_AuraScript::CalculateAmountExpertise, EFFECT_2, SPELL_AURA_MOD_EXPERTISE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_scaling_04_AuraScript(); + } +}; + +class spell_hun_pet_passive_crit : public SpellScriptLoader +{ +public: + spell_hun_pet_passive_crit() : SpellScriptLoader("spell_hun_pet_passive_crit") { } + + class spell_hun_pet_passive_crit_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_passive_crit_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountCritSpell(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritSpell = 0.0f; + // Crit from Intellect + // CritSpell += owner->GetSpellCritFromIntellect(); + // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE + // CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + // CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit spell from spell crit ratings + // CritSpell += owner->GetRatingBonusValue(CR_CRIT_SPELL); + + amount += (CritSpell*0.8f); + } + } + + void CalculateAmountCritMelee(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritMelee = 0.0f; + // Crit from Agility + // CritMelee += owner->GetMeleeCritFromAgility(); + // Increase crit from SPELL_AURA_MOD_WEAPON_CRIT_PERCENT + // CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + // CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit melee from melee crit ratings + // CritMelee += owner->GetRatingBonusValue(CR_CRIT_MELEE); + + amount += (CritMelee*0.8f); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_passive_crit_AuraScript::CalculateAmountCritSpell, EFFECT_1, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_passive_crit_AuraScript::CalculateAmountCritMelee, EFFECT_0, SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_passive_crit_AuraScript(); + } +}; + +class spell_hun_pet_passive_damage_done : public SpellScriptLoader +{ +public: + spell_hun_pet_passive_damage_done() : SpellScriptLoader("spell_hun_pet_passive_damage_done") { } + + class spell_hun_pet_passive_damage_done_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_passive_damage_done_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountDamageDone(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // Pet's base damage changes depending on happiness + if (GetCaster()->isPet() && GetCaster()->ToPet()->isHunterPet()) + { + switch (GetCaster()->ToPet()->GetHappinessState()) + { + case HAPPY: + // 125% of normal damage + amount += 25.0f; + break; + case CONTENT: + // 100% of normal damage, nothing to modify + break; + case UNHAPPY: + // 75% of normal damage + amount += -25.0f; + break; + } + } + // Cobra Reflexes + if (AuraEffect* cobraReflexes = GetCaster()->GetAuraEffectOfRankedSpell(61682, EFFECT_0)) + amount -= cobraReflexes->GetAmount(); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_passive_damage_done_AuraScript::CalculateAmountDamageDone, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_passive_damage_done_AuraScript(); + } +}; + +class spell_hun_animal_handler : public SpellScriptLoader +{ +public: + spell_hun_animal_handler() : SpellScriptLoader("spell_hun_animal_handler") { } + + class spell_hun_animal_handler_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_animal_handler_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountDamageDone(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + if (AuraEffect* aurEffect = owner->GetAuraEffectOfRankedSpell(SPELL_HUNTER_ANIMAL_HANDLER, EFFECT_1)) + amount = aurEffect->GetAmount(); + else + amount = 0; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_animal_handler_AuraScript::CalculateAmountDamageDone, EFFECT_0, SPELL_AURA_MOD_ATTACK_POWER_PCT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_animal_handler_AuraScript(); + } +}; + + +class spell_dk_avoidance_passive : public SpellScriptLoader +{ +public: + spell_dk_avoidance_passive() : SpellScriptLoader("spell_dk_avoidance_passive") { } + + class spell_dk_avoidance_passive_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_avoidance_passive_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAvoidanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (Unit* owner = pet->GetOwner()) + + // Army of the dead ghoul + if (pet->GetEntry() == ENTRY_ARMY_OF_THE_DEAD_GHOUL) + amount = -90; + // Night of the dead + else if ( Aura * aur = owner->GetAuraOfRankedSpell(SPELL_NIGHT_OF_THE_DEAD)) + amount = aur->GetSpellInfo()->Effects[EFFECT_2].CalcValue(); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_avoidance_passive_AuraScript::CalculateAvoidanceAmount, EFFECT_0, SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_avoidance_passive_AuraScript(); + } +}; + +class spell_dk_pet_scaling_01 : public SpellScriptLoader +{ +public: + spell_dk_pet_scaling_01() : SpellScriptLoader("spell_dk_pet_scaling_01") { } + + class spell_dk_pet_scaling_01_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_pet_scaling_01_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + _tempHealth = 0; + return true; + } + + void CalculateStaminaAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (pet->isGuardian()) + { + if (Unit* owner = pet->GetOwner()) + { + float mod = 0.3f; + + // Ravenous Dead. Check just if owner has Ravenous Dead since it's effect is not an aura + if (AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0)) + { + mod += aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()/100; // Ravenous Dead edits the original scale + } + // Glyph of the Ghoul + if (AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_DEATH_KNIGHT_GLYPH_OF_GHOUL, 0)) + mod += aurEff->GetAmount()/100; + + float ownerBonus = float(owner->GetStat(STAT_STAMINA)) * mod; + amount += ownerBonus; + } + } + } + } + + void ApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (_tempHealth) + pet->SetHealth(_tempHealth); + } + + void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + _tempHealth = pet->GetHealth(); + } + + void CalculateStrengthAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isGuardian()) + return; + + Unit* owner = pet->GetOwner(); + if (!owner) + return; + + float mod = 0.7f; + + // Ravenous Dead + AuraEffect const* aurEff = NULL; + // Check just if owner has Ravenous Dead since it's effect is not an aura + aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0); + if (aurEff) + { + mod += CalculatePctN(mod, aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()); // Ravenous Dead edits the original scale + } + // Glyph of the Ghoul + aurEff = owner->GetAuraEffect(58686, 0); + if (aurEff) + mod += CalculatePctN(1.0f, aurEff->GetAmount()); // Glyph of the Ghoul adds a flat value to the scale mod + float ownerBonus = float(owner->GetStat(STAT_STRENGTH)) * mod; + amount += ownerBonus; + } + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_dk_pet_scaling_01_AuraScript::RemoveEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_dk_pet_scaling_01_AuraScript::ApplyEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_01_AuraScript::CalculateStaminaAmount, EFFECT_0, SPELL_AURA_MOD_STAT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_01_AuraScript::CalculateStrengthAmount, EFFECT_1, SPELL_AURA_MOD_STAT); + } + + private: + uint32 _tempHealth; + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_pet_scaling_01_AuraScript(); + } +}; + +class spell_dk_pet_scaling_02 : public SpellScriptLoader +{ +public: + spell_dk_pet_scaling_02() : SpellScriptLoader("spell_dk_pet_scaling_02") { } + + class spell_dk_pet_scaling_02_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_pet_scaling_02_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHaste(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HasteMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HasteMelee += (1-owner->m_modAttackSpeedPct[BASE_ATTACK])*100; + + amount += int32(HasteMelee); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_02_AuraScript::CalculateAmountMeleeHaste, EFFECT_1, SPELL_AURA_MELEE_SLOW); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_pet_scaling_02_AuraScript(); + } +}; + +class spell_dk_pet_scaling_03 : public SpellScriptLoader +{ +public: + spell_dk_pet_scaling_03() : SpellScriptLoader("spell_dk_pet_scaling_03") { } + + class spell_dk_pet_scaling_03_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_pet_scaling_03_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + // Increase hit melee from meele hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_MELEE); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_03_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_03_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_pet_scaling_03_AuraScript(); + } +}; + +class spell_dk_rune_weapon_scaling_02 : public SpellScriptLoader +{ +public: + spell_dk_rune_weapon_scaling_02() : SpellScriptLoader("spell_dk_rune_weapon_scaling_02") { } + + class spell_dk_rune_weapon_scaling_02_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_rune_weapon_scaling_02_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateDamageDoneAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + Unit* owner = pet->GetOwner(); + if (!owner) + return; + + if (pet->isGuardian()) + ((Guardian*)pet)->SetBonusDamage(owner->GetTotalAttackPowerValue(BASE_ATTACK)); + + amount += owner->CalculateDamage(BASE_ATTACK, true, true);; + } + } + + void CalculateAmountMeleeHaste(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HasteMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HasteMelee += (1-owner->m_modAttackSpeedPct[BASE_ATTACK])*100; + + amount += int32(HasteMelee); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_rune_weapon_scaling_02_AuraScript::CalculateDamageDoneAmount, EFFECT_0, SPELL_AURA_MOD_DAMAGE_DONE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_rune_weapon_scaling_02_AuraScript::CalculateAmountMeleeHaste, EFFECT_1, SPELL_AURA_MELEE_SLOW); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_rune_weapon_scaling_02_AuraScript(); + } +}; + +void AddSC_pet_spell_scripts() +{ + new spell_gen_pet_calculate(); +} diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index 790a9d0f814..308c7f9afa3 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -1245,6 +1245,36 @@ class go_veil_skith_cage : public GameObjectScript } }; +/*###### +## go_frostblade_shrine +######*/ + +enum TheCleansing +{ + QUEST_THE_CLEANSING_HORDE = 11317, + QUEST_THE_CLEANSING_ALLIANCE = 11322, + SPELL_CLEANSING_SOUL = 43351, + SPELL_RECENT_MEDITATION = 61720, +}; + +class go_frostblade_shrine : public GameObjectScript +{ +public: + go_frostblade_shrine() : GameObjectScript("go_frostblade_shrine") { } + + bool OnGossipHello(Player* player, GameObject* go) + { + if (!player->HasAura(SPELL_RECENT_MEDITATION)) + if (player->GetQuestStatus(QUEST_THE_CLEANSING_HORDE) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_THE_CLEANSING_ALLIANCE) == QUEST_STATUS_INCOMPLETE) + { + go->UseDoorOrButton(10); + player->CastSpell(player, SPELL_CLEANSING_SOUL); + player->SetStandState(UNIT_STAND_STATE_SIT); + } + return true; + } +}; + void AddSC_go_scripts() { new go_cat_figurine; @@ -1285,4 +1315,5 @@ void AddSC_go_scripts() new go_gjalerbron_cage; new go_large_gjalerbron_cage; new go_veil_skith_cage; + new go_frostblade_shrine; } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index c9aeea07382..57a65423b6f 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -47,6 +47,7 @@ EndContentData */ #include "ObjectMgr.h" #include "ScriptMgr.h" #include "World.h" +#include "PetAI.h" /*######## # npc_air_force_bots @@ -2100,16 +2101,18 @@ class npc_shadowfiend : public CreatureScript public: npc_shadowfiend() : CreatureScript("npc_shadowfiend") { } - struct npc_shadowfiendAI : public ScriptedAI + struct npc_shadowfiendAI : public PetAI { - npc_shadowfiendAI(Creature* creature) : ScriptedAI(creature) {} + npc_shadowfiendAI(Creature* creature) : PetAI(creature) {} - void DamageTaken(Unit* /*killer*/, uint32& damage) + void JustDied(Unit* killer) { if (me->isSummon()) if (Unit* owner = me->ToTempSummon()->GetSummoner()) - if (owner->HasAura(GLYPH_OF_SHADOWFIEND) && damage >= me->GetHealth()) + if (owner->HasAura(GLYPH_OF_SHADOWFIEND)) owner->CastSpell(owner, GLYPH_OF_SHADOWFIEND_MANA, true); + + PetAI::JustDied(killer); } }; diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index d315c6417ea..89cc6ab25e5 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -314,18 +314,17 @@ void CharacterDatabaseConnection::DoPrepareStatements() PREPARE_STATEMENT(CHAR_DEL_OLD_CORPSES, "DELETE FROM corpse WHERE corpseType = 0 OR time < (UNIX_TIMESTAMP(NOW()) - ?)", CONNECTION_ASYNC) // Creature respawn - PREPARE_STATEMENT(CHAR_SEL_CREATURE_RESPAWNS, "SELECT guid, respawnTime, instanceId FROM creature_respawn", CONNECTION_SYNCH) - PREPARE_STATEMENT(CHAR_REP_CREATURE_RESPAWN, "REPLACE INTO creature_respawn (guid, respawnTime, instanceId) VALUES (?, ?, ?)", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN, "DELETE FROM creature_respawn WHERE guid = ? AND instanceId = ?", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN_BY_GUID, "DELETE FROM creature_respawn WHERE guid = ?", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE, "DELETE FROM creature_respawn WHERE instanceId = ?", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_SEL_CREATURE_RESPAWNS, "SELECT guid, respawnTime FROM creature_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH) + PREPARE_STATEMENT(CHAR_REP_CREATURE_RESPAWN, "REPLACE INTO creature_respawn (guid, respawnTime, mapId, instanceId) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN, "DELETE FROM creature_respawn WHERE guid = ? AND mapId = ? AND instanceId = ?", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE, "DELETE FROM creature_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC) PREPARE_STATEMENT(CHAR_SEL_MAX_CREATURE_RESPAWNS, "SELECT MAX(respawnTime), instanceId FROM creature_respawn WHERE instanceId > 0 GROUP BY instanceId", CONNECTION_SYNCH) // Gameobject respawn - PREPARE_STATEMENT(CHAR_SEL_GO_RESPAWNS, "SELECT guid, respawnTime, instanceId FROM gameobject_respawn", CONNECTION_SYNCH) - PREPARE_STATEMENT(CHAR_REP_GO_RESPAWN, "REPLACE INTO gameobject_respawn (guid, respawnTime, instanceId) VALUES (?, ?, ?)", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN, "DELETE FROM gameobject_respawn WHERE guid = ? AND instanceId = ?", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE instanceId = ?", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_SEL_GO_RESPAWNS, "SELECT guid, respawnTime FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH) + PREPARE_STATEMENT(CHAR_REP_GO_RESPAWN, "REPLACE INTO gameobject_respawn (guid, respawnTime, mapId, instanceId) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN, "DELETE FROM gameobject_respawn WHERE guid = ? AND mapId = ? AND instanceId = ?", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC) // GM Tickets PREPARE_STATEMENT(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed FROM gm_tickets", CONNECTION_SYNCH) diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index cf6bbd7bdfa..e1530f36e44 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -296,7 +296,6 @@ enum CharacterDatabaseStatements CHAR_SEL_CREATURE_RESPAWNS, CHAR_REP_CREATURE_RESPAWN, CHAR_DEL_CREATURE_RESPAWN, - CHAR_DEL_CREATURE_RESPAWN_BY_GUID, CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE, CHAR_SEL_MAX_CREATURE_RESPAWNS, diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index db167fb86fb..cc4c4a555c2 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -483,12 +483,13 @@ LogFileLevel = 0 DebugLogMask = 0 # -# WorldLogFile -# Description: Packet logging file for the world server. -# Example: "World.log" - (Enabled) +# PacketLogFile +# Description: Binary packet logging file for the world server. +# Filename extension must be .bin to be parsable with WowPacketParser. +# Example: "World.bin" - (Enabled) # Default: "" - (Disabled) -WorldLogFile = "" +PacketLogFile = "" # # DBErrorLogFile @@ -2024,17 +2025,17 @@ Visibility.GroupMode = 1 # Visibility.Distance.Instances # Visibility.Distance.BGArenas # Description: Visibility distance to see other players or gameobjects. -# Visibility on continents on retail ~90 yards. In BG/Arenas ~180. -# For instances default ~120. -# Max limited by active player zone: ~ 333 +# Visibility on continents on retail ~90 yards. In BG/Arenas ~533. +# For instances default ~170. +# Max limited by grid size: 533.33333 # Min limit is max aggro radius (45) * Rate.Creature.Aggro # Default: 90 - (Visibility.Distance.Continents) -# 120 - (Visibility.Distance.Instances) -# 180 - (Visibility.Distance.BGArenas) +# 170 - (Visibility.Distance.Instances) +# 533 - (Visibility.Distance.BGArenas) Visibility.Distance.Continents = 90 -Visibility.Distance.Instances = 120 -Visibility.Distance.BGArenas = 180 +Visibility.Distance.Instances = 170 +Visibility.Distance.BGArenas = 533 # # Visibility.Notify.Period.OnContinents diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 1505f2c2cee..d64276c6363 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -48,9 +48,9 @@ char output_path[128] = "."; char input_path[128] = "."; uint32 maxAreaId = 0; -//************************************************** +// ************************************************** // Extractor options -//************************************************** +// ************************************************** enum Extract { EXTRACT_MAP = 1, @@ -221,7 +221,7 @@ uint32 ReadMapDBC() map_ids[x].id = dbc.getRecord(x).getUInt(0); strcpy(map_ids[x].name, dbc.getRecord(x).getString(1)); } - printf("Done! (%u maps loaded)\n", map_count); + printf("Done! (%zu maps loaded)\n", map_count); return map_count; } @@ -246,7 +246,7 @@ void ReadAreaTableDBC() maxAreaId = dbc.getMaxId(); - printf("Done! (%u areas loaded)\n", area_count); + printf("Done! (%zu areas loaded)\n", area_count); } void ReadLiquidTypeTableDBC() @@ -267,7 +267,7 @@ void ReadLiquidTypeTableDBC() for(uint32 x = 0; x < liqTypeCount; ++x) LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); - printf("Done! (%u LiqTypes loaded)\n", liqTypeCount); + printf("Done! (%zu LiqTypes loaded)\n", liqTypeCount); } // @@ -572,7 +572,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, // Try store as packed in uint16 or uint8 values if (!(heightHeader.flags & MAP_HEIGHT_NO_HEIGHT)) { - float step; + float step = 0; // Try Store as uint values if (CONF_allow_float_to_int) { |