diff options
Diffstat (limited to 'src')
67 files changed, 1533 insertions, 1787 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 5f6573ad1a6..36eedae90ef 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2264,7 +2264,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (linked) ProcessEvent(linked, unit, var0, var1, bvar, spell, gob); else - TC_LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.link); + TC_LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.link); } } diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 79b9557fc2b..43fe9a80bc3 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -462,7 +462,7 @@ void AccountMgr::LoadRBAC() while (result->NextRow()); TC_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading default permissions"); - result = LoginDatabase.Query("SELECT secId, permissionId FROM rbac_default_permissions ORDER BY secId ASC"); + result = LoginDatabase.PQuery("SELECT secId, permissionId FROM rbac_default_permissions WHERE (realmId = %u OR realmId = -1) ORDER BY secId ASC", realmID); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 default permission definitions. DB table `rbac_default_permissions` is empty."); diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 7001374d90a..d63ba84605e 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -100,6 +100,7 @@ enum RBACPermissions RBAC_PERM_COMMANDS_PINFO_CHECK_PERSONAL_DATA = 48, RBAC_PERM_EMAIL_CONFIRM_FOR_PASS_CHANGE = 49, RBAC_PERM_MAY_CHECK_OWN_EMAIL = 50, + RBAC_PERM_ALLOW_TWO_SIDE_TRADE = 51, // Free space for core permissions (till 149) // Roles (Permissions with delegated permissions) use 199 and descending diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 6f614994489..f05ce5bded9 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -982,7 +982,7 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text) if (!idS) return 0; - uint32 id = (uint32)atol(idS); + uint32 id = atoul(idS); switch (type) { @@ -995,13 +995,10 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text) if (!talentEntry) return 0; - int32 rank = param1_str ? (uint32)atol(param1_str) : 0; + uint32 rank = param1_str ? atol(param1_str) : 0u; if (rank >= MAX_TALENT_RANK) return 0; - if (rank < 0) - rank = 0; - return talentEntry->RankID[rank]; } case SPELL_LINK_ENCHANT: @@ -1009,7 +1006,7 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text) return id; case SPELL_LINK_GLYPH: { - uint32 glyph_prop_id = param1_str ? (uint32)atol(param1_str) : 0; + uint32 glyph_prop_id = param1_str ? atoul(param1_str) : 0; GlyphPropertiesEntry const* glyphPropEntry = sGlyphPropertiesStore.LookupEntry(glyph_prop_id); if (!glyphPropEntry) @@ -1082,7 +1079,7 @@ ObjectGuid ChatHandler::extractGuidFromLink(char* text) } case SPELL_LINK_CREATURE: { - uint32 lowguid = (uint32)atol(idS); + uint32 lowguid = atoul(idS); if (CreatureData const* data = sObjectMgr->GetCreatureData(lowguid)) return ObjectGuid(HIGHGUID_UNIT, data->id, lowguid); @@ -1091,7 +1088,7 @@ ObjectGuid ChatHandler::extractGuidFromLink(char* text) } case SPELL_LINK_GAMEOBJECT: { - uint32 lowguid = (uint32)atol(idS); + uint32 lowguid = atoul(idS); if (GameObjectData const* data = sObjectMgr->GetGOData(lowguid)) return ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, lowguid); diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 094a8345395..f7fa719a610 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -29,6 +29,79 @@ #include "SpellMgr.h" #include "Spell.h" +char const* ConditionMgr::StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX] = +{ + "None", + "Creature Loot", + "Disenchant Loot", + "Fishing Loot", + "GameObject Loot", + "Item Loot", + "Mail Loot", + "Milling Loot", + "Pickpocketing Loot", + "Prospecting Loot", + "Reference Loot", + "Skinning Loot", + "Spell Loot", + "Spell Impl. Target", + "Gossip Menu", + "Gossip Menu Option", + "Creature Vehicle", + "Spell Expl. Target", + "Spell Click Event", + "Quest Accept", + "Quest Show Mark", + "Vehicle Spell", + "SmartScript", + "Npc Vendor", + "Spell Proc", + "Phase Def" +}; + +ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[CONDITION_MAX] = +{ + { "None", false, false, false }, + { "Aura", true, true, true }, + { "Item Stored", true, true, true }, + { "Item Equipped", true, false, false }, + { "Zone", true, false, false }, + { "Reputation", true, true, false }, + { "Team", true, false, false }, + { "Skill", true, true, false }, + { "Quest Rewarded", true, false, false }, + { "Quest Taken", true, false, false }, + { "Drunken", true, false, false }, + { "WorldState", true, true, false }, + { "Active Event", true, false, false }, + { "Instance Info", true, true, true }, + { "Quest None", true, false, false }, + { "Class", true, false, false }, + { "Race", true, false, false }, + { "Achievement", true, false, false }, + { "Title", true, false, false }, + { "SpawnMask", true, false, false }, + { "Gender", true, false, false }, + { "Unit State", true, false, false }, + { "Map", true, false, false }, + { "Area", true, false, false }, + { "CreatureType", true, false, false }, + { "Spell Known", true, false, false }, + { "PhaseMask", true, false, false }, + { "Level", true, true, false }, + { "Quest Completed", true, false, false }, + { "Near Creature", true, true, false }, + { "Near GameObject", true, true, false }, + { "Object Entry or Guid", true, true, true }, + { "Object TypeMask", true, false, false }, + { "Relation", true, true, false }, + { "Reaction", true, true, false }, + { "Distance", true, true, true }, + { "Alive", false, false, false }, + { "Health Value", true, true, false }, + { "Health Pct", true, true, false } +}; + // Checks if object meets the condition // Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI) bool Condition::Meets(ConditionSourceInfo& sourceInfo) @@ -38,7 +111,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) // object not present, return false if (!object) { - TC_LOG_DEBUG("condition", "Condition object not found for condition (Entry: %u Type: %u Group: %u)", SourceEntry, SourceType, SourceGroup); + TC_LOG_DEBUG("condition", "Condition object not found for %s", ToString().c_str()); return false; } bool condMeets = false; @@ -535,6 +608,34 @@ uint32 Condition::GetMaxAvailableConditionTargets() } } +std::string Condition::ToString(bool ext /*= false*/) const +{ + std::ostringstream ss; + ss << "[Condition "; + ss << "SourceType: " << SourceType; + if (SourceType < CONDITION_SOURCE_TYPE_MAX) + ss << " (" << ConditionMgr::StaticSourceTypeData[SourceType] << ")"; + else + ss << " (Unknown)"; + if (ConditionMgr::CanHaveSourceGroupSet(SourceType)) + ss << ", SourceGroup: " << SourceGroup; + ss << ", SourceEntry: " << SourceEntry; + if (ConditionMgr::CanHaveSourceIdSet(SourceType)) + ss << ", SourceId: " << SourceId; + + if (ext) + { + ss << ", ConditionType: " << ConditionType; + if (ConditionType < CONDITION_MAX) + ss << " (" << ConditionMgr::StaticConditionTypeData[ConditionType].Name << ")"; + else + ss << " (Unknown)"; + } + + ss << "]"; + return ss.str(); +} + ConditionMgr::ConditionMgr() { } ConditionMgr::~ConditionMgr() @@ -597,7 +698,7 @@ bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, std::map<uint32, bool> ElseGroupStore; for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i) { - TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList condType: %u val1: %u", (*i)->ConditionType, (*i)->ConditionValue1); + TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList %s val1: %u", (*i)->ToString().c_str(), (*i)->ConditionValue1); if ((*i)->isLoaded()) { //! Find ElseGroup in ElseGroupStore @@ -618,8 +719,8 @@ bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, } else { - TC_LOG_DEBUG("condition", "IsPlayerMeetToConditionList: Reference template -%u not found", - (*i)->ReferenceId);//checked at loading, should never happen + TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList %s Reference template -%u not found", + (*i)->ToString().c_str(), (*i)->ReferenceId); // checked at loading, should never happen } } @@ -658,7 +759,7 @@ bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, Con return IsObjectMeetToConditionList(sourceInfo, conditions); } -bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const +bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) { return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE || sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE || @@ -681,7 +782,7 @@ bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR); } -bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType) const +bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType) { return (sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT); } @@ -715,7 +816,7 @@ ConditionList ConditionMgr::GetConditionsForSpellClickEvent(uint32 creatureId, u if (i != (*itr).second.end()) { cond = (*i).second; - TC_LOG_DEBUG("condition", "GetConditionsForSpellClickEvent: found conditions for Vehicle entry %u spell %u", creatureId, spellId); + TC_LOG_DEBUG("condition", "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry %u spell %u", creatureId, spellId); } } return cond; @@ -747,7 +848,7 @@ ConditionList ConditionMgr::GetConditionsForSmartEvent(int32 entryOrGuid, uint32 if (i != (*itr).second.end()) { cond = (*i).second; - TC_LOG_DEBUG("condition", "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid %d event_id %u", entryOrGuid, eventId); + TC_LOG_DEBUG("condition", "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid %d eventId %u", entryOrGuid, eventId); } } return cond; @@ -895,26 +996,26 @@ void ConditionMgr::LoadConditions(bool isReload) //Grouping is only allowed for some types (loot templates, gossip menus, gossip items) if (cond->SourceGroup && !CanHaveSourceGroupSet(cond->SourceType)) { - TC_LOG_ERROR("sql.sql", "Condition type %u has not allowed value of SourceGroup = %u!", uint32(cond->SourceType), cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s has not allowed value of SourceGroup = %u!", cond->ToString().c_str(), cond->SourceGroup); delete cond; continue; } if (cond->SourceId && !CanHaveSourceIdSet(cond->SourceType)) { - TC_LOG_ERROR("sql.sql", "Condition type %u has not allowed value of SourceId = %u!", uint32(cond->SourceType), cond->SourceId); + TC_LOG_ERROR("sql.sql", "%s has not allowed value of SourceId = %u!", cond->ToString().c_str(), cond->SourceId); delete cond; continue; } if (cond->ErrorType && cond->SourceType != CONDITION_SOURCE_TYPE_SPELL) { - TC_LOG_ERROR("sql.sql", "Condition type %u entry %i can't have ErrorType (%u), set to 0!", uint32(cond->SourceType), cond->SourceEntry, cond->ErrorType); + TC_LOG_ERROR("sql.sql", "%s can't have ErrorType (%u), set to 0!", cond->ToString().c_str(), cond->ErrorType); cond->ErrorType = 0; } if (cond->ErrorTextId && !cond->ErrorType) { - TC_LOG_ERROR("sql.sql", "Condition type %u entry %i has any ErrorType, ErrorTextId (%u) is set, set to 0!", uint32(cond->SourceType), cond->SourceEntry, cond->ErrorTextId); + TC_LOG_ERROR("sql.sql", "%s has any ErrorType, ErrorTextId (%u) is set, set to 0!", cond->ToString().c_str(), cond->ErrorTextId); cond->ErrorTextId = 0; } @@ -1005,7 +1106,7 @@ void ConditionMgr::LoadConditions(bool isReload) if (!valid) { - TC_LOG_ERROR("sql.sql", "Not handled grouped condition, SourceGroup %u", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s Not handled grouped condition.", cond->ToString().c_str()); delete cond; } else @@ -1038,21 +1139,20 @@ void ConditionMgr::LoadConditions(bool isReload) while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u conditions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - } bool ConditionMgr::addToLootTemplate(Condition* cond, LootTemplate* loot) { if (!loot) { - TC_LOG_ERROR("sql.sql", "ConditionMgr: LootTemplate %u not found", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s LootTemplate %u not found.", cond->ToString().c_str(), cond->SourceGroup); return false; } if (loot->addConditionItem(cond)) return true; - TC_LOG_ERROR("sql.sql", "ConditionMgr: Item %u not found in LootTemplate %u", cond->SourceEntry, cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s Item %u not found in LootTemplate %u.", cond->ToString().c_str(), cond->SourceEntry, cond->SourceGroup); return false; } @@ -1072,7 +1172,7 @@ bool ConditionMgr::addToGossipMenus(Condition* cond) } } - TC_LOG_ERROR("sql.sql", "addToGossipMenus: GossipMenu %u not found", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s GossipMenu %u not found.", cond->ToString().c_str(), cond->SourceGroup); return false; } @@ -1091,7 +1191,7 @@ bool ConditionMgr::addToGossipMenuItems(Condition* cond) } } - TC_LOG_ERROR("sql.sql", "addToGossipMenuItems: GossipMenuId %u Item %u not found", cond->SourceGroup, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s GossipMenuId %u Item %u not found.", cond->ToString().c_str(), cond->SourceGroup, cond->SourceEntry); return false; } @@ -1116,12 +1216,12 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) continue; // build new shared mask with found effect - uint32 sharedMask = (1<<i); + uint32 sharedMask = (1 << i); ConditionList* cmp = spellInfo->Effects[i].ImplicitTargetConditions; for (uint8 effIndex = i+1; effIndex < MAX_SPELL_EFFECTS; ++effIndex) { if (spellInfo->Effects[effIndex].ImplicitTargetConditions == cmp) - sharedMask |= 1<<effIndex; + sharedMask |= 1 << effIndex; } sharedMasks.push_back(sharedMask); } @@ -1148,8 +1248,8 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) // we have overlapping masks in db if (conditionEffMask != *itr) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set - " - "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->SourceEntry, cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s in `condition` table, has incorrect SourceGroup %u (spell effectMask) set - " + "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->ToString().c_str(), cond->SourceGroup); return false; } } @@ -1182,7 +1282,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (cond->SourceType == CONDITION_SOURCE_TYPE_NONE || cond->SourceType >= CONDITION_SOURCE_TYPE_MAX) { - TC_LOG_ERROR("sql.sql", "Invalid ConditionSourceType %u in `condition` table, ignoring.", uint32(cond->SourceType)); + TC_LOG_ERROR("sql.sql", "%s Invalid ConditionSourceType in `condition` table, ignoring.", cond->ToString().c_str()); return false; } @@ -1192,7 +1292,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Creature.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1200,7 +1300,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1209,7 +1309,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Disenchant.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1217,7 +1317,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1226,7 +1326,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Fishing.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1234,7 +1334,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1243,7 +1343,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Gameobject.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1251,7 +1351,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1260,7 +1360,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Item.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1268,7 +1368,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1277,7 +1377,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Mail.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1285,7 +1385,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1294,7 +1394,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Milling.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1302,7 +1402,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1311,7 +1411,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Pickpocketing.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1319,7 +1419,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1328,7 +1428,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Prospecting.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1336,7 +1436,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1345,7 +1445,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Reference.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1353,7 +1453,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1362,7 +1462,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Skinning.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1370,7 +1470,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1379,7 +1479,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!LootTemplates_Spell.HaveLootFor(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceGroup %u in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceGroup in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->ToString().c_str()); return false; } @@ -1387,7 +1487,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!pItemProto && !loot->isReference(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1397,13 +1497,13 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry); if (!spellInfo) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s in `condition` table, SourceEntry does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str()); return false; } if ((cond->SourceGroup > MAX_EFFECT_MASK) || !cond->SourceGroup) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set, ignoring.", cond->SourceEntry, cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s in `condition` table, has incorrect SourceGroup (spell effectMask) set, ignoring.", cond->ToString().c_str()); return false; } @@ -1411,7 +1511,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (!((1<<i) & cond->SourceGroup)) + if (!((1 << i) & cond->SourceGroup)) continue; switch (spellInfo->Effects[i].TargetA.GetSelectionCategory()) @@ -1435,7 +1535,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) } TC_LOG_ERROR("sql.sql", "SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i)); - cond->SourceGroup &= ~(1<<i); + cond->SourceGroup &= ~(1 << i); } // all effects were removed, no need to add the condition at all if (!cond->SourceGroup) @@ -1446,7 +1546,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!sObjectMgr->GetCreatureTemplate(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1457,48 +1557,42 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry); if (!spellProto) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str()); return false; } break; } case CONDITION_SOURCE_TYPE_QUEST_ACCEPT: - if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry)) - { - TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_QUEST_ACCEPT specifies non-existing quest (%u), skipped", cond->SourceEntry); - return false; - } - break; case CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK: if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK specifies non-existing quest (%u), skipped", cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceEntry specifies non-existing quest, skipped.", cond->ToString().c_str()); return false; } break; case CONDITION_SOURCE_TYPE_VEHICLE_SPELL: if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); return false; } if (!sSpellMgr->GetSpellInfo(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str()); return false; } break; case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT: if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); return false; } if (!sSpellMgr->GetSpellInfo(cond->SourceEntry)) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1506,13 +1600,13 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) { if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup)) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString().c_str()); return false; } ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(cond->SourceEntry); if (!itemTemplate) { - TC_LOG_ERROR("sql.sql", "SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString().c_str()); return false; } break; @@ -1537,13 +1631,13 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (cond->ConditionType == CONDITION_NONE || cond->ConditionType >= CONDITION_MAX) { - TC_LOG_ERROR("sql.sql", "Invalid ConditionType %u at SourceEntry %u in `condition` table, ignoring.", uint32(cond->ConditionType), cond->SourceEntry); + TC_LOG_ERROR("sql.sql", "%s Invalid ConditionType in `condition` table, ignoring.", cond->ToString().c_str()); return false; } if (cond->ConditionTarget >= cond->GetMaxAvailableConditionTargets()) { - TC_LOG_ERROR("sql.sql", "SourceType %u, SourceEntry %u, SourceGroup %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->SourceType, cond->SourceEntry, cond->SourceGroup); + TC_LOG_ERROR("sql.sql", "%s in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->ToString(true).c_str()); return false; } @@ -1553,17 +1647,15 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1)) { - TC_LOG_ERROR("sql.sql", "Aura condition has non existing spell (Id: %d), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing spell (Id: %d), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (cond->ConditionValue2 > EFFECT_2) { - TC_LOG_ERROR("sql.sql", "Aura condition has non existing effect index (%u) (must be 0..2), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has non existing effect index (%u) (must be 0..2), skipped.", cond->ToString(true).c_str(), cond->ConditionValue2); return false; } - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Aura condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_ITEM: @@ -1571,13 +1663,13 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1); if (!proto) { - TC_LOG_ERROR("sql.sql", "Item condition has non existing item (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s Item (%u) does not exist, skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (!cond->ConditionValue2) { - TC_LOG_ERROR("sql.sql", "Item condition has 0 set for item count in value2 (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s Zero item count in ConditionValue2, skipped.", cond->ToString(true).c_str()); return false; } break; @@ -1587,14 +1679,9 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1); if (!proto) { - TC_LOG_ERROR("sql.sql", "ItemEquipped condition has non existing item (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s Item (%u) does not exist, skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "ItemEquipped condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "ItemEquipped condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_ZONEID: @@ -1602,20 +1689,15 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->ConditionValue1); if (!areaEntry) { - TC_LOG_ERROR("sql.sql", "ZoneID condition has non existing area (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s Area (%u) does not exist, skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (areaEntry->zone != 0) { - TC_LOG_ERROR("sql.sql", "ZoneID condition requires to be in area (%u) which is a subzone but zone expected, skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s requires to be in area (%u) which is a subzone but zone expected, skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "ZoneID condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "ZoneID condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_REPUTATION_RANK: @@ -1623,25 +1705,18 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->ConditionValue1); if (!factionEntry) { - TC_LOG_ERROR("sql.sql", "Reputation condition has non existing faction (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing faction (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Reputation condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_TEAM: { if (cond->ConditionValue1 != ALLIANCE && cond->ConditionValue1 != HORDE) { - TC_LOG_ERROR("sql.sql", "Team condition specifies unknown team (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s specifies unknown team (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "Team condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Team condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_SKILL: @@ -1649,17 +1724,15 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(cond->ConditionValue1); if (!pSkill) { - TC_LOG_ERROR("sql.sql", "Skill condition specifies non-existing skill (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s specifies non-existing skill (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (cond->ConditionValue2 < 1 || cond->ConditionValue2 > sWorld->GetConfigMaxSkillValue()) { - TC_LOG_ERROR("sql.sql", "Skill condition specifies skill (%u) with invalid value (%u), skipped", cond->ConditionValue1, cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s specifies skill (%u) with invalid value (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1, cond->ConditionValue2); return false; } - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Skill condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_QUESTREWARDED: @@ -1669,30 +1742,19 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (!sObjectMgr->GetQuestTemplate(cond->ConditionValue1)) { - TC_LOG_ERROR("sql.sql", "Quest condition (Type: %u) points to non-existing quest (%u) for Source Entry %u. SourceGroup: %u, SourceTypeOrReferenceId: %u", - cond->ConditionType, cond->ConditionValue1, cond->SourceEntry, cond->SourceGroup, cond->SourceType); + TC_LOG_ERROR("sql.sql", "%s points to non-existing quest (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - - if (cond->ConditionValue2 > 1) - TC_LOG_ERROR("sql.sql", "Quest condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Quest condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_ACTIVE_EVENT: { GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); - if (cond->ConditionValue1 >=events.size() || !events[cond->ConditionValue1].isValid()) + if (cond->ConditionValue1 >= events.size() || !events[cond->ConditionValue1].isValid()) { - TC_LOG_ERROR("sql.sql", "ActiveEvent condition has non existing event id (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing event id (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "ActiveEvent condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "ActiveEvent condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_ACHIEVEMENT: @@ -1700,56 +1762,36 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) AchievementEntry const* achievement = sAchievementMgr->GetAchievement(cond->ConditionValue1); if (!achievement) { - TC_LOG_ERROR("sql.sql", "Achivement condition has non existing achivement id (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing achivement id (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "Achivement condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Achivement condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_CLASS: { if (!(cond->ConditionValue1 & CLASSMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Class condition has non existing classmask (%u), skipped", cond->ConditionValue1 & ~CLASSMASK_ALL_PLAYABLE); + TC_LOG_ERROR("sql.sql", "%s has non existing classmask (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1 & ~CLASSMASK_ALL_PLAYABLE); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "Class condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Class condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_RACE: { if (!(cond->ConditionValue1 & RACEMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Race condition has non existing racemask (%u), skipped", cond->ConditionValue1 & ~RACEMASK_ALL_PLAYABLE); + TC_LOG_ERROR("sql.sql", "%s has non existing racemask (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1 & ~RACEMASK_ALL_PLAYABLE); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "Race condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Race condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_GENDER: { if (!Player::IsValidGender(uint8(cond->ConditionValue1))) { - TC_LOG_ERROR("sql.sql", "Gender condition has invalid gender (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has invalid gender (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "Gender condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Gender condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_MAPID: @@ -1757,77 +1799,54 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) MapEntry const* me = sMapStore.LookupEntry(cond->ConditionValue1); if (!me) { - TC_LOG_ERROR("sql.sql", "Map condition has non existing map (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing map (%u), skipped", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "Map condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Map condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_SPELL: { if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1)) { - TC_LOG_ERROR("sql.sql", "Spell condition has non existing spell (Id: %d), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing spell (Id: %d), skipped", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "Spell condition has useless data (spell Id: %d) in value2 (%u)!", cond->ConditionValue1, cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Spell condition has useless data (spell Id: %d) in value3 (%u)!", cond->ConditionValue1, cond->ConditionValue3); break; } case CONDITION_LEVEL: { if (cond->ConditionValue2 >= COMP_TYPE_MAX) { - TC_LOG_ERROR("sql.sql", "Level condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has invalid ComparisionType (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue2); return false; } - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Level condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_DRUNKENSTATE: { if (cond->ConditionValue1 > DRUNKEN_SMASHED) { - TC_LOG_ERROR("sql.sql", "DrunkState condition has invalid state (%u), skipped", cond->ConditionValue1); - return false; - } - if (cond->ConditionValue2) - { - TC_LOG_ERROR("sql.sql", "DrunkState condition has useless data in value2 (%u)!", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has invalid state (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "DrunkState condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_NEAR_CREATURE: { if (!sObjectMgr->GetCreatureTemplate(cond->ConditionValue1)) { - TC_LOG_ERROR("sql.sql", "NearCreature condition has non existing creature template entry (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing creature template entry (%u), skipped", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "NearCreature condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_NEAR_GAMEOBJECT: { if (!sObjectMgr->GetGameObjectTemplate(cond->ConditionValue1)) { - TC_LOG_ERROR("sql.sql", "NearGameObject condition has non existing gameobject template entry (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing gameobject template entry (%u), skipped.", cond->ToString().c_str(), cond->ConditionValue1); return false; } - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "NearGameObject condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_OBJECT_ENTRY_GUID: @@ -1837,7 +1856,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) case TYPEID_UNIT: if (cond->ConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->ConditionValue2)) { - TC_LOG_ERROR("sql.sql", "ObjectEntryGuid condition has non existing creature template entry (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has non existing creature template entry (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue2); return false; } if (cond->ConditionValue3) @@ -1846,13 +1865,13 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (cond->ConditionValue2 && creatureData->id != cond->ConditionValue2) { - TC_LOG_ERROR("sql.sql", "ObjectEntryGuid condition has guid %u set but does not match creature entry (%u), skipped", cond->ConditionValue3, cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has guid %u set but does not match creature entry (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue3, cond->ConditionValue2); return false; } } else { - TC_LOG_ERROR("sql.sql", "ObjectEntryGuid condition has non existing creature guid (%u), skipped", cond->ConditionValue3); + TC_LOG_ERROR("sql.sql", "%s has non existing creature guid (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue3); return false; } } @@ -1860,7 +1879,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) case TYPEID_GAMEOBJECT: if (cond->ConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->ConditionValue2)) { - TC_LOG_ERROR("sql.sql", "ObjectEntryGuid condition has non existing gameobject template entry (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has non existing gameobject template entry (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue2); return false; } if (cond->ConditionValue3) @@ -1869,13 +1888,13 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (cond->ConditionValue2 && goData->id != cond->ConditionValue2) { - TC_LOG_ERROR("sql.sql", "ObjectEntryGuid condition has guid %u set but does not match gameobject entry (%u), skipped", cond->ConditionValue3, cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has guid %u set but does not match gameobject entry (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue3, cond->ConditionValue2); return false; } } else { - TC_LOG_ERROR("sql.sql", "ObjectEntryGuid condition has non existing gameobject guid (%u), skipped", cond->ConditionValue3); + TC_LOG_ERROR("sql.sql", "%s has non existing gameobject guid (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue3); return false; } } @@ -1883,12 +1902,12 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) case TYPEID_PLAYER: case TYPEID_CORPSE: if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "ObjectEntryGuid condition has useless data in value2 (%u)!", cond->ConditionValue2); + LogUselessConditionValue(cond, 2, cond->ConditionValue2); if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "ObjectEntryGuid condition has useless data in value3 (%u)!", cond->ConditionValue3); + LogUselessConditionValue(cond, 3, cond->ConditionValue3); break; default: - TC_LOG_ERROR("sql.sql", "ObjectEntryGuid condition has wrong typeid set (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has wrong typeid set (%u), skipped", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } break; @@ -1897,51 +1916,45 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (!cond->ConditionValue1 || (cond->ConditionValue1 & ~(TYPEMASK_UNIT | TYPEMASK_PLAYER | TYPEMASK_GAMEOBJECT | TYPEMASK_CORPSE))) { - TC_LOG_ERROR("sql.sql", "TypeMask condition has invalid typemask set (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has invalid typemask set (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue2); return false; } - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "TypeMask condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "TypeMask condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_RELATION_TO: { if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets()) { - TC_LOG_ERROR("sql.sql", "RelationTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has invalid ConditionValue1(ConditionTarget selection) (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (cond->ConditionValue1 == cond->ConditionTarget) { - TC_LOG_ERROR("sql.sql", "RelationTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has ConditionValue1(ConditionTarget selection) set to self (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (cond->ConditionValue2 >= RELATION_MAX) { - TC_LOG_ERROR("sql.sql", "RelationTo condition has invalid ConditionValue2(RelationType) (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has invalid ConditionValue2(RelationType) (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue2); return false; } - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "RelationTo condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_REACTION_TO: { if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets()) { - TC_LOG_ERROR("sql.sql", "ReactionTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has invalid ConditionValue1(ConditionTarget selection) (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (cond->ConditionValue1 == cond->ConditionTarget) { - TC_LOG_ERROR("sql.sql", "ReactionTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has ConditionValue1(ConditionTarget selection) set to self (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (!cond->ConditionValue2) { - TC_LOG_ERROR("sql.sql", "mConditionValue2 condition has invalid ConditionValue2(rankMask) (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has invalid ConditionValue2(rankMask) (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue2); return false; } break; @@ -1950,78 +1963,55 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets()) { - TC_LOG_ERROR("sql.sql", "DistanceTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has invalid ConditionValue1(ConditionTarget selection) (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (cond->ConditionValue1 == cond->ConditionTarget) { - TC_LOG_ERROR("sql.sql", "DistanceTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has ConditionValue1(ConditionTarget selection) set to self (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (cond->ConditionValue3 >= COMP_TYPE_MAX) { - TC_LOG_ERROR("sql.sql", "DistanceTo condition has invalid ComparisionType (%u), skipped", cond->ConditionValue3); + TC_LOG_ERROR("sql.sql", "%s has invalid ComparisionType (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue3); return false; } break; } - case CONDITION_ALIVE: - { - if (cond->ConditionValue1) - TC_LOG_ERROR("sql.sql", "Alive condition has useless data in value1 (%u)!", cond->ConditionValue1); - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "Alive condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Alive condition has useless data in value3 (%u)!", cond->ConditionValue3); - break; - } case CONDITION_HP_VAL: { if (cond->ConditionValue2 >= COMP_TYPE_MAX) { - TC_LOG_ERROR("sql.sql", "HpVal condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has invalid ComparisionType (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue2); return false; } if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "HpVal condition has useless data in value3 (%u)!", cond->ConditionValue3); + TC_LOG_ERROR("sql.sql", "%s has useless data in value3 (%u)!", cond->ToString(true).c_str(), cond->ConditionValue3); break; } case CONDITION_HP_PCT: { if (cond->ConditionValue1 > 100) { - TC_LOG_ERROR("sql.sql", "HpPct condition has too big percent value (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has too big percent value (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } if (cond->ConditionValue2 >= COMP_TYPE_MAX) { - TC_LOG_ERROR("sql.sql", "HpPct condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR("sql.sql", "%s has invalid ComparisionType (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue2); return false; } if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "HpPct condition has useless data in value3 (%u)!", cond->ConditionValue3); + TC_LOG_ERROR("sql.sql", "%s has useless data in value3 (%u)!", cond->ToString().c_str(), cond->ConditionValue3); break; } - case CONDITION_AREAID: - case CONDITION_INSTANCE_INFO: - break; case CONDITION_WORLD_STATE: { if (!sWorld->getWorldState(cond->ConditionValue1)) { - TC_LOG_ERROR("sql.sql", "World state condition has non existing world state in value1 (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing world state in value1 (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "World state condition has useless data in value3 (%u)!", cond->ConditionValue3); - break; - } - case CONDITION_PHASEMASK: - { - if (cond->ConditionValue2) - TC_LOG_ERROR("sql.sql", "Phasemask condition has useless data in value2 (%u)!", cond->ConditionValue2); - if (cond->ConditionValue3) - TC_LOG_ERROR("sql.sql", "Phasemask condition has useless data in value3 (%u)!", cond->ConditionValue3); break; } case CONDITION_TITLE: @@ -2029,7 +2019,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(cond->ConditionValue1); if (!titleEntry) { - TC_LOG_ERROR("sql.sql", "Title condition has non existing title in value1 (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing title in value1 (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } break; @@ -2038,7 +2028,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (cond->ConditionValue1 > SPAWNMASK_RAID_ALL) { - TC_LOG_ERROR("sql.sql", "SpawnMask condition has non existing SpawnMask in value1 (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing SpawnMask in value1 (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } break; @@ -2047,7 +2037,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (!(cond->ConditionValue1 & UNIT_STATE_ALL_STATE_SUPPORTED)) { - TC_LOG_ERROR("sql.sql", "UnitState condition has non existing UnitState in value1 (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing UnitState in value1 (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } break; @@ -2056,17 +2046,35 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (!cond->ConditionValue1 || cond->ConditionValue1 > CREATURE_TYPE_GAS_CLOUD) { - TC_LOG_ERROR("sql.sql", "CreatureType condition has non existing CreatureType in value1 (%u), skipped", cond->ConditionValue1); + TC_LOG_ERROR("sql.sql", "%s has non existing CreatureType in value1 (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1); return false; } break; } + case CONDITION_INSTANCE_INFO: + case CONDITION_AREAID: + case CONDITION_PHASEMASK: + case CONDITION_ALIVE: + break; default: break; } + + if (cond->ConditionValue1 && !StaticConditionTypeData[cond->ConditionType].HasConditionValue1) + LogUselessConditionValue(cond, 1, cond->ConditionValue1); + if (cond->ConditionValue2 && !StaticConditionTypeData[cond->ConditionType].HasConditionValue2) + LogUselessConditionValue(cond, 2, cond->ConditionValue2); + if (cond->ConditionValue3 && !StaticConditionTypeData[cond->ConditionType].HasConditionValue3) + LogUselessConditionValue(cond, 3, cond->ConditionValue3); + return true; } +void ConditionMgr::LogUselessConditionValue(Condition* cond, uint8 index, uint32 value) +{ + TC_LOG_ERROR("sql.sql", "%s has useless data in ConditionValue%u (%u)!", cond->ToString(true).c_str(), index, value); +} + void ConditionMgr::Clean() { for (ConditionReferenceContainer::iterator itr = ConditionReferenceStore.begin(); itr != ConditionReferenceStore.end(); ++itr) diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index 24e44c662ba..621da355b7b 100644 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -210,6 +210,8 @@ struct Condition uint32 GetSearcherTypeMaskForCondition(); bool isLoaded() const { return ConditionType > CONDITION_NONE || ReferenceId; } uint32 GetMaxAvailableConditionTargets(); + + std::string ToString(bool ext = false) const; /// For logging purpose }; typedef std::list<Condition*> ConditionList; @@ -228,7 +230,6 @@ class ConditionMgr ~ConditionMgr(); public: - static ConditionMgr* instance() { static ConditionMgr instance; @@ -243,14 +244,24 @@ class ConditionMgr bool IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions); bool IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions); bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions); - bool CanHaveSourceGroupSet(ConditionSourceType sourceType) const; - bool CanHaveSourceIdSet(ConditionSourceType sourceType) const; + static bool CanHaveSourceGroupSet(ConditionSourceType sourceType); + static bool CanHaveSourceIdSet(ConditionSourceType sourceType); ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry); ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId); ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType); ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId); ConditionList GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId); + struct ConditionTypeInfo + { + char const* Name; + bool HasConditionValue1; + bool HasConditionValue2; + bool HasConditionValue3; + }; + static char const* StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX]; + static ConditionTypeInfo const StaticConditionTypeData[CONDITION_MAX]; + private: bool isSourceTypeValid(Condition* cond); bool addToLootTemplate(Condition* cond, LootTemplate* loot); @@ -259,6 +270,8 @@ class ConditionMgr bool addToSpellImplicitTargetConditions(Condition* cond); bool IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions); + static void LogUselessConditionValue(Condition* cond, uint8 index, uint32 value); + void Clean(); // free up resources std::list<Condition*> AllocatedMemoryStore; // some garbage collection :) diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 4ffddde021c..6702815870f 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -607,7 +607,7 @@ void Object::_LoadIntoDataField(std::string const& data, uint32 startOffset, uin for (uint32 index = 0; index < count; ++index) { - m_uint32Values[startOffset + index] = atol(tokens[index]); + m_uint32Values[startOffset + index] = atoul(tokens[index]); _changesMask.SetBit(startOffset + index); } } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 8a45c1c6420..b8abc33f675 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -203,7 +203,7 @@ void PlayerTaxi::LoadTaxiMask(std::string const &data) for (Tokenizer::const_iterator iter = tokens.begin(); index < TaxiMaskSize && iter != tokens.end(); ++iter, ++index) { // load and set bits only for existing taxi nodes - m_taximask[index] = sTaxiNodesMask[index] & uint32(atol(*iter)); + m_taximask[index] = sTaxiNodesMask[index] & atoul(*iter); } } @@ -229,7 +229,7 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, uint3 for (Tokenizer::const_iterator iter = Tokenizer.begin(); iter != Tokenizer.end(); ++iter) { - uint32 node = uint32(atol(*iter)); + uint32 node = atoul(*iter); AddTaxiDestination(node); } @@ -15483,12 +15483,13 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, void Player::FailQuest(uint32 questId) { - // Already complete quests shouldn't turn failed. - if (GetQuestStatus(questId) == QUEST_STATUS_COMPLETE) - return; if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { + // Already complete quests shouldn't turn failed. + if (GetQuestStatus(questId) == QUEST_STATUS_COMPLETE && !quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)) + return; + SetQuestStatus(questId, QUEST_STATUS_FAILED); uint16 log_slot = FindQuestSlot(questId); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 9a4b7a347c8..beac32b0145 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13852,7 +13852,7 @@ void CharmInfo::LoadPetActionBar(const std::string& data) // use unsigned cast to avoid sign negative format use at long-> ActiveStates (int) conversion ActiveStates type = ActiveStates(atol(*iter)); ++iter; - uint32 action = uint32(atol(*iter)); + uint32 action = atoul(*iter); PetActionBar[index].SetActionAndType(action, type); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 9e31e901189..8dc117b3362 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -556,17 +556,17 @@ void ObjectMgr::LoadCreatureTemplateAddons() creatureAddon.auras.resize(tokens.size()); for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) { - SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(uint32(atol(*itr))); + SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(atoul(*itr)); if (!AdditionalSpellInfo) { - TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has wrong spell %u defined in `auras` field in `creature_template_addon`.", entry, uint32(atol(*itr))); + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has wrong spell %lu defined in `auras` field in `creature_template_addon`.", entry, atoul(*itr)); continue; } if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) - TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_template_addon`.", entry, uint32(atol(*itr))); + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_template_addon`.", entry, atoul(*itr)); - creatureAddon.auras[i++] = uint32(atol(*itr)); + creatureAddon.auras[i++] = atoul(*itr); } if (creatureAddon.mount) @@ -1004,17 +1004,17 @@ void ObjectMgr::LoadCreatureAddons() creatureAddon.auras.resize(tokens.size()); for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) { - SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(uint32(atol(*itr))); + SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(atoul(*itr)); if (!AdditionalSpellInfo) { - TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has wrong spell %u defined in `auras` field in `creature_addon`.", guid, uint32(atol(*itr))); + TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has wrong spell %lu defined in `auras` field in `creature_addon`.", guid, atoul(*itr)); continue; } if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) - TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_addon`.", guid, uint32(atol(*itr))); + TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_addon`.", guid, atoul(*itr)); - creatureAddon.auras[i++] = uint32(atol(*itr)); + creatureAddon.auras[i++] = atoul(*itr); } if (creatureAddon.mount) @@ -5673,35 +5673,32 @@ void ObjectMgr::LoadAreaTriggerScripts() uint32 oldMSTime = getMSTime(); _areaTriggerScriptStore.clear(); // need for reload case - QueryResult result = WorldDatabase.Query("SELECT entry, ScriptName FROM areatrigger_scripts"); + QueryResult result = WorldDatabase.Query("SELECT entry, ScriptName FROM areatrigger_scripts"); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 areatrigger scripts. DB table `areatrigger_scripts` is empty."); return; } - uint32 count = 0; - do { - ++count; - Field* fields = result->Fetch(); - uint32 Trigger_ID = fields[0].GetUInt32(); - const char *scriptName = fields[1].GetCString(); + uint32 triggerId = fields[0].GetUInt32(); + char const* scriptName = fields[1].GetCString(); - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(triggerId); if (!atEntry) { - TC_LOG_ERROR("sql.sql", "Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.", Trigger_ID); + TC_LOG_ERROR("sql.sql", "AreaTrigger (ID: %u) does not exist in `AreaTrigger.dbc`.", triggerId); continue; } - _areaTriggerScriptStore[Trigger_ID] = GetScriptId(scriptName); - } while (result->NextRow()); + _areaTriggerScriptStore[triggerId] = GetScriptId(scriptName); + } + while (result->NextRow()); - TC_LOG_INFO("server.loading", ">> Loaded %u areatrigger scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " areatrigger scripts in %u ms", _areaTriggerScriptStore.size(), GetMSTimeDiffToNow(oldMSTime)); } uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 team) @@ -8544,31 +8541,32 @@ void ObjectMgr::LoadScriptNames() { uint32 oldMSTime = getMSTime(); - _scriptNamesStore.push_back(""); + _scriptNamesStore.emplace_back(""); + QueryResult result = WorldDatabase.Query( - "SELECT DISTINCT(ScriptName) FROM achievement_criteria_data WHERE ScriptName <> '' AND type = 11 " - "UNION " - "SELECT DISTINCT(ScriptName) FROM battleground_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM spell_script_names WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM transports WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM game_weather WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM conditions WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM outdoorpvp_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); + "SELECT DISTINCT(ScriptName) FROM achievement_criteria_data WHERE ScriptName <> '' AND type = 11 " + "UNION " + "SELECT DISTINCT(ScriptName) FROM battleground_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM spell_script_names WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM transports WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM game_weather WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM conditions WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM outdoorpvp_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); if (!result) { @@ -8576,20 +8574,23 @@ void ObjectMgr::LoadScriptNames() return; } - uint32 count = 1; - do { - _scriptNamesStore.push_back((*result)[0].GetString()); - ++count; + _scriptNamesStore.emplace_back((*result)[0].GetCString()); } while (result->NextRow()); std::sort(_scriptNamesStore.begin(), _scriptNamesStore.end()); - TC_LOG_INFO("server.loading", ">> Loaded %d Script Names in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + +#ifdef SCRIPTS + for (size_t i = 1; i < _scriptNamesStore.size(); ++i) + UnusedScriptNames.push_back(_scriptNamesStore[i]); +#endif + + TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " ScriptNames in %u ms", _scriptNamesStore.size(), GetMSTimeDiffToNow(oldMSTime)); } -uint32 ObjectMgr::GetScriptId(const char *name) +uint32 ObjectMgr::GetScriptId(char const* name) { // use binary search to find the script name in the sorted vector // assume "" is the first element diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 62303143202..7504f03868e 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1253,9 +1253,8 @@ class ObjectMgr bool IsVendorItemValid(uint32 vendor_entry, uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* player = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const; void LoadScriptNames(); - ScriptNameContainer &GetScriptNames() { return _scriptNamesStore; } - const char * GetScriptName(uint32 id) const { return id < _scriptNamesStore.size() ? _scriptNamesStore[id].c_str() : ""; } - uint32 GetScriptId(const char *name); + char const* GetScriptName(uint32 id) const { return id < _scriptNamesStore.size() ? _scriptNamesStore[id].c_str() : ""; } + uint32 GetScriptId(char const* name); SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const { diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 18cd5d5bd06..7e218b601e0 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -2004,7 +2004,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) } for (uint32 index = 0; index < ktcount; ++index) - knownTitles[index] = atol(tokens[index]); + knownTitles[index] = atoul(tokens[index]); for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeTitles.begin(); it != sObjectMgr->FactionChangeTitles.end(); ++it) { diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index 1e6dc1adbb9..9bee32a95e6 100644 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -42,14 +42,6 @@ enum CharterItemIDs ARENA_TEAM_CHARTER_5v5 = 23562 }; -enum CharterCosts -{ - GUILD_CHARTER_COST = 1000, - ARENA_TEAM_CHARTER_2v2_COST = 800000, - ARENA_TEAM_CHARTER_3v3_COST = 1200000, - ARENA_TEAM_CHARTER_5v5_COST = 2000000 -}; - void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_BUY"); @@ -106,7 +98,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) return; charterid = GUILD_CHARTER; - cost = GUILD_CHARTER_COST; + cost = sWorld->getIntConfig(CONFIG_CHARTER_COST_GUILD); type = GUILD_CHARTER_TYPE; } else @@ -122,17 +114,17 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) { case 1: charterid = ARENA_TEAM_CHARTER_2v2; - cost = ARENA_TEAM_CHARTER_2v2_COST; + cost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_2v2); type = ARENA_TEAM_CHARTER_2v2_TYPE; break; case 2: charterid = ARENA_TEAM_CHARTER_3v3; - cost = ARENA_TEAM_CHARTER_3v3_COST; + cost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_3v3); type = ARENA_TEAM_CHARTER_3v3_TYPE; break; case 3: charterid = ARENA_TEAM_CHARTER_5v5; - cost = ARENA_TEAM_CHARTER_5v5_COST; + cost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_5v5); type = ARENA_TEAM_CHARTER_5v5_TYPE; break; default: @@ -945,7 +937,7 @@ void WorldSession::SendPetitionShowList(ObjectGuid guid) data << uint32(1); // index data << uint32(GUILD_CHARTER); // charter entry data << uint32(CHARTER_DISPLAY_ID); // charter display id - data << uint32(GUILD_CHARTER_COST); // charter cost + data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_GUILD)); // charter cost data << uint32(0); // unknown data << uint32(sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS)); // required signs } @@ -956,21 +948,21 @@ void WorldSession::SendPetitionShowList(ObjectGuid guid) data << uint32(1); // index data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry data << uint32(CHARTER_DISPLAY_ID); // charter display id - data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost + data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_2v2)); // charter cost data << uint32(2); // unknown data << uint32(2); // required signs? // 3v3 data << uint32(2); // index data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry data << uint32(CHARTER_DISPLAY_ID); // charter display id - data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost + data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_3v3)); // charter cost data << uint32(3); // unknown data << uint32(3); // required signs? // 5v5 data << uint32(3); // index data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry data << uint32(CHARTER_DISPLAY_ID); // charter display id - data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost + data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_5v5)); // charter cost data << uint32(5); // unknown data << uint32(5); // required signs? } diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index 4b032199604..8949b161e7b 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -676,7 +676,9 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) return; } - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && pOther->GetTeam() !=_player->GetTeam()) + if (pOther->GetTeam() != _player->GetTeam() && + (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && + !GetPlayer()->GetSession()->HasPermission(rbac::RBAC_PERM_ALLOW_TWO_SIDE_TRADE))) { info.Status = TRADE_STATUS_WRONG_FACTION; SendTradeStatus(info); diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 88ee153423f..77d3d3ffe0b 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -128,7 +128,7 @@ void InstanceScript::LoadObjectData(ObjectData const* creatureData, ObjectData c if (gameObjectData) LoadObjectData(gameObjectData, _gameObjectInfo); - TC_LOG_ERROR("scripts", "InstanceScript::LoadObjectData: " SZFMTD " objects loaded.", _creatureInfo.size() + _gameObjectInfo.size()); + TC_LOG_DEBUG("scripts", "InstanceScript::LoadObjectData: " SZFMTD " objects loaded.", _creatureInfo.size() + _gameObjectInfo.size()); } void InstanceScript::LoadObjectData(ObjectData const* data, ObjectInfoMap& objectInfo) diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 2e859a7a56f..33d93ee1384 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -56,12 +56,12 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature) Trinity::NormalizeMapCoord(destX); Trinity::NormalizeMapCoord(destY); - travelDistZ = distanceX*distanceX + distanceY*distanceY; + travelDistZ = range; // sin^2+cos^2=1, so travelDistZ=range^2; no need for sqrt below if (is_air_ok) // 3D system above ground and above water (flying mode) { // Limit height change - const float distanceZ = float(rand_norm()) * std::sqrt(travelDistZ)/2.0f; + const float distanceZ = float(rand_norm()) * travelDistZ/2.0f; destZ = respZ + distanceZ; float levelZ = map->GetWaterOrGroundLevel(destX, destY, destZ-2.0f); @@ -73,7 +73,7 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature) else // 2D only { // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE) - travelDistZ = travelDistZ >= 100.0f ? 10.0f : std::sqrt(travelDistZ); + travelDistZ = travelDistZ >= 10.0f ? 10.0f : travelDistZ; // The fastest way to get an accurate result 90% of the time. // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index be0bf1aa067..d1ebcba118d 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -34,6 +34,12 @@ #include "WorldPacket.h" #include "WorldSession.h" +// namespace +// { + UnusedScriptContainer UnusedScripts; + UnusedScriptNamesContainer UnusedScriptNames; +// } + // This is the global static registry of scripts. template<class TScript> class ScriptRegistry @@ -89,6 +95,12 @@ class ScriptRegistry { ScriptPointerList[id] = script; sScriptMgr->IncrementScriptCount(); + + #ifdef SCRIPTS + UnusedScriptNamesContainer::iterator itr = std::lower_bound(UnusedScriptNames.begin(), UnusedScriptNames.end(), script->GetName()); + if (itr != UnusedScriptNames.end() && *itr == script->GetName()) + UnusedScriptNames.erase(itr); + #endif } else { @@ -106,8 +118,7 @@ class ScriptRegistry // Avoid calling "delete script;" because we are currently in the script constructor // In a valid scenario this will not happen because every script has a name assigned in the database - // If that happens, it's acceptable to just leak a few bytes - + UnusedScripts.push_back(script); return; } } @@ -189,6 +200,15 @@ void ScriptMgr::Initialize() FillSpellSummary(); AddScripts(); +#ifdef SCRIPTS + for (std::string const& scriptName : UnusedScriptNames) + { + TC_LOG_ERROR("sql.sql", "ScriptName '%s' exists in database, but no core script found!", scriptName.c_str()); + } +#endif + + UnloadUnusedScripts(); + TC_LOG_INFO("server.loading", ">> Loaded %u C++ scripts in %u ms", GetScriptCount(), GetMSTimeDiffToNow(oldMSTime)); } @@ -229,10 +249,19 @@ void ScriptMgr::Unload() #undef SCR_CLEAR + UnloadUnusedScripts(); + delete[] SpellSummary; delete[] UnitAI::AISpellInfo; } +void ScriptMgr::UnloadUnusedScripts() +{ + for (size_t i = 0; i < UnusedScripts.size(); ++i) + delete UnusedScripts[i]; + UnusedScripts.clear(); +} + void ScriptMgr::LoadDatabase() { sScriptSystemMgr->LoadScriptWaypoints(); diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index f6e76763f95..6a4e2f9910a 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -873,6 +873,15 @@ class GroupScript : public ScriptObject // Placed here due to ScriptRegistry::AddScript dependency. #define sScriptMgr ScriptMgr::instance() +// namespace +// { + typedef std::vector<ScriptObject*> UnusedScriptContainer; + typedef std::list<std::string> UnusedScriptNamesContainer; + + extern UnusedScriptContainer UnusedScripts; + extern UnusedScriptNamesContainer UnusedScriptNames; +// } + // Manages registration, loading, and execution of scripts. class ScriptMgr { @@ -901,6 +910,7 @@ class ScriptMgr public: /* Unloading */ void Unload(); + void UnloadUnusedScripts(); public: /* SpellScriptLoader */ diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 69297d32105..609617f0478 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -284,11 +284,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) while (m_Socket && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater)) { - if (!AntiDOS.EvaluateOpcode(*packet, currentTime)) - { - KickPlayer(); - } - else if (packet->GetOpcode() >= NUM_MSG_TYPES) + if (packet->GetOpcode() >= NUM_MSG_TYPES) { TC_LOG_ERROR("network.opcode", "Received non-existed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() , GetPlayerInfo().c_str()); @@ -320,7 +316,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) "Player is currently not in world yet.", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()); } } - else if (_player->IsInWorld()) + else if (_player->IsInWorld() && AntiDOS.EvaluateOpcode(*packet, currentTime)) { sScriptMgr->OnPacketReceive(this, *packet); (this->*opHandle.handler)(*packet); @@ -332,7 +328,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT", "the player has not logged in yet and not recently logout"); - else + else if (AntiDOS.EvaluateOpcode(*packet, currentTime)) { // not expected _player or must checked in packet handler sScriptMgr->OnPacketReceive(this, *packet); @@ -345,7 +341,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet"); else if (_player->IsInWorld()) LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world"); - else + else if(AntiDOS.EvaluateOpcode(*packet, currentTime)) { sScriptMgr->OnPacketReceive(this, *packet); (this->*opHandle.handler)(*packet); @@ -365,9 +361,12 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (packet->GetOpcode() == CMSG_CHAR_ENUM) m_playerRecentlyLogout = false; - sScriptMgr->OnPacketReceive(this, *packet); - (this->*opHandle.handler)(*packet); - LogUnprocessedTail(packet); + if (AntiDOS.EvaluateOpcode(*packet, currentTime)) + { + sScriptMgr->OnPacketReceive(this, *packet); + (this->*opHandle.handler)(*packet); + LogUnprocessedTail(packet); + } break; case STATUS_NEVER: TC_LOG_ERROR("network.opcode", "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() @@ -1262,8 +1261,11 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co case POLICY_LOG: return true; case POLICY_KICK: + { TC_LOG_INFO("network", "AntiDOS: Player kicked!"); + Session->KickPlayer(); return false; + } case POLICY_BAN: { BanMode bm = (BanMode)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANMODE); @@ -1277,7 +1279,7 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co } sWorld->BanAccount(bm, nameOrIp, duration, "DOS (Packet Flooding/Spoofing", "Server: AutoDOS"); TC_LOG_INFO("network", "AntiDOS: Player automatically banned for %u seconds.", duration); - + Session->KickPlayer(); return false; } default: // invalid policy diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 311182291c5..e8e1bbd8ff4 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3438,7 +3438,7 @@ void Spell::SendSpellCooldown() { // Handle pet cooldowns here if needed instead of in PetAI to avoid hidden cooldown restarts Creature* _creature = m_caster->ToCreature(); - if (_creature && _creature->IsPet()) + if (_creature && (_creature->IsPet() || _creature->IsGuardian())) _creature->AddCreatureSpellCooldown(m_spellInfo->Id); return; @@ -7043,6 +7043,19 @@ bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMo return preventDefault; } +void Spell::CallScriptSuccessfulDispel(SpellEffIndex effIndex) +{ + for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + { + (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_EFFECT_SUCCESSFUL_DISPEL); + std::list<SpellScript::EffectHandler>::iterator hookItrEnd = (*scritr)->OnEffectSuccessfulDispel.end(), hookItr = (*scritr)->OnEffectSuccessfulDispel.begin(); + for (; hookItr != hookItrEnd; ++hookItr) + hookItr->Call(*scritr, effIndex); + + (*scritr)->_FinishScriptCall(); + } +} + void Spell::CallScriptBeforeHitHandlers() { for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 6e0a5fc9d3e..c219a497eb9 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -644,6 +644,7 @@ class Spell SpellCastResult CallScriptCheckCastHandlers(); void PrepareScriptHitHandlers(); bool CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMode mode); + void CallScriptSuccessfulDispel(SpellEffIndex effIndex); void CallScriptBeforeHitHandlers(); void CallScriptOnHitHandlers(); void CallScriptAfterHitHandlers(); diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 8ab3a72b47e..fccdea7fde1 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -310,6 +310,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 `OnEffectHitTarget` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + for (std::list<EffectHandler>::iterator itr = OnEffectSuccessfulDispel.begin(); itr != OnEffectSuccessfulDispel.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 `OnEffectSuccessfulDispel` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + for (std::list<ObjectAreaTargetSelectHandler>::iterator itr = OnObjectAreaTargetSelect.begin(); itr != OnObjectAreaTargetSelect.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 `OnObjectAreaTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 653ae9ab5e9..c606cb91de3 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -130,6 +130,7 @@ enum SpellScriptHookType SPELL_SCRIPT_HOOK_EFFECT_LAUNCH_TARGET, SPELL_SCRIPT_HOOK_EFFECT_HIT, SPELL_SCRIPT_HOOK_EFFECT_HIT_TARGET, + SPELL_SCRIPT_HOOK_EFFECT_SUCCESSFUL_DISPEL, SPELL_SCRIPT_HOOK_BEFORE_HIT, SPELL_SCRIPT_HOOK_HIT, SPELL_SCRIPT_HOOK_AFTER_HIT, @@ -292,6 +293,7 @@ class SpellScript : public _SpellScript HookList<EffectHandler> OnEffectLaunchTarget; HookList<EffectHandler> OnEffectHit; HookList<EffectHandler> OnEffectHitTarget; + HookList<EffectHandler> OnEffectSuccessfulDispel; #define SpellEffectFn(F, I, N) EffectHandlerFunction(&F, I, N) // example: BeforeHit += SpellHitFn(class::function); @@ -334,6 +336,9 @@ class SpellScript : public _SpellScript // 11. OnHit - executed just before spell deals damage and procs auras - when spell hits target - called for each target from spell target map // 12. AfterHit - executed just after spell finishes all it's jobs for target - called for each target from spell target map + // this hook is only executed after a successful dispel of any aura + // OnEffectSuccessfulDispel - executed just after effect successfully dispelled aura(s) + // // methods allowing interaction with Spell object // diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index 584331ad393..136f8aab22c 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -527,10 +527,10 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s if (!changenth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); - race = uint8(atol(getnth(line, 4).c_str())); - playerClass = uint8(atol(getnth(line, 5).c_str())); - gender = uint8(atol(getnth(line, 6).c_str())); - level = uint8(atol(getnth(line, 7).c_str())); + race = uint8(atoul(getnth(line, 4).c_str())); + playerClass = uint8(atoul(getnth(line, 5).c_str())); + gender = uint8(atoul(getnth(line, 6).c_str())); + level = uint8(atoul(getnth(line, 7).c_str())); if (name.empty()) { // check if the original name already exists diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 47dd37936aa..de191774b77 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -692,6 +692,11 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_MIN_PET_NAME] = 2; } + m_int_configs[CONFIG_CHARTER_COST_GUILD] = sConfigMgr->GetIntDefault("Guild.CharterCost", 1000); + m_int_configs[CONFIG_CHARTER_COST_ARENA_2v2] = sConfigMgr->GetIntDefault("ArenaTeam.CharterCost.2v2", 800000); + m_int_configs[CONFIG_CHARTER_COST_ARENA_3v3] = sConfigMgr->GetIntDefault("ArenaTeam.CharterCost.3v3", 1200000); + m_int_configs[CONFIG_CHARTER_COST_ARENA_5v5] = sConfigMgr->GetIntDefault("ArenaTeam.CharterCost.5v5", 2000000); + m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled", 0); m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled.RaceMask", 0); m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled.ClassMask", 0); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 5c97b8f5653..a02f735ed4d 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -341,6 +341,10 @@ enum WorldIntConfigs CONFIG_BIRTHDAY_TIME, CONFIG_CREATURE_PICKPOCKET_REFILL, CONFIG_AHBOT_UPDATE_INTERVAL, + CONFIG_CHARTER_COST_GUILD, + CONFIG_CHARTER_COST_ARENA_2v2, + CONFIG_CHARTER_COST_ARENA_3v3, + CONFIG_CHARTER_COST_ARENA_5v5, INT_CONFIG_VALUE_COUNT }; diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index d3d012e70d5..2eebc9cae10 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -488,7 +488,7 @@ public: static bool HandleDebugSendQuestPartyMsgCommand(ChatHandler* handler, char const* args) { - uint32 msg = atol((char*)args); + uint32 msg = atoul(args); handler->GetSession()->GetPlayer()->SendPushToPartyResponse(handler->GetSession()->GetPlayer(), msg); return true; } @@ -507,7 +507,7 @@ public: static bool HandleDebugSendQuestInvalidMsgCommand(ChatHandler* handler, char const* args) { - QuestFailedReason msg = static_cast<QuestFailedReason>(atol((char*)args)); + QuestFailedReason msg = static_cast<QuestFailedReason>(atoul(args)); handler->GetSession()->GetPlayer()->SendCanTakeQuestResponse(msg); return true; } diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index f3ddc6f0137..c0bf2a6bb84 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -118,7 +118,7 @@ public: if (!id) return false; - uint32 objectId = atol(id); + uint32 objectId = atoul(id); if (!objectId) return false; @@ -238,7 +238,7 @@ public: if (!id) return false; - uint32 objectId = atol(id); + uint32 objectId = atoul(id); if (objectId) result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1", diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index a558d977b85..06967c69888 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -269,7 +269,7 @@ public: const char* onlineState = ""; // Parse the guid to uint32... - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args))); + ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); // ... and try to extract a player out of it. if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget)) diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index 0f21200c22d..b57629a577e 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -65,7 +65,7 @@ public: if (!id) return false; - uint32 creatureId = atol(id); + uint32 creatureId = atoul(id); if (!creatureId) { handler->PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, creatureId); @@ -82,7 +82,7 @@ public: } char* countStr = strtok(NULL, " "); - uint32 count = countStr ? atol(countStr) : 10; + uint32 count = countStr ? atoul(countStr) : 10; if (count == 0) return false; @@ -133,11 +133,11 @@ public: if (!*args) return false; - char* id = handler->extractKeyFromLink((char*)args, "Hitem"); + char const* id = handler->extractKeyFromLink((char*)args, "Hitem"); if (!id) return false; - uint32 itemId = atol(id); + uint32 itemId = atoul(id); if (!itemId) { handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); @@ -154,7 +154,7 @@ public: } char* countStr = strtok(NULL, " "); - uint32 count = countStr ? atol(countStr) : 10; + uint32 count = countStr ? atoul(countStr) : 10; if (count == 0) return false; @@ -354,7 +354,7 @@ public: if (!id) return false; - uint32 gameObjectId = atol(id); + uint32 gameObjectId = atoul(id); if (!gameObjectId) { handler->PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, gameObjectId); @@ -371,7 +371,7 @@ public: } char* countStr = strtok(NULL, " "); - uint32 count = countStr ? atol(countStr) : 10; + uint32 count = countStr ? atoul(countStr) : 10; if (count == 0) return false; @@ -476,7 +476,7 @@ public: if (!*args) return false; - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args))); + ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) { diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index a853a02bb11..331a31f6c02 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1134,7 +1134,7 @@ public: char const* id = handler->extractKeyFromLink((char*)args, "Hitem"); if (!id) return false; - itemId = uint32(atol(id)); + itemId = atoul(id); } char const* ccount = strtok(NULL, " "); @@ -1216,7 +1216,7 @@ public: if (!id) return false; - uint32 itemSetId = atol(id); + uint32 itemSetId = atoul(id); // prevent generation all items with itemset field value '0' if (itemSetId == 0) @@ -1357,7 +1357,7 @@ public: return false; } - int32 level = uint32(atol(levelStr)); + int32 level = atol(levelStr); Player* target = handler->getSelectedPlayer(); if (!target) @@ -1379,7 +1379,7 @@ public: // 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); + uint16 max = maxPureSkill ? atoul(maxPureSkill) : targetHasSkill ? target->GetPureMaxSkillValue(skill) : uint16(level); if (level <= 0 || level > max || max <= 0) return false; @@ -1419,7 +1419,7 @@ public: PreparedStatement* stmt = NULL; // To make sure we get a target, we convert our guid to an omniversal... - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args))); + ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); // ... and make sure we get a target, somehow. if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) @@ -1780,7 +1780,7 @@ public: uint32 totalmail = uint32(fields[1].GetUInt64()); // ... we have to convert it from Char to int. We can use totalmail as it is - rmailint = atol(readmail.c_str()); + rmailint = atoul(readmail.c_str()); // Output XXI. LANG_INFO_CHR_MAILS if at least one mail is given if (totalmail >= 1) @@ -1978,7 +1978,7 @@ public: static bool HandleMuteInfoHelper(uint32 accountId, char const* accountName, ChatHandler *handler) { PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_MUTE_INFO); - stmt->setUInt16(0, accountId); + stmt->setUInt32(0, accountId); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 987c12debb7..1434493e948 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -326,15 +326,15 @@ public: char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 uint32 maxcount = 0; if (fmaxcount) - maxcount = atol(fmaxcount); + maxcount = atoul(fmaxcount); char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 uint32 incrtime = 0; if (fincrtime) - incrtime = atol(fincrtime); + incrtime = atoul(fincrtime); char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 - uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0; + uint32 extendedcost = fextendedcost ? atoul(fextendedcost) : 0; Creature* vendor = handler->getSelectedCreature(); if (!vendor) { @@ -564,7 +564,7 @@ public: handler->SetSentErrorMessage(true); return false; } - uint32 itemId = atol(pitem); + uint32 itemId = atoul(pitem); if (!sObjectMgr->RemoveVendorItem(vendor->GetEntry(), itemId)) { @@ -1321,7 +1321,7 @@ public: return false; } - ObjectGuid receiver_guid(HIGHGUID_PLAYER, uint32(atol(receiver_str))); + ObjectGuid receiver_guid(HIGHGUID_PLAYER, uint32(atoul(receiver_str))); // check online security Player* receiver = ObjectAccessor::FindPlayer(receiver_guid); diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index fb486128049..9f7098b9134 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -67,7 +67,7 @@ public: if (!cId) return false; - uint32 entry = atol(cId); + uint32 entry = atoul(cId); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); @@ -112,7 +112,7 @@ public: if (!cId) return false; - uint32 entry = atol(cId); + uint32 entry = atoul(cId); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); @@ -165,7 +165,7 @@ public: if (!cId) return false; - uint32 entry = atol(cId); + uint32 entry = atoul(cId); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); @@ -269,7 +269,7 @@ public: if (!cId) return false; - uint32 entry = atol(cId); + uint32 entry = atoul(cId); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp index 58f38ec4267..860cc609c7b 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -225,7 +225,7 @@ class boss_ragnaros : public CreatureScript events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, urand(10000, 14000)); break; case EVENT_MAGMA_BLAST: - if (me->IsWithinMeleeRange(me->GetVictim())) + if (!me->IsWithinMeleeRange(me->GetVictim())) { DoCastVictim(SPELL_MAGMA_BLAST); if (!_hasYelledMagmaBurst) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 992b20d2580..e0416b56397 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -25,10 +25,9 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" -#include "hyjal.h" -#include "SpellAuras.h" -#include "hyjal_trash.h" +#include "SpellScript.h" #include "Player.h" +#include "hyjal.h" enum Texts { @@ -39,42 +38,59 @@ enum Texts SAY_ENRAGE = 5, SAY_DEATH = 6, SAY_SOUL_CHARGE = 7, + // YELL_ARCHIMONDE_INTRO = 8 }; enum Spells { - SPELL_DENOUEMENT_WISP = 32124, - SPELL_ANCIENT_SPARK = 39349, - SPELL_PROTECTION_OF_ELUNE = 38528, - - SPELL_DRAIN_WORLD_TREE = 39140, - SPELL_DRAIN_WORLD_TREE_2 = 39141, - - SPELL_FINGER_OF_DEATH = 31984, - SPELL_HAND_OF_DEATH = 35354, - SPELL_AIR_BURST = 32014, - SPELL_GRIP_OF_THE_LEGION = 31972, - SPELL_DOOMFIRE_STRIKE = 31903, //summons two creatures - SPELL_DOOMFIRE_SPAWN = 32074, - SPELL_DOOMFIRE = 31945, - SPELL_SOUL_CHARGE_YELLOW = 32045, - SPELL_SOUL_CHARGE_GREEN = 32051, - SPELL_SOUL_CHARGE_RED = 32052, - SPELL_UNLEASH_SOUL_YELLOW = 32054, - SPELL_UNLEASH_SOUL_GREEN = 32057, - SPELL_UNLEASH_SOUL_RED = 32053, - SPELL_FEAR = 31970, + SPELL_DENOUEMENT_WISP = 32124, + SPELL_ANCIENT_SPARK = 39349, + SPELL_PROTECTION_OF_ELUNE = 38528, + + SPELL_DRAIN_WORLD_TREE = 39140, + SPELL_DRAIN_WORLD_TREE_TRIGGERED = 39141, + + SPELL_FINGER_OF_DEATH = 31984, + SPELL_HAND_OF_DEATH = 35354, + SPELL_AIR_BURST = 32014, + SPELL_GRIP_OF_THE_LEGION = 31972, + SPELL_DOOMFIRE_STRIKE = 31903, // summons two creatures + SPELL_DOOMFIRE_SPAWN = 32074, + SPELL_DOOMFIRE = 31945, + SPELL_SOUL_CHARGE_YELLOW = 32045, + SPELL_SOUL_CHARGE_GREEN = 32051, + SPELL_SOUL_CHARGE_RED = 32052, + SPELL_UNLEASH_SOUL_YELLOW = 32054, + SPELL_UNLEASH_SOUL_GREEN = 32057, + SPELL_UNLEASH_SOUL_RED = 32053, + SPELL_FEAR = 31970 +}; + +enum Events +{ + EVENT_HAND_OF_DEATH = 1, // Raid wiper + EVENT_UNLEASH_SOUL_CHARGE, + EVENT_FINGER_OF_DEATH, + EVENT_GRIP_OF_THE_LEGION, + EVENT_FEAR, + EVENT_AIR_BURST, + EVENT_DOOMFIRE, + EVENT_DISTANCE_CHECK, // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage + EVENT_SUMMON_WHISP }; enum Summons { - CREATURE_DOOMFIRE = 18095, - CREATURE_DOOMFIRE_SPIRIT = 18104, - CREATURE_ANCIENT_WISP = 17946, - CREATURE_CHANNEL_TARGET = 22418, + NPC_DOOMFIRE = 18095, + NPC_DOOMFIRE_SPIRIT = 18104, + NPC_ANCIENT_WISP = 17946 }; -Position const NordrassilLoc = {5503.713f, -3523.436f, 1608.781f, 0.0f}; +enum Actions +{ + ACTION_ENRAGE, + ACTION_CHANNEL_WORLD_TREE +}; class npc_ancient_wisp : public CreatureScript { @@ -200,7 +216,6 @@ public: } void MoveInLineOfSight(Unit* who) override - { //will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0 //when UpdateAI needs it, it will be forced to select randomPoint @@ -249,409 +264,309 @@ class boss_archimonde : public CreatureScript public: boss_archimonde() : CreatureScript("boss_archimonde") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_archimondeAI>(creature); - } - - struct boss_archimondeAI : public hyjal_trashAI + struct boss_archimondeAI : public BossAI { - boss_archimondeAI(Creature* creature) : hyjal_trashAI(creature) + boss_archimondeAI(Creature* creature) : BossAI(creature, DATA_ARCHIMONDE) { Initialize(); - instance = creature->GetInstanceScript(); } void Initialize() { DoomfireSpiritGUID.Clear(); - damageTaken = 0; - WorldTreeGUID.Clear(); - - DrainNordrassilTimer = 0; - FearTimer = 42000; - AirBurstTimer = 30000; - GripOfTheLegionTimer = urand(5000, 25000); - DoomfireTimer = 20000; - SoulChargeTimer = urand(2000, 30000); + SoulChargeCount = 0; - MeleeRangeCheckTimer = 15000; - HandOfDeathTimer = 2000; WispCount = 0; // When ~30 wisps are summoned, Archimonde dies - EnrageTimer = 600000; // 10 minutes - CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage - SummonWispTimer = 0; + _unleashSpell = 0; + _chargeSpell = 0; Enraged = false; - BelowTenPercent = false; HasProtected = false; - IsChanneling = false; } - InstanceScript* instance; - - ObjectGuid DoomfireSpiritGUID; - ObjectGuid WorldTreeGUID; - - uint32 DrainNordrassilTimer; - uint32 FearTimer; - uint32 AirBurstTimer; - uint32 GripOfTheLegionTimer; - uint32 DoomfireTimer; - uint32 SoulChargeTimer; - uint8 SoulChargeCount; - uint32 MeleeRangeCheckTimer; - uint32 HandOfDeathTimer; - uint32 SummonWispTimer; - uint8 WispCount; - uint32 EnrageTimer; - uint32 CheckDistanceTimer; - - bool Enraged; - bool BelowTenPercent; - bool HasProtected; - bool IsChanneling; + void InitializeAI() override + { + BossAI::InitializeAI(); + DoAction(ACTION_CHANNEL_WORLD_TREE); + } void Reset() override { - instance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); - Initialize(); + _Reset(); + me->RemoveAllAuras(); // Reset Soul Charge auras. } void EnterCombat(Unit* /*who*/) override { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); Talk(SAY_AGGRO); - DoZoneInCombat(); - - instance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit* victim) override - { - Talk(SAY_SLAY); - - if (victim && victim->GetTypeId() == TYPEID_PLAYER) - GainSoulCharge(victim->ToPlayer()); + _EnterCombat(); + events.ScheduleEvent(EVENT_FEAR, 42000); + events.ScheduleEvent(EVENT_AIR_BURST, 30000); + events.ScheduleEvent(EVENT_GRIP_OF_THE_LEGION, urand(5000, 25000)); + events.ScheduleEvent(EVENT_DOOMFIRE, 20000); + events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000)); + events.ScheduleEvent(EVENT_FINGER_OF_DEATH, 15000); + events.ScheduleEvent(EVENT_HAND_OF_DEATH, 600000); + events.ScheduleEvent(EVENT_DISTANCE_CHECK, 30000); } - void GainSoulCharge(Player* victim) + void ExecuteEvent(uint32 eventId) override { - switch (victim->getClass()) + switch (eventId) { - case CLASS_PRIEST: - case CLASS_PALADIN: - case CLASS_WARLOCK: - victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); + case EVENT_HAND_OF_DEATH: + DoCastAOE(SPELL_HAND_OF_DEATH); + events.ScheduleEvent(EVENT_HAND_OF_DEATH, 2000); + break; + case EVENT_UNLEASH_SOUL_CHARGE: + _chargeSpell = 0; + _unleashSpell = 0; + me->InterruptNonMeleeSpells(false); + switch (urand(0, 2)) + { + case 0: + _chargeSpell = SPELL_SOUL_CHARGE_RED; + _unleashSpell = SPELL_UNLEASH_SOUL_RED; + break; + case 1: + _chargeSpell = SPELL_SOUL_CHARGE_YELLOW; + _unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; + break; + case 2: + _chargeSpell = SPELL_SOUL_CHARGE_GREEN; + _unleashSpell = SPELL_UNLEASH_SOUL_GREEN; + break; + } + + if (me->HasAura(_chargeSpell)) + { + me->RemoveAuraFromStack(_chargeSpell); + DoCastVictim(_unleashSpell); + SoulChargeCount--; + events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000)); + } + break; + case EVENT_FINGER_OF_DEATH: + if (!SelectTarget(SELECT_TARGET_RANDOM, 0, 5.0f)) // Checks if there are no targets in melee range + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); + events.ScheduleEvent(EVENT_FINGER_OF_DEATH, 1000); + } + else + events.ScheduleEvent(EVENT_FINGER_OF_DEATH, 5000); break; - case CLASS_MAGE: - case CLASS_ROGUE: - case CLASS_WARRIOR: - victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); + case EVENT_GRIP_OF_THE_LEGION: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_GRIP_OF_THE_LEGION); + events.ScheduleEvent(EVENT_GRIP_OF_THE_LEGION, urand(5000, 25000)); break; - case CLASS_DRUID: - case CLASS_SHAMAN: - case CLASS_HUNTER: - victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); + case EVENT_AIR_BURST: + Talk(SAY_AIR_BURST); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) + DoCast(target, SPELL_AIR_BURST); //not on tank + events.ScheduleEvent(EVENT_AIR_BURST, urand(25000, 40000)); + break; + case EVENT_FEAR: + DoCastAOE(SPELL_FEAR); + events.ScheduleEvent(EVENT_FEAR, 42000); + break; + case EVENT_DOOMFIRE: + Talk(SAY_DOOMFIRE); + if (Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 1)) + SummonDoomfire(temp); + else + SummonDoomfire(me->GetVictim()); + events.ScheduleEvent(EVENT_DOOMFIRE, 20000); + break; + case EVENT_DISTANCE_CHECK: + if (Creature* channelTrigger = instance->GetCreature(DATA_CHANNEL_TARGET)) + if (me->IsWithinDistInMap(channelTrigger, 75.0f)) + DoAction(ACTION_ENRAGE); + events.ScheduleEvent(EVENT_DISTANCE_CHECK, 5000); + break; + case EVENT_SUMMON_WHISP: + DoSpawnCreature(NPC_ANCIENT_WISP, float(rand32() % 40), float(rand32() % 40), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ++WispCount; + if (WispCount >= 30) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + events.ScheduleEvent(EVENT_SUMMON_WHISP, 1500); + break; + default: break; } - - SoulChargeTimer = urand(2000, 30000); - ++SoulChargeCount; - } - - void JustDied(Unit* killer) override - { - hyjal_trashAI::JustDied(killer); - Talk(SAY_DEATH); - - instance->SetData(DATA_ARCHIMONDEEVENT, DONE); } - bool CanUseFingerOfDeath() + void DamageTaken(Unit* /*attacker*/, uint32 &damage) override { - // First we check if our current victim is in melee range or not. - Unit* victim = me->GetVictim(); - if (victim && me->IsWithinDistInMap(victim, me->GetAttackDistance(victim))) - return false; - - ThreatContainer::StorageType const &threatlist = me->getThreatManager().getThreatList(); - if (threatlist.empty()) - return false; - - std::list<Unit*> targets; - ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); - for (; itr != threatlist.end(); ++itr) + if (me->HealthBelowPctDamaged(10, damage)) { - Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (unit && unit->IsAlive()) - targets.push_back(unit); - } + if (!Enraged) + DoAction(ACTION_ENRAGE); - if (targets.empty()) - return false; + if (!HasProtected) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); - targets.sort(Trinity::ObjectDistanceOrderPred(me)); - Unit* target = targets.front(); - if (target) - { - if (!me->IsWithinDistInMap(target, me->GetAttackDistance(target))) - return true; // Cast Finger of Death - else // This target is closest, he is our new tank - me->AddThreat(target, me->getThreatManager().getThreat(me->GetVictim())); + // All members of raid must get this buff + DoCastAOE(SPELL_PROTECTION_OF_ELUNE, true); + HasProtected = true; + events.ScheduleEvent(EVENT_SUMMON_WHISP, 1500); + } } - - return false; } - void JustSummoned(Creature* summoned) override + void KilledUnit(Unit* victim) override { - if (summoned->GetEntry() == CREATURE_ANCIENT_WISP) - summoned->AI()->AttackStart(me); - else - { - summoned->setFaction(me->getFaction()); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT) - { - DoomfireSpiritGUID = summoned->GetGUID(); - } + Talk(SAY_SLAY); - if (summoned->GetEntry() == CREATURE_DOOMFIRE) + if (victim->GetTypeId() == TYPEID_PLAYER) { - summoned->CastSpell(summoned, SPELL_DOOMFIRE_SPAWN, false); - summoned->CastSpell(summoned, SPELL_DOOMFIRE, true, 0, 0, me->GetGUID()); - - if (Unit* DoomfireSpirit = ObjectAccessor::GetUnit(*me, DoomfireSpiritGUID)) + switch (victim->getClass()) { - summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit, 0.0f, 0.0f); - DoomfireSpiritGUID.Clear(); + case CLASS_PRIEST: + case CLASS_PALADIN: + case CLASS_WARLOCK: + victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); + break; + case CLASS_MAGE: + case CLASS_ROGUE: + case CLASS_WARRIOR: + victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); + break; + case CLASS_DRUID: + case CLASS_SHAMAN: + case CLASS_HUNTER: + victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); + break; } + + events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000)); + ++SoulChargeCount; } } - //this is code doing close to what the summoning spell would do (spell 31903) - void SummonDoomfire(Unit* target) + void JustReachedHome() override { - me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, - target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, - TEMPSUMMON_TIMED_DESPAWN, 27000); - - me->SummonCreature(CREATURE_DOOMFIRE, - target->GetPositionX()-15.0f, target->GetPositionY()-15.0f, target->GetPositionZ(), 0, - TEMPSUMMON_TIMED_DESPAWN, 27000); + DoAction(ACTION_CHANNEL_WORLD_TREE); } - void UnleashSoulCharge() + void JustDied(Unit* /*killer*/) override { - me->InterruptNonMeleeSpells(false); - - bool HasCast = false; - uint32 chargeSpell = 0; - uint32 unleashSpell = 0; + Talk(SAY_DEATH); + _JustDied(); + // @todo: remove this when instance script gets updated, kept for compatibility only + instance->SetData(DATA_ARCHIMONDE, DONE); + } - switch (urand(0, 2)) + void JustSummoned(Creature* summoned) override + { + switch (summoned->GetEntry()) { - case 0: - chargeSpell = SPELL_SOUL_CHARGE_RED; - unleashSpell = SPELL_UNLEASH_SOUL_RED; - break; - case 1: - chargeSpell = SPELL_SOUL_CHARGE_YELLOW; - unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; + case NPC_ANCIENT_WISP: + summoned->AI()->AttackStart(me); break; - case 2: - chargeSpell = SPELL_SOUL_CHARGE_GREEN; - unleashSpell = SPELL_UNLEASH_SOUL_GREEN; + case NPC_DOOMFIRE_SPIRIT: + DoomfireSpiritGUID = summoned->GetGUID(); break; - } + case NPC_DOOMFIRE: + summoned->CastSpell(summoned, SPELL_DOOMFIRE_SPAWN, false); + summoned->CastSpell(summoned, SPELL_DOOMFIRE, true, 0, 0, me->GetGUID()); - if (me->HasAura(chargeSpell)) - { - me->RemoveAuraFromStack(chargeSpell); - DoCastVictim(unleashSpell); - HasCast = true; - SoulChargeCount--; + if (Unit* DoomfireSpirit = ObjectAccessor::GetUnit(*me, DoomfireSpiritGUID)) + { + summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit, 0.0f, 0.0f); + DoomfireSpiritGUID.Clear(); + } + break; + default: + break; } - - if (HasCast) - SoulChargeTimer = urand(2000, 30000); } - void UpdateAI(uint32 diff) override + void DoAction(int32 actionId) override { - if (!me->IsInCombat()) + switch (actionId) { - // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished. - if ((instance->GetData(DATA_AZGALOREVENT) < DONE) && (me->IsVisible() || (me->getFaction() != 35))) - { - me->SetVisible(false); - me->setFaction(35); - } - else if ((instance->GetData(DATA_AZGALOREVENT) >= DONE) && (!me->IsVisible() || (me->getFaction() == 35))) - { - me->setFaction(1720); - me->SetVisible(true); - } - - if (DrainNordrassilTimer <= diff) - { - if (!IsChanneling) - { - Creature* temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 1200000); - - if (temp) - WorldTreeGUID = temp->GetGUID(); - - if (Unit* Nordrassil = ObjectAccessor::GetUnit(*me, WorldTreeGUID)) - { - Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Nordrassil->SetDisplayId(11686); - DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE); - IsChanneling = true; - } - } - - if (Unit* Nordrassil = ObjectAccessor::GetUnit(*me, WorldTreeGUID)) - { - Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true); - DrainNordrassilTimer = 1000; - } - } else DrainNordrassilTimer -= diff; + case ACTION_ENRAGE: + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + Enraged = true; + Talk(SAY_ENRAGE); + break; + case ACTION_CHANNEL_WORLD_TREE: + DoCastAOE(SPELL_DRAIN_WORLD_TREE, true); + break; + default: + break; } + } - if (!UpdateVictim()) + //this is code doing close to what the summoning spell would do (spell 31903) + void SummonDoomfire(Unit* target) + { + if (!target) return; - if (me->HealthBelowPct(10) && !BelowTenPercent && !Enraged) - BelowTenPercent = true; - - if (!Enraged) - { - if (EnrageTimer <= diff) - { - if (HealthAbovePct(10)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - Talk(SAY_ENRAGE); - } - } else EnrageTimer -= diff; + me->SummonCreature(NPC_DOOMFIRE_SPIRIT, + target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, + TEMPSUMMON_TIMED_DESPAWN, 27000); - if (CheckDistanceTimer <= diff) - { - // To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature - Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 2000); - if (Check) - { - Check->SetVisible(false); - - if (me->IsWithinDistInMap(Check, 75)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - Talk(SAY_ENRAGE); - } - } - CheckDistanceTimer = 5000; - } else CheckDistanceTimer -= diff; - } + me->SummonCreature(NPC_DOOMFIRE, + target->GetPositionX()-15.0f, target->GetPositionY()-15.0f, target->GetPositionZ(), 0, + TEMPSUMMON_TIMED_DESPAWN, 27000); + } - if (BelowTenPercent) - { - if (!HasProtected) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); + private: + ObjectGuid DoomfireSpiritGUID; + uint8 SoulChargeCount; + uint8 WispCount; + uint32 _chargeSpell; + uint32 _unleashSpell; + bool Enraged; + bool HasProtected; + }; - //all members of raid must get this buff - DoCastVictim(SPELL_PROTECTION_OF_ELUNE, true); - HasProtected = true; - Enraged = true; - } + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_archimondeAI>(creature); + } +}; - if (SummonWispTimer <= diff) - { - DoSpawnCreature(CREATURE_ANCIENT_WISP, float(rand32() % 40), float(rand32() % 40), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - SummonWispTimer = 1500; - ++WispCount; - } else SummonWispTimer -= diff; +// 39142 - Drain World Tree Dummy +class spell_archimonde_drain_world_tree_dummy : public SpellScriptLoader +{ + public: + spell_archimonde_drain_world_tree_dummy() : SpellScriptLoader("spell_archimonde_drain_world_tree_dummy") { } - if (WispCount >= 30) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } + class spell_archimonde_drain_world_tree_dummy_SpellScript : public SpellScript + { + PrepareSpellScript(spell_archimonde_drain_world_tree_dummy_SpellScript); - if (Enraged) + bool Validate(SpellInfo const* /*spellInfo*/) override { - if (HandOfDeathTimer <= diff) - { - DoCastVictim(SPELL_HAND_OF_DEATH); - HandOfDeathTimer = 2000; - } else HandOfDeathTimer -= diff; - return; // Don't do anything after this point. + if (!sSpellMgr->GetSpellInfo(SPELL_DRAIN_WORLD_TREE_TRIGGERED)) + return false; + return true; } - if (SoulChargeCount) + void HandleScript(SpellEffIndex /*effIndex*/) { - if (SoulChargeTimer <= diff) - UnleashSoulCharge(); - else SoulChargeTimer -= diff; + if (Unit* target = GetHitUnit()) + target->CastSpell(GetCaster(), SPELL_DRAIN_WORLD_TREE_TRIGGERED, true); } - if (GripOfTheLegionTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION); - GripOfTheLegionTimer = urand(5000, 25000); - } else GripOfTheLegionTimer -= diff; - - if (AirBurstTimer <= diff) - { - Talk(SAY_AIR_BURST); - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank - AirBurstTimer = urand(25000, 40000); - } else AirBurstTimer -= diff; - - if (FearTimer <= diff) - { - DoCastVictim(SPELL_FEAR); - FearTimer = 42000; - } else FearTimer -= diff; - - if (DoomfireTimer <= diff) + void Register() override { - Talk(SAY_DOOMFIRE); - Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 1); - if (!temp) - temp = me->GetVictim(); - - //replace with spell cast 31903 once implicitTarget 73 implemented - SummonDoomfire(temp); - - //supposedly three doomfire can be up at the same time - DoomfireTimer = 20000; - } else DoomfireTimer -= diff; - - if (MeleeRangeCheckTimer <= diff) - { - if (CanUseFingerOfDeath()) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); - MeleeRangeCheckTimer = 1000; - } - - MeleeRangeCheckTimer = 5000; - } else MeleeRangeCheckTimer -= diff; + OnEffectHitTarget += SpellEffectFn(spell_archimonde_drain_world_tree_dummy_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; - DoMeleeAttackIfReady(); + SpellScript* GetSpellScript() const override + { + return new spell_archimonde_drain_world_tree_dummy_SpellScript(); } - void WaypointReached(uint32 /*waypointId*/) override { } - }; }; void AddSC_boss_archimonde() @@ -660,4 +575,5 @@ void AddSC_boss_archimonde() new npc_doomfire(); new npc_doomfire_targetting(); new npc_ancient_wisp(); + new spell_archimonde_drain_world_tree_dummy(); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h index c5f4d4ae679..54a763573ed 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h @@ -44,7 +44,8 @@ enum DataTypes DATA_HORDE_RETREAT = 17, DATA_RAIDDAMAGE = 18, DATA_RESET_RAIDDAMAGE = 19, - TYPE_RETREAT = 20 + TYPE_RETREAT = 20, + DATA_CHANNEL_TARGET = 21 }; enum WorldStateIds @@ -77,7 +78,8 @@ enum CreaturesIds KAZROGAL = 17888, AZGALOR = 17842, ARCHIMONDE = 17968, - NPC_WORLD_TRIGGER_TINY = 21987 + NPC_WORLD_TRIGGER_TINY = 21987, + NPC_CHANNEL_TARGET = 22418 }; enum GameobjectIds @@ -89,5 +91,6 @@ enum GameobjectIds GO_ROARING_FLAME = 182592 }; -#endif +#define MINRAIDDAMAGE 700000 // minimal damage before trash can drop loot and reputation, resets if faction leader dies +#endif diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp index c6adbd58c4a..d4b4061aaa8 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp @@ -26,7 +26,6 @@ enum Spells SPELL_METEOR = 33814, //infernal visual SPELL_IMMOLATION = 37059, SPELL_FLAME_BUFFET = 31724, - NPC_TRIGGER = 21987, //World Trigger (Tiny) MODEL_INVIS = 11686, //invisible model SPELL_DISEASE_CLOUD = 31607, SPELL_KNOCKDOWN = 31610, @@ -465,10 +464,7 @@ public: } if (!meteor) { - float x, y, z; - me->GetPosition(x, y, z); - Creature* trigger = me->SummonCreature(NPC_TRIGGER, x + 8, y + 8, z + 25 + rand32() % 10, me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 1000); - if (trigger) + if (Creature* trigger = me->SummonCreature(NPC_WORLD_TRIGGER_TINY, me->GetPositionWithOffset({ 8.0f, 8.0f, frand(25.0f, 35.0f), 0.0f }), TEMPSUMMON_TIMED_DESPAWN, 1000)) { trigger->SetVisible(false); trigger->setFaction(me->getFaction()); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h index 18122ba2b0c..62f82ebcee1 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h @@ -21,8 +21,6 @@ #include "hyjal.h" #include "ScriptedEscortAI.h" -#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies - struct hyjal_trashAI : public npc_escortAI { hyjal_trashAI(Creature* creature); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp index 1d4a728b08b..99b8515c6e8 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp @@ -26,10 +26,7 @@ EndScriptData */ #include "ScriptMgr.h" #include "InstanceScript.h" #include "ScriptedCreature.h" -#include "hyjal_trash.h" -#include "Player.h" -#include "WorldPacket.h" -#include "Chat.h" +#include "hyjal.h" /* Battle of Mount Hyjal encounters: 0 - Rage Winterchill event @@ -39,8 +36,16 @@ EndScriptData */ 4 - Archimonde event */ -#define YELL_EFFORTS "All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more." -#define YELL_EFFORTS_NAME "Archimonde" +enum Yells +{ + YELL_ARCHIMONDE_INTRO = 8 +}; + +ObjectData const creatureData[] = +{ + { NPC_CHANNEL_TARGET, DATA_CHANNEL_TARGET }, + { 0, 0 } // END +}; class instance_hyjal : public InstanceMapScript { @@ -57,6 +62,7 @@ public: instance_mount_hyjal_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); + LoadObjectData(creatureData, nullptr); memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); RaidDamage = 0; @@ -104,15 +110,35 @@ public: { switch (creature->GetEntry()) { - case RAGE_WINTERCHILL: RageWinterchill = creature->GetGUID(); break; - case ANETHERON: Anetheron = creature->GetGUID(); break; - case KAZROGAL: Kazrogal = creature->GetGUID(); break; - case AZGALOR: Azgalor = creature->GetGUID(); break; - case ARCHIMONDE: Archimonde = creature->GetGUID(); break; - case JAINA: JainaProudmoore = creature->GetGUID(); break; - case THRALL: Thrall = creature->GetGUID(); break; - case TYRANDE: TyrandeWhisperwind = creature->GetGUID(); break; + case RAGE_WINTERCHILL: + RageWinterchill = creature->GetGUID(); + break; + case ANETHERON: + Anetheron = creature->GetGUID(); + break; + case KAZROGAL: + Kazrogal = creature->GetGUID(); + break; + case AZGALOR: + Azgalor = creature->GetGUID(); + break; + case ARCHIMONDE: + Archimonde = creature->GetGUID(); + if (GetData(DATA_AZGALOREVENT) != DONE) + creature->SetVisible(false); + break; + case JAINA: + JainaProudmoore = creature->GetGUID(); + break; + case THRALL: + Thrall = creature->GetGUID(); + break; + case TYRANDE: + TyrandeWhisperwind = creature->GetGUID(); + break; } + + InstanceScript::OnCreatureCreate(creature); } ObjectGuid GetGuidData(uint32 identifier) const override @@ -146,39 +172,18 @@ public: m_auiEncounter[2] = data; break; case DATA_AZGALOREVENT: + m_auiEncounter[3] = data; + if (data == DONE) { - m_auiEncounter[3] = data; - if (data == DONE) + instance->LoadGrid(5581.49f, -3445.63f); + if (Creature* archimonde = instance->GetCreature(Archimonde)) { - if (ArchiYell) - break; - - ArchiYell = true; + archimonde->SetVisible(true); - Creature* creature = instance->GetCreature(Azgalor); - if (creature) + if (!ArchiYell) { - Creature* unit = creature->SummonCreature(NPC_WORLD_TRIGGER_TINY, creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000); - - Map* map = creature->GetMap(); - if (map->IsDungeon() && unit) - { - unit->SetVisible(false); - Map::PlayerList const &PlayerList = map->GetPlayers(); - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* player = i->GetSource()) - { - WorldPacket packet; - ChatHandler::BuildChatPacket(packet, CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, unit, player, YELL_EFFORTS); - player->SendDirectMessage(&packet); - player->PlayDirectSound(10986, player); - } - } - } + ArchiYell = true; + archimonde->AI()->Talk(YELL_ARCHIMONDE_INTRO); } } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp index b84d24d66d3..794496382c2 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp @@ -292,6 +292,7 @@ public: break; } player->CLOSE_GOSSIP_MENU(); + ai->SetDespawnAtFar(false); creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); return true; } diff --git a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp index 9f5e7bdf29d..d254cbe08fb 100644 --- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp @@ -19,12 +19,11 @@ /* ScriptData SDName: Dustwallow_Marsh SD%Complete: 95 -SDComment: Quest support: 11180, 558, 11126, 11142, 11174, Vendor Nat Pagle +SDComment: Quest support: 558, 11126, 11142, 11174, Vendor Nat Pagle SDCategory: Dustwallow Marsh EndScriptData */ /* ContentData -npc_risen_husk_spirit npc_lady_jaina_proudmoore npc_nat_pagle npc_private_hendel @@ -40,99 +39,6 @@ EndContentData */ #include "WorldSession.h" /*###### -## npc_risen_husk_spirit -######*/ - -enum HauntingWitchHill -{ - // Quest - QUEST_WHATS_HAUNTING_WITCH_HILL = 11180, - - // General spells - SPELL_SUMMON_RESTLESS_APPARITION = 42511, - SPELL_WITCH_HILL_INFORMATION_CREDIT = 42512, - - // Risen Husk specific - SPELL_CONSUME_FLESH = 37933, - NPC_RISEN_HUSK = 23555, - - // Risen Spirit specific - SPELL_INTANGIBLE_PRESENCE = 43127, - NPC_RISEN_SPIRIT = 23554, - - // Events - EVENT_CONSUME_FLESH = 1, - EVENT_INTANGIBLE_PRESENCE = 2, -}; - -class npc_risen_husk_spirit : public CreatureScript -{ - public: - npc_risen_husk_spirit() : CreatureScript("npc_risen_husk_spirit") { } - - struct npc_risen_husk_spiritAI : public ScriptedAI - { - npc_risen_husk_spiritAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - events.Reset(); - if (me->GetEntry() == NPC_RISEN_HUSK) - events.ScheduleEvent(EVENT_CONSUME_FLESH, 5000); - else if (me->GetEntry() == NPC_RISEN_SPIRIT) - events.ScheduleEvent(EVENT_INTANGIBLE_PRESENCE, 5000); - } - - void JustDied(Unit* killer) override - { - if (killer->GetTypeId() == TYPEID_PLAYER) - { - if (killer->ToPlayer()->GetQuestStatus(QUEST_WHATS_HAUNTING_WITCH_HILL) == QUEST_STATUS_INCOMPLETE) - { - DoCast(me, SPELL_SUMMON_RESTLESS_APPARITION, true); - DoCast(killer, SPELL_WITCH_HILL_INFORMATION_CREDIT, true); - } - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_CONSUME_FLESH: - DoCastVictim(SPELL_CONSUME_FLESH); - events.ScheduleEvent(EVENT_CONSUME_FLESH, 15000); - break; - case EVENT_INTANGIBLE_PRESENCE: - DoCastVictim(SPELL_INTANGIBLE_PRESENCE); - events.ScheduleEvent(EVENT_INTANGIBLE_PRESENCE, 15000); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_risen_husk_spiritAI(creature); - } -}; - -/*###### ## npc_lady_jaina_proudmoore ######*/ @@ -369,131 +275,6 @@ public: }; -/*###### -## npc_stinky -######*/ - -enum Stinky -{ - QUEST_STINKYS_ESCAPE_H = 1270, - QUEST_STINKYS_ESCAPE_A = 1222, - SAY_QUEST_ACCEPTED = 0, - SAY_STAY_1 = 1, - SAY_STAY_2 = 2, - SAY_STAY_3 = 3, - SAY_STAY_4 = 4, - SAY_STAY_5 = 5, - SAY_STAY_6 = 6, - SAY_QUEST_COMPLETE = 7, - SAY_ATTACKED_1 = 8, - EMOTE_DISAPPEAR = 9 -}; - -class npc_stinky : public CreatureScript -{ -public: - npc_stinky() : CreatureScript("npc_stinky") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_stinkyAI(creature); - } - - bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override - { - if (quest->GetQuestId() == QUEST_STINKYS_ESCAPE_H || quest->GetQuestId() == QUEST_STINKYS_ESCAPE_A) - { - if (npc_stinkyAI* pEscortAI = CAST_AI(npc_stinky::npc_stinkyAI, creature->AI())) - { - creature->setFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE); - creature->SetStandState(UNIT_STAND_STATE_STAND); - creature->AI()->Talk(SAY_QUEST_ACCEPTED); - pEscortAI->Start(false, false, player->GetGUID()); - } - } - return true; - } - - struct npc_stinkyAI : public npc_escortAI - { - npc_stinkyAI(Creature* creature) : npc_escortAI(creature) { } - - void WaypointReached(uint32 waypointId) override - { - Player* player = GetPlayerForEscort(); - if (!player) - return; - - switch (waypointId) - { - case 7: - Talk(SAY_STAY_1, player); - break; - case 11: - Talk(SAY_STAY_2, player); - break; - case 25: - Talk(SAY_STAY_3, player); - break; - case 26: - Talk(SAY_STAY_4, player); - break; - case 27: - Talk(SAY_STAY_5, player); - break; - case 28: - Talk(SAY_STAY_6, player); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - break; - case 29: - me->SetStandState(UNIT_STAND_STATE_STAND); - break; - case 37: - Talk(SAY_QUEST_COMPLETE, player); - me->SetSpeed(MOVE_RUN, 1.2f, true); - me->SetWalk(false); - if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_H)) - player->GroupEventHappens(QUEST_STINKYS_ESCAPE_H, me); - if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_A)) - player->GroupEventHappens(QUEST_STINKYS_ESCAPE_A, me); - break; - case 39: - Talk(EMOTE_DISAPPEAR); - break; - } - } - - void EnterCombat(Unit* who) override - { - Talk(SAY_ATTACKED_1, who); - } - - void Reset() override { } - - void JustDied(Unit* /*killer*/) override - { - Player* player = GetPlayerForEscort(); - if (player && HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_H)) - player->FailQuest(QUEST_STINKYS_ESCAPE_H); - - if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_A)) - player->FailQuest(QUEST_STINKYS_ESCAPE_A); - } - } - - void UpdateAI(uint32 uiDiff) override - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - }; -}; enum SpellScripts { @@ -634,46 +415,13 @@ class spell_energize_aoe : public SpellScriptLoader } }; -/*###### -## go_blackhoof_cage -######*/ - -enum PrisonersOfTheGrimTotems -{ - NPC_THERAMORE_PRISONER = 23720, - SAY_FREE = 0, -}; - -class go_blackhoof_cage : public GameObjectScript -{ -public: - go_blackhoof_cage() : GameObjectScript("go_blackhoof_cage") { } - - bool OnGossipHello(Player* player, GameObject* go) override - { - go->UseDoorOrButton(); - if (Creature* prisoner = go->FindNearestCreature(NPC_THERAMORE_PRISONER, 1.0f)) - { - if (player) - player->KilledMonsterCredit(NPC_THERAMORE_PRISONER); - - prisoner->AI()->Talk(SAY_FREE); // We also emote cry here (handled in creature_text.emote) - prisoner->DespawnOrUnsummon(6000); - } - return true; - } -}; - void AddSC_dustwallow_marsh() { - new npc_risen_husk_spirit(); new npc_lady_jaina_proudmoore(); new npc_nat_pagle(); new npc_private_hendel(); new npc_zelfrax(); - new npc_stinky(); new spell_ooze_zap(); new spell_ooze_zap_channel_end(); new spell_energize_aoe(); - new go_blackhoof_cage(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index a5978d8f8fa..a3d23108038 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -364,7 +364,7 @@ class NecroticPlagueTargetCheck : public std::unary_function<Unit*, bool> bool operator()(Unit* unit) const { - if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->IsTotem() || unit->HasAura(SPELL_PLAGUE_AVOIDANCE)) + if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->GetTypeId() != TYPEID_PLAYER || unit->HasAura(SPELL_PLAGUE_AVOIDANCE)) return false; if ((_notAura1 && unit->HasAura(_notAura1)) || (_notAura2 && unit->HasAura(_notAura2))) return false; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 6fe7bb30056..7292850bef1 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -30,26 +30,23 @@ EndScriptData */ #include "naxxramas.h" #include "Player.h" -enum Yells +enum Texts { - //when shappiron dies. dialog between kel and lich king (in this order) - SAY_SAPP_DIALOG1 = 0, //not used - SAY_SAPP_DIALOG2_LICH = 1, //not used - SAY_SAPP_DIALOG3 = 2, //not used - SAY_SAPP_DIALOG4_LICH = 3, //not used - SAY_SAPP_DIALOG5 = 4, //not used - SAY_CAT_DIED = 5, //when cat dies, not used - //when each of the 4 wing bosses dies - SAY_TAUNT = 6, SAY_AGGRO = 7, SAY_SLAY = 8, SAY_DEATH = 9, SAY_CHAIN = 10, SAY_FROST_BLAST = 11, SAY_REQUEST_AID = 12, //start of phase 3 - SAY_ANSWER_REQUEST = 13, //lich king answer + EMOTE_PHASE_TWO = 13, SAY_SUMMON_MINIONS = 14, //start of phase 1 - SAY_SPECIAL = 15 + SAY_SPECIAL = 15, + + // The Lich King + SAY_ANSWER_REQUEST = 3, + + // Old World Trigger + SAY_GUARDIAN_SPAWNED = 0 }; enum Events @@ -70,7 +67,10 @@ enum Events EVENT_TRIGGER, EVENT_PHASE, - EVENT_MORTAL_WOUND + EVENT_MORTAL_WOUND, + + EVENT_ANSWER_REQUEST, + EVENT_SUMMON_GUARDIANS }; enum Spells @@ -123,6 +123,13 @@ enum Spells SPELL_MORTAL_WOUND = 28467 }; +enum Phases +{ + PHASE_ONE = 1, // Players move in the circle and Kel'Thuzad spawns his minions. + PHASE_TWO = 2, // Starts on a timer. + PHASE_THREE = 3 // At 45% health. +}; + enum Creatures { NPC_WASTE = 16427, // Soldiers of the Frozen Wastes @@ -270,15 +277,11 @@ public: void Initialize() { nGuardiansOfIcecrownCount = 0; - uiGuardiansOfIcecrownTimer = 5000; // 5 seconds for summoning each Guardian of Icecrown in phase 3 - Phase = 0; nAbomination = 0; nWeaver = 0; } - uint32 Phase; - uint32 uiGuardiansOfIcecrownTimer; uint32 uiFaction; uint8 nGuardiansOfIcecrownCount; @@ -345,7 +348,6 @@ public: void EnterCombat(Unit* /*who*/) override { me->setFaction(uiFaction); - _EnterCombat(); for (uint8 i = 0; i <= 3; ++i) { @@ -354,10 +356,10 @@ public: } DoCast(me, SPELL_KELTHUZAD_CHANNEL, false); Talk(SAY_SUMMON_MINIONS); - Phase = 1; me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4); me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4); + events.SetPhase(PHASE_ONE); events.ScheduleEvent(EVENT_TRIGGER, 5000); events.ScheduleEvent(EVENT_WASTE, 15000); events.ScheduleEvent(EVENT_ABOMIN, 30000); @@ -365,6 +367,23 @@ public: events.ScheduleEvent(EVENT_PHASE, 228000); } + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (events.IsInPhase(PHASE_TWO) && me->HealthBelowPctDamaged(45, damage)) + { + Talk(SAY_REQUEST_AID); + events.SetPhase(PHASE_THREE); + events.ScheduleEvent(EVENT_ANSWER_REQUEST, 4000); + + for (uint8 i = 0; i <= 3; ++i) + { + if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_PORTAL01 + i))) + if (portal->getLootState() == GO_READY) + portal->UseDoorOrButton(); + } + } + } + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) @@ -372,7 +391,7 @@ public: events.Update(diff); - if (Phase == 1) + if (events.IsInPhase(PHASE_ONE)) { while (uint32 eventId = events.ExecuteEvent()) { @@ -405,6 +424,7 @@ public: case EVENT_PHASE: events.Reset(); Talk(SAY_AGGRO); + Talk(EMOTE_PHASE_TWO); spawns.DespawnAll(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); me->CastStop(); @@ -417,7 +437,7 @@ public: events.ScheduleEvent(EVENT_BLAST, urand(60000, 120000)); if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) events.ScheduleEvent(EVENT_CHAIN, urand(30000, 60000)); - Phase = 2; + events.SetPhase(PHASE_TWO); break; default: break; @@ -426,38 +446,6 @@ public: } else { - //start phase 3 when we are 45% health - if (Phase != 3) - { - if (HealthBelowPct(45)) - { - Phase = 3; - Talk(SAY_REQUEST_AID); - //here Lich King should respond to KelThuzad but I don't know which Creature to make talk - //so for now just make Kelthuzad says it. - Talk(SAY_ANSWER_REQUEST); - - for (uint8 i = 0; i <= 3; ++i) - { - if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_PORTAL01 + i))) - if (portal->getLootState() == GO_READY) - portal->UseDoorOrButton(); - } - } - } - else if (nGuardiansOfIcecrownCount < RAID_MODE(2, 4)) - { - if (uiGuardiansOfIcecrownTimer <= diff) - { - /// @todo Add missing text - if (Creature* guardian = DoSummon(NPC_ICECROWN, Pos[RAND(2, 5, 8, 11)])) - guardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2); - ++nGuardiansOfIcecrownCount; - uiGuardiansOfIcecrownTimer = 5000; - } - else uiGuardiansOfIcecrownTimer -= diff; - } - if (me->HasUnitState(UNIT_STATE_CASTING)) return; @@ -609,6 +597,18 @@ public: Talk(SAY_FROST_BLAST); events.Repeat(30000, 90000); break; + case EVENT_ANSWER_REQUEST: + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_LICH_KING))) + lichKing->AI()->Talk(SAY_ANSWER_REQUEST); + events.ScheduleEvent(EVENT_SUMMON_GUARDIANS, 5000); + break; + case EVENT_SUMMON_GUARDIANS: + if (Creature* guardian = DoSummon(NPC_ICECROWN, Pos[RAND(2, 5, 8, 11)])) + guardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2); + ++nGuardiansOfIcecrownCount; + if (nGuardiansOfIcecrownCount < RAID_MODE(2, 4)) + events.ScheduleEvent(EVENT_SUMMON_GUARDIANS, 5000); + break; default: break; } diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 4151c4a85a7..e5895d78ab3 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -69,6 +69,15 @@ MinionData const minionData[] = { 0, 0, } }; +ObjectData const objectData[] = +{ + { GO_NAXX_PORTAL_ARACHNID, DATA_NAXX_PORTAL_ARACHNID }, + { GO_NAXX_PORTAL_CONSTRUCT, DATA_NAXX_PORTAL_CONSTRUCT }, + { GO_NAXX_PORTAL_PLAGUE, DATA_NAXX_PORTAL_PLAGUE }, + { GO_NAXX_PORTAL_MILITARY, DATA_NAXX_PORTAL_MILITARY }, + { 0, 0, } +}; + float const HeiganPos[2] = { 2796.0f, -3707.0f }; float const HeiganEruptionSlope[3] = { @@ -111,10 +120,12 @@ class instance_naxxramas : public InstanceMapScript SetBossNumber(EncounterCount); LoadDoorData(doorData); LoadMinionData(minionData); + LoadObjectData(nullptr, objectData); minHorsemenDiedTime = 0; maxHorsemenDiedTime = 0; AbominationCount = 0; + CurrentWingTaunt = SAY_KELTHUZAD_FIRST_WING_TAUNT; playerDied = 0; } @@ -156,6 +167,9 @@ class instance_naxxramas : public InstanceMapScript case NPC_KEL_THUZAD: KelthuzadGUID = creature->GetGUID(); break; + case NPC_LICH_KING: + LichKingGUID = creature->GetGUID(); + break; default: break; } @@ -201,11 +215,30 @@ class instance_naxxramas : public InstanceMapScript case GO_KELTHUZAD_TRIGGER: KelthuzadTriggerGUID = go->GetGUID(); break; + case GO_ROOM_KELTHUZAD: + KelthuzadDoorGUID = go->GetGUID(); + break; + case GO_NAXX_PORTAL_ARACHNID: + if (GetBossState(BOSS_MAEXXNA) == DONE) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + case GO_NAXX_PORTAL_CONSTRUCT: + if (GetBossState(BOSS_THADDIUS) == DONE) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + case GO_NAXX_PORTAL_PLAGUE: + if (GetBossState(BOSS_LOATHEB) == DONE) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + case GO_NAXX_PORTAL_MILITARY: + if (GetBossState(BOSS_HORSEMEN) == DONE) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; default: break; } - AddDoor(go, true); + InstanceScript::OnGameObjectCreate(go); } void OnGameObjectRemove(GameObject* go) override @@ -232,7 +265,7 @@ class instance_naxxramas : public InstanceMapScript break; } - AddDoor(go, false); + InstanceScript::OnGameObjectRemove(go); } void OnUnitDeath(Unit* unit) override @@ -242,6 +275,15 @@ class instance_naxxramas : public InstanceMapScript playerDied = 1; SaveToDB(); } + + if (Creature* creature = unit->ToCreature()) + if (creature->GetEntry() == NPC_BIGGLESWORTH) + { + // Loads Kel'Thuzad's grid. We need this as he must be active in order for his texts to work. + instance->LoadGrid(3749.67f, -5114.06f); + if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) + kelthuzad->AI()->Talk(SAY_KELTHUZAD_CAT_DIED); + } } void SetData(uint32 id, uint32 value) override @@ -327,6 +369,8 @@ class instance_naxxramas : public InstanceMapScript return PortalsGUID[3]; case DATA_KELTHUZAD_TRIGGER: return KelthuzadTriggerGUID; + case DATA_LICH_KING: + return LichKingGUID; } return ObjectGuid::Empty; @@ -337,18 +381,156 @@ class instance_naxxramas : public InstanceMapScript if (!InstanceScript::SetBossState(id, state)) return false; - if (id == BOSS_HORSEMEN && state == DONE) + switch (id) { - if (GameObject* horsemenChest = instance->GetGameObject(HorsemenChestGUID)) - { - horsemenChest->SetRespawnTime(horsemenChest->GetRespawnDelay()); - horsemenChest->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - } + case BOSS_MAEXXNA: + if (state == DONE) + { + if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_ARACHNID)) + teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); + } + break; + case BOSS_LOATHEB: + if (state == DONE) + { + if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_PLAGUE)) + teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); + } + break; + case BOSS_THADDIUS: + if (state == DONE) + { + if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_CONSTRUCT)) + teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); + } + break; + case BOSS_GOTHIK: + if (state == DONE) + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ, 10000); + break; + case BOSS_HORSEMEN: + if (state == DONE) + { + if (GameObject* horsemenChest = instance->GetGameObject(HorsemenChestGUID)) + { + horsemenChest->SetRespawnTime(horsemenChest->GetRespawnDelay()); + horsemenChest->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + + if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_MILITARY)) + teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); + } + break; + case BOSS_SAPPHIRON: + if (state == DONE) + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD, 6000); + break; + default: + break; } return true; } + void Update(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DIALOGUE_GOTHIK_KORTHAZZ: + if (Creature* korthazz = instance->GetCreature(ThaneGUID)) + korthazz->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK, 5000); + break; + case EVENT_DIALOGUE_GOTHIK_ZELIEK: + if (Creature* zeliek = instance->GetCreature(SirGUID)) + zeliek->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX, 6000); + break; + case EVENT_DIALOGUE_GOTHIK_BLAUMEUX: + if (Creature* blaumeux = instance->GetCreature(LadyGUID)) + blaumeux->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE, 6000); + break; + case EVENT_DIALOGUE_GOTHIK_RIVENDARE: + if (Creature* rivendare = instance->GetCreature(BaronGUID)) + rivendare->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX2, 6000); + break; + case EVENT_DIALOGUE_GOTHIK_BLAUMEUX2: + if (Creature* blaumeux = instance->GetCreature(LadyGUID)) + blaumeux->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK2, 6000); + break; + case EVENT_DIALOGUE_GOTHIK_ZELIEK2: + if (Creature* zeliek = instance->GetCreature(SirGUID)) + zeliek->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ2, 6000); + break; + case EVENT_DIALOGUE_GOTHIK_KORTHAZZ2: + if (Creature* korthazz = instance->GetCreature(ThaneGUID)) + korthazz->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE2, 6000); + break; + case EVENT_DIALOGUE_GOTHIK_RIVENDARE2: + if (Creature* rivendare = instance->GetCreature(BaronGUID)) + rivendare->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2); + break; + case EVENT_KELTHUZAD_WING_TAUNT: + // Loads Kel'Thuzad's grid. We need this as he must be active in order for his texts to work. + instance->LoadGrid(3749.67f, -5114.06f); + if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) + kelthuzad->AI()->Talk(CurrentWingTaunt); + ++CurrentWingTaunt; + break; + case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD: + if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) + kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD); + HandleGameObject(KelthuzadDoorGUID, false); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING, 6000); + break; + case EVENT_DIALOGUE_SAPPHIRON_LICHKING: + if (Creature* lichKing = instance->GetCreature(LichKingGUID)) + lichKing->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_LICH_KING); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2, 16000); + break; + case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2: + if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) + kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD2); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING2, 9000); + break; + case EVENT_DIALOGUE_SAPPHIRON_LICHKING2: + if (Creature* lichKing = instance->GetCreature(LichKingGUID)) + lichKing->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_LICH_KING2); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3, 12000); + break; + case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3: + if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) + kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD3); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4, 6000); + break; + case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4: + if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) + kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD4); + HandleGameObject(KelthuzadDoorGUID, true); + break; + default: + break; + } + } + } + void HeiganErupt(uint32 section) { for (uint32 i = 0; i < 4; ++i) @@ -450,10 +632,15 @@ class instance_naxxramas : public InstanceMapScript ObjectGuid KelthuzadGUID; ObjectGuid KelthuzadTriggerGUID; ObjectGuid PortalsGUID[4]; + ObjectGuid KelthuzadDoorGUID; + ObjectGuid LichKingGUID; uint8 AbominationCount; + uint8 CurrentWingTaunt; /* The Immortal / The Undying */ uint32 playerDied; + + EventMap events; }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index 8325271a403..0f710a66bbe 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -52,6 +52,11 @@ enum Data DATA_HORSEMEN2, DATA_HORSEMEN3, DATA_ABOMINATION_KILLED, + + DATA_NAXX_PORTAL_ARACHNID, + DATA_NAXX_PORTAL_CONSTRUCT, + DATA_NAXX_PORTAL_PLAGUE, + DATA_NAXX_PORTAL_MILITARY }; enum Data64 @@ -71,6 +76,7 @@ enum Data64 DATA_KELTHUZAD_PORTAL03, DATA_KELTHUZAD_PORTAL04, DATA_KELTHUZAD_TRIGGER, + DATA_LICH_KING }; enum CreaturesIds @@ -89,7 +95,10 @@ enum CreaturesIds NPC_CRYPT_GUARD = 16573, NPC_NAXXRAMAS_FOLLOWER = 16505, NPC_FOLLOWER_WORSHIPPER = 16506, - NPC_DK_UNDERSTUDY = 16803 + NPC_DK_UNDERSTUDY = 16803, + NPC_BIGGLESWORTH = 16998, + NPC_LICH_KING = 16980, + NPC_OLD_WORLD_TRIGGER = 15384 }; enum GameObjectsIds @@ -133,7 +142,13 @@ enum GameObjectsIds GO_CONS_EYE_RAMP_BOSS = 181232, GO_CONS_NOX_TESLA_FEUGEN = 181477, GO_CONS_NOX_TESLA_STALAGG = 181478, - GO_BIRTH = 181356 + GO_BIRTH = 181356, + + // Teleporting pads spawned by the end of every quarter. + GO_NAXX_PORTAL_ARACHNID = 181575, + GO_NAXX_PORTAL_CONSTRUCT = 181576, + GO_NAXX_PORTAL_PLAGUE = 181577, + GO_NAXX_PORTAL_MILITARY = 181578 }; enum SpellIds @@ -142,6 +157,50 @@ enum SpellIds SPELL_SLIME = 28801 }; +enum InstanceEvents +{ + // Dialogue that happens after Gothik's death. + EVENT_DIALOGUE_GOTHIK_KORTHAZZ = 1, + EVENT_DIALOGUE_GOTHIK_ZELIEK, + EVENT_DIALOGUE_GOTHIK_BLAUMEUX, + EVENT_DIALOGUE_GOTHIK_RIVENDARE, + EVENT_DIALOGUE_GOTHIK_BLAUMEUX2, + EVENT_DIALOGUE_GOTHIK_ZELIEK2, + EVENT_DIALOGUE_GOTHIK_KORTHAZZ2, + EVENT_DIALOGUE_GOTHIK_RIVENDARE2, + + // Dialogue that happens after each wing. + EVENT_KELTHUZAD_WING_TAUNT, + + // Dialogue that happens after Sapphiron's death. + EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD, + EVENT_DIALOGUE_SAPPHIRON_LICHKING, + EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2, + EVENT_DIALOGUE_SAPPHIRON_LICHKING2, + EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3, + EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4 +}; + +enum InstanceTexts +{ + // The Four Horsemen + SAY_DIALOGUE_GOTHIK_HORSEMAN = 5, + SAY_DIALOGUE_GOTHIK_HORSEMAN2 = 6, + + // Kel'Thuzad + SAY_DIALOGUE_SAPPHIRON_KELTHUZAD = 0, + SAY_DIALOGUE_SAPPHIRON_KELTHUZAD2 = 2, + SAY_DIALOGUE_SAPPHIRON_KELTHUZAD3 = 4, + SAY_DIALOGUE_SAPPHIRON_KELTHUZAD4 = 20, + + SAY_KELTHUZAD_CAT_DIED = 5, + SAY_KELTHUZAD_FIRST_WING_TAUNT = 16, + + // Lich King + SAY_DIALOGUE_SAPPHIRON_LICH_KING = 1, + SAY_DIALOGUE_SAPPHIRON_LICH_KING2 = 2 +}; + /* template<class AI> CreatureAI* GetNaxxramasAI(Creature* creature) diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp index ed08296acd8..dac06186dff 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp @@ -100,21 +100,21 @@ class boss_anomalus : public CreatureScript { Initialize(); - instance->SetData(DATA_ANOMALUS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_ANOMALUS, NOT_STARTED); } void EnterCombat(Unit* /*who*/) override { Talk(SAY_AGGRO); - instance->SetData(DATA_ANOMALUS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_ANOMALUS, IN_PROGRESS); } void JustDied(Unit* /*killer*/) override { Talk(SAY_DEATH); - instance->SetData(DATA_ANOMALUS_EVENT, DONE); + instance->SetBossState(DATA_ANOMALUS, DONE); } uint32 GetData(uint32 type) const override diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp index 6b3df5ef665..a8ffb1d542e 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp @@ -101,7 +101,7 @@ public: RemovePrison(CheckContainmentSpheres()); - instance->SetData(DATA_KERISTRASZA_EVENT, NOT_STARTED); + instance->SetBossState(DATA_KERISTRASZA, NOT_STARTED); } void EnterCombat(Unit* /*who*/) override @@ -109,14 +109,14 @@ public: Talk(SAY_AGGRO); DoCastAOE(SPELL_INTENSE_COLD); - instance->SetData(DATA_KERISTRASZA_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_KERISTRASZA, IN_PROGRESS); } void JustDied(Unit* /*killer*/) override { Talk(SAY_DEATH); - instance->SetData(DATA_KERISTRASZA_EVENT, DONE); + instance->SetBossState(DATA_KERISTRASZA, DONE); } void KilledUnit(Unit* who) override diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp index 8c58a65cdbe..1df5f5eac8f 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp @@ -31,7 +31,9 @@ enum Spells SPELL_FIRE_MAGUS_VISUAL = 47705, SPELL_FROST_MAGUS_VISUAL = 47706, - SPELL_ARCANE_MAGUS_VISUAL = 47704 + SPELL_ARCANE_MAGUS_VISUAL = 47704, + + SPELL_WEAR_CHRISTMAS_HAT = 61400 }; enum Creatures @@ -53,7 +55,9 @@ enum Yells enum Misc { ACTION_MAGUS_DEAD = 1, - DATA_SPLIT_PERSONALITY = 2 + DATA_SPLIT_PERSONALITY = 2, + + GAME_EVENT_WINTER_VEIL = 2, }; const Position CenterOfRoom = {504.80f, 89.07f, -16.12f, 6.27f}; @@ -128,21 +132,24 @@ public: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetVisible(true); - instance->SetData(DATA_MAGUS_TELESTRA_EVENT, NOT_STARTED); + instance->SetBossState(DATA_MAGUS_TELESTRA, NOT_STARTED); + + if (IsHeroic() && sGameEventMgr->IsActiveEvent(GAME_EVENT_WINTER_VEIL) && !me->HasAura(SPELL_WEAR_CHRISTMAS_HAT)) + me->AddAura(SPELL_WEAR_CHRISTMAS_HAT, me); } void EnterCombat(Unit* /*who*/) override { Talk(SAY_AGGRO); - instance->SetData(DATA_MAGUS_TELESTRA_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_MAGUS_TELESTRA, IN_PROGRESS); } void JustDied(Unit* /*killer*/) override { Talk(SAY_DEATH); - instance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE); + instance->SetBossState(DATA_MAGUS_TELESTRA, DONE); } void KilledUnit(Unit* who) override diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp index 84523c1864d..f065f0679fc 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp @@ -68,7 +68,7 @@ public: struct boss_ormorokAI : public BossAI { - boss_ormorokAI(Creature* creature) : BossAI(creature, DATA_ORMOROK_EVENT) + boss_ormorokAI(Creature* creature) : BossAI(creature, DATA_ORMOROK) { Initialize(); } @@ -95,8 +95,6 @@ public: events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000); Talk(SAY_AGGRO); - - instance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS); } void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override @@ -112,10 +110,7 @@ public: void JustDied(Unit* /*killer*/) override { _JustDied(); - Talk(SAY_DEATH); - - instance->SetData(DATA_ORMOROK_EVENT, DONE); } void KilledUnit(Unit* who) override @@ -138,27 +133,27 @@ public: { switch (eventId) { - case EVENT_TRAMPLE: - DoCast(me, SPELL_TRAMPLE); - events.ScheduleEvent(EVENT_TRAMPLE, 10000); - break; - case EVENT_SPELL_REFLECTION: - Talk(SAY_REFLECT); - DoCast(me, SPELL_SPELL_REFLECTION); - events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000); - break; - case EVENT_CRYSTAL_SPIKES: - Talk(SAY_CRYSTAL_SPIKES); - DoCast(SPELL_CRYSTAL_SPIKES); - events.ScheduleEvent(EVENT_CRYSTAL_SPIKES, 12000); - break; - case EVENT_CRYSTALLINE_TANGLER: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, OrmorokTanglerPredicate(me))) - DoCast(target, SPELL_SUMMON_CRYSTALLINE_TANGLER); - events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000); - break; - default: - break; + case EVENT_TRAMPLE: + DoCast(me, SPELL_TRAMPLE); + events.ScheduleEvent(EVENT_TRAMPLE, 10000); + break; + case EVENT_SPELL_REFLECTION: + Talk(SAY_REFLECT); + DoCast(me, SPELL_SPELL_REFLECTION); + events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000); + break; + case EVENT_CRYSTAL_SPIKES: + Talk(SAY_CRYSTAL_SPIKES); + DoCast(SPELL_CRYSTAL_SPIKES); + events.ScheduleEvent(EVENT_CRYSTAL_SPIKES, 12000); + break; + case EVENT_CRYSTALLINE_TANGLER: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, OrmorokTanglerPredicate(me))) + DoCast(target, SPELL_SUMMON_CRYSTALLINE_TANGLER); + events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000); + break; + default: + break; } } diff --git a/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp index b7f2e23616b..b3b2cdd540f 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp @@ -18,10 +18,8 @@ #include "ScriptMgr.h" #include "InstanceScript.h" -#include "nexus.h" #include "Player.h" - -#define NUMBER_OF_ENCOUNTERS 4 +#include "nexus.h" enum Factions { @@ -30,229 +28,163 @@ enum Factions class instance_nexus : public InstanceMapScript { -public: - instance_nexus() : InstanceMapScript("instance_nexus", 576) { } - - InstanceScript* GetInstanceScript(InstanceMap* map) const override - { - return new instance_nexus_InstanceMapScript(map); - } + public: + instance_nexus() : InstanceMapScript(NexusScriptName, 576) { } - struct instance_nexus_InstanceMapScript : public InstanceScript - { - instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map) + struct instance_nexus_InstanceMapScript : public InstanceScript { - SetHeaders(DataHeader); - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - uint32 m_auiEncounter[NUMBER_OF_ENCOUNTERS]; - - ObjectGuid Anomalus; - ObjectGuid Keristrasza; - - ObjectGuid AnomalusContainmentSphere; - ObjectGuid OrmoroksContainmentSphere; - ObjectGuid TelestrasContainmentSphere; - - std::string strInstData; - - void OnCreatureCreate(Creature* creature) override - { - Map::PlayerList const &players = instance->GetPlayers(); - uint32 TeamInInstance = 0; - - if (!players.isEmpty()) + instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map) { - if (Player* player = players.begin()->GetSource()) - TeamInInstance = player->GetTeam(); + SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + _teamInInstance = 0; } - switch (creature->GetEntry()) + + void OnPlayerEnter(Player* player) override { - case 26763: - Anomalus = creature->GetGUID(); - break; - case 26723: - Keristrasza = creature->GetGUID(); - break; - // Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs. - case 26800: - { - if (ServerAllowsTwoSideGroups()) - creature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - creature->UpdateEntry(26799); - break; - } - case 26802: - { - if (ServerAllowsTwoSideGroups()) - creature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - creature->UpdateEntry(26801); - break; - } - case 26805: - { - if (ServerAllowsTwoSideGroups()) - creature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - creature->UpdateEntry(26803); - break; - } - case 27949: - { - if (ServerAllowsTwoSideGroups()) - creature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - creature->UpdateEntry(27947); - break; - } - case 26796: - { - if (ServerAllowsTwoSideGroups()) - creature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - creature->UpdateEntry(26798); - break; - } + if (!_teamInInstance) + _teamInInstance = player->GetTeam(); } - } - void OnGameObjectCreate(GameObject* go) override - { - switch (go->GetEntry()) + void OnCreatureCreate(Creature* creature) override { - case 188527: - { - AnomalusContainmentSphere = go->GetGUID(); - if (m_auiEncounter[1] == DONE) - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - break; - } - case 188528: - { - OrmoroksContainmentSphere = go->GetGUID(); - if (m_auiEncounter[2] == DONE) - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - break; - } - case 188526: + switch (creature->GetEntry()) { - TelestrasContainmentSphere = go->GetGUID(); - if (m_auiEncounter[0] == DONE) - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - break; + case NPC_ANOMALUS: + AnomalusGUID = creature->GetGUID(); + break; + case NPC_KERISTRASZA: + KeristraszaGUID = creature->GetGUID(); + break; + // Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs. + case NPC_ALLIANCE_BERSERKER: + if (ServerAllowsTwoSideGroups()) + creature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_HORDE_BERSERKER); + break; + case NPC_ALLIANCE_RANGER: + if (ServerAllowsTwoSideGroups()) + creature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_HORDE_RANGER); + break; + case NPC_ALLIANCE_CLERIC: + if (ServerAllowsTwoSideGroups()) + creature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_HORDE_CLERIC); + break; + case NPC_ALLIANCE_COMMANDER: + if (ServerAllowsTwoSideGroups()) + creature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_HORDE_COMMANDER); + break; + case NPC_COMMANDER_STOUTBEARD: + if (ServerAllowsTwoSideGroups()) + creature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_COMMANDER_KOLURG); + break; + default: + break; } } - } - - uint32 GetData(uint32 identifier) const override - { - switch (identifier) - { - case DATA_MAGUS_TELESTRA_EVENT: return m_auiEncounter[0]; - case DATA_ANOMALUS_EVENT: return m_auiEncounter[1]; - case DATA_ORMOROK_EVENT: return m_auiEncounter[2]; - case DATA_KERISTRASZA_EVENT: return m_auiEncounter[3]; - } - return 0; - } - void SetData(uint32 identifier, uint32 data) override - { - switch (identifier) + void OnGameObjectCreate(GameObject* go) override { - case DATA_MAGUS_TELESTRA_EVENT: + switch (go->GetEntry()) { - if (data == DONE) - { - GameObject* Sphere = instance->GetGameObject(TelestrasContainmentSphere); - if (Sphere) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - } - m_auiEncounter[0] = data; - break; + case GO_ANOMALUS_CONTAINMET_SPHERE: + AnomalusContainmentSphere = go->GetGUID(); + if (GetBossState(DATA_ANOMALUS) == DONE) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + case GO_ORMOROKS_CONTAINMET_SPHERE: + OrmoroksContainmentSphere = go->GetGUID(); + if (GetBossState(DATA_ORMOROK) == DONE) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + case GO_TELESTRAS_CONTAINMET_SPHERE: + TelestrasContainmentSphere = go->GetGUID(); + if (GetBossState(DATA_MAGUS_TELESTRA) == DONE) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + default: + break; } - case DATA_ANOMALUS_EVENT: - { - if (data == DONE) - { - if (GameObject* Sphere = instance->GetGameObject(AnomalusContainmentSphere)) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - } - m_auiEncounter[1] = data; - break; - } - case DATA_ORMOROK_EVENT: - { - if (data == DONE) - { - if (GameObject* Sphere = instance->GetGameObject(OrmoroksContainmentSphere)) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - } - m_auiEncounter[2] = data; - break; - } - case DATA_KERISTRASZA_EVENT: - m_auiEncounter[3] = data; - break; } - if (data == DONE) + bool SetBossState(uint32 type, EncounterState state) override { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' - << m_auiEncounter[3]; + if (!InstanceScript::SetBossState(type, state)) + return false; - strInstData = saveStream.str(); + switch (type) + { + case DATA_MAGUS_TELESTRA: + if (state == DONE) + { + if (GameObject* sphere = instance->GetGameObject(TelestrasContainmentSphere)) + sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + break; + case DATA_ANOMALUS: + if (state == DONE) + { + if (GameObject* sphere = instance->GetGameObject(AnomalusContainmentSphere)) + sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + break; + case DATA_ORMOROK: + if (state == DONE) + { + if (GameObject* sphere = instance->GetGameObject(OrmoroksContainmentSphere)) + sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + break; + default: + break; + } - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; + return true; } - } - ObjectGuid GetGuidData(uint32 uiIdentifier) const override - { - switch (uiIdentifier) + ObjectGuid GetGuidData(uint32 type) const override { - case DATA_ANOMALUS: return Anomalus; - case DATA_KERISTRASZA: return Keristrasza; - case ANOMALUS_CONTAINMET_SPHERE: return AnomalusContainmentSphere; - case ORMOROKS_CONTAINMET_SPHERE: return OrmoroksContainmentSphere; - case TELESTRAS_CONTAINMET_SPHERE: return TelestrasContainmentSphere; - } - return ObjectGuid::Empty; - } - - std::string GetSaveData() override - { - return strInstData; - } + switch (type) + { + case DATA_ANOMALUS: + return AnomalusGUID; + case DATA_KERISTRASZA: + return KeristraszaGUID; + case ANOMALUS_CONTAINMET_SPHERE: + return AnomalusContainmentSphere; + case ORMOROKS_CONTAINMET_SPHERE: + return OrmoroksContainmentSphere; + case TELESTRAS_CONTAINMET_SPHERE: + return TelestrasContainmentSphere; + default: + break; + } - void Load(const char *chrIn) - { - if (!chrIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; + return ObjectGuid::Empty; } - OUT_LOAD_INST_DATA(chrIn); - - std::istringstream loadStream(chrIn); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + private: + ObjectGuid AnomalusGUID; + ObjectGuid KeristraszaGUID; + ObjectGuid AnomalusContainmentSphere; + ObjectGuid OrmoroksContainmentSphere; + ObjectGuid TelestrasContainmentSphere; + uint32 _teamInInstance; + }; - for (uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; + InstanceScript* GetInstanceScript(InstanceMap* map) const override + { + return new instance_nexus_InstanceMapScript(map); } - }; - }; void AddSC_instance_nexus() diff --git a/src/server/scripts/Northrend/Nexus/Nexus/nexus.h b/src/server/scripts/Northrend/Nexus/Nexus/nexus.h index c9f5d44c932..9962b0c884d 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/nexus.h +++ b/src/server/scripts/Northrend/Nexus/Nexus/nexus.h @@ -18,21 +18,48 @@ #ifndef DEF_NEXUS_H #define DEF_NEXUS_H +#define NexusScriptName "instance_nexus" #define DataHeader "NEX" +uint32 const EncounterCount = 4; + enum DataTypes { - DATA_MAGUS_TELESTRA_EVENT, - DATA_ANOMALUS_EVENT, - DATA_ORMOROK_EVENT, - DATA_KERISTRASZA_EVENT, + DATA_MAGUS_TELESTRA = 0, + DATA_ANOMALUS = 1, + DATA_ORMOROK = 2, + DATA_KERISTRASZA = 3, + + ANOMALUS_CONTAINMET_SPHERE = 4, + ORMOROKS_CONTAINMET_SPHERE = 5, + TELESTRAS_CONTAINMET_SPHERE = 6 +}; - DATA_ANOMALUS, - DATA_KERISTRASZA, +enum CreatureIds +{ + NPC_ANOMALUS = 26763, + NPC_KERISTRASZA = 26723, + + // Alliance + NPC_ALLIANCE_BERSERKER = 26800, + NPC_ALLIANCE_RANGER = 26802, + NPC_ALLIANCE_CLERIC = 26805, + NPC_ALLIANCE_COMMANDER = 27949, + NPC_COMMANDER_STOUTBEARD = 26796, + + // Horde + NPC_HORDE_BERSERKER = 26799, + NPC_HORDE_RANGER = 26801, + NPC_HORDE_CLERIC = 26803, + NPC_HORDE_COMMANDER = 27947, + NPC_COMMANDER_KOLURG = 26798 +}; - ANOMALUS_CONTAINMET_SPHERE, - ORMOROKS_CONTAINMET_SPHERE, - TELESTRAS_CONTAINMET_SPHERE +enum GameObjectIds +{ + GO_ANOMALUS_CONTAINMET_SPHERE = 188527, + GO_ORMOROKS_CONTAINMET_SPHERE = 188528, + GO_TELESTRAS_CONTAINMET_SPHERE = 188526 }; #endif diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp index 1c5aadc3581..24a712d9d38 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -192,6 +192,7 @@ class instance_oculus : public InstanceMapScript FreeDragons(); if (Creature* varos = instance->GetCreature(VarosGUID)) varos->SetPhaseMask(1, true); + events.ScheduleEvent(EVENT_VAROS_INTRO, 15000); } break; case DATA_VAROS: @@ -209,6 +210,7 @@ class instance_oculus : public InstanceMapScript { eregos->SetPhaseMask(1, true); GreaterWhelps(); + events.ScheduleEvent(EVENT_EREGOS_INTRO, 5000); } } break; @@ -267,6 +269,28 @@ class instance_oculus : public InstanceMapScript } } + void Update(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_VAROS_INTRO: + if (Creature* varos = instance->GetCreature(VarosGUID)) + varos->AI()->Talk(SAY_VAROS_INTRO_TEXT); + break; + case EVENT_EREGOS_INTRO: + if (Creature* eregos = instance->GetCreature(EregosGUID)) + eregos->AI()->Talk(SAY_EREGOS_INTRO_TEXT); + break; + default: + break; + } + } + } + void GreaterWhelps() { for (ObjectGuid guid : GreaterWhelpList) @@ -289,6 +313,8 @@ class instance_oculus : public InstanceMapScript ObjectGuid EregosCacheGUID; GuidList GreaterWhelpList; + + EventMap events; }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.h b/src/server/scripts/Northrend/Nexus/Oculus/oculus.h index 268cdb54e3e..d1144df9486 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.h +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.h @@ -79,6 +79,18 @@ enum OculusSpells SPELL_DEATH_SPELL = 50415 }; +enum InstanceTexts +{ + SAY_EREGOS_INTRO_TEXT = 0, + SAY_VAROS_INTRO_TEXT = 4 +}; + +enum InstanceEvents +{ + EVENT_VAROS_INTRO = 1, + EVENT_EREGOS_INTRO +}; + enum Misc { POINT_MOVE_OUT = 1 diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index fc29369c28f..8c7d0c2797f 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -28,7 +28,7 @@ EndScriptData */ #include "SpellScript.h" #include "halls_of_lightning.h" -enum Yells +enum Texts { SAY_INTRO_1 = 0, SAY_INTRO_2 = 1, @@ -51,6 +51,21 @@ enum Spells SPELL_PULSING_SHOCKWAVE_AURA = 59414 }; +enum Events +{ + EVENT_ARC_LIGHTNING = 1, + EVENT_LIGHTNING_NOVA, + EVENT_RESUME_PULSING_SHOCKWAVE, + EVENT_INTRO_DIALOGUE +}; + +enum Phases +{ + // Phases are used to allow executing the intro event while UpdateVictim() returns false and convenience. + PHASE_INTRO = 1, + PHASE_NORMAL +}; + enum Misc { ACHIEV_TIMELY_DEATH_START_EVENT = 20384 @@ -65,57 +80,41 @@ class boss_loken : public CreatureScript public: boss_loken() : CreatureScript("boss_loken") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_lokenAI>(creature); - } - - struct boss_lokenAI : public ScriptedAI + struct boss_lokenAI : public BossAI { - boss_lokenAI(Creature* creature) : ScriptedAI(creature) + boss_lokenAI(Creature* creature) : BossAI(creature, DATA_LOKEN) { Initialize(); - instance = creature->GetInstanceScript(); + _isIntroDone = false; } void Initialize() { - m_uiArcLightning_Timer = 15000; - m_uiLightningNova_Timer = 20000; - m_uiResumePulsingShockwave_Timer = 1000; - - m_uiHealthAmountModifier = 1; + _healthAmountModifier = 1; } - InstanceScript* instance; - - uint32 m_uiArcLightning_Timer; - uint32 m_uiLightningNova_Timer; - uint32 m_uiResumePulsingShockwave_Timer; - - uint32 m_uiHealthAmountModifier; - void Reset() override { Initialize(); - - instance->SetBossState(DATA_LOKEN, NOT_STARTED); + _Reset(); instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); } void EnterCombat(Unit* /*who*/) override { + _EnterCombat(); Talk(SAY_AGGRO); - - instance->SetBossState(DATA_LOKEN, IN_PROGRESS); + events.SetPhase(PHASE_NORMAL); + events.ScheduleEvent(EVENT_ARC_LIGHTNING, 15000); + events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 20000); + events.ScheduleEvent(EVENT_RESUME_PULSING_SHOCKWAVE, 1000); instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); } void JustDied(Unit* /*killer*/) override { Talk(SAY_DEATH); - - instance->SetBossState(DATA_LOKEN, DONE); + _JustDied(); instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PULSING_SHOCKWAVE_AURA); } @@ -125,66 +124,89 @@ public: Talk(SAY_SLAY); } - void UpdateAI(uint32 uiDiff) override + void MoveInLineOfSight(Unit* who) override { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_uiResumePulsingShockwave_Timer) + if (!_isIntroDone && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 40.0f)) { - if (m_uiResumePulsingShockwave_Timer <= uiDiff) - { - DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); - me->ClearUnitState(UNIT_STATE_CASTING); // this flag breaks movement - - DoCast(me, SPELL_PULSING_SHOCKWAVE, true); - m_uiResumePulsingShockwave_Timer = 0; - } - else - m_uiResumePulsingShockwave_Timer -= uiDiff; + _isIntroDone = true; + Talk(SAY_INTRO_1); + events.ScheduleEvent(EVENT_INTRO_DIALOGUE, 20000, 0, PHASE_INTRO); } + BossAI::MoveInLineOfSight(who); + } - if (m_uiArcLightning_Timer <= uiDiff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_ARC_LIGHTNING); + void UpdateAI(uint32 diff) override + { + if (events.IsInPhase(PHASE_NORMAL) && !UpdateVictim()) + return; - m_uiArcLightning_Timer = urand(15000, 16000); - } - else - m_uiArcLightning_Timer -= uiDiff; + events.Update(diff); - if (m_uiLightningNova_Timer <= uiDiff) + while (uint32 eventId = events.ExecuteEvent()) { - Talk(SAY_NOVA); - Talk(EMOTE_NOVA); - DoCast(me, SPELL_LIGHTNING_NOVA); - - me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_PULSING_SHOCKWAVE, me)); - m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura - m_uiLightningNova_Timer = urand(20000, 21000); + switch (eventId) + { + case EVENT_ARC_LIGHTNING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_ARC_LIGHTNING); + events.ScheduleEvent(EVENT_ARC_LIGHTNING, urand(15000, 16000)); + break; + case EVENT_LIGHTNING_NOVA: + Talk(SAY_NOVA); + Talk(EMOTE_NOVA); + DoCastAOE(SPELL_LIGHTNING_NOVA); + me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_PULSING_SHOCKWAVE, me)); + events.ScheduleEvent(EVENT_RESUME_PULSING_SHOCKWAVE, DUNGEON_MODE(5000, 4000)); // Pause Pulsing Shockwave aura + events.ScheduleEvent(EVENT_LIGHTNING_NOVA, urand(20000, 21000)); + break; + case EVENT_RESUME_PULSING_SHOCKWAVE: + DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); + me->ClearUnitState(UNIT_STATE_CASTING); // This flag breaks movement. + DoCast(me, SPELL_PULSING_SHOCKWAVE, true); + break; + case EVENT_INTRO_DIALOGUE: + Talk(SAY_INTRO_2); + events.SetPhase(PHASE_NORMAL); + break; + default: + break; + } } - else - m_uiLightningNova_Timer -= uiDiff; - // Health check - if (HealthBelowPct(100 - 25 * m_uiHealthAmountModifier)) + DoMeleeAttackIfReady(); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (me->HealthBelowPctDamaged(100 - 25 * _healthAmountModifier, damage)) { - switch (m_uiHealthAmountModifier) + switch (_healthAmountModifier) { - case 1: Talk(SAY_75HEALTH); break; - case 2: Talk(SAY_50HEALTH); break; - case 3: Talk(SAY_25HEALTH); break; + case 1: + Talk(SAY_75HEALTH); + break; + case 2: + Talk(SAY_50HEALTH); + break; + case 3: + Talk(SAY_25HEALTH); + break; + default: + break; } - - ++m_uiHealthAmountModifier; + ++_healthAmountModifier; } - - DoMeleeAttackIfReady(); } + + private: + uint32 _healthAmountModifier; + bool _isIntroDone; }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_lokenAI>(creature); + } }; class spell_loken_pulsing_shockwave : public SpellScriptLoader diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp index eff84365f63..b949c43b64d 100644 --- a/src/server/scripts/Northrend/zone_dragonblight.cpp +++ b/src/server/scripts/Northrend/zone_dragonblight.cpp @@ -366,48 +366,6 @@ class npc_commander_eligor_dawnbringer : public CreatureScript } }; -enum AlexstraszaWrGate -{ - // Quest - QUEST_RETURN_TO_AG_A = 12499, - QUEST_RETURN_TO_AG_H = 12500, - - // Movie - MOVIE_ID_GATES = 14 -}; - -#define GOSSIP_ITEM_WHAT_HAPPENED "Alexstrasza, can you show me what happened here?" - -class npc_alexstrasza_wr_gate : public CreatureScript -{ -public: - npc_alexstrasza_wr_gate() : CreatureScript("npc_alexstrasza_wr_gate") { } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestRewardStatus(QUEST_RETURN_TO_AG_A) || player->GetQuestRewardStatus(QUEST_RETURN_TO_AG_H)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WHAT_HAPPENED, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - return true; - } - - bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - player->CLOSE_GOSSIP_MENU(); - player->SendMovieStart(MOVIE_ID_GATES); - } - - return true; - } -}; - /*###### ## Quest Strengthen the Ancients (12096|12092) ######*/ @@ -746,7 +704,6 @@ class npc_torturer_lecraft : public CreatureScript void AddSC_dragonblight() { new npc_commander_eligor_dawnbringer(); - new npc_alexstrasza_wr_gate(); new spell_q12096_q12092_dummy(); new spell_q12096_q12092_bark(); new npc_wyrmrest_defender(); diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp index 7436ac8400f..2b317453992 100644 --- a/src/server/scripts/Northrend/zone_icecrown.cpp +++ b/src/server/scripts/Northrend/zone_icecrown.cpp @@ -210,52 +210,6 @@ public: }; /*###### -## npc_vereth_the_cunning -######*/ - -enum VerethTheCunning -{ - NPC_GEIST_RETURN_BUNNY_KC = 31049, - NPC_LITHE_STALKER = 30894, - SPELL_SUBDUED_LITHE_STALKER = 58151, -}; - -class npc_vereth_the_cunning : public CreatureScript -{ -public: - npc_vereth_the_cunning() : CreatureScript("npc_vereth_the_cunning") { } - - struct npc_vereth_the_cunningAI : public ScriptedAI - { - npc_vereth_the_cunningAI(Creature* creature) : ScriptedAI(creature) { } - - void MoveInLineOfSight(Unit* who) override - - { - ScriptedAI::MoveInLineOfSight(who); - - if (who->GetEntry() == NPC_LITHE_STALKER && me->IsWithinDistInMap(who, 10.0f)) - { - if (Unit* owner = who->GetCharmer()) - { - if (who->HasAura(SPELL_SUBDUED_LITHE_STALKER)) - { - owner->ToPlayer()->KilledMonsterCredit(NPC_GEIST_RETURN_BUNNY_KC); - who->ToCreature()->DisappearAndDie(); - - } - } - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_vereth_the_cunningAI(creature); - } -}; - -/*###### * npc_tournament_training_dummy ######*/ enum TournamentDummy @@ -881,207 +835,12 @@ class npc_frostbrood_skytalon : public CreatureScript } }; -/*###### -## The Flesh Giant Champion - Id: 13235 -######*/ -enum FleshGiant -{ - QUEST_FLESH_GIANT_CHAMPION = 13235, - - NPC_MORBIDUS = 30698, - NPC_LICH_KING = 31301, - NPC_OLAKIN = 31428, - NPC_DHAKAR = 31306, - - FACTION_HOSTILE = 14, - FACTION_BASIC = 2102, - - EVENT_INTRO = 1, - EVENT_LK_SAY_1 = 2, - EVENT_LK_SAY_2 = 3, - EVENT_LK_SAY_3 = 4, - EVENT_LK_SAY_4 = 5, - EVENT_LK_SAY_5 = 6, - EVENT_OUTRO = 7, - EVENT_START = 8, - - SPELL_SIMPLE_TELEPORT = 64195, - - SAY_DHAKAR_START = 0, - SAY_LK_1 = 0, - SAY_LK_2 = 1, - SAY_LK_3 = 2, - SAY_LK_4 = 3, - SAY_LK_5 = 4, - SAY_OLAKIN_PAY = 0 -}; - -class npc_margrave_dhakar : public CreatureScript -{ - public: - npc_margrave_dhakar() : CreatureScript("npc_margrave_dhakar") { } - - struct npc_margrave_dhakarAI : public ScriptedAI - { - npc_margrave_dhakarAI(Creature* creature) : ScriptedAI(creature) , _summons(me) { } - - void Reset() override - { - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - - _events.Reset(); - _summons.DespawnAll(); - } - - void sGossipSelect(Player* player, uint32 sender, uint32 action) override - { - if (player->GetQuestStatus(QUEST_FLESH_GIANT_CHAMPION) == QUEST_STATUS_INCOMPLETE && !player->IsInCombat()) - { - if (me->GetCreatureTemplate()->GossipMenuId == sender && !action) - { - _events.ScheduleEvent(EVENT_INTRO, 1000); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - } - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_INTRO: - { - Talk(SAY_DHAKAR_START); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); - - if (Creature* morbidus = me->FindNearestCreature(NPC_MORBIDUS, 50.0f, true)) - { - if (Creature* lichKing = me->SummonCreature(NPC_LICH_KING, morbidus->GetPositionX() + 10.0f, morbidus->GetPositionY(), morbidus->GetPositionZ())) - { - _lichKingGuid = lichKing->GetGUID(); - lichKing->SetFacingTo(morbidus->GetOrientation()); - lichKing->CastSpell(lichKing, SPELL_SIMPLE_TELEPORT, true); - } - } - - _events.ScheduleEvent(EVENT_LK_SAY_1, 5000); - break; - } - case EVENT_LK_SAY_1: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_1); - _events.ScheduleEvent(EVENT_LK_SAY_2, 5000); - break; - } - case EVENT_LK_SAY_2: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_2); - _events.ScheduleEvent(EVENT_LK_SAY_3, 5000); - break; - } - case EVENT_LK_SAY_3: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_3); - _events.ScheduleEvent(EVENT_LK_SAY_4, 5000); - break; - } - case EVENT_LK_SAY_4: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_4); - _events.ScheduleEvent(EVENT_OUTRO, 12000); - break; - } - case EVENT_LK_SAY_5: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_5); - _events.ScheduleEvent(EVENT_OUTRO, 8000); - break; - } - case EVENT_OUTRO: - { - if (Creature* olakin = me->FindNearestCreature(NPC_OLAKIN, 50.0f, true)) - olakin->AI()->Talk(SAY_OLAKIN_PAY); - - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->DespawnOrUnsummon(0); - - _events.ScheduleEvent(EVENT_START, 5000); - break; - } - case EVENT_START: - { - if (Creature* morbidus = me->FindNearestCreature(NPC_MORBIDUS, 50.0f, true)) - { - morbidus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_DISABLE_MOVE); - morbidus->setFaction(FACTION_HOSTILE); - } - - break; - } - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap _events; - SummonList _summons; - ObjectGuid _lichKingGuid; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_margrave_dhakarAI(creature); - } -}; - -class npc_morbidus : public CreatureScript -{ - public: - npc_morbidus() : CreatureScript("npc_morbidus") { } - - struct npc_morbidusAI : public ScriptedAI - { - npc_morbidusAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - if (Creature* dhakar = me->FindNearestCreature(NPC_DHAKAR, 50.0f, true)) - dhakar->AI()->Reset(); - - // this will prevent the event to start without morbidus being alive - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - me->setFaction(FACTION_BASIC); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_morbidusAI(creature); - } -}; - void AddSC_icecrown() { new npc_squire_david; new npc_argent_valiant; new npc_guardian_pavilion; - new npc_vereth_the_cunning; new npc_tournament_training_dummy; new npc_blessed_banner(); new npc_frostbrood_skytalon(); - new npc_margrave_dhakar(); - new npc_morbidus(); } diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp index 53fbf8f0cf7..1f55abf8a11 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp @@ -21,8 +21,14 @@ DoorData const doorData[] = { - { GO_IKISS_DOOR, DATA_TALON_KING_IKISS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_IKISS_DOOR, DATA_TALON_KING_IKISS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; + +ObjectData const gameObjectData[] = +{ + { GO_TALON_KING_COFFER, DATA_TALON_KING_COFFER }, + { 0, 0 } // END }; class instance_sethekk_halls : public InstanceMapScript @@ -37,6 +43,7 @@ class instance_sethekk_halls : public InstanceMapScript SetHeaders(DataHeader); SetBossNumber(EncounterCount); LoadDoorData(doorData); + LoadObjectData(nullptr, gameObjectData); } void OnCreatureCreate(Creature* creature) override @@ -50,16 +57,27 @@ class instance_sethekk_halls : public InstanceMapScript } } - void OnGameObjectCreate(GameObject* go) override + bool SetBossState(uint32 type, EncounterState state) override { - if (go->GetEntry() == GO_IKISS_DOOR) - AddDoor(go, true); - } + if (!InstanceScript::SetBossState(type, state)) + return false; - void OnGameObjectRemove(GameObject* go) override - { - if (go->GetEntry() == GO_IKISS_DOOR) - AddDoor(go, false); + switch (type) + { + case DATA_TALON_KING_IKISS: + if (state == DONE) + { + /// @workaround: GO_FLAG_INTERACT_COND remains on the gob, but it is not handled correctly in this case + /// gameobject should have GO_DYNFLAG_LO_ACTIVATE too, which makes gobs interactable with GO_FLAG_INTERACT_COND + /// so just removed GO_FLAG_INTERACT_COND + if (GameObject* coffer = GetGameObject(DATA_TALON_KING_COFFER)) + coffer->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE); + } + break; + default: + break; + } + return true; } }; diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h b/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h index 4b6bfab46cb..8cf01fb4635 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h @@ -28,7 +28,10 @@ enum DataTypes // Encounter States/Boss GUIDs DATA_DARKWEAVER_SYTH = 0, DATA_TALON_KING_IKISS = 1, - DATA_ANZU = 2 + DATA_ANZU = 2, + + // Additional Data + DATA_TALON_KING_COFFER = 3 }; enum CreatureIds @@ -39,7 +42,8 @@ enum CreatureIds enum GameObjectIds { - GO_IKISS_DOOR = 177203 + GO_IKISS_DOOR = 177203, + GO_TALON_KING_COFFER = 187372 }; template<class AI> diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp index f0884e83baa..794d3a490f6 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp @@ -31,21 +31,25 @@ class go_main_chambers_access_panel : public GameObjectScript return false; if (go->GetEntry() == GO_ACCESS_PANEL_HYDRO && (instance->GetBossState(DATA_HYDROMANCER_THESPIA) == DONE || instance->GetBossState(DATA_HYDROMANCER_THESPIA) == SPECIAL)) - { instance->SetBossState(DATA_HYDROMANCER_THESPIA, SPECIAL); - go->SetGoState(GO_STATE_ACTIVE); - } if (go->GetEntry() == GO_ACCESS_PANEL_MEK && (instance->GetBossState(DATA_MEKGINEER_STEAMRIGGER) == DONE || instance->GetBossState(DATA_MEKGINEER_STEAMRIGGER) == SPECIAL)) - { instance->SetBossState(DATA_MEKGINEER_STEAMRIGGER, SPECIAL); - go->SetGoState(GO_STATE_ACTIVE); - } + + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + go->SetGoState(GO_STATE_ACTIVE); return true; } }; +ObjectData const gameObjectData[] = +{ + { GO_ACCESS_PANEL_HYDRO, DATA_ACCESS_PANEL_HYDRO }, + { GO_ACCESS_PANEL_MEK, DATA_ACCESS_PANEL_MEK }, + { 0, 0 } // END +}; + class instance_steam_vault : public InstanceMapScript { public: @@ -57,6 +61,7 @@ class instance_steam_vault : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(EncounterCount); + LoadObjectData(nullptr, gameObjectData); DistillerState = 0; } @@ -89,6 +94,8 @@ class instance_steam_vault : public InstanceMapScript default: break; } + + InstanceScript::OnGameObjectCreate(go); } ObjectGuid GetGuidData(uint32 type) const override @@ -128,6 +135,9 @@ class instance_steam_vault : public InstanceMapScript switch (type) { case DATA_HYDROMANCER_THESPIA: + if (state == DONE) + if (GameObject* panel = GetGameObject(DATA_ACCESS_PANEL_HYDRO)) + panel->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); if (state == SPECIAL) { if (GetBossState(DATA_MEKGINEER_STEAMRIGGER) == SPECIAL) @@ -137,6 +147,9 @@ class instance_steam_vault : public InstanceMapScript } break; case DATA_MEKGINEER_STEAMRIGGER: + if (state == DONE) + if (GameObject* panel = GetGameObject(DATA_ACCESS_PANEL_MEK)) + panel->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); if (state == SPECIAL) { if (GetBossState(DATA_HYDROMANCER_THESPIA) == SPECIAL) diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h index 58f71b047ef..d18d0406dea 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h @@ -28,7 +28,11 @@ enum DataTypes DATA_HYDROMANCER_THESPIA = 0, DATA_MEKGINEER_STEAMRIGGER = 1, DATA_WARLORD_KALITHRESH = 2, - DATA_DISTILLER = 3 + DATA_DISTILLER = 3, + + // Additional Data + DATA_ACCESS_PANEL_HYDRO = 4, + DATA_ACCESS_PANEL_MEK = 5 }; enum CreatureIds diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 22968d70ff1..6717bec109f 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -69,7 +69,7 @@ class spell_hun_aspect_of_the_beast : public SpellScriptLoader bool Load() override { - return GetCaster()->GetTypeId() == TYPEID_PLAYER; + return GetOwner()->GetTypeId() == TYPEID_PLAYER; } bool Validate(SpellInfo const* /*spellInfo*/) override @@ -81,16 +81,16 @@ class spell_hun_aspect_of_the_beast : public SpellScriptLoader void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (Player* caster = GetCaster()->ToPlayer()) - if (Pet* pet = caster->GetPet()) - pet->RemoveAurasDueToSpell(SPELL_HUNTER_ASPECT_OF_THE_BEAST_PET); + Player* player = GetTarget()->ToPlayer(); + if (Pet* pet = player->GetPet()) + pet->RemoveAurasDueToSpell(SPELL_HUNTER_ASPECT_OF_THE_BEAST_PET); } void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (Player* caster = GetCaster()->ToPlayer()) - if (caster->GetPet()) - caster->CastSpell(caster, SPELL_HUNTER_ASPECT_OF_THE_BEAST_PET, true); + Player* player = GetTarget()->ToPlayer(); + if (player->GetPet()) + player->CastSpell(player, SPELL_HUNTER_ASPECT_OF_THE_BEAST_PET, true); } void Register() override diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index e35f7c9b70e..28680c9d1ce 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -40,8 +40,6 @@ go_dragonflayer_cage go_tadpole_cage go_amberpine_outhouse go_hive_pod -go_gjalerbron_cage -go_large_gjalerbron_cage go_veil_skith_cage EndContentData */ @@ -1111,69 +1109,6 @@ class go_massive_seaforium_charge : public GameObjectScript }; /*###### -## go_gjalerbron_cage -######*/ - -enum OfKeysAndCages -{ - QUEST_ALLIANCE_OF_KEYS_AND_CAGES = 11231, - QUEST_HORDE_OF_KEYS_AND_CAGES = 11265, - NPC_GJALERBRON_PRISONER = 24035, - SAY_FREE = 0, -}; - -class go_gjalerbron_cage : public GameObjectScript -{ - public: - go_gjalerbron_cage() : GameObjectScript("go_gjalerbron_cage") { } - - bool OnGossipHello(Player* player, GameObject* go) override - { - go->UseDoorOrButton(); - if ((player->GetTeamId() == TEAM_ALLIANCE && player->GetQuestStatus(QUEST_ALLIANCE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE) || - (player->GetTeamId() == TEAM_HORDE && player->GetQuestStatus(QUEST_HORDE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE)) - { - if (Creature* prisoner = go->FindNearestCreature(NPC_GJALERBRON_PRISONER, 5.0f)) - { - player->KilledMonsterCredit(NPC_GJALERBRON_PRISONER); - - prisoner->AI()->Talk(SAY_FREE); - prisoner->DespawnOrUnsummon(6000); - } - } - return true; - } -}; - -/*######## -## go_large_gjalerbron_cage -#####*/ - -class go_large_gjalerbron_cage : public GameObjectScript -{ - public: - go_large_gjalerbron_cage() : GameObjectScript("go_large_gjalerbron_cage") { } - - bool OnGossipHello(Player* player, GameObject* go) override - { - go->UseDoorOrButton(); - if ((player->GetTeamId() == TEAM_ALLIANCE && player->GetQuestStatus(QUEST_ALLIANCE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE) || - (player->GetTeamId() == TEAM_HORDE && player->GetQuestStatus(QUEST_HORDE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE)) - { - std::list<Creature*> prisonerList; - GetCreatureListWithEntryInGrid(prisonerList, go, NPC_GJALERBRON_PRISONER, INTERACTION_DISTANCE); - for (std::list<Creature*>::const_iterator itr = prisonerList.begin(); itr != prisonerList.end(); ++itr) - { - player->KilledMonsterCredit(NPC_GJALERBRON_PRISONER, (*itr)->GetGUID()); - (*itr)->DespawnOrUnsummon(6000); - (*itr)->AI()->Talk(SAY_FREE); - } - } - return false; - } -}; - -/*######## #### go_veil_skith_cage #####*/ @@ -1293,8 +1228,6 @@ void AddSC_go_scripts() new go_amberpine_outhouse(); new go_hive_pod(); new go_massive_seaforium_charge(); - new go_gjalerbron_cage(); - new go_large_gjalerbron_cage(); new go_veil_skith_cage(); new go_frostblade_shrine(); new go_midsummer_bonfire(); diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h index 27e6cb63514..8ffb138379a 100644 --- a/src/server/shared/Common.h +++ b/src/server/shared/Common.h @@ -79,6 +79,9 @@ inline float finiteAlways(float f) { return std::isfinite(f) ? f : 0.0f; } +inline unsigned long atoul(char const* str) { return strtoul(str, nullptr, 10); } +inline unsigned long long atoull(char const* str) { return strtoull(str, nullptr, 10); } + #define STRINGIZE(a) #a enum TimeConstants diff --git a/src/server/shared/Networking/MessageBuffer.h b/src/server/shared/Networking/MessageBuffer.h index 2dcd4fbc161..a214af9d127 100644 --- a/src/server/shared/Networking/MessageBuffer.h +++ b/src/server/shared/Networking/MessageBuffer.h @@ -81,6 +81,14 @@ public: } } + // Ensures there's "some" free space, make sure to call Normalize() before this + void EnsureFreeSpace() + { + // Double the size of the buffer if it's already full + if (GetRemainingSpace() == 0) + _storage.resize(_storage.size() * 2); + } + void Write(void const* data, std::size_t size) { if (size) diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index d3e29ceaaea..b4f1692aeb2 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -90,7 +90,8 @@ public: return; _readBuffer.Normalize(); - _socket.async_read_some(boost::asio::buffer(_readBuffer.GetWritePointer(), READ_BLOCK_SIZE), + _readBuffer.EnsureFreeSpace(); + _socket.async_read_some(boost::asio::buffer(_readBuffer.GetWritePointer(), _readBuffer.GetRemainingSpace()), std::bind(&Socket<T>::ReadHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } diff --git a/src/server/shared/Networking/SocketMgr.h b/src/server/shared/Networking/SocketMgr.h index dbe2b8ec902..a62fe973dfa 100644 --- a/src/server/shared/Networking/SocketMgr.h +++ b/src/server/shared/Networking/SocketMgr.h @@ -46,7 +46,16 @@ public: return false; } - _acceptor = new AsyncAcceptor(service, bindIp, port); + try + { + _acceptor = new AsyncAcceptor(service, bindIp, port); + } + catch (boost::system::system_error const& err) + { + TC_LOG_ERROR("network", "Exception caught in SocketMgr.StartNetwork (%s:%u): %s", bindIp.c_str(), port, err.what()); + return false; + } + _threads = CreateThreads(); ASSERT(_threads); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index faf6441fd72..6a1d9706b30 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -581,6 +581,22 @@ MinCharterName = 2 MinPetName = 2 # +# Guild.CharterCost +# ArenaTeam.CharterCost.2v2 +# ArenaTeam.CharterCost.3v3 +# ArenaTeam.CharterCost.5v5 +# Description: Amount of money (in Copper) the petitions costs. +# Default: 1000 - (10 Silver) +# 800000 - (80 Gold) +# 1200000 - (120 Gold) +# 2000000 - (200 Gold) + +Guild.CharterCost = 1000 +ArenaTeam.CharterCost.2v2 = 800000 +ArenaTeam.CharterCost.3v3 = 1200000 +ArenaTeam.CharterCost.5v5 = 2000000 + +# # MaxWhoListReturns # Description: Set the max number of players returned in the /who list and interface. # Default: 49 - (stable) @@ -3028,7 +3044,7 @@ AuctionHouseBot.Buyer.Neutral.Chance.Ratio = 3 ################################################################################################### ################################################################################################### -# LOGGING SYSTEM SETTINGS +# LOGGING SYSTEM SETTINGS # # Appender config values: Given a appender "name" # Appender.name |