diff options
Diffstat (limited to 'src')
171 files changed, 3227 insertions, 2193 deletions
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index 28e9f324c19..d1b2b614037 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -178,42 +178,44 @@ extern int main(int argc, char** argv) Handler.register_handler(SIGINT, &SignalINT); Handler.register_handler(SIGTERM, &SignalTERM); +#if defined(_WIN32) || defined(__linux__) + ///- Handle affinity for multiple processors and process priority uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0); bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false); #ifdef _WIN32 // Windows + + HANDLE hProcess = GetCurrentProcess(); + if (affinity > 0) { - HANDLE hProcess = GetCurrentProcess(); - - if (affinity > 0) - { - ULONG_PTR appAff; - ULONG_PTR sysAff; - - if (GetProcessAffinityMask(hProcess, &appAff, &sysAff)) - { - ULONG_PTR currentAffinity = affinity & appAff; // remove non accessible processors - - if (!currentAffinity) - TC_LOG_ERROR("server.authserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the authserver. Accessible processors bitmask (hex): %x", affinity, appAff); - else if (SetProcessAffinityMask(hProcess, currentAffinity)) - TC_LOG_INFO("server.authserver", "Using processors (bitmask, hex): %x", currentAffinity); - else - TC_LOG_ERROR("server.authserver", "Can't set used processors (hex): %x", currentAffinity); - } - } - - if (highPriority) + ULONG_PTR appAff; + ULONG_PTR sysAff; + + if (GetProcessAffinityMask(hProcess, &appAff, &sysAff)) { - if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) - TC_LOG_INFO("server.authserver", "authserver process priority class set to HIGH"); + // remove non accessible processors + ULONG_PTR currentAffinity = affinity & appAff; + + if (!currentAffinity) + TC_LOG_ERROR("server.authserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the authserver. Accessible processors bitmask (hex): %x", affinity, appAff); + else if (SetProcessAffinityMask(hProcess, currentAffinity)) + TC_LOG_INFO("server.authserver", "Using processors (bitmask, hex): %x", currentAffinity); else - TC_LOG_ERROR("server.authserver", "Can't set authserver process priority class."); + TC_LOG_ERROR("server.authserver", "Can't set used processors (hex): %x", currentAffinity); } } -#elif __linux__ // Linux - + + if (highPriority) + { + if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) + TC_LOG_INFO("server.authserver", "authserver process priority class set to HIGH"); + else + TC_LOG_ERROR("server.authserver", "Can't set authserver process priority class."); + } + +#else // Linux + if (affinity > 0) { cpu_set_t mask; @@ -240,7 +242,8 @@ extern int main(int argc, char** argv) else TC_LOG_INFO("server.authserver", "authserver process priority class set to %i", getpriority(PRIO_PROCESS, 0)); } - + +#endif #endif // maximum counter for next ping diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp index 67d3975815f..c7bb600024a 100644 --- a/src/server/authserver/Server/AuthSocket.cpp +++ b/src/server/authserver/Server/AuthSocket.cpp @@ -321,9 +321,7 @@ bool AuthSocket::_HandleLogonChallenge() socket().recv((char *)&buf[0], 4); -#if TRINITY_ENDIAN == TRINITY_BIGENDIAN - EndianConvert(*((uint16*)(buf[0]))); -#endif + EndianConvertPtr<uint16>(&buf[0]); uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; TC_LOG_DEBUG("server.authserver", "[AuthChallenge] got header, body is %#04x bytes", remaining); @@ -343,15 +341,13 @@ bool AuthSocket::_HandleLogonChallenge() // BigEndian code, nop in little endian case // size already converted -#if TRINITY_ENDIAN == TRINITY_BIGENDIAN - EndianConvert(*((uint32*)(&ch->gamename[0]))); + EndianConvertPtr<uint32>(&ch->gamename[0]); EndianConvert(ch->build); - EndianConvert(*((uint32*)(&ch->platform[0]))); - EndianConvert(*((uint32*)(&ch->os[0]))); - EndianConvert(*((uint32*)(&ch->country[0]))); + EndianConvertPtr<uint32>(&ch->platform[0]); + EndianConvertPtr<uint32>(&ch->os[0]); + EndianConvertPtr<uint32>(&ch->country[0]); EndianConvert(ch->timezone_bias); EndianConvert(ch->ip); -#endif ByteBuffer pkt; @@ -397,7 +393,7 @@ bool AuthSocket::_HandleLogonChallenge() bool locked = false; if (fields[2].GetUInt8() == 1) // if ip is locked { - TC_LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), fields[3].GetCString()); + TC_LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), fields[4].GetCString()); TC_LOG_DEBUG("server.authserver", "[AuthChallenge] Player address is '%s'", ip_address.c_str()); if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0) @@ -783,9 +779,7 @@ bool AuthSocket::_HandleReconnectChallenge() socket().recv((char *)&buf[0], 4); -#if TRINITY_ENDIAN == TRINITY_BIGENDIAN - EndianConvert(*((uint16*)(buf[0]))); -#endif + EndianConvertPtr<uint16>(&buf[0]); uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; TC_LOG_DEBUG("server.authserver", "[ReconnectChallenge] got header, body is %#04x bytes", remaining); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index bd51fe0a85b..49beb0ae86f 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -76,6 +76,7 @@ SmartScript::SmartScript() goOrigGUID = 0; mLastInvoker = 0; mScriptType = SMART_SCRIPT_TYPE_CREATURE; + isProcessingTimedActionList = false; } SmartScript::~SmartScript() @@ -3253,6 +3254,7 @@ void SmartScript::OnUpdate(uint32 const diff) bool needCleanup = true; if (!mTimedActionList.empty()) { + isProcessingTimedActionList = true; for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i) { if ((*i).enableTimed) @@ -3261,6 +3263,8 @@ void SmartScript::OnUpdate(uint32 const diff) needCleanup = false; } } + + isProcessingTimedActionList = false; } if (needCleanup) mTimedActionList.clear(); @@ -3502,6 +3506,14 @@ Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly) void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry) { + //do NOT clear mTimedActionList if it's being iterated because it will invalidate the iterator and delete + // any SmartScriptHolder contained like the "e" parameter passed to this function + if (isProcessingTimedActionList) + { + TC_LOG_ERROR("scripts.ai", "Entry %d SourceType %u Event %u Action %u is trying to overwrite timed action list from a timed action, this is not allowed!.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType()); + return; + } + mTimedActionList.clear(); mTimedActionList = sSmartScriptMgr->GetScript(entry, SMART_SCRIPT_TYPE_TIMED_ACTIONLIST); if (mTimedActionList.empty()) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 2e1068d1bff..244728a3037 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -118,7 +118,7 @@ class SmartScript smart = false; if (!smart) - TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: %u Entry: %u) is not using SmartAI, action skipped to prevent crash.", c ? c->GetDBTableGUIDLow() : (me ? me->GetDBTableGUIDLow() : 0), c ? c->GetEntry() : (me ? me->GetEntry() : 0)); + TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: %u Entry: %u) is not using SmartAI, action called by Creature (GUID: %u Entry: %u) skipped to prevent crash.", c ? c->GetDBTableGUIDLow() : 0, c ? c->GetEntry() : 0, me ? me->GetDBTableGUIDLow() : 0, me ? me->GetEntry() : 0); return smart; } @@ -132,7 +132,7 @@ class SmartScript if (!go || go->GetAIName() != "SmartGameObjectAI") smart = false; if (!smart) - TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: %u Entry: %u) is not using SmartGameObjectAI, action skipped to prevent crash.", g ? g->GetDBTableGUIDLow() : (go ? go->GetDBTableGUIDLow() : 0), g ? g->GetEntry() : (go ? go->GetEntry() : 0)); + TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: %u Entry: %u) is not using SmartGameObjectAI, action called by GameObject (GUID: %u Entry: %u) skipped to prevent crash.", g ? g->GetDBTableGUIDLow() : 0, g ? g->GetEntry() : 0, go ? go->GetDBTableGUIDLow() : 0, go ? go->GetEntry() : 0); return smart; } @@ -222,6 +222,7 @@ class SmartScript SmartAIEventList mEvents; SmartAIEventList mInstallEvents; SmartAIEventList mTimedActionList; + bool isProcessingTimedActionList; Creature* me; uint64 meOrigGUID; GameObject* go; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 543cb9235d3..c6b73a468d2 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -766,6 +766,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); return false; } + if (!IsMinMaxValid(e, e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax)) return false; break; @@ -886,6 +887,12 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; break; } + case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST: + { + if (!IsMinMaxValid(e, e.action.randTimedActionList.entry1, e.action.randTimedActionList.entry2)) + return false; + break; + } case SMART_ACTION_SET_POWER: case SMART_ACTION_ADD_POWER: case SMART_ACTION_REMOVE_POWER: @@ -985,7 +992,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_SIMPLE_TALK: case SMART_ACTION_CROSS_CAST: case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: - case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST: case SMART_ACTION_RANDOM_MOVE: case SMART_ACTION_SET_UNIT_FIELD_BYTES_1: case SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 9ba5ccc578e..265df8e2ac4 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -52,9 +52,12 @@ enum SMART_EVENT_PHASE SMART_EVENT_PHASE_4 = 4, SMART_EVENT_PHASE_5 = 5, SMART_EVENT_PHASE_6 = 6, - SMART_EVENT_PHASE_MAX = 7, + SMART_EVENT_PHASE_7 = 7, + SMART_EVENT_PHASE_8 = 8, + SMART_EVENT_PHASE_9 = 9, + SMART_EVENT_PHASE_MAX = 10, - SMART_EVENT_PHASE_COUNT = 6 + SMART_EVENT_PHASE_COUNT = 9 }; enum SMART_EVENT_PHASE_BITS @@ -66,7 +69,10 @@ enum SMART_EVENT_PHASE_BITS SMART_EVENT_PHASE_4_BIT = 8, SMART_EVENT_PHASE_5_BIT = 16, SMART_EVENT_PHASE_6_BIT = 32, - SMART_EVENT_PHASE_ALL = SMART_EVENT_PHASE_1_BIT + SMART_EVENT_PHASE_2_BIT + SMART_EVENT_PHASE_3_BIT + SMART_EVENT_PHASE_4_BIT + SMART_EVENT_PHASE_5_BIT + SMART_EVENT_PHASE_6_BIT + SMART_EVENT_PHASE_7_BIT = 64, + SMART_EVENT_PHASE_8_BIT = 128, + SMART_EVENT_PHASE_9_BIT = 256, + SMART_EVENT_PHASE_ALL = SMART_EVENT_PHASE_1_BIT + SMART_EVENT_PHASE_2_BIT + SMART_EVENT_PHASE_3_BIT + SMART_EVENT_PHASE_4_BIT + SMART_EVENT_PHASE_5_BIT + SMART_EVENT_PHASE_6_BIT + SMART_EVENT_PHASE_7_BIT + SMART_EVENT_PHASE_8_BIT + SMART_EVENT_PHASE_9_BIT }; const uint32 SmartPhaseMask[SMART_EVENT_PHASE_COUNT][2] = @@ -76,7 +82,10 @@ const uint32 SmartPhaseMask[SMART_EVENT_PHASE_COUNT][2] = {SMART_EVENT_PHASE_3, SMART_EVENT_PHASE_3_BIT }, {SMART_EVENT_PHASE_4, SMART_EVENT_PHASE_4_BIT }, {SMART_EVENT_PHASE_5, SMART_EVENT_PHASE_5_BIT }, - {SMART_EVENT_PHASE_6, SMART_EVENT_PHASE_6_BIT } + {SMART_EVENT_PHASE_6, SMART_EVENT_PHASE_6_BIT }, + {SMART_EVENT_PHASE_7, SMART_EVENT_PHASE_7_BIT }, + {SMART_EVENT_PHASE_8, SMART_EVENT_PHASE_8_BIT }, + {SMART_EVENT_PHASE_9, SMART_EVENT_PHASE_9_BIT } }; enum SMART_EVENT diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 2a10da29c20..dc5a2768668 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -678,6 +678,9 @@ enum RBACPermissions RBAC_PERM_COMMAND_WP_UNLOAD = 772, RBAC_PERM_COMMAND_WP_RELOAD = 773, RBAC_PERM_COMMAND_WP_SHOW = 774, + RBAC_PERM_COMMAND_MODIFY_CURRENCY = 775, // only 4.3.4 + RBAC_PERM_COMMAND_DEBUG_PHASE = 776, // only 4.3.4 + RBAC_PERM_COMMAND_MAILBOX = 777, // custom permissions 1000+ RBAC_PERM_MAX diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 7d53f481fe8..b98ff3e4f01 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -97,6 +97,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: + case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN: break; default: if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT) @@ -110,7 +111,8 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) switch (dataType) { case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE: - case ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT: + case ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT: + case ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY: return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE: if (!creature.id || !sObjectMgr->GetCreatureTemplate(creature.id)) @@ -259,7 +261,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM: if (equipped_item.item_quality >= MAX_ITEM_QUALITY) { - TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for requirement ACHIEVEMENT_CRITERIA_REQUIRE_S_EQUIPED_ITEM (%u) has unknown quality state in value1 (%u), ignored.", + TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM (%u) has unknown quality state in value1 (%u), ignored.", criteria->ID, criteria->requiredType, dataType, equipped_item.item_quality); return false; } @@ -267,7 +269,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID: if (!sMapStore.LookupEntry(map_id.mapId)) { - TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for requirement ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID (%u) has unknown map id in value1 (%u), ignored.", + TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID (%u) has unknown map id in value1 (%u), ignored.", criteria->ID, criteria->requiredType, dataType, map_id.mapId); return false; } @@ -292,6 +294,14 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) return false; } return true; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE: + if (!sCharTitlesStore.LookupEntry(known_title.title_id)) + { + TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE (%u) have unknown title_id in value1 (%u), ignore.", + criteria->ID, criteria->requiredType, dataType, known_title.title_id); + return false; + } + return true; default: TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) has data for non-supported data type (%u), ignored.", criteria->ID, criteria->requiredType, dataType); return false; @@ -317,7 +327,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un return false; return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE: - if (!source || source->GetTypeId() != TYPEID_PLAYER) + if (source->GetTypeId() != TYPEID_PLAYER) return false; if (classRace.class_id && classRace.class_id != source->ToPlayer()->getClass()) return false; @@ -381,22 +391,22 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un uint32 score = bg->GetTeamScore(source->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE); return score >= bg_loss_team_score.min_score && score <= bg_loss_team_score.max_score; } - case ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT: + case ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT: { if (!source->IsInWorld()) return false; Map* map = source->GetMap(); if (!map->IsDungeon()) { - TC_LOG_ERROR("achievement", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT (%u) for achievement criteria %u for non-dungeon/non-raid map %u", - ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT, criteria_id, map->GetId()); + TC_LOG_ERROR("achievement", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u for non-dungeon/non-raid map %u", + dataType, criteria_id, map->GetId()); return false; } - InstanceScript* instance = ((InstanceMap*)map)->GetInstanceScript(); + InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript(); if (!instance) { - TC_LOG_ERROR("achievement", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT (%u) for achievement criteria %u for map %u but map does not have a instance script", - ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT, criteria_id, map->GetId()); + TC_LOG_ERROR("achievement", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u for map %u but map does not have a instance script", + dataType, criteria_id, map->GetId()); return false; } return instance->CheckAchievementCriteriaMeet(criteria_id, source, target, miscvalue1); @@ -410,6 +420,25 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un } case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID: return source->GetMapId() == map_id.mapId; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY: + { + time_t birthday_start = time_t(sWorld->getIntConfig(CONFIG_BIRTHDAY_TIME)); + tm birthday_tm; + ACE_OS::localtime_r(&birthday_start, &birthday_tm); + + // exactly N birthday + birthday_tm.tm_year += birthday_login.nth_birthday; + + time_t birthday = mktime(&birthday_tm); + time_t now = sWorld->GetGameTime(); + return now <= birthday + DAY && now >= birthday; + } + case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE: + { + if (CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(known_title.title_id)) + return source->HasTitle(titleInfo->bit_index); + return false; + } default: break; } @@ -1562,6 +1591,20 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; } + case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN: + { + // This criteria is only called directly after login - with expected miscvalue1 == 1 + if (!miscValue1) + continue; + + // They have no proper requirements in dbc + AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria); + if (!data || !data->Meets(GetPlayer(), unit)) + continue; + + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; + } // std case: not exist in DBC, not triggered in code as result case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER: @@ -1574,7 +1617,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID: case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA: case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK: - case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE: break; // Not implemented yet :( } @@ -1717,6 +1759,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return progress->counter >= achievementCriteria->get_killing_blow.killCount; case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: return achievementCriteria->win_arena.count && progress->counter >= achievementCriteria->win_arena.count; + case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN: + return true; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: @@ -2287,11 +2331,24 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() switch (criteria->requiredType) { - case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: // any cases - break; case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: + case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: + case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: + case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE: + case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL: + case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: + case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: + case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: + case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN: case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE: - break; // any cases + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: + // achievement requires db data + break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: { AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->referredAchievement); @@ -2304,44 +2361,22 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() continue; } - case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: // any cases - break; - case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: // any cases - break; case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA: // need skip generic cases if (criteria->additionalRequirements[0].additionalRequirement_type != ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE) continue; break; - case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: // any cases - break; - case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: - break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: // need skip generic cases if (criteria->do_emote.count == 0) continue; break; - case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: - break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: // skip statistics if (criteria->win_duel.duelCount == 0) continue; break; - case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: // any cases - break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: // need skip generic cases if (criteria->loot_type.lootTypeCount != 1) continue; break; - case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: - break; // any cases - case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL: // any cases - break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements { @@ -2352,8 +2387,6 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() continue; break; } - case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: - break; default: // type not use DB data, ignore continue; } diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h index 1a6777d1055..c4216b2ee74 100644 --- a/src/server/game/Achievements/AchievementMgr.h +++ b/src/server/game/Achievements/AchievementMgr.h @@ -65,13 +65,15 @@ enum AchievementCriteriaDataType ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK = 15, // drunken_state 0 (enum DrunkenState) of player ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16, // holiday_id 0 event in holiday time ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE = 17, // min_score max_score player's team win bg and opposition team have team score in range - ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT = 18, // 0 0 maker instance script call for check current criteria requirements fit + ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18, // 0 0 maker instance script call for check current criteria requirements fit ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19, // item_level item_quality for equipped item in slot to check item level and quality ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20, // map_id 0 player must be on map with id in map_id - ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21 // class_id race_id + ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21, // class_id race_id + ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 22, // N login on day of N-th Birthday + ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23 // title_id known (pvp) title, values from dbc }; -#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 22 // maximum value in AchievementCriteriaDataType enum +#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 24 // maximum value in AchievementCriteriaDataType enum struct AchievementCriteriaData { @@ -161,7 +163,7 @@ struct AchievementCriteriaData uint32 min_score; uint32 max_score; } bg_loss_team_score; - // ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT = 18 (no data) + // ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18 (no data) // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19 struct { @@ -173,6 +175,16 @@ struct AchievementCriteriaData { uint32 mapId; } map_id; + // ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 21 + struct + { + uint32 nth_birthday; + } birthday_login; + // ACHIEVEMENT_CRITERIA_DATA_TYPE_KNOWN_TITLE = 22 + struct + { + uint32 title_id; + } known_title; // ... struct { diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index f7a6864fb95..52ed50f3948 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -340,7 +340,8 @@ CalendarEventStore CalendarMgr::GetPlayerEvents(uint64 guid) for (CalendarEventInviteStore::const_iterator itr = _invites.begin(); itr != _invites.end(); ++itr) for (CalendarInviteStore::const_iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2) if ((*itr2)->GetInviteeGUID() == guid) - events.insert(GetEvent(itr->first)); + if (CalendarEvent* event = GetEvent(itr->first)) // NULL check added as attempt to fix #11512 + events.insert(event); if (Player* player = ObjectAccessor::FindPlayer(guid)) for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr) diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 87397c6685b..8d8b7c89a5c 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -91,9 +91,9 @@ enum AchievementCriteriaFlags { ACHIEVEMENT_CRITERIA_FLAG_SHOW_PROGRESS_BAR = 0x00000001, // Show progress as bar ACHIEVEMENT_CRITERIA_FLAG_HIDDEN = 0x00000002, // Not show criteria in client - ACHIEVEMENT_CRITERIA_FLAG_UNK3 = 0x00000004, // BG related?? - ACHIEVEMENT_CRITERIA_FLAG_UNK4 = 0x00000008, // - ACHIEVEMENT_CRITERIA_FLAG_UNK5 = 0x00000010, // not used + ACHIEVEMENT_CRITERIA_FLAG_FAIL_ACHIEVEMENT = 0x00000004, // BG related?? + ACHIEVEMENT_CRITERIA_FLAG_RESET_ON_START = 0x00000008, // + ACHIEVEMENT_CRITERIA_FLAG_IS_DATE = 0x00000010, // not used ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER = 0x00000020 // Displays counter as money }; @@ -174,7 +174,7 @@ enum AchievementCriteriaTypes ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70, ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72, /// @todo 73: Achievements 1515, 1241, 1103 (Name: Mal'Ganis) - ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE = 74, /// @todo title id is not mentioned in dbc + ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN = 74, ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75, ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76, ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77, diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 2dcba7b6a76..1665eae0fcc 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -405,7 +405,9 @@ void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */) lockData = LFG_LOCKSTATUS_NOT_IN_SEASON; else if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty))) { - if (ar->achievement && !player->HasAchieved(ar->achievement)) + if (player->GetAverageItemLevel() < ar->item_level) + lockData = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; + else if (ar->achievement && !player->HasAchieved(ar->achievement)) lockData = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT; else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A)) lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; @@ -422,7 +424,6 @@ void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */) } /* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED) - lockData = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; lockData = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 21d5ba0d21a..e3c8c9c8136 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -986,9 +986,17 @@ bool GameObject::ActivateToQuest(Player* target) const switch (GetGoType()) { - // scan GO chest with loot including quest items + case GAMEOBJECT_TYPE_QUESTGIVER: + { + GameObject* go = const_cast<GameObject*>(this); + QuestGiverStatus questStatus = target->GetQuestDialogStatus(go); + if (questStatus > DIALOG_STATUS_UNAVAILABLE) + return true; + break; + } case GAMEOBJECT_TYPE_CHEST: { + // scan GO chest with loot including quest items if (LootTemplates_Gameobject.HaveQuestLootForPlayer(GetGOInfo()->GetLootId(), target)) { if (Battleground const* bg = target->GetBattleground()) @@ -2148,6 +2156,10 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t int16 pathProgress = -1; switch (GetGoType()) { + case GAMEOBJECT_TYPE_QUESTGIVER: + if (ActivateToQuest(target)) + dynFlags |= GO_DYNFLAG_LO_ACTIVATE; + break; case GAMEOBJECT_TYPE_CHEST: case GAMEOBJECT_TYPE_GOOBER: if (ActivateToQuest(target)) @@ -2209,3 +2221,20 @@ void GameObject::GetRespawnPosition(float &x, float &y, float &z, float* ori /* if (ori) *ori = GetOrientation(); } + +float GameObject::GetInteractionDistance() +{ + switch (GetGoType()) + { + /// @todo find out how the client calculates the maximal usage distance to spellless working + // gameobjects like guildbanks and mailboxes - 10.0 is a just an abitrary choosen number + case GAMEOBJECT_TYPE_GUILD_BANK: + case GAMEOBJECT_TYPE_MAILBOX: + return 10.0f; + case GAMEOBJECT_TYPE_FISHINGHOLE: + case GAMEOBJECT_TYPE_FISHINGNODE: + return 20.0f + CONTACT_DISTANCE; // max spell range + default: + return INTERACTION_DISTANCE; + } +} diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 0ef03723cb4..84abc391bc6 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -830,6 +830,8 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map float GetStationaryZ() const { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionZ(); return GetPositionZ(); } float GetStationaryO() const { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetOrientation(); return GetOrientation(); } + float GetInteractionDistance(); + protected: bool AIM_Initialize(); void UpdateModel(); // updates model in case displayId were changed diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index c218c3c645f..a887e85e77e 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -1122,9 +1122,8 @@ void Pet::_LoadSpellCooldowns() { time_t curTime = time(NULL); - WorldPacket data(SMSG_SPELL_COOLDOWN, size_t(8+1+result->GetRowCount()*8)); - data << GetGUID(); - data << uint8(0x0); // flags (0x1, 0x2) + PacketCooldowns cooldowns; + WorldPacket data; do { @@ -1143,8 +1142,7 @@ void Pet::_LoadSpellCooldowns() if (db_time <= curTime) continue; - data << uint32(spell_id); - data << uint32(uint32(db_time-curTime)*IN_MILLISECONDS); + cooldowns[spell_id] = uint32(db_time - curTime)*IN_MILLISECONDS; _AddCreatureSpellCooldown(spell_id, db_time); @@ -1152,8 +1150,11 @@ void Pet::_LoadSpellCooldowns() } while (result->NextRow()); - if (!m_CreatureSpellCooldowns.empty() && GetOwner()) + if (!cooldowns.empty() && GetOwner()) + { + BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, cooldowns); GetOwner()->GetSession()->SendPacket(&data); + } } } @@ -2050,21 +2051,17 @@ void Pet::SynchronizeLevelWithOwner() void Pet::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) { - WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+m_spells.size()*8); - data << uint64(GetGUID()); - data << uint8(0x0); // flags (0x1, 0x2) + PacketCooldowns cooldowns; + WorldPacket data; time_t curTime = time(NULL); for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) { if (itr->second.state == PETSPELL_REMOVED) continue; + uint32 unSpellId = itr->first; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(unSpellId); - if (!spellInfo) - { - ASSERT(spellInfo); - continue; - } + ASSERT(spellInfo); // Not send cooldown for this spells if (spellInfo->IsCooldownStartedOnEvent()) @@ -2075,14 +2072,18 @@ void Pet::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) if ((idSchoolMask & spellInfo->GetSchoolMask()) && GetCreatureSpellCooldownDelay(unSpellId) < unTimeMs) { - data << uint32(unSpellId); - data << uint32(unTimeMs); // in m.secs + cooldowns[unSpellId] = unTimeMs; _AddCreatureSpellCooldown(unSpellId, curTime + unTimeMs/IN_MILLISECONDS); } } - if (Player* owner = GetOwner()) - owner->GetSession()->SendPacket(&data); + if (!cooldowns.empty()) + { + BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, cooldowns); + + if (Player* owner = GetOwner()) + owner->GetSession()->SendPacket(&data); + } } Player* Pet::GetOwner() const diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4dab652d732..09a0d033c68 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -687,7 +687,7 @@ Player::Player(WorldSession* session): Unit(true) m_regenTimerCount = 0; m_weaponChangeTimer = 0; - m_zoneUpdateId = 0; + m_zoneUpdateId = uint32(-1); m_zoneUpdateTimer = 0; m_areaUpdateId = 0; @@ -2634,38 +2634,38 @@ void Player::RegenerateHealth() if (getLevel() < 15) HealthIncreaseRate = sWorld->getRate(RATE_HEALTH) * (2.066f - (getLevel() * 0.066f)); - float addvalue = 0.0f; + float addValue = 0.0f; // polymorphed case if (IsPolymorphed()) - addvalue = (float)GetMaxHealth()/3; + addValue = float(GetMaxHealth()) / 3.0f; // normal regen case (maybe partly in combat case) else if (!IsInCombat() || HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT)) { - addvalue = OCTRegenHPPerSpirit() * HealthIncreaseRate; + addValue = OCTRegenHPPerSpirit() * HealthIncreaseRate; if (!IsInCombat()) { AuraEffectList const& mModHealthRegenPct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); for (AuraEffectList::const_iterator i = mModHealthRegenPct.begin(); i != mModHealthRegenPct.end(); ++i) - AddPct(addvalue, (*i)->GetAmount()); + AddPct(addValue, (*i)->GetAmount()); - addvalue += GetTotalAuraModifier(SPELL_AURA_MOD_REGEN) * 2 * IN_MILLISECONDS / (5 * IN_MILLISECONDS); + addValue += GetTotalAuraModifier(SPELL_AURA_MOD_REGEN) * 0.4f; } else if (HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT)) - ApplyPct(addvalue, GetTotalAuraModifier(SPELL_AURA_MOD_REGEN_DURING_COMBAT)); + ApplyPct(addValue, GetTotalAuraModifier(SPELL_AURA_MOD_REGEN_DURING_COMBAT)); if (!IsStandState()) - addvalue *= 1.5f; + addValue *= 1.5f; } // always regeneration bonus (including combat) - addvalue += GetTotalAuraModifier(SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT); - addvalue += m_baseHealthRegen / 2.5f; + addValue += GetTotalAuraModifier(SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT); + addValue += m_baseHealthRegen / 2.5f; - if (addvalue < 0) - addvalue = 0; + if (addValue < 0.0f) + addValue = 0.0f; - ModifyHealth(int32(addvalue)); + ModifyHealth(int32(addValue)); } void Player::ResetAllPowers() @@ -2765,30 +2765,14 @@ GameObject* Player::GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes { if (go->GetGoType() == type) { - float maxdist; - switch (type) - { - /// @todo find out how the client calculates the maximal usage distance to spellless working - // gameobjects like guildbanks and mailboxes - 10.0 is a just an abitrary choosen number - case GAMEOBJECT_TYPE_GUILD_BANK: - case GAMEOBJECT_TYPE_MAILBOX: - maxdist = 10.0f; - break; - case GAMEOBJECT_TYPE_FISHINGHOLE: - maxdist = 20.0f+CONTACT_DISTANCE; // max spell range - break; - default: - maxdist = INTERACTION_DISTANCE; - break; - } - - if (go->IsWithinDistInMap(this, maxdist)) + if (go->IsWithinDistInMap(this, go->GetInteractionDistance())) return go; - TC_LOG_DEBUG("maps", "IsGameObjectOfTypeInRange: GameObject '%s' [GUID: %u] is too far away from player %s [GUID: %u] to be used by him (distance=%f, maximal 10 is allowed)", go->GetGOInfo()->name.c_str(), + TC_LOG_DEBUG("maps", "GetGameObjectIfCanInteractWith: GameObject '%s' [GUID: %u] is too far away from player %s [GUID: %u] to be used by him (distance=%f, maximal 10 is allowed)", go->GetGOInfo()->name.c_str(), go->GetGUIDLow(), GetName().c_str(), GetGUIDLow(), go->GetDistance(this)); } } + return NULL; } @@ -5127,7 +5111,10 @@ void Player::BuildPlayerRepop() // BG - remove insignia related RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); -// SendCorpseReclaimDelay(); + int32 corpseReclaimDelay = CalculateCorpseReclaimDelay(); + + if (corpseReclaimDelay >= 0) + SendCorpseReclaimDelay(corpseReclaimDelay); // to prevent cheating corpse->ResetGhostTime(); @@ -5235,7 +5222,11 @@ void Player::KillPlayer() m_deathTimer = 6 * MINUTE * IN_MILLISECONDS; UpdateCorpseReclaimDelay(); // dependent at use SetDeathPvP() call before kill - SendCorpseReclaimDelay(); + + int32 corpseReclaimDelay = CalculateCorpseReclaimDelay(); + + if (corpseReclaimDelay >= 0) + SendCorpseReclaimDelay(corpseReclaimDelay); // don't create corpse at this moment, player might be falling @@ -7517,14 +7508,9 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) { if (Weather* weather = WeatherMgr::FindWeather(zone->ID)) weather->SendWeatherUpdateToPlayer(this); - else - { - if (!WeatherMgr::AddWeather(zone->ID)) - { - // send fine weather packet to remove old zone's weather - WeatherMgr::SendFineWeatherUpdateToPlayer(this); - } - } + else if (!WeatherMgr::AddWeather(zone->ID)) + // send fine weather packet to remove old zone's weather + WeatherMgr::SendFineWeatherUpdateToPlayer(this); } sScriptMgr->OnPlayerUpdateZone(this, newZone, newArea); @@ -12364,11 +12350,8 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update) GetGlobalCooldownMgr().AddGlobalCooldown(spellProto, m_weaponChangeTimer); - WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+4); - data << uint64(GetGUID()); - data << uint8(1); - data << uint32(cooldownSpell); - data << uint32(0); + WorldPacket data; + BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_INCLUDE_GCD, cooldownSpell, 0); GetSession()->SendPacket(&data); } } @@ -15051,7 +15034,7 @@ void Player::AddQuestAndCheckCompletion(Quest const* quest, Object* questGiver) switch (questGiver->GetTypeId()) { case TYPEID_UNIT: - sScriptMgr->OnQuestAccept(this, (questGiver->ToCreature()), quest); + sScriptMgr->OnQuestAccept(this, questGiver->ToCreature(), quest); questGiver->ToCreature()->AI()->sQuestAccept(this, quest); break; case TYPEID_ITEM: @@ -15194,7 +15177,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest_id); - UpdateForQuestWorldObjects(); + SendQuestUpdate(quest_id); } void Player::CompleteQuest(uint32 quest_id) @@ -15360,7 +15343,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, else if (quest->IsSeasonal()) SetSeasonalQuestStatus(quest_id); - RemoveActiveQuest(quest_id); + RemoveActiveQuest(quest_id, false); m_RewardedQuests.insert(quest_id); m_RewardedQuestsSave[quest_id] = true; @@ -15408,6 +15391,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, UpdatePvPState(); } + SendQuestUpdate(quest_id); + //lets remove flag for delayed teleports SetCanDelayTeleport(false); } @@ -16001,17 +15986,49 @@ bool Player::CanShareQuest(uint32 quest_id) const return false; } -void Player::SetQuestStatus(uint32 quest_id, QuestStatus status) +void Player::SetQuestStatus(uint32 questId, QuestStatus status, bool update /*= true*/) { - if (sObjectMgr->GetQuestTemplate(quest_id)) + if (sObjectMgr->GetQuestTemplate(questId)) + { + m_QuestStatus[questId].Status = status; + m_QuestStatusSave[questId] = true; + } + + if (update) + SendQuestUpdate(questId); +} + +void Player::RemoveActiveQuest(uint32 questId, bool update /*= true*/) +{ + QuestStatusMap::iterator itr = m_QuestStatus.find(questId); + if (itr != m_QuestStatus.end()) { - m_QuestStatus[quest_id].Status = status; - m_QuestStatusSave[quest_id] = true; + m_QuestStatus.erase(itr); + m_QuestStatusSave[questId] = false; } + if (update) + SendQuestUpdate(questId); +} + +void Player::RemoveRewardedQuest(uint32 questId, bool update /*= true*/) +{ + RewardedQuestSet::iterator rewItr = m_RewardedQuests.find(questId); + if (rewItr != m_RewardedQuests.end()) + { + m_RewardedQuests.erase(rewItr); + m_RewardedQuestsSave[questId] = false; + } + + if (update) + SendQuestUpdate(questId); +} + +void Player::SendQuestUpdate(uint32 questId) +{ uint32 zone = 0, area = 0; - SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id); + SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(questId); if (saBounds.first != saBounds.second) { GetZoneAndAreaId(zone, area); @@ -16022,7 +16039,7 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status) CastSpell(this, itr->second->spellId, true); } - saBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id); + saBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(questId); if (saBounds.first != saBounds.second) { if (!zone || !area) @@ -16036,25 +16053,108 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status) UpdateForQuestWorldObjects(); } -void Player::RemoveActiveQuest(uint32 quest_id) +QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver) { - QuestStatusMap::iterator itr = m_QuestStatus.find(quest_id); - if (itr != m_QuestStatus.end()) + QuestRelationBounds qr; + QuestRelationBounds qir; + + switch (questgiver->GetTypeId()) { - m_QuestStatus.erase(itr); - m_QuestStatusSave[quest_id] = false; - return; + case TYPEID_GAMEOBJECT: + { + QuestGiverStatus questStatus = QuestGiverStatus(sScriptMgr->GetDialogStatus(this, questgiver->ToGameObject())); + if (questStatus != DIALOG_STATUS_SCRIPTED_NO_STATUS) + return questStatus; + qr = sObjectMgr->GetGOQuestRelationBounds(questgiver->GetEntry()); + qir = sObjectMgr->GetGOQuestInvolvedRelationBounds(questgiver->GetEntry()); + break; + } + case TYPEID_UNIT: + { + QuestGiverStatus questStatus = QuestGiverStatus(sScriptMgr->GetDialogStatus(this, questgiver->ToCreature())); + if (questStatus != DIALOG_STATUS_SCRIPTED_NO_STATUS) + return questStatus; + qr = sObjectMgr->GetCreatureQuestRelationBounds(questgiver->GetEntry()); + qir = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(questgiver->GetEntry()); + break; + } + default: + // it's impossible, but check + TC_LOG_ERROR("entities.player.quest", "GetQuestDialogStatus called for unexpected type %u", questgiver->GetTypeId()); + return DIALOG_STATUS_NONE; } -} -void Player::RemoveRewardedQuest(uint32 quest_id) -{ - RewardedQuestSet::iterator rewItr = m_RewardedQuests.find(quest_id); - if (rewItr != m_RewardedQuests.end()) + QuestGiverStatus result = DIALOG_STATUS_NONE; + + for (QuestRelations::const_iterator i = qir.first; i != qir.second; ++i) { - m_RewardedQuests.erase(rewItr); - m_RewardedQuestsSave[quest_id] = false; + QuestGiverStatus result2 = DIALOG_STATUS_NONE; + uint32 questId = i->second; + Quest const* quest = sObjectMgr->GetQuestTemplate(questId); + if (!quest) + continue; + + ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId()); + if (!sConditionMgr->IsObjectMeetToConditions(this, conditions)) + continue; + + QuestStatus status = GetQuestStatus(questId); + if ((status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus(questId)) || + (quest->IsAutoComplete() && CanTakeQuest(quest, false))) + { + if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) + result2 = DIALOG_STATUS_REWARD_REP; + else + result2 = DIALOG_STATUS_REWARD; + } + else if (status == QUEST_STATUS_INCOMPLETE) + result2 = DIALOG_STATUS_INCOMPLETE; + + if (result2 > result) + result = result2; + } + + for (QuestRelations::const_iterator i = qr.first; i != qr.second; ++i) + { + QuestGiverStatus result2 = DIALOG_STATUS_NONE; + uint32 questId = i->second; + Quest const* quest = sObjectMgr->GetQuestTemplate(questId); + if (!quest) + continue; + + ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId()); + if (!sConditionMgr->IsObjectMeetToConditions(this, conditions)) + continue; + + QuestStatus status = GetQuestStatus(questId); + if (status == QUEST_STATUS_NONE) + { + if (CanSeeStartQuest(quest)) + { + if (SatisfyQuestLevel(quest, false)) + { + if (quest->IsAutoComplete()) + result2 = DIALOG_STATUS_REWARD_REP; + else if (getLevel() <= (GetQuestLevel(quest) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) + { + if (quest->IsDaily()) + result2 = DIALOG_STATUS_AVAILABLE_REP; + else + result2 = DIALOG_STATUS_AVAILABLE; + } + else + result2 = DIALOG_STATUS_LOW_LEVEL_AVAILABLE; + } + else + result2 = DIALOG_STATUS_UNAVAILABLE; + } + } + + if (result2 > result) + result = result2; } + + return result; } // not used in Trinity, but used in scripting code @@ -17452,8 +17552,9 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) UpdateHonorFields(); m_deathExpireTime = time_t(fields[36].GetUInt32()); - if (m_deathExpireTime > now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP) - m_deathExpireTime = now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP-1; + + if (m_deathExpireTime > now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP) + m_deathExpireTime = now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP - 1; // clear channel spell data (if saved at channel spell casting) SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0); @@ -18507,6 +18608,9 @@ void Player::_LoadGroup(PreparedQueryResult result) { if (Group* group = sGroupMgr->GetGroupByDbStoreId((*result)[0].GetUInt32())) { + if (group->IsLeader(GetGUID())) + SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER); + uint8 subgroup = group->GetMemberGroup(GetGUID()); SetGroup(group, subgroup); if (getLevel() >= LEVELREQUIREMENT_HEROIC) @@ -18517,6 +18621,9 @@ void Player::_LoadGroup(PreparedQueryResult result) } } } + + if (!GetGroup() || !GetGroup()->IsLeader(GetGUID())) + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER); } void Player::_LoadBoundInstances(PreparedQueryResult result) @@ -21298,10 +21405,8 @@ void Player::ContinueTaxiFlight() void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) { - // last check 2.0.10 - WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+m_spells.size()*8); - data << uint64(GetGUID()); - data << uint8(0x0); // flags (0x1, 0x2) + PacketCooldowns cooldowns; + WorldPacket data; time_t curTime = time(NULL); for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) { @@ -21324,12 +21429,16 @@ void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) if ((idSchoolMask & spellInfo->GetSchoolMask()) && GetSpellCooldownDelay(unSpellId) < unTimeMs) { - data << uint32(unSpellId); - data << uint32(unTimeMs); // in m.secs + cooldowns[unSpellId] = unTimeMs; AddSpellCooldown(unSpellId, 0, curTime + unTimeMs/IN_MILLISECONDS); } } - GetSession()->SendPacket(&data); + + if (!cooldowns.empty()) + { + BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, cooldowns); + GetSession()->SendPacket(&data); + } } void Player::InitDataForForm(bool reapplyMods) @@ -21487,6 +21596,15 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 return false; } + if (!(pProto->AllowableClass & getClassMask()) && pProto->Bonding == BIND_WHEN_PICKED_UP && !IsGameMaster()) + { + SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, item, 0); + return false; + } + + if (!IsGameMaster() && ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && GetTeam() == ALLIANCE) || (pProto->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && GetTeam() == HORDE))) + return false; + Creature* creature = GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); if (!creature) { @@ -21495,6 +21613,14 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 return false; } + ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(creature->GetEntry(), item); + if (!sConditionMgr->IsObjectMeetToConditions(this, creature, conditions)) + { + TC_LOG_DEBUG("condition", "BuyItemFromVendor: conditions not met for creature entry %u item %u", creature->GetEntry(), item); + SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, item, 0); + return false; + } + VendorItemData const* vItems = creature->GetVendorItems(); if (!vItems || vItems->Empty()) { @@ -21789,6 +21915,8 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite time_t catrecTime; time_t recTime; + bool needsCooldownPacket = false; + // overwrite time for selected category if (infinityCooldown) { @@ -21811,6 +21939,16 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite if (catrec > 0 && !(spellInfo->AttributesEx6 & SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS)) ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell); + if (int32 cooldownMod = GetTotalAuraModifier(SPELL_AURA_MOD_COOLDOWN)) + { + // Apply SPELL_AURA_MOD_COOLDOWN only to own spells + if (HasSpell(spellInfo->Id)) + { + needsCooldownPacket = true; + rec += cooldownMod * IN_MILLISECONDS; // SPELL_AURA_MOD_COOLDOWN does not affect category cooldows, verified with shaman shocks + } + } + // replace negative cooldowns by 0 if (rec < 0) rec = 0; if (catrec < 0) catrec = 0; @@ -21825,8 +21963,17 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite // self spell cooldown if (recTime > 0) + { AddSpellCooldown(spellInfo->Id, itemId, recTime); + if (needsCooldownPacket) + { + WorldPacket data; + BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, spellInfo->Id, rec); + SendDirectMessage(&data); + } + } + // category spells if (cat && catrec > 0) { @@ -23326,7 +23473,7 @@ void Player::UpdateForQuestWorldObjects() UpdateData udata; WorldPacket packet; - for (ClientGUIDs::iterator itr=m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr) + for (ClientGUIDs::iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr) { if (IS_GAMEOBJECT_GUID(*itr)) { @@ -23605,7 +23752,7 @@ uint32 Player::GetResurrectionSpellId() } // Used in triggers for check "Only to targets that grant experience or honor" req -bool Player::isHonorOrXPTarget(Unit* victim) +bool Player::isHonorOrXPTarget(Unit* victim) const { uint8 v_level = victim->getLevel(); uint8 k_grey = Trinity::XP::GetGrayLevel(getLevel()); @@ -23844,7 +23991,7 @@ uint32 Player::GetCorpseReclaimDelay(bool pvp) const time_t now = time(NULL); // 0..2 full period // should be ceil(x)-1 but not floor(x) - uint64 count = (now < m_deathExpireTime - 1) ? (m_deathExpireTime - 1 - now)/DEATH_EXPIRE_STEP : 0; + uint64 count = (now < m_deathExpireTime - 1) ? (m_deathExpireTime - 1 - now) / DEATH_EXPIRE_STEP : 0; return copseReclaimDelay[count]; } @@ -23857,65 +24004,66 @@ void Player::UpdateCorpseReclaimDelay() return; time_t now = time(NULL); + if (now < m_deathExpireTime) { // full and partly periods 1..3 - uint64 count = (m_deathExpireTime - now)/DEATH_EXPIRE_STEP +1; + uint64 count = (m_deathExpireTime - now) / DEATH_EXPIRE_STEP + 1; + if (count < MAX_DEATH_COUNT) - m_deathExpireTime = now+(count+1)*DEATH_EXPIRE_STEP; + m_deathExpireTime = now+(count + 1) * DEATH_EXPIRE_STEP; else - m_deathExpireTime = now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP; + m_deathExpireTime = now + MAX_DEATH_COUNT*DEATH_EXPIRE_STEP; } else - m_deathExpireTime = now+DEATH_EXPIRE_STEP; + m_deathExpireTime = now + DEATH_EXPIRE_STEP; } -void Player::SendCorpseReclaimDelay(bool load) +int32 Player::CalculateCorpseReclaimDelay(bool load) { Corpse* corpse = GetCorpse(); + if (load && !corpse) - return; + return -1; - bool pvp; - if (corpse) - pvp = (corpse->GetType() == CORPSE_RESURRECTABLE_PVP); - else - pvp = (m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH); + bool pvp = corpse ? corpse->GetType() == CORPSE_RESURRECTABLE_PVP : m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH; + + uint32 delay; - time_t delay; if (load) { if (corpse->GetGhostTime() > m_deathExpireTime) - return; + return -1; + + uint64 count = 0; - uint64 count; if ((pvp && sWorld->getBoolConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP)) || (!pvp && sWorld->getBoolConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE))) { - count = (m_deathExpireTime-corpse->GetGhostTime())/DEATH_EXPIRE_STEP; + count = (m_deathExpireTime - corpse->GetGhostTime()) / DEATH_EXPIRE_STEP; + if (count >= MAX_DEATH_COUNT) - count = MAX_DEATH_COUNT-1; + count = MAX_DEATH_COUNT - 1; } - else - count=0; - - time_t expected_time = corpse->GetGhostTime()+copseReclaimDelay[count]; + time_t expected_time = corpse->GetGhostTime() + copseReclaimDelay[count]; time_t now = time(NULL); + if (now >= expected_time) - return; + return -1; - delay = expected_time-now; + delay = expected_time - now; } else delay = GetCorpseReclaimDelay(pvp); - if (!delay) - return; + return delay * IN_MILLISECONDS; +} - //! corpse reclaim delay 30 * 1000ms or longer at often deaths +void Player::SendCorpseReclaimDelay(uint32 delay) +{ WorldPacket data(SMSG_CORPSE_RECLAIM_DELAY, 4); - data << uint32(delay*IN_MILLISECONDS); + data << uint32(delay); GetSession()->SendPacket(&data); } @@ -24309,7 +24457,7 @@ bool Player::isTotalImmune() return false; } -bool Player::HasTitle(uint32 bitIndex) +bool Player::HasTitle(uint32 bitIndex) const { if (bitIndex > MAX_TITLE_INDEX) return false; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index cd73f38823e..2eb740f0a82 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -840,6 +840,7 @@ struct AccessRequirement { uint8 levelMin; uint8 levelMax; + uint16 item_level; uint32 item; uint32 item2; uint32 quest_A; @@ -1382,9 +1383,11 @@ class Player : public Unit, public GridObject<Player> bool TakeQuestSourceItem(uint32 questId, bool msg); bool GetQuestRewardStatus(uint32 quest_id) const; QuestStatus GetQuestStatus(uint32 quest_id) const; - void SetQuestStatus(uint32 quest_id, QuestStatus status); - void RemoveActiveQuest(uint32 quest_id); - void RemoveRewardedQuest(uint32 quest_id); + void SetQuestStatus(uint32 questId, QuestStatus status, bool update = true); + void RemoveActiveQuest(uint32 questId, bool update = true); + void RemoveRewardedQuest(uint32 questId, bool update = true); + void SendQuestUpdate(uint32 questId); + QuestGiverStatus GetQuestDialogStatus(Object* questGiver); void SetDailyQuestStatus(uint32 quest_id); void SetWeeklyQuestStatus(uint32 quest_id); @@ -1894,7 +1897,7 @@ class Player : public Unit, public GridObject<Player> bool IsAtRecruitAFriendDistance(WorldObject const* pOther) const; void RewardPlayerAndGroupAtKill(Unit* victim, bool isBattleGround); void RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewardSource); - bool isHonorOrXPTarget(Unit* victim); + bool isHonorOrXPTarget(Unit* victim) const; bool GetsRecruitAFriendBonus(bool forXP); uint8 GetGrantableLevels() { return m_grantableLevels; } @@ -1936,7 +1939,8 @@ class Player : public Unit, public GridObject<Player> uint32 GetDeathTimer() const { return m_deathTimer; } uint32 GetCorpseReclaimDelay(bool pvp) const; void UpdateCorpseReclaimDelay(); - void SendCorpseReclaimDelay(bool load = false); + int32 CalculateCorpseReclaimDelay(bool load = false); + void SendCorpseReclaimDelay(uint32 delay); uint32 GetShieldBlockValue() const; // overwrite Unit version (virtual) bool CanParry() const { return m_canParry; } @@ -2262,8 +2266,8 @@ class Player : public Unit, public GridObject<Player> void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry); void CompletedAchievement(AchievementEntry const* entry); - bool HasTitle(uint32 bitIndex); - bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } + bool HasTitle(uint32 bitIndex) const; + bool HasTitle(CharTitlesEntry const* title) const { return HasTitle(title->bit_index); } void SetTitle(CharTitlesEntry const* title, bool lost = false); //bool isActiveObject() const { return true; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 3de062148e9..52565a2eaa5 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -4484,10 +4484,13 @@ uint32 Unit::GetDoTsByCaster(uint64 casterGUID) const int32 Unit::GetTotalAuraModifier(AuraType auratype) const { + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + if (mTotalAuraList.empty()) + return 0; + std::map<SpellGroup, int32> SameEffectSpellGroup; int32 modifier = 0; - AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) if (!sSpellMgr->AddSameEffectStackRuleSpellGroups((*i)->GetSpellInfo(), (*i)->GetAmount(), SameEffectSpellGroup)) modifier += (*i)->GetAmount(); @@ -5668,17 +5671,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere break; } } - - // Retaliation - if (dummySpell->SpellFamilyFlags[1] & 0x8) - { - // check attack comes not from behind - if (!HasInArc(M_PI, victim)) - return false; - - triggered_spell_id = 22858; - break; - } // Second Wind if (dummySpell->SpellIconID == 1697) { @@ -5708,19 +5700,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 58374; break; } - // Glyph of Sunder Armor - if (dummySpell->Id == 58387) - { - if (!victim || !victim->IsAlive() || !procSpell) - return false; - - target = SelectNearbyTarget(victim); - if (!target) - return false; - - triggered_spell_id = 58567; - break; - } break; } case SPELLFAMILY_WARLOCK: @@ -8740,13 +8719,28 @@ ReputationRank Unit::GetReactionTo(Unit const* target) const if (GetCharmerOrOwnerOrSelf() == target->GetCharmerOrOwnerOrSelf()) return REP_FRIENDLY; + Player const* selfPlayerOwner = GetAffectingPlayer(); + Player const* targetPlayerOwner = target->GetAffectingPlayer(); + + // check forced reputation to support SPELL_AURA_FORCE_REACTION + if (selfPlayerOwner) + { + if (FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry()) + if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(targetFactionTemplateEntry)) + return *repRank; + } + else if (targetPlayerOwner) + { + if (FactionTemplateEntry const* selfFactionTemplateEntry = GetFactionTemplateEntry()) + if (ReputationRank const* repRank = targetPlayerOwner->GetReputationMgr().GetForcedRankIfAny(selfFactionTemplateEntry)) + return *repRank; + } + + if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) { if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) { - Player const* selfPlayerOwner = GetAffectingPlayer(); - Player const* targetPlayerOwner = target->GetAffectingPlayer(); - if (selfPlayerOwner && targetPlayerOwner) { // always friendly to other unit controlled by player, or to the player himself @@ -9365,9 +9359,7 @@ void Unit::SetMinion(Minion *minion, bool apply) } if (minion->m_Properties && minion->m_Properties->Type == SUMMON_TYPE_MINIPET) - { SetCritterGUID(minion->GetGUID()); - } // PvP, FFAPvP minion->SetByteValue(UNIT_FIELD_BYTES_2, 1, GetByteValue(UNIT_FIELD_BYTES_2, 1)); @@ -13274,12 +13266,14 @@ void Unit::SetLevel(uint8 lvl) { SetUInt32Value(UNIT_FIELD_LEVEL, lvl); - // group update - if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetGroup()) - ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_LEVEL); + if (Player* player = ToPlayer()) + { + // group update + if (player->GetGroup()) + player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_LEVEL); - if (GetTypeId() == TYPEID_PLAYER) - sWorld->UpdateCharacterNameDataLevel(ToPlayer()->GetGUIDLow(), lvl); + sWorld->UpdateCharacterNameDataLevel(GetGUIDLow(), lvl); + } } void Unit::SetHealth(uint32 val) @@ -17469,19 +17463,21 @@ bool Unit::SetHover(bool enable, bool /*packetOnly = false*/) if (enable == HasUnitMovementFlag(MOVEMENTFLAG_HOVER)) return false; + float hoverHeight = GetFloatValue(UNIT_FIELD_HOVERHEIGHT); + if (enable) { //! No need to check height on ascent AddUnitMovementFlag(MOVEMENTFLAG_HOVER); - if (float hh = GetFloatValue(UNIT_FIELD_HOVERHEIGHT)) - UpdateHeight(GetPositionZ() + hh); + if (hoverHeight) + UpdateHeight(GetPositionZ() + hoverHeight); } else { RemoveUnitMovementFlag(MOVEMENTFLAG_HOVER); - if (float hh = GetFloatValue(UNIT_FIELD_HOVERHEIGHT)) + if (hoverHeight) { - float newZ = GetPositionZ() - hh; + float newZ = GetPositionZ() - hoverHeight; UpdateAllowedPositionZ(GetPositionX(), GetPositionY(), newZ); UpdateHeight(newZ); } @@ -17663,3 +17659,24 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) updateMask.AppendToPacket(data); data->append(fieldBuffer); } + +void Unit::BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown) +{ + data.Initialize(SMSG_SPELL_COOLDOWN, 8 + 1 + 4 + 4); + data << uint64(GetGUID()); + data << uint8(flags); + data << uint32(spellId); + data << uint32(cooldown); +} + +void Unit::BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns) +{ + data.Initialize(SMSG_SPELL_COOLDOWN, 8 + 1 + (4 + 4) * cooldowns.size()); + data << uint64(GetGUID()); + data << uint8(flags); + for (UNORDERED_MAP<uint32, uint32>::const_iterator itr = cooldowns.begin(); itr != cooldowns.end(); ++itr) + { + data << uint32(itr->first); + data << uint32(itr->second); + } +} diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 151f20d09f9..751bfcb8126 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -683,7 +683,8 @@ enum NPCFlags UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100% UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click) - UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000 // players with mounts that have vehicle data should have it set + UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set + UNIT_NPC_FLAG_MAILBOX = 0x04000000 // }; enum MovementFlags @@ -1232,6 +1233,16 @@ enum PlayerTotemType SUMMON_TYPE_TOTEM_AIR = 83 }; +/// Spell cooldown flags sent in SMSG_SPELL_COOLDOWN +enum SpellCooldownFlags +{ + SPELL_COOLDOWN_FLAG_NONE = 0x0, + SPELL_COOLDOWN_FLAG_INCLUDE_GCD = 0x1, ///< Starts GCD in addition to normal cooldown specified in the packet + SPELL_COOLDOWN_FLAG_INCLUDE_EVENT_COOLDOWNS = 0x2 ///< Starts GCD for spells that should start their cooldown on events, requires SPELL_COOLDOWN_FLAG_INCLUDE_GCD set +}; + +typedef UNORDERED_MAP<uint32, uint32> PacketCooldowns; + // delay time next attack to prevent client attack animation problems #define ATTACK_DISPLAY_DELAY 200 #define MAX_PLAYER_STEALTH_DETECT_RANGE 30.0f // max distance for detection targets by player @@ -1564,6 +1575,8 @@ class Unit : public WorldObject void SetAuraStack(uint32 spellId, Unit* target, uint32 stack); void SendPlaySpellVisual(uint32 id); void SendPlaySpellImpact(uint64 guid, uint32 id); + void BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown); + void BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns); void DeMorph(); @@ -2260,12 +2273,23 @@ namespace Trinity { public: PowerPctOrderPred(Powers power, bool ascending = true) : _power(power), _ascending(ascending) { } - bool operator() (Unit const* a, Unit const* b) const + + bool operator()(WorldObject const* objA, WorldObject const* objB) const + { + Unit const* a = objA->ToUnit(); + Unit const* b = objB->ToUnit(); + float rA = (a && a->GetMaxPower(_power)) ? float(a->GetPower(_power)) / float(a->GetMaxPower(_power)) : 0.0f; + float rB = (b && b->GetMaxPower(_power)) ? float(b->GetPower(_power)) / float(b->GetMaxPower(_power)) : 0.0f; + return _ascending ? rA < rB : rA > rB; + } + + bool operator()(Unit const* a, Unit const* b) const { float rA = a->GetMaxPower(_power) ? float(a->GetPower(_power)) / float(a->GetMaxPower(_power)) : 0.0f; float rB = b->GetMaxPower(_power) ? float(b->GetPower(_power)) / float(b->GetMaxPower(_power)) : 0.0f; return _ascending ? rA < rB : rA > rB; } + private: Powers const _power; bool const _ascending; @@ -2276,12 +2300,23 @@ namespace Trinity { public: HealthPctOrderPred(bool ascending = true) : _ascending(ascending) { } + + bool operator()(WorldObject const* objA, WorldObject const* objB) const + { + Unit const* a = objA->ToUnit(); + Unit const* b = objB->ToUnit(); + float rA = (a && a->GetMaxHealth()) ? float(a->GetHealth()) / float(a->GetMaxHealth()) : 0.0f; + float rB = (b && b->GetMaxHealth()) ? float(b->GetHealth()) / float(b->GetMaxHealth()) : 0.0f; + return _ascending ? rA < rB : rA > rB; + } + bool operator() (Unit const* a, Unit const* b) const { float rA = a->GetMaxHealth() ? float(a->GetHealth()) / float(a->GetMaxHealth()) : 0.0f; float rB = b->GetMaxHealth() ? float(b->GetHealth()) / float(b->GetMaxHealth()) : 0.0f; return _ascending ? rA < rB : rA > rB; } + private: bool const _ascending; }; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 04f3395653d..c5c97e74777 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -705,12 +705,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) cInfo->Entry, cInfo->type, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->type); } - if (cInfo->type_flags != difficultyInfo->type_flags) - { - TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, type_flags %u) has different `type_flags` in difficulty %u mode (Entry: %u, type_flags %u).", - cInfo->Entry, cInfo->type_flags, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->type_flags); - } - if (!cInfo->VehicleId && difficultyInfo->VehicleId) { TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, VehicleId %u) has different `VehicleId` in difficulty %u mode (Entry: %u, VehicleId %u).", @@ -6012,8 +6006,9 @@ void ObjectMgr::LoadAccessRequirements() _accessRequirementStore.clear(); // need for reload case } - // 0 1 2 3 4 5 6 7 8 9 - QueryResult result = WorldDatabase.Query("SELECT mapid, difficulty, level_min, level_max, item, item2, quest_done_A, quest_done_H, completed_achievement, quest_failed_text FROM access_requirement"); + // 0 1 2 3 4 5 6 7 8 9 10 + QueryResult result = WorldDatabase.Query("SELECT mapid, difficulty, level_min, level_max, item_level, item, item2, quest_done_A, quest_done_H, completed_achievement, quest_failed_text FROM access_requirement"); + if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 access requirement definitions. DB table `access_requirement` is empty."); @@ -6036,12 +6031,13 @@ void ObjectMgr::LoadAccessRequirements() ar->levelMin = fields[2].GetUInt8(); ar->levelMax = fields[3].GetUInt8(); - ar->item = fields[4].GetUInt32(); - ar->item2 = fields[5].GetUInt32(); - ar->quest_A = fields[6].GetUInt32(); - ar->quest_H = fields[7].GetUInt32(); - ar->achievement = fields[8].GetUInt32(); - ar->questFailedText = fields[9].GetString(); + ar->item_level = fields[4].GetUInt16(); + ar->item = fields[5].GetUInt32(); + ar->item2 = fields[6].GetUInt32(); + ar->quest_A = fields[7].GetUInt32(); + ar->quest_H = fields[8].GetUInt32(); + ar->achievement = fields[9].GetUInt32(); + ar->questFailedText = fields[10].GetString(); if (ar->item) { @@ -7510,6 +7506,10 @@ void ObjectMgr::LoadGameObjectForQuests() { switch (itr->second.type) { + case GAMEOBJECT_TYPE_QUESTGIVER: + _gameObjectForQuestStore.insert(itr->second.entry); + ++count; + break; case GAMEOBJECT_TYPE_CHEST: { // scan GO chest with loot including quest items diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index f5138845012..319b7b589b9 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -835,26 +835,6 @@ namespace Trinity float i_range; }; - class AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck - { - public: - AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck(Unit const* funit, float range) - : i_funit(funit), i_range(range) { } - - bool operator()(const Unit* u) - { - return u->IsAlive() - && i_funit->IsWithinDistInMap(u, i_range) - && !i_funit->IsFriendlyTo(u) - && i_funit->IsValidAttackTarget(u) - && u->GetCreatureType() != CREATURE_TYPE_CRITTER - && i_funit->CanSeeOrDetect(u); - } - private: - Unit const* i_funit; - float i_range; - }; - class CreatureWithDbGUIDCheck { public: diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 354f00a9e91..a3fee2d52aa 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -99,6 +99,7 @@ bool Group::Create(Player* leader) m_guid = MAKE_NEW_GUID(lowguid, 0, HIGHGUID_GROUP); m_leaderGuid = leaderGuid; m_leaderName = leader->GetName(); + leader->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER); if (isBGGroup() || isBFGroup()) m_groupType = GROUPTYPE_BGRAID; @@ -666,6 +667,10 @@ void Group::ChangeLeader(uint64 newLeaderGuid) CharacterDatabase.CommitTransaction(trans); } + if (Player* oldLeader = ObjectAccessor::FindPlayer(m_leaderGuid)) + oldLeader->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER); + + newLeader->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER); m_leaderGuid = newLeader->GetGUID(); m_leaderName = newLeader->GetName(); ToggleGroupMemberFlag(slot, MEMBER_FLAG_ASSISTANT, false); diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index fba575ee84e..45d4d221d06 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -235,18 +235,20 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) recvData.ReadPackedTime(unkPackedTime); recvData >> flags; - CalendarEvent* calendarEvent = new CalendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId, + CalendarEvent calendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId, time_t(eventPackedTime), flags, time_t(unkPackedTime), title, description); - if (calendarEvent->IsGuildEvent() || calendarEvent->IsGuildAnnouncement()) + if (calendarEvent.IsGuildEvent() || calendarEvent.IsGuildAnnouncement()) if (Player* creator = ObjectAccessor::FindPlayer(guid)) - calendarEvent->SetGuildId(creator->GetGuildId()); + calendarEvent.SetGuildId(creator->GetGuildId()); - if (calendarEvent->IsGuildAnnouncement()) + if (calendarEvent.IsGuildAnnouncement()) { // 946684800 is 01/01/2000 00:00:00 - default response time - CalendarInvite* invite = new CalendarInvite(0, calendarEvent->GetEventId(), 0, guid, 946684800, CALENDAR_STATUS_NOT_SIGNED_UP, CALENDAR_RANK_PLAYER, ""); - sCalendarMgr->AddInvite(calendarEvent, invite); + CalendarInvite invite(0, calendarEvent.GetEventId(), 0, guid, 946684800, CALENDAR_STATUS_NOT_SIGNED_UP, CALENDAR_RANK_PLAYER, ""); + // WARNING: By passing pointer to a local variable, the underlying method(s) must NOT perform any kind + // of storage of the pointer as it will lead to memory corruption + sCalendarMgr->AddInvite(&calendarEvent, &invite); } else { @@ -262,12 +264,12 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) recvData >> status >> rank; // 946684800 is 01/01/2000 00:00:00 - default response time - CalendarInvite* invite = new CalendarInvite(sCalendarMgr->GetFreeInviteId(), calendarEvent->GetEventId(), invitee, guid, 946684800, CalendarInviteStatus(status), CalendarModerationRank(rank), ""); - sCalendarMgr->AddInvite(calendarEvent, invite); + CalendarInvite* invite = new CalendarInvite(sCalendarMgr->GetFreeInviteId(), calendarEvent.GetEventId(), invitee, guid, 946684800, CalendarInviteStatus(status), CalendarModerationRank(rank), ""); + sCalendarMgr->AddInvite(&calendarEvent, invite); } } - sCalendarMgr->AddEvent(calendarEvent, CALENDAR_SENDTYPE_ADD); + sCalendarMgr->AddEvent(new CalendarEvent(calendarEvent, calendarEvent.GetEventId()), CALENDAR_SENDTYPE_ADD); } void WorldSession::HandleCalendarUpdateEvent(WorldPacket& recvData) diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 94e9306b29f..333d4d893cd 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1027,6 +1027,9 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) m_playerLoading = false; + // Handle Login-Achievements (should be handled after loading) + _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN, 1); + sScriptMgr->OnPlayerLogin(pCurrChar); delete holder; } @@ -1590,9 +1593,6 @@ void WorldSession::HandleEquipmentSetDelete(WorldPacket &recvData) void WorldSession::HandleEquipmentSetUse(WorldPacket &recvData) { - if (_player->IsInCombat()) - return; - TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_USE"); for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) @@ -1609,6 +1609,10 @@ void WorldSession::HandleEquipmentSetUse(WorldPacket &recvData) if (itemGuid == 1) continue; + // Only equip weapons in combat + if (_player->IsInCombat() && i != EQUIPMENT_SLOT_MAINHAND && i != EQUIPMENT_SLOT_OFFHAND && i != EQUIPMENT_SLOT_RANGED) + continue; + Item* item = _player->GetItemByGuid(itemGuid); uint16 dstpos = i | (INVENTORY_SLOT_BAG_0 << 8); diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index b45840ab190..fbc78564ea5 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -55,6 +55,14 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) return; } + if (lang == LANG_UNIVERSAL && type != CHAT_MSG_AFK && type != CHAT_MSG_DND) + { + TC_LOG_ERROR("network", "CMSG_MESSAGECHAT: Possible hacking-attempt: %s tried to send a message in universal language", GetPlayerInfo().c_str()); + SendNotification(LANG_UNKNOWN_LANGUAGE); + recvData.rfinish(); + return; + } + Player* sender = GetPlayer(); //TC_LOG_DEBUG("CHAT: packet received. type %u, lang %u", type, lang); @@ -67,6 +75,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) recvData.rfinish(); return; } + if (langDesc->skill_id != 0 && !sender->HasSkill(langDesc->skill_id)) { // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) @@ -242,6 +251,10 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) case CHAT_MSG_EMOTE: case CHAT_MSG_YELL: { + // Prevent cheating + if (!sender->IsAlive()) + return; + if (sender->getLevel() < sWorld->getIntConfig(CONFIG_CHAT_SAY_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_SAY_REQ), sWorld->getIntConfig(CONFIG_CHAT_SAY_LEVEL_REQ)); @@ -302,18 +315,18 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) Group* group = GetPlayer()->GetOriginalGroup(); if (!group) { - group = _player->GetGroup(); + group = sender->GetGroup(); if (!group || group->isBGGroup()) return; } - if (type == CHAT_MSG_PARTY_LEADER && !group->IsLeader(_player->GetGUID())) + if (type == CHAT_MSG_PARTY_LEADER && !group->IsLeader(sender->GetGUID())) return; sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); WorldPacket data; - ChatHandler::BuildChatPacket(data, ChatMsg(type), Language(lang), _player, NULL, msg); + ChatHandler::BuildChatPacket(data, ChatMsg(type), Language(lang), sender, NULL, msg); group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID())); } break; case CHAT_MSG_GUILD: @@ -354,7 +367,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID, Language(lang), _player, NULL, msg); + ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID, Language(lang), sender, NULL, msg); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_LEADER: @@ -364,14 +377,14 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) if (!group) { group = GetPlayer()->GetGroup(); - if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetGUID())) + if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(sender->GetGUID())) return; } sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_LEADER, Language(lang), _player, NULL, msg); + ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_LEADER, Language(lang), sender, NULL, msg); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_WARNING: @@ -384,7 +397,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) WorldPacket data; //in battleground, raid warning is sent only to players in battleground - code is ok - ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_WARNING, Language(lang), _player, NULL, msg); + ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_WARNING, Language(lang), sender, NULL, msg); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_BATTLEGROUND: @@ -397,7 +410,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND, Language(lang), _player, NULL, msg); + ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND, Language(lang), sender, NULL, msg); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_BATTLEGROUND_LEADER: @@ -410,74 +423,74 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND_LEADER, Language(lang), _player, NULL, msg);; + ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND_LEADER, Language(lang), sender, NULL, msg);; group->BroadcastPacket(&data, false); } break; case CHAT_MSG_CHANNEL: { if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ)) { - if (_player->getLevel() < sWorld->getIntConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)) + if (sender->getLevel() < sWorld->getIntConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_CHANNEL_REQ), sWorld->getIntConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)); return; } } - if (ChannelMgr* cMgr = ChannelMgr::forTeam(_player->GetTeam())) + if (ChannelMgr* cMgr = ChannelMgr::forTeam(sender->GetTeam())) { - if (Channel* chn = cMgr->GetChannel(channel, _player)) + if (Channel* chn = cMgr->GetChannel(channel, sender)) { - sScriptMgr->OnPlayerChat(_player, type, lang, msg, chn); - chn->Say(_player->GetGUID(), msg.c_str(), lang); + sScriptMgr->OnPlayerChat(sender, type, lang, msg, chn); + chn->Say(sender->GetGUID(), msg.c_str(), lang); } } } break; case CHAT_MSG_AFK: { - if (!_player->IsInCombat()) + if (!sender->IsInCombat()) { - if (_player->isAFK()) // Already AFK + if (sender->isAFK()) // Already AFK { if (msg.empty()) - _player->ToggleAFK(); // Remove AFK + sender->ToggleAFK(); // Remove AFK else - _player->autoReplyMsg = msg; // Update message + sender->autoReplyMsg = msg; // Update message } else // New AFK mode { - _player->autoReplyMsg = msg.empty() ? GetTrinityString(LANG_PLAYER_AFK_DEFAULT) : msg; + sender->autoReplyMsg = msg.empty() ? GetTrinityString(LANG_PLAYER_AFK_DEFAULT) : msg; - if (_player->isDND()) - _player->ToggleDND(); + if (sender->isDND()) + sender->ToggleDND(); - _player->ToggleAFK(); + sender->ToggleAFK(); } - sScriptMgr->OnPlayerChat(_player, type, lang, msg); + sScriptMgr->OnPlayerChat(sender, type, lang, msg); } break; } case CHAT_MSG_DND: { - if (_player->isDND()) // Already DND + if (sender->isDND()) // Already DND { if (msg.empty()) - _player->ToggleDND(); // Remove DND + sender->ToggleDND(); // Remove DND else - _player->autoReplyMsg = msg; // Update message + sender->autoReplyMsg = msg; // Update message } else // New DND mode { - _player->autoReplyMsg = msg.empty() ? GetTrinityString(LANG_PLAYER_DND_DEFAULT) : msg; + sender->autoReplyMsg = msg.empty() ? GetTrinityString(LANG_PLAYER_DND_DEFAULT) : msg; - if (_player->isAFK()) - _player->ToggleAFK(); + if (sender->isAFK()) + sender->ToggleAFK(); - _player->ToggleDND(); + sender->ToggleDND(); } - sScriptMgr->OnPlayerChat(_player, type, lang, msg); + sScriptMgr->OnPlayerChat(sender, type, lang, msg); break; } default: diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index 4fd912298ec..f3a1803dfca 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -223,7 +223,7 @@ void WorldSession::HandleLootOpcode(WorldPacket& recvData) recvData >> guid; // Check possible cheat - if (!_player->IsAlive()) + if (!GetPlayer()->IsAlive() || !IS_CRE_OR_VEH_GUID(guid)) return; GetPlayer()->SendLoot(guid, LOOT_CORPSE); diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 5ab24f44a22..10ef7810d1d 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -29,6 +29,32 @@ #include "Item.h" #include "AccountMgr.h" +bool WorldSession::CanOpenMailBox(uint64 guid) +{ + if (guid == _player->GetGUID()) + { + if (!HasPermission(rbac::RBAC_PERM_COMMAND_MAILBOX)) + { + TC_LOG_WARN("cheat", "%s attempt open mailbox in cheating way.", _player->GetName().c_str()); + return false; + } + } + else if (IS_GAMEOBJECT_GUID(guid)) + { + if (!_player->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_MAILBOX)) + return false; + } + else if (IS_CRE_OR_VEH_OR_PET_GUID(guid)) + { + if (!_player->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_MAILBOX)) + return false; + } + else + return false; + + return true; +} + void WorldSession::HandleSendMail(WorldPacket& recvData) { uint64 mailbox, unk3; @@ -62,7 +88,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) // packet read complete, now do check - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; if (receiverName.empty()) @@ -307,7 +333,7 @@ void WorldSession::HandleMailMarkAsRead(WorldPacket& recvData) recvData >> mailbox; recvData >> mailId; - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -331,7 +357,7 @@ void WorldSession::HandleMailDelete(WorldPacket& recvData) recvData >> mailId; recvData.read_skip<uint32>(); // mailTemplateId - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Mail* m = _player->GetMail(mailId); @@ -359,7 +385,7 @@ void WorldSession::HandleMailReturnToSender(WorldPacket& recvData) recvData >> mailId; recvData.read_skip<uint64>(); // original sender GUID for return to, not used - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -424,7 +450,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData) recvData >> mailId; recvData >> itemId; // item guid low - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -518,7 +544,7 @@ void WorldSession::HandleMailTakeMoney(WorldPacket& recvData) recvData >> mailbox; recvData >> mailId; - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -555,7 +581,7 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData) uint64 mailbox; recvData >> mailbox; - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -678,7 +704,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData) recvData >> mailbox; recvData >> mailId; - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 8b92706bd06..60f4fb09c28 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -734,34 +734,34 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket& recvData) uint64 guid; recvData >> guid; - if (GetPlayer()->IsAlive()) + if (_player->IsAlive()) return; // do not allow corpse reclaim in arena - if (GetPlayer()->InArena()) + if (_player->InArena()) return; // body not released yet - if (!GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + if (!_player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) return; - Corpse* corpse = GetPlayer()->GetCorpse(); + Corpse* corpse = _player->GetCorpse(); if (!corpse) return; // prevent resurrect before 30-sec delay after body release not finished - if (time_t(corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP)) > time_t(time(NULL))) + if (time_t(corpse->GetGhostTime() + _player->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP)) > time_t(time(NULL))) return; - if (!corpse->IsWithinDistInMap(GetPlayer(), CORPSE_RECLAIM_RADIUS, true)) + if (!corpse->IsWithinDistInMap(_player, CORPSE_RECLAIM_RADIUS, true)) return; // resurrect - GetPlayer()->ResurrectPlayer(GetPlayer()->InBattleground() ? 1.0f : 0.5f); + _player->ResurrectPlayer(_player->InBattleground() ? 1.0f : 0.5f); // spawn bones - GetPlayer()->SpawnCorpseBones(); + _player->SpawnCorpseBones(); } void WorldSession::HandleResurrectResponseOpcode(WorldPacket& recvData) @@ -1135,7 +1135,6 @@ void WorldSession::HandleMoveRootAck(WorldPacket& recvData) void WorldSession::HandleSetActionBarToggles(WorldPacket& recvData) { uint8 actionBar; - recvData >> actionBar; if (!GetPlayer()) // ignore until not logged (check needed because STATUS_AUTHED) diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index df6703980d1..fc14797ea94 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -103,6 +103,13 @@ void WorldSession::SendShowBank(uint64 guid) SendPacket(&data); } +void WorldSession::SendShowMailBox(uint64 guid) +{ + WorldPacket data(SMSG_SHOW_MAILBOX, 8); + data << guid; + SendPacket(&data); +} + void WorldSession::HandleTrainerListOpcode(WorldPacket& recvData) { uint64 guid; @@ -383,7 +390,6 @@ void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket& recvData) TC_LOG_DEBUG("network", "WORLD: CMSG_SPIRIT_HEALER_ACTIVATE"); uint64 guid; - recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_SPIRITHEALER); @@ -403,7 +409,6 @@ void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket& recvData) void WorldSession::SendSpiritResurrect() { _player->ResurrectPlayer(0.5f, true); - _player->DurabilityLossAll(0.25f, true); // get corpse nearest graveyard diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index e8d43b55fd8..d4dc7a9ab0d 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -38,42 +38,34 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData) recvData >> guid; uint32 questStatus = DIALOG_STATUS_NONE; - Object* questgiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - if (!questgiver) + Object* questGiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); + if (!questGiver) { TC_LOG_INFO("network", "Error in CMSG_QUESTGIVER_STATUS_QUERY, called for non-existing questgiver (Typeid: %u GUID: %u)", GuidHigh2TypeId(GUID_HIPART(guid)), GUID_LOPART(guid)); return; } - switch (questgiver->GetTypeId()) + switch (questGiver->GetTypeId()) { case TYPEID_UNIT: { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u", questgiver->GetGUIDLow()); - Creature* cr_questgiver = questgiver->ToCreature(); - if (!cr_questgiver->IsHostileTo(_player)) // do not show quest status to enemies - { - questStatus = sScriptMgr->GetDialogStatus(_player, cr_questgiver); - if (questStatus == DIALOG_STATUS_SCRIPTED_NO_STATUS) - questStatus = getDialogStatus(_player, cr_questgiver); - } + TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u", questGiver->GetGUIDLow()); + if (!questGiver->ToCreature()->IsHostileTo(_player)) // do not show quest status to enemies + questStatus = _player->GetQuestDialogStatus(questGiver); break; } case TYPEID_GAMEOBJECT: { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u", questgiver->GetGUIDLow()); - GameObject* go_questgiver = questgiver->ToGameObject(); - questStatus = sScriptMgr->GetDialogStatus(_player, go_questgiver); - if (questStatus == DIALOG_STATUS_SCRIPTED_NO_STATUS) - questStatus = getDialogStatus(_player, go_questgiver); + TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u", questGiver->GetGUIDLow()); + questStatus = _player->GetQuestDialogStatus(questGiver); break; } default: - TC_LOG_ERROR("network", "QuestGiver called for unexpected type %u", questgiver->GetTypeId()); + TC_LOG_ERROR("network", "QuestGiver called for unexpected type %u", questGiver->GetTypeId()); break; } - //inform client about status of quest + // inform client about status of quest _player->PlayerTalkClass->SendQuestGiverStatus(uint8(questStatus), guid); } @@ -174,7 +166,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvData) if (_player->CanAddQuest(quest, true)) { - _player->AddQuest(quest, object); + _player->AddQuestAndCheckCompletion(quest, object); if (quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) { @@ -191,7 +183,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvData) { player->SetDivider(_player->GetGUID()); - //need confirmation that any gossip window will close + // need confirmation that any gossip window will close player->PlayerTalkClass->SendCloseGossip(); _player->SendQuestConfirmAccept(quest, player); @@ -200,45 +192,6 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvData) } } - if (_player->CanCompleteQuest(questId)) - _player->CompleteQuest(questId); - - switch (object->GetTypeId()) - { - case TYPEID_UNIT: - sScriptMgr->OnQuestAccept(_player, (object->ToCreature()), quest); - object->ToCreature()->AI()->sQuestAccept(_player, quest); - break; - case TYPEID_ITEM: - case TYPEID_CONTAINER: - { - Item* item = (Item*)object; - sScriptMgr->OnQuestAccept(_player, item, quest); - - // destroy not required for quest finish quest starting item - bool destroyItem = true; - for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) - { - if (quest->RequiredItemId[i] == item->GetEntry() && item->GetTemplate()->MaxCount > 0) - { - destroyItem = false; - break; - } - } - - if (destroyItem) - _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); - - break; - } - case TYPEID_GAMEOBJECT: - sScriptMgr->OnQuestAccept(_player, object->ToGameObject(), quest); - object->ToGameObject()->AI()->QuestAccept(_player, quest); - break; - default: - break; - } - _player->PlayerTalkClass->SendCloseGossip(); if (quest->GetSrcSpell() > 0) @@ -314,7 +267,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData) TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %u, quest = %u, reward = %u", uint32(GUID_LOPART(guid)), questId, reward); - Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); if (!object || !object->hasInvolvedQuest(questId)) return; @@ -338,7 +291,9 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData) switch (object->GetTypeId()) { case TYPEID_UNIT: - if (!(sScriptMgr->OnQuestReward(_player, (object->ToCreature()), quest, reward))) + { + Creature* questgiver = object->ToCreature(); + if (!sScriptMgr->OnQuestReward(_player, questgiver, quest, reward)) { // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) @@ -349,11 +304,14 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData) _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); } - (object->ToCreature())->AI()->sQuestReward(_player, quest, reward); + questgiver->AI()->sQuestReward(_player, quest, reward); } break; + } case TYPEID_GAMEOBJECT: - if (!sScriptMgr->OnQuestReward(_player, ((GameObject*)object), quest, reward)) + { + GameObject* questGiver = object->ToGameObject(); + if (!sScriptMgr->OnQuestReward(_player, questGiver, quest, reward)) { // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) @@ -364,9 +322,10 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData) _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); } - object->ToGameObject()->AI()->QuestReward(_player, quest, reward); + questGiver->AI()->QuestReward(_player, quest, reward); } break; + } default: break; } @@ -384,7 +343,7 @@ void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket& recvData) TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_REQUEST_REWARD npc = %u, quest = %u", uint32(GUID_LOPART(guid)), questId); - Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); if (!object || !object->hasInvolvedQuest(questId)) return; @@ -468,17 +427,16 @@ void WorldSession::HandleQuestConfirmAccept(WorldPacket& recvData) TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT quest = %u", questId); - if (const Quest* quest = sObjectMgr->GetQuestTemplate(questId)) + if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { if (!quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) return; - Player* pOriginalPlayer = ObjectAccessor::FindPlayer(_player->GetDivider()); - - if (!pOriginalPlayer) + Player* originalPlayer = ObjectAccessor::FindPlayer(_player->GetDivider()); + if (!originalPlayer) return; - if (!_player->IsInSameRaidWith(pOriginalPlayer)) + if (!_player->IsInSameRaidWith(originalPlayer)) return; if (_player->CanAddQuest(quest, true)) @@ -501,7 +459,7 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData) if (!quest) return; - Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); if (!object || !object->hasInvolvedQuest(questId)) return; @@ -638,104 +596,6 @@ void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket) } } -uint32 WorldSession::getDialogStatus(Player* player, Object* questgiver) -{ - uint32 result = DIALOG_STATUS_NONE; - - QuestRelationBounds qr; - QuestRelationBounds qir; - - switch (questgiver->GetTypeId()) - { - case TYPEID_GAMEOBJECT: - { - qr = sObjectMgr->GetGOQuestRelationBounds(questgiver->GetEntry()); - qir = sObjectMgr->GetGOQuestInvolvedRelationBounds(questgiver->GetEntry()); - break; - } - case TYPEID_UNIT: - { - qr = sObjectMgr->GetCreatureQuestRelationBounds(questgiver->GetEntry()); - qir = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(questgiver->GetEntry()); - break; - } - default: - //its imposible, but check ^) - TC_LOG_ERROR("network", "Warning: GetDialogStatus called for unexpected type %u", questgiver->GetTypeId()); - return DIALOG_STATUS_NONE; - } - - for (QuestRelations::const_iterator i = qir.first; i != qir.second; ++i) - { - uint32 result2 = 0; - uint32 quest_id = i->second; - Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id); - if (!quest) - continue; - - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId()); - if (!sConditionMgr->IsObjectMeetToConditions(player, conditions)) - continue; - - QuestStatus status = player->GetQuestStatus(quest_id); - if ((status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(quest_id)) || - (quest->IsAutoComplete() && player->CanTakeQuest(quest, false))) - { - if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) - result2 = DIALOG_STATUS_REWARD_REP; - else - result2 = DIALOG_STATUS_REWARD; - } - else if (status == QUEST_STATUS_INCOMPLETE) - result2 = DIALOG_STATUS_INCOMPLETE; - - if (result2 > result) - result = result2; - } - - for (QuestRelations::const_iterator i = qr.first; i != qr.second; ++i) - { - uint32 result2 = 0; - uint32 quest_id = i->second; - Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id); - if (!quest) - continue; - - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId()); - if (!sConditionMgr->IsObjectMeetToConditions(player, conditions)) - continue; - - QuestStatus status = player->GetQuestStatus(quest_id); - if (status == QUEST_STATUS_NONE) - { - if (player->CanSeeStartQuest(quest)) - { - if (player->SatisfyQuestLevel(quest, false)) - { - if (quest->IsAutoComplete()) - result2 = DIALOG_STATUS_REWARD_REP; - else if (player->getLevel() <= ((player->GetQuestLevel(quest) == -1) ? player->getLevel() : player->GetQuestLevel(quest) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) - { - if (quest->IsDaily()) - result2 = DIALOG_STATUS_AVAILABLE_REP; - else - result2 = DIALOG_STATUS_AVAILABLE; - } - else - result2 = DIALOG_STATUS_LOW_LEVEL_AVAILABLE; - } - else - result2 = DIALOG_STATUS_UNAVAILABLE; - } - } - - if (result2 > result) - result = result2; - } - - return result; -} - void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket*/) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY"); @@ -758,9 +618,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) continue; - questStatus = sScriptMgr->GetDialogStatus(_player, questgiver); - if (questStatus == DIALOG_STATUS_SCRIPTED_NO_STATUS) - questStatus = getDialogStatus(_player, questgiver); + questStatus = _player->GetQuestDialogStatus(questgiver); data << uint64(questgiver->GetGUID()); data << uint8(questStatus); @@ -772,9 +630,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket if (!questgiver || questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) continue; - questStatus = sScriptMgr->GetDialogStatus(_player, questgiver); - if (questStatus == DIALOG_STATUS_SCRIPTED_NO_STATUS) - questStatus = getDialogStatus(_player, questgiver); + questStatus = _player->GetQuestDialogStatus(questgiver); data << uint64(questgiver->GetGUID()); data << uint8(questStatus); diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index bbbe1a4987f..fe893314b87 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -68,6 +68,9 @@ void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData) return; } + if (!unit->isCanTrainingAndResetTalentsOf(_player)) + return; + // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 75a98247186..ba30803e8c2 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -266,19 +266,21 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) void WorldSession::HandleGameObjectUseOpcode(WorldPacket& recvData) { uint64 guid; - recvData >> guid; TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid)); if (GameObject* obj = GetPlayer()->GetMap()->GetGameObject(guid)) { + if (!obj->IsWithinDistInMap(GetPlayer(), obj->GetInteractionDistance())) + return; + // ignore for remote control state - if (_player->m_mover != _player) - if (!(_player->IsOnVehicle(_player->m_mover) || _player->IsMounted()) && !obj->GetGOInfo()->IsUsableMounted()) + if (GetPlayer()->m_mover != GetPlayer()) + if (!(GetPlayer()->IsOnVehicle(GetPlayer()->m_mover) || GetPlayer()->IsMounted()) && !obj->GetGOInfo()->IsUsableMounted()) return; - obj->Use(_player); + obj->Use(GetPlayer()); } } diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp index 4487ae7b15f..34899fc23df 100644 --- a/src/server/game/Handlers/TaxiHandler.cpp +++ b/src/server/game/Handlers/TaxiHandler.cpp @@ -184,6 +184,14 @@ void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket& recvData) { uint32 node; recvData >> node; + + if (!GetPlayer()->m_taxi.IsTaximaskNodeKnown(node) && !GetPlayer()->isTaxiCheater()) + { + SendActivateTaxiReply(ERR_TAXINOTVISITED); + recvData.rfinish(); + return; + } + nodes.push_back(node); } @@ -290,6 +298,15 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recvData) return; } + if (!GetPlayer()->isTaxiCheater()) + { + if (!GetPlayer()->m_taxi.IsTaximaskNodeKnown(nodes[0]) || !GetPlayer()->m_taxi.IsTaximaskNodeKnown(nodes[1])) + { + SendActivateTaxiReply(ERR_TAXINOTVISITED); + return; + } + } + GetPlayer()->ActivateTaxiPathTo(nodes, npc); } diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp index b9949ac631d..688d7e58b6c 100644 --- a/src/server/game/Handlers/TicketHandler.cpp +++ b/src/server/game/Handlers/TicketHandler.cpp @@ -49,13 +49,23 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData) // Player must not have ticket if (!ticket || ticket->IsClosed()) { - ticket = new GmTicket(GetPlayer(), recvData); - + uint32 mapId; + float x, y, z; + std::string message; + uint32 needResponse; + bool needMoreHelp; uint32 count; std::list<uint32> times; uint32 decompressedSize; std::string chatLog; + recvData >> mapId; + recvData >> x >> y >> z; + recvData >> message; + + recvData >> needResponse; + recvData >> needMoreHelp; + recvData >> count; for (uint32 i = 0; i < count; i++) @@ -77,19 +87,25 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData) if (uncompress(dest.contents(), &realSize, recvData.contents() + pos, recvData.size() - pos) == Z_OK) { dest >> chatLog; - ticket->SetChatLog(times, chatLog); } else { TC_LOG_ERROR("network", "CMSG_GMTICKET_CREATE possibly corrupt. Uncompression failed."); recvData.rfinish(); - delete ticket; return; } recvData.rfinish(); // Will still have compressed data in buffer. } + ticket = new GmTicket(GetPlayer()); + ticket->SetPosition(mapId, x, y, z); + ticket->SetMessage(message); + ticket->SetGmAction(needResponse, needMoreHelp); + + if (!chatLog.empty()) + ticket->SetChatLog(times, chatLog); + sTicketMgr->AddTicket(ticket); sTicketMgr->UpdateLastChange(); diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index d224c21efe8..55f745d993b 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -337,6 +337,9 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa if (_owner->GetTypeId() == TYPEID_PLAYER) return; + if (speedXY <= 0.1f) + return; + float x, y, z; float moveTimeHalf = speedZ / Movement::gravity; float dist = 2 * moveTimeHalf * speedXY; @@ -370,6 +373,8 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id) { TC_LOG_DEBUG("misc", "Unit (GUID: %u) jump to point (X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), x, y, z); + if (speedXY <= 0.1f) + return; float moveTimeHalf = speedZ / Movement::gravity; float max_height = -Movement::computeFallElevation(moveTimeHalf, false, -speedZ); diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 97e81de7ecf..ea02b83f2e8 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -931,7 +931,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL }, /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, - /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode }, + /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode }, /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRealmSplitOpcode }, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 8b00cb9432e..0af6069a0e5 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -275,6 +275,8 @@ class WorldSession void SendTrainerList(uint64 guid, std::string const& strTitle); void SendListInventory(uint64 guid); void SendShowBank(uint64 guid); + bool CanOpenMailBox(uint64 guid); + void SendShowMailBox(uint64 guid); void SendTabardVendorActivate(uint64 guid); void SendSpiritResurrect(); void SendBindPoint(Creature* npc); @@ -357,7 +359,6 @@ class WorldSession uint32 GetLatency() const { return m_latency; } void SetLatency(uint32 latency) { m_latency = latency; } void ResetClientTimeDelay() { m_clientTimeDelay = 0; } - uint32 getDialogStatus(Player* player, Object* questgiver); ACE_Atomic_Op<ACE_Thread_Mutex, time_t> m_timeOutTime; void UpdateTimeOutTime(uint32 diff) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 5cb86244aa1..b7aabcc7589 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5351,37 +5351,6 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH)) target->RemoveAurasDueToSpell(31665); break; - // Killing Spree - case 51690: - { - /// @todo this should use effect[1] of 51690 - UnitList targets; - { - // eff_radius == 0 - float radius = GetSpellInfo()->GetMaxRange(false); - - CellCoord p(Trinity::ComputeCellCoord(target->GetPositionX(), target->GetPositionY())); - Cell cell(p); - - Trinity::AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck u_check(target, radius); - Trinity::UnitListSearcher<Trinity::AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck> checker(target, targets, u_check); - - TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); - TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); - - cell.Visit(p, grid_object_checker, *GetBase()->GetOwner()->GetMap(), *target, radius); - cell.Visit(p, world_object_checker, *GetBase()->GetOwner()->GetMap(), *target, radius); - } - - if (targets.empty()) - return; - - Unit* spellTarget = Trinity::Containers::SelectRandomContainerElement(targets); - - target->CastSpell(spellTarget, 57840, true); - target->CastSpell(spellTarget, 57841, true); - break; - } // Overkill case 58428: if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH)) @@ -5874,6 +5843,13 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const else damage = uint32(target->CountPctFromMaxHealth(damage)); + if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + { + damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); + if (caster->GetTypeId() != TYPEID_PLAYER) + damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); + } + bool crit = IsPeriodicTickCrit(target, caster); if (crit) damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target); @@ -6106,8 +6082,10 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (target != caster && GetSpellInfo()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL) { uint32 funnelDamage = GetSpellInfo()->ManaPerSecond; // damage is not affected by spell power - if ((int32)funnelDamage > gain) + + if ((int32)funnelDamage > gain && gain > 0) funnelDamage = gain; + uint32 funnelAbsorb = 0; caster->DealDamageMods(caster, funnelDamage, &funnelAbsorb); caster->SendSpellNonMeleeDamageLog(caster, GetId(), funnelDamage, GetSpellInfo()->GetSchoolMask(), funnelAbsorb, 0, false, 0, false); diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 9c7fff612b7..8e7edfc5355 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1525,11 +1525,8 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b player->RemoveSpellCooldown(GetSpellInfo()->Id, true); player->AddSpellCooldown(GetSpellInfo()->Id, 0, uint32(time(NULL) + aurEff->GetAmount())); - WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+4+4); - data << uint64(player->GetGUID()); - data << uint8(0x0); // flags (0x1, 0x2) - data << uint32(GetSpellInfo()->Id); - data << uint32(aurEff->GetAmount()*IN_MILLISECONDS); + WorldPacket data; + player->BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, GetSpellInfo()->Id, aurEff->GetAmount()*IN_MILLISECONDS); player->SendDirectMessage(&data); } break; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 49eed70f57d..bf6f95d8c92 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -85,9 +85,26 @@ SpellDestination::SpellDestination(WorldObject const& wObj) _transportGUID = wObj.GetTransGUID(); _transportOffset.Relocate(wObj.GetTransOffsetX(), wObj.GetTransOffsetY(), wObj.GetTransOffsetZ(), wObj.GetTransOffsetO()); _position.Relocate(wObj); - _position.SetOrientation(wObj.GetOrientation()); } +void SpellDestination::Relocate(Position const& pos) +{ + if (_transportGUID) + { + Position offset; + _position.GetPositionOffsetTo(pos, offset); + _transportOffset.RelocateOffset(offset); + } + _position.Relocate(pos); +} + +void SpellDestination::RelocateOffset(Position const& offset) +{ + if (_transportGUID) + _transportOffset.RelocateOffset(offset); + + _position.RelocateOffset(offset); +} SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0), m_strTarget() { @@ -350,14 +367,7 @@ void SpellCastTargets::SetSrc(WorldObject const& wObj) void SpellCastTargets::ModSrc(Position const& pos) { ASSERT(m_targetMask & TARGET_FLAG_SOURCE_LOCATION); - - if (m_src._transportGUID) - { - Position offset; - m_src._position.GetPositionOffsetTo(pos, offset); - m_src._transportOffset.RelocateOffset(offset); - } - m_src._position.Relocate(pos); + m_src.Relocate(pos); } void SpellCastTargets::RemoveSrc() @@ -393,6 +403,12 @@ void SpellCastTargets::SetDst(WorldObject const& wObj) m_targetMask |= TARGET_FLAG_DEST_LOCATION; } +void SpellCastTargets::SetDst(SpellDestination const& spellDest) +{ + m_dst = spellDest; + m_targetMask |= TARGET_FLAG_DEST_LOCATION; +} + void SpellCastTargets::SetDst(SpellCastTargets const& spellTargets) { m_dst = spellTargets.m_dst; @@ -402,14 +418,13 @@ void SpellCastTargets::SetDst(SpellCastTargets const& spellTargets) void SpellCastTargets::ModDst(Position const& pos) { ASSERT(m_targetMask & TARGET_FLAG_DEST_LOCATION); + m_dst.Relocate(pos); +} - if (m_dst._transportGUID) - { - Position offset; - m_dst._position.GetPositionOffsetTo(pos, offset); - m_dst._transportOffset.RelocateOffset(offset); - } - m_dst._position.Relocate(pos); +void SpellCastTargets::ModDst(SpellDestination const& spellDest) +{ + ASSERT(m_targetMask & TARGET_FLAG_DEST_LOCATION); + m_dst = spellDest; } void SpellCastTargets::RemoveDst() @@ -1090,24 +1105,13 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge Trinity::Containers::RandomResizeList(targets, maxTargets); } - // for compability with older code - add only unit and go targets - /// @todo remove this - std::list<Unit*> unitTargets; - std::list<GameObject*> gObjTargets; - for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) { if (Unit* unitTarget = (*itr)->ToUnit()) - unitTargets.push_back(unitTarget); + AddUnitTarget(unitTarget, effMask, false); else if (GameObject* gObjTarget = (*itr)->ToGameObject()) - gObjTargets.push_back(gObjTarget); + AddGOTarget(gObjTarget, effMask); } - - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) - AddUnitTarget(*itr, effMask, false); - - for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr) - AddGOTarget(*itr, effMask); } } } @@ -1167,200 +1171,10 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod; SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions); - // Custom entries - /// @todo remove those - switch (m_spellInfo->Id) - { - case 46584: // Raise Dead - { - if (Player* playerCaster = m_caster->ToPlayer()) - { - for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) - { - switch ((*itr)->GetTypeId()) - { - case TYPEID_UNIT: - case TYPEID_PLAYER: - { - Unit* unitTarget = (*itr)->ToUnit(); - if (unitTarget->IsAlive() || !playerCaster->isHonorOrXPTarget(unitTarget) - || ((unitTarget->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0) - || (unitTarget->GetDisplayId() != unitTarget->GetNativeDisplayId())) - break; - AddUnitTarget(unitTarget, effMask, false); - // no break; - } - case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet - m_targets.SetDst(*(*itr)); - return; // nothing more to do here - default: - break; - } - } - } - return; // don't add targets to target map - } - // Corpse Explosion - case 49158: - case 51325: - case 51326: - case 51327: - case 51328: - // check if our target is not valid (spell can target ghoul or dead unit) - if (!(m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId() && - ((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID()) - || m_targets.GetUnitTarget()->isDead()))) - { - // remove existing targets - CleanupTargetList(); - - for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) - { - switch ((*itr)->GetTypeId()) - { - case TYPEID_UNIT: - case TYPEID_PLAYER: - if (!(*itr)->ToUnit()->isDead()) - break; - AddUnitTarget((*itr)->ToUnit(), 1 << effIndex, false); - return; - default: - break; - } - } - if (m_caster->GetTypeId() == TYPEID_PLAYER) - m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); - SendCastResult(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW); - finish(false); - } - return; - default: - break; - } - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex); - std::list<Unit*> unitTargets; - std::list<GameObject*> gObjTargets; - // for compability with older code - add only unit and go targets - /// @todo remove this - for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + if (!targets.empty()) { - if (Unit* unitTarget = (*itr)->ToUnit()) - unitTargets.push_back(unitTarget); - else if (GameObject* gObjTarget = (*itr)->ToGameObject()) - gObjTargets.push_back(gObjTarget); - } - - if (!unitTargets.empty()) - { - // Special target selection for smart heals and energizes - uint32 maxSize = 0; - int32 power = -1; - switch (m_spellInfo->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - switch (m_spellInfo->Id) - { - case 52759: // Ancestral Awakening - case 71610: // Echoes of Light (Althor's Abacus normal version) - case 71641: // Echoes of Light (Althor's Abacus heroic version) - maxSize = 1; - power = POWER_HEALTH; - break; - case 54968: // Glyph of Holy Light - maxSize = m_spellInfo->MaxAffectedTargets; - power = POWER_HEALTH; - break; - case 57669: // Replenishment - // In arenas Replenishment may only affect the caster - if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->InArena()) - { - unitTargets.clear(); - unitTargets.push_back(m_caster); - break; - } - maxSize = 10; - power = POWER_MANA; - break; - default: - break; - } - break; - case SPELLFAMILY_PRIEST: - if (m_spellInfo->SpellFamilyFlags[0] == 0x10000000) // Circle of Healing - { - maxSize = m_caster->HasAura(55675) ? 6 : 5; // Glyph of Circle of Healing - power = POWER_HEALTH; - } - else if (m_spellInfo->Id == 64844) // Divine Hymn - { - maxSize = 3; - power = POWER_HEALTH; - } - else if (m_spellInfo->Id == 64904) // Hymn of Hope - { - maxSize = 3; - power = POWER_MANA; - } - else - break; - - // Remove targets outside caster's raid - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end();) - { - if (!(*itr)->IsInRaidWith(m_caster)) - itr = unitTargets.erase(itr); - else - ++itr; - } - break; - case SPELLFAMILY_DRUID: - if (m_spellInfo->SpellFamilyFlags[1] == 0x04000000) // Wild Growth - { - maxSize = m_caster->HasAura(62970) ? 6 : 5; // Glyph of Wild Growth - power = POWER_HEALTH; - } - else - break; - - // Remove targets outside caster's raid - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end();) - if (!(*itr)->IsInRaidWith(m_caster)) - itr = unitTargets.erase(itr); - else - ++itr; - break; - default: - break; - } - - if (maxSize && power != -1) - { - if (Powers(power) == POWER_HEALTH) - { - if (unitTargets.size() > maxSize) - { - unitTargets.sort(Trinity::HealthPctOrderPred()); - unitTargets.resize(maxSize); - } - } - else - { - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end();) - if ((*itr)->getPowerType() != (Powers)power) - itr = unitTargets.erase(itr); - else - ++itr; - - if (unitTargets.size() > maxSize) - { - unitTargets.sort(Trinity::PowerPctOrderPred((Powers)power)); - unitTargets.resize(maxSize); - } - } - } - // Other special target selection goes here if (uint32 maxTargets = m_spellValue->MaxAffectedTargets) { @@ -1369,138 +1183,138 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge if ((*j)->IsAffectedOnSpell(m_spellInfo)) maxTargets += (*j)->GetAmount(); - Trinity::Containers::RandomResizeList(unitTargets, maxTargets); + Trinity::Containers::RandomResizeList(targets, maxTargets); } - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) - AddUnitTarget(*itr, effMask, false); - } - - if (!gObjTargets.empty()) - { - if (uint32 maxTargets = m_spellValue->MaxAffectedTargets) + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) { - Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); - for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j) - if ((*j)->IsAffectedOnSpell(m_spellInfo)) - maxTargets += (*j)->GetAmount(); - - Trinity::Containers::RandomResizeList(gObjTargets, maxTargets); + if (Unit* unitTarget = (*itr)->ToUnit()) + AddUnitTarget(unitTarget, effMask, false); + else if (GameObject* gObjTarget = (*itr)->ToGameObject()) + AddGOTarget(gObjTarget, effMask); } - - for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr) - AddGOTarget(*itr, effMask); } } void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { + SpellDestination dest(*m_caster); + switch (targetType.GetTarget()) { case TARGET_DEST_CASTER: - m_targets.SetDst(*m_caster); - return; + break; case TARGET_DEST_HOME: if (Player* playerCaster = m_caster->ToPlayer()) - m_targets.SetDst(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId); - return; + dest = SpellDestination(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId); + break; case TARGET_DEST_DB: if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, effIndex)) { /// @todo fix this check if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS) || m_spellInfo->HasEffect(SPELL_EFFECT_BIND)) - m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId); + dest = SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId); else if (st->target_mapId == m_caster->GetMapId()) - m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation); + dest = SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation); } else { TC_LOG_DEBUG("spells", "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id); - WorldObject* target = m_targets.GetObjectTarget(); - m_targets.SetDst(target ? *target : *m_caster); + if (WorldObject* target = m_targets.GetObjectTarget()) + dest = SpellDestination(*target); } - return; + break; case TARGET_DEST_CASTER_FISHING: { - float min_dis = m_spellInfo->GetMinRange(true); - float max_dis = m_spellInfo->GetMaxRange(true); - float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis; - float x, y, z, angle; - angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f); - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle); - - float ground = z; - float liquidLevel = m_caster->GetMap()->GetWaterOrGroundLevel(x, y, z, &ground); - if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level - { - SendCastResult(SPELL_FAILED_NOT_HERE); - SendChannelUpdate(0); - finish(false); - return; - } - - if (ground + 0.75 > liquidLevel) - { - SendCastResult(SPELL_FAILED_TOO_SHALLOW); - SendChannelUpdate(0); - finish(false); - return; - } - - m_targets.SetDst(x, y, liquidLevel, m_caster->GetOrientation()); - return; + float minDist = m_spellInfo->GetMinRange(true); + float maxDist = m_spellInfo->GetMaxRange(true); + float dist = frand(minDist, maxDist); + float x, y, z; + float angle = float(rand_norm()) * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f); + m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dist, angle); + + float ground = z; + float liquidLevel = m_caster->GetMap()->GetWaterOrGroundLevel(x, y, z, &ground); + if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level + { + SendCastResult(SPELL_FAILED_NOT_HERE); + SendChannelUpdate(0); + finish(false); + return; + } + + if (ground + 0.75 > liquidLevel) + { + SendCastResult(SPELL_FAILED_TOO_SHALLOW); + SendChannelUpdate(0); + finish(false); + return; + } + + dest = SpellDestination(x, y, liquidLevel, m_caster->GetOrientation()); + break; } default: - break; - } + { + float dist; + float angle = targetType.CalcDirectionAngle(); + float objSize = m_caster->GetObjectSize(); + if (targetType.GetTarget() == TARGET_DEST_CASTER_SUMMON) + dist = PET_FOLLOW_DIST; + else + dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); - float dist; - float angle = targetType.CalcDirectionAngle(); - float objSize = m_caster->GetObjectSize(); - if (targetType.GetTarget() == TARGET_DEST_CASTER_SUMMON) - dist = PET_FOLLOW_DIST; - else - dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + if (dist < objSize) + dist = objSize; + else if (targetType.GetTarget() == TARGET_DEST_CASTER_RANDOM) + dist = objSize + (dist - objSize) * float(rand_norm()); - if (dist < objSize) - dist = objSize; - else if (targetType.GetTarget() == TARGET_DEST_CASTER_RANDOM) - dist = objSize + (dist - objSize) * (float)rand_norm(); + Position pos = dest._position; + if (targetType.GetTarget() == TARGET_DEST_CASTER_FRONT_LEAP) + m_caster->MovePositionToFirstCollision(pos, dist, angle); + else + m_caster->MovePosition(pos, dist, angle); - Position pos; - if (targetType.GetTarget() == TARGET_DEST_CASTER_FRONT_LEAP) - m_caster->GetFirstCollisionPosition(pos, dist, angle); - else - m_caster->GetNearPosition(pos, dist, angle); - m_targets.SetDst(*m_caster); - m_targets.ModDst(pos); + dest.Relocate(pos); + break; + } + } + + CallScriptDestinationTargetSelectHandlers(dest, effIndex); + m_targets.SetDst(dest); } void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { WorldObject* target = m_targets.GetObjectTarget(); + + SpellDestination dest(*target); + switch (targetType.GetTarget()) { case TARGET_DEST_TARGET_ENEMY: case TARGET_DEST_TARGET_ANY: - m_targets.SetDst(*target); - return; + break; default: + { + float angle = targetType.CalcDirectionAngle(); + float objSize = target->GetObjectSize(); + float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + if (dist < objSize) + dist = objSize; + else if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) + dist = objSize + (dist - objSize) * float(rand_norm()); + + Position pos = dest._position; + target->MovePosition(pos, dist, angle); + + dest.Relocate(pos); break; + } } - float angle = targetType.CalcDirectionAngle(); - float objSize = target->GetObjectSize(); - float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); - if (dist < objSize) - dist = objSize; - else if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) - dist = objSize + (dist - objSize) * (float)rand_norm(); - - Position pos; - target->GetNearPosition(pos, dist, angle); - m_targets.SetDst(*target); - m_targets.ModDst(pos); + CallScriptDestinationTargetSelectHandlers(dest, effIndex); + m_targets.SetDst(dest); } void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) @@ -1509,8 +1323,9 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT // can only happen if previous destination target could not be set for some reason // (not found nearby target, or channel target for example // maybe we should abort the spell in such case? - if (!m_targets.HasDst()) - m_targets.SetDst(*m_caster); + CheckDst(); + + SpellDestination dest(*m_targets.GetDst()); switch (targetType.GetTarget()) { @@ -1520,20 +1335,25 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT case TARGET_DEST_DEST: return; case TARGET_DEST_TRAJ: - SelectImplicitTrajTargets(); + SelectImplicitTrajTargets(effIndex); return; default: + { + float angle = targetType.CalcDirectionAngle(); + float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) + dist *= float(rand_norm()); + + Position pos = dest._position; + m_caster->MovePosition(pos, dist, angle); + + dest.Relocate(pos); break; + } } - float angle = targetType.CalcDirectionAngle(); - float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); - if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) - dist *= (float)rand_norm(); - - Position pos = *m_targets.GetDstPos(); - m_caster->MovePosition(pos, dist, angle); - m_targets.ModDst(pos); + CallScriptDestinationTargetSelectHandlers(dest, effIndex); + m_targets.ModDst(dest); } void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) @@ -1624,14 +1444,9 @@ void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTarg // Chain primary target is added earlier CallScriptObjectAreaTargetSelectHandlers(targets, effIndex); - // for backward compability - std::list<Unit*> unitTargets; for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) if (Unit* unitTarget = (*itr)->ToUnit()) - unitTargets.push_back(unitTarget); - - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) - AddUnitTarget(*itr, effMask, false); + AddUnitTarget(unitTarget, effMask, false); } } @@ -1649,7 +1464,7 @@ float tangent(float x) #define DEBUG_TRAJ(a) //a -void Spell::SelectImplicitTrajTargets() +void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex) { if (!m_targets.HasTraj()) return; @@ -1778,7 +1593,11 @@ void Spell::SelectImplicitTrajTargets() Position trajDst; trajDst.Relocate(x, y, z, m_caster->GetOrientation()); - m_targets.ModDst(trajDst); + SpellDestination dest(*m_targets.GetDst()); + dest.Relocate(trajDst); + + CallScriptDestinationTargetSelectHandlers(dest, effIndex); + m_targets.ModDst(dest); } } @@ -3201,7 +3020,7 @@ void Spell::cast(bool skipCheck) if (this->GetSpellInfo()->DmgClass != SPELL_DAMAGE_CLASS_NONE) if (Pet* playerPet = playerCaster->GetPet()) if (playerPet->IsAlive() && playerPet->isControlled() && (m_targets.GetTargetMask() & TARGET_FLAG_UNIT)) - playerPet->AI()->OwnerAttacked(m_targets.GetObjectTarget()->ToUnit()); + playerPet->AI()->OwnerAttacked(m_targets.GetUnitTarget()); } SetExecutedCurrently(true); @@ -4976,8 +4795,7 @@ SpellCastResult Spell::CheckCast(bool strict) uint32 zone, area; m_caster->GetZoneAndAreaId(zone, area); - SpellCastResult locRes= m_spellInfo->CheckLocation(m_caster->GetMapId(), zone, area, - m_caster->GetTypeId() == TYPEID_PLAYER ? m_caster->ToPlayer() : NULL); + SpellCastResult locRes = m_spellInfo->CheckLocation(m_caster->GetMapId(), zone, area, m_caster->ToPlayer()); if (locRes != SPELL_CAST_OK) return locRes; } @@ -6832,10 +6650,10 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) if (m_damage > 0) { - if (m_spellInfo->Effects[i].IsTargetingArea()) + if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) { m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); - if (m_caster->GetTypeId() == TYPEID_UNIT) + if (m_caster->GetTypeId() != TYPEID_PLAYER) m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); if (m_caster->GetTypeId() == TYPEID_PLAYER) @@ -7177,6 +6995,20 @@ void Spell::CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffI } } +void Spell::CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex) +{ + for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + { + (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_DESTINATION_TARGET_SELECT); + std::list<SpellScript::DestinationTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnDestinationTargetSelect.end(), hookItr = (*scritr)->OnDestinationTargetSelect.begin(); + for (; hookItr != hookItrEnd; ++hookItr) + if (hookItr->IsEffectAffected(m_spellInfo, effIndex)) + hookItr->Call(*scritr, target); + + (*scritr)->_FinishScriptCall(); + } +} + bool Spell::CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToCheck) { // Skip if there are not any script diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 72bc195aec7..031311f2749 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -87,6 +87,9 @@ struct SpellDestination SpellDestination(Position const& pos); SpellDestination(WorldObject const& wObj); + void Relocate(Position const& pos); + void RelocateOffset(Position const& offset); + WorldLocation _position; uint64 _transportGUID; Position _transportOffset; @@ -141,8 +144,10 @@ class SpellCastTargets void SetDst(float x, float y, float z, float orientation, uint32 mapId = MAPID_INVALID); void SetDst(Position const& pos); void SetDst(WorldObject const& wObj); + void SetDst(SpellDestination const& spellDest); void SetDst(SpellCastTargets const& spellTargets); void ModDst(Position const& pos); + void ModDst(SpellDestination const& spellDest); void RemoveDst(); bool HasSrc() const { return GetTargetMask() & TARGET_FLAG_SOURCE_LOCATION; } @@ -359,7 +364,7 @@ class Spell void SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); void SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask); - void SelectImplicitTrajTargets(); + void SelectImplicitTrajTargets(SpellEffIndex effIndex); void SelectEffectTypeImplicitTargets(uint8 effIndex); @@ -552,7 +557,7 @@ class Spell GameObject* focusObject; // Damage and healing in effects need just calculate - int32 m_damage; // Damge in effects count here + int32 m_damage; // Damage in effects count here int32 m_healing; // Healing in effects count here // ****************************************** @@ -636,6 +641,7 @@ class Spell void CallScriptAfterHitHandlers(); void CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex); void CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex); + void CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex); bool CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToCheck); std::list<SpellScript*> m_loadedScripts; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 4e57c538c4d..73d3c39148a 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -682,11 +682,6 @@ void Spell::EffectDummy(SpellEffIndex effIndex) if (!unitTarget && !gameObjTarget && !itemTarget) return; - uint32 spell_id = 0; - int32 bp = 0; - bool triggered = true; - SpellCastTargets targets; - // selection by spell family switch (m_spellInfo->SpellFamilyName) { @@ -723,60 +718,10 @@ void Spell::EffectDummy(SpellEffIndex effIndex) } } break; - case SPELLFAMILY_DEATHKNIGHT: - switch (m_spellInfo->Id) - { - case 46584: // Raise Dead - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - // Do we have talent Master of Ghouls? - if (m_caster->HasAura(52143)) - // summon as pet - bp = 52150; - else - // or guardian - bp = 46585; - - if (m_targets.HasDst()) - targets.SetDst(*m_targets.GetDstPos()); - else - { - targets.SetDst(*m_caster); - // Corpse not found - take reagents (only not triggered cast can take them) - triggered = false; - } - // Remove cooldown - summon spellls have category - m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); - spell_id = 48289; - break; - // Raise dead - take reagents and trigger summon spells - case 48289: - if (m_targets.HasDst()) - targets.SetDst(*m_targets.GetDstPos()); - spell_id = CalculateDamage(0, NULL); - break; - } + default: break; } - //spells triggered by dummy effect should not miss - if (spell_id) - { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id); - - if (!spellInfo) - { - TC_LOG_ERROR("spells", "EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id); - return; - } - - targets.SetUnitTarget(unitTarget); - Spell* spell = new Spell(m_caster, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, m_originalCasterGUID, true); - if (bp) spell->SetSpellValue(SPELLVALUE_BASE_POINT0, bp); - spell->prepare(&targets); - } - // pet auras if (PetAura const* petSpell = sSpellMgr->GetPetAura(m_spellInfo->Id, effIndex)) { @@ -910,7 +855,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!spellInfo) { - TC_LOG_DEBUG("spells", "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id); + TC_LOG_ERROR("spells", "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id); return; } @@ -962,7 +907,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!spellInfo) { - TC_LOG_DEBUG("spells", "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id); + TC_LOG_ERROR("spells", "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id); return; } @@ -4101,65 +4046,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) } break; } - case SPELLFAMILY_PALADIN: - { - // Judgement (seal trigger) - if (m_spellInfo->GetCategory() == SPELLCATEGORY_JUDGEMENT) - { - if (!unitTarget || !unitTarget->IsAlive()) - return; - uint32 spellId1 = 0; - uint32 spellId2 = 0; - - // Judgement self add switch - switch (m_spellInfo->Id) - { - case 53407: spellId1 = 20184; break; // Judgement of Justice - case 20271: // Judgement of Light - case 57774: spellId1 = 20185; break; // Judgement of Light - case 53408: spellId1 = 20186; break; // Judgement of Wisdom - default: - TC_LOG_ERROR("spells", "Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect", m_spellInfo->Id); - return; - } - // all seals have aura dummy in 2 effect - Unit::AuraApplicationMap & sealAuras = m_caster->GetAppliedAuras(); - for (Unit::AuraApplicationMap::iterator iter = sealAuras.begin(); iter != sealAuras.end();) - { - Aura* aura = iter->second->GetBase(); - if (aura->GetSpellInfo()->GetSpellSpecific() == SPELL_SPECIFIC_SEAL) - { - if (AuraEffect* aureff = aura->GetEffect(2)) - if (aureff->GetAuraType() == SPELL_AURA_DUMMY) - { - if (sSpellMgr->GetSpellInfo(aureff->GetAmount())) - spellId2 = aureff->GetAmount(); - break; - } - if (!spellId2) - { - switch (iter->first) - { - // Seal of light, Seal of wisdom, Seal of justice - case 20165: - case 20166: - case 20164: - spellId2 = 54158; - } - } - break; - } - else - ++iter; - } - if (spellId1) - m_caster->CastSpell(unitTarget, spellId1, true); - if (spellId2) - m_caster->CastSpell(unitTarget, spellId2, true); - return; - } - break; - } case SPELLFAMILY_DEATHKNIGHT: { // Pestilence @@ -4978,7 +4864,7 @@ void Spell::EffectQuestClear(SpellEffIndex effIndex) } } - player->RemoveActiveQuest(quest_id); + player->RemoveActiveQuest(quest_id, false); player->RemoveRewardedQuest(quest_id); } @@ -5072,6 +4958,7 @@ void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/) hadPet = false; } + // TODO: Better to fail Hunter's "Revive Pet" at cast instead of here when casting ends Pet* pet = player->GetPet(); // Attempt to get current pet if (!pet || pet->IsAlive()) return; @@ -5799,6 +5686,7 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* TempSummon* summon = map->SummonCreature(entry, pos, properties, duration, caster, m_spellInfo->Id); if (!summon) return; + if (summon->HasUnitTypeMask(UNIT_MASK_GUARDIAN)) ((Guardian*)summon)->InitStatsForLevel(level); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index d51be9b04b5..93f264d2d61 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -814,7 +814,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellPr { if (EventProcFlag & PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS) { - if (!(procExtra & PROC_EX_INTERNAL_DOT)) + if (!(procExtra & PROC_EX_INTERNAL_HOT)) return false; } else if (procExtra & PROC_EX_INTERNAL_HOT) @@ -2714,8 +2714,39 @@ void SpellMgr::UnloadSpellInfoImplicitTargetConditionLists() void SpellMgr::LoadSpellInfoCustomAttributes() { uint32 oldMSTime = getMSTime(); - + uint32 oldMSTime2 = oldMSTime; SpellInfo* spellInfo = NULL; + + QueryResult result = WorldDatabase.Query("SELECT entry, attributes FROM spell_custom_attr"); + + if (!result) + TC_LOG_INFO("server.loading", ">> Loaded 0 spell custom attributes from DB. DB table `spell_custom_attr` is empty."); + else + { + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + + uint32 spellId = fields[0].GetUInt32(); + uint32 attributes = fields[1].GetUInt32(); + + spellInfo = _GetSpellInfo(spellId); + if (!spellInfo) + { + TC_LOG_ERROR("sql.sql", "Table `spell_custom_attr` has wrong spell (entry: %u), ignored.", spellId); + continue; + } + + // TODO: validate attributes + + spellInfo->AttributesCu |= attributes; + ++count; + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u spell custom attributes from DB in %u ms", count, GetMSTimeDiffToNow(oldMSTime2)); + } + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { spellInfo = mSpellInfoMap[i]; @@ -2826,165 +2857,6 @@ void SpellMgr::LoadSpellInfoCustomAttributes() if (spellInfo->SpellVisual[0] == 3879) spellInfo->AttributesCu |= SPELL_ATTR0_CU_CONE_BACK; - switch (spellInfo->Id) - { - case 1776: // Gouge - case 1777: - case 8629: - case 11285: - case 11286: - case 12540: - case 13579: - case 24698: - case 28456: - case 29425: - case 34940: - case 36862: - case 38764: - case 38863: - case 52743: // Head Smack - spellInfo->AttributesCu |= SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER; - break; - case 53: // Backstab - case 2589: - case 2590: - case 2591: - case 8721: - case 11279: - case 11280: - case 11281: - case 25300: - case 26863: - case 48656: - case 48657: - case 703: // Garrote - case 8631: - case 8632: - case 8633: - case 11289: - case 11290: - case 26839: - case 26884: - case 48675: - case 48676: - case 5221: // Shred - case 6800: - case 8992: - case 9829: - case 9830: - case 27001: - case 27002: - case 48571: - case 48572: - case 8676: // Ambush - case 8724: - case 8725: - case 11267: - case 11268: - case 11269: - case 27441: - case 48689: - case 48690: - case 48691: - case 6785: // Ravage - case 6787: - case 9866: - case 9867: - case 27005: - case 48578: - case 48579: - case 21987: // Lash of Pain - case 23959: // Test Stab R50 - case 24825: // Test Backstab - case 58563: // Assassinate Restless Lookout - spellInfo->AttributesCu |= SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET; - break; - case 26029: // Dark Glare - case 37433: // Spout - case 43140: // Flame Breath - case 43215: // Flame Breath - case 70461: // Coldflame Trap - case 72133: // Pain and Suffering - case 73788: // Pain and Suffering - case 73789: // Pain and Suffering - case 73790: // Pain and Suffering - spellInfo->AttributesCu |= SPELL_ATTR0_CU_CONE_LINE; - break; - case 24340: // Meteor - case 26558: // Meteor - case 28884: // Meteor - case 36837: // Meteor - case 38903: // Meteor - case 41276: // Meteor - case 57467: // Meteor - case 26789: // Shard of the Fallen Star - case 31436: // Malevolent Cleave - case 35181: // Dive Bomb - case 40810: // Saber Lash - case 43267: // Saber Lash - case 43268: // Saber Lash - case 42384: // Brutal Swipe - case 45150: // Meteor Slash - case 64688: // Sonic Screech - case 72373: // Shared Suffering - case 71904: // Chaos Bane - case 70492: // Ooze Eruption - case 72505: // Ooze Eruption - case 72624: // Ooze Eruption - case 72625: // Ooze Eruption - // ONLY SPELLS WITH SPELLFAMILY_GENERIC and EFFECT_SCHOOL_DAMAGE - spellInfo->AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE; - break; - case 18500: // Wing Buffet - case 33086: // Wild Bite - case 49749: // Piercing Blow - case 52890: // Penetrating Strike - case 53454: // Impale - case 59446: // Impale - case 62383: // Shatter - case 64777: // Machine Gun - case 65239: // Machine Gun - case 65919: // Impale - case 67858: // Impale - case 67859: // Impale - case 67860: // Impale - case 69293: // Wing Buffet - case 74439: // Machine Gun - case 63278: // Mark of the Faceless (General Vezax) - case 62544: // Thrust (Argent Tournament) - case 64588: // Thrust (Argent Tournament) - case 66479: // Thrust (Argent Tournament) - case 68505: // Thrust (Argent Tournament) - case 62709: // Counterattack! (Argent Tournament) - case 62626: // Break-Shield (Argent Tournament, Player) - case 64590: // Break-Shield (Argent Tournament, Player) - case 64342: // Break-Shield (Argent Tournament, NPC) - case 64686: // Break-Shield (Argent Tournament, NPC) - case 65147: // Break-Shield (Argent Tournament, NPC) - case 68504: // Break-Shield (Argent Tournament, NPC) - case 62874: // Charge (Argent Tournament, Player) - case 68498: // Charge (Argent Tournament, Player) - case 64591: // Charge (Argent Tournament, Player) - case 63003: // Charge (Argent Tournament, NPC) - case 63010: // Charge (Argent Tournament, NPC) - case 68321: // Charge (Argent Tournament, NPC) - case 72255: // Mark of the Fallen Champion (Deathbringer Saurfang) - case 72444: // Mark of the Fallen Champion (Deathbringer Saurfang) - case 72445: // Mark of the Fallen Champion (Deathbringer Saurfang) - case 72446: // Mark of the Fallen Champion (Deathbringer Saurfang) - spellInfo->AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR; - break; - case 64422: // Sonic Screech (Auriaya) - spellInfo->AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE; - spellInfo->AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR; - break; - case 72293: // Mark of the Fallen Champion (Deathbringer Saurfang) - spellInfo->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF0; - break; - default: - break; - } - switch (spellInfo->SpellFamilyName) { case SPELLFAMILY_WARRIOR: diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 7301e693978..c0bcd477e5b 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -203,8 +203,8 @@ void SpellScript::HitHandler::Call(SpellScript* spellScript) (spellScript->*pHitHandlerScript)(); } -SpellScript::TargetHook::TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area) - : _SpellScript::EffectHook(_effectIndex), targetType(_targetType), area(_area) { } +SpellScript::TargetHook::TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area, bool _dest) + : _SpellScript::EffectHook(_effectIndex), targetType(_targetType), area(_area), dest(_dest) { } std::string SpellScript::TargetHook::ToString() { @@ -236,8 +236,9 @@ bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 eff switch (targetInfo.GetObjectType()) { case TARGET_OBJECT_TYPE_SRC: // EMPTY - case TARGET_OBJECT_TYPE_DEST: // EMPTY return false; + case TARGET_OBJECT_TYPE_DEST: // DEST + return dest; default: switch (targetInfo.GetReferenceType()) { @@ -259,7 +260,7 @@ bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 eff } SpellScript::ObjectAreaTargetSelectHandler::ObjectAreaTargetSelectHandler(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) - : TargetHook(_effIndex, _targetType, true) + : TargetHook(_effIndex, _targetType, true, false) { pObjectAreaTargetSelectHandlerScript = _pObjectAreaTargetSelectHandlerScript; } @@ -270,7 +271,7 @@ void SpellScript::ObjectAreaTargetSelectHandler::Call(SpellScript* spellScript, } SpellScript::ObjectTargetSelectHandler::ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) - : TargetHook(_effIndex, _targetType, false) + : TargetHook(_effIndex, _targetType, false, false) { pObjectTargetSelectHandlerScript = _pObjectTargetSelectHandlerScript; } @@ -280,6 +281,17 @@ void SpellScript::ObjectTargetSelectHandler::Call(SpellScript* spellScript, Worl (spellScript->*pObjectTargetSelectHandlerScript)(target); } +SpellScript::DestinationTargetSelectHandler::DestinationTargetSelectHandler(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) + : TargetHook(_effIndex, _targetType, false, true) +{ + DestinationTargetSelectHandlerScript = _DestinationTargetSelectHandlerScript; +} + +void SpellScript::DestinationTargetSelectHandler::Call(SpellScript* spellScript, SpellDestination& target) +{ + (spellScript->*DestinationTargetSelectHandlerScript)(target); +} + bool SpellScript::_Validate(SpellInfo const* entry) { for (std::list<EffectHandler>::iterator itr = OnEffectLaunch.begin(); itr != OnEffectLaunch.end(); ++itr) @@ -306,6 +318,10 @@ bool SpellScript::_Validate(SpellInfo const* entry) if (!(*itr).GetAffectedEffectsMask(entry)) TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnObjectTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + for (std::list<DestinationTargetSelectHandler>::iterator itr = OnDestinationTargetSelect.begin(); itr != OnDestinationTargetSelect.end(); ++itr) + if (!(*itr).GetAffectedEffectsMask(entry)) + TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnDestinationTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + return _SpellScript::_Validate(entry); } @@ -560,16 +576,28 @@ void SpellScript::PreventHitDefaultEffect(SpellEffIndex effIndex) m_hitPreventDefaultEffectMask |= 1 << effIndex; } -int32 SpellScript::GetEffectValue() +int32 SpellScript::GetEffectValue() const { if (!IsInEffectHook()) { - TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::PreventHitDefaultEffect was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::GetEffectValue was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); return 0; } + return m_spell->damage; } +void SpellScript::SetEffectValue(int32 value) +{ + if (!IsInEffectHook()) + { + TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::SetEffectValue was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + return; + } + + m_spell->damage = value; +} + Item* SpellScript::GetCastItem() { return m_spell->m_CastItem; diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 75cf63b495b..6378a8bed9b 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -135,6 +135,7 @@ enum SpellScriptHookType SPELL_SCRIPT_HOOK_AFTER_HIT, SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT, SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT, + SPELL_SCRIPT_HOOK_DESTINATION_TARGET_SELECT, SPELL_SCRIPT_HOOK_CHECK_CAST, SPELL_SCRIPT_HOOK_BEFORE_CAST, SPELL_SCRIPT_HOOK_ON_CAST, @@ -158,7 +159,8 @@ class SpellScript : public _SpellScript typedef void(CLASSNAME::*SpellHitFnType)(); \ typedef void(CLASSNAME::*SpellCastFnType)(); \ typedef void(CLASSNAME::*SpellObjectAreaTargetSelectFnType)(std::list<WorldObject*>&); \ - typedef void(CLASSNAME::*SpellObjectTargetSelectFnType)(WorldObject*&); + typedef void(CLASSNAME::*SpellObjectTargetSelectFnType)(WorldObject*&); \ + typedef void(CLASSNAME::*SpellDestinationTargetSelectFnType)(SpellDestination&); SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript) @@ -203,12 +205,13 @@ class SpellScript : public _SpellScript class TargetHook : public _SpellScript::EffectHook { public: - TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area); + TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area, bool _dest); bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex); std::string ToString(); protected: uint16 targetType; bool area; + bool dest; }; class ObjectAreaTargetSelectHandler : public TargetHook @@ -224,18 +227,28 @@ class SpellScript : public _SpellScript { public: ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); - void Call(SpellScript* spellScript, WorldObject*& targets); + void Call(SpellScript* spellScript, WorldObject*& target); private: SpellObjectTargetSelectFnType pObjectTargetSelectHandlerScript; }; + class DestinationTargetSelectHandler : public TargetHook + { + public: + DestinationTargetSelectHandler(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); + void Call(SpellScript* spellScript, SpellDestination& target); + private: + SpellDestinationTargetSelectFnType DestinationTargetSelectHandlerScript; + }; + #define SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \ class CastHandlerFunction : public SpellScript::CastHandler { public: CastHandlerFunction(SpellCastFnType _pCastHandlerScript) : SpellScript::CastHandler((SpellScript::SpellCastFnType)_pCastHandlerScript) { } }; \ class CheckCastHandlerFunction : public SpellScript::CheckCastHandler { public: CheckCastHandlerFunction(SpellCheckCastFnType _checkCastHandlerScript) : SpellScript::CheckCastHandler((SpellScript::SpellCheckCastFnType)_checkCastHandlerScript) { } }; \ class EffectHandlerFunction : public SpellScript::EffectHandler { public: EffectHandlerFunction(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : SpellScript::EffectHandler((SpellScript::SpellEffectFnType)_pEffectHandlerScript, _effIndex, _effName) { } }; \ class HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) { } }; \ class ObjectAreaTargetSelectHandlerFunction : public SpellScript::ObjectAreaTargetSelectHandler { public: ObjectAreaTargetSelectHandlerFunction(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectAreaTargetSelectHandler((SpellScript::SpellObjectAreaTargetSelectFnType)_pObjectAreaTargetSelectHandlerScript, _effIndex, _targetType) { } }; \ - class ObjectTargetSelectHandlerFunction : public SpellScript::ObjectTargetSelectHandler { public: ObjectTargetSelectHandlerFunction(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectTargetSelectHandler((SpellScript::SpellObjectTargetSelectFnType)_pObjectTargetSelectHandlerScript, _effIndex, _targetType) { } }; + class ObjectTargetSelectHandlerFunction : public SpellScript::ObjectTargetSelectHandler { public: ObjectTargetSelectHandlerFunction(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectTargetSelectHandler((SpellScript::SpellObjectTargetSelectFnType)_pObjectTargetSelectHandlerScript, _effIndex, _targetType) { } }; \ + class DestinationTargetSelectHandlerFunction : public SpellScript::DestinationTargetSelectHandler { public: DestinationTargetSelectHandlerFunction(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::DestinationTargetSelectHandler((SpellScript::SpellDestinationTargetSelectFnType)_DestinationTargetSelectHandlerScript, _effIndex, _targetType) { } }; #define PrepareSpellScript(CLASSNAME) SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) public: @@ -299,11 +312,17 @@ class SpellScript : public _SpellScript HookList<ObjectTargetSelectHandler> OnObjectTargetSelect; #define SpellObjectTargetSelectFn(F, I, N) ObjectTargetSelectHandlerFunction(&F, I, N) + // example: OnDestinationTargetSelect += SpellDestinationTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); + // where function is void function(SpellDestination& target) + HookList<DestinationTargetSelectHandler> OnDestinationTargetSelect; + #define SpellDestinationTargetSelectFn(F, I, N) DestinationTargetSelectHandlerFunction(&F, I, N) + // hooks are executed in following order, at specified event of spell: // 1. BeforeCast - executed when spell preparation is finished (when cast bar becomes full) before cast is handled // 2. OnCheckCast - allows to override result of CheckCast function // 3a. OnObjectAreaTargetSelect - executed just before adding selected targets to final target list (for area targets) // 3b. OnObjectTargetSelect - executed just before adding selected target to final target list (for single unit targets) + // 3c. OnDestinationTargetSelect - executed just before adding selected target to final target list (for destination targets) // 4. OnCast - executed just before spell is launched (creates missile) or executed // 5. AfterCast - executed after spell missile is launched and immediate spell actions are done // 6. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched @@ -392,7 +411,8 @@ class SpellScript : public _SpellScript void PreventHitDefaultEffect(SpellEffIndex effIndex); // method avalible only in EffectHandler method - int32 GetEffectValue(); + int32 GetEffectValue() const; + void SetEffectValue(int32 value); // returns: cast item if present. Item* GetCastItem(); diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp index 83c049363d4..43c9ba80e24 100644 --- a/src/server/game/Tickets/TicketMgr.cpp +++ b/src/server/game/Tickets/TicketMgr.cpp @@ -34,26 +34,13 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; } // GM ticket GmTicket::GmTicket() : _id(0), _playerGuid(0), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), - _needResponse(false), _haveTicket(false) { } + _needResponse(false), _needMoreHelp(false) { } -GmTicket::GmTicket(Player* player, WorldPacket& recvData) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _haveTicket(false) +GmTicket::GmTicket(Player* player) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needResponse(false), _needMoreHelp(false) { _id = sTicketMgr->GenerateTicketId(); _playerName = player->GetName(); _playerGuid = player->GetGUID(); - - uint32 mapId; - recvData >> mapId; // Map is sent as UInt32! - _mapId = mapId; - - recvData >> _posX; - recvData >> _posY; - recvData >> _posZ; - recvData >> _message; - uint32 needResponse; - recvData >> needResponse; - _needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default) - recvData >> _haveTicket; // Requests further GM interaction on a ticket to which a GM has already responded. Basically means "has a new ticket" } GmTicket::~GmTicket() { } @@ -80,7 +67,7 @@ bool GmTicket::LoadFromDB(Field* fields) _completed = fields[++index].GetBool(); _escalatedStatus = GMTicketEscalationStatus(fields[++index].GetUInt8()); _viewed = fields[++index].GetBool(); - _haveTicket = fields[++index].GetBool(); + _needMoreHelp = fields[++index].GetBool(); return true; } @@ -107,7 +94,7 @@ void GmTicket::SaveToDB(SQLTransaction& trans) const stmt->setBool (++index, _completed); stmt->setUInt8 (++index, uint8(_escalatedStatus)); stmt->setBool (++index, _viewed); - stmt->setBool (++index, _haveTicket); + stmt->setBool (++index, _needMoreHelp); CharacterDatabase.ExecuteOrAppend(trans, stmt); } @@ -124,7 +111,7 @@ void GmTicket::WritePacket(WorldPacket& data) const data << uint32(GMTICKET_STATUS_HASTEXT); data << uint32(_id); data << _message; - data << uint8(_haveTicket); + data << uint8(_needMoreHelp); data << GetAge(_lastModifiedTime); if (GmTicket* ticket = sTicketMgr->GetOldestOpenTicket()) data << GetAge(ticket->GetLastModifiedTime()); @@ -220,6 +207,20 @@ void GmTicket::SetUnassigned() } } +void GmTicket::SetPosition(uint32 mapId, float x, float y, float z) +{ + _mapId = mapId; + _posX = x; + _posY = y; + _posZ = z; +} + +void GmTicket::SetGmAction(uint32 needResponse, bool needMoreHelp) +{ + _needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default) + _needMoreHelp = needMoreHelp; // Requests further GM interaction on a ticket to which a GM has already responded. Basically means "has a new ticket" +} + void GmTicket::TeleportTo(Player* player) const { player->TeleportTo(_mapId, _posX, _posY, _posZ, 0.0f, 0); diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h index 3dd048189d7..5bfe78abbba 100644 --- a/src/server/game/Tickets/TicketMgr.h +++ b/src/server/game/Tickets/TicketMgr.h @@ -82,7 +82,7 @@ class GmTicket { public: GmTicket(); - GmTicket(Player* player, WorldPacket& recvData); + GmTicket(Player* player); ~GmTicket(); bool IsClosed() const { return _closedBy; } @@ -129,6 +129,8 @@ public: void SetComment(std::string const& comment) { _comment = comment; } void SetViewed() { _viewed = true; } void SetUnassigned(); + void SetPosition(uint32 mapId, float x, float y, float z); + void SetGmAction(uint32 needResponse, bool needMoreHelp); void AppendResponse(std::string const& response) { _response += response; } @@ -164,7 +166,7 @@ private: GMTicketEscalationStatus _escalatedStatus; bool _viewed; bool _needResponse; /// @todo find out the use of this, and then store it in DB - bool _haveTicket; + bool _needMoreHelp; std::string _response; std::string _chatLog; // No need to store in db, will be refreshed every session client side }; diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp index 4611a4da884..42872bba22e 100644 --- a/src/server/game/Warden/Warden.cpp +++ b/src/server/game/Warden/Warden.cpp @@ -223,6 +223,9 @@ std::string Warden::Penalty(WardenCheck* check /*= NULL*/) void WorldSession::HandleWardenDataOpcode(WorldPacket& recvData) { + if (!_warden) + return; + _warden->DecryptData(recvData.contents(), recvData.size()); uint8 opcode; recvData >> opcode; diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp index b9133c9d0b1..cb332df9a41 100644 --- a/src/server/game/Weather/Weather.cpp +++ b/src/server/game/Weather/Weather.cpp @@ -194,7 +194,6 @@ bool Weather::ReGenerate() void Weather::SendWeatherUpdateToPlayer(Player* player) { WorldPacket data(SMSG_WEATHER, (4+4+4)); - data << uint32(GetWeatherState()) << (float)m_grade << uint8(0); player->GetSession()->SendPacket(&data); } @@ -202,10 +201,6 @@ void Weather::SendWeatherUpdateToPlayer(Player* player) /// Send the new weather to all players in the zone bool Weather::UpdateWeather() { - Player* player = sWorld->FindPlayerInZone(m_zone); - if (!player) - return false; - ///- Send the weather packet to all players in this zone if (m_grade >= 1) m_grade = 0.9999f; @@ -215,8 +210,13 @@ bool Weather::UpdateWeather() WeatherState state = GetWeatherState(); WorldPacket data(SMSG_WEATHER, (4+4+4)); - data << uint32(state) << (float)m_grade << uint8(0); - player->SendMessageToSet(&data, true); + data << uint32(state); + data << (float)m_grade; + data << uint8(0); + + //- Returns false if there were no players found to update + if (!sWorld->SendZoneMessage(m_zone, &data)) + return false; ///- Log the event char const* wthstr; @@ -263,8 +263,8 @@ bool Weather::UpdateWeather() wthstr = "fine"; break; } - TC_LOG_INFO("misc", "Change the weather of zone %u to %s.", m_zone, wthstr); + TC_LOG_INFO("misc", "Change the weather of zone %u to %s.", m_zone, wthstr); sScriptMgr->OnWeatherChange(this, state, m_grade); return true; } diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp index e327836fa4a..886a910becc 100644 --- a/src/server/game/Weather/WeatherMgr.cpp +++ b/src/server/game/Weather/WeatherMgr.cpp @@ -145,7 +145,6 @@ void LoadWeatherData() void SendFineWeatherUpdateToPlayer(Player* player) { WorldPacket data(SMSG_WEATHER, (4+4+4)); - data << (uint32)WEATHER_STATE_FINE << (float)0.0f << uint8(0); player->GetSession()->SendPacket(&data); } diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index d5bd0974922..af2fb90ea1b 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -169,10 +169,7 @@ Player* World::FindPlayerInZone(uint32 zone) continue; if (player->IsInWorld() && player->GetZoneId() == zone) - { - // Used by the weather system. We return the player to broadcast the change weather message to him and all players in the zone. return player; - } } return NULL; } @@ -1265,6 +1262,8 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_PACKET_SPOOF_BANDURATION] = sConfigMgr->GetIntDefault("PacketSpoof.BanDuration", 86400); + m_int_configs[CONFIG_BIRTHDAY_TIME] = sConfigMgr->GetIntDefault("BirthdayTime", 1222964635); + // call ScriptMgr if we're reloading the configuration if (reload) sScriptMgr->OnConfigLoad(reload); @@ -2278,9 +2277,11 @@ void World::SendGlobalText(const char* text, WorldSession* self) } /// Send a packet to all players (or players selected team) in the zone (except self if mentioned) -void World::SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self, uint32 team) +bool World::SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self, uint32 team) { + bool foundPlayerToSend = false; SessionMap::const_iterator itr; + for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { if (itr->second && @@ -2291,8 +2292,11 @@ void World::SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self (team == 0 || itr->second->GetPlayer()->GetTeam() == team)) { itr->second->SendPacket(packet); + foundPlayerToSend = true; } } + + return foundPlayerToSend; } /// Send a System Message to all players in the zone (except self if mentioned) diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 8c8aebf97d9..4c43507d038 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -339,6 +339,7 @@ enum WorldIntConfigs CONFIG_BG_REWARD_WINNER_ARENA_LAST, CONFIG_BG_REWARD_LOSER_HONOR_FIRST, CONFIG_BG_REWARD_LOSER_HONOR_LAST, + CONFIG_BIRTHDAY_TIME, INT_CONFIG_VALUE_COUNT }; @@ -628,7 +629,7 @@ class World void SendGMText(int32 string_id, ...); void SendGlobalMessage(WorldPacket* packet, WorldSession* self = 0, uint32 team = 0); void SendGlobalGMMessage(WorldPacket* packet, WorldSession* self = 0, uint32 team = 0); - void SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self = 0, uint32 team = 0); + bool SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self = 0, uint32 team = 0); void SendZoneText(uint32 zone, const char *text, WorldSession* self = 0, uint32 team = 0); void SendServerMessage(ServerMessageType type, const char *text = "", Player* player = NULL); diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp index b1a3dd4bca5..aa90c21c995 100644 --- a/src/server/scripts/Commands/cs_ban.cpp +++ b/src/server/scripts/Commands/cs_ban.cpp @@ -205,7 +205,7 @@ public: else handler->PSendSysMessage(LANG_BAN_YOUBANNED, nameOrIP.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); } - else + else { if (sWorld->getBoolConfig(CONFIG_SHOW_BAN_IN_WORLD)) sWorld->SendWorldText(LANG_BAN_ACCOUNT_YOUPERMBANNEDMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), nameOrIP.c_str(), reasonStr); diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index 55e22a8c99a..498ee68ba11 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -198,33 +198,34 @@ public: //Enable\Disable Invisible mode static bool HandleGMVisibleCommand(ChatHandler* handler, char const* args) { + Player* _player = handler->GetSession()->GetPlayer(); + if (!*args) { - handler->PSendSysMessage(LANG_YOU_ARE, handler->GetSession()->GetPlayer()->isGMVisible() ? handler->GetTrinityString(LANG_VISIBLE) : handler->GetTrinityString(LANG_INVISIBLE)); + handler->PSendSysMessage(LANG_YOU_ARE, _player->isGMVisible() ? handler->GetTrinityString(LANG_VISIBLE) : handler->GetTrinityString(LANG_INVISIBLE)); return true; } const uint32 VISUAL_AURA = 37800; std::string param = (char*)args; - Player* player = handler->GetSession()->GetPlayer(); if (param == "on") { - if (player->HasAura(VISUAL_AURA, 0)) - player->RemoveAurasDueToSpell(VISUAL_AURA); + if (_player->HasAura(VISUAL_AURA, 0)) + _player->RemoveAurasDueToSpell(VISUAL_AURA); - player->SetGMVisible(true); + _player->SetGMVisible(true); + _player->UpdateObjectVisibility(); handler->GetSession()->SendNotification(LANG_INVISIBLE_VISIBLE); return true; } if (param == "off") { + _player->AddAura(VISUAL_AURA, _player); + _player->SetGMVisible(false); + _player->UpdateObjectVisibility(); handler->GetSession()->SendNotification(LANG_INVISIBLE_INVISIBLE); - player->SetGMVisible(false); - - player->AddAura(VISUAL_AURA, player); - return true; } @@ -236,12 +237,11 @@ public: //Enable\Disable GM Mode static bool HandleGMCommand(ChatHandler* handler, char const* args) { + Player* _player = handler->GetSession()->GetPlayer(); + if (!*args) { - if (handler->GetSession()->GetPlayer()->IsGameMaster()) - handler->GetSession()->SendNotification(LANG_GM_ON); - else - handler->GetSession()->SendNotification(LANG_GM_OFF); + handler->GetSession()->SendNotification(_player->IsGameMaster() ? LANG_GM_ON : LANG_GM_OFF); return true; } @@ -249,9 +249,9 @@ public: if (param == "on") { - handler->GetSession()->GetPlayer()->SetGameMaster(true); + _player->SetGameMaster(true); handler->GetSession()->SendNotification(LANG_GM_ON); - handler->GetSession()->GetPlayer()->UpdateTriggerVisibility(); + _player->UpdateTriggerVisibility(); #ifdef _DEBUG_VMAPS VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); vMapManager->processCommand("stoplog"); @@ -261,9 +261,9 @@ public: if (param == "off") { - handler->GetSession()->GetPlayer()->SetGameMaster(false); + _player->SetGameMaster(false); handler->GetSession()->SendNotification(LANG_GM_OFF); - handler->GetSession()->GetPlayer()->UpdateTriggerVisibility(); + _player->UpdateTriggerVisibility(); #ifdef _DEBUG_VMAPS VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); vMapManager->processCommand("startlog"); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 1b8f50b5eab..6de8a155d01 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -94,6 +94,7 @@ public: { "unpossess", rbac::RBAC_PERM_COMMAND_UNPOSSESS, false, &HandleUnPossessCommand, "", NULL }, { "unstuck", rbac::RBAC_PERM_COMMAND_UNSTUCK, true, &HandleUnstuckCommand, "", NULL }, { "wchange", rbac::RBAC_PERM_COMMAND_WCHANGE, false, &HandleChangeWeather, "", NULL }, + { "mailbox", rbac::RBAC_PERM_COMMAND_MAILBOX, false, &HandleMailBoxCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; return commandTable; @@ -813,11 +814,12 @@ public: if (kickReason != NULL) kickReasonStr = kickReason; - if (sWorld->getBoolConfig(CONFIG_SHOW_KICK_IN_WORLD)) - sWorld->SendWorldText(LANG_COMMAND_KICKMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), playerName.c_str(), kickReasonStr.c_str()); - else - handler->PSendSysMessage(LANG_COMMAND_KICKMESSAGE, playerName.c_str()); - target->GetSession()->KickPlayer(); + if (sWorld->getBoolConfig(CONFIG_SHOW_KICK_IN_WORLD)) + sWorld->SendWorldText(LANG_COMMAND_KICKMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), playerName.c_str(), kickReasonStr.c_str()); + else + handler->PSendSysMessage(LANG_COMMAND_KICKMESSAGE, playerName.c_str()); + + target->GetSession()->KickPlayer(); return true; } @@ -1337,23 +1339,20 @@ public: return false; } - std::string tNameLink = handler->GetNameLink(target); - - if (!target->GetSkillValue(skill)) - { - handler->PSendSysMessage(LANG_SET_SKILL_ERROR, tNameLink.c_str(), skill, skillLine->name[handler->GetSessionDbcLocale()]); - handler->SetSentErrorMessage(true); - return false; - } + bool targetHasSkill = target->GetSkillValue(skill); - uint16 max = maxPureSkill ? atol (maxPureSkill) : target->GetPureMaxSkillValue(skill); + // If our target does not yet have the skill they are trying to add to them, the chosen level also becomes + // the max level of the new profession. + uint16 max = maxPureSkill ? atol (maxPureSkill) : targetHasSkill ? target->GetPureMaxSkillValue(skill) : uint16(level); if (level <= 0 || level > max || max <= 0) return false; - target->SetSkill(skill, target->GetSkillStep(skill), level, max); - handler->PSendSysMessage(LANG_SET_SKILL, skill, skillLine->name[handler->GetSessionDbcLocale()], tNameLink.c_str(), level, max); - + // If the player has the skill, we get the current skill step. If they don't have the skill, we + // add the skill to the player's book with step 1 (which is the first rank, in most cases something + // like 'Apprentice <skill>'. + target->SetSkill(skill, targetHasSkill ? target->GetSkillStep(skill) : 1, level, max); + handler->PSendSysMessage(LANG_SET_SKILL, skill, skillLine->name[handler->GetSessionDbcLocale()], handler->GetNameLink(target).c_str(), level, max); return true; } @@ -1840,7 +1839,7 @@ public: target->GetSession()->m_muteTime = muteTime; stmt->setInt64(0, muteTime); std::string nameLink = handler->playerLink(targetName); - + if (sWorld->getBoolConfig(CONFIG_SHOW_MUTE_IN_WORLD)) { sWorld->SendWorldText(LANG_COMMAND_MUTEMESSAGE_WORLD, (handler->GetSession() ? handler->GetSession()->GetPlayerName().c_str() : "Server"), nameLink.c_str(), notSpeakTime, muteReasonStr.c_str()); @@ -2480,6 +2479,14 @@ public: player->StopCastingBindSight(); return true; } + + static bool HandleMailBoxCommand(ChatHandler* handler, char const* /*args*/) + { + Player* player = handler->GetSession()->GetPlayer(); + + handler->GetSession()->SendShowMailBox(player->GetGUID()); + return true; + } }; void AddSC_misc_commandscript() diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index 01e28b0910d..369a8e87289 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -147,7 +147,7 @@ public: } } - player->RemoveActiveQuest(entry); + player->RemoveActiveQuest(entry, false); player->RemoveRewardedQuest(entry); handler->SendSysMessage(LANG_COMMAND_QUEST_REMOVED); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp index 845db0cac1c..1edb1100289 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp @@ -74,7 +74,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Moira = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_MOIRA) : 0)) + if (Creature* Moira = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MOIRA))) { Moira->AI()->EnterEvadeMode(); Moira->setFaction(35); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp index fe38377341b..8989a8065dc 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp @@ -191,7 +191,7 @@ public: void SetData(uint32 type, uint32 data) OVERRIDE { - if (instance && type == AREATRIGGER && data == AREATRIGGER_BLACKROCK_STADIUM) + if (type == AREATRIGGER && data == AREATRIGGER_BLACKROCK_STADIUM) { if (!gythEvent) { diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp index d292e5f7701..3930656f0e1 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp @@ -183,7 +183,7 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance && instance->GetBossState(BOSS_FLAMEGOR) != DONE) + if (instance->GetBossState(BOSS_FLAMEGOR) != DONE) { EnterEvadeMode(); return; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp index b8a3c157c52..8d25fe117fe 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp @@ -45,7 +45,7 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance && instance->GetBossState(BOSS_BROODLORD) != DONE) + if (instance->GetBossState(BOSS_BROODLORD) != DONE) { EnterEvadeMode(); return; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp index 706f376e882..cbd625e852a 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp @@ -45,7 +45,7 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance && instance->GetBossState(BOSS_BROODLORD) != DONE) + if (instance->GetBossState(BOSS_BROODLORD) != DONE) { EnterEvadeMode(); return; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp index e262cba1978..390bcaa3c9d 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp @@ -50,7 +50,7 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance && instance->GetBossState(BOSS_BROODLORD) != DONE) + if (instance->GetBossState(BOSS_BROODLORD) != DONE) { EnterEvadeMode(); return; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp index 945d8b40d32..02662cd235c 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp @@ -223,16 +223,14 @@ public: void SetData(uint32 type, uint32 data) OVERRIDE { - if (instance && type == 1 && data == 1) + if ( type == 1 && data == 1) { me->StopMoving(); events.ScheduleEvent(EVENT_PATH_2, 9000); } - if (instance && type == 1 && data == 2) - { + if (type == 1 && data == 2) events.ScheduleEvent(EVENT_SUCCESS_1, 5000); - } } void UpdateAI(uint32 diff) OVERRIDE diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp index 294b662aea7..d2bd82447dc 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp @@ -96,7 +96,7 @@ class boss_majordomo : public CreatureScript void UpdateAI(uint32 diff) OVERRIDE { - if (instance && instance->GetBossState(BOSS_MAJORDOMO_EXECUTUS) != DONE) + if (instance->GetBossState(BOSS_MAJORDOMO_EXECUTUS) != DONE) { if (!UpdateVictim()) return; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp index 4e135ad513a..4d22ba6abb3 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -233,7 +233,7 @@ class boss_ragnaros : public CreatureScript break; case EVENT_SUBMERGE: { - if (instance && !_isBanished) + if (!_isBanished) { //Creature spawning and ragnaros becomming unattackable //is not very well supported in the core //no it really isnt diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index d26458be82e..2b50c525f78 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -193,15 +193,10 @@ public: instance->HandleGameObject(0, false, go); } - void SetInFace(bool bBool) + void SetInFace(bool isRight) { - if (bBool) - { - if (GameObject* go = GameObject::GetGameObject(*me, instance->GetData64(DATA_GO_CAVE_IN_RIGHT))) - me->SetFacingToObject(go); - }else - if (GameObject* go = GameObject::GetGameObject(*me, instance->GetData64(DATA_GO_CAVE_IN_LEFT))) - me->SetFacingToObject(go); + if (GameObject* go = GameObject::GetGameObject(*me, instance->GetData64(isRight ? DATA_GO_CAVE_IN_RIGHT : DATA_GO_CAVE_IN_LEFT))) + me->SetFacingToObject(go); } void RestoreAll() diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp index 36bb2e32cb6..2dff776c35a 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp @@ -252,7 +252,7 @@ public: if (!UpdateVictim()) return; - if (instance && !instance->GetData(TYPE_MOROES)) + if (!instance->GetData(TYPE_MOROES)) { EnterEvadeMode(); return; @@ -371,7 +371,7 @@ struct boss_moroes_guestAI : public ScriptedAI void UpdateAI(uint32 /*diff*/) OVERRIDE { - if (instance && !instance->GetData(TYPE_MOROES)) + if (!instance->GetData(TYPE_MOROES)) EnterEvadeMode(); DoMeleeAttackIfReady(); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp index 1b9ef055b8c..ebd8762e9be 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp @@ -247,13 +247,13 @@ public: PortalPhase = false; Talk(EMOTE_PHASE_BANISH); - for (int i=0; i<3; ++i) + for (uint8 i = 0; i < 3; ++i) me->RemoveAurasDueToSpell(NetherBuff[i]); } void HandleDoors(bool open) // Massive Door switcher { - if (GameObject* Door = GameObject::GetGameObject(*me, instance ? instance->GetData64(DATA_GO_MASSIVE_DOOR) : 0)) + if (GameObject* Door = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_GO_MASSIVE_DOOR) )) Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY); } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp index f667394f29c..241ac85faa2 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp @@ -496,12 +496,13 @@ public: EventStarted = false; YellTimer = 0; - if (instance && instance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0) + if (instance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0) { instance->SetData64(DATA_IMAGE_OF_MEDIVH, me->GetGUID()); (*me).GetMotionMaster()->MovePoint(1, MedivPos[0], MedivPos[1], MedivPos[2]); Step = 0; - }else + } + else { me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); me->RemoveCorpse(); diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp index 6c15fdc77fa..0601c69e96d 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -515,7 +515,7 @@ public: return; } //Don't really die in all phases of Kael'Thas - if (instance && instance->GetData(DATA_KAELTHAS_EVENT) == 0) + if (instance->GetData(DATA_KAELTHAS_EVENT) == 0) { //prevent death damage = 0; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp index 8592120f94a..4bc0ee68cc3 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp @@ -376,7 +376,7 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI ResetThreatTimer = urand(5000, 20000); // in case she is not alive and Reset was for some reason called, respawn her (most likely party wipe after killing her) - if (Creature* pDelrissa = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_DELRISSA) : 0)) + if (Creature* pDelrissa = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DELRISSA))) { if (!pDelrissa->IsAlive()) pDelrissa->Respawn(); diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp index 0d62d47a5d6..a78dce47784 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp @@ -172,7 +172,7 @@ public: if (!UpdateVictim()) return; - if (_bHasDied && !_bHeal && instance && instance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == SPECIAL) + if (_bHasDied && !_bHeal && instance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == SPECIAL) { //On ressurection, stop fake death and heal whitemane and resume fight if (Unit* Whitemane = Unit::GetUnit(*me, instance->GetData64(DATA_WHITEMANE))) @@ -259,7 +259,7 @@ public: void AttackStart(Unit* who) OVERRIDE { - if (instance && instance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == NOT_STARTED) + if (instance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == NOT_STARTED) return; ScriptedAI::AttackStart(who); @@ -289,11 +289,11 @@ public: if (_bCanResurrect) { //When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out - if (instance && Wait_Timer <= diff) + if (Wait_Timer <= diff) { - if (Unit* Mograine = Unit::GetUnit(*me, instance->GetData64(DATA_MOGRAINE))) + if (Creature* mograine = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MOGRAINE))) { - DoCast(Mograine, SPELL_SCARLETRESURRECTION); + DoCast(mograine, SPELL_SCARLETRESURRECTION); Talk(SAY_WH_RESSURECT); _bCanResurrect = false; } @@ -325,7 +325,7 @@ public: if (!HealthAbovePct(75)) target = me; - if (Creature* mograine = Unit::GetCreature((*me), instance->GetData64(DATA_MOGRAINE))) + if (Creature* mograine = Unit::GetCreature(*me, instance->GetData64(DATA_MOGRAINE))) { // checking _bCanResurrectCheck prevents her healing Mograine while he is "faking death" if (_bCanResurrectCheck && mograine->IsAlive() && !mograine->HealthAbovePct(75)) diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp index eb7295f72d0..76ae6b06058 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp @@ -93,7 +93,7 @@ public: InstanceScript* instance = creature->GetInstanceScript(); if (instance && instance->GetData(TYPE_FREE_NPC) != DONE && instance->GetData(TYPE_RETHILGORE) == DONE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DOOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DOOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp index fe0e3a050c8..f4663c0f8ec 100644 --- a/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp @@ -93,7 +93,7 @@ public: MortalStrike_Timer = 12000; // RaiseDead_Timer = 30000; SummonSkeletons_Timer = 34000; - if (instance && instance->GetData(TYPE_RAMSTEIN) == DONE) + if (instance->GetData(TYPE_RAMSTEIN) == DONE) instance->SetData(TYPE_BARON, NOT_STARTED); } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp index a52ddcea3b0..9dcbed211bb 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp @@ -176,7 +176,7 @@ public: void DoIntro() { - Creature* Madrigosa = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_MADRIGOSA) : 0); + Creature* Madrigosa = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MADRIGOSA)); if (!Madrigosa) return; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index 9d073cd7ef8..e8b112aa1cd 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -454,7 +454,7 @@ public: { if (uiRandomSayTimer < diff) { - if (instance && instance->GetBossState(DATA_MURU) != DONE && instance->GetBossState(DATA_KILJAEDEN) == NOT_STARTED) + if (instance->GetBossState(DATA_MURU) != DONE && instance->GetBossState(DATA_KILJAEDEN) == NOT_STARTED) Talk(SAY_KJ_OFFCOMBAT); uiRandomSayTimer = 30000; } else uiRandomSayTimer -= diff; @@ -1206,7 +1206,7 @@ public: if (uiTimer <= diff) { - if (Unit* random = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_PLAYER_GUID) : 0)) + if (Unit* random = ObjectAccessor::GetPlayer(*me, instance->GetData64(DATA_PLAYER_GUID))) DoCast(random, SPELL_SHADOW_BOLT, false); uiTimer = urand(500, 1000); } else uiTimer -= diff; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp index 426771e6db6..6980dbfb9c2 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp @@ -433,10 +433,11 @@ public: { if (!SummonSentinel) { - if (InAction && instance && instance->GetBossState(DATA_MURU) == NOT_STARTED) + if (InAction && instance->GetBossState(DATA_MURU) == NOT_STARTED) Reset(); return; } + if (SummonTimer <= diff) { DoCastAOE(SPELL_SUMMON_VOID_SENTINEL, false); @@ -602,7 +603,7 @@ public: { if (SpellTimer <= diff) { - Unit* Victim = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_PLAYER_GUID) : 0); + Unit* Victim = Unit::GetUnit(*me, instance->GetData64(DATA_PLAYER_GUID)); switch (NeedForAHack) { case 0: diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp index 04e3d9f3450..d6657ac0986 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp @@ -231,7 +231,7 @@ struct boss_hexlord_addAI : public ScriptedAI void UpdateAI(uint32 /*diff*/) OVERRIDE { - if (instance && instance->GetData(DATA_HEXLORDEVENT) != IN_PROGRESS) + if (instance->GetData(DATA_HEXLORDEVENT) != IN_PROGRESS) { EnterEvadeMode(); return; diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 5b943fd57f2..e542b3c4895 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -344,9 +344,8 @@ class npc_zulian_prowler : public CreatureScript DoCast(me, SPELL_SNEAK_RANK_1_1); DoCast(me, SPELL_SNEAK_RANK_1_2); - if (_instance) - if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK))) - me->GetMotionMaster()->MovePoint(0, arlokk->GetPositionX(), arlokk->GetPositionY(), arlokk->GetPositionZ()); + if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK))) + me->GetMotionMaster()->MovePoint(0, arlokk->GetPositionX(), arlokk->GetPositionY(), arlokk->GetPositionZ()); _events.ScheduleEvent(EVENT_ATTACK, 6000); } @@ -365,13 +364,10 @@ class npc_zulian_prowler : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (_instance) + if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK))) { - if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK))) - { - if (arlokk->IsAlive()) - arlokk->GetAI()->SetData(_sideData, 0); - } + if (arlokk->IsAlive()) + arlokk->GetAI()->SetData(_sideData, 0); } me->DespawnOrUnsummon(4000); } diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp index e6ef90d1638..336599f2cc5 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,13 +15,6 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Jeklik -SD%Complete: 85 -SDComment: Problem in finding the right flying batriders for spawning and making them fly. -SDCategory: Zul'Gurub -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "zulgurub.h" @@ -44,11 +36,47 @@ enum Spells SPELL_CHAIN_MIND_FLAY = 26044, // Right ID unknown. So disabled SPELL_GREATERHEAL = 23954, SPELL_BAT_FORM = 23966, + // Batriders Spell SPELL_BOMB = 40332 // Wrong ID but Magmadars bomb is not working... }; -class boss_jeklik : public CreatureScript //jeklik +enum BatIds +{ + NPC_BLOODSEEKER_BAT = 11368, + NPC_FRENZIED_BAT = 14965 +}; + +enum Events +{ + EVENT_CHARGE_JEKLIK = 1, + EVENT_SONIC_BURST, + EVENT_SCREECH, + EVENT_SPAWN_BATS, + EVENT_SHADOW_WORD_PAIN, + EVENT_MIND_FLAY, + EVENT_CHAIN_MIND_FLAY, + EVENT_GREATER_HEAL, + EVENT_SPAWN_FLYING_BATS +}; + +enum Phase +{ + PHASE_ONE = 1, + PHASE_TWO = 2 +}; + +Position const SpawnBat[6] = +{ + { -12291.6220f, -1380.2640f, 144.8304f, 5.483f }, + { -12289.6220f, -1380.2640f, 144.8304f, 5.483f }, + { -12293.6220f, -1380.2640f, 144.8304f, 5.483f }, + { -12291.6220f, -1380.2640f, 144.8304f, 5.483f }, + { -12289.6220f, -1380.2640f, 144.8304f, 5.483f }, + { -12293.6220f, -1380.2640f, 144.8304f, 5.483f } +}; + +class boss_jeklik : public CreatureScript { public: boss_jeklik() : CreatureScript("boss_jeklik") { } @@ -56,32 +84,9 @@ class boss_jeklik : public CreatureScript //jeklik { boss_jeklikAI(Creature* creature) : BossAI(creature, DATA_JEKLIK) { } - uint32 Charge_Timer; - uint32 SonicBurst_Timer; - uint32 Screech_Timer; - uint32 SpawnBats_Timer; - uint32 ShadowWordPain_Timer; - uint32 MindFlay_Timer; - uint32 ChainMindFlay_Timer; - uint32 GreaterHeal_Timer; - uint32 SpawnFlyingBats_Timer; - - bool PhaseTwo; - void Reset() OVERRIDE { _Reset(); - Charge_Timer = 20000; - SonicBurst_Timer = 8000; - Screech_Timer = 13000; - SpawnBats_Timer = 60000; - ShadowWordPain_Timer = 6000; - MindFlay_Timer = 11000; - ChainMindFlay_Timer = 26000; - GreaterHeal_Timer = 50000; - SpawnFlyingBats_Timer = 10000; - - PhaseTwo = false; } void JustDied(Unit* /*killer*/) OVERRIDE @@ -94,156 +99,124 @@ class boss_jeklik : public CreatureScript //jeklik { _EnterCombat(); Talk(SAY_AGGRO); + events.SetPhase(PHASE_ONE); + + events.ScheduleEvent(EVENT_CHARGE_JEKLIK, 20000, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_SONIC_BURST, 8000, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_SCREECH, 13000, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_SPAWN_BATS, 60000, 0, PHASE_ONE); + + me->SetCanFly(true); DoCast(me, SPELL_BAT_FORM); } + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) OVERRIDE + { + if (events.IsInPhase(PHASE_ONE) && !HealthAbovePct(50)) + { + me->RemoveAurasDueToSpell(SPELL_BAT_FORM); + me->SetCanFly(false); + DoResetThreat(); + events.SetPhase(PHASE_TWO); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 6000, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_MIND_FLAY, 11000, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_CHAIN_MIND_FLAY, 26000, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_GREATER_HEAL, 50000, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_SPAWN_FLYING_BATS, 10000, 0, PHASE_TWO); + return; + } + } + void UpdateAI(uint32 diff) OVERRIDE { if (!UpdateVictim()) return; - if (me->GetVictim() && me->IsAlive()) + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - if (HealthAbovePct(50)) + switch (eventId) { - if (Charge_Timer <= diff) - { + case EVENT_CHARGE_JEKLIK: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { DoCast(target, SPELL_CHARGE); AttackStart(target); } - - Charge_Timer = urand(15000, 30000); - } else Charge_Timer -= diff; - - if (SonicBurst_Timer <= diff) - { + events.ScheduleEvent(EVENT_CHARGE_JEKLIK, urand(15000, 30000), 0, PHASE_ONE); + break; + case EVENT_SONIC_BURST: DoCastVictim(SPELL_SONICBURST); - SonicBurst_Timer = urand(8000, 13000); - } else SonicBurst_Timer -= diff; - - if (Screech_Timer <= diff) - { + events.ScheduleEvent(EVENT_SONIC_BURST, urand(8000, 13000), 0, PHASE_ONE); + case EVENT_SCREECH: DoCastVictim(SPELL_SCREECH); - Screech_Timer = urand(18000, 26000); - } else Screech_Timer -= diff; - - if (SpawnBats_Timer <= diff) - { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); - - Creature* Bat = NULL; - Bat = me->SummonCreature(11368, -12291.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (target && Bat) Bat ->AI()->AttackStart(target); - - Bat = me->SummonCreature(11368, -12289.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (target && Bat) Bat ->AI()->AttackStart(target); - - Bat = me->SummonCreature(11368, -12293.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (target && Bat) Bat ->AI()->AttackStart(target); - - Bat = me->SummonCreature(11368, -12291.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (target && Bat) Bat ->AI()->AttackStart(target); - - Bat = me->SummonCreature(11368, -12289.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (target && Bat) Bat ->AI()->AttackStart(target); - Bat = me->SummonCreature(11368, -12293.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (target && Bat) Bat ->AI()->AttackStart(target); - - SpawnBats_Timer = 60000; - } else SpawnBats_Timer -= diff; - } - else - { - if (PhaseTwo) - { - if (ShadowWordPain_Timer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - { - DoCast(target, SPELL_SHADOW_WORD_PAIN); - ShadowWordPain_Timer = urand(12000, 18000); - } - }ShadowWordPain_Timer -=diff; - - if (MindFlay_Timer <= diff) - { - DoCastVictim(SPELL_MIND_FLAY); - MindFlay_Timer = 16000; - }MindFlay_Timer -=diff; - - if (ChainMindFlay_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCastVictim(SPELL_CHAIN_MIND_FLAY); - ChainMindFlay_Timer = urand(15000, 30000); - }ChainMindFlay_Timer -=diff; - - if (GreaterHeal_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_GREATERHEAL); - GreaterHeal_Timer = urand(25000, 35000); - }GreaterHeal_Timer -=diff; - - if (SpawnFlyingBats_Timer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - { - if (Creature* FlyingBat = me->SummonCreature(14965, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000)) - FlyingBat->AI()->AttackStart(target); - } - - SpawnFlyingBats_Timer = urand(10000, 15000); - } else SpawnFlyingBats_Timer -=diff; - } - else - { - me->SetDisplayId(15219); - DoResetThreat(); - PhaseTwo = true; - } + events.ScheduleEvent(EVENT_SCREECH, urand(18000, 26000), 0, PHASE_ONE); + case EVENT_SPAWN_BATS: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + for (uint8 i = 0; i < 6; ++i) + if (Creature* bat = me->SummonCreature(NPC_BLOODSEEKER_BAT, SpawnBat[i], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000)) + bat->AI()->AttackStart(target); + events.ScheduleEvent(EVENT_SPAWN_BATS, 60000, 0, PHASE_ONE); + break; + case EVENT_SHADOW_WORD_PAIN: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_SHADOW_WORD_PAIN); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(12000, 18000), 0, PHASE_TWO); + break; + case EVENT_MIND_FLAY: + DoCastVictim(SPELL_MIND_FLAY); + events.ScheduleEvent(EVENT_MIND_FLAY, 16000, 0, PHASE_TWO); + break; + case EVENT_CHAIN_MIND_FLAY: + me->InterruptNonMeleeSpells(false); + DoCastVictim(SPELL_CHAIN_MIND_FLAY); + events.ScheduleEvent(EVENT_CHAIN_MIND_FLAY, urand(15000, 30000), 0, PHASE_TWO); + break; + case EVENT_GREATER_HEAL: + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_GREATERHEAL); + events.ScheduleEvent(EVENT_GREATER_HEAL, urand(25000, 35000), 0, PHASE_TWO); + break; + case EVENT_SPAWN_FLYING_BATS: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + if (Creature* flyingBat = me->SummonCreature(NPC_FRENZIED_BAT, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000)) + flyingBat->AI()->AttackStart(target); + events.ScheduleEvent(EVENT_SPAWN_FLYING_BATS, urand(10000, 15000), 0, PHASE_TWO); + break; + default: + break; } - - DoMeleeAttackIfReady(); } + + DoMeleeAttackIfReady(); } }; CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return new boss_jeklikAI(creature); + return GetZulGurubAI<boss_jeklikAI>(creature); } }; -//Flying Bat +// Flying Bat class npc_batrider : public CreatureScript { public: - - npc_batrider() - : CreatureScript("npc_batrider") - { - } + npc_batrider() : CreatureScript("npc_batrider") { } struct npc_batriderAI : public ScriptedAI { - npc_batriderAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; + npc_batriderAI(Creature* creature) : ScriptedAI(creature) { } uint32 Bomb_Timer; - uint32 Check_Timer; void Reset() OVERRIDE { Bomb_Timer = 2000; - Check_Timer = 1000; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } @@ -254,7 +227,6 @@ class npc_batrider : public CreatureScript if (!UpdateVictim()) return; - //Bomb_Timer if (Bomb_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) @@ -262,20 +234,9 @@ class npc_batrider : public CreatureScript DoCast(target, SPELL_BOMB); Bomb_Timer = 5000; } - } else Bomb_Timer -= diff; - - //Check_Timer - if (Check_Timer <= diff) - { - if (instance->GetBossState(DATA_JEKLIK) == DONE) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - return; - } - - Check_Timer = 1000; - } else Check_Timer -= diff; + } + else + Bomb_Timer -= diff; DoMeleeAttackIfReady(); } @@ -283,7 +244,7 @@ class npc_batrider : public CreatureScript CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return GetInstanceAI<npc_batriderAI>(creature); + return new npc_batriderAI(creature); } }; @@ -292,4 +253,3 @@ void AddSC_boss_jeklik() new boss_jeklik(); new npc_batrider(); } - diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h index c92e8b8724d..a9386ff1782 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h +++ b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h @@ -66,13 +66,9 @@ enum GameobjectIds }; template<class AI> -CreatureAI* GetZulGurubAI(Creature* creature) +AI* GetZulGurubAI(Creature* creature) { - if (InstanceMap* instance = creature->GetMap()->ToInstanceMap()) - if (instance->GetInstanceScript()) - if (instance->GetScriptId() == sObjectMgr->GetScriptId(ZGScriptName)) - return new AI(creature); - return NULL; + return GetInstanceAI<AI>(creature, ZGScriptName); } #endif diff --git a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp index 4bfbff50dd5..0cd1403d48a 100644 --- a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp +++ b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp @@ -233,10 +233,7 @@ public: struct npc_lord_gregor_lescovarAI : public npc_escortAI { - npc_lord_gregor_lescovarAI(Creature* creature) : npc_escortAI(creature) - { - creature->RestoreFaction(); - } + npc_lord_gregor_lescovarAI(Creature* creature) : npc_escortAI(creature) { } uint32 uiTimer; uint32 uiPhase; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp index a4f9a364684..c7803f23e1b 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp @@ -72,14 +72,15 @@ public: AuraTimer = 5000; InfernoTimer = 45000; - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_ANETHERONEVENT, IN_PROGRESS); + Talk(SAY_ONAGGRO); } @@ -91,7 +92,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 7 && instance) + if (waypointId == 7) { Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_JAINAPROUDMOORE)); if (target && target->IsAlive()) @@ -102,7 +103,7 @@ public: void JustDied(Unit* killer) OVERRIDE { hyjal_trashAI::JustDied(killer); - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_ANETHERONEVENT, DONE); Talk(SAY_ONDEATH); } @@ -225,7 +226,7 @@ public: { if (AnetheronGUID) { - Creature* boss = Unit::GetCreature((*me), AnetheronGUID); + Creature* boss = ObjectAccessor::GetCreature(*me, AnetheronGUID); if (!boss || (boss && boss->isDead())) { me->setDeathState(JUST_DIED); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp index 6d296945659..4decce7482f 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp @@ -78,14 +78,15 @@ public: EnrageTimer = 600000; enraged = false; - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_AZGALOREVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_AZGALOREVENT, IN_PROGRESS); + Talk(SAY_ONAGGRO); } @@ -107,7 +108,7 @@ public: void JustDied(Unit* killer) OVERRIDE { hyjal_trashAI::JustDied(killer); - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_AZGALOREVENT, DONE); Talk(SAY_ONDEATH); } @@ -237,7 +238,7 @@ public: { if (AzgalorGUID) { - Creature* boss = Unit::GetCreature((*me), AzgalorGUID); + Creature* boss = ObjectAccessor::GetCreature(*me, AzgalorGUID); if (!boss || (boss && boss->isDead())) { me->setDeathState(JUST_DIED); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp index 7a5870809f7..af7b0c1d899 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp @@ -74,13 +74,13 @@ public: MarkTimer = 45000; MarkTimerBase = 45000; - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_KAZROGALEVENT, IN_PROGRESS); Talk(SAY_ONAGGRO); } @@ -103,7 +103,7 @@ public: void JustDied(Unit* killer) OVERRIDE { hyjal_trashAI::JustDied(killer); - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_KAZROGALEVENT, DONE); DoPlaySoundToSet(me, SOUND_ONDEATH); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp index 4d6a94b6e73..691207a4682 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp @@ -69,13 +69,13 @@ public: NovaTimer = 15000; IceboltTimer = 10000; - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_RAGEWINTERCHILLEVENT, IN_PROGRESS); Talk(SAY_ONAGGRO); } @@ -98,7 +98,7 @@ public: void JustDied(Unit* killer) OVERRIDE { hyjal_trashAI::JustDied(killer); - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_RAGEWINTERCHILLEVENT, DONE); Talk(SAY_ONDEATH); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp index 3b3cacf7d3f..c8006158ef1 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp @@ -705,7 +705,7 @@ void hyjalAI::UpdateAI(uint32 diff) switch (me->GetEntry()) { case JAINA: - if (instance && instance->GetData(DATA_ALLIANCE_RETREAT)) + if (instance->GetData(DATA_ALLIANCE_RETREAT)) { me->SetVisible(false); HideNearPos(me->GetPositionX(), me->GetPositionY()); @@ -717,7 +717,7 @@ void hyjalAI::UpdateAI(uint32 diff) else me->SetVisible(true); break; case THRALL: //thrall - if (instance && instance->GetData(DATA_HORDE_RETREAT)) + if (instance->GetData(DATA_HORDE_RETREAT)) { me->SetVisible(false); HideNearPos(me->GetPositionX(), me->GetPositionY()); @@ -781,7 +781,7 @@ void hyjalAI::UpdateAI(uint32 diff) if (Summon) { - if (instance && EnemyCount) + if (EnemyCount) { EnemyCount = instance->GetData(DATA_TRASH); if (!EnemyCount) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp index 2688fbbdaff..cbace6df028 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp @@ -443,7 +443,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 0 && instance && !IsOverrun) + if (waypointId == 0 && !IsOverrun) { if (instance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall { @@ -559,7 +559,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 7 && instance && !IsOverrun) + if (waypointId == 7 && !IsOverrun) { if (instance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall { @@ -658,7 +658,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 7 && instance && !IsOverrun) + if (waypointId == 7 && !IsOverrun) { if (instance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall { @@ -769,7 +769,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 7 && instance && !IsOverrun) + if (waypointId == 7 && !IsOverrun) { if (instance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall { @@ -882,7 +882,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 7 && instance && !IsOverrun) + if (waypointId == 7 && !IsOverrun) { if (instance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall { @@ -978,7 +978,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 7 && instance && !IsOverrun) + if (waypointId == 7 && !IsOverrun) { if (instance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall { @@ -1064,7 +1064,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 7 && instance && !IsOverrun) + if (waypointId == 7 && !IsOverrun) { if (instance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall { @@ -1153,7 +1153,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 2 && instance && !IsOverrun) + if (waypointId == 2 && !IsOverrun) { Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_THRALL)); if (target && target->IsAlive()) @@ -1166,7 +1166,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { - if (instance && IsEvent) + if (IsEvent) instance->SetData(DATA_TRASH, 0);//signal trash is dead float x, y, z; @@ -1181,11 +1181,13 @@ public: void UpdateAI(uint32 diff) OVERRIDE { hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) { CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); npc_escortAI::UpdateAI(diff); } + if (IsEvent) { if (!go) @@ -1197,7 +1199,9 @@ public: AddWaypoint(i, FrostWyrmWPs[i][0], FrostWyrmWPs[i][1], FrostWyrmWPs[i][2]); Start(false, true); SetDespawnAtEnd(false); - }else{//fly path FlyPathWPs + } + else + {//fly path FlyPathWPs for (uint8 i = 0; i < 3; ++i) AddWaypoint(i, FlyPathWPs[i][0]+irand(-10, 10), FlyPathWPs[i][1]+irand(-10, 10), FlyPathWPs[i][2]); Start(false, true); @@ -1205,9 +1209,12 @@ public: } } } + if (!UpdateVictim()) return; - if (!me->IsWithinDist(me->GetVictim(), 25)){ + + if (!me->IsWithinDist(me->GetVictim(), 25)) + { if (MoveTimer <= diff) { me->GetMotionMaster()->MoveChase(me->GetVictim()); @@ -1227,7 +1234,6 @@ public: } else FrostBreathTimer -= diff; } }; - }; class npc_gargoyle : public CreatureScript @@ -1246,7 +1252,8 @@ public: { instance = creature->GetInstanceScript(); go = false; - DummyTarget[0] = 0;DummyTarget[1] = 0;DummyTarget[2] = 0; + for (uint8 i = 0; i < 3; ++i) + DummyTarget[i] = 0; Reset(); } @@ -1267,7 +1274,7 @@ public: void WaypointReached(uint32 waypointId) OVERRIDE { - if (waypointId == 2 && instance && !IsOverrun) + if (waypointId == 2 && !IsOverrun) { Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_THRALL)); if (target && target->IsAlive()) @@ -1291,11 +1298,13 @@ public: void UpdateAI(uint32 diff) OVERRIDE { hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) { CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); npc_escortAI::UpdateAI(diff); } + if (IsEvent) { if (!go) @@ -1315,6 +1324,7 @@ public: } } } + if (IsOverrun && !UpdateVictim()) { if (faction == 0)//alliance @@ -1326,8 +1336,10 @@ public: } else StrikeTimer -= diff; } } + if (!UpdateVictim()) return; + if (!me->IsWithinDist(me->GetVictim(), 20) || forcemove) { forcemove = false; @@ -1347,6 +1359,7 @@ public: MoveTimer = 2000; } else MoveTimer-=diff; } + if (StrikeTimer <= diff) { if (me->IsWithinDist(me->GetVictim(), 20)) @@ -1359,7 +1372,6 @@ public: } else StrikeTimer -= diff; } }; - }; class alliance_rifleman : public CreatureScript diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp index e4f1324d19c..7c0169cda95 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp @@ -147,7 +147,7 @@ public: return; } - if (Creature* pArthas = me->GetCreature(*me, instance ? instance->GetData64(DATA_ARTHAS) : 0)) + if (Creature* pArthas = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_ARTHAS))) if (pArthas->isDead()) { EnterEvadeMode(); @@ -196,7 +196,7 @@ public: uiOutroTimer = 8000; break; case 2: - me->SetTarget(instance ? instance->GetData64(DATA_ARTHAS) : 0); + me->SetTarget(instance->GetData64(DATA_ARTHAS)); me->HandleEmoteCommand(29); Talk(SAY_ESCAPE_SPEECH_2); ++uiOutroStep; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp index 061c7fdfc62..5b1db051a56 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp @@ -99,7 +99,7 @@ public: { Talk(SAY_DEATH); - if (instance && instance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + if (instance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) instance->SetData(TYPE_THRALL_PART1, DONE); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp index cb25d96acf3..4d75bc0545c 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp @@ -91,7 +91,7 @@ public: { Talk(SAY_DEATH); - if (instance && instance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + if (instance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) instance->SetData(TYPE_THRALL_PART4, DONE); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp index 6e4ef814dbe..bf902ba403c 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp @@ -82,7 +82,7 @@ public: player->PrepareQuestMenu(creature->GetGUID()); InstanceScript* instance = creature->GetInstanceScript(); - if (instance && instance->GetData(TYPE_BARREL_DIVERSION) != DONE && !player->HasItemCount(ITEM_ENTRY_BOMBS)) + if (instance->GetData(TYPE_BARREL_DIVERSION) != DONE && !player->HasItemCount(ITEM_ENTRY_BOMBS)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); if (player->GetQuestStatus(QUEST_ENTRY_RETURN) == QUEST_STATUS_COMPLETE) @@ -92,7 +92,6 @@ public: return true; } - }; /*###### @@ -585,18 +584,14 @@ public: { player->CLOSE_GOSSIP_MENU(); - if (instance && instance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + if (instance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) { instance->SetData(TYPE_THRALL_PART4, IN_PROGRESS); if (instance->GetData64(DATA_EPOCH) == 0) creature->SummonCreature(ENTRY_EPOCH, 2639.13f, 698.55f, 65.43f, 4.59f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - if (uint64 ThrallGUID = instance->GetData64(DATA_THRALL)) - { - Creature* Thrall = (Unit::GetCreature((*creature), ThrallGUID)); - if (Thrall) - CAST_AI(npc_thrall_old_hillsbrad::npc_thrall_old_hillsbradAI, Thrall->AI())->StartWP(); - } + if (Creature* thrall = (Unit::GetCreature(*creature, instance->GetData64(DATA_THRALL)))) + CAST_AI(npc_thrall_old_hillsbrad::npc_thrall_old_hillsbradAI, thrall->AI())->StartWP(); } } return true; @@ -605,7 +600,7 @@ public: bool OnGossipHello(Player* player, Creature* creature) OVERRIDE { InstanceScript* instance = creature->GetInstanceScript(); - if (instance && instance->GetData(TYPE_THRALL_PART3) == DONE && instance->GetData(TYPE_THRALL_PART4) == NOT_STARTED) + if (instance->GetData(TYPE_THRALL_PART3) == DONE && instance->GetData(TYPE_THRALL_PART4) == NOT_STARTED) { player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); player->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH1, creature->GetGUID()); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp index f1406a5a008..58bda23fb36 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp @@ -138,8 +138,8 @@ public: void AttackStart(Unit* /*who*/) OVERRIDE { - //if (instance && instance->GetData(TYPE_MEDIVH) == IN_PROGRESS) - //return; + //if (instance->GetData(TYPE_MEDIVH) == IN_PROGRESS) + // return; //ScriptedAI::AttackStart(who); } @@ -297,7 +297,7 @@ public: if (!creature_entry) return; - if (instance && instance->GetData(TYPE_MEDIVH) != IN_PROGRESS) + if (instance->GetData(TYPE_MEDIVH) != IN_PROGRESS) { me->InterruptNonMeleeSpells(true); me->RemoveAllAuras(); @@ -311,7 +311,7 @@ public: pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); if (Unit* Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) - if (Unit* temp = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_MEDIVH) : 0)) + if (Unit* temp = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MEDIVH))) Summon->AddThreat(temp, 0.0f); } diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp index 7381594a1ce..29e08699a0f 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -340,7 +340,7 @@ public: Trinity::GameObjectInRangeCheck check(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 15); Trinity::GameObjectLastSearcher<Trinity::GameObjectInRangeCheck> searcher(me, Floor, check); me->VisitNearbyGridObject(30, searcher); - if (instance && Floor) + if (Floor) instance->SetData64(DATA_FLOOR_ERUPTION_GUID, Floor->GetGUID()); events.ScheduleEvent(EVENT_BELLOWING_ROAR, 30000); break; diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp index d29831b8cde..830c3fed382 100644 --- a/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp +++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp @@ -40,7 +40,10 @@ public: struct boss_gluttonAI : public BossAI { - boss_gluttonAI(Creature* creature) : BossAI(creature, DATA_GLUTTON) { } + boss_gluttonAI(Creature* creature) : BossAI(creature, DATA_GLUTTON) + { + hp15 = false; + } void Reset() OVERRIDE { diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp index 3b4defeca56..b9605794074 100644 --- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp +++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp @@ -158,6 +158,7 @@ public: { instance = creature->GetInstanceScript(); eventInProgress = false; + spawnerCount = 0; } void Reset() OVERRIDE @@ -177,9 +178,7 @@ public: void EnterCombat(Unit* who) OVERRIDE { if (channeling) - { Talk(SAY_WATCH_OUT, who); - } else { events.ScheduleEvent(EVENT_FIREBALL, 1000); diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h index 4778677e067..a9a5a82f127 100644 --- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h +++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h @@ -61,13 +61,9 @@ enum GameObjectIds }; template<class AI> -CreatureAI* GetRazorfenDownsAI(Creature* creature) +AI* GetRazorfenDownsAI(Creature* creature) { - if (InstanceMap* instance = creature->GetMap()->ToInstanceMap()) - if (instance->GetInstanceScript()) - if (instance->GetScriptId() == sObjectMgr->GetScriptId(RFDScriptName)) - return new AI(creature); - return NULL; + return GetInstanceAI<AI>(creature, RFDScriptName); } #endif diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp index c1897ff48ad..433193bd703 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp @@ -119,7 +119,7 @@ public: //Checking if Vem is dead. If yes we will enrage. if (Check_Timer <= diff) { - if (instance && instance->GetData(DATA_VEMISDEAD)) + if (instance->GetData(DATA_VEMISDEAD)) { DoCast(me, SPELL_ENRAGE); VemDead = true; diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp index 81171eef580..d84279f1e8b 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -502,8 +502,6 @@ public: //Added. Can be removed if its included in DB. me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0); } void CastSpellOnBug(Creature* target) diff --git a/src/server/scripts/Kalimdor/zone_ashenvale.cpp b/src/server/scripts/Kalimdor/zone_ashenvale.cpp index 41c0441bca5..ec28ee42625 100644 --- a/src/server/scripts/Kalimdor/zone_ashenvale.cpp +++ b/src/server/scripts/Kalimdor/zone_ashenvale.cpp @@ -198,7 +198,7 @@ public: void sQuestAccept(Player* player, Quest const* quest) { - if (quest->GetQuestId() == QUEST_TOREK_ASSULT) + if (quest->GetQuestId() == QUEST_FREEDOM_TO_RUUL) { me->setFaction(FACTION_QUEST); npc_escortAI::Start(true, false, player->GetGUID()); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp index 1890dfb4ff8..f599e6e7c27 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp @@ -394,7 +394,7 @@ public: void AttackStart(Unit* victim) OVERRIDE { - if ((instance && instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS) || !victim) + if ((instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS) || !victim) return; ScriptedAI::AttackStart(victim); @@ -403,7 +403,7 @@ public: void MoveInLineOfSight(Unit* who) OVERRIDE { - if ((instance && instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS) || !who) + if ((instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS) || !who) return; ScriptedAI::MoveInLineOfSight(who); @@ -432,7 +432,7 @@ public: void UpdateAI(uint32 diff) OVERRIDE { - if (instance && bCheckTimer <= diff) + if (bCheckTimer <= diff) { if (me->GetGUID() == instance->GetData64(DATA_ADD_JEDOGA_OPFER) && !bWalking) { diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp index 77d3ce21d0c..efe439de440 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp @@ -17,76 +17,75 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "Player.h" #include "ahnkahet.h" enum Spells { - SPELL_BLOODTHIRST = 55968, // Trigger Spell + add aura - SPELL_CONJURE_FLAME_SPHERE = 55931, - SPELL_FLAME_SPHERE_SUMMON_1 = 55895, // 1x 30106 - H_SPELL_FLAME_SPHERE_SUMMON_1 = 59511, // 1x 31686 - H_SPELL_FLAME_SPHERE_SUMMON_2 = 59512, // 1x 31687 - SPELL_FLAME_SPHERE_SPAWN_EFFECT = 55891, - SPELL_FLAME_SPHERE_VISUAL = 55928, - SPELL_FLAME_SPHERE_PERIODIC = 55926, - SPELL_FLAME_SPHERE_DEATH_EFFECT = 55947, - SPELL_BEAM_VISUAL = 60342, - SPELL_EMBRACE_OF_THE_VAMPYR = 55959, - SPELL_VANISH = 55964, - CREATURE_FLAME_SPHERE = 30106, - H_CREATURE_FLAME_SPHERE_1 = 31686, - H_CREATURE_FLAME_SPHERE_2 = 31687, - SPELL_HOVER_FALL = 60425 + SPELL_BLOODTHIRST = 55968, // Trigger Spell + add aura + SPELL_CONJURE_FLAME_SPHERE = 55931, + SPELL_FLAME_SPHERE_SUMMON_1 = 55895, // 1x 30106 + SPELL_FLAME_SPHERE_SUMMON_2 = 59511, // 1x 31686 + SPELL_FLAME_SPHERE_SUMMON_3 = 59512, // 1x 31687 + SPELL_FLAME_SPHERE_SPAWN_EFFECT = 55891, + SPELL_FLAME_SPHERE_VISUAL = 55928, + SPELL_FLAME_SPHERE_PERIODIC = 55926, + SPELL_FLAME_SPHERE_DEATH_EFFECT = 55947, + SPELL_EMBRACE_OF_THE_VAMPYR = 55959, + SPELL_VANISH = 55964, + + NPC_FLAME_SPHERE_1 = 30106, + NPC_FLAME_SPHERE_2 = 31686, + NPC_FLAME_SPHERE_3 = 31687, + + SPELL_BEAM_VISUAL = 60342, + SPELL_HOVER_FALL = 60425 }; enum Misc { - DATA_EMBRACE_DMG = 20000, - H_DATA_EMBRACE_DMG = 40000, - DATA_SPHERE_DISTANCE = 15 + DATA_EMBRACE_DMG = 20000, + H_DATA_EMBRACE_DMG = 40000 }; -#define DATA_SPHERE_ANGLE_OFFSET 0.7f -#define DATA_GROUND_POSITION_Z 11.30809f +#define DATA_SPHERE_DISTANCE 25.0f +#define DATA_SPHERE_ANGLE_OFFSET M_PI / 2 +#define DATA_GROUND_POSITION_Z 11.30809f enum Yells { - SAY_1 = 0, - SAY_WARNING = 1, - SAY_AGGRO = 2, - SAY_SLAY = 3, - SAY_DEATH = 4, - SAY_FEED = 5, - SAY_VANISH = 6 + SAY_1 = 0, + SAY_WARNING = 1, + SAY_AGGRO = 2, + SAY_SLAY = 3, + SAY_DEATH = 4, + SAY_FEED = 5, + SAY_VANISH = 6 }; enum Events { - EVENT_CASTING_FLAME_SPHERES = 1, + EVENT_CONJURE_FLAME_SPHERES = 1, + EVENT_BLOODTHIRST, + EVENT_VANISH, EVENT_JUST_VANISHED, EVENT_VANISHED, EVENT_FEEDING, - EVENT_BLOODTHIRST, - EVENT_FLAME_SPHERE, - EVENT_VANISH -}; - -enum Phase -{ - PHASE_NORMAL = 1, - PHASE_SPECIAL = 2 + // Flame Sphere + EVENT_START_MOVE, + EVENT_DESPAWN }; -class boss_taldaram : public CreatureScript +class boss_prince_taldaram : public CreatureScript { public: - boss_taldaram() : CreatureScript("boss_taldaram") { } + boss_prince_taldaram() : CreatureScript("boss_prince_taldaram") { } - struct boss_taldaramAI : public BossAI + struct boss_prince_taldaramAI : public BossAI { - boss_taldaramAI(Creature* creature) : BossAI(creature, DATA_PRINCE_TALDARAM) + boss_prince_taldaramAI(Creature* creature) : BossAI(creature, DATA_PRINCE_TALDARAM) { me->SetDisableGravity(true); } @@ -94,6 +93,7 @@ class boss_taldaram : public CreatureScript void Reset() OVERRIDE { _Reset(); + _flameSphereTargetGUID = 0; _embraceTargetGUID = 0; _embraceTakenDamage = 0; } @@ -102,10 +102,24 @@ class boss_taldaram : public CreatureScript { _EnterCombat(); Talk(SAY_AGGRO); - events.SetPhase(PHASE_NORMAL); events.ScheduleEvent(EVENT_BLOODTHIRST, 10000); events.ScheduleEvent(EVENT_VANISH, urand(25000, 35000)); - events.ScheduleEvent(EVENT_FLAME_SPHERE, 5000); + events.ScheduleEvent(EVENT_CONJURE_FLAME_SPHERES, 5000); + } + + void JustSummoned(Creature* summon) + { + BossAI::JustSummoned(summon); + + switch (summon->GetEntry()) + { + case NPC_FLAME_SPHERE_1: + case NPC_FLAME_SPHERE_2: + case NPC_FLAME_SPHERE_3: + summon->AI()->SetGUID(_flameSphereTargetGUID); + default: + return; + } } void UpdateAI(uint32 diff) OVERRIDE @@ -122,80 +136,40 @@ class boss_taldaram : public CreatureScript { switch (eventId) { - if (events.IsInPhase(PHASE_NORMAL)) - { - case EVENT_BLOODTHIRST: - DoCast(me, SPELL_BLOODTHIRST); - events.ScheduleEvent(EVENT_BLOODTHIRST, 10000); - break; - case EVENT_FLAME_SPHERE: - DoCastVictim(SPELL_CONJURE_FLAME_SPHERE); - events.SetPhase(PHASE_SPECIAL); - events.ScheduleEvent(EVENT_CASTING_FLAME_SPHERES, 3000); - events.ScheduleEvent(EVENT_FLAME_SPHERE, 15000); - break; - case EVENT_VANISH: + case EVENT_BLOODTHIRST: + DoCast(me, SPELL_BLOODTHIRST); + events.ScheduleEvent(EVENT_BLOODTHIRST, 10000); + break; + case EVENT_CONJURE_FLAME_SPHERES: + // random target? + if (Unit* victim = me->GetVictim()) { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - uint32 targets = 0; - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player* player = i->GetSource(); - if (player && player->IsAlive()) - ++targets; - } - - if (targets > 2) - { - Talk(SAY_VANISH); - DoCast(me, SPELL_VANISH); - events.SetPhase(PHASE_SPECIAL); - events.ScheduleEvent(EVENT_JUST_VANISHED, 500); - if (Unit* embraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - _embraceTargetGUID = embraceTarget->GetGUID(); - } - events.ScheduleEvent(EVENT_VANISH, urand(25000, 35000)); - break; + _flameSphereTargetGUID = victim->GetGUID(); + DoCast(victim, SPELL_CONJURE_FLAME_SPHERE); } - } - case EVENT_CASTING_FLAME_SPHERES: + events.ScheduleEvent(EVENT_CONJURE_FLAME_SPHERES, 15000); + break; + case EVENT_VANISH: { - events.SetPhase(PHASE_NORMAL); - Unit* sphereTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!sphereTarget) - break; - - float angle, x, y; - - //DoCast(me, SPELL_FLAME_SPHERE_SUMMON_1); - if (Creature* sphere = DoSpawnCreature(CREATURE_FLAME_SPHERE, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10 * IN_MILLISECONDS)) + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + uint32 targets = 0; + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) { - angle = sphere->GetAngle(sphereTarget); - x = sphere->GetPositionX() + DATA_SPHERE_DISTANCE * std::cos(angle); - y = sphere->GetPositionY() + DATA_SPHERE_DISTANCE * std::sin(angle); - sphere->GetMotionMaster()->MovePoint(0, x, y, sphere->GetPositionZ()); + Player* player = i->GetSource(); + if (player && player->IsAlive()) + ++targets; } - if (IsHeroic()) + if (targets > 2) { - //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_1); - if (Creature* sphere = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_1, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10 * IN_MILLISECONDS)) - { - angle = sphere->GetAngle(sphereTarget) + DATA_SPHERE_ANGLE_OFFSET; - x = sphere->GetPositionX() + DATA_SPHERE_DISTANCE/2 * std::cos(angle); - y = sphere->GetPositionY() + DATA_SPHERE_DISTANCE/2 * std::sin(angle); - sphere->GetMotionMaster()->MovePoint(0, x, y, sphere->GetPositionZ()); - } - - //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_2); - if (Creature* sphere = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_2, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10 * IN_MILLISECONDS)) - { - angle = sphere->GetAngle(sphereTarget) - DATA_SPHERE_ANGLE_OFFSET; - x = sphere->GetPositionX() + DATA_SPHERE_DISTANCE/2 * std::cos(angle); - y = sphere->GetPositionY() + DATA_SPHERE_DISTANCE/2 * std::sin(angle); - sphere->GetMotionMaster()->MovePoint(0, x, y, sphere->GetPositionZ()); - } + Talk(SAY_VANISH); + DoCast(me, SPELL_VANISH); + events.DelayEvents(500); + events.ScheduleEvent(EVENT_JUST_VANISHED, 500); + if (Unit* embraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + _embraceTargetGUID = embraceTarget->GetGUID(); } + events.ScheduleEvent(EVENT_VANISH, urand(25000, 35000)); break; } case EVENT_JUST_VANISHED: @@ -218,7 +192,6 @@ class boss_taldaram : public CreatureScript break; case EVENT_FEEDING: _embraceTargetGUID = 0; - events.SetPhase(PHASE_NORMAL); break; default: break; @@ -232,13 +205,12 @@ class boss_taldaram : public CreatureScript { Unit* embraceTarget = GetEmbraceTarget(); - if (events.IsInPhase(PHASE_SPECIAL) && embraceTarget && embraceTarget->IsAlive()) + if (embraceTarget && embraceTarget->IsAlive()) { _embraceTakenDamage += damage; if (_embraceTakenDamage > DUNGEON_MODE<uint32>(DATA_EMBRACE_DMG, H_DATA_EMBRACE_DMG)) { _embraceTargetGUID = 0; - events.SetPhase(PHASE_NORMAL); me->CastStop(); } } @@ -255,12 +227,9 @@ class boss_taldaram : public CreatureScript if (victim->GetTypeId() != TYPEID_PLAYER) return; - Unit* embraceTarget = GetEmbraceTarget(); - if (events.IsInPhase(PHASE_SPECIAL) && embraceTarget && victim == embraceTarget) - { + if (victim->GetGUID() == _embraceTargetGUID) _embraceTargetGUID = 0; - events.SetPhase(PHASE_NORMAL); - } + Talk(SAY_SLAY); } @@ -289,76 +258,120 @@ class boss_taldaram : public CreatureScript me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation()); DoCast(SPELL_HOVER_FALL); me->SetDisableGravity(false); - me->GetMotionMaster()->MovePoint(0, me->GetHomePosition()); + me->GetMotionMaster()->MoveLand(0, me->GetHomePosition()); Talk(SAY_WARNING); instance->HandleGameObject(instance->GetData64(DATA_PRINCE_TALDARAM_PLATFORM), true); } private: + uint64 _flameSphereTargetGUID; uint64 _embraceTargetGUID; uint32 _embraceTakenDamage; }; CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return GetAhnKahetAI<boss_taldaramAI>(creature); + return GetAhnKahetAI<boss_prince_taldaramAI>(creature); } }; -class npc_taldaram_flamesphere : public CreatureScript +// 30106, 31686, 31687 - Flame Sphere +class npc_prince_taldaram_flame_sphere : public CreatureScript { public: - npc_taldaram_flamesphere() : CreatureScript("npc_taldaram_flamesphere") { } + npc_prince_taldaram_flame_sphere() : CreatureScript("npc_prince_taldaram_flame_sphere") { } - struct npc_taldaram_flamesphereAI : public ScriptedAI + struct npc_prince_taldaram_flame_sphereAI : public ScriptedAI { - npc_taldaram_flamesphereAI(Creature* creature) : ScriptedAI(creature) + npc_prince_taldaram_flame_sphereAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() OVERRIDE { + DoCast(me, SPELL_FLAME_SPHERE_SPAWN_EFFECT, true); + DoCast(me, SPELL_FLAME_SPHERE_VISUAL, true); + + _flameSphereTargetGUID = 0; + _events.Reset(); + _events.ScheduleEvent(EVENT_START_MOVE, 3 * IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_DESPAWN, 13 * IN_MILLISECONDS); } - void Reset() OVERRIDE + void SetGUID(uint64 guid, int32 /*id = 0*/) OVERRIDE { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //! HACK: Creature's can't have MOVEMENTFLAG_FLYING - me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); - me->setFaction(16); - me->SetObjectScale(1.0f); - DoCast(me, SPELL_FLAME_SPHERE_VISUAL); - DoCast(me, SPELL_FLAME_SPHERE_SPAWN_EFFECT); - DoCast(me, SPELL_FLAME_SPHERE_PERIODIC); - _despawnTimer = 10 * IN_MILLISECONDS; + _flameSphereTargetGUID = guid; } void EnterCombat(Unit* /*who*/) OVERRIDE { } void MoveInLineOfSight(Unit* /*who*/) OVERRIDE { } - void JustDied(Unit* /*killer*/) OVERRIDE - { - DoCast(me, SPELL_FLAME_SPHERE_DEATH_EFFECT); - } - void UpdateAI(uint32 diff) OVERRIDE { - if (_despawnTimer <= diff) - me->DisappearAndDie(); - else - _despawnTimer -= diff; + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_START_MOVE: + { + DoCast(me, SPELL_FLAME_SPHERE_PERIODIC, true); + + /// @todo: find correct values + float angleOffset = 0.0f; + float distOffset = DATA_SPHERE_DISTANCE; + + switch (me->GetEntry()) + { + case NPC_FLAME_SPHERE_1: + break; + case NPC_FLAME_SPHERE_2: + angleOffset = DATA_SPHERE_ANGLE_OFFSET; + break; + case NPC_FLAME_SPHERE_3: + angleOffset = -DATA_SPHERE_ANGLE_OFFSET; + break; + default: + return; + } + + Unit* sphereTarget = ObjectAccessor::GetUnit(*me, _flameSphereTargetGUID); + if (!sphereTarget) + return; + + float angle = me->GetAngle(sphereTarget) + angleOffset; + float x = me->GetPositionX() + distOffset * std::cos(angle); + float y = me->GetPositionY() + distOffset * std::sin(angle); + + /// @todo: correct speed + me->GetMotionMaster()->MovePoint(0, x, y, me->GetPositionZ()); + break; + } + case EVENT_DESPAWN: + DoCast(me, SPELL_FLAME_SPHERE_DEATH_EFFECT, true); + me->DespawnOrUnsummon(1000); + break; + default: + break; + } + } } private: - uint32 _despawnTimer; + EventMap _events; + uint64 _flameSphereTargetGUID; }; CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return new npc_taldaram_flamesphereAI(creature); + return new npc_prince_taldaram_flame_sphereAI(creature); } }; -class prince_taldaram_sphere : public GameObjectScript +// 193093, 193094 - Ancient Nerubian Device +class go_prince_taldaram_sphere : public GameObjectScript { public: - prince_taldaram_sphere() : GameObjectScript("prince_taldaram_sphere") { } + go_prince_taldaram_sphere() : GameObjectScript("go_prince_taldaram_sphere") { } bool OnGossipHello(Player* /*player*/, GameObject* go) OVERRIDE { @@ -369,7 +382,6 @@ class prince_taldaram_sphere : public GameObjectScript Creature* PrinceTaldaram = ObjectAccessor::GetCreature(*go, instance->GetData64(DATA_PRINCE_TALDARAM)); if (PrinceTaldaram && PrinceTaldaram->IsAlive()) { - // maybe these are hacks :( go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); go->SetGoState(GO_STATE_ACTIVE); @@ -385,15 +397,88 @@ class prince_taldaram_sphere : public GameObjectScript break; } - CAST_AI(boss_taldaram::boss_taldaramAI, PrinceTaldaram->AI())->CheckSpheres(); + CAST_AI(boss_prince_taldaram::boss_prince_taldaramAI, PrinceTaldaram->AI())->CheckSpheres(); } return true; } }; +// 55931 - Conjure Flame Sphere +class spell_prince_taldaram_conjure_flame_sphere : public SpellScriptLoader +{ + public: + spell_prince_taldaram_conjure_flame_sphere() : SpellScriptLoader("spell_prince_taldaram_conjure_flame_sphere") { } + + class spell_prince_taldaram_conjure_flame_sphere_SpellScript : public SpellScript + { + PrepareSpellScript(spell_prince_taldaram_conjure_flame_sphere_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_FLAME_SPHERE_SUMMON_1) + || !sSpellMgr->GetSpellInfo(SPELL_FLAME_SPHERE_SUMMON_2) + || !sSpellMgr->GetSpellInfo(SPELL_FLAME_SPHERE_SUMMON_3)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_1, true); + + if (caster->GetMap()->IsHeroic()) + { + caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_2, true); + caster->CastSpell(caster, SPELL_FLAME_SPHERE_SUMMON_3, true); + } + } + + void Register() OVERRIDE + { + OnEffectHitTarget += SpellEffectFn(spell_prince_taldaram_conjure_flame_sphere_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_prince_taldaram_conjure_flame_sphere_SpellScript(); + } +}; + +// 55895, 59511, 59512 - Flame Sphere Summon +class spell_prince_taldaram_flame_sphere_summon : public SpellScriptLoader +{ + public: + spell_prince_taldaram_flame_sphere_summon() : SpellScriptLoader("spell_prince_taldaram_flame_sphere_summon") { } + + class spell_prince_taldaram_flame_sphere_summon_SpellScript : public SpellScript + { + PrepareSpellScript(spell_prince_taldaram_flame_sphere_summon_SpellScript); + + void SetDest(SpellDestination& dest) + { + Position offset = { 0.0f, 0.0f, 5.5f, 0.0f }; + dest.RelocateOffset(offset); + } + + void Register() OVERRIDE + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_prince_taldaram_flame_sphere_summon_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_prince_taldaram_flame_sphere_summon_SpellScript(); + } +}; + void AddSC_boss_taldaram() { - new boss_taldaram(); - new npc_taldaram_flamesphere(); - new prince_taldaram_sphere(); + new boss_prince_taldaram(); + new npc_prince_taldaram_flame_sphere(); + new go_prince_taldaram_sphere(); + new spell_prince_taldaram_conjure_flame_sphere(); + new spell_prince_taldaram_flame_sphere_summon(); } diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp index 7534e747ee0..a7ad7dbfb4b 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp @@ -84,7 +84,7 @@ public: uiDoorsTimer = urand(20*IN_MILLISECONDS, 30*IN_MILLISECONDS); uiCheckDistanceTimer = 2*IN_MILLISECONDS; - if (instance && (instance->GetBossState(DATA_HADRONOX) != DONE && !bFirstTime)) + if (instance->GetBossState(DATA_HADRONOX) != DONE && !bFirstTime) instance->SetBossState(DATA_HADRONOX, FAIL); bFirstTime = false; diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp index dd699911786..9ae6f811e19 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp @@ -253,7 +253,7 @@ struct dummy_dragonAI : public ScriptedAI { case NPC_TENEBRON: { - if (instance && !instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) + if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) { for (uint32 i = 0; i < 6; ++i) me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggs[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); @@ -267,7 +267,7 @@ struct dummy_dragonAI : public ScriptedAI } case NPC_SHADRON: { - if (instance && !instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) + if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000); else me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000); @@ -276,7 +276,7 @@ struct dummy_dragonAI : public ScriptedAI } case NPC_VESPERON: { - if (instance && !instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) + if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS) { if (Creature* acolyte = me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000)) { @@ -328,19 +328,19 @@ struct dummy_dragonAI : public ScriptedAI { case NPC_TENEBRON: spellId = SPELL_POWER_OF_TENEBRON; - if (instance && instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) + if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) instance->SetBossState(DATA_TENEBRON, DONE); break; case NPC_SHADRON: spellId = SPELL_POWER_OF_SHADRON; - if (instance && instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) + if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) instance->SetBossState(DATA_SHADRON, DONE); if (Creature* acolyte = me->FindNearestCreature(NPC_ACOLYTE_OF_SHADRON, 100.0f)) acolyte->Kill(acolyte); break; case NPC_VESPERON: spellId = SPELL_POWER_OF_VESPERON; - if (instance && instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) + if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) instance->SetBossState(DATA_VESPERON, DONE); if (Creature* acolyte = me->FindNearestCreature(NPC_ACOLYTE_OF_VESPERON, 100.0f)) acolyte->Kill(acolyte); diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp index 91c1563b494..6c0acc9bba4 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp @@ -252,9 +252,8 @@ class npc_baltharus_the_warborn_clone : public CreatureScript void JustDied(Unit* killer) OVERRIDE { // This is here because DamageTaken wont trigger if the damage is deadly. - if (_instance) - if (Creature* baltharus = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_BALTHARUS_THE_WARBORN))) - killer->Kill(baltharus); + if (Creature* baltharus = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_BALTHARUS_THE_WARBORN))) + killer->Kill(baltharus); } void UpdateAI(uint32 diff) OVERRIDE @@ -262,8 +261,7 @@ class npc_baltharus_the_warborn_clone : public CreatureScript if (!UpdateVictim()) return; - if (_instance) - me->SetHealth(_instance->GetData(DATA_BALTHARUS_SHARED_HEALTH)); + me->SetHealth(_instance->GetData(DATA_BALTHARUS_SHARED_HEALTH)); _events.Update(diff); diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 0f583d54a13..c35c9ba2d11 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -1697,6 +1697,7 @@ class spell_halion_twilight_phasing : public SpellScriptLoader } }; +// 74805 - Summon Exit Portals class spell_halion_summon_exit_portals : public SpellScriptLoader { public: @@ -1706,23 +1707,22 @@ class spell_halion_summon_exit_portals : public SpellScriptLoader { PrepareSpellScript(spell_halion_summon_exit_portals_SpellScript); - void OnSummon(SpellEffIndex effIndex) + void SetDest0(SpellDestination& dest) { - WorldLocation summonPos = *GetExplTargetDest(); - Position offset = {0.0f, 20.0f, 0.0f, 0.0f}; - if (effIndex == EFFECT_1) - offset.m_positionY = -20.0f; - - summonPos.RelocateOffset(offset); + Position const offset = { 0.0f, 20.0f, 0.0f, 0.0f }; + dest.RelocateOffset(offset); + } - SetExplTargetDest(summonPos); - GetHitDest()->RelocateOffset(offset); + void SetDest1(SpellDestination& dest) + { + Position const offset = { 0.0f, -20.0f, 0.0f, 0.0f }; + dest.RelocateOffset(offset); } void Register() OVERRIDE { - OnEffectLaunch += SpellEffectFn(spell_halion_summon_exit_portals_SpellScript::OnSummon, EFFECT_0, SPELL_EFFECT_SUMMON_OBJECT_WILD); - OnEffectLaunch += SpellEffectFn(spell_halion_summon_exit_portals_SpellScript::OnSummon, EFFECT_1, SPELL_EFFECT_SUMMON_OBJECT_WILD); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_halion_summon_exit_portals_SpellScript::SetDest0, EFFECT_0, TARGET_DEST_CASTER); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_halion_summon_exit_portals_SpellScript::SetDest1, EFFECT_1, TARGET_DEST_CASTER); } }; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp index 3b1b5d4fd24..d2f6b8a3420 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp @@ -363,11 +363,11 @@ public: { bDone = true; - if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) + if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f); EnterEvadeMode(); @@ -496,11 +496,11 @@ public: { bDone = true; - if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) + if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f); instance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); @@ -639,11 +639,11 @@ public: { bDone = true; - if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) + if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f); instance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); @@ -783,11 +783,11 @@ public: { bDone = true; - if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) + if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f); instance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); @@ -929,11 +929,11 @@ public: { bDone = true; - if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) + if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1)) me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2)) me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f); - else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) + else if (me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3)) me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f); instance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp index ab21393fce3..a60e69d6479 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp @@ -431,7 +431,7 @@ public: void JustSummoned(Creature* summon) OVERRIDE { - if (instance && instance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) + if (instance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) { summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); summon->SetReactState(REACT_PASSIVE); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index 0b9b9f2543f..93d5c399725 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -470,7 +470,7 @@ class npc_swarm_scarab : public CreatureScript void UpdateAI(uint32 diff) OVERRIDE { - if (_instance && _instance->GetBossState(BOSS_ANUBARAK) != IN_PROGRESS) + if (_instance->GetBossState(BOSS_ANUBARAK) != IN_PROGRESS) me->DisappearAndDie(); if (!UpdateVictim()) @@ -540,7 +540,7 @@ class npc_nerubian_burrower : public CreatureScript void UpdateAI(uint32 diff) OVERRIDE { - if (_instance && _instance->GetBossState(BOSS_ANUBARAK) != IN_PROGRESS) + if (_instance->GetBossState(BOSS_ANUBARAK) != IN_PROGRESS) me->DisappearAndDie(); if (!UpdateVictim() && !me->HasAura(SPELL_SUBMERGE_EFFECT)) diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index 99423a4b7ae..cb4b3cfcea3 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -239,7 +239,7 @@ class npc_legion_flame : public CreatureScript void UpdateAI(uint32 /*diff*/) OVERRIDE { UpdateVictim(); - if (_instance && _instance->GetBossState(BOSS_JARAXXUS) != IN_PROGRESS) + if (_instance->GetBossState(BOSS_JARAXXUS) != IN_PROGRESS) me->DespawnOrUnsummon(); } private: @@ -326,7 +326,7 @@ class npc_fel_infernal : public CreatureScript void UpdateAI(uint32 diff) OVERRIDE { - if (_instance && _instance->GetBossState(BOSS_JARAXXUS) != IN_PROGRESS) + if (_instance->GetBossState(BOSS_JARAXXUS) != IN_PROGRESS) { me->DespawnOrUnsummon(); return; @@ -420,8 +420,7 @@ class npc_mistress_of_pain : public CreatureScript npc_mistress_of_painAI(Creature* creature) : ScriptedAI(creature) { _instance = creature->GetInstanceScript(); - if (_instance) - _instance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, INCREASE); + _instance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, INCREASE); } void Reset() OVERRIDE @@ -435,13 +434,12 @@ class npc_mistress_of_pain : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (_instance) - _instance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, DECREASE); + _instance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, DECREASE); } void UpdateAI(uint32 diff) OVERRIDE { - if (_instance && _instance->GetBossState(BOSS_JARAXXUS) != IN_PROGRESS) + if (_instance->GetBossState(BOSS_JARAXXUS) != IN_PROGRESS) { me->DespawnOrUnsummon(); return; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index a11a74250f5..ea166585bb3 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -295,8 +295,7 @@ class npc_snobold_vassal : public CreatureScript npc_snobold_vassalAI(Creature* creature) : ScriptedAI(creature) { _instance = creature->GetInstanceScript(); - if (_instance) - _instance->SetData(DATA_SNOBOLD_COUNT, INCREASE); + _instance->SetData(DATA_SNOBOLD_COUNT, INCREASE); } void Reset() OVERRIDE @@ -350,8 +349,7 @@ class npc_snobold_vassal : public CreatureScript if (Unit* target = ObjectAccessor::GetPlayer(*me, _targetGUID)) if (target->IsAlive()) target->RemoveAurasDueToSpell(SPELL_SNOBOLLED); - if (_instance) - _instance->SetData(DATA_SNOBOLD_COUNT, DECREASE); + _instance->SetData(DATA_SNOBOLD_COUNT, DECREASE); } void DoAction(int32 action) OVERRIDE @@ -378,30 +376,27 @@ class npc_snobold_vassal : public CreatureScript { if (!target->IsAlive()) { - if (_instance) + Unit* gormok = ObjectAccessor::GetCreature(*me, _instance->GetData64(NPC_GORMOK)); + if (gormok && gormok->IsAlive()) { - Unit* gormok = ObjectAccessor::GetCreature(*me, _instance->GetData64(NPC_GORMOK)); - if (gormok && gormok->IsAlive()) - { - SetCombatMovement(false); - _targetDied = true; + SetCombatMovement(false); + _targetDied = true; - // looping through Gormoks seats - for (uint8 i = 0; i < MAX_SNOBOLDS; i++) + // looping through Gormoks seats + for (uint8 i = 0; i < MAX_SNOBOLDS; i++) + { + if (!gormok->GetVehicleKit()->GetPassenger(i)) { - if (!gormok->GetVehicleKit()->GetPassenger(i)) - { - me->EnterVehicle(gormok, i); - DoAction(ACTION_ENABLE_FIRE_BOMB); - break; - } + me->EnterVehicle(gormok, i); + DoAction(ACTION_ENABLE_FIRE_BOMB); + break; } } - else if (Unit* target2 = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) - { - _targetGUID = target2->GetGUID(); - me->GetMotionMaster()->MoveJump(target2->GetPositionX(), target2->GetPositionY(), target2->GetPositionZ(), 15.0f, 15.0f); - } + } + else if (Unit* target2 = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + { + _targetGUID = target2->GetGUID(); + me->GetMotionMaster()->MoveJump(target2->GetPositionX(), target2->GetPositionY(), target2->GetPositionZ(), 15.0f, 15.0f); } } } @@ -528,7 +523,7 @@ struct boss_jormungarAI : public BossAI void JustReachedHome() OVERRIDE { // prevent losing 2 attempts at once on heroics - if (instance && instance->GetData(TYPE_NORTHREND_BEASTS) != FAIL) + if (instance->GetData(TYPE_NORTHREND_BEASTS) != FAIL) instance->SetData(TYPE_NORTHREND_BEASTS, FAIL); me->DespawnOrUnsummon(); @@ -552,7 +547,7 @@ struct boss_jormungarAI : public BossAI if (!UpdateVictim()) return; - if (!Enraged && instance && instance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL) + if (!Enraged && instance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL) { me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp index cb0ec2acc38..fdefde10b4f 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -247,8 +247,8 @@ class boss_lich_king_toc : public CreatureScript summoned->CastSpell(summoned, 51807, false); summoned->SetDisplayId(summoned->GetCreatureTemplate()->Modelid2); } - if (_instance) - _instance->SetBossState(BOSS_LICH_KING, IN_PROGRESS); + + _instance->SetBossState(BOSS_LICH_KING, IN_PROGRESS); me->SetWalk(true); } @@ -401,12 +401,9 @@ class npc_fizzlebang_toc : public CreatureScript { case 1: me->SetWalk(false); - if (_instance) - { - _instance->DoUseDoorOrButton(_instance->GetData64(GO_MAIN_GATE_DOOR)); - _instance->SetData(TYPE_EVENT, 1120); - _instance->SetData(TYPE_EVENT_TIMER, 1*IN_MILLISECONDS); - } + _instance->DoUseDoorOrButton(_instance->GetData64(GO_MAIN_GATE_DOOR)); + _instance->SetData(TYPE_EVENT, 1120); + _instance->SetData(TYPE_EVENT_TIMER, 1*IN_MILLISECONDS); break; default: break; diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index c9247ce17f3..1f4713415ac 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -664,8 +664,7 @@ class npc_jaina_or_sylvanas_hor : public CreatureScript _events.ScheduleEvent(EVENT_INTRO_END, 5000); break; case EVENT_INTRO_END: - if (_instance) - _instance->SetData(DATA_INTRO_EVENT, DONE); + _instance->SetData(DATA_INTRO_EVENT, DONE); // Loralen or Koreln disappearAndDie() if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID)) { @@ -1830,7 +1829,7 @@ public: _emergeTimer = 4000; _doEmerge = false; _doJump = false; - if (_instance && _instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS) + if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS) _instance->SetData(DATA_SUMMONS, 1); } @@ -1838,13 +1837,11 @@ public: void IsSummonedBy(Unit*) OVERRIDE { DoCast(me, SPELL_EMERGE_VISUAL); - DoZoneInCombat(me, 100.00f); } void JustDied(Unit* /*killer*/) OVERRIDE { - if (_instance) - _instance->SetData(DATA_SUMMONS, 0); + _instance->SetData(DATA_SUMMONS, 0); } void AttackStart(Unit* who) OVERRIDE @@ -1932,9 +1929,8 @@ public: _boltVolleyTimer = 15000; _curseTimer = 7000; _doEmerge = false; - if (_instance) - if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS) - _instance->SetData(DATA_SUMMONS, 1); + if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS) + _instance->SetData(DATA_SUMMONS, 1); } void IsSummonedBy(Unit*) OVERRIDE @@ -1945,9 +1941,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { - if (_instance) - _instance->SetData(DATA_SUMMONS, 0); - + _instance->SetData(DATA_SUMMONS, 0); } void AttackStart(Unit* who) OVERRIDE @@ -2049,9 +2043,8 @@ public: _doWalk = false; _vomitTimer = 15000; _strikeTimer = 6000; - if (_instance) - if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS) - _instance->SetData(DATA_SUMMONS, 1); + if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS) + _instance->SetData(DATA_SUMMONS, 1); } void IsSummonedBy(Unit*) OVERRIDE @@ -2062,9 +2055,6 @@ public: void UpdateAI(uint32 diff) OVERRIDE { - if (!_instance) - return; - if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS) { if (_doWalk != true) @@ -2103,8 +2093,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { - if (_instance) - _instance->SetData(DATA_SUMMONS, 0); + _instance->SetData(DATA_SUMMONS, 0); } }; diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h index ff3192b89d5..c4776c3cfcd 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h @@ -147,9 +147,9 @@ struct boss_horAI : ScriptedAI { events.Reset(); me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); me->SetReactState(REACT_PASSIVE); - if (instance && instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED) + if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED) instance->ProcessEvent(0, EVENT_DO_WIPE); } @@ -158,7 +158,7 @@ struct boss_horAI : ScriptedAI switch (actionID) { case ACTION_ENTER_COMBAT: // called by InstanceScript when boss shall enter in combat. - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); me->SetReactState(REACT_AGGRESSIVE); if (Unit* unit = me->SelectNearestTarget()) diff --git a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp index 5a16271d378..46912eeb898 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp @@ -423,7 +423,7 @@ public: if (id == 1) { - if (Creature* colossus = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + if (Creature* colossus = Unit::GetCreature(*me, instance->GetData64(DATA_DRAKKARI_COLOSSUS))) { colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS); if (!colossus->AI()->GetData(DATA_INTRO_DONE)) @@ -440,7 +440,7 @@ public: return; // we do this checks to see if the creature is one of the creatures that sorround the boss - if (Creature* colossus = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + if (Creature* colossus = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DRAKKARI_COLOSSUS))) { Position homePosition; me->GetHomePosition().GetPosition(&homePosition); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index 30c11ec556d..b053f0a0258 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -1492,6 +1492,7 @@ class spell_taldaram_ball_of_inferno_flame : public SpellScriptLoader } }; +// 72080 - Kinetic Bomb (Valanar) class spell_valanar_kinetic_bomb : public SpellScriptLoader { public: @@ -1501,18 +1502,15 @@ class spell_valanar_kinetic_bomb : public SpellScriptLoader { PrepareSpellScript(spell_valanar_kinetic_bomb_SpellScript); - void ChangeSummonPos(SpellEffIndex /*effIndex*/) + void SetDest(SpellDestination& dest) { - WorldLocation summonPos = *GetExplTargetDest(); - Position offset = {0.0f, 0.0f, 20.0f, 0.0f}; - summonPos.RelocateOffset(offset); - SetExplTargetDest(summonPos); - GetHitDest()->RelocateOffset(offset); + Position const offset = { 0.0f, 0.0f, 20.0f, 0.0f }; + dest.RelocateOffset(offset); } void Register() OVERRIDE { - OnEffectHit += SpellEffectFn(spell_valanar_kinetic_bomb_SpellScript::ChangeSummonPos, EFFECT_0, SPELL_EFFECT_SUMMON); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_valanar_kinetic_bomb_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index f3b62cd7b24..ca2c75e502c 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -2034,6 +2034,7 @@ class spell_svalna_remove_spear : public SpellScriptLoader } }; +// 72585 - Soul Missile class spell_icc_soul_missile : public SpellScriptLoader { public: @@ -2043,15 +2044,15 @@ class spell_icc_soul_missile : public SpellScriptLoader { PrepareSpellScript(spell_icc_soul_missile_SpellScript); - void RelocateDest() + void RelocateDest(SpellDestination& dest) { - static Position const offset = {0.0f, 0.0f, 200.0f, 0.0f}; - const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); + static Position const offset = { 0.0f, 0.0f, 200.0f, 0.0f }; + dest.RelocateOffset(offset); } void Register() OVERRIDE { - OnCast += SpellCastFn(spell_icc_soul_missile_SpellScript::RelocateDest); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_icc_soul_missile_SpellScript::RelocateDest, EFFECT_0, TARGET_DEST_CASTER); } }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 41d1f53b52d..2091b82e20c 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -374,11 +374,11 @@ public: void FindGameObjects() { - PortalsGUID[0] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL01) : 0; - PortalsGUID[1] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL02) : 0; - PortalsGUID[2] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL03) : 0; - PortalsGUID[3] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL04) : 0; - KTTriggerGUID = instance ? instance->GetData64(DATA_KELTHUZAD_TRIGGER) : 0; + PortalsGUID[0] = instance->GetData64(DATA_KELTHUZAD_PORTAL01); + PortalsGUID[1] = instance->GetData64(DATA_KELTHUZAD_PORTAL02); + PortalsGUID[2] = instance->GetData64(DATA_KELTHUZAD_PORTAL03); + PortalsGUID[3] = instance->GetData64(DATA_KELTHUZAD_PORTAL04); + KTTriggerGUID = instance->GetData64(DATA_KELTHUZAD_TRIGGER); } void UpdateAI(uint32 diff) OVERRIDE @@ -757,8 +757,7 @@ class npc_kelthuzad_abomination : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (_instance) - _instance->SetData(DATA_ABOMINATION_KILLED, _instance->GetData(DATA_ABOMINATION_KILLED) + 1); + _instance->SetData(DATA_ABOMINATION_KILLED, _instance->GetData(DATA_ABOMINATION_KILLED) + 1); } private: diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 4e386afae17..7ae9ce3faa6 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -450,7 +450,7 @@ public: { case ACTION_LAND_ENCOUNTER_START: events.CancelEventGroup(1); - if (Creature* alexstraszaBunny = me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) + if (Creature* alexstraszaBunny = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) { Position pos; pos.m_positionZ = alexstraszaBunny->GetPositionZ(); @@ -713,7 +713,8 @@ public: { _firstCyclicMovementStarted = true; me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFacingToObject(me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))); + if (Creature* alexstraszaBunny = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) + me->SetFacingToObject(alexstraszaBunny); events.ScheduleEvent(EVENT_SUMMON_ARCANE_BOMB, 1*IN_MILLISECONDS, 0, PHASE_TWO); } _flyingOutOfPlatform = false; @@ -722,7 +723,8 @@ public: break; case POINT_PHASE_ONE_TO_TWO_TRANSITION: me->SetDisableGravity(true); - me->SetFacingToObject(me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))); + if (Creature* alexstraszaBunny = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) + me->SetFacingToObject(alexstraszaBunny); SendLightOverride(LIGHT_ARCANE_RUNES, 5*IN_MILLISECONDS); events.ScheduleEvent(EVENT_FLY_OUT_OF_PLATFORM, 18*IN_MILLISECONDS, 0, PHASE_TWO); break; @@ -780,7 +782,7 @@ public: me->CastCustomSpell(SPELL_RANDOM_PORTAL, SPELLVALUE_MAX_TARGETS, 1); break; case EVENT_LAND_START_ENCOUNTER: - if (GameObject* iris = me->GetMap()->GetGameObject(instance->GetData64(DATA_FOCUSING_IRIS_GUID))) + if (GameObject* iris = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_FOCUSING_IRIS_GUID))) { me->SetFacingToObject(iris); iris->Delete(); // this is not the best way. @@ -837,7 +839,7 @@ public: case EVENT_FLY_OUT_OF_PLATFORM: if (!_performingDestroyPlatform) { - if (Creature* alexstraszaBunny = me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) + if (Creature* alexstraszaBunny = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) { Position randomPosOnRadius; // Hardcodded retail value, reason is Z getters can fail... (TO DO: Change to getter when height calculation works on 100%!) @@ -908,7 +910,7 @@ public: if (!_flyingOutOfPlatform) { DoCast(me, SPELL_SUMMON_ARCANE_BOMB, true); - if (Creature* lastArcaneOverloadBunny = me->GetMap()->GetCreature(_arcaneOverloadGUID)) + if (Creature* lastArcaneOverloadBunny = ObjectAccessor::GetCreature(*me, _arcaneOverloadGUID)) DoCast(lastArcaneOverloadBunny, SPELL_ARCANE_BOMB_TRIGGER, true); } events.ScheduleEvent(EVENT_SUMMON_ARCANE_BOMB, urand(15, 16)*IN_MILLISECONDS, 2, PHASE_TWO); @@ -993,7 +995,7 @@ public: { _JustDied(); Talk(SAY_DEATH); - if (Creature* alexstraszaGiftBoxBunny = me->GetMap()->GetCreature(instance->GetData64(DATA_GIFT_BOX_BUNNY_GUID))) + if (Creature* alexstraszaGiftBoxBunny = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_GIFT_BOX_BUNNY_GUID))) { if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) alexstraszaGiftBoxBunny->SummonGameObject(GO_HEART_OF_MAGIC_10, HeartOfMagicSpawnPos.GetPositionX(), HeartOfMagicSpawnPos.GetPositionY(), @@ -1087,7 +1089,7 @@ public: { if (spell->Id == SPELL_PORTAL_OPENED) { - if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + if (Creature* malygos = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) { if (malygos->AI()->GetData(DATA_PHASE) == PHASE_ONE) DoCast(me, SPELL_SUMMON_POWER_PARK, true); @@ -1101,15 +1103,12 @@ public: if (!me->HasAura(SPELL_PORTAL_VISUAL_CLOSED) && !me->HasAura(SPELL_PORTAL_OPENED)) DoCast(me, SPELL_PORTAL_VISUAL_CLOSED, true); - if (_instance) + if (Creature* malygos = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) { - if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + if (malygos->AI()->GetData(DATA_PHASE) != PHASE_ONE && me->HasAura(SPELL_PORTAL_OPENED)) { - if (malygos->AI()->GetData(DATA_PHASE) != PHASE_ONE && me->HasAura(SPELL_PORTAL_OPENED)) - { - me->RemoveAura(SPELL_PORTAL_OPENED); - DoCast(me, SPELL_PORTAL_VISUAL_CLOSED, true); - } + me->RemoveAura(SPELL_PORTAL_OPENED); + DoCast(me, SPELL_PORTAL_VISUAL_CLOSED, true); } } } @@ -1143,9 +1142,8 @@ public: { me->GetMotionMaster()->MoveIdle(); - if (_instance) - if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) - me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f); + if (Creature* malygos = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) + me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f); } void UpdateAI(uint32 /*diff*/) OVERRIDE @@ -1153,7 +1151,7 @@ public: if (!_instance) return; - if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + if (Creature* malygos = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) { if (malygos->AI()->GetData(DATA_PHASE) != PHASE_ONE || _instance->GetBossState(DATA_MALYGOS_EVENT) == FAIL) { @@ -1432,7 +1430,7 @@ class npc_nexus_lord : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + if (Creature* malygos = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) malygos->AI()->SetData(DATA_SUMMON_DEATHS, malygos->AI()->GetData(DATA_SUMMON_DEATHS) + 1); } @@ -1499,7 +1497,7 @@ class npc_scion_of_eternity : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + if (Creature* malygos = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) malygos->AI()->SetData(DATA_SUMMON_DEATHS, malygos->AI()->GetData(DATA_SUMMON_DEATHS) + 1); } @@ -1542,7 +1540,7 @@ public: void DoAction(int32 /*action*/) OVERRIDE { - if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + if (Creature* malygos = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) { if (malygos->AI()->GetData(DATA_PHASE) == PHASE_TWO) me->DespawnOrUnsummon(6*IN_MILLISECONDS); @@ -2047,7 +2045,7 @@ class spell_scion_of_eternity_arcane_barrage : public SpellScriptLoader Creature* caster = GetCaster()->ToCreature(); InstanceScript* instance = caster->GetInstanceScript(); - Creature* malygos = caster->GetMap()->GetCreature(instance->GetData64(DATA_MALYGOS)); + Creature* malygos = ObjectAccessor::GetCreature(*caster, instance->GetData64(DATA_MALYGOS)); // If max possible targets are more than 1 then Scions wouldn't select previosly selected target, // in longer terms this means if spell picks target X then 2nd cast of this spell will pick smth else @@ -2232,6 +2230,7 @@ class spell_alexstrasza_bunny_destroy_platform_event : public SpellScriptLoader } }; +// 56070 - Summon Red Dragon Buddy class spell_wyrmrest_skytalon_summon_red_dragon_buddy : public SpellScriptLoader { public: @@ -2246,19 +2245,16 @@ class spell_wyrmrest_skytalon_summon_red_dragon_buddy : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_PLAYER; } - void ChangeSummonPos(SpellEffIndex /*effIndex*/) + void SetDest(SpellDestination& dest) { // Adjust effect summon position to lower Z - WorldLocation summonPos = *GetExplTargetDest(); - Position offset = { 0.0f, 0.0f, -80.0f, 0.0f }; - summonPos.RelocateOffset(offset); - SetExplTargetDest(summonPos); - GetHitDest()->RelocateOffset(offset); + Position const offset = { 0.0f, 0.0f, -80.0f, 0.0f }; + dest.RelocateOffset(offset); } void Register() OVERRIDE { - OnEffectHit += SpellEffectFn(spell_wyrmrest_skytalon_summon_red_dragon_buddy_SpellScript::ChangeSummonPos, EFFECT_0, SPELL_EFFECT_SUMMON); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_wyrmrest_skytalon_summon_red_dragon_buddy_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER_RADIUS); } }; diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp index 2f6a328b728..9943ad7e1b1 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp @@ -213,7 +213,7 @@ public: { InstanceScript* instance = go->GetInstanceScript(); - Creature* pKeristrasza = Unit::GetCreature(*go, instance ? instance->GetData64(DATA_KERISTRASZA) : 0); + Creature* pKeristrasza = ObjectAccessor::GetCreature(*go, instance->GetData64(DATA_KERISTRASZA)); if (pKeristrasza && pKeristrasza->IsAlive()) { // maybe these are hacks :( diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp index 40e526219fa..506e16741fb 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -375,27 +375,16 @@ class spell_oculus_call_ruby_emerald_amber_drake : public SpellScriptLoader { PrepareSpellScript(spell_oculus_call_ruby_emerald_amber_drake_SpellScript); - void ChangeSummonPos(SpellEffIndex /*effIndex*/) + void SetDest(SpellDestination& dest) { // Adjust effect summon position - WorldLocation summonPos = *GetExplTargetDest(); - Position offset = { 0.0f, 0.0f, 12.0f, 0.0f }; - summonPos.RelocateOffset(offset); - SetExplTargetDest(summonPos); - GetHitDest()->RelocateOffset(offset); - } - - void ModDestHeight(SpellEffIndex /*effIndex*/) - { - // Used to cast visual effect at proper position - Position offset = { 0.0f, 0.0f, 12.0f, 0.0f }; - const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); + Position const offset = { 0.0f, 0.0f, 12.0f, 0.0f }; + dest.RelocateOffset(offset); } void Register() OVERRIDE { - OnEffectHit += SpellEffectFn(spell_oculus_call_ruby_emerald_amber_drake_SpellScript::ChangeSummonPos, EFFECT_0, SPELL_EFFECT_SUMMON); - OnEffectLaunch += SpellEffectFn(spell_oculus_call_ruby_emerald_amber_drake_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_oculus_call_ruby_emerald_amber_drake_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER_FRONT); } }; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index c666a36741b..1788ecacd35 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -168,7 +168,7 @@ public: for (std::list<uint64>::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr) { - if (Creature* pSpark = Unit::GetCreature(*me, *itr)) + if (Creature* pSpark = ObjectAccessor::GetCreature(*me, *itr)) { if (pSpark->IsAlive()) { @@ -297,11 +297,6 @@ class npc_spark_of_ionar : public CreatureScript public: npc_spark_of_ionar() : CreatureScript("npc_spark_of_ionar") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return GetInstanceAI<npc_spark_of_ionarAI>(creature); - } - struct npc_spark_of_ionarAI : public ScriptedAI { npc_spark_of_ionarAI(Creature* creature) : ScriptedAI(creature) @@ -336,7 +331,7 @@ public: void UpdateAI(uint32 uiDiff) OVERRIDE { // Despawn if the encounter is not running - if (instance && instance->GetBossState(DATA_IONAR) != IN_PROGRESS) + if (instance->GetBossState(DATA_IONAR) != IN_PROGRESS) { me->DespawnOrUnsummon(); return; @@ -345,13 +340,13 @@ public: // Prevent them to follow players through the whole instance if (uiCheckTimer <= uiDiff) { - Creature* pIonar = instance->instance->GetCreature(instance->GetData64(DATA_IONAR)); - if (pIonar && pIonar->IsAlive()) + Creature* ionar = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_IONAR)); + if (ionar && ionar->IsAlive()) { - if (me->GetDistance(pIonar) > DATA_MAX_SPARK_DISTANCE) + if (me->GetDistance(ionar) > DATA_MAX_SPARK_DISTANCE) { Position pos; - pIonar->GetPosition(&pos); + ionar->GetPosition(&pos); me->SetSpeed(MOVE_RUN, 2.0f); me->GetMotionMaster()->Clear(); @@ -369,6 +364,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetInstanceAI<npc_spark_of_ionarAI>(creature); + } }; void AddSC_boss_ionar() diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index a8f933431c3..9599700eccb 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -1253,6 +1253,7 @@ class spell_algalon_remove_phase : public SpellScriptLoader } }; +// 62295 - Cosmic Smash class spell_algalon_cosmic_smash : public SpellScriptLoader { public: @@ -1262,16 +1263,15 @@ class spell_algalon_cosmic_smash : public SpellScriptLoader { PrepareSpellScript(spell_algalon_cosmic_smash_SpellScript); - void ModDestHeight(SpellEffIndex /*effIndex*/) + void ModDestHeight(SpellDestination& dest) { - Position offset = {0.0f, 0.0f, 65.0f, 0.0f}; - const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); - GetHitDest()->RelocateOffset(offset); + Position const offset = { 0.0f, 0.0f, 65.0f, 0.0f }; + dest.RelocateOffset(offset); } void Register() OVERRIDE { - OnEffectLaunch += SpellEffectFn(spell_algalon_cosmic_smash_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_algalon_cosmic_smash_SpellScript::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER_SUMMON); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 779adf67211..ee1345590f3 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -1192,7 +1192,7 @@ class npc_lorekeeper : public CreatureScript bool OnGossipHello(Player* player, Creature* creature) OVERRIDE { InstanceScript* instance = creature->GetInstanceScript(); - if (instance && instance->GetData(BOSS_LEVIATHAN) !=DONE && player) + if (instance && instance->GetData(BOSS_LEVIATHAN) != DONE && player) { player->PrepareGossipMenu(creature); @@ -1285,8 +1285,7 @@ class go_ulduar_tower : public GameObjectScript break; } - Creature* trigger = go->FindNearestCreature(NPC_ULDUAR_GAUNTLET_GENERATOR, 15.0f, true); - if (trigger) + if (Creature* trigger = go->FindNearestCreature(NPC_ULDUAR_GAUNTLET_GENERATOR, 15.0f, true)) trigger->DisappearAndDie(); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index 480c04c3254..169a7085672 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -227,7 +227,7 @@ class npc_flash_freeze : public CreatureScript // Prevents to have Ice Block on other place than target is me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation()); if (target->GetTypeId() == TYPEID_PLAYER) - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(BOSS_HODIR) : 0)) + if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_HODIR))) Hodir->AI()->DoAction(ACTION_CHEESE_THE_FREEZE); } } @@ -279,7 +279,7 @@ class npc_ice_block : public CreatureScript { Helper->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(BOSS_HODIR) : 0)) + if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_HODIR))) { if (!Hodir->IsInCombat()) { @@ -658,7 +658,7 @@ class npc_hodir_priest : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(BOSS_HODIR) : 0)) + if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_HODIR))) Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); } @@ -720,7 +720,7 @@ class npc_hodir_shaman : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(BOSS_HODIR) : 0)) + if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_HODIR))) Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); } @@ -781,7 +781,7 @@ class npc_hodir_druid : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(BOSS_HODIR) : 0)) + if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_HODIR))) Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); } @@ -861,7 +861,7 @@ class npc_hodir_mage : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(BOSS_HODIR) : 0)) + if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_HODIR))) Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp index 862ee2c786b..e96cfaccc56 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp @@ -312,7 +312,7 @@ class go_razorscale_harpoon : public GameObjectScript bool OnGossipHello(Player* /*player*/, GameObject* go) OVERRIDE { InstanceScript* instance = go->GetInstanceScript(); - if (ObjectAccessor::GetCreature(*go, instance ? instance->GetData64(BOSS_RAZORSCALE) : 0)) + if (ObjectAccessor::GetCreature(*go, instance->GetData64(BOSS_RAZORSCALE))) go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); return false; } @@ -347,14 +347,14 @@ class boss_razorscale : public CreatureScript me->SetReactState(REACT_PASSIVE); PermaGround = false; HarpoonCounter = 0; - if (Creature* commander = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_EXPEDITION_COMMANDER) : 0)) + if (Creature* commander = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EXPEDITION_COMMANDER))) commander->AI()->DoAction(ACTION_COMMANDER_RESET); } void EnterCombat(Unit* /*who*/) OVERRIDE { _EnterCombat(); - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_RAZORSCALE_CONTROL) : 0)) + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_RAZORSCALE_CONTROL))) controller->AI()->DoAction(ACTION_HARPOON_BUILD); me->SetSpeed(MOVE_FLIGHT, 3.0f, true); me->SetReactState(REACT_PASSIVE); @@ -369,7 +369,7 @@ class boss_razorscale : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { _JustDied(); - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_RAZORSCALE_CONTROL) : 0)) + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_RAZORSCALE_CONTROL))) controller->AI()->Reset(); } @@ -445,7 +445,7 @@ class boss_razorscale : public CreatureScript me->SetCanFly(false); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); - if (Creature* commander = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_EXPEDITION_COMMANDER) : 0)) + if (Creature* commander = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EXPEDITION_COMMANDER))) commander->AI()->DoAction(ACTION_GROUND_PHASE); events.ScheduleEvent(EVENT_BREATH, 30000, 0, PHASE_GROUND); events.ScheduleEvent(EVENT_BUFFET, 33000, 0, PHASE_GROUND); @@ -461,7 +461,7 @@ class boss_razorscale : public CreatureScript return; case EVENT_BUFFET: DoCastAOE(SPELL_WINGBUFFET); - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(DATA_RAZORSCALE_CONTROL) : 0)) + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_RAZORSCALE_CONTROL))) controller->CastSpell(controller, SPELL_FLAMED, true); events.CancelEvent(EVENT_BUFFET); return; @@ -689,7 +689,7 @@ class npc_expedition_commander : public CreatureScript Phase = 5; break; case 5: - if (Creature* Razorscale = ObjectAccessor::GetCreature(*me, instance ? instance->GetData64(BOSS_RAZORSCALE) : 0)) + if (Creature* Razorscale = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_RAZORSCALE))) { Razorscale->AI()->DoAction(ACTION_EVENT_START); me->SetInCombatWith(Razorscale); diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp index 4dd3aa9916b..7377029080f 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp @@ -195,7 +195,7 @@ class npc_tempest_minion : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* emalon = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EMALON) : 0)) + if (Creature* emalon = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EMALON))) { if (emalon->IsAlive()) { @@ -210,7 +210,7 @@ class npc_tempest_minion : public CreatureScript DoZoneInCombat(); events.ScheduleEvent(EVENT_SHOCK, 20000); - if (Creature* pEmalon = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EMALON) : 0)) + if (Creature* pEmalon = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EMALON))) { if (!pEmalon->GetVictim() && pEmalon->AI()) pEmalon->AI()->AttackStart(who); diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp index ccb1b5ed7d8..bd2128a1b4c 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp @@ -241,7 +241,7 @@ class npc_frozen_orb_stalker : public CreatureScript npc_frozen_orb_stalkerAI(Creature* creature) : ScriptedAI(creature) { creature->SetVisible(false); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); creature->SetReactState(REACT_PASSIVE); instance = creature->GetInstanceScript(); @@ -256,7 +256,7 @@ class npc_frozen_orb_stalker : public CreatureScript return; spawned = true; - Unit* toravon = me->GetCreature(*me, instance ? instance->GetData64(DATA_TORAVON) : 0); + Unit* toravon = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TORAVON)); if (!toravon) return; diff --git a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp index ec20489bfc2..e53d046b396 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp @@ -90,7 +90,7 @@ public: void UpdateAI(uint32 diff) OVERRIDE { - if (instance && instance->GetData(DATA_REMOVE_NPC) == 1) + if (instance->GetData(DATA_REMOVE_NPC) == 1) { me->DespawnOrUnsummon(); instance->SetData(DATA_REMOVE_NPC, 0); diff --git a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp index 81edfd65d03..441603dcdc8 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp @@ -79,12 +79,12 @@ public: else if (instance->GetData(DATA_WAVE_COUNT) == 12) instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - if (Creature* pGuard1 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_1) : 0)) + if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_1))) { if (!pGuard1->IsAlive()) pGuard1->Respawn(); } - if (Creature* pGuard2 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_2) : 0)) + if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_2))) { if (!pGuard2->IsAlive()) pGuard2->Respawn(); @@ -103,15 +103,15 @@ public: who->SetInCombatWith(me); DoStartMovement(who); - if (Creature* pGuard1 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_1) : 0)) + if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_1))) { - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); if (!pGuard1->GetVictim() && pGuard1->AI()) pGuard1->AI()->AttackStart(who); } - if (Creature* pGuard2 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_2) : 0)) + if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_2))) { - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); if (!pGuard2->GetVictim() && pGuard2->AI()) pGuard2->AI()->AttackStart(who); } @@ -148,9 +148,9 @@ public: //spam stormstrike in hc mode if spawns are dead if (IsHeroic()) { - if (Creature* pGuard1 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_1) : 0)) + if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_1))) { - if (Creature* pGuard2 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_2) : 0)) + if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_2))) { if (!pGuard1->IsAlive() && !pGuard2->IsAlive()) DoCastVictim(SPELL_STORMSTRIKE); @@ -168,12 +168,12 @@ public: { if (uint64 TargetGUID = GetChainHealTargetGUID()) { - if (Creature* target = Unit::GetCreature(*me, TargetGUID)) + if (Creature* target = ObjectAccessor::GetCreature(*me, TargetGUID)) DoCast(target, SPELL_CHAIN_HEAL); //If one of the adds is dead spawn heals faster - Creature* pGuard1 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_1) : 0); - Creature* pGuard2 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_2) : 0); + Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_1)); + Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_2)); uiChainHealTimer = ((pGuard1 && !pGuard1->IsAlive()) || (pGuard2 && !pGuard2->IsAlive()) ? 3000 : 8000) + rand()%3000; } } else uiChainHealTimer -= diff; @@ -229,11 +229,11 @@ public: if (HealthBelowPct(85)) return me->GetGUID(); - Creature* pGuard1 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_1) : 0); + Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_1)); if (pGuard1 && pGuard1->IsAlive() && !pGuard1->HealthAbovePct(75)) return pGuard1->GetGUID(); - Creature* pGuard2 = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_EREKEM_GUARD_2) : 0); + Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_EREKEM_GUARD_2)); if (pGuard2 && pGuard2->IsAlive() && !pGuard2->HealthAbovePct(75)) return pGuard2->GetGUID(); diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp index 79025bb5c0f..5f79e609e01 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp @@ -446,7 +446,7 @@ public: void Reset() OVERRIDE { - if (instance && !uiBoss) + if (!uiBoss) uiBoss = instance->GetData(DATA_WAVE_COUNT) == 6 ? instance->GetData(DATA_FIRST_BOSS) : instance->GetData(DATA_SECOND_BOSS); me->SetReactState(REACT_PASSIVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); @@ -486,7 +486,7 @@ public: void UpdateAI(uint32 diff) OVERRIDE { - if (instance && instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS) + if (instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS) me->CastStop(); npc_escortAI::UpdateAI(diff); @@ -723,7 +723,7 @@ struct violet_hold_trashAI : public npc_escortAI void UpdateAI(uint32) OVERRIDE { - if (instance && instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS) + if (instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS) me->CastStop(); if (!bHasGotMovingPoints) diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index 0173454ef28..f840c0562b3 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -1359,10 +1359,7 @@ public: struct npc_counselor_talbotAI : public ScriptedAI { - npc_counselor_talbotAI(Creature* creature) : ScriptedAI(creature) - { - creature->RestoreFaction(); - } + npc_counselor_talbotAI(Creature* creature) : ScriptedAI(creature) { } uint64 leryssaGUID; uint64 arlosGUID; diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp index f91f5d8c007..7487c3c8828 100644 --- a/src/server/scripts/Northrend/zone_dragonblight.cpp +++ b/src/server/scripts/Northrend/zone_dragonblight.cpp @@ -150,7 +150,10 @@ class npc_commander_eligor_dawnbringer : public CreatureScript struct npc_commander_eligor_dawnbringerAI : public ScriptedAI { - npc_commander_eligor_dawnbringerAI(Creature* creature) : ScriptedAI(creature) { } + npc_commander_eligor_dawnbringerAI(Creature* creature) : ScriptedAI(creature) + { + talkWing = 0; + } void Reset() OVERRIDE { @@ -649,7 +652,10 @@ class npc_torturer_lecraft : public CreatureScript struct npc_torturer_lecraftAI : public ScriptedAI { - npc_torturer_lecraftAI(Creature* creature) : ScriptedAI(creature) { } + npc_torturer_lecraftAI(Creature* creature) : ScriptedAI(creature) + { + _playerGUID = 0; + } void Reset() OVERRIDE { diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index bacc6de57f0..112d42441b9 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -20,8 +20,6 @@ #include "ScriptedCreature.h" #include "ScriptedEscortAI.h" #include "Player.h" -#include "Spell.h" -#include "SpellInfo.h" #include "SpellScript.h" #include "CreatureTextMgr.h" diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index 69e4e65225a..70de4d4758d 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -451,7 +451,10 @@ public: struct npc_brann_bronzebeard_keystoneAI : public ScriptedAI { - npc_brann_bronzebeard_keystoneAI(Creature* creature) : ScriptedAI(creature) { } + npc_brann_bronzebeard_keystoneAI(Creature* creature) : ScriptedAI(creature) + { + objectCounter = 0; + } void Reset() OVERRIDE { @@ -634,7 +637,10 @@ public: struct npc_king_jokkum_vehicleAI : public VehicleAI { - npc_king_jokkum_vehicleAI(Creature* creature) : VehicleAI(creature) { } + npc_king_jokkum_vehicleAI(Creature* creature) : VehicleAI(creature) + { + pathEnd = false; + } void Reset() OVERRIDE { diff --git a/src/server/scripts/Northrend/zone_wintergrasp.cpp b/src/server/scripts/Northrend/zone_wintergrasp.cpp index 311b18524b2..e218741649d 100644 --- a/src/server/scripts/Northrend/zone_wintergrasp.cpp +++ b/src/server/scripts/Northrend/zone_wintergrasp.cpp @@ -249,7 +249,10 @@ class npc_wg_queue : public CreatureScript struct npc_wg_queueAI : public ScriptedAI { - npc_wg_queueAI(Creature* creature) : ScriptedAI(creature) { } + npc_wg_queueAI(Creature* creature) : ScriptedAI(creature) + { + FrostArmor_Timer = 0; + } uint32 FrostArmor_Timer; diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index 3bbd41afc89..d74aecb9b25 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -1672,7 +1672,7 @@ public: { if (Check_Timer <= diff) { - if (instance && instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE) + if (instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE) me->SetVisible(true); Check_Timer = 5000; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp index 6d632c81bca..9055bb1862d 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp @@ -139,21 +139,20 @@ public: RAdvisors[0] = instance->GetData64(DATA_SHARKKIS); RAdvisors[1] = instance->GetData64(DATA_TIDALVESS); RAdvisors[2] = instance->GetData64(DATA_CARIBDIS); - //Respawn of the 3 Advisors - Creature* pAdvisor = NULL; - for (int i=0; i<MAX_ADVISORS; ++i) + // Respawn of the 3 Advisors + for (uint8 i = 0; i < MAX_ADVISORS; ++i) if (RAdvisors[i]) { - pAdvisor = (Unit::GetCreature((*me), RAdvisors[i])); - if (pAdvisor && !pAdvisor->IsAlive()) + Creature* advisor = ObjectAccessor::GetCreature(*me, RAdvisors[i]); + if (advisor && !advisor->IsAlive()) { - pAdvisor->Respawn(); - pAdvisor->AI()->EnterEvadeMode(); - pAdvisor->GetMotionMaster()->MoveTargetedHome(); + advisor->Respawn(); + advisor->AI()->EnterEvadeMode(); + advisor->GetMotionMaster()->MoveTargetedHome(); } } - instance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + instance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); } void EventSharkkisDeath() @@ -215,7 +214,7 @@ public: void UpdateAI(uint32 diff) OVERRIDE { //Only if not incombat check if the event is started - if (!me->IsInCombat() && instance && instance->GetData(DATA_KARATHRESSEVENT)) + if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) { if (Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_KARATHRESSEVENT_STARTER))) { @@ -229,7 +228,7 @@ public: return; //someone evaded! - if (instance && !instance->GetData(DATA_KARATHRESSEVENT)) + if (!instance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; @@ -269,12 +268,11 @@ public: { BlessingOfTides = true; bool continueTriggering = false; - Creature* Advisor; for (uint8 i = 0; i < MAX_ADVISORS; ++i) if (Advisors[i]) { - Advisor = (Unit::GetCreature(*me, Advisors[i])); - if (Advisor && Advisor->IsAlive()) + Creature* advisor = ObjectAccessor::GetCreature(*me, Advisors[i]); + if (advisor && advisor->IsAlive()) { continueTriggering = true; break; @@ -333,11 +331,9 @@ public: pet = false; - Creature* Pet = Unit::GetCreature(*me, SummonedPet); + Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet); if (Pet && Pet->IsAlive()) - { Pet->DealDamage(Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } SummonedPet = 0; @@ -346,7 +342,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Karathress = (Unit::GetCreature((*me), instance->GetData64(DATA_KARATHRESS)))) + if (Creature* Karathress = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_KARATHRESS))) CAST_AI(boss_fathomlord_karathress::boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); } @@ -359,7 +355,7 @@ public: void UpdateAI(uint32 diff) OVERRIDE { //Only if not incombat check if the event is started - if (!me->IsInCombat() && instance && instance->GetData(DATA_KARATHRESSEVENT)) + if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) { if (Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_KARATHRESSEVENT_STARTER))) AttackStart(target); @@ -370,7 +366,7 @@ public: return; //someone evaded! - if (instance && !instance->GetData(DATA_KARATHRESSEVENT)) + if (!instance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; @@ -394,11 +390,11 @@ public: if (TheBeastWithin_Timer <= diff) { DoCast(me, SPELL_THE_BEAST_WITHIN); - Creature* Pet = Unit::GetCreature(*me, SummonedPet); + + Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet); if (Pet && Pet->IsAlive()) - { Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); - } + TheBeastWithin_Timer = 30000; } else TheBeastWithin_Timer -= diff; @@ -472,7 +468,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Karathress = Unit::GetCreature((*me), instance->GetData64(DATA_KARATHRESS))) + if (Creature* Karathress = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_KARATHRESS))) CAST_AI(boss_fathomlord_karathress::boss_fathomlord_karathressAI, Karathress->AI())->EventTidalvessDeath(); } @@ -486,7 +482,7 @@ public: void UpdateAI(uint32 diff) OVERRIDE { //Only if not incombat check if the event is started - if (!me->IsInCombat() && instance && instance->GetData(DATA_KARATHRESSEVENT)) + if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) { if (Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_KARATHRESSEVENT_STARTER))) AttackStart(target); @@ -497,7 +493,7 @@ public: return; //someone evaded! - if (instance && !instance->GetData(DATA_KARATHRESSEVENT)) + if (!instance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; @@ -588,7 +584,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Karathress = Unit::GetCreature((*me), instance->GetData64(DATA_KARATHRESS))) + if (Creature* Karathress = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_KARATHRESS))) CAST_AI(boss_fathomlord_karathress::boss_fathomlord_karathressAI, Karathress->AI())->EventCaribdisDeath(); } @@ -601,7 +597,7 @@ public: void UpdateAI(uint32 diff) OVERRIDE { //Only if not incombat check if the event is started - if (!me->IsInCombat() && instance && instance->GetData(DATA_KARATHRESSEVENT)) + if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) { if (Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_KARATHRESSEVENT_STARTER))) AttackStart(target); @@ -612,7 +608,7 @@ public: return; //someone evaded! - if (instance && !instance->GetData(DATA_KARATHRESSEVENT)) + if (!instance->GetData(DATA_KARATHRESSEVENT)) { EnterEvadeMode(); return; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp index b421d9c1153..8d6eb064194 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -519,7 +519,7 @@ public: if (CheckTimer <= diff) { // Start Phase 3 - if (instance && instance->GetData(DATA_CANSTARTPHASE3)) + if (instance->GetData(DATA_CANSTARTPHASE3)) { // set life 50% me->SetHealth(me->CountPctFromMaxHealth(50)); diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp index a45e4ddb0a9..f9370b44c20 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp @@ -317,10 +317,10 @@ public: // and reseting equipment me->LoadEquipment(); - if (instance && instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + if (instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) { Unit* victim = NULL; - victim = Unit::GetUnit(*me, instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); + victim = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); if (victim) me->getThreatManager().addThreat(victim, 1); StartEvent(); @@ -750,7 +750,7 @@ public: return; } - if (instance && !instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + if (!instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) { EnterEvadeMode(); return; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp index a6cd426f435..718c32cd8ae 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp @@ -112,10 +112,11 @@ public: bool CheckCanStart()//check if players fished { - if (instance && instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) + if (instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) return false; return true; } + void Reset() OVERRIDE { me->SetSwim(true); diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp index 42833fead04..3661ebc8cc3 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp @@ -224,11 +224,11 @@ public: { if (Repair_Timer <= diff) { - if (instance && instance->GetBossState(DATA_MEKGINEER_STEAMRIGGER) == IN_PROGRESS) + if (instance->GetBossState(DATA_MEKGINEER_STEAMRIGGER) == IN_PROGRESS) { - if (Unit* pMekgineer = Unit::GetUnit(*me, instance->GetData64(DATA_MEKGINEER_STEAMRIGGER))) + if (Creature* mekgineer = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MEKGINEER_STEAMRIGGER))) { - if (me->IsWithinDistInMap(pMekgineer, MAX_REPAIR_RANGE)) + if (me->IsWithinDistInMap(mekgineer, MAX_REPAIR_RANGE)) { //are we already channeling? Doesn't work very well, find better check? if (!me->GetUInt32Value(UNIT_CHANNEL_SPELL)) diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index d802e48f3b0..a961800025d 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -484,7 +484,7 @@ class npc_ember_of_alar : public CreatureScript me->setDeathState(JUST_DIED); } - void DamageTaken(Unit* killer, uint32 &damage) OVERRIDE + void DamageTaken(Unit* killer, uint32& damage) OVERRIDE { if (damage >= me->GetHealth() && killer != me && !toDie) { @@ -492,7 +492,7 @@ class npc_ember_of_alar : public CreatureScript DoCast(me, SPELL_EMBER_BLAST, true); me->SetDisplayId(11686); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (instance && instance->GetData(DATA_ALAREVENT) == 2) + if (instance->GetData(DATA_ALAREVENT) == 2) { if (Unit* Alar = Unit::GetUnit(*me, instance->GetData64(DATA_ALAR))) { diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index 75b1bfe8ad1..077539b6b88 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -182,7 +182,7 @@ struct advisorbase_ai : public ScriptedAI me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); //reset encounter - if (instance && (instance->GetData(DATA_KAELTHASEVENT) == 1 || instance->GetData(DATA_KAELTHASEVENT) == 3)) + if (instance->GetData(DATA_KAELTHASEVENT) == 1 || instance->GetData(DATA_KAELTHASEVENT) == 3) if (Creature* Kaelthas = Unit::GetCreature(*me, instance->GetData64(DATA_KAELTHAS))) Kaelthas->AI()->EnterEvadeMode(); } @@ -223,14 +223,14 @@ struct advisorbase_ai : public ScriptedAI return; //Prevent glitch if in fake death - if (FakeDeath && instance && instance->GetData(DATA_KAELTHASEVENT) != 0) + if (FakeDeath && instance->GetData(DATA_KAELTHASEVENT) != 0) { damage = 0; return; } //Don't really die in phase 1 & 3, only die after that - if (instance && instance->GetData(DATA_KAELTHASEVENT) != 0) + if (instance->GetData(DATA_KAELTHASEVENT) != 0) { //prevent death damage = 0; @@ -417,7 +417,7 @@ class boss_kaelthas : public CreatureScript } else if (me->GetMap()->IsDungeon()) { - if (instance && !instance->GetData(DATA_KAELTHASEVENT) && !Phase) + if (!instance->GetData(DATA_KAELTHASEVENT) && !Phase) StartEvent(); who->SetInCombatWith(me); @@ -429,7 +429,7 @@ class boss_kaelthas : public CreatureScript void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance && !instance->GetData(DATA_KAELTHASEVENT) && !Phase) + if (!instance->GetData(DATA_KAELTHASEVENT) && !Phase) StartEvent(); } @@ -1046,7 +1046,7 @@ class boss_thaladred_the_darkener : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (instance && instance->GetData(DATA_KAELTHASEVENT) == 3) + if (instance->GetData(DATA_KAELTHASEVENT) == 3) Talk(SAY_THALADRED_DEATH); } @@ -1138,7 +1138,7 @@ class boss_lord_sanguinar : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (instance && instance->GetData(DATA_KAELTHASEVENT) == 3) + if (instance->GetData(DATA_KAELTHASEVENT) == 3) Talk(SAY_SANGUINAR_DEATH); } @@ -1203,7 +1203,7 @@ class boss_grand_astromancer_capernian : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (instance && instance->GetData(DATA_KAELTHASEVENT) == 3) + if (instance->GetData(DATA_KAELTHASEVENT) == 3) Talk(SAY_CAPERNIAN_DEATH); } @@ -1342,7 +1342,7 @@ class boss_master_engineer_telonicus : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (instance && instance->GetData(DATA_KAELTHASEVENT) == 3) + if (instance->GetData(DATA_KAELTHASEVENT) == 3) Talk(SAY_TELONICUS_DEATH); } diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp index a1917d6201c..1a972f65360 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp @@ -77,7 +77,7 @@ class boss_void_reaver : public CreatureScript Enraged = false; - if (instance && me->IsAlive()) + if (me->IsAlive()) instance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); } diff --git a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp index cc58be26664..3f1579c42b1 100644 --- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp +++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp @@ -113,7 +113,10 @@ public: struct npc_bloodmaul_bruteAI : public ScriptedAI { - npc_bloodmaul_bruteAI(Creature* creature) : ScriptedAI(creature) { } + npc_bloodmaul_bruteAI(Creature* creature) : ScriptedAI(creature) + { + hp30 = false; + } void Reset() OVERRIDE { @@ -1128,6 +1131,7 @@ public: npc_oscillating_frequency_scanner_master_bunnyAI(Creature* creature) : ScriptedAI(creature) { playerGuid = 0; + timer = 500; } void Reset() OVERRIDE diff --git a/src/server/scripts/Outland/zone_nagrand.cpp b/src/server/scripts/Outland/zone_nagrand.cpp index 8d5c81d1c01..9b7a3f8aa2a 100644 --- a/src/server/scripts/Outland/zone_nagrand.cpp +++ b/src/server/scripts/Outland/zone_nagrand.cpp @@ -182,13 +182,11 @@ public: { if (quest->GetQuestId() == QUEST_TOTEM_KARDASH_H) { - if (npc_maghar_captiveAI* pEscortAI = dynamic_cast<npc_maghar_captiveAI*>(creature->AI())) + if (npc_maghar_captiveAI* EscortAI = dynamic_cast<npc_maghar_captiveAI*>(creature->AI())) { creature->SetStandState(UNIT_STAND_STATE_STAND); creature->setFaction(232); - - pEscortAI->Start(true, false, player->GetGUID(), quest); - + EscortAI->Start(true, false, player->GetGUID(), quest); creature->AI()->Talk(SAY_MAG_START); creature->SummonCreature(NPC_MURK_RAIDER, m_afAmbushA[0]+2.5f, m_afAmbushA[1]-2.5f, m_afAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); @@ -208,15 +206,15 @@ public: { npc_maghar_captiveAI(Creature* creature) : npc_escortAI(creature) { Reset(); } - uint32 m_uiChainLightningTimer; - uint32 m_uiHealTimer; - uint32 m_uiFrostShockTimer; + uint32 ChainLightningTimer; + uint32 HealTimer; + uint32 FrostShockTimer; void Reset() OVERRIDE { - m_uiChainLightningTimer = 1000; - m_uiHealTimer = 0; - m_uiFrostShockTimer = 6000; + ChainLightningTimer = 1000; + HealTimer = 0; + FrostShockTimer = 6000; } void EnterCombat(Unit* /*who*/) OVERRIDE @@ -224,6 +222,18 @@ public: DoCast(me, SPELL_EARTHBIND_TOTEM, false); } + void JustDied(Unit* /*killer*/) OVERRIDE + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + if (Player* player = GetPlayerForEscort()) + { + if (player->GetQuestStatus(QUEST_TOTEM_KARDASH_H) != QUEST_STATUS_COMPLETE) + player->FailQuest(QUEST_TOTEM_KARDASH_H); + } + } + void WaypointReached(uint32 waypointId) OVERRIDE { switch (waypointId) @@ -263,9 +273,9 @@ public: } - void SpellHitTarget(Unit* /*target*/, const SpellInfo* pSpell) OVERRIDE + void SpellHitTarget(Unit* /*target*/, const SpellInfo* spell) OVERRIDE { - if (pSpell->Id == SPELL_CHAIN_LIGHTNING) + if (spell->Id == SPELL_CHAIN_LIGHTNING) { if (rand()%10) return; @@ -274,38 +284,42 @@ public: } } - void UpdateAI(uint32 uiDiff) OVERRIDE + void UpdateAI(uint32 diff) OVERRIDE { - npc_escortAI::UpdateAI(uiDiff); - if (!me->GetVictim()) + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + + if (me->HasUnitState(UNIT_STATE_CASTING)) return; - if (m_uiChainLightningTimer <= uiDiff) + if (ChainLightningTimer <= diff) { DoCastVictim(SPELL_CHAIN_LIGHTNING); - m_uiChainLightningTimer = urand(7000, 14000); + ChainLightningTimer = urand(7000, 14000); } else - m_uiChainLightningTimer -= uiDiff; + ChainLightningTimer -= diff; if (HealthBelowPct(30)) { - if (m_uiHealTimer <= uiDiff) + if (HealTimer <= diff) { DoCast(me, SPELL_HEALING_WAVE); - m_uiHealTimer = 5000; + HealTimer = 5000; } else - m_uiHealTimer -= uiDiff; + HealTimer -= diff; } - if (m_uiFrostShockTimer <= uiDiff) + if (FrostShockTimer <= diff) { DoCastVictim(SPELL_FROST_SHOCK); - m_uiFrostShockTimer = urand(7500, 15000); + FrostShockTimer = urand(7500, 15000); } else - m_uiFrostShockTimer -= uiDiff; + FrostShockTimer -= diff; DoMeleeAttackIfReady(); } @@ -517,6 +531,7 @@ public: if (npc_kurenai_captiveAI* EscortAI = dynamic_cast<npc_kurenai_captiveAI*>(creature->AI())) { creature->SetStandState(UNIT_STAND_STATE_STAND); + creature->setFaction(231); EscortAI->Start(true, false, player->GetGUID(), quest); creature->AI()->Talk(SAY_KUR_START); @@ -629,6 +644,8 @@ public: void UpdateAI(uint32 diff) OVERRIDE { + npc_escortAI::UpdateAI(diff); + if (!UpdateVictim()) return; diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index e1ef9ea6862..e8108f03e7d 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -25,6 +25,7 @@ #include "ScriptMgr.h" #include "SpellScript.h" #include "SpellAuraEffects.h" +#include "Containers.h" enum DeathKnightSpells { @@ -49,6 +50,8 @@ enum DeathKnightSpells SPELL_DK_IMPROVED_UNHOLY_PRESENCE_TRIGGERED = 63622, SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART = 64962, SPELL_DK_ITEM_T8_MELEE_4P_BONUS = 64736, + SPELL_DK_MASTER_OF_GHOULS = 52143, + SPELL_DK_RAISE_DEAD_USE_REAGENT = 48289, SPELL_DK_RUNIC_POWER_ENERGIZE = 49088, SPELL_DK_SCENT_OF_BLOOD = 50422, SPELL_DK_SCOURGE_STRIKE_TRIGGERED = 70890, @@ -63,6 +66,11 @@ enum DeathKnightSpellIcons DK_ICON_ID_IMPROVED_DEATH_STRIKE = 2751 }; +enum Misc +{ + NPC_DK_GHOUL = 26125 +}; + // 50462 - Anti-Magic Shell (on raid member) class spell_dk_anti_magic_shell_raid : public SpellScriptLoader { @@ -140,13 +148,12 @@ class spell_dk_anti_magic_shell_self : public SpellScriptLoader absorbAmount = std::min(CalculatePct(dmgInfo.GetDamage(), absorbPct), GetTarget()->CountPctFromMaxHealth(hpPct)); } - void Trigger(AuraEffect* aurEff, DamageInfo & /*dmgInfo*/, uint32 & absorbAmount) + void Trigger(AuraEffect* aurEff, DamageInfo& /*dmgInfo*/, uint32& absorbAmount) { - Unit* target = GetTarget(); // damage absorbed by Anti-Magic Shell energizes the DK with additional runic power. // This, if I'm not mistaken, shows that we get back ~20% of the absorbed damage as runic power. - int32 bp = absorbAmount * 2 / 10; - target->CastCustomSpell(target, SPELL_DK_RUNIC_POWER_ENERGIZE, &bp, NULL, NULL, true, NULL, aurEff); + int32 bp = CalculatePct(absorbAmount, 20); + GetTarget()->CastCustomSpell(SPELL_DK_RUNIC_POWER_ENERGIZE, SPELLVALUE_BASE_POINT0, bp, GetTarget(), true, NULL, aurEff); } void Register() OVERRIDE @@ -312,6 +319,28 @@ class spell_dk_blood_gorged : public SpellScriptLoader } }; +class CorpseExplosionCheck +{ +public: + explicit CorpseExplosionCheck(uint64 casterGUID) : _casterGUID(casterGUID) { } + + bool operator()(WorldObject* obj) const + { + if (Unit* target = obj->ToUnit()) + { + if ((target->isDead() || (target->GetEntry() == NPC_DK_GHOUL && target->GetOwnerGUID() == _casterGUID)) + && !(target->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) + && target->GetDisplayId() == target->GetNativeDisplayId()) + return false; + } + + return true; + } + +private: + uint64 _casterGUID; +}; + // 49158 - Corpse Explosion (51325, 51326, 51327, 51328) class spell_dk_corpse_explosion : public SpellScriptLoader { @@ -322,41 +351,87 @@ class spell_dk_corpse_explosion : public SpellScriptLoader { PrepareSpellScript(spell_dk_corpse_explosion_SpellScript); - bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + bool Validate(SpellInfo const* spellInfo) OVERRIDE { - if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED) || !sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_EXPLODE)) - return false; - if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_VISUAL)) + if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED) + || !sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_EXPLODE) + || !sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_VISUAL) + || !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_1].CalcValue())) return false; return true; } - void HandleDummy(SpellEffIndex /*effIndex*/) + bool Load() OVERRIDE + { + _target = NULL; + return true; + } + + void CheckTarget(WorldObject*& target) + { + if (CorpseExplosionCheck(GetCaster()->GetGUID())(target)) + target = NULL; + + _target = target; + } + + void CheckTargets(std::list<WorldObject*>& targets) + { + WorldObject* target = _target; + if (!target) + { + targets.remove_if(CorpseExplosionCheck(GetCaster()->GetGUID())); + if (targets.empty()) + { + FinishCast(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW); + return; + } + target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } + else + targets.clear(); + } + + void HandleDamage(SpellEffIndex effIndex, Unit* target) + { + if (effIndex == EFFECT_0) + GetCaster()->CastCustomSpell(GetSpellInfo()->Effects[EFFECT_1].CalcValue(), SPELLVALUE_BASE_POINT0, GetEffectValue(), target, true); + else if (effIndex == EFFECT_1) + GetCaster()->CastCustomSpell(GetEffectValue(), SPELLVALUE_BASE_POINT0, GetSpell()->CalculateDamage(EFFECT_0, NULL), target, true); + } + + void HandleCorpseExplosion(SpellEffIndex effIndex) { if (Unit* unitTarget = GetHitUnit()) { - int32 bp = 0; if (unitTarget->IsAlive()) // Living ghoul as a target { - bp = int32(unitTarget->CountPctFromMaxHealth(25)); - unitTarget->CastCustomSpell(unitTarget, SPELL_DK_GHOUL_EXPLODE, &bp, NULL, NULL, false); + unitTarget->CastSpell(unitTarget, SPELL_DK_GHOUL_EXPLODE, false); + // Corpse Explosion (Suicide) and Set corpse look handled in SpellScript of SPELL_DK_GHOUL_EXPLODE } else // Some corpse { - bp = GetEffectValue(); - GetCaster()->CastCustomSpell(unitTarget, GetSpellInfo()->Effects[EFFECT_1].CalcValue(), &bp, NULL, NULL, true); + HandleDamage(effIndex, unitTarget); // Corpse Explosion (Suicide) unitTarget->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED, true); + // Set corpse look + GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true); } - // Set corpse look - GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true); } } void Register() OVERRIDE { - OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_dk_corpse_explosion_SpellScript::CheckTarget, EFFECT_0, TARGET_UNIT_TARGET_ANY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_corpse_explosion_SpellScript::CheckTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleCorpseExplosion, EFFECT_0, SPELL_EFFECT_DUMMY); + OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleCorpseExplosion, EFFECT_1, SPELL_EFFECT_DUMMY); } + + private: + WorldObject* _target; }; SpellScript* GetSpellScript() const OVERRIDE @@ -617,24 +692,34 @@ class spell_dk_ghoul_explode : public SpellScriptLoader { PrepareSpellScript(spell_dk_ghoul_explode_SpellScript); - bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + bool Validate(SpellInfo const* spellInfo) OVERRIDE { - if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED)) + if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED) + || spellInfo->Effects[EFFECT_2].CalcValue() <= 0) return false; return true; } + void HandleDamage(SpellEffIndex /*effIndex*/) + { + int32 value = int32(GetCaster()->CountPctFromMaxHealth(GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster()))); + SetEffectValue(value); + } + void Suicide(SpellEffIndex /*effIndex*/) { if (Unit* unitTarget = GetHitUnit()) { // Corpse Explosion (Suicide) unitTarget->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED, true); + // Set corpse look + GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true); } } void Register() OVERRIDE { + OnEffectLaunchTarget += SpellEffectFn(spell_dk_ghoul_explode_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); OnEffectHitTarget += SpellEffectFn(spell_dk_ghoul_explode_SpellScript::Suicide, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE); } }; @@ -941,6 +1026,162 @@ class spell_dk_presence : public SpellScriptLoader } }; +class RaiseDeadCheck +{ + public: + explicit RaiseDeadCheck(Player const* caster) : _caster(caster) { } + + bool operator()(WorldObject* obj) const + { + if (Unit* target = obj->ToUnit()) + { + if (!target->IsAlive() + && _caster->isHonorOrXPTarget(target) + && target->GetCreatureType() == CREATURE_TYPE_HUMANOID + && target->GetDisplayId() == target->GetNativeDisplayId()) + return false; + } + + return true; + } + + private: + Player const* _caster; +}; + +// 46584 - Raise Dead +class spell_dk_raise_dead : public SpellScriptLoader +{ + public: + spell_dk_raise_dead() : SpellScriptLoader("spell_dk_raise_dead") { } + + class spell_dk_raise_dead_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dk_raise_dead_SpellScript); + + bool Validate(SpellInfo const* spellInfo) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_1].CalcValue()) + || !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_2].CalcValue()) + || !sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_DEAD_USE_REAGENT) + || !sSpellMgr->GetSpellInfo(SPELL_DK_MASTER_OF_GHOULS)) + return false; + return true; + } + + bool Load() OVERRIDE + { + _result = SPELL_CAST_OK; + _corpse = false; + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + SpellCastResult CheckCast() + { + /// process spell target selection before cast starts + /// targets of effect_1 are used to check cast + GetSpell()->SelectSpellTargets(); + /// cleanup spell target map, and fill it again on normal way + GetSpell()->CleanupTargetList(); + /// _result is set in spell target selection + return _result; + } + + SpellCastResult CheckReagents() + { + /// @workaround: there is no access to castresult of other spells, check it manually + SpellInfo const* reagentSpell = sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_DEAD_USE_REAGENT); + Player* player = GetCaster()->ToPlayer(); + if (!player->CanNoReagentCast(reagentSpell)) + { + for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++) + { + if (reagentSpell->Reagent[i] <= 0) + continue; + + if (!player->HasItemCount(reagentSpell->Reagent[i], reagentSpell->ReagentCount[i])) + { + Spell::SendCastResult(player, reagentSpell, 0, SPELL_FAILED_REAGENTS); + return SPELL_FAILED_DONT_REPORT; + } + } + } + return SPELL_CAST_OK; + } + + void CheckTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(RaiseDeadCheck(GetCaster()->ToPlayer())); + + if (targets.empty()) + { + if (GetSpell()->getState() == SPELL_STATE_PREPARING) + _result = CheckReagents(); + + return; + } + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + _corpse = true; + } + + void CheckTarget(WorldObject*& target) + { + // Don't add caster to target map, if we found a corpse to raise dead + if (_corpse) + target = NULL; + } + + void ConsumeReagents() + { + // No corpse found, take reagents + if (!_corpse) + GetCaster()->CastSpell(GetCaster(), SPELL_DK_RAISE_DEAD_USE_REAGENT, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); + } + + uint32 GetGhoulSpellId() + { + // Do we have talent Master of Ghouls? + if (GetCaster()->HasAura(SPELL_DK_MASTER_OF_GHOULS)) + // summon as pet + return GetSpellInfo()->Effects[EFFECT_2].CalcValue(); + + // or guardian + return GetSpellInfo()->Effects[EFFECT_1].CalcValue(); + } + + void HandleRaiseDead(SpellEffIndex /*effIndex*/) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(GetGhoulSpellId()); + SpellCastTargets targets; + targets.SetDst(*GetHitUnit()); + + GetCaster()->CastSpell(targets, spellInfo, NULL, TRIGGERED_FULL_MASK); + } + + void Register() OVERRIDE + { + OnCheckCast += SpellCheckCastFn(spell_dk_raise_dead_SpellScript::CheckCast); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_raise_dead_SpellScript::CheckTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_dk_raise_dead_SpellScript::CheckTarget, EFFECT_2, TARGET_UNIT_CASTER); + OnCast += SpellCastFn(spell_dk_raise_dead_SpellScript::ConsumeReagents); + OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_2, SPELL_EFFECT_DUMMY); + } + + private: + SpellCastResult _result; + bool _corpse; + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_dk_raise_dead_SpellScript(); + } +}; + // 59754 Rune Tap - Party class spell_dk_rune_tap_party : public SpellScriptLoader { @@ -1225,6 +1466,7 @@ void AddSC_deathknight_spell_scripts() new spell_dk_improved_frost_presence(); new spell_dk_improved_unholy_presence(); new spell_dk_presence(); + new spell_dk_raise_dead(); new spell_dk_rune_tap_party(); new spell_dk_scent_of_blood(); new spell_dk_scourge_strike(); diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 9fd43807fd5..5e56d4b8d92 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -993,6 +993,76 @@ class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader } }; +class RaidCheck +{ + public: + explicit RaidCheck(Unit const* caster) : _caster(caster) { } + + bool operator()(WorldObject* obj) const + { + if (Unit* target = obj->ToUnit()) + return !_caster->IsInRaidWith(target); + + return true; + } + + private: + Unit const* _caster; +}; + +// -48438 - Wild Growth +class spell_dru_wild_growth : public SpellScriptLoader +{ + public: + spell_dru_wild_growth() : SpellScriptLoader("spell_dru_wild_growth") { } + + class spell_dru_wild_growth_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dru_wild_growth_SpellScript); + + bool Validate(SpellInfo const* spellInfo) OVERRIDE + { + if (spellInfo->Effects[EFFECT_2].IsEffect() || spellInfo->Effects[EFFECT_2].CalcValue() <= 0) + return false; + return true; + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(RaidCheck(GetCaster())); + + uint32 const maxTargets = uint32(GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster())); + + if (targets.size() > maxTargets) + { + targets.sort(Trinity::HealthPctOrderPred()); + targets.resize(maxTargets); + } + + _targets = targets; + } + + void SetTargets(std::list<WorldObject*>& targets) + { + targets = _targets; + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dru_wild_growth_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dru_wild_growth_SpellScript::SetTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ALLY); + } + + private: + std::list<WorldObject*> _targets; + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_dru_wild_growth_SpellScript(); + } +}; + void AddSC_druid_spell_scripts() { new spell_dru_dash(); @@ -1018,4 +1088,5 @@ void AddSC_druid_spell_scripts() new spell_dru_tiger_s_fury(); new spell_dru_typhoon(); new spell_dru_t10_restoration_4p_bonus(); + new spell_dru_wild_growth(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 3feb9821177..1e9a8713019 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -2963,22 +2963,65 @@ enum Replenishment SPELL_INFINITE_REPLENISHMENT = 61782 }; +class ReplenishmentCheck +{ +public: + bool operator()(WorldObject* obj) const + { + if (Unit* target = obj->ToUnit()) + return target->getPowerType() != POWER_MANA; + + return true; + } +}; + class spell_gen_replenishment : public SpellScriptLoader { public: spell_gen_replenishment() : SpellScriptLoader("spell_gen_replenishment") { } - class spell_gen_replenishment_AuraScript : public AuraScript + class spell_gen_replenishment_SpellScript : public SpellScript { - PrepareAuraScript(spell_gen_replenishment_AuraScript); + PrepareSpellScript(spell_gen_replenishment_SpellScript); - bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + void RemoveInvalidTargets(std::list<WorldObject*>& targets) { - if (!sSpellMgr->GetSpellInfo(SPELL_REPLENISHMENT) || - !sSpellMgr->GetSpellInfo(SPELL_INFINITE_REPLENISHMENT)) - return false; - return true; + // In arenas Replenishment may only affect the caster + if (Player* caster = GetCaster()->ToPlayer()) + { + if (caster->InArena()) + { + targets.clear(); + targets.push_back(caster); + return; + } + } + + targets.remove_if(ReplenishmentCheck()); + + uint8 const maxTargets = 10; + + if (targets.size() > maxTargets) + { + targets.sort(Trinity::PowerPctOrderPred(POWER_MANA)); + targets.resize(maxTargets); + } + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gen_replenishment_SpellScript::RemoveInvalidTargets, EFFECT_ALL, TARGET_UNIT_CASTER_AREA_RAID); } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_gen_replenishment_SpellScript(); + } + + class spell_gen_replenishment_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_replenishment_AuraScript); bool Load() OVERRIDE { diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp index bb84606dece..07d95aa63f5 100644 --- a/src/server/scripts/Spells/spell_holiday.cpp +++ b/src/server/scripts/Spells/spell_holiday.cpp @@ -277,6 +277,62 @@ class spell_hallow_end_tricky_treat : public SpellScriptLoader } }; +enum PilgrimsBountyBuffFood +{ + // Pilgrims Bounty Buff Food + SPELL_WELL_FED_AP_TRIGGER = 65414, + SPELL_WELL_FED_ZM_TRIGGER = 65412, + SPELL_WELL_FED_HIT_TRIGGER = 65416, + SPELL_WELL_FED_HASTE_TRIGGER = 65410, + SPELL_WELL_FED_SPIRIT_TRIGGER = 65415 +}; + +class spell_pilgrims_bounty_buff_food : public SpellScriptLoader +{ + private: + uint32 const _triggeredSpellId; + public: + spell_pilgrims_bounty_buff_food(const char* name, uint32 triggeredSpellId) : SpellScriptLoader(name), _triggeredSpellId(triggeredSpellId) { } + + class spell_pilgrims_bounty_buff_food_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pilgrims_bounty_buff_food_AuraScript) + private: + uint32 const _triggeredSpellId; + + public: + spell_pilgrims_bounty_buff_food_AuraScript(uint32 triggeredSpellId) : AuraScript(), _triggeredSpellId(triggeredSpellId) { } + + bool Load() OVERRIDE + { + _handled = false; + return true; + } + + void HandleTriggerSpell(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + if (_handled) + return; + + _handled = true; + GetTarget()->CastSpell(GetTarget(), _triggeredSpellId, true); + } + + void Register() OVERRIDE + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_pilgrims_bounty_buff_food_AuraScript::HandleTriggerSpell, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + + bool _handled; + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_pilgrims_bounty_buff_food_AuraScript(_triggeredSpellId); + } +}; + enum Mistletoe { SPELL_CREATE_MISTLETOE = 26206, @@ -396,6 +452,12 @@ void AddSC_holiday_spell_scripts() new spell_hallow_end_trick(); new spell_hallow_end_trick_or_treat(); new spell_hallow_end_tricky_treat(); + // Pilgrims Bounty + new spell_pilgrims_bounty_buff_food("spell_gen_slow_roasted_turkey", SPELL_WELL_FED_AP_TRIGGER); + new spell_pilgrims_bounty_buff_food("spell_gen_cranberry_chutney", SPELL_WELL_FED_ZM_TRIGGER); + new spell_pilgrims_bounty_buff_food("spell_gen_spice_bread_stuffing", SPELL_WELL_FED_HIT_TRIGGER); + new spell_pilgrims_bounty_buff_food("spell_gen_pumpkin_pie", SPELL_WELL_FED_SPIRIT_TRIGGER); + new spell_pilgrims_bounty_buff_food("spell_gen_candied_sweet_potato", SPELL_WELL_FED_HASTE_TRIGGER); // Winter Veil new spell_winter_veil_mistletoe(); new spell_winter_veil_px_238_winter_wondervolt(); diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 8b3716f8f7d..837023f3bdd 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -349,6 +349,40 @@ class spell_item_deviate_fish : public SpellScriptLoader } }; +// 71610, 71641 - Echoes of Light (Althor's Abacus) +class spell_item_echoes_of_light : public SpellScriptLoader +{ + public: + spell_item_echoes_of_light() : SpellScriptLoader("spell_item_echoes_of_light") { } + + class spell_item_echoes_of_light_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_echoes_of_light_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + if (targets.size() < 2) + return; + + targets.sort(Trinity::HealthPctOrderPred()); + + WorldObject* target = targets.front(); + targets.clear(); + targets.push_back(target); + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_item_echoes_of_light_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_item_echoes_of_light_SpellScript(); + } +}; + // http://www.wowhead.com/item=47499 Flask of the North // 67019 Flask of the North enum FlaskOfTheNorthSpells @@ -2571,6 +2605,7 @@ void AddSC_item_spell_scripts() new spell_item_defibrillate("spell_item_gnomish_army_knife", 33); new spell_item_desperate_defense(); new spell_item_deviate_fish(); + new spell_item_echoes_of_light(); new spell_item_flask_of_the_north(); new spell_item_gnomish_death_ray(); new spell_item_make_a_wish(); diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 0b790f01d29..b5265561d85 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -57,6 +57,11 @@ enum PaladinSpells SPELL_PALADIN_ITEM_HEALING_TRANCE = 37706, + SPELL_PALADIN_JUDGEMENT_DAMAGE = 54158, + SPELL_PALADIN_JUDGEMENT_OF_JUSTICE = 20184, + SPELL_PALADIN_JUDGEMENT_OF_LIGHT = 20185, + SPELL_PALADIN_JUDGEMENT_OF_WISDOM = 20186, + SPELL_PALADIN_GLYPH_OF_SALVATION = 63225, SPELL_PALADIN_RIGHTEOUS_DEFENSE_TAUNT = 31790, @@ -361,7 +366,6 @@ class spell_pal_divine_sacrifice : public SpellScriptLoader bool Load() OVERRIDE { - if (Unit* caster = GetCaster()) { if (caster->GetTypeId() == TYPEID_PLAYER) @@ -564,6 +568,39 @@ class spell_pal_eye_for_an_eye : public SpellScriptLoader } }; +// 54968 - Glyph of Holy Light +class spell_pal_glyph_of_holy_light : public SpellScriptLoader +{ + public: + spell_pal_glyph_of_holy_light() : SpellScriptLoader("spell_pal_glyph_of_holy_light") { } + + class spell_pal_glyph_of_holy_light_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pal_glyph_of_holy_light_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + uint32 const maxTargets = GetSpellInfo()->MaxAffectedTargets; + + if (targets.size() > maxTargets) + { + targets.sort(Trinity::HealthPctOrderPred()); + targets.resize(maxTargets); + } + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pal_glyph_of_holy_light_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_pal_glyph_of_holy_light_SpellScript(); + } +}; + // 63521 - Guarded by The Light class spell_pal_guarded_by_the_light : public SpellScriptLoader { @@ -891,6 +928,67 @@ class spell_pal_item_healing_discount : public SpellScriptLoader } }; +// 53407 - Judgement of Justice +// 20271 - Judgement of Light +// 53408 - Judgement of Wisdom +class spell_pal_judgement : public SpellScriptLoader +{ + public: + spell_pal_judgement(char const* scriptName, uint32 spellId) : SpellScriptLoader(scriptName), _spellId(spellId) { } + + class spell_pal_judgement_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pal_judgement_SpellScript); + + public: + spell_pal_judgement_SpellScript(uint32 spellId) : SpellScript(), _spellId(spellId) { } + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_JUDGEMENT_DAMAGE) + || !sSpellMgr->GetSpellInfo(_spellId)) + return false; + return true; + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + uint32 spellId2 = SPELL_PALADIN_JUDGEMENT_DAMAGE; + + // some seals have SPELL_AURA_DUMMY in EFFECT_2 + Unit::AuraEffectList const& auras = GetCaster()->GetAuraEffectsByType(SPELL_AURA_DUMMY); + for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i) + { + if ((*i)->GetSpellInfo()->GetSpellSpecific() == SPELL_SPECIFIC_SEAL && (*i)->GetEffIndex() == EFFECT_2) + if (sSpellMgr->GetSpellInfo((*i)->GetAmount())) + { + spellId2 = (*i)->GetAmount(); + break; + } + } + + GetCaster()->CastSpell(GetHitUnit(), _spellId, true); + GetCaster()->CastSpell(GetHitUnit(), spellId2, true); + } + + void Register() OVERRIDE + { + OnEffectHitTarget += SpellEffectFn(spell_pal_judgement_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + + private: + uint32 const _spellId; + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_pal_judgement_SpellScript(_spellId); + } + + private: + uint32 const _spellId; +}; + // 20425 - Judgement of Command class spell_pal_judgement_of_command : public SpellScriptLoader { @@ -1142,6 +1240,7 @@ void AddSC_paladin_spell_scripts() new spell_pal_divine_storm_dummy(); new spell_pal_exorcism_and_holy_wrath_damage(); new spell_pal_eye_for_an_eye(); + new spell_pal_glyph_of_holy_light(); new spell_pal_guarded_by_the_light(); new spell_pal_hand_of_sacrifice(); new spell_pal_hand_of_salvation(); @@ -1154,6 +1253,9 @@ void AddSC_paladin_spell_scripts() new spell_pal_improved_aura_effect("spell_pal_improved_devotion_aura_effect"); new spell_pal_improved_aura_effect("spell_pal_sanctified_retribution_effect"); new spell_pal_item_healing_discount(); + new spell_pal_judgement("spell_pal_judgement_of_justice", SPELL_PALADIN_JUDGEMENT_OF_JUSTICE); + new spell_pal_judgement("spell_pal_judgement_of_light", SPELL_PALADIN_JUDGEMENT_OF_LIGHT); + new spell_pal_judgement("spell_pal_judgement_of_wisdom", SPELL_PALADIN_JUDGEMENT_OF_WISDOM); new spell_pal_judgement_of_command(); new spell_pal_lay_on_hands(); new spell_pal_righteous_defense(); diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp index 3d6853daf2c..a7742630ccd 100644 --- a/src/server/scripts/Spells/spell_pet.cpp +++ b/src/server/scripts/Spells/spell_pet.cpp @@ -1498,9 +1498,8 @@ public: // 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; diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 4a702c7559c..71e5dac28ec 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -31,6 +31,7 @@ enum PriestSpells { SPELL_PRIEST_DIVINE_AEGIS = 47753, SPELL_PRIEST_EMPOWERED_RENEW = 63544, + SPELL_PRIEST_GLYPH_OF_CIRCLE_OF_HEALING = 55675, SPELL_PRIEST_GLYPH_OF_LIGHTWELL = 55673, SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL = 56161, SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153, @@ -53,6 +54,82 @@ enum PriestSpellIcons PRIEST_ICON_ID_PAIN_AND_SUFFERING = 2874, }; +class PowerCheck +{ + public: + explicit PowerCheck(Powers const power) : _power(power) { } + + bool operator()(WorldObject* obj) const + { + if (Unit* target = obj->ToUnit()) + return target->getPowerType() != _power; + + return true; + } + + private: + Powers const _power; +}; + +class RaidCheck +{ + public: + explicit RaidCheck(Unit const* caster) : _caster(caster) { } + + bool operator()(WorldObject* obj) const + { + if (Unit* target = obj->ToUnit()) + return !_caster->IsInRaidWith(target); + + return true; + } + + private: + Unit const* _caster; +}; + +// -34861 - Circle of Healing +class spell_pri_circle_of_healing : public SpellScriptLoader +{ + public: + spell_pri_circle_of_healing() : SpellScriptLoader("spell_pri_circle_of_healing") { } + + class spell_pri_circle_of_healing_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pri_circle_of_healing_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPH_OF_CIRCLE_OF_HEALING)) + return false; + return true; + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(RaidCheck(GetCaster())); + + uint32 const maxTargets = GetCaster()->HasAura(SPELL_PRIEST_GLYPH_OF_CIRCLE_OF_HEALING) ? 6 : 5; // Glyph of Circle of Healing + + if (targets.size() > maxTargets) + { + targets.sort(Trinity::HealthPctOrderPred()); + targets.resize(maxTargets); + } + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_circle_of_healing_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_pri_circle_of_healing_SpellScript(); + } +}; + // -47509 - Divine Aegis class spell_pri_divine_aegis : public SpellScriptLoader { @@ -103,6 +180,41 @@ class spell_pri_divine_aegis : public SpellScriptLoader } }; +// 64844 - Divine Hymn +class spell_pri_divine_hymn : public SpellScriptLoader +{ + public: + spell_pri_divine_hymn() : SpellScriptLoader("spell_pri_divine_hymn") { } + + class spell_pri_divine_hymn_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pri_divine_hymn_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(RaidCheck(GetCaster())); + + uint32 const maxTargets = 3; + + if (targets.size() > maxTargets) + { + targets.sort(Trinity::HealthPctOrderPred()); + targets.resize(maxTargets); + } + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_divine_hymn_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_pri_divine_hymn_SpellScript(); + } +}; + // 55680 - Glyph of Prayer of Healing class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader { @@ -198,6 +310,42 @@ class spell_pri_guardian_spirit : public SpellScriptLoader } }; +// 64904 - Hymn of Hope +class spell_pri_hymn_of_hope : public SpellScriptLoader +{ + public: + spell_pri_hymn_of_hope() : SpellScriptLoader("spell_pri_hymn_of_hope") { } + + class spell_pri_hymn_of_hope_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pri_hymn_of_hope_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(PowerCheck(POWER_MANA)); + targets.remove_if(RaidCheck(GetCaster())); + + uint32 const maxTargets = 3; + + if (targets.size() > maxTargets) + { + targets.sort(Trinity::PowerPctOrderPred(POWER_MANA)); + targets.resize(maxTargets); + } + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_hymn_of_hope_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_pri_hymn_of_hope_SpellScript(); + } +}; + // 37594 - Greater Heal Refund class spell_pri_item_greater_heal_refund : public SpellScriptLoader { @@ -703,9 +851,12 @@ class spell_pri_vampiric_touch : public SpellScriptLoader void AddSC_priest_spell_scripts() { + new spell_pri_circle_of_healing(); new spell_pri_divine_aegis(); + new spell_pri_divine_hymn(); new spell_pri_glyph_of_prayer_of_healing(); new spell_pri_guardian_spirit(); + new spell_pri_hymn_of_hope(); new spell_pri_item_greater_heal_refund(); new spell_pri_lightwell_renew(); new spell_pri_mana_burn(); diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 419a289aed4..cdf32bd94d5 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -1606,6 +1606,7 @@ class spell_q12527_zuldrak_rat : public SpellScriptLoader } }; +// 55368 - Summon Stefan class spell_q12661_q12669_q12676_q12677_q12713_summon_stefan : public SpellScriptLoader { public: @@ -1615,19 +1616,16 @@ class spell_q12661_q12669_q12676_q12677_q12713_summon_stefan : public SpellScrip { PrepareSpellScript(spell_q12661_q12669_q12676_q12677_q12713_summon_stefan_SpellScript); - void ChangeSummonPos(SpellEffIndex /*effIndex*/) + void SetDest(SpellDestination& dest) { // Adjust effect summon position - WorldLocation summonPos = *GetExplTargetDest(); - Position offset = { 0.0f, 0.0f, 20.0f, 0.0f }; - summonPos.RelocateOffset(offset); - SetExplTargetDest(summonPos); - GetHitDest()->RelocateOffset(offset); + Position const offset = { 0.0f, 0.0f, 20.0f, 0.0f }; + dest.RelocateOffset(offset); } void Register() OVERRIDE { - OnEffectHit += SpellEffectFn(spell_q12661_q12669_q12676_q12677_q12713_summon_stefan_SpellScript::ChangeSummonPos, EFFECT_0, SPELL_EFFECT_SUMMON); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_q12661_q12669_q12676_q12677_q12713_summon_stefan_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER_BACK); } }; @@ -1723,6 +1721,7 @@ class spell_q13291_q13292_q13239_q13261_frostbrood_skytalon_grab_decoy : public } }; +// 59303 - Summon Frost Wyrm class spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon : public SpellScriptLoader { public: @@ -1732,19 +1731,16 @@ class spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon : public S { PrepareSpellScript(spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon_SpellScript); - void ChangeSummonPos(SpellEffIndex /*effIndex*/) + void SetDest(SpellDestination& dest) { // Adjust effect summon position - WorldLocation summonPos = *GetExplTargetDest(); - Position offset = { 0.0f, 0.0f, 20.0f, 0.0f }; - summonPos.RelocateOffset(offset); - SetExplTargetDest(summonPos); - GetHitDest()->RelocateOffset(offset); + Position const offset = { 0.0f, 0.0f, 20.0f, 0.0f }; + dest.RelocateOffset(offset); } void Register() OVERRIDE { - OnEffectHit += SpellEffectFn(spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon_SpellScript::ChangeSummonPos, EFFECT_0, SPELL_EFFECT_SUMMON); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER_BACK); } }; @@ -1754,6 +1750,7 @@ class spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon : public S } }; +// 12601 - Second Chances: Summon Landgren's Soul Moveto Target Bunny class spell_q12847_summon_soul_moveto_bunny : public SpellScriptLoader { public: @@ -1763,19 +1760,16 @@ class spell_q12847_summon_soul_moveto_bunny : public SpellScriptLoader { PrepareSpellScript(spell_q12847_summon_soul_moveto_bunny_SpellScript); - void ChangeSummonPos(SpellEffIndex /*effIndex*/) + void SetDest(SpellDestination& dest) { // Adjust effect summon position - WorldLocation summonPos = *GetExplTargetDest(); - Position offset = { 0.0f, 0.0f, 2.5f, 0.0f }; - summonPos.RelocateOffset(offset); - SetExplTargetDest(summonPos); - GetHitDest()->RelocateOffset(offset); + Position const offset = { 0.0f, 0.0f, 2.5f, 0.0f }; + dest.RelocateOffset(offset); } void Register() OVERRIDE { - OnEffectHit += SpellEffectFn(spell_q12847_summon_soul_moveto_bunny_SpellScript::ChangeSummonPos, EFFECT_0, SPELL_EFFECT_SUMMON); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_q12847_summon_soul_moveto_bunny_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER); } }; @@ -2012,19 +2006,19 @@ class spell_q12308_escape_from_silverbrook_summon_worgen : public SpellScriptLoa { PrepareSpellScript(spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript); - void ModDest(SpellEffIndex effIndex) + void ModDest(SpellDestination& dest) { - float dist = GetSpellInfo()->Effects[effIndex].CalcRadius(GetCaster()); - float angle = (urand(0, 1) ? -1 : 1) * (frand(0.75f, 1.0f) * M_PI); + float dist = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster()); + float angle = frand(0.75f, 1.25f) * M_PI; Position pos; GetCaster()->GetNearPosition(pos, dist, angle); - GetHitDest()->Relocate(&pos); + dest.Relocate(pos); } void Register() OVERRIDE { - OnEffectHit += SpellEffectFn(spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript::ModDest, EFFECT_0, SPELL_EFFECT_SUMMON); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript::ModDest, EFFECT_0, TARGET_DEST_CASTER_SUMMON); } }; @@ -2241,6 +2235,47 @@ class spell_q12919_gymers_throw : public SpellScriptLoader } }; +enum Quest_The_Hunter_And_The_Prince +{ + SPELL_ILLIDAN_KILL_CREDIT = 61748 +}; + +class spell_q13400_illidan_kill_master : public SpellScriptLoader +{ + public: + spell_q13400_illidan_kill_master() : SpellScriptLoader("spell_q13400_illidan_kill_master") { } + + class spell_q13400_illidan_kill_master_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q13400_illidan_kill_master_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_ILLIDAN_KILL_CREDIT)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + if (caster->IsVehicle()) + if (Unit* passenger = caster->GetVehicleKit()->GetPassenger(0)) + passenger->CastSpell(passenger, SPELL_ILLIDAN_KILL_CREDIT, true); + } + + void Register() OVERRIDE + { + OnEffectHitTarget += SpellEffectFn(spell_q13400_illidan_kill_master_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_q13400_illidan_kill_master_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -2295,4 +2330,5 @@ void AddSC_quest_spell_scripts() new spell_q12619_emblazon_runeblade_effect(); new spell_q12919_gymers_grab(); new spell_q12919_gymers_throw(); + new spell_q13400_illidan_kill_master(); } diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index 4670117f0ea..d1d43684f3e 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -25,16 +25,21 @@ #include "ScriptMgr.h" #include "SpellScript.h" #include "SpellAuraEffects.h" +#include "Containers.h" enum RogueSpells { - SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK = 22482, - SPELL_ROGUE_CHEAT_DEATH_COOLDOWN = 31231, - SPELL_ROGUE_GLYPH_OF_PREPARATION = 56819, - SPELL_ROGUE_PREY_ON_THE_WEAK = 58670, - SPELL_ROGUE_SHIV_TRIGGERED = 5940, - SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST = 57933, - SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628, + SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK = 22482, + SPELL_ROGUE_CHEAT_DEATH_COOLDOWN = 31231, + SPELL_ROGUE_GLYPH_OF_PREPARATION = 56819, + SPELL_ROGUE_KILLING_SPREE = 51690, + SPELL_ROGUE_KILLING_SPREE_TELEPORT = 57840, + SPELL_ROGUE_KILLING_SPREE_WEAPON_DMG = 57841, + SPELL_ROGUE_KILLING_SPREE_DMG_BUFF = 61851, + SPELL_ROGUE_PREY_ON_THE_WEAK = 58670, + SPELL_ROGUE_SHIV_TRIGGERED = 5940, + SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST = 57933, + SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628, }; // 13877, 33735, (check 51211, 65956) - Blade Flurry @@ -249,6 +254,106 @@ class spell_rog_deadly_poison : public SpellScriptLoader } }; +// 51690 - Killing Spree +#define KillingSpreeScriptName "spell_rog_killing_spree" +class spell_rog_killing_spree : public SpellScriptLoader +{ + public: + spell_rog_killing_spree() : SpellScriptLoader(KillingSpreeScriptName) { } + + class spell_rog_killing_spree_SpellScript : public SpellScript + { + PrepareSpellScript(spell_rog_killing_spree_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + if (targets.empty() || GetCaster()->GetVehicleBase()) + FinishCast(SPELL_FAILED_OUT_OF_RANGE); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (Aura* aura = GetCaster()->GetAura(SPELL_ROGUE_KILLING_SPREE)) + { + if (spell_rog_killing_spree_AuraScript* script = dynamic_cast<spell_rog_killing_spree_AuraScript*>(aura->GetScriptByName(KillingSpreeScriptName))) + script->AddTarget(GetHitUnit()); + } + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rog_killing_spree_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_rog_killing_spree_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_rog_killing_spree_SpellScript(); + } + + class spell_rog_killing_spree_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_killing_spree_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_KILLING_SPREE_TELEPORT) + || !sSpellMgr->GetSpellInfo(SPELL_ROGUE_KILLING_SPREE_WEAPON_DMG) + || !sSpellMgr->GetSpellInfo(SPELL_ROGUE_KILLING_SPREE_DMG_BUFF)) + return false; + return true; + } + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->CastSpell(GetTarget(), SPELL_ROGUE_KILLING_SPREE_DMG_BUFF, true); + } + + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) + { + while (!_targets.empty()) + { + uint64 guid = Trinity::Containers::SelectRandomContainerElement(_targets); + if (Unit* target = ObjectAccessor::GetUnit(*GetTarget(), guid)) + { + GetTarget()->CastSpell(target, SPELL_ROGUE_KILLING_SPREE_TELEPORT, true); + GetTarget()->CastSpell(target, SPELL_ROGUE_KILLING_SPREE_WEAPON_DMG, true); + break; + } + else + _targets.remove(guid); + } + } + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(SPELL_ROGUE_KILLING_SPREE_DMG_BUFF); + } + + void Register() OVERRIDE + { + AfterEffectApply += AuraEffectApplyFn(spell_rog_killing_spree_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_rog_killing_spree_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + AfterEffectRemove += AuraEffectRemoveFn(spell_rog_killing_spree_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + + public: + void AddTarget(Unit* target) + { + _targets.push_back(target->GetGUID()); + } + + private: + std::list<uint64> _targets; + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_rog_killing_spree_AuraScript(); + } +}; + // -31130 - Nerves of Steel class spell_rog_nerves_of_steel : public SpellScriptLoader { @@ -594,6 +699,7 @@ void AddSC_rogue_spell_scripts() new spell_rog_blade_flurry(); new spell_rog_cheat_death(); new spell_rog_deadly_poison(); + new spell_rog_killing_spree(); new spell_rog_nerves_of_steel(); new spell_rog_preparation(); new spell_rog_prey_on_the_weak(); diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index c8fa5b3f1fe..707c8a0985f 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -79,6 +79,18 @@ class spell_sha_ancestral_awakening_proc : public SpellScriptLoader return true; } + void FilterTargets(std::list<WorldObject*>& targets) + { + if (targets.size() < 2) + return; + + targets.sort(Trinity::HealthPctOrderPred()); + + WorldObject* target = targets.front(); + targets.clear(); + targets.push_back(target); + } + void HandleDummy(SpellEffIndex /*effIndex*/) { int32 damage = GetEffectValue(); @@ -88,6 +100,7 @@ class spell_sha_ancestral_awakening_proc : public SpellScriptLoader void Register() OVERRIDE { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_ancestral_awakening_proc_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_RAID); OnEffectHitTarget += SpellEffectFn(spell_sha_ancestral_awakening_proc_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index cafe510cc4f..5a655a92996 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -42,7 +42,9 @@ enum WarriorSpells SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF = 65156, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT = 64976, SPELL_WARRIOR_LAST_STAND_TRIGGERED = 12976, + SPELL_WARRIOR_RETALIATION_DAMAGE = 22858, SPELL_WARRIOR_SLAM = 50783, + SPELL_WARRIOR_SUNDER_ARMOR = 58567, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK = 26654, SPELL_WARRIOR_TAUNT = 355, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_1 = 46859, @@ -53,6 +55,11 @@ enum WarriorSpells SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT = 59665 }; +enum WarriorSpellIcons +{ + WARRIOR_ICON_ID_SUDDEN_DEATH = 1989 +}; + enum MiscSpells { SPELL_PALADIN_BLESSING_OF_SANCTUARY = 20911, @@ -61,11 +68,6 @@ enum MiscSpells SPELL_GEN_DAMAGE_REDUCTION_AURA = 68066, }; -enum WarriorSpellIcons -{ - WARRIOR_ICON_ID_SUDDEN_DEATH = 1989 -}; - // 23881 - Bloodthirst class spell_warr_bloodthirst : public SpellScriptLoader { @@ -313,7 +315,7 @@ class spell_warr_execute : public SpellScriptLoader return true; } - void HandleDummy(SpellEffIndex effIndex) + void HandleEffect(SpellEffIndex effIndex) { Unit* caster = GetCaster(); if (Unit* target = GetHitUnit()) @@ -342,7 +344,7 @@ class spell_warr_execute : public SpellScriptLoader void Register() OVERRIDE { - OnEffectHitTarget += SpellEffectFn(spell_warr_execute_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + OnEffectHitTarget += SpellEffectFn(spell_warr_execute_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_DUMMY); } }; @@ -352,6 +354,42 @@ class spell_warr_execute : public SpellScriptLoader } }; +// 58387 - Glyph of Sunder Armor +class spell_warr_glyph_of_sunder_armor : public SpellScriptLoader +{ + public: + spell_warr_glyph_of_sunder_armor() : SpellScriptLoader("spell_warr_glyph_of_sunder_armor") { } + + class spell_warr_glyph_of_sunder_armor_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warr_glyph_of_sunder_armor_AuraScript); + + void HandleEffectCalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod) + { + if (!spellMod) + { + spellMod = new SpellModifier(aurEff->GetBase()); + spellMod->op = SpellModOp(aurEff->GetMiscValue()); + spellMod->type = SPELLMOD_FLAT; + spellMod->spellId = GetId(); + spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask; + } + + spellMod->value = aurEff->GetAmount(); + } + + void Register() OVERRIDE + { + DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_warr_glyph_of_sunder_armor_AuraScript::HandleEffectCalcSpellMod, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_warr_glyph_of_sunder_armor_AuraScript(); + } +}; + // 59725 - Improved Spell Reflection class spell_warr_improved_spell_reflection : public SpellScriptLoader { @@ -528,6 +566,48 @@ class spell_warr_rend : public SpellScriptLoader } }; +// 20230 - Retaliation +class spell_warr_retaliation : public SpellScriptLoader +{ + public: + spell_warr_retaliation() : SpellScriptLoader("spell_warr_retaliation") { } + + class spell_warr_retaliation_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warr_retaliation_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_RETALIATION_DAMAGE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + // check attack comes not from behind and warrior is not stunned + return GetTarget()->isInFront(eventInfo.GetActor(), M_PI) && !GetTarget()->HasUnitState(UNIT_STATE_STUNNED); + } + + void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_WARRIOR_RETALIATION_DAMAGE, true, NULL, aurEff); + } + + void Register() OVERRIDE + { + DoCheckProc += AuraCheckProcFn(spell_warr_retaliation_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warr_retaliation_AuraScript::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_warr_retaliation_AuraScript(); + } +}; + // 64380, 65941 - Shattering Throw class spell_warr_shattering_throw : public SpellScriptLoader { @@ -739,7 +819,7 @@ class spell_warr_vigilance : public SpellScriptLoader } }; -// 50725 Vigilance +// 50725 - Vigilance class spell_warr_vigilance_trigger : public SpellScriptLoader { public: @@ -779,11 +859,13 @@ void AddSC_warrior_spell_scripts() new spell_warr_damage_shield(); new spell_warr_deep_wounds(); new spell_warr_execute(); + new spell_warr_glyph_of_sunder_armor(); new spell_warr_improved_spell_reflection(); new spell_warr_intimidating_shout(); new spell_warr_last_stand(); new spell_warr_overpower(); new spell_warr_rend(); + new spell_warr_retaliation(); new spell_warr_shattering_throw(); new spell_warr_slam(); new spell_warr_sweeping_strikes(); diff --git a/src/server/scripts/World/npc_taxi.cpp b/src/server/scripts/World/npc_taxi.cpp index 730523c85f4..31617e0ef71 100644 --- a/src/server/scripts/World/npc_taxi.cpp +++ b/src/server/scripts/World/npc_taxi.cpp @@ -162,7 +162,6 @@ public: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CRIMSONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+25); break; case 17209: - player->SetTaxiCheater(true); player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 28); player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 29); player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 30); diff --git a/src/server/shared/CompilerDefs.h b/src/server/shared/CompilerDefs.h index 71b20a4d175..8a557328af4 100644 --- a/src/server/shared/CompilerDefs.h +++ b/src/server/shared/CompilerDefs.h @@ -57,6 +57,8 @@ #if defined(__cplusplus) && __cplusplus == 201103L # define COMPILER_HAS_CPP11_SUPPORT 1 +#elif _MSC_VER >= 1700 +# define COMPILER_HAS_CPP11_SUPPORT 1 #else # define COMPILER_HAS_CPP11_SUPPORT 0 #endif diff --git a/src/server/shared/Cryptography/OpenSSLCrypto.cpp b/src/server/shared/Cryptography/OpenSSLCrypto.cpp index 10ea595640a..bd72459e9df 100644 --- a/src/server/shared/Cryptography/OpenSSLCrypto.cpp +++ b/src/server/shared/Cryptography/OpenSSLCrypto.cpp @@ -33,7 +33,12 @@ static void lockingCallback(int mode, int type, const char* /*file*/, int /*line static void threadIdCallback(CRYPTO_THREADID * id) { +/// ACE_thread_t turns out to be a struct under Mac OS. +#ifndef __APPLE__ CRYPTO_THREADID_set_numeric(id, ACE_Thread::self()); +#else + CRYPTO_THREADID_set_pointer(id, ACE_Thread::self()); +#endif } void OpenSSLCrypto::threadsSetup() diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp index f4da4093dfa..e838c42d32d 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.cpp +++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp @@ -51,6 +51,7 @@ LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter; HANDLE WheatyExceptionReport::m_hReportFile; HANDLE WheatyExceptionReport::m_hDumpFile; HANDLE WheatyExceptionReport::m_hProcess; +SymbolPairs WheatyExceptionReport::symbols; // Declare global instance of class WheatyExceptionReport g_WheatyExceptionReport; @@ -62,6 +63,13 @@ WheatyExceptionReport::WheatyExceptionReport() // Constructor // Install the unhandled exception filter function m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter); m_hProcess = GetCurrentProcess(); + if (!IsDebuggerPresent()) + { + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + } } //============ @@ -71,6 +79,7 @@ WheatyExceptionReport::~WheatyExceptionReport() { if (m_previousFilter) SetUnhandledExceptionFilter(m_previousFilter); + ClearSymbols(); } //=========================================================== @@ -348,7 +357,7 @@ void WheatyExceptionReport::PrintSystemInfo() } //=========================================================================== -void WheatyExceptionReport::printTracesForAllThreads() +void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables) { THREADENTRY32 te32; @@ -384,7 +393,7 @@ void WheatyExceptionReport::printTracesForAllThreads() if (threadHandle) { if (GetThreadContext(threadHandle, &context)) - WriteStackDetails(&context, false, threadHandle); + WriteStackDetails(&context, bWriteVariables, threadHandle); CloseHandle(threadHandle); } } @@ -480,7 +489,7 @@ PEXCEPTION_POINTERS pExceptionInfo) CONTEXT trashableContext = *pCtx; WriteStackDetails(&trashableContext, false, NULL); - printTracesForAllThreads(); + printTracesForAllThreads(false); // #ifdef _M_IX86 // X86 Only! @@ -489,13 +498,14 @@ PEXCEPTION_POINTERS pExceptionInfo) trashableContext = *pCtx; WriteStackDetails(&trashableContext, true, NULL); + printTracesForAllThreads(true); - _tprintf(_T("========================\r\n")); + /*_tprintf(_T("========================\r\n")); _tprintf(_T("Global Variables\r\n")); SymEnumSymbols(GetCurrentProcess(), (UINT_PTR)GetModuleHandle(szFaultingModule), - 0, EnumerateSymbolsCallback, 0); + 0, EnumerateSymbolsCallback, 0);*/ // #endif // X86 Only! SymCleanup(GetCurrentProcess()); @@ -566,6 +576,9 @@ PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset) DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase; + if (!hMod) + return FALSE; + if (!GetModuleFileName((HMODULE)hMod, szModule, len)) return FALSE; @@ -708,7 +721,7 @@ bool bWriteVariables, HANDLE pThreadHandle) } // Get the source line for this stack frame entry - IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE) }; + IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) }; DWORD dwLineDisplacement; if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo)) @@ -746,15 +759,16 @@ ULONG /*SymbolSize*/, PVOID UserContext) { - char szBuffer[2048]; + char szBuffer[1024 * 64]; __try { - if (FormatSymbolValue(pSymInfo, (STACKFRAME*)UserContext, + ClearSymbols(); + if (FormatSymbolValue(pSymInfo, (STACKFRAME64*)UserContext, szBuffer, sizeof(szBuffer))) _tprintf(_T("\t%s\r\n"), szBuffer); } - __except(1) + __except (EXCEPTION_EXECUTE_HANDLER) { _tprintf(_T("punting on symbol %s\r\n"), pSymInfo->Name); } @@ -769,7 +783,7 @@ PVOID UserContext) ////////////////////////////////////////////////////////////////////////////// bool WheatyExceptionReport::FormatSymbolValue( PSYMBOL_INFO pSym, -STACKFRAME * sf, +STACKFRAME64 * sf, char * pszBuffer, unsigned /*cbBuffer*/) { @@ -782,7 +796,7 @@ unsigned /*cbBuffer*/) pszCurrBuffer += sprintf(pszCurrBuffer, "Local "); // If it's a function, don't do anything. - if (pSym->Tag == 5) // SymTagFunction from CVCONST.H from the DIA SDK + if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK return false; DWORD_PTR pVariable = 0; // Will point to the variable's data in memory @@ -791,7 +805,11 @@ unsigned /*cbBuffer*/) { // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1) { // This may change!!! +#ifdef _M_IX86 pVariable = sf->AddrFrame.Offset; +#elif _M_X64 + pVariable = sf->AddrStack.Offset; +#endif pVariable += (DWORD_PTR)pSym->Address; } // else @@ -810,7 +828,7 @@ unsigned /*cbBuffer*/) // will return true. bool bHandled; pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, pSym->ModBase, pSym->TypeIndex, - 0, pVariable, bHandled, pSym->Name); + 0, pVariable, bHandled, pSym->Name, ""); if (!bHandled) { @@ -842,10 +860,18 @@ DWORD dwTypeIndex, unsigned nestingLevel, DWORD_PTR offset, bool & bHandled, -char* /*Name*/) +char* Name, +char* suffix) { bHandled = false; + if (!StoreSymbol(dwTypeIndex, offset)) + return pszCurrBuffer; + + DWORD typeTag; + if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMTAG, &typeTag)) + return pszCurrBuffer; + // Get the name of the symbol. This will either be a Type name (if a UDT), // or the structure member name. WCHAR * pwszTypeName; @@ -856,10 +882,82 @@ char* /*Name*/) LocalFree(pwszTypeName); } + if (strlen(suffix) > 0) + pszCurrBuffer += sprintf(pszCurrBuffer, "%s", suffix); + + DWORD innerTypeID; + switch (typeTag) + { + case SymTagPointerType: + if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID)) + { +#define MAX_NESTING_LEVEL 5 + if (nestingLevel >= MAX_NESTING_LEVEL) + break; + + pszCurrBuffer += sprintf(pszCurrBuffer, " %s", Name); + BOOL isReference; + SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_IS_REFERENCE, &isReference); + + char addressStr[40]; + memset(addressStr, 0, sizeof(addressStr)); + + if (isReference) + addressStr[0] = '&'; + else + addressStr[0] = '*'; + + DWORD_PTR address = *(PDWORD_PTR)offset; + if (address == NULL) + { + pwszTypeName; + if (SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_SYMNAME, + &pwszTypeName)) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " %ls", pwszTypeName); + LocalFree(pwszTypeName); + } + + pszCurrBuffer += sprintf(pszCurrBuffer, "%s = NULL\r\n", addressStr); + + bHandled = true; + return pszCurrBuffer; + } + else + { + FormatOutputValue(&addressStr[1], btVoid, sizeof(PVOID), (PVOID)offset); + pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1, + address, bHandled, "", addressStr); + } + } + break; + case SymTagData: + if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID)) + { + DWORD innerTypeTag; + if (!SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_SYMTAG, &innerTypeTag)) + break; + + if (innerTypeTag == SymTagPointerType) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " %s", Name); + + pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1, + offset, bHandled, "", ""); + } + } + break; + case SymTagBaseType: + break; + case SymTagEnum: + return pszCurrBuffer; + default: + break; + } + // Determine how many children this type has. DWORD dwChildrenCount = 0; - SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, - &dwChildrenCount); + SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &dwChildrenCount); if (!dwChildrenCount) // If no children, we're done return pszCurrBuffer; @@ -869,7 +967,7 @@ char* /*Name*/) // TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this. struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS { - ULONG MoreChildIds[1024]; + ULONG MoreChildIds[1024*2]; FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);} } children; @@ -889,6 +987,12 @@ char* /*Name*/) // Iterate through each of the children for (unsigned i = 0; i < dwChildrenCount; i++) { + DWORD symTag; + SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_SYMTAG, &symTag); + + if (symTag == SymTagFunction || symTag == SymTagTypedef) + continue; + // Add appropriate indentation level (since this routine is recursive) for (unsigned j = 0; j <= nestingLevel+1; j++) pszCurrBuffer += sprintf(pszCurrBuffer, "\t"); @@ -898,18 +1002,21 @@ char* /*Name*/) BasicType basicType = GetBasicType(children.ChildId[i], modBase); pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); + // Get the offset of the child member, relative to its parent + DWORD dwMemberOffset; + SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], + TI_GET_OFFSET, &dwMemberOffset); + + // Calculate the address of the member + DWORD_PTR dwFinalOffset = offset + dwMemberOffset; + pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, children.ChildId[i], nestingLevel+1, - offset, bHandled2, ""/*Name */); + dwFinalOffset, bHandled2, ""/*Name */, ""); // If the child wasn't a UDT, format it appropriately if (!bHandled2) { - // Get the offset of the child member, relative to its parent - DWORD dwMemberOffset; - SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], - TI_GET_OFFSET, &dwMemberOffset); - // Get the real "TypeId" of the child. We need this for the // SymGetTypeInfo(TI_GET_TYPEID) call below. DWORD typeId; @@ -920,9 +1027,6 @@ char* /*Name*/) ULONG64 length; SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_LENGTH, &length); - // Calculate the address of the member - DWORD_PTR dwFinalOffset = offset + dwMemberOffset; - // BasicType basicType = GetBasicType(children.ChildId[i], modBase); // // pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); @@ -946,41 +1050,60 @@ BasicType basicType, DWORD64 length, PVOID pAddress) { - // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!) - if (length == 1) - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PBYTE)pAddress); - else if (length == 2) - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PWORD)pAddress); - else if (length == 4) + __try { - if (basicType == btFloat) + // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!) + if (length == 1) + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PBYTE)pAddress); + else if (length == 2) + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PWORD)pAddress); + else if (length == 4) { - pszCurrBuffer += sprintf(pszCurrBuffer, " = %f", *(PFLOAT)pAddress); + if (basicType == btFloat) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " = %f", *(PFLOAT)pAddress); + } + else if (basicType == btChar) + { + if (!IsBadStringPtr(*(PSTR*)pAddress, 32)) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " = \"%.31s\"", + *(PSTR*)pAddress); + } + else + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", + *(PDWORD)pAddress); + } + else + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PDWORD)pAddress); } - else if (basicType == btChar) + else if (length == 8) { - if (!IsBadStringPtr(*(PSTR*)pAddress, 32)) + if (basicType == btFloat) { - pszCurrBuffer += sprintf(pszCurrBuffer, " = \"%.31s\"", - *(PSTR*)pAddress); + pszCurrBuffer += sprintf(pszCurrBuffer, " = %lf", + *(double *)pAddress); } else - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", - *(PDWORD)pAddress); + pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X", + *(DWORD64*)pAddress); } else - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PDWORD)pAddress); - } - else if (length == 8) - { - if (basicType == btFloat) { - pszCurrBuffer += sprintf(pszCurrBuffer, " = %lf", - *(double *)pAddress); +#if _WIN64 + pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X", (DWORD64*)pAddress); +#else + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", (PDWORD)pAddress); +#endif } - else - pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X", - *(DWORD64*)pAddress); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { +#if _WIN64 + pszCurrBuffer += sprintf(pszCurrBuffer, " <Unable to read memory> = %I64X", (DWORD64*)pAddress); +#else + pszCurrBuffer += sprintf(pszCurrBuffer, " <Unable to read memory> = %X", (PDWORD)pAddress); +#endif } return pszCurrBuffer; @@ -1017,7 +1140,7 @@ WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase) //============================================================================ int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...) { - TCHAR szBuff[1024]; + TCHAR szBuff[1024 * 64]; int retValue; DWORD cbWritten; va_list argptr; @@ -1031,4 +1154,14 @@ int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...) return retValue; } +bool WheatyExceptionReport::StoreSymbol(DWORD type, DWORD_PTR offset) +{ + return symbols.insert(SymbolPair(type, offset)).second; +} + +void WheatyExceptionReport::ClearSymbols() +{ + symbols.clear(); +} + #endif // _WIN32 diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h index 582f1f157b8..74330370509 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.h +++ b/src/server/shared/Debugging/WheatyExceptionReport.h @@ -4,7 +4,7 @@ #if PLATFORM == PLATFORM_WINDOWS && !defined(__MINGW32__) #include <dbghelp.h> - +#include <set> #if _MSC_VER < 1400 # define countof(array) (sizeof(array) / sizeof(array[0])) #else @@ -70,6 +70,25 @@ const char* const rgBaseType[] = " HRESULT " // btHresult = 31 }; +struct SymbolPair +{ + SymbolPair(DWORD type, DWORD_PTR offset) + { + _type = type; + _offset = offset; + } + + bool operator<(const SymbolPair& other) const + { + return _offset < other._offset || + (_offset == other._offset && _type < other._type); + } + + DWORD _type; + DWORD_PTR _offset; +}; +typedef std::set<SymbolPair> SymbolPairs; + class WheatyExceptionReport { public: @@ -81,7 +100,7 @@ class WheatyExceptionReport static LONG WINAPI WheatyUnhandledExceptionFilter( PEXCEPTION_POINTERS pExceptionInfo); - static void printTracesForAllThreads(); + static void printTracesForAllThreads(bool); private: // where report info is extracted and generated static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo); @@ -98,9 +117,9 @@ class WheatyExceptionReport static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID); - static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer); + static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *, char * pszBuffer, unsigned cbBuffer); - static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool &, char*); + static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool &, char*, char*); static char * FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress); @@ -108,6 +127,9 @@ class WheatyExceptionReport static int __cdecl _tprintf(const TCHAR * format, ...); + static bool StoreSymbol(DWORD type , DWORD_PTR offset); + static void ClearSymbols(); + // Variables used by the class static TCHAR m_szLogFileName[MAX_PATH]; static TCHAR m_szDumpFileName[MAX_PATH]; @@ -115,6 +137,7 @@ class WheatyExceptionReport static HANDLE m_hReportFile; static HANDLE m_hDumpFile; static HANDLE m_hProcess; + static SymbolPairs symbols; }; extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp index b9c2fd7339d..a88188266e2 100644 --- a/src/server/shared/Logging/AppenderFile.cpp +++ b/src/server/shared/Logging/AppenderFile.cpp @@ -33,7 +33,8 @@ AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, co dynamicName = std::string::npos != filename.find("%s"); backup = (_flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0; - logfile = !dynamicName ? OpenFile(_filename, _mode, mode == "w" && backup) : NULL; + if (!dynamicName) + logfile = OpenFile(_filename, _mode, mode == "w" && backup); } AppenderFile::~AppenderFile() @@ -49,7 +50,15 @@ void AppenderFile::_write(LogMessage const& message) { char namebuf[TRINITY_PATH_MAX]; snprintf(namebuf, TRINITY_PATH_MAX, filename.c_str(), message.param1.c_str()); - logfile = OpenFile(namebuf, mode, backup || exceedMaxSize); + // always use "a" with dynamic name otherwise it could delete the log we wrote in last _write() call + FILE* file = OpenFile(namebuf, "a", backup || exceedMaxSize); + if (!file) + return; + fprintf(file, "%s%s", message.prefix.c_str(), message.text.c_str()); + fflush(file); + fileSize += uint64(message.Size()); + fclose(file); + return; } else if (exceedMaxSize) logfile = OpenFile(filename, "w", true); @@ -60,9 +69,6 @@ void AppenderFile::_write(LogMessage const& message) fprintf(logfile, "%s%s", message.prefix.c_str(), message.text.c_str()); fflush(logfile); fileSize += uint64(message.Size()); - - if (dynamicName) - CloseFile(); } FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mode, bool backup) diff --git a/src/server/shared/Utilities/ByteConverter.h b/src/server/shared/Utilities/ByteConverter.h index bf1342a10e4..8eebb05bb13 100644 --- a/src/server/shared/Utilities/ByteConverter.h +++ b/src/server/shared/Utilities/ByteConverter.h @@ -47,9 +47,13 @@ namespace ByteConverter #if TRINITY_ENDIAN == TRINITY_BIGENDIAN template<typename T> inline void EndianConvert(T& val) { ByteConverter::apply<T>(&val); } template<typename T> inline void EndianConvertReverse(T&) { } +template<typename T> inline void EndianConvertPtr(void* val) { ByteConverter::apply<T>(val); } +template<typename T> inline void EndianConvertPtrReverse(void*) { } #else template<typename T> inline void EndianConvert(T&) { } template<typename T> inline void EndianConvertReverse(T& val) { ByteConverter::apply<T>(&val); } +template<typename T> inline void EndianConvertPtr(void*) { } +template<typename T> inline void EndianConvertPtrReverse(void* val) { ByteConverter::apply<T>(val); } #endif template<typename T> void EndianConvert(T*); // will generate link error diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp index 499ad0502b7..ffef61557fc 100644 --- a/src/server/shared/Utilities/Util.cpp +++ b/src/server/shared/Utilities/Util.cpp @@ -510,6 +510,9 @@ void vutf8printf(FILE* out, const char *str, va_list* ap) wchar_t wtemp_buf[32*1024]; size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap); + //vsnprintf returns -1 if the buffer is too small + if (temp_len == size_t(-1)) + temp_len = 32*1024-1; size_t wtemp_len = 32*1024-1; Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len); diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp index f4b2b542de6..c3075deb762 100644 --- a/src/server/worldserver/Master.cpp +++ b/src/server/worldserver/Master.cpp @@ -200,42 +200,44 @@ int Master::Run() ACE_Based::Thread rarThread(new RARunnable); +#if defined(_WIN32) || defined(__linux__) + ///- Handle affinity for multiple processors and process priority uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0); bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false); #ifdef _WIN32 // Windows + + HANDLE hProcess = GetCurrentProcess(); + + if (affinity > 0) { - HANDLE hProcess = GetCurrentProcess(); - - if (affinity > 0) - { - ULONG_PTR appAff; - ULONG_PTR sysAff; - - if (GetProcessAffinityMask(hProcess, &appAff, &sysAff)) - { - ULONG_PTR currentAffinity = affinity & appAff; // remove non accessible processors - - if (!currentAffinity) - TC_LOG_ERROR("server.worldserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the worldserver. Accessible processors bitmask (hex): %x", affinity, appAff); - else if (SetProcessAffinityMask(hProcess, currentAffinity)) - TC_LOG_INFO("server.worldserver", "Using processors (bitmask, hex): %x", currentAffinity); - else - TC_LOG_ERROR("server.worldserver", "Can't set used processors (hex): %x", currentAffinity); - } - } - - if (highPriority) + ULONG_PTR appAff; + ULONG_PTR sysAff; + + if (GetProcessAffinityMask(hProcess, &appAff, &sysAff)) { - if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) - TC_LOG_INFO("server.worldserver", "worldserver process priority class set to HIGH"); + ULONG_PTR currentAffinity = affinity & appAff; // remove non accessible processors + + if (!currentAffinity) + TC_LOG_ERROR("server.worldserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the worldserver. Accessible processors bitmask (hex): %x", affinity, appAff); + else if (SetProcessAffinityMask(hProcess, currentAffinity)) + TC_LOG_INFO("server.worldserver", "Using processors (bitmask, hex): %x", currentAffinity); else - TC_LOG_ERROR("server.worldserver", "Can't set worldserver process priority class."); + TC_LOG_ERROR("server.worldserver", "Can't set used processors (hex): %x", currentAffinity); } } -#elif __linux__ // Linux - + + if (highPriority) + { + if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) + TC_LOG_INFO("server.worldserver", "worldserver process priority class set to HIGH"); + else + TC_LOG_ERROR("server.worldserver", "Can't set worldserver process priority class."); + } + +#else // Linux + if (affinity > 0) { cpu_set_t mask; @@ -262,7 +264,8 @@ int Master::Run() else TC_LOG_INFO("server.worldserver", "worldserver process priority class set to %i", getpriority(PRIO_PROCESS, 0)); } - + +#endif #endif //Start soap serving thread diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 2a47c8f989e..1762859afae 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1140,6 +1140,15 @@ AccountInstancesPerHour = 5 Account.PasswordChangeSecurity = 0 # +# BirthdayTime +# Description: Set to date of project's birth in UNIX time. By default the date when TrinityCore was started (Thu Oct 2, 2008) +# Default: 1222964635 +# +# + +BirthdayTime = 1222964635 + +# ################################################################################################### ################################################################################################### diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 805926defa0..aa02d76fe47 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -340,7 +340,9 @@ namespace MMAP /**************************************************************************/ void MapBuilder::buildMap(uint32 mapID) { +#ifndef __APPLE__ printf("[Thread %u] Building map %03u:\n", uint32(ACE_Thread::self()), mapID); +#endif std::set<uint32>* tiles = getTileList(mapID); diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index b28ed84e105..d75af79f379 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -396,7 +396,7 @@ bool processArgv(int argc, char ** argv, const char *versionString) { hasInputPathParam = true; strcpy(input_path, argv[i+1]); - if (input_path[strlen(input_path) - 1] != '\\' || input_path[strlen(input_path) - 1] != '/') + if (input_path[strlen(input_path) - 1] != '\\' && input_path[strlen(input_path) - 1] != '/') strcat(input_path, "/"); ++i; } |
