diff options
Diffstat (limited to 'src')
56 files changed, 448 insertions, 599 deletions
diff --git a/src/common/Debugging/Errors.h b/src/common/Debugging/Errors.h index edf56b29136..3ceaf2c328f 100644 --- a/src/common/Debugging/Errors.h +++ b/src/common/Debugging/Errors.h @@ -29,7 +29,7 @@ namespace Trinity DECLSPEC_NORETURN void Fatal(char const* file, int line, char const* function, char const* message) ATTR_NORETURN; DECLSPEC_NORETURN void Error(char const* file, int line, char const* function, char const* message) ATTR_NORETURN; - + DECLSPEC_NORETURN void Abort(char const* file, int line, char const* function) ATTR_NORETURN; void Warning(char const* file, int line, char const* function, char const* message); diff --git a/src/server/database/Database/DatabaseLoader.cpp b/src/server/database/Database/DatabaseLoader.cpp index a3e2083fff4..69e212cf7e1 100644 --- a/src/server/database/Database/DatabaseLoader.cpp +++ b/src/server/database/Database/DatabaseLoader.cpp @@ -66,7 +66,7 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st if (error) { TC_LOG_ERROR("sql.driver", "\nDatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile " - "for specific errors. Read wiki at http://collab.kpsn.org/display/tc/TrinityCore+Home", name.c_str()); + "for specific errors. Read wiki at http://www.trinitycore.info/display/tc/TrinityCore+Home", name.c_str()); return false; } diff --git a/src/server/database/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h index 32837daf5da..c34192592e9 100644 --- a/src/server/database/Database/DatabaseWorkerPool.h +++ b/src/server/database/Database/DatabaseWorkerPool.h @@ -67,6 +67,7 @@ class DatabaseWorkerPool WPFatal(mysql_thread_safe(), "Used MySQL library isn't thread-safe."); WPFatal(mysql_get_client_version() >= MIN_MYSQL_CLIENT_VERSION, "TrinityCore does not support MySQL versions below 5.1"); + WPFatal(mysql_get_client_version() == LIBMYSQL_VERSION_ID, "Used MySQL library does not match the version used to compile TrinityCore."); } ~DatabaseWorkerPool() diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 3e0d684a1fd..45bfee5d596 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -335,10 +335,11 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC); // GM Tickets - PrepareStatement(CHAR_SEL_GM_TICKETS, "SELECT id, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp FROM gm_ticket", CONNECTION_SYNCH); - PrepareStatement(CHAR_REP_GM_TICKET, "REPLACE INTO gm_ticket (id, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_GM_TICKETS, "SELECT id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp FROM gm_ticket", CONNECTION_SYNCH); + PrepareStatement(CHAR_REP_GM_TICKET, "REPLACE INTO gm_ticket (id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_GM_TICKET, "DELETE FROM gm_ticket WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_PLAYER_GM_TICKETS, "DELETE FROM gm_ticket WHERE playerGuid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION, "UPDATE gm_ticket SET type = 2 WHERE playerGuid = ?", CONNECTION_ASYNC); // GM Survey/subsurvey/lag report PrepareStatement(CHAR_INS_GM_SURVEY, "INSERT INTO gm_survey (guid, surveyId, mainSurvey, comment, createTime) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(NOW()))", CONNECTION_ASYNC); diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index 3382430d695..7a463c73df2 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -286,6 +286,7 @@ enum CharacterDatabaseStatements CHAR_DEL_GM_TICKET, CHAR_DEL_ALL_GM_TICKETS, CHAR_DEL_PLAYER_GM_TICKETS, + CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION, CHAR_INS_GM_SURVEY, CHAR_INS_GM_SUBSURVEY, diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp index 9b7bf285efc..de003c2092b 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.cpp +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp @@ -47,8 +47,8 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.sessionkey, a.last_ip, a.locked, a.lock_country, a.expansion, a.mutetime, a.locale, a.recruiter, a.os, aa.gmLevel, " - "(ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate) AND ab.active, r.id FROM account a LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, ?) " - "LEFT JOIN account_banned ab ON a.id = ab.id LEFT JOIN account r ON a.id = r.recruiter WHERE a.username = ? ORDER BY aa.RealmID DESC LIMIT 1", CONNECTION_ASYNC); + "ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id FROM account a LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, ?) " + "LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account r ON a.id = r.recruiter WHERE a.username = ? ORDER BY aa.RealmID DESC LIMIT 1", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_EMAIL, "SELECT id, username FROM account WHERE email = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_NUM_CHARS_ON_REALM, "SELECT numchars FROM realmcharacters WHERE realmid = ? AND acctid= ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_BY_IP, "SELECT id, username FROM account WHERE last_ip = ?", CONNECTION_SYNCH); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 6a3e978e504..a1703dfa78f 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -1026,16 +1026,21 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) { - if (!IsCreature(*itr)) - continue; - - if ((*itr)->ToUnit()->IsAlive() && IsSmart((*itr)->ToCreature())) + if (Creature* target = (*itr)->ToCreature()) { - ENSURE_AI(SmartAI, (*itr)->ToCreature()->AI())->SetDespawnTime(e.action.forceDespawn.delay + 1); // Next tick - ENSURE_AI(SmartAI, (*itr)->ToCreature()->AI())->StartDespawn(); + if (target->IsAlive() && IsSmart(target)) + { + ENSURE_AI(SmartAI, target->AI())->SetDespawnTime(e.action.forceDespawn.delay + 1); // Next tick + ENSURE_AI(SmartAI, target->AI())->StartDespawn(); + } + else + target->DespawnOrUnsummon(e.action.forceDespawn.delay); + } + else if (GameObject* goTarget = (*itr)->ToGameObject()) + { + if (IsSmartGO(goTarget)) + goTarget->SetRespawnTime(e.action.forceDespawn.delay + 1); } - else - (*itr)->ToCreature()->DespawnOrUnsummon(e.action.forceDespawn.delay); } delete targets; diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 96aa1f735fc..6f9046520b0 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -246,10 +246,10 @@ class SmartScript DecPhase(abs(p)); } - void DecPhase(int32 p = 1) - { + void DecPhase(int32 p = 1) + { if(mEventPhase > (uint32)p) - mEventPhase -= (uint32)p; + mEventPhase -= (uint32)p; else mEventPhase = 0; } diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 2662273697f..2bacaff496f 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -2344,7 +2344,7 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT) TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` has ScriptName set for non-scripted data type (Entry: %u, type %u), useless data.", criteria_id, dataType); else - scriptId = sObjectMgr->GetScriptId(scriptName.c_str()); + scriptId = sObjectMgr->GetScriptId(scriptName); } AchievementCriteriaData data(dataType, fields[2].GetUInt32(), fields[3].GetUInt32(), scriptId); diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 5bdaf0e661d..3aac3f080f2 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -549,7 +549,7 @@ void BattlegroundMgr::LoadBattlegroundTemplates() float dist = fields[9].GetFloat(); bgTemplate.MaxStartDistSq = dist * dist; bgTemplate.Weight = fields[10].GetUInt8(); - bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[11].GetCString()); + bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[11].GetString()); bgTemplate.BattlemasterEntry = bl; if (bgTemplate.MaxPlayersPerTeam == 0 || bgTemplate.MinPlayersPerTeam > bgTemplate.MaxPlayersPerTeam) diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 161aefdfc67..c99fe62f11e 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -1131,7 +1131,7 @@ void ChatHandler::extractOptFirstArg(char* args, char** arg1, char** arg2) char* ChatHandler::extractQuotedArg(char* args) { - if (!*args) + if (!args || !*args) return NULL; if (*args == '"') diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index ff8757a891d..2420331e363 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -42,7 +42,7 @@ class ChatCommand public: ChatCommand(char const* name, uint32 permission, bool allowConsole, pHandler handler, std::string help, std::vector<ChatCommand> childCommands = std::vector<ChatCommand>()) - : Name(name), Permission(permission), AllowConsole(allowConsole), Handler(handler), Help(std::move(help)), ChildCommands(std::move(childCommands)) { } + : Name(ASSERT_NOTNULL(name)), Permission(permission), AllowConsole(allowConsole), Handler(handler), Help(std::move(help)), ChildCommands(std::move(childCommands)) { } char const* Name; uint32 Permission; // function pointer required correct align (use uint32) diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 3675d43a3b4..d9fa125b64c 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -967,7 +967,7 @@ void ConditionMgr::LoadConditions(bool isReload) cond->NegativeCondition = fields[10].GetBool(); cond->ErrorType = fields[11].GetUInt32(); cond->ErrorTextId = fields[12].GetUInt32(); - cond->ScriptId = sObjectMgr->GetScriptId(fields[13].GetCString()); + cond->ScriptId = sObjectMgr->GetScriptId(fields[13].GetString()); if (iConditionTypeOrReference >= 0) cond->ConditionType = ConditionTypes(iConditionTypeOrReference); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 6a994d61852..9173d44ae86 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -440,6 +440,7 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/) ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); } + LoadCreaturesAddon(); UpdateMovementFlags(); return true; } @@ -820,8 +821,6 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u break; } - LoadCreaturesAddon(); - //! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER)) { @@ -1411,11 +1410,11 @@ bool Creature::CanStartAttack(Unit const* who, bool force) const return false; // This set of checks is should be done only for creatures - if ((HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC) && who->GetTypeId() != TYPEID_PLAYER) // flag is valid only for non player characters + if ((HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC) && who->GetTypeId() != TYPEID_PLAYER) // flag is valid only for non player characters || (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) && who->GetTypeId() == TYPEID_PLAYER) // immune to PC and target is a player, return false || (who->GetOwner() && who->GetOwner()->GetTypeId() == TYPEID_PLAYER && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC))) // player pets are immune to pc as well return false; - + // Do not attack non-combat pets if (who->GetTypeId() == TYPEID_UNIT && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET) return false; @@ -1557,7 +1556,7 @@ void Creature::setDeathState(DeathState s) if (GetCreatureData() && GetPhaseMask() != GetCreatureData()->phaseMask) SetPhaseMask(GetCreatureData()->phaseMask, false); Unit::setDeathState(ALIVE); - LoadCreaturesAddon(true); + LoadCreaturesAddon(); } } @@ -2063,7 +2062,7 @@ CreatureAddon const* Creature::GetCreatureAddon() const } //creature_addon table -bool Creature::LoadCreaturesAddon(bool reload) +bool Creature::LoadCreaturesAddon() { CreatureAddon const* cainfo = GetCreatureAddon(); if (!cainfo) @@ -2129,12 +2128,7 @@ bool Creature::LoadCreaturesAddon(bool reload) // skip already applied aura if (HasAura(*itr)) - { - if (!reload) - TC_LOG_ERROR("sql.sql", "Creature (GUID: %u Entry: %u) has duplicate aura (spell %u) in `auras` field.", GetSpawnId(), GetEntry(), *itr); - continue; - } AddAura(*itr, this); TC_LOG_DEBUG("entities.unit", "Spell: %u added to creature (GUID: %u Entry: %u)", *itr, GetGUID().GetCounter(), GetEntry()); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index df83a2f9c0f..9a41c8570ed 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -432,7 +432,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject void DisappearAndDie(); bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 entry, float x, float y, float z, float ang, CreatureData const* data = nullptr, uint32 vehId = 0); - bool LoadCreaturesAddon(bool reload = false); + bool LoadCreaturesAddon(); void SelectLevel(); void LoadEquipment(int8 id = 1, bool force = false); diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 2d353fa154e..e8ce0acdc86 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -240,7 +240,8 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z) Trinity::NormalizeMapCoord(dx); Trinity::NormalizeMapCoord(dy); - member->UpdateGroundPositionZ(dx, dy, dz); + if (!member->IsFlying()) + member->UpdateGroundPositionZ(dx, dy, dz); if (member->IsWithinDist(m_leader, dist + MAX_DESYNC)) member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags()); diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 9a6af376e6d..19cf9beff21 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -1435,3 +1435,19 @@ void Item::ItemContainerDeleteLootMoneyAndLootItemsFromDB() ItemContainerDeleteLootMoneyFromDB(); ItemContainerDeleteLootItemsFromDB(); } + +void Item::SetCount(uint32 value) +{ + SetUInt32Value(ITEM_FIELD_STACK_COUNT, value); + + if (Player* player = GetOwner()) + { + if (TradeData* tradeData = player->GetTradeData()) + { + TradeSlots slot = tradeData->GetTradeSlotForItem(GetGUID()); + + if (slot != TRADE_SLOT_INVALID) + tradeData->SetItem(slot, this, true); + } + } +} diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index a268334b212..1eb6530a996 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -262,7 +262,7 @@ class Item : public Object bool GemsFitSockets() const; uint32 GetCount() const { return GetUInt32Value(ITEM_FIELD_STACK_COUNT); } - void SetCount(uint32 value) { SetUInt32Value(ITEM_FIELD_STACK_COUNT, value); } + void SetCount(uint32 value); uint32 GetMaxStackCount() const { return GetTemplate()->GetMaxStackSize(); } uint8 GetGemCountWithID(uint32 GemID) const; uint8 GetGemCountWithLimitCategory(uint32 limitCategory) const; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index e4d9e61bca3..afb987f1980 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1863,7 +1863,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert summon = new Minion(properties, summoner, false); break; } - + if (!summon->Create(GenerateLowGuid<HighGuid::Unit>(), this, phase, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), nullptr, vehId)) { delete summon; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 2f78280a409..3d11e786d52 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -69,6 +69,7 @@ #include "SpellMgr.h" #include "SpellHistory.h" #include "Transport.h" +#include "TicketMgr.h" #include "UpdateData.h" #include "UpdateFieldFlags.h" #include "UpdateMask.h" @@ -323,13 +324,13 @@ Item* TradeData::GetSpellCastItem() const return m_spellCastItem ? m_player->GetItemByGuid(m_spellCastItem) : NULL; } -void TradeData::SetItem(TradeSlots slot, Item* item) +void TradeData::SetItem(TradeSlots slot, Item* item, bool update /*= false*/) { ObjectGuid itemGuid; if (item) itemGuid = item->GetGUID(); - if (m_items[slot] == itemGuid) + if (m_items[slot] == itemGuid && !update) return; m_items[slot] = itemGuid; @@ -4546,6 +4547,11 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe if (Guild* guild = sGuildMgr->GetGuildById(guildId)) guild->DeleteMember(playerguid, false, false, true); + // close player ticket if any + GmTicket* ticket = sTicketMgr->GetTicketByPlayer(playerguid); + if (ticket) + ticket->SetClosedBy(playerguid); + // remove from arena teams LeaveAllArenaTeams(playerguid); @@ -4757,9 +4763,18 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe stmt->setUInt32(0, guid); trans->Append(stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS); - stmt->setUInt32(0, guid); - trans->Append(stmt); + if (sWorld->getBoolConfig(CONFIG_DELETE_CHARACTER_TICKET_TRACE)) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION); + stmt->setUInt32(0, guid); + trans->Append(stmt); + } + else + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS); + stmt->setUInt32(0, guid); + trans->Append(stmt); + } stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER); stmt->setUInt32(0, guid); @@ -21413,7 +21428,7 @@ void Player::InitDisplayIds() PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); if (!info) { - TC_LOG_ERROR("entities.player", "Player %u has incorrect race/class pair. Can't init display ids.", GetGUID().GetCounter()); + TC_LOG_ERROR("entities.player", "Player %s (%s) has incorrect race/class pair. Can't init display ids.", GetName().c_str(), GetGUID().ToString().c_str()); return; } @@ -21429,8 +21444,7 @@ void Player::InitDisplayIds() SetNativeDisplayId(info->displayId_m); break; default: - TC_LOG_ERROR("entities.player", "Invalid gender %u for player", gender); - return; + TC_LOG_ERROR("entities.player", "Player %s (%s) has invalid gender %u", GetName().c_str(), GetGUID().ToString().c_str(), gender); } } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 75f04cb0d7b..c9388fe56b2 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1020,7 +1020,7 @@ class TradeData Item* GetItem(TradeSlots slot) const; bool HasItem(ObjectGuid itemGuid) const; TradeSlots GetTradeSlotForItem(ObjectGuid itemGuid) const; - void SetItem(TradeSlots slot, Item* item); + void SetItem(TradeSlots slot, Item* item, bool update = false); uint32 GetSpell() const { return m_spell; } void SetSpell(uint32 spell_id, Item* castItem = NULL); @@ -1947,6 +1947,12 @@ class Player : public Unit, public GridObject<Player> void SetHonorPoints(uint32 value); void SetArenaPoints(uint32 value); + // duel health and mana reset methods + void SaveHealthBeforeDuel() { healthBeforeDuel = GetHealth(); } + void SaveManaBeforeDuel() { manaBeforeDuel = GetPower(POWER_MANA); } + void RestoreHealthAfterDuel() { SetHealth(healthBeforeDuel); } + void RestoreManaAfterDuel() { SetPower(POWER_MANA, manaBeforeDuel); } + //End of PvP System void SetDrunkValue(uint8 newDrunkValue, uint32 itemId = 0); @@ -2630,6 +2636,10 @@ class Player : public Unit, public GridObject<Player> uint32 _activeCheats; + // variables to save health and mana before duel and restore them after duel + uint32 healthBeforeDuel; + uint32 manaBeforeDuel; + WorldLocation _corpseLocation; }; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 7a9302699b2..046ce422cd2 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -503,7 +503,7 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields) creatureTemplate.RegenHealth = fields[71].GetBool(); creatureTemplate.MechanicImmuneMask = fields[72].GetUInt32(); creatureTemplate.flags_extra = fields[73].GetUInt32(); - creatureTemplate.ScriptID = GetScriptId(fields[74].GetCString()); + creatureTemplate.ScriptID = GetScriptId(fields[74].GetString()); } void ObjectMgr::LoadCreatureTemplateAddons() @@ -555,6 +555,12 @@ void ObjectMgr::LoadCreatureTemplateAddons() if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) 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)); + if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), atoul(*itr)) != creatureAddon.auras.end()) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has duplicate aura (spell %lu) in `auras` field in `creature_template_addon`.", entry, atoul(*itr)); + continue; + } + creatureAddon.auras[i++] = atoul(*itr); } @@ -1003,6 +1009,12 @@ void ObjectMgr::LoadCreatureAddons() if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) 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)); + if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), atoul(*itr)) != creatureAddon.auras.end()) + { + TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has duplicate aura (spell %lu) in `auras` field in `creature_addon`.", guid, atoul(*itr)); + continue; + } + creatureAddon.auras[i++] = atoul(*itr); } @@ -2405,7 +2417,7 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.Duration = fields[129].GetUInt32(); itemTemplate.ItemLimitCategory = uint32(fields[130].GetInt16()); itemTemplate.HolidayId = fields[131].GetUInt32(); - itemTemplate.ScriptId = sObjectMgr->GetScriptId(fields[132].GetCString()); + itemTemplate.ScriptId = sObjectMgr->GetScriptId(fields[132].GetString()); itemTemplate.DisenchantID = fields[133].GetUInt32(); itemTemplate.FoodType = uint32(fields[134].GetUInt8()); itemTemplate.MinMoneyLoot = fields[135].GetUInt32(); @@ -5103,8 +5115,8 @@ void ObjectMgr::LoadSpellScriptNames() Field* fields = result->Fetch(); - int32 spellId = fields[0].GetInt32(); - char const* scriptName = fields[1].GetCString(); + int32 spellId = fields[0].GetInt32(); + std::string const scriptName = fields[1].GetString(); bool allRanks = false; if (spellId < 0) @@ -5116,18 +5128,18 @@ void ObjectMgr::LoadSpellScriptNames() SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) { - TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) does not exist.", scriptName, spellId); + TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) does not exist.", scriptName.c_str(), spellId); continue; } if (allRanks) { if (!spellInfo->IsRanked()) - TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) has no ranks of spell.", scriptName, fields[0].GetInt32()); + TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) has no ranks of spell.", scriptName.c_str(), fields[0].GetInt32()); if (spellInfo->GetFirstRankSpell()->Id != uint32(spellId)) { - TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is not first rank of spell.", scriptName, fields[0].GetInt32()); + TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is not first rank of spell.", scriptName.c_str(), fields[0].GetInt32()); continue; } @@ -5140,7 +5152,7 @@ void ObjectMgr::LoadSpellScriptNames() else { if (spellInfo->IsRanked()) - TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is ranked spell. Perhaps not all ranks are assigned to this script.", scriptName, spellId); + TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is ranked spell. Perhaps not all ranks are assigned to this script.", scriptName.c_str(), spellId); _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, GetScriptId(scriptName))); } @@ -5178,7 +5190,7 @@ void ObjectMgr::ValidateSpellScripts() bool valid = true; if (!spellScript && !auraScript) { - TC_LOG_ERROR("scripts", "Functions GetSpellScript() and GetAuraScript() of script `%s` do not return objects - script skipped", GetScriptName(sitr->second->second)); + TC_LOG_ERROR("scripts", "Functions GetSpellScript() and GetAuraScript() of script `%s` do not return objects - script skipped", GetScriptName(sitr->second->second).c_str()); valid = false; } if (spellScript) @@ -5314,7 +5326,7 @@ void ObjectMgr::LoadInstanceTemplate() instanceTemplate.AllowMount = fields[3].GetBool(); instanceTemplate.Parent = uint32(fields[1].GetUInt16()); - instanceTemplate.ScriptId = sObjectMgr->GetScriptId(fields[2].GetCString()); + instanceTemplate.ScriptId = sObjectMgr->GetScriptId(fields[2].GetString()); _instanceTemplateStore[mapID] = instanceTemplate; @@ -5779,8 +5791,8 @@ void ObjectMgr::LoadAreaTriggerScripts() { Field* fields = result->Fetch(); - uint32 triggerId = fields[0].GetUInt32(); - char const* scriptName = fields[1].GetCString(); + uint32 triggerId = fields[0].GetUInt32(); + std::string const scriptName = fields[1].GetString(); AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(triggerId); if (!atEntry) @@ -6001,7 +6013,8 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float // not need to check validity of map object; MapId _MUST_ be valid here if (range.first == range.second && !map->IsBattlegroundOrArena()) { - TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team); + if (zoneId != 0) // zone == 0 can't be fixed, used by bliz for bugged zones + TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team); return GetDefaultGraveYard(team); } @@ -6637,7 +6650,7 @@ void ObjectMgr::LoadGameObjectTemplate() got.raw.data[i] = fields[10 + i].GetInt32(); // data1 and data6 can be -1 got.AIName = fields[34].GetString(); - got.ScriptId = GetScriptId(fields[35].GetCString()); + got.ScriptId = GetScriptId(fields[35].GetString()); // Checks @@ -8585,11 +8598,18 @@ void ObjectMgr::LoadScriptNames() TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " ScriptNames in %u ms", _scriptNamesStore.size(), GetMSTimeDiffToNow(oldMSTime)); } -uint32 ObjectMgr::GetScriptId(char const* name) +std::string const& ObjectMgr::GetScriptName(uint32 id) const +{ + static std::string const empty = ""; + return id < _scriptNamesStore.size() ? _scriptNamesStore[id] : empty; +} + + +uint32 ObjectMgr::GetScriptId(std::string const& name) { // use binary search to find the script name in the sorted vector // assume "" is the first element - if (!name) + if (name.empty()) return 0; ScriptNameContainer::const_iterator itr = std::lower_bound(_scriptNamesStore.begin(), _scriptNamesStore.end(), name); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 033ea482912..396be440205 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1270,8 +1270,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(); - char const* GetScriptName(uint32 id) const { return id < _scriptNamesStore.size() ? _scriptNamesStore[id].c_str() : ""; } - uint32 GetScriptId(char const* name); + std::string const& GetScriptName(uint32 id) const; + uint32 GetScriptId(std::string const& name); SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const { diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 4893b742a16..6fbef752228 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -303,19 +303,19 @@ template<> void Map::AddToGrid(Corpse* obj, Cell const& cell) { NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); - if (obj->IsWorldObject()) - { - // Corpses are a special object type - they can be added to grid via a call to AddToMap - // or loaded through ObjectGridLoader. - // Both corpses loaded from database and these freshly generated by Player::CreateCoprse are added to _corpsesByCell - // ObjectGridLoader loads all corpses from _corpsesByCell even if they were already added to grid before it was loaded - // so we need to explicitly check it here (Map::AddToGrid is only called from Player::BuildPlayerRepop, not from ObjectGridLoader) - // to avoid failing an assertion in GridObject::AddToGrid - if (grid->isGridObjectDataLoaded()) + // Corpses are a special object type - they can be added to grid via a call to AddToMap + // or loaded through ObjectGridLoader. + // Both corpses loaded from database and these freshly generated by Player::CreateCoprse are added to _corpsesByCell + // ObjectGridLoader loads all corpses from _corpsesByCell even if they were already added to grid before it was loaded + // so we need to explicitly check it here (Map::AddToGrid is only called from Player::BuildPlayerRepop, not from ObjectGridLoader) + // to avoid failing an assertion in GridObject::AddToGrid + if (grid->isGridObjectDataLoaded()) + { + if (obj->IsWorldObject()) grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj); + else + grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj); } - else - grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj); // bones. nothing special here } template<class T> @@ -3177,7 +3177,7 @@ void InstanceMap::CreateInstanceData(bool load) i_data->SetCompletedEncountersMask(fields[1].GetUInt32()); if (!data.empty()) { - TC_LOG_DEBUG("maps", "Loading instance data for `%s` with id %u", sObjectMgr->GetScriptName(i_script_id), i_InstanceId); + TC_LOG_DEBUG("maps", "Loading instance data for `%s` with id %u", sObjectMgr->GetScriptName(i_script_id).c_str(), i_InstanceId); i_data->Load(data.c_str()); } } diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index 4245bffb864..7ab7534199a 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -33,7 +33,7 @@ void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner) { owner->ClearUnitState(UNIT_STATE_EVADE); owner->SetWalk(true); - owner->LoadCreaturesAddon(true); + owner->LoadCreaturesAddon(); owner->AI()->JustReachedHome(); } } diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.h b/src/server/game/OutdoorPvP/OutdoorPvP.h index b35147a8502..4a423a8da5b 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvP.h +++ b/src/server/game/OutdoorPvP/OutdoorPvP.h @@ -308,12 +308,12 @@ class OutdoorPvP : public ZoneScript template<class Worker> void BroadcastWorker(Worker& _worker, uint32 zoneId); - + // Hack to store map because this code is just shit void SetMapFromZone(uint32 zone); std::map<ObjectGuid::LowType, GameObject*> m_GoScriptStore; std::map<ObjectGuid::LowType, Creature*> m_CreatureScriptStore; - + Map* m_map; }; diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp index e7b6765c177..37a380bf576 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp @@ -71,7 +71,7 @@ void OutdoorPvPMgr::InitOutdoorPvP() OutdoorPvPData* data = new OutdoorPvPData(); OutdoorPvPTypes realTypeId = OutdoorPvPTypes(typeId); data->TypeId = realTypeId; - data->ScriptId = sObjectMgr->GetScriptId(fields[1].GetCString()); + data->ScriptId = sObjectMgr->GetScriptId(fields[1].GetString()); m_OutdoorPvPDatas[realTypeId] = data; ++count; diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index a6a8eca6004..47a23dedf0c 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -102,11 +102,8 @@ void AddSC_boss_galvangar(); void AddSC_boss_vanndar(); void AddSC_blackrock_depths(); //Blackrock Depths void AddSC_boss_ambassador_flamelash(); -void AddSC_boss_anubshiah(); void AddSC_boss_draganthaurissan(); void AddSC_boss_general_angerforge(); -void AddSC_boss_gorosh_the_dervish(); -void AddSC_boss_grizzle(); void AddSC_boss_high_interrogator_gerstahn(); void AddSC_boss_magmus(); void AddSC_boss_moira_bronzebeard(); @@ -804,11 +801,8 @@ void AddEasternKingdomsScripts() AddSC_boss_vanndar(); AddSC_blackrock_depths(); //Blackrock Depths AddSC_boss_ambassador_flamelash(); - AddSC_boss_anubshiah(); AddSC_boss_draganthaurissan(); AddSC_boss_general_angerforge(); - AddSC_boss_gorosh_the_dervish(); - AddSC_boss_grizzle(); AddSC_boss_high_interrogator_gerstahn(); AddSC_boss_magmus(); AddSC_boss_moira_bronzebeard(); diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index c47df973692..3cbdf93ca54 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -41,6 +41,60 @@ UnusedScriptNamesContainer UnusedScriptNames; // } +// Trait which indicates whether this script type +// must be assigned in the database. +template<typename> +struct is_script_database_bound + : std::false_type { }; + +template<> +struct is_script_database_bound<SpellScriptLoader> + : std::true_type { }; + +template<> +struct is_script_database_bound<InstanceMapScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<ItemScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<CreatureScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<GameObjectScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<AreaTriggerScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<BattlegroundScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<OutdoorPvPScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<WeatherScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<ConditionScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<TransportScript> + : std::true_type { }; + +template<> +struct is_script_database_bound<AchievementCriteriaScript> + : std::true_type { }; + // This is the global static registry of scripts. template<class TScript> class ScriptRegistry @@ -71,78 +125,83 @@ class ScriptRegistry } } - if (script->IsDatabaseBound()) + AddScript(is_script_database_bound<TScript>{}, script); + } + + // Gets a script by its ID (assigned by ObjectMgr). + static TScript* GetScriptById(uint32 id) + { + ScriptMapIterator it = ScriptPointerList.find(id); + if (it != ScriptPointerList.end()) + return it->second; + + return NULL; + } + + private: + + // Adds a database bound script + static void AddScript(std::true_type, TScript* const script) + { + // Get an ID for the script. An ID only exists if it's a script that is assigned in the database + // through a script name (or similar). + uint32 id = sObjectMgr->GetScriptId(script->GetName()); + if (id) { - // Get an ID for the script. An ID only exists if it's a script that is assigned in the database - // through a script name (or similar). - uint32 id = sObjectMgr->GetScriptId(script->GetName().c_str()); - if (id) + // Try to find an existing script. + bool existing = false; + for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it) { - // Try to find an existing script. - bool existing = false; - for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it) - { - // If the script names match... - if (it->second->GetName() == script->GetName()) - { - // ... It exists. - existing = true; - break; - } - } - - // If the script isn't assigned -> assign it! - if (!existing) + // If the script names match... + if (it->second->GetName() == script->GetName()) { - 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 + // ... It exists. + existing = true; + break; } - else - { - // If the script is already assigned -> delete it! - TC_LOG_ERROR("scripts", "Script '%s' already assigned with the same script name, so the script can't work.", - script->GetName().c_str()); + } - ABORT(); // Error that should be fixed ASAP. - } + // If the script isn't assigned -> assign it! + if (!existing) + { + 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 { - // The script uses a script name from database, but isn't assigned to anything. - TC_LOG_ERROR("sql.sql", "Script named '%s' does not have a script name assigned in database.", script->GetName().c_str()); + // If the script is already assigned -> delete it! + TC_LOG_ERROR("scripts", "Script '%s' already assigned with the same script name, so the script can't work.", + script->GetName().c_str()); - // 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 - UnusedScripts.push_back(script); - return; + ABORT(); // Error that should be fixed ASAP. } } else { - // We're dealing with a code-only script; just add it. - ScriptPointerList[_scriptIdCounter++] = script; - sScriptMgr->IncrementScriptCount(); + // The script uses a script name from database, but isn't assigned to anything. + TC_LOG_ERROR("sql.sql", "Script named '%s' does not have a script name assigned in database.", script->GetName().c_str()); + + // 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 + UnusedScripts.push_back(script); + return; } } - // Gets a script by its ID (assigned by ObjectMgr). - static TScript* GetScriptById(uint32 id) + // Adds a non database bound script + static void AddScript(std::false_type, TScript* const script) { - ScriptMapIterator it = ScriptPointerList.find(id); - if (it != ScriptPointerList.end()) - return it->second; - - return NULL; + // We're dealing with a code-only script; just add it. + ScriptPointerList[_scriptIdCounter++] = script; + sScriptMgr->IncrementScriptCount(); } - private: - // Counter used for code-only scripts. static uint32 _scriptIdCounter; }; diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 025cedd84e0..046c6c1a009 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -153,10 +153,6 @@ class ScriptObject public: - // Do not override this in scripts; it should be overridden by the various script type classes. It indicates - // whether or not this script type must be assigned in the database. - virtual bool IsDatabaseBound() const { return false; } - const std::string& GetName() const { return _name; } protected: @@ -198,8 +194,6 @@ class SpellScriptLoader : public ScriptObject public: - bool IsDatabaseBound() const final override { return true; } - // Should return a fully valid SpellScript pointer. virtual SpellScript* GetSpellScript() const { return NULL; } @@ -356,8 +350,6 @@ class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap> public: - bool IsDatabaseBound() const final override { return true; } - // Gets an InstanceScript object for this instance. virtual InstanceScript* GetInstanceScript(InstanceMap* /*map*/) const { return NULL; } }; @@ -377,8 +369,6 @@ class ItemScript : public ScriptObject public: - bool IsDatabaseBound() const final override { return true; } - // Called when a dummy spell effect is triggered on the item. virtual bool OnDummyEffect(Unit* /*caster*/, uint32 /*spellId*/, SpellEffIndex /*effIndex*/, Item* /*target*/) { return false; } @@ -426,8 +416,6 @@ class CreatureScript : public UnitScript, public UpdatableScript<Creature> public: - bool IsDatabaseBound() const final override { return true; } - // Called when a dummy spell effect is triggered on the creature. virtual bool OnDummyEffect(Unit* /*caster*/, uint32 /*spellId*/, SpellEffIndex /*effIndex*/, Creature* /*target*/) { return false; } @@ -464,8 +452,6 @@ class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject> public: - bool IsDatabaseBound() const final override { return true; } - // Called when a dummy spell effect is triggered on the gameobject. virtual bool OnDummyEffect(Unit* /*caster*/, uint32 /*spellId*/, SpellEffIndex /*effIndex*/, GameObject* /*target*/) { return false; } @@ -511,8 +497,6 @@ class AreaTriggerScript : public ScriptObject public: - bool IsDatabaseBound() const final override { return true; } - // Called when the area trigger is activated by a player. virtual bool OnTrigger(Player* /*player*/, AreaTriggerEntry const* /*trigger*/) { return false; } }; @@ -525,8 +509,6 @@ class BattlegroundScript : public ScriptObject public: - bool IsDatabaseBound() const final override { return true; } - // Should return a fully valid Battleground object for the type ID. virtual Battleground* GetBattleground() const = 0; }; @@ -539,8 +521,6 @@ class OutdoorPvPScript : public ScriptObject public: - bool IsDatabaseBound() const final override { return true; } - // Should return a fully valid OutdoorPvP object for the type ID. virtual OutdoorPvP* GetOutdoorPvP() const = 0; }; @@ -565,8 +545,6 @@ class WeatherScript : public ScriptObject, public UpdatableScript<Weather> public: - bool IsDatabaseBound() const final override { return true; } - // Called when the weather changes in the zone this script is associated with. virtual void OnChange(Weather* /*weather*/, WeatherState /*state*/, float /*grade*/) { } }; @@ -600,8 +578,6 @@ class ConditionScript : public ScriptObject public: - bool IsDatabaseBound() const final override { return true; } - // Called when a single condition is checked for a player. virtual bool OnConditionCheck(Condition const* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; } }; @@ -648,8 +624,6 @@ class TransportScript : public ScriptObject, public UpdatableScript<Transport> public: - bool IsDatabaseBound() const final override { return true; } - // Called when a player boards the transport. virtual void OnAddPassenger(Transport* /*transport*/, Player* /*player*/) { } @@ -671,8 +645,6 @@ class AchievementCriteriaScript : public ScriptObject public: - bool IsDatabaseBound() const final override { return true; } - // Called when an additional criteria is checked. virtual bool OnCheck(Player* source, Unit* target) = 0; }; @@ -809,8 +781,6 @@ class GuildScript : public ScriptObject public: - bool IsDatabaseBound() const final override { return false; } - // Called when a member is added to the guild. virtual void OnAddMember(Guild* /*guild*/, Player* /*player*/, uint8& /*plRank*/) { } @@ -852,8 +822,6 @@ class GroupScript : public ScriptObject public: - bool IsDatabaseBound() const final override { return false; } - // Called when a member is added to a group. virtual void OnAddMember(Group* /*group*/, ObjectGuid /*guid*/) { } diff --git a/src/server/game/Skills/SkillExtraItems.cpp b/src/server/game/Skills/SkillExtraItems.cpp index 2c9a2a7bcfd..50e00b24133 100644 --- a/src/server/game/Skills/SkillExtraItems.cpp +++ b/src/server/game/Skills/SkillExtraItems.cpp @@ -210,7 +210,7 @@ bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateCh // lack of entry means no perfection proc possible if (!thisEntry) return false; - + // if you don't have the spell needed, then no procs for you if (!player->HasSpell(thisEntry->requiredSpecialization)) return false; @@ -218,7 +218,7 @@ bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateCh // set values as appropriate perfectCreateChance = thisEntry->perfectCreateChance; perfectItemType = thisEntry->perfectItemType; - + // and tell the caller to start rolling the dice return true; } diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp index d2cf03dc936..f8593fc8005 100644 --- a/src/server/game/Spells/SpellHistory.cpp +++ b/src/server/game/Spells/SpellHistory.cpp @@ -671,19 +671,14 @@ void SpellHistory::RestoreCooldownStateAfterDuel() _spellCooldownsBeforeDuel[itr->first] = _spellCooldowns[itr->first]; } - _spellCooldowns = _spellCooldownsBeforeDuel; - - // update the client: clear all cooldowns - std::vector<int32> resetCooldowns; - resetCooldowns.reserve(_spellCooldowns.size()); - - for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end(); ++itr) - resetCooldowns.push_back(itr->first); - - if (resetCooldowns.empty()) - return; - - SendClearCooldowns(resetCooldowns); + // check for spell with onHold active before and during the duel + for (auto itr = _spellCooldownsBeforeDuel.begin(); itr != _spellCooldownsBeforeDuel.end(); ++itr) + { + if (!itr->second.OnHold && + _spellCooldowns.find(itr->first) != _spellCooldowns.end() && + !_spellCooldowns[itr->first].OnHold) + _spellCooldowns[itr->first] = _spellCooldownsBeforeDuel[itr->first]; + } // update the client: restore old cooldowns PacketCooldowns cooldowns; @@ -694,14 +689,14 @@ void SpellHistory::RestoreCooldownStateAfterDuel() uint32 cooldownDuration = itr->second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(itr->second.CooldownEnd - now).count() : 0; // cooldownDuration must be between 0 and 10 minutes in order to avoid any visual bugs - if (cooldownDuration == 0 || cooldownDuration > 10 * MINUTE * IN_MILLISECONDS) + if (cooldownDuration <= 0 || cooldownDuration > 10 * MINUTE * IN_MILLISECONDS || itr->second.OnHold) continue; cooldowns[itr->first] = cooldownDuration; } WorldPacket data; - BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, cooldowns); + BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_INCLUDE_EVENT_COOLDOWNS, cooldowns); player->SendDirectMessage(&data); } } diff --git a/src/server/game/Spells/SpellHistory.h b/src/server/game/Spells/SpellHistory.h index 572f407da96..6a1da28f08f 100644 --- a/src/server/game/Spells/SpellHistory.h +++ b/src/server/game/Spells/SpellHistory.h @@ -122,7 +122,7 @@ public: CooldownStorageType::size_type GetCooldownsSizeForPacket() const { return _spellCooldowns.size(); } void SaveCooldownStateBeforeDuel(); void RestoreCooldownStateAfterDuel(); - + private: Player* GetPlayerOwner() const; void SendClearCooldowns(std::vector<int32> const& cooldowns) const; diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp index dbf66c6bd71..b4b3b8267c6 100644 --- a/src/server/game/Tickets/TicketMgr.cpp +++ b/src/server/game/Tickets/TicketMgr.cpp @@ -32,11 +32,11 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; } /////////////////////////////////////////////////////////////////////////////////////////////////// // GM ticket -GmTicket::GmTicket() : _id(0), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0), +GmTicket::GmTicket() : _id(0), _type(TICKET_TYPE_OPEN), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needResponse(false), _needMoreHelp(false) { } -GmTicket::GmTicket(Player* player) : _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(time(NULL)), _lastModifiedTime(time(NULL)), +GmTicket::GmTicket(Player* player) : _type(TICKET_TYPE_OPEN), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needResponse(false), _needMoreHelp(false) { @@ -49,10 +49,11 @@ GmTicket::~GmTicket() { } bool GmTicket::LoadFromDB(Field* fields) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - // ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + // id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp uint8 index = 0; _id = fields[ index].GetUInt32(); + _type = TicketType(fields[++index].GetUInt8()); _playerGuid = ObjectGuid(HighGuid::Player, fields[++index].GetUInt32()); _playerName = fields[++index].GetString(); _message = fields[++index].GetString(); @@ -75,11 +76,12 @@ bool GmTicket::LoadFromDB(Field* fields) void GmTicket::SaveToDB(SQLTransaction& trans) const { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 - // id, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + // id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy uint8 index = 0; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GM_TICKET); stmt->setUInt32( index, _id); + stmt->setUInt8 (++index, uint8(_type)); stmt->setUInt32(++index, _playerGuid.GetCounter()); stmt->setString(++index, _playerName); stmt->setString(++index, _message); diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h index f7d3178978f..a90a1ec0206 100644 --- a/src/server/game/Tickets/TicketMgr.h +++ b/src/server/game/Tickets/TicketMgr.h @@ -77,6 +77,13 @@ enum LagReportType LAG_REPORT_TYPE_SPELL = 6 }; +enum TicketType +{ + TICKET_TYPE_OPEN = 0, + TICKET_TYPE_CLOSED = 1, + TICKET_TYPE_CHARACTER_DELETED = 2, +}; + class GmTicket { public: @@ -84,7 +91,7 @@ public: GmTicket(Player* player); ~GmTicket(); - bool IsClosed() const { return !_closedBy.IsEmpty(); } + bool IsClosed() const { return _type != TICKET_TYPE_OPEN; } bool IsCompleted() const { return _completed; } bool IsFromPlayer(ObjectGuid guid) const { return guid == _playerGuid; } bool IsAssigned() const { return !_assignedTo.IsEmpty(); } @@ -118,7 +125,7 @@ public: else if (_escalatedStatus == TICKET_UNASSIGNED) _escalatedStatus = TICKET_ASSIGNED; } - void SetClosedBy(ObjectGuid value) { _closedBy = value; } + void SetClosedBy(ObjectGuid value) { _closedBy = value; _type = TICKET_TYPE_CLOSED; } void SetResolvedBy(ObjectGuid value) { _resolvedBy = value; } void SetCompleted() { _completed = true; } void SetMessage(std::string const& message) @@ -150,6 +157,7 @@ public: private: uint32 _id; + TicketType _type; // 0 = Open, 1 = Closed, 2 = Character deleted ObjectGuid _playerGuid; std::string _playerName; float _posX; @@ -159,8 +167,8 @@ private: std::string _message; uint64 _createTime; uint64 _lastModifiedTime; - ObjectGuid _closedBy; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket or read the GM response message, other = GM who closed it. - ObjectGuid _resolvedBy; // 0 = Open, -1 = Resolved by Console, GM who resolved it by closing or completing the ticket. + ObjectGuid _closedBy; // 0 = Open or Closed by Console (if type = 1), playerGuid = GM who closed it or player abandoned ticket or read the GM response message. + ObjectGuid _resolvedBy; // 0 = Open or Resolved by Console (if type = 1), playerGuid = GM who resolved it by closing or completing the ticket. ObjectGuid _assignedTo; std::string _comment; bool _completed; diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp index 64775a05faa..ff55d2d9a27 100644 --- a/src/server/game/Weather/WeatherMgr.cpp +++ b/src/server/game/Weather/WeatherMgr.cpp @@ -131,7 +131,7 @@ void LoadWeatherData() } } - wzc.ScriptId = sObjectMgr->GetScriptId(fields[13].GetCString()); + wzc.ScriptId = sObjectMgr->GetScriptId(fields[13].GetString()); ++count; } diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index a0dd889876c..c41caa8f955 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -395,6 +395,7 @@ void World::LoadConfigSettings(bool reload) ///- Read ticket system setting from the config file m_bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetBoolDefault("AllowTickets", true); + m_bool_configs[CONFIG_DELETE_CHARACTER_TICKET_TRACE] = sConfigMgr->GetBoolDefault("DeletedCharacterTicketTrace", false); ///- Get string for new logins (newly created characters) SetNewCharString(sConfigMgr->GetStringDefault("PlayerStart.String", "")); @@ -1182,6 +1183,7 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_START_ALL_SPELLS] = sConfigMgr->GetBoolDefault("PlayerStart.AllSpells", false); m_int_configs[CONFIG_HONOR_AFTER_DUEL] = sConfigMgr->GetIntDefault("HonorPointsAfterDuel", 0); m_bool_configs[CONFIG_RESET_DUEL_COOLDOWNS] = sConfigMgr->GetBoolDefault("ResetDuelCooldowns", false); + m_bool_configs[CONFIG_RESET_DUEL_HEALTH_MANA] = sConfigMgr->GetBoolDefault("ResetDuelHealthMana", false); m_bool_configs[CONFIG_START_ALL_EXPLORED] = sConfigMgr->GetBoolDefault("PlayerStart.MapsExplored", false); m_bool_configs[CONFIG_START_ALL_REP] = sConfigMgr->GetBoolDefault("PlayerStart.AllReputation", false); m_bool_configs[CONFIG_ALWAYS_MAXSKILL] = sConfigMgr->GetBoolDefault("AlwaysMaxWeaponSkill", false); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index b8ffc946615..133ac3f2386 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -144,6 +144,7 @@ enum WorldBoolConfigs CONFIG_SHOW_BAN_IN_WORLD, CONFIG_AUTOBROADCAST, CONFIG_ALLOW_TICKETS, + CONFIG_DELETE_CHARACTER_TICKET_TRACE, CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES, CONFIG_PRESERVE_CUSTOM_CHANNELS, CONFIG_PDUMP_NO_PATHS, @@ -163,6 +164,7 @@ enum WorldBoolConfigs CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA, CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA, CONFIG_RESET_DUEL_COOLDOWNS, + CONFIG_RESET_DUEL_HEALTH_MANA, BOOL_CONFIG_VALUE_COUNT }; diff --git a/src/server/scripts/Commands/cs_cast.cpp b/src/server/scripts/Commands/cs_cast.cpp index f45e73b7c58..5252d5e368a 100644 --- a/src/server/scripts/Commands/cs_cast.cpp +++ b/src/server/scripts/Commands/cs_cast.cpp @@ -120,7 +120,7 @@ public: uint32 spellId = handler->extractSpellIdFromLink((char*)args); if (!spellId) return false; - + if (!CheckSpellExistsAndIsValid(handler, spellId)) return false; @@ -218,7 +218,7 @@ public: uint32 spellId = handler->extractSpellIdFromLink((char*)args); if (!spellId) return false; - + if (!CheckSpellExistsAndIsValid(handler, spellId)) return false; @@ -251,7 +251,7 @@ public: uint32 spellId = handler->extractSpellIdFromLink((char*)args); if (!spellId) return false; - + if (!CheckSpellExistsAndIsValid(handler, spellId)) return false; diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index 9b771f734be..a9baa45f344 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -150,7 +150,7 @@ public: return true; } - sTicketMgr->ResolveAndCloseTicket(ticket->GetId(), player ? player->GetGUID() : ObjectGuid(uint64(-1))); + sTicketMgr->ResolveAndCloseTicket(ticket->GetId(), player ? player->GetGUID() : ObjectGuid(uint64(0))); sTicketMgr->UpdateLastChange(); std::string msg = ticket->FormatMessageString(*handler, player ? player->GetName().c_str() : "Console", NULL, NULL, NULL, NULL); @@ -248,7 +248,7 @@ public: Player* gm = handler->GetSession() ? handler->GetSession()->GetPlayer() : nullptr; SQLTransaction trans = SQLTransaction(NULL); - ticket->SetResolvedBy(gm ? gm->GetGUID() : ObjectGuid(uint64(-1))); + ticket->SetResolvedBy(gm ? gm->GetGUID() : ObjectGuid(uint64(0))); ticket->SetCompleted(); ticket->SaveToDB(trans); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp deleted file mode 100644 index c2261785782..00000000000 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ScriptMgr.h" -#include "ScriptedCreature.h" - -enum Spells -{ - SPELL_SHADOWBOLT = 17228, - SPELL_CURSEOFTONGUES = 15470, - SPELL_CURSEOFWEAKNESS = 17227, - SPELL_DEMONARMOR = 11735, - SPELL_ENVELOPINGWEB = 15471 -}; - -enum Events -{ - EVENT_SHADOWBOLT = 1, - EVENT_CURSE_OF_TONGUES = 2, - EVENT_CURSE_OF_WEAKNESS = 3, - EVENT_DEMON_ARMOR = 4, - EVENT_ENVELOPING_WEB = 5 -}; - -class boss_anubshiah : public CreatureScript -{ - public: - boss_anubshiah() : CreatureScript("boss_anubshiah") { } - - struct boss_anubshiahAI : public ScriptedAI - { - boss_anubshiahAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - _events.Reset(); - } - - void EnterCombat(Unit* /*who*/) override - { - _events.ScheduleEvent(EVENT_SHADOWBOLT, 7000); - _events.ScheduleEvent(EVENT_CURSE_OF_TONGUES, 24000); - _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 12000); - _events.ScheduleEvent(EVENT_DEMON_ARMOR, 3000); - _events.ScheduleEvent(EVENT_ENVELOPING_WEB, 16000); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SHADOWBOLT: - DoCast(me, SPELL_SHADOWBOLT); - _events.ScheduleEvent(EVENT_SHADOWBOLT, 7000); - break; - case EVENT_CURSE_OF_TONGUES: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_CURSEOFTONGUES); - _events.ScheduleEvent(EVENT_CURSE_OF_TONGUES, 18000); - break; - case EVENT_CURSE_OF_WEAKNESS: - DoCastVictim(SPELL_CURSEOFWEAKNESS); - _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 45000); - break; - case EVENT_DEMON_ARMOR: - DoCast(me, SPELL_DEMONARMOR); - _events.ScheduleEvent(EVENT_DEMON_ARMOR, 300000); - break; - case EVENT_ENVELOPING_WEB: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_ENVELOPINGWEB); - _events.ScheduleEvent(EVENT_ENVELOPING_WEB, 12000); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_anubshiahAI(creature); - } -}; - -void AddSC_boss_anubshiah() -{ - new boss_anubshiah(); -} diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp deleted file mode 100644 index 83702ffb16d..00000000000 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ScriptMgr.h" -#include "ScriptedCreature.h" - -enum Spells -{ - SPELL_WHIRLWIND = 15589, - SPELL_MORTALSTRIKE = 24573 -}; - -enum Events -{ - EVENT_WHIRLWIND = 1, - EVENT_MORTALSTRIKE = 2 -}; - -class boss_gorosh_the_dervish : public CreatureScript -{ - public: - boss_gorosh_the_dervish() : CreatureScript("boss_gorosh_the_dervish") { } - - struct boss_gorosh_the_dervishAI : public ScriptedAI - { - boss_gorosh_the_dervishAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - _events.Reset(); - } - - void EnterCombat(Unit* /*who*/) override - { - _events.ScheduleEvent(EVENT_WHIRLWIND, 12000); - _events.ScheduleEvent(EVENT_MORTALSTRIKE, 22000); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_WHIRLWIND: - DoCast(me, SPELL_WHIRLWIND); - _events.ScheduleEvent(EVENT_WHIRLWIND, 15000); - break; - case EVENT_MORTALSTRIKE: - DoCastVictim(SPELL_MORTALSTRIKE); - _events.ScheduleEvent(EVENT_MORTALSTRIKE, 15000); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_gorosh_the_dervishAI(creature); - } -}; - -void AddSC_boss_gorosh_the_dervish() -{ - new boss_gorosh_the_dervish(); -} diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp deleted file mode 100644 index 44dbbe3f4c2..00000000000 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ScriptMgr.h" -#include "ScriptedCreature.h" - -enum Grizzle -{ - SPELL_GROUNDTREMOR = 6524, - SPELL_FRENZY = 28371, - EMOTE_FRENZY_KILL = 0 -}; - -enum Events -{ - EVENT_GROUNDTREMOR = 1, - EVENT_FRENZY = 2 -}; - -enum Phases -{ - PHASE_ONE = 1, - PHASE_TWO = 2 -}; - -class boss_grizzle : public CreatureScript -{ - public: - boss_grizzle() : CreatureScript("boss_grizzle") { } - - struct boss_grizzleAI : public ScriptedAI - { - boss_grizzleAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - _events.Reset(); - } - - void EnterCombat(Unit* /*who*/) override - { - _events.SetPhase(PHASE_ONE); - _events.ScheduleEvent(EVENT_GROUNDTREMOR, 12000); - } - - void DamageTaken(Unit* /*attacker*/, uint32& damage) override - { - if (me->HealthBelowPctDamaged(50, damage) && _events.IsInPhase(PHASE_ONE)) - { - _events.SetPhase(PHASE_TWO); - _events.ScheduleEvent(EVENT_FRENZY, 0, 0, PHASE_TWO); - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_GROUNDTREMOR: - DoCastVictim(SPELL_GROUNDTREMOR); - _events.ScheduleEvent(EVENT_GROUNDTREMOR, 8000); - break; - case EVENT_FRENZY: - DoCast(me, SPELL_FRENZY); - Talk(EMOTE_FRENZY_KILL); - _events.ScheduleEvent(EVENT_FRENZY, 15000, 0, PHASE_TWO); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_grizzleAI(creature); - } -}; - -void AddSC_boss_grizzle() -{ - new boss_grizzle(); -} diff --git a/src/server/scripts/EasternKingdoms/CMakeLists.txt b/src/server/scripts/EasternKingdoms/CMakeLists.txt index fdebfca7979..76e4d36e0a9 100644 --- a/src/server/scripts/EasternKingdoms/CMakeLists.txt +++ b/src/server/scripts/EasternKingdoms/CMakeLists.txt @@ -17,12 +17,9 @@ set(scripts_STAT_SRCS EasternKingdoms/AlteracValley/boss_vanndar.cpp EasternKingdoms/AlteracValley/alterac_valley.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index f9d5a310526..4a76dc667e8 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -309,7 +309,7 @@ class boss_valithria_dreamwalker : public CreatureScript { me->SetHealth(_spawnHealth); me->SetReactState(REACT_PASSIVE); - me->LoadCreaturesAddon(true); + me->LoadCreaturesAddon(); // immune to percent heals me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_OBS_MOD_HEALTH, true); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_HEAL_PCT, true); @@ -1072,7 +1072,7 @@ class npc_dream_cloud : public CreatureScript _events.Reset(); _events.ScheduleEvent(EVENT_CHECK_PLAYER, 1000); me->SetCorpseDelay(0); // remove corpse immediately - me->LoadCreaturesAddon(true); + me->LoadCreaturesAddon(); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index 471a7adc9d6..47569a6b85f 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -116,7 +116,7 @@ public: void JustSummoned(Creature* summon) override { BossAI::JustSummoned(summon); - + if (me->IsInCombat()) if (summon->GetEntry() == NPC_CRYPT_GUARD) summon->AI()->Talk(EMOTE_SPAWN, me); @@ -160,7 +160,7 @@ public: Talk(SAY_AGGRO); summons.DoZoneInCombat(); - + events.SetPhase(PHASE_NORMAL); events.ScheduleEvent(EVENT_IMPALE, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_NORMAL); events.ScheduleEvent(EVENT_SCARABS, urand(20 * IN_MILLISECONDS, 30 * IN_MILLISECONDS), 0, PHASE_NORMAL); @@ -209,7 +209,7 @@ public: Talk(EMOTE_LOCUST); DoCast(me, SPELL_LOCUST_SWARM); events.ScheduleEvent(EVENT_SPAWN_GUARD, 3 * IN_MILLISECONDS); - + events.ScheduleEvent(EVENT_LOCUST_ENDS, RAID_MODE(19, 23) * IN_MILLISECONDS); events.ScheduleEvent(EVENT_LOCUST, 90000); events.SetPhase(PHASE_SWARM); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp index 5248c48029c..36e48d068b5 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp @@ -103,7 +103,7 @@ public: { _EnterCombat(); Talk(SAY_AGGRO); - + eruptSection = 3; events.ScheduleEvent(EVENT_DISRUPT, urand(15 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_FIGHT); events.ScheduleEvent(EVENT_FEVER, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_FIGHT); @@ -182,7 +182,7 @@ public: private: uint32 eruptSection; bool eruptDirection; - + bool safetyDance; // is achievement still possible? (= no player deaths yet) }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index f6dc75c7b3b..106661b70bf 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -178,7 +178,7 @@ public: return; if (damage < me->GetHealth()) return; - + me->SetHealth(1u); damage = 0u; } @@ -226,7 +226,7 @@ public: case EVENT_WARRIOR: Talk(SAY_SUMMON); Talk(EMOTE_SUMMON); - + CastSummon(RAID_MODE(2, 3), 0, 0); events.ScheduleEvent(EVENT_WARRIOR, 40 * IN_MILLISECONDS, 0, PHASE_GROUND); @@ -291,7 +291,7 @@ public: break; case EVENT_GROUND: ++balconyCount; - + DoCastAOE(SPELL_TELEPORT_BACK); Talk(EMOTE_TELEPORT_2); @@ -308,7 +308,7 @@ public: { /* workaround for movechase breaking after blinking without this noth would just stand there unless his current target moves */ - if (justBlinked && me->GetVictim() && !me->IsWithinMeleeRange(me->EnsureVictim())) + if (justBlinked && me->GetVictim() && !me->IsWithinMeleeRange(me->EnsureVictim())) { me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveChase(me->EnsureVictim()); @@ -321,7 +321,7 @@ public: private: uint32 balconyCount; - + bool justBlinked; uint32 _SummonWarriorSpells[N_WARRIOR_SPELLS]; diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp index d5d2eebda38..6e4a8df6f25 100644 --- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp +++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp @@ -622,17 +622,17 @@ public: enum MiscLifewarden { - NPC_PRESENCE = 28563, // Freya's Presence - NPC_SABOTEUR = 28538, // Cultist Saboteur - NPC_SERVANT = 28320, // Servant of Freya + NPC_PRESENCE = 28563, // Freya's Presence + NPC_SABOTEUR = 28538, // Cultist Saboteur + NPC_SERVANT = 28320, // Servant of Freya - WHISPER_ACTIVATE = 0, + WHISPER_ACTIVATE = 0, - SPELL_FREYA_DUMMY = 51318, - SPELL_LIFEFORCE = 51395, - SPELL_FREYA_DUMMY_TRIGGER = 51335, - SPELL_LASHER_EMERGE = 48195, - SPELL_WILD_GROWTH = 52948, + SPELL_FREYA_DUMMY = 51318, + SPELL_LIFEFORCE = 51395, + SPELL_FREYA_DUMMY_TRIGGER = 51335, + SPELL_LASHER_EMERGE = 48195, + SPELL_WILD_GROWTH = 52948, }; class spell_q12620_the_lifewarden_wrath : public SpellScriptLoader @@ -702,25 +702,25 @@ public: enum KickWhatKick { - NPC_LUCKY_WILHELM = 28054, - NPC_APPLE = 28053, - NPC_DROSTAN = 28328, - NPC_CRUNCHY = 28346, - NPC_THICKBIRD = 28093, - - SPELL_HIT_APPLE = 51331, - SPELL_MISS_APPLE = 51332, - SPELL_MISS_BIRD_APPLE = 51366, - SPELL_APPLE_FALL = 51371, - SPELL_BIRD_FALL = 51369, - - EVENT_MISS = 0, - EVENT_HIT = 1, - EVENT_MISS_BIRD = 2, - - SAY_WILHELM_MISS = 0, - SAY_WILHELM_HIT = 1, - SAY_DROSTAN_REPLY_MISS = 0, + NPC_LUCKY_WILHELM = 28054, + NPC_APPLE = 28053, + NPC_DROSTAN = 28328, + NPC_CRUNCHY = 28346, + NPC_THICKBIRD = 28093, + + SPELL_HIT_APPLE = 51331, + SPELL_MISS_APPLE = 51332, + SPELL_MISS_BIRD_APPLE = 51366, + SPELL_APPLE_FALL = 51371, + SPELL_BIRD_FALL = 51369, + + EVENT_MISS = 0, + EVENT_HIT = 1, + EVENT_MISS_BIRD = 2, + + SAY_WILHELM_MISS = 0, + SAY_WILHELM_HIT = 1, + SAY_DROSTAN_REPLY_MISS = 0, }; class spell_q12589_shoot_rjr : public SpellScriptLoader @@ -800,8 +800,6 @@ public: wilhelm->AI()->Talk(SAY_WILHELM_HIT); if (Player* player = shooter->ToPlayer()) player->KilledMonsterCredit(NPC_APPLE); - apple->DespawnOrUnsummon(); - break; } } @@ -828,11 +826,11 @@ may be easily converted to SAI when they get.*/ enum SongOfWindAndWater { // Spells - SPELL_DEVOUR_WIND = 52862, - SPELL_DEVOUR_WATER = 52864, + SPELL_DEVOUR_WIND = 52862, + SPELL_DEVOUR_WATER = 52864, // NPCs - NPC_HAIPHOON_WATER = 28999, - NPC_HAIPHOON_AIR = 28985 + NPC_HAIPHOON_WATER = 28999, + NPC_HAIPHOON_AIR = 28985 }; class npc_haiphoon : public CreatureScript @@ -883,7 +881,7 @@ enum ReconnaissanceFlight VIC_SAY_6 = 6, PLANE_EMOTE = 0, - SPELL_ENGINE = 52255, // Engine on Fire + SPELL_ENGINE = 52255, // Engine on Fire SPELL_LAND = 52226, // Land Flying Machine SPELL_CREDIT = 53328 // Land Flying Machine Credit diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp index 9224817b699..89f35457a44 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp @@ -75,7 +75,7 @@ void OPvPCapturePointEP_EWT::ChangeState() auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); for (auto itr = bounds.first; itr != bounds.second; ++itr) itr->second->SetGoArtKit(artkit); - + bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_Objects[EP_EWT_FLAGS]); for (auto itr = bounds.first; itr != bounds.second; ++itr) itr->second->SetGoArtKit(artkit); diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp index 500b0ae4bcb..f47e191c118 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp @@ -82,7 +82,7 @@ class boss_shattered_executioner : public CreatureScript void Reset() override { _Reset(); - + // _Reset() resets the loot mode, so we add them again, if any uint32 prisonersExecuted = instance->GetData(DATA_PRISONERS_EXECUTED); if (prisonersExecuted == 0) diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index 0dc75ff8efa..872269fd19f 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -297,7 +297,7 @@ const float CAPERNIAN_DISTANCE = 20.0f; //she casts away fro Position const afGravityPos = {795.0f, 0.0f, 70.0f}; -Position const TransitionPos[6] = +Position const TransitionPos[6] = { // First two values are not static, they seem to differ on each sniff. { 794.0522f, -0.96732f, 48.97848f, 0.0f }, @@ -869,7 +869,7 @@ class boss_thaladred_the_darkener : public CreatureScript public: boss_thaladred_the_darkener() : CreatureScript("boss_thaladred_the_darkener") { } - + struct boss_thaladred_the_darkenerAI : public advisorbase_ai { boss_thaladred_the_darkenerAI(Creature* creature) : advisorbase_ai(creature) @@ -963,7 +963,7 @@ class boss_lord_sanguinar : public CreatureScript public: boss_lord_sanguinar() : CreatureScript("boss_lord_sanguinar") { } - + struct boss_lord_sanguinarAI : public advisorbase_ai { boss_lord_sanguinarAI(Creature* creature) : advisorbase_ai(creature) @@ -1027,7 +1027,7 @@ class boss_grand_astromancer_capernian : public CreatureScript public: boss_grand_astromancer_capernian() : CreatureScript("boss_grand_astromancer_capernian") { } - + struct boss_grand_astromancer_capernianAI : public advisorbase_ai { boss_grand_astromancer_capernianAI(Creature* creature) : advisorbase_ai(creature) @@ -1307,7 +1307,7 @@ class npc_phoenix_tk : public CreatureScript public: npc_phoenix_tk() : CreatureScript("npc_phoenix_tk") { } - + struct npc_phoenix_tkAI : public ScriptedAI { npc_phoenix_tkAI(Creature* creature) : ScriptedAI(creature) @@ -1366,7 +1366,7 @@ class npc_phoenix_egg_tk : public CreatureScript public: npc_phoenix_egg_tk() : CreatureScript("npc_phoenix_egg_tk") { } - + struct npc_phoenix_egg_tkAI : public ScriptedAI { npc_phoenix_egg_tkAI(Creature* creature) : ScriptedAI(creature) @@ -1464,7 +1464,7 @@ class spell_kael_gravity_lapse : public SpellScriptLoader { OnEffectHitTarget += SpellEffectFn(spell_kael_gravity_lapse_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } - + private: uint8 _targetCount; }; diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index fcfa77bc2e0..0a9f8640ad2 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -483,7 +483,7 @@ class npc_barada : public CreatureScript { public: npc_barada() : CreatureScript("npc_barada") { } - + struct npc_baradaAI : public ScriptedAI { npc_baradaAI(Creature* creature) : ScriptedAI(creature) @@ -779,7 +779,7 @@ public: me->SetCanFly(true); me->SetSpeed(MOVE_RUN, 0.2f); - + me->SetFacingTo(3.207566f); me->GetMotionMaster()->MoveJump(exorcismPos[2], 2.0f, 2.0f); @@ -860,14 +860,14 @@ public: } } } - + private: EventMap events; SummonList summons; - + uint8 circleRounds; uint8 point; - + bool wpreached; }; diff --git a/src/server/scripts/World/duel_reset.cpp b/src/server/scripts/World/duel_reset.cpp index f08469d5bd5..ae98c0eb4ab 100644 --- a/src/server/scripts/World/duel_reset.cpp +++ b/src/server/scripts/World/duel_reset.cpp @@ -17,6 +17,7 @@ #include "ScriptMgr.h" #include "Player.h" +#include "Pet.h" class DuelResetScript : public PlayerScript { @@ -26,28 +27,90 @@ class DuelResetScript : public PlayerScript // Called when a duel starts (after 3s countdown) void OnDuelStart(Player* player1, Player* player2) override { + // Cooldowns reset if (sWorld->getBoolConfig(CONFIG_RESET_DUEL_COOLDOWNS)) { player1->GetSpellHistory()->SaveCooldownStateBeforeDuel(); player2->GetSpellHistory()->SaveCooldownStateBeforeDuel(); - player1->RemoveArenaSpellCooldowns(true); - player2->RemoveArenaSpellCooldowns(true); + + ResetSpellCooldowns(player1, true); + ResetSpellCooldowns(player2, true); + } + + // Health and mana reset + if (sWorld->getBoolConfig(CONFIG_RESET_DUEL_HEALTH_MANA)) + { + player1->SaveHealthBeforeDuel(); + player1->SetHealth(player1->GetMaxHealth()); + + player2->SaveHealthBeforeDuel(); + player2->SetHealth(player2->GetMaxHealth()); + + // check if player1 class uses mana + if (player1->getPowerType() == POWER_MANA || player1->getClass() == CLASS_DRUID) + { + player1->SaveManaBeforeDuel(); + player1->SetPower(POWER_MANA, player1->GetMaxPower(POWER_MANA)); + } + + // check if player2 class uses mana + if (player2->getPowerType() == POWER_MANA || player2->getClass() == CLASS_DRUID) + { + player2->SaveManaBeforeDuel(); + player2->SetPower(POWER_MANA, player2->GetMaxPower(POWER_MANA)); + } } } // Called when a duel ends - void OnDuelEnd(Player* winner, Player* loser, DuelCompleteType /*type*/) override + void OnDuelEnd(Player* winner, Player* loser, DuelCompleteType type) override { - if (sWorld->getBoolConfig(CONFIG_RESET_DUEL_COOLDOWNS)) + // do not reset anything if DUEL_INTERRUPTED or DUEL_FLED + if (type == DUEL_WON) { - winner->RemoveArenaSpellCooldowns(true); - loser->RemoveArenaSpellCooldowns(true); + // Cooldown restore + if (sWorld->getBoolConfig(CONFIG_RESET_DUEL_COOLDOWNS)) + { + + ResetSpellCooldowns(winner, true); + ResetSpellCooldowns(loser, true); - winner->GetSpellHistory()->RestoreCooldownStateAfterDuel(); - loser->GetSpellHistory()->RestoreCooldownStateAfterDuel(); + winner->GetSpellHistory()->RestoreCooldownStateAfterDuel(); + loser->GetSpellHistory()->RestoreCooldownStateAfterDuel(); + } + + // Health and mana restore + if (sWorld->getBoolConfig(CONFIG_RESET_DUEL_HEALTH_MANA)) + { + winner->RestoreHealthAfterDuel(); + loser->RestoreHealthAfterDuel(); + + // check if player1 class uses mana + if (winner->getPowerType() == POWER_MANA || winner->getClass() == CLASS_DRUID) + winner->RestoreManaAfterDuel(); + + // check if player2 class uses mana + if (loser->getPowerType() == POWER_MANA || loser->getClass() == CLASS_DRUID) + loser->RestoreManaAfterDuel(); + } } } + + void ResetSpellCooldowns(Player* player, bool removeActivePetCooldowns) + { + // remove cooldowns on spells that have < 10 min CD and has no onHold + player->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool + { + SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS && !itr->second.OnHold; + }, true); + + // pet cooldowns + if (removeActivePetCooldowns) + if (Pet* pet = player->GetPet()) + pet->GetSpellHistory()->ResetAllCooldowns(); + } }; void AddSC_duel_reset() diff --git a/src/server/shared/Dynamic/TypeContainer.h b/src/server/shared/Dynamic/TypeContainer.h index b68dec00da7..7addf8028bf 100644 --- a/src/server/shared/Dynamic/TypeContainer.h +++ b/src/server/shared/Dynamic/TypeContainer.h @@ -47,7 +47,7 @@ template<> struct ContainerMapList<TypeNull> /* nothing is in type null */ { }; -template<class H, class T> +template<class H, class T> struct ContainerMapList<TypeList<H, T> > { ContainerMapList<H> _elements; @@ -105,7 +105,7 @@ class TypeMapContainer template<class SPECIFIC_TYPE> size_t Count() const { return Trinity::Count(i_elements, (SPECIFIC_TYPE*)NULL); } /// inserts a specific object into the container - template<class SPECIFIC_TYPE> + template<class SPECIFIC_TYPE> bool insert(SPECIFIC_TYPE *obj) { SPECIFIC_TYPE* t = Trinity::Insert(i_elements, obj); @@ -113,7 +113,7 @@ class TypeMapContainer } /// Removes the object from the container, and returns the removed object - //template<class SPECIFIC_TYPE> + //template<class SPECIFIC_TYPE> //bool remove(SPECIFIC_TYPE* obj) //{ // SPECIFIC_TYPE* t = Trinity::Remove(i_elements, obj); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 13b6b22bed4..381df373932 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1074,6 +1074,16 @@ Command.LookupMaxResults = 0 AllowTickets = 1 # +# DeletedCharacterTicketTrace +# Description: Keep trace of tickets opened by deleted characters +# gm_ticket.playerGuid will be 0, old GUID and character name +# will be included in gm_ticket.comment +# Default: 0 - (Disabled) +# 1 - (Enabled) + +DeletedCharacterTicketTrace = 0 + +# # DungeonFinder.OptionsMask # Description: Dungeon and raid finder system. # Value is a bitmask consisting of: @@ -2630,6 +2640,13 @@ HonorPointsAfterDuel = 0 ResetDuelCooldowns = 0 +# ResetDuelHealthMana +# Description: Reset health and mana before duel starts and restore them when duel ends. +# Default: 0 - (Disabled) +# 1 - (Enabled) + +ResetDuelHealthMana = 0 + # # AlwaysMaxWeaponSkill # Description: Players will automatically gain max weapon/defense skill when logging in, |