Merge branch 'master' into Playerbot
This commit is contained in:
@@ -15,8 +15,9 @@ results = {
|
|||||||
"Multiple blank lines check": "Passed",
|
"Multiple blank lines check": "Passed",
|
||||||
"Trailing whitespace check": "Passed",
|
"Trailing whitespace check": "Passed",
|
||||||
"SQL codestyle check": "Passed",
|
"SQL codestyle check": "Passed",
|
||||||
"INSERT safety usage check": "Passed",
|
"INSERT & DELETE safety usage check": "Passed",
|
||||||
"Missing semicolon check": "Passed"
|
"Missing semicolon check": "Passed",
|
||||||
|
"Backtick check": "Passed"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Collect all files in all directories
|
# Collect all files in all directories
|
||||||
@@ -44,8 +45,9 @@ def parsing_file(files: list) -> None:
|
|||||||
multiple_blank_lines_check(file, file_path)
|
multiple_blank_lines_check(file, file_path)
|
||||||
trailing_whitespace_check(file, file_path)
|
trailing_whitespace_check(file, file_path)
|
||||||
sql_check(file, file_path)
|
sql_check(file, file_path)
|
||||||
insert_safety_check(file, file_path)
|
insert_delete_safety_check(file, file_path)
|
||||||
semicolon_check(file, file_path)
|
semicolon_check(file, file_path)
|
||||||
|
backtick_check(file, file_path)
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
print(f"\nCould not decode file {file_path}")
|
print(f"\nCould not decode file {file_path}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -134,9 +136,10 @@ def sql_check(file: io, file_path: str) -> None:
|
|||||||
error_handler = True
|
error_handler = True
|
||||||
results["SQL codestyle check"] = "Failed"
|
results["SQL codestyle check"] = "Failed"
|
||||||
|
|
||||||
def insert_safety_check(file: io, file_path: str) -> None:
|
def insert_delete_safety_check(file: io, file_path: str) -> None:
|
||||||
global error_handler, results
|
global error_handler, results
|
||||||
file.seek(0) # Reset file pointer to the beginning
|
file.seek(0) # Reset file pointer to the beginning
|
||||||
|
not_delete = ["creature_template", "gameobject_template", "item_template", "quest_template"]
|
||||||
check_failed = False
|
check_failed = False
|
||||||
previous_line = ""
|
previous_line = ""
|
||||||
|
|
||||||
@@ -148,11 +151,18 @@ def insert_safety_check(file: io, file_path: str) -> None:
|
|||||||
print(f"No DELETE keyword found after the INSERT in {file_path} at line {line_number}\nIf this error is intended, please advert a maintainer")
|
print(f"No DELETE keyword found after the INSERT in {file_path} at line {line_number}\nIf this error is intended, please advert a maintainer")
|
||||||
check_failed = True
|
check_failed = True
|
||||||
previous_line = line
|
previous_line = line
|
||||||
|
match = re.match(r"DELETE FROM\s+`([^`]+)`", line, re.IGNORECASE)
|
||||||
|
if match:
|
||||||
|
table_name = match.group(1)
|
||||||
|
if table_name in not_delete:
|
||||||
|
print(
|
||||||
|
f"Entries from {table} should not be deleted! {file_path} at line {line_number}")
|
||||||
|
check_failed = True
|
||||||
|
|
||||||
# Handle the script error and update the result output
|
# Handle the script error and update the result output
|
||||||
if check_failed:
|
if check_failed:
|
||||||
error_handler = True
|
error_handler = True
|
||||||
results["INSERT safety usage check"] = "Failed"
|
results["INSERT & DELETE safety usage check"] = "Failed"
|
||||||
|
|
||||||
def semicolon_check(file: io, file_path: str) -> None:
|
def semicolon_check(file: io, file_path: str) -> None:
|
||||||
global error_handler, results
|
global error_handler, results
|
||||||
@@ -192,6 +202,30 @@ def semicolon_check(file: io, file_path: str) -> None:
|
|||||||
error_handler = True
|
error_handler = True
|
||||||
results["Missing semicolon check"] = "Failed"
|
results["Missing semicolon check"] = "Failed"
|
||||||
|
|
||||||
|
def backtick_check(file: io, file_path: str) -> None:
|
||||||
|
global error_handler, results
|
||||||
|
file.seek(0)
|
||||||
|
check_failed = False
|
||||||
|
pattern = re.compile(
|
||||||
|
r'\b(SELECT|FROM|JOIN|WHERE|GROUP BY|ORDER BY|DELETE FROM|UPDATE|INSERT INTO|SET)\s+([^;]+)',
|
||||||
|
re.IGNORECASE)
|
||||||
|
|
||||||
|
for line_number, line in enumerate(file, start=1):
|
||||||
|
matches = pattern.findall(line)
|
||||||
|
for clause, content in matches:
|
||||||
|
words = re.findall(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b', content)
|
||||||
|
for word in words:
|
||||||
|
if word.upper() in {"SELECT", "FROM", "JOIN", "WHERE", "GROUP", "BY", "ORDER",
|
||||||
|
"DELETE", "UPDATE", "INSERT", "INTO", "SET", "VALUES"}:
|
||||||
|
continue
|
||||||
|
if not re.search(rf'`{re.escape(word)}`', content):
|
||||||
|
print(f"Missing backticks around ({word}). {file_path} at line {line_number}")
|
||||||
|
check_failed = True
|
||||||
|
|
||||||
|
if check_failed:
|
||||||
|
error_handler = True
|
||||||
|
results["Backtick check"] = "Failed"
|
||||||
|
|
||||||
# Collect all files from matching directories
|
# Collect all files from matching directories
|
||||||
all_files = collect_files_from_directories(src_directory)
|
all_files = collect_files_from_directories(src_directory)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# install chocolatey before
|
# install chocolatey before
|
||||||
|
|
||||||
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
|
# powershell.exe -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
|
||||||
|
|
||||||
# install automatically following packages:
|
# install automatically following packages:
|
||||||
# cmake
|
# cmake
|
||||||
@@ -24,7 +24,7 @@ fi
|
|||||||
|
|
||||||
choco install -y --skip-checksums $INSTALL_ARGS cmake.install -y --installargs 'ADD_CMAKE_TO_PATH=System'
|
choco install -y --skip-checksums $INSTALL_ARGS cmake.install -y --installargs 'ADD_CMAKE_TO_PATH=System'
|
||||||
choco install -y --skip-checksums $INSTALL_ARGS visualstudio2022-workload-nativedesktop
|
choco install -y --skip-checksums $INSTALL_ARGS visualstudio2022-workload-nativedesktop
|
||||||
choco install -y --skip-checksums $INSTALL_ARGS openssl --version=3.1.1
|
choco install -y --skip-checksums $INSTALL_ARGS openssl --force --version=3.3.2
|
||||||
choco install -y --skip-checksums $INSTALL_ARGS boost-msvc-14.3 --version=1.82.0
|
choco install -y --skip-checksums $INSTALL_ARGS boost-msvc-14.3 --force --version=1.87.0
|
||||||
choco install -y --skip-checksums $INSTALL_ARGS mysql --version=8.0.31
|
choco install -y --skip-checksums $INSTALL_ARGS mysql --force --version=8.4.4
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
-- DB update 2024_11_15_00 -> 2025_01_31_00
|
||||||
|
--
|
||||||
|
DROP TABLE IF EXISTS `world_state`;
|
||||||
|
CREATE TABLE IF NOT EXISTS `world_state` (
|
||||||
|
`Id` INT UNSIGNED NOT NULL COMMENT 'Internal save ID',
|
||||||
|
`Data` longtext,
|
||||||
|
PRIMARY KEY(`Id`)
|
||||||
|
) ENGINE=MYISAM DEFAULT CHARSET=utf8mb4 COMMENT='WorldState save system';
|
||||||
|
|
||||||
|
-- Isle of Quel'danas is in its final stage with all subphases completed
|
||||||
|
-- open all Sunwell Plateau gates
|
||||||
|
DELETE FROM `world_state` WHERE `Id` = 20;
|
||||||
|
INSERT INTO `world_state` (`Id`, `Data`) VALUES(20, '3 15 10000 10000 10000 10000 10000 10000 10000 10000 10000 10000 3 80 80 80');
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
|||||||
|
-- DB update 2025_01_31_00 -> 2025_01_31_01
|
||||||
|
-- Add pure energy immune script for Vex
|
||||||
|
UPDATE `creature_template` SET `ScriptName` = 'npc_pure_energy' WHERE (`entry` = 24745);
|
||||||
|
|
||||||
|
-- AOE_IMMUNE Flag for pure energy
|
||||||
|
UPDATE `creature_template` SET `flags_extra` = (`flags_extra` | 4194304) WHERE (`entry` = 24745);
|
||||||
|
|
||||||
|
-- Vexallus (Entry: 24744) Overload Emote with broadcasttextid 77866
|
||||||
|
DELETE FROM `creature_text` WHERE `CreatureID` = 24744 AND `GroupID` = 5 AND `ID` = 0;
|
||||||
|
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||||
|
(24744, 5, 0, 'Vexallus overloads!', 41, 0, 100, 0, 0, 0, 23781, 0, 'Vexallus - EMOTE_OVERLOAD');
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
-- DB update 2025_01_31_01 -> 2025_02_01_00
|
||||||
|
--
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24761);
|
||||||
|
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||||
|
(24761, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44406, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Brightscale Wyrm - On Just Died - Cast \'Energy Infusion\'');
|
||||||
|
|
||||||
|
DELETE FROM `spell_custom_attr` WHERE `spell_id`= 44406;
|
||||||
|
INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES (44406, 4194304);
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- DB update 2025_02_01_00 -> 2025_02_01_01
|
||||||
|
--
|
||||||
|
UPDATE `creature_template` SET `ScriptName` = '' WHERE (`entry` = 24745);
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- DB update 2025_02_01_01 -> 2025_02_01_02
|
||||||
|
--
|
||||||
|
DELETE FROM `acore_string` WHERE `entry` = 6617;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
-- DB update 2025_02_01_02 -> 2025_02_03_00
|
||||||
|
-- Add Russian locale for QuestID: 4641
|
||||||
|
DELETE FROM `quest_offer_reward_locale` WHERE `ID` = 4641 AND `locale` = 'ruRU';
|
||||||
|
INSERT INTO `quest_offer_reward_locale` (`ID`, `locale`, `RewardText`, `VerifiedBuild`) VALUES (4641,'ruRU','Очередной рекрут Калтунка?$B$BВидно, плохи наши дела, если у нас нет никого получше. Ну, ничего. К тому времени, как мы решим, что тебе пора покинуть долину, из тебя $c получится бравый воитель Орды!',0);
|
||||||
|
|
||||||
|
-- Add Russian locale for QuestID: 788
|
||||||
|
DELETE FROM `quest_offer_reward_locale` WHERE `ID` = 788 AND `locale` = 'ruRU';
|
||||||
|
INSERT INTO `quest_offer_reward_locale` (`ID`, `locale`, `RewardText`, `VerifiedBuild`) VALUES (788,'ruRU','Ну что ж, $N, неплохо. Но не задирай носа: грядут бои с куда более серьезными врагами.$b$bОднако ты показал себя достойным бойцом. В следующем испытании тебе придется встретиться с более опасным противником, так что дополнительная защита не помешает.',0);
|
||||||
|
|
||||||
|
-- Fix Russian locale for QuestID: 783
|
||||||
|
DELETE FROM `quest_template_locale` WHERE `ID` = 783 AND `locale` = 'ruRU';
|
||||||
|
INSERT INTO `quest_template_locale` (`ID`, `locale`, `Title`, `Details`, `Objectives`, `VerifiedBuild`) VALUES (783, 'ruRU', 'Внутренняя угроза', 'Надеюсь, ты $gготов:готова; к подвигам, |3-6($c), поскольку для тебя есть дело здесь, в Североземье.$B$BИ я имею в виду не мирные сельские заботы.$B$BСтража Штормграда с трудом поддерживает здесь мир: слишком многие из нас находятся в дальних краях, а тревожных вестей меньше не становится. И потому мы надеемся на помощь всех, кто готов защитить свой дом и своих близких.$B$BЕсли ты $gготов:готова; откликнуться на призыв, то поговори с моим командиром, маршалом Макбрайдом. Он здесь, в аббатстве у меня за спиной.', 'Поговорите с маршалом Макбрайдом.', 0);
|
||||||
|
|
||||||
|
-- Fix Russian locale for QuestID: 792
|
||||||
|
DELETE FROM `quest_template_locale` WHERE `ID` = 792 AND `locale` = 'ruRU';
|
||||||
|
INSERT INTO `quest_template_locale` (`ID`, `locale`, `Title`, `Details`, `Objectives`, `VerifiedBuild`) VALUES (792, 'ruRU', 'Злобные фамильяры', 'Что ж, |3-6($c), надеюсь, у нас ты многому научишься.$b$bМеня послали сюда, чтобы я стала твоей наставницей, но оказывается, здесь не все ладно!$b$bВ долине Испытаний обосновался клан Пылающего Клинка. Эти твари скрываются в пещере на северо-востоке, и их злобные фамильяры выбираются оттуда и сеют хаос.$b$bИтак, вот твое первое задание в борьбе с Пылающим Клинком: перебей их столько, сколько сумеешь, и, если выживешь, возвращайся ко мне.', 'Убейте 8 злобных фамильяров и вернитесь к Зурите Востроглазой, которая ждет вас у Логова.', 0);
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- DB update 2025_02_03_00 -> 2025_02_03_01
|
||||||
|
--
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 25485) AND (`source_type` = 0) AND (`id` IN (0));
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
-- DB update 2025_02_03_01 -> 2025_02_04_00
|
||||||
|
--
|
||||||
|
-- Set questId on WP start
|
||||||
|
UPDATE `smart_scripts` SET `action_param4` = 5203 WHERE (`entryorguid` = 1101600) AND (`source_type` = 9) AND (`id` = 9);
|
||||||
|
-- Delete area explored action
|
||||||
|
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 11016) AND (`source_type` = 0) AND (`id` = 38);
|
||||||
|
UPDATE `smart_scripts` SET `link`=39 WHERE (`entryorguid` = 11016) AND (`source_type` = 0) AND (`id` = 37);
|
||||||
@@ -4304,6 +4304,19 @@ Event.Announce = 0
|
|||||||
#
|
#
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
|
# WORLD STATE
|
||||||
|
#
|
||||||
|
# Sunsreach.CounterMax
|
||||||
|
# Description: Counter value to be reached to transition phases
|
||||||
|
# during the Sun's Reach Reclamation event.
|
||||||
|
# Default: 10000
|
||||||
|
|
||||||
|
Sunsreach.CounterMax = 10000
|
||||||
|
|
||||||
|
#
|
||||||
|
###################################################################################################
|
||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
# AUCTION HOUSE
|
# AUCTION HOUSE
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -2696,7 +2696,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
|||||||
}
|
}
|
||||||
case SMART_ACTION_PLAYER_TALK:
|
case SMART_ACTION_PLAYER_TALK:
|
||||||
{
|
{
|
||||||
char const* text = sObjectMgr->GetAcoreString(e.action.playerTalk.textId, DEFAULT_LOCALE);
|
std::string text = sObjectMgr->GetAcoreString(e.action.playerTalk.textId, DEFAULT_LOCALE);
|
||||||
|
|
||||||
if (!targets.empty())
|
if (!targets.empty())
|
||||||
for (WorldObject* target : targets)
|
for (WorldObject* target : targets)
|
||||||
@@ -3282,6 +3282,16 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
|||||||
sWorldState->HandleExternalEvent(static_cast<WorldStateEvent>(e.action.worldStateScript.eventId), e.action.worldStateScript.param);
|
sWorldState->HandleExternalEvent(static_cast<WorldStateEvent>(e.action.worldStateScript.eventId), e.action.worldStateScript.param);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SMART_ACTION_DISABLE_REWARD:
|
||||||
|
{
|
||||||
|
for (WorldObject* target : targets)
|
||||||
|
if (IsCreature(target))
|
||||||
|
{
|
||||||
|
target->ToCreature()->SetReputationRewardDisabled(static_cast<bool>(e.action.reward.reputation));
|
||||||
|
target->ToCreature()->SetLootRewardDisabled(static_cast<bool>(e.action.reward.loot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -860,6 +860,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
|||||||
case SMART_ACTION_MOVEMENT_PAUSE: return sizeof(SmartAction::move);
|
case SMART_ACTION_MOVEMENT_PAUSE: return sizeof(SmartAction::move);
|
||||||
case SMART_ACTION_MOVEMENT_RESUME: return sizeof(SmartAction::move);
|
case SMART_ACTION_MOVEMENT_RESUME: return sizeof(SmartAction::move);
|
||||||
case SMART_ACTION_WORLD_SCRIPT: return sizeof(SmartAction::worldStateScript);
|
case SMART_ACTION_WORLD_SCRIPT: return sizeof(SmartAction::worldStateScript);
|
||||||
|
case SMART_ACTION_DISABLE_REWARD: return sizeof(SmartAction::reward);
|
||||||
default:
|
default:
|
||||||
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
|
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
|
||||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||||
@@ -1894,6 +1895,9 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
|||||||
return IsSAIBoolValid(e, e.action.setHealthRegen.regenHealth);
|
return IsSAIBoolValid(e, e.action.setHealthRegen.regenHealth);
|
||||||
case SMART_ACTION_CALL_TIMED_ACTIONLIST:
|
case SMART_ACTION_CALL_TIMED_ACTIONLIST:
|
||||||
return IsSAIBoolValid(e, e.action.timedActionList.allowOverride);
|
return IsSAIBoolValid(e, e.action.timedActionList.allowOverride);
|
||||||
|
case SMART_ACTION_DISABLE_REWARD:
|
||||||
|
return IsSAIBoolValid(e, e.action.reward.reputation) &&
|
||||||
|
IsSAIBoolValid(e, e.action.reward.loot);
|
||||||
case SMART_ACTION_FLEE_FOR_ASSIST:
|
case SMART_ACTION_FLEE_FOR_ASSIST:
|
||||||
case SMART_ACTION_MOVE_TO_POS:
|
case SMART_ACTION_MOVE_TO_POS:
|
||||||
case SMART_ACTION_EVADE:
|
case SMART_ACTION_EVADE:
|
||||||
|
|||||||
@@ -738,8 +738,9 @@ enum SMART_ACTION
|
|||||||
SMART_ACTION_MOVEMENT_PAUSE = 235, // timer
|
SMART_ACTION_MOVEMENT_PAUSE = 235, // timer
|
||||||
SMART_ACTION_MOVEMENT_RESUME = 236, // timerOverride
|
SMART_ACTION_MOVEMENT_RESUME = 236, // timerOverride
|
||||||
SMART_ACTION_WORLD_SCRIPT = 237, // eventId, param
|
SMART_ACTION_WORLD_SCRIPT = 237, // eventId, param
|
||||||
|
SMART_ACTION_DISABLE_REWARD = 238, // reputation 0/1, loot 0/1
|
||||||
|
|
||||||
SMART_ACTION_AC_END = 238, // placeholder
|
SMART_ACTION_AC_END = 239, // placeholder
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SmartActionSummonCreatureFlags
|
enum class SmartActionSummonCreatureFlags
|
||||||
@@ -1501,6 +1502,12 @@ struct SmartAction
|
|||||||
uint32 param5;
|
uint32 param5;
|
||||||
uint32 param6;
|
uint32 param6;
|
||||||
} raw;
|
} raw;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
SAIBool reputation;
|
||||||
|
SAIBool loot;
|
||||||
|
} reward;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2438,7 +2438,7 @@ bool AchievementMgr::HasAchieved(uint32 achievementId) const
|
|||||||
|
|
||||||
bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement)
|
bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement)
|
||||||
{
|
{
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, nullptr))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, nullptr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (achievement->mapID != -1 && GetPlayer()->GetMapId() != uint32(achievement->mapID))
|
if (achievement->mapID != -1 && GetPlayer()->GetMapId() != uint32(achievement->mapID))
|
||||||
@@ -2917,7 +2917,7 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetCriteriaDataSet(criteria) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, entryId, nullptr))
|
if (!GetCriteriaDataSet(criteria) && !sDisableMgr->IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, entryId, nullptr))
|
||||||
LOG_ERROR("sql.sql", "Table `achievement_criteria_data` does not have expected data for criteria (Entry: {} Type: {}) for achievement {}.", criteria->ID, criteria->requiredType, criteria->referredAchievement);
|
LOG_ERROR("sql.sql", "Table `achievement_criteria_data` does not have expected data for criteria (Entry: {} Type: {}) for achievement {}.", criteria->ID, criteria->requiredType, criteria->referredAchievement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ namespace Acore
|
|||||||
|
|
||||||
void operator()(WorldPacket& data, LocaleConstant loc_idx)
|
void operator()(WorldPacket& data, LocaleConstant loc_idx)
|
||||||
{
|
{
|
||||||
char const* text = sObjectMgr->GetAcoreString(_textId, loc_idx);
|
std::string strtext = sObjectMgr->GetAcoreString(_textId, loc_idx);
|
||||||
|
char const* text = strtext.c_str();
|
||||||
if (_args)
|
if (_args)
|
||||||
{
|
{
|
||||||
// we need copy va_list before use or original va_list will corrupted
|
// we need copy va_list before use or original va_list will corrupted
|
||||||
@@ -95,9 +96,12 @@ namespace Acore
|
|||||||
|
|
||||||
void operator()(WorldPacket& data, LocaleConstant loc_idx)
|
void operator()(WorldPacket& data, LocaleConstant loc_idx)
|
||||||
{
|
{
|
||||||
char const* text = sObjectMgr->GetAcoreString(_textId, loc_idx);
|
std::string strtext = sObjectMgr->GetAcoreString(_textId, loc_idx);
|
||||||
char const* arg1str = _arg1 ? sObjectMgr->GetAcoreString(_arg1, loc_idx) : "";
|
char const* text = strtext.c_str();
|
||||||
char const* arg2str = _arg2 ? sObjectMgr->GetAcoreString(_arg2, loc_idx) : "";
|
std::string stragr1str = sObjectMgr->GetAcoreString(_arg1, loc_idx);
|
||||||
|
char const* arg1str = _arg1 ? stragr1str.c_str() : "";
|
||||||
|
std::string strarg2str = sObjectMgr->GetAcoreString(_arg2, loc_idx);
|
||||||
|
char const* arg2str = _arg2 ? strarg2str.c_str() : "";
|
||||||
|
|
||||||
char str[2048];
|
char str[2048];
|
||||||
snprintf(str, 2048, text, arg1str, arg2str);
|
snprintf(str, 2048, text, arg1str, arg2str);
|
||||||
@@ -1659,13 +1663,6 @@ void Battleground::EndNow()
|
|||||||
SetEndTime(0);
|
SetEndTime(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// To be removed
|
|
||||||
char const* Battleground::GetAcoreString(int32 entry)
|
|
||||||
{
|
|
||||||
// FIXME: now we have different DBC locales and need localized message for each target client
|
|
||||||
return sObjectMgr->GetAcoreStringForDBCLocale(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Battleground::HandleTriggerBuff(GameObject* gameObject)
|
void Battleground::HandleTriggerBuff(GameObject* gameObject)
|
||||||
{
|
{
|
||||||
// Xinef: crash fix?
|
// Xinef: crash fix?
|
||||||
|
|||||||
@@ -559,8 +559,6 @@ public:
|
|||||||
|
|
||||||
void DoorOpen(uint32 type);
|
void DoorOpen(uint32 type);
|
||||||
void DoorClose(uint32 type);
|
void DoorClose(uint32 type);
|
||||||
//to be removed
|
|
||||||
const char* GetAcoreString(int32 entry);
|
|
||||||
|
|
||||||
virtual bool HandlePlayerUnderMap(Player* /*player*/) { return false; }
|
virtual bool HandlePlayerUnderMap(Player* /*player*/) { return false; }
|
||||||
|
|
||||||
|
|||||||
@@ -467,7 +467,7 @@ void BattlegroundMgr::LoadBattlegroundTemplates()
|
|||||||
|
|
||||||
BattlegroundTypeId bgTypeId = static_cast<BattlegroundTypeId>(fields[0].Get<uint32>());
|
BattlegroundTypeId bgTypeId = static_cast<BattlegroundTypeId>(fields[0].Get<uint32>());
|
||||||
|
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId, nullptr))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId, nullptr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// can be overwrite by values from DB
|
// can be overwrite by values from DB
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ Player* ChatHandler::GetPlayer() const
|
|||||||
return m_session ? m_session->GetPlayer() : nullptr;
|
return m_session ? m_session->GetPlayer() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* ChatHandler::GetAcoreString(uint32 entry) const
|
std::string ChatHandler::GetAcoreString(uint32 entry) const
|
||||||
{
|
{
|
||||||
return m_session->GetAcoreString(entry);
|
return m_session->GetAcoreString(entry);
|
||||||
}
|
}
|
||||||
@@ -953,7 +953,7 @@ std::string ChatHandler::GetNameLink(Player* chr) const
|
|||||||
return playerLink(chr->GetName());
|
return playerLink(chr->GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* CliHandler::GetAcoreString(uint32 entry) const
|
std::string CliHandler::GetAcoreString(uint32 entry) const
|
||||||
{
|
{
|
||||||
return sObjectMgr->GetAcoreStringForDBCLocale(entry);
|
return sObjectMgr->GetAcoreStringForDBCLocale(entry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// function with different implementation for chat/console
|
// function with different implementation for chat/console
|
||||||
virtual char const* GetAcoreString(uint32 entry) const;
|
virtual std::string GetAcoreString(uint32 entry) const;
|
||||||
virtual void SendSysMessage(std::string_view str, bool escapeCharacters = false);
|
virtual void SendSysMessage(std::string_view str, bool escapeCharacters = false);
|
||||||
|
|
||||||
void SendSysMessage(uint32 entry);
|
void SendSysMessage(uint32 entry);
|
||||||
@@ -276,7 +276,7 @@ public:
|
|||||||
explicit CliHandler(void* callbackArg, Print* zprint) : m_callbackArg(callbackArg), m_print(zprint) { }
|
explicit CliHandler(void* callbackArg, Print* zprint) : m_callbackArg(callbackArg), m_print(zprint) { }
|
||||||
|
|
||||||
// overwrite functions
|
// overwrite functions
|
||||||
char const* GetAcoreString(uint32 entry) const override;
|
std::string GetAcoreString(uint32 entry) const override;
|
||||||
void SendSysMessage(std::string_view, bool escapeCharacters) override;
|
void SendSysMessage(std::string_view, bool escapeCharacters) override;
|
||||||
bool ParseCommands(std::string_view str) override;
|
bool ParseCommands(std::string_view str) override;
|
||||||
std::string GetNameLink() const override;
|
std::string GetNameLink() const override;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ void Acore::Impl::ChatCommands::SendErrorMessageToHandler(ChatHandler* handler,
|
|||||||
handler->SetSentErrorMessage(true);
|
handler->SetSentErrorMessage(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* Acore::Impl::ChatCommands::GetAcoreString(ChatHandler const* handler, AcoreStrings which)
|
std::string Acore::Impl::ChatCommands::GetAcoreString(ChatHandler const* handler, AcoreStrings which)
|
||||||
{
|
{
|
||||||
return handler->GetAcoreString(which);
|
return handler->GetAcoreString(which);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ namespace Acore::Impl::ChatCommands
|
|||||||
};
|
};
|
||||||
|
|
||||||
AC_GAME_API void SendErrorMessageToHandler(ChatHandler* handler, std::string_view str);
|
AC_GAME_API void SendErrorMessageToHandler(ChatHandler* handler, std::string_view str);
|
||||||
AC_GAME_API char const* GetAcoreString(ChatHandler const* handler, AcoreStrings which);
|
AC_GAME_API std::string GetAcoreString(ChatHandler const* handler, AcoreStrings which);
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
std::string FormatAcoreString(ChatHandler const* handler, AcoreStrings which, Ts&&... args)
|
std::string FormatAcoreString(ChatHandler const* handler, AcoreStrings which, Ts&&... args)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,393 +28,418 @@
|
|||||||
#include "VMapMgr2.h"
|
#include "VMapMgr2.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
|
||||||
namespace DisableMgr
|
std::map<DisableType, std::map<uint32, DisableData>> DisableMgr::m_DisableMap;
|
||||||
|
|
||||||
|
DisableMgr::DisableMgr() {}
|
||||||
|
DisableMgr::~DisableMgr() {}
|
||||||
|
|
||||||
|
DisableMgr* DisableMgr::instance()
|
||||||
{
|
{
|
||||||
namespace
|
static DisableMgr instance;
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisableMgr::LoadDisables()
|
||||||
|
{
|
||||||
|
uint32 oldMSTime = getMSTime();
|
||||||
|
|
||||||
|
// reload case
|
||||||
|
for (DisableMap::iterator itr = m_DisableMap.begin(); itr != m_DisableMap.end(); ++itr)
|
||||||
|
itr->second.clear();
|
||||||
|
|
||||||
|
m_DisableMap.clear();
|
||||||
|
|
||||||
|
QueryResult result = WorldDatabase.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables");
|
||||||
|
|
||||||
|
uint32 total_count = 0;
|
||||||
|
|
||||||
|
if (!result)
|
||||||
{
|
{
|
||||||
struct DisableData
|
LOG_WARN("server.loading", ">> Loaded 0 disables. DB table `disables` is empty!");
|
||||||
{
|
|
||||||
uint8 flags;
|
|
||||||
std::set<uint32> params[2]; // params0, params1
|
|
||||||
};
|
|
||||||
|
|
||||||
// single disables here with optional data
|
|
||||||
typedef std::map<uint32, DisableData> DisableTypeMap;
|
|
||||||
// global disable map by source
|
|
||||||
typedef std::map<DisableType, DisableTypeMap> DisableMap;
|
|
||||||
|
|
||||||
DisableMap m_DisableMap;
|
|
||||||
|
|
||||||
uint8 MAX_DISABLE_TYPES = 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadDisables()
|
|
||||||
{
|
|
||||||
uint32 oldMSTime = getMSTime();
|
|
||||||
|
|
||||||
// reload case
|
|
||||||
for (DisableMap::iterator itr = m_DisableMap.begin(); itr != m_DisableMap.end(); ++itr)
|
|
||||||
itr->second.clear();
|
|
||||||
|
|
||||||
m_DisableMap.clear();
|
|
||||||
|
|
||||||
QueryResult result = WorldDatabase.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables");
|
|
||||||
|
|
||||||
uint32 total_count = 0;
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
LOG_WARN("server.loading", ">> Loaded 0 disables. DB table `disables` is empty!");
|
|
||||||
LOG_INFO("server.loading", " ");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Field* fields;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
fields = result->Fetch();
|
|
||||||
DisableType type = DisableType(fields[0].Get<uint32>());
|
|
||||||
if (type >= MAX_DISABLE_TYPES)
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Invalid type {} specified in `disables` table, skipped.", type);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 entry = fields[1].Get<uint32>();
|
|
||||||
uint8 flags = fields[2].Get<uint8>();
|
|
||||||
std::string params_0 = fields[3].Get<std::string>();
|
|
||||||
std::string params_1 = fields[4].Get<std::string>();
|
|
||||||
|
|
||||||
DisableData data;
|
|
||||||
data.flags = flags;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case DISABLE_TYPE_GO_LOS:
|
|
||||||
if (!sObjectMgr->GetGameObjectTemplate(entry))
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Gameobject entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (flags)
|
|
||||||
LOG_ERROR("sql.sql", "Disable flags specified for gameobject {}, useless data.", entry);
|
|
||||||
break;
|
|
||||||
case DISABLE_TYPE_SPELL:
|
|
||||||
if (!(sSpellMgr->GetSpellInfo(entry) || flags & SPELL_DISABLE_DEPRECATED_SPELL))
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Spell entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!flags || flags > MAX_SPELL_DISABLE_TYPE)
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Disable flags for spell {} are invalid, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & SPELL_DISABLE_MAP)
|
|
||||||
{
|
|
||||||
for (std::string_view mapStr : Acore::Tokenize(params_0, ',', true))
|
|
||||||
{
|
|
||||||
if (Optional<uint32> mapId = Acore::StringTo<uint32>(mapStr))
|
|
||||||
data.params[0].insert(*mapId);
|
|
||||||
else
|
|
||||||
LOG_ERROR("sql.sql", "Disable map '{}' for spell {} is invalid, skipped.", mapStr, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & SPELL_DISABLE_AREA)
|
|
||||||
{
|
|
||||||
for (std::string_view areaStr : Acore::Tokenize(params_1, ',', true))
|
|
||||||
{
|
|
||||||
if (Optional<uint32> areaId = Acore::StringTo<uint32>(areaStr))
|
|
||||||
data.params[1].insert(*areaId);
|
|
||||||
else
|
|
||||||
LOG_ERROR("sql.sql", "Disable area '{}' for spell {} is invalid, skipped.", areaStr, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// xinef: if spell has disabled los, add flag
|
|
||||||
if (flags & SPELL_DISABLE_LOS)
|
|
||||||
{
|
|
||||||
SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->GetSpellInfo(entry));
|
|
||||||
spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
// checked later
|
|
||||||
case DISABLE_TYPE_QUEST:
|
|
||||||
break;
|
|
||||||
case DISABLE_TYPE_MAP:
|
|
||||||
case DISABLE_TYPE_LFG_MAP:
|
|
||||||
{
|
|
||||||
MapEntry const* mapEntry = sMapStore.LookupEntry(entry);
|
|
||||||
if (!mapEntry)
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Map entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bool isFlagInvalid = false;
|
|
||||||
switch (mapEntry->map_type)
|
|
||||||
{
|
|
||||||
case MAP_COMMON:
|
|
||||||
if (flags)
|
|
||||||
isFlagInvalid = true;
|
|
||||||
break;
|
|
||||||
case MAP_INSTANCE:
|
|
||||||
case MAP_RAID:
|
|
||||||
if (flags & DUNGEON_STATUSFLAG_HEROIC && !GetMapDifficultyData(entry, DUNGEON_DIFFICULTY_HEROIC))
|
|
||||||
isFlagInvalid = true;
|
|
||||||
else if (flags & RAID_STATUSFLAG_10MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_10MAN_HEROIC))
|
|
||||||
isFlagInvalid = true;
|
|
||||||
else if (flags & RAID_STATUSFLAG_25MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_25MAN_HEROIC))
|
|
||||||
isFlagInvalid = true;
|
|
||||||
break;
|
|
||||||
case MAP_BATTLEGROUND:
|
|
||||||
case MAP_ARENA:
|
|
||||||
LOG_ERROR("sql.sql", "Battleground map {} specified to be disabled in map case, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (isFlagInvalid)
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Disable flags for map {} are invalid, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DISABLE_TYPE_BATTLEGROUND:
|
|
||||||
if (!sBattlemasterListStore.LookupEntry(entry))
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Battleground entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (flags)
|
|
||||||
LOG_ERROR("sql.sql", "Disable flags specified for battleground {}, useless data.", entry);
|
|
||||||
break;
|
|
||||||
case DISABLE_TYPE_OUTDOORPVP:
|
|
||||||
if (entry > MAX_OUTDOORPVP_TYPES)
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "OutdoorPvPTypes value {} from `disables` is invalid, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (flags)
|
|
||||||
LOG_ERROR("sql.sql", "Disable flags specified for outdoor PvP {}, useless data.", entry);
|
|
||||||
break;
|
|
||||||
case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
|
|
||||||
if (!sAchievementCriteriaStore.LookupEntry(entry))
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Achievement Criteria entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (flags)
|
|
||||||
LOG_ERROR("sql.sql", "Disable flags specified for Achievement Criteria {}, useless data.", entry);
|
|
||||||
break;
|
|
||||||
case DISABLE_TYPE_VMAP:
|
|
||||||
{
|
|
||||||
MapEntry const* mapEntry = sMapStore.LookupEntry(entry);
|
|
||||||
if (!mapEntry)
|
|
||||||
{
|
|
||||||
LOG_ERROR("sql.sql", "Map entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (mapEntry->map_type)
|
|
||||||
{
|
|
||||||
case MAP_COMMON:
|
|
||||||
if (flags & VMAP::VMAP_DISABLE_AREAFLAG)
|
|
||||||
LOG_INFO("disable", "Areaflag disabled for world map {}.", entry);
|
|
||||||
if (flags & VMAP::VMAP_DISABLE_LIQUIDSTATUS)
|
|
||||||
LOG_INFO("disable", "Liquid status disabled for world map {}.", entry);
|
|
||||||
break;
|
|
||||||
case MAP_INSTANCE:
|
|
||||||
case MAP_RAID:
|
|
||||||
if (flags & VMAP::VMAP_DISABLE_HEIGHT)
|
|
||||||
LOG_INFO("disable", "Height disabled for instance map {}.", entry);
|
|
||||||
if (flags & VMAP::VMAP_DISABLE_LOS)
|
|
||||||
LOG_INFO("disable", "LoS disabled for instance map {}.", entry);
|
|
||||||
break;
|
|
||||||
case MAP_BATTLEGROUND:
|
|
||||||
if (flags & VMAP::VMAP_DISABLE_HEIGHT)
|
|
||||||
LOG_INFO("disable", "Height disabled for battleground map {}.", entry);
|
|
||||||
if (flags & VMAP::VMAP_DISABLE_LOS)
|
|
||||||
LOG_INFO("disable", "LoS disabled for battleground map {}.", entry);
|
|
||||||
break;
|
|
||||||
case MAP_ARENA:
|
|
||||||
if (flags & VMAP::VMAP_DISABLE_HEIGHT)
|
|
||||||
LOG_INFO("disable", "Height disabled for arena map {}.", entry);
|
|
||||||
if (flags & VMAP::VMAP_DISABLE_LOS)
|
|
||||||
LOG_INFO("disable", "LoS disabled for arena map {}.", entry);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DISABLE_TYPE_GAME_EVENT:
|
|
||||||
{
|
|
||||||
GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList();
|
|
||||||
if (activeEvents.find(entry) != activeEvents.end())
|
|
||||||
{
|
|
||||||
sGameEventMgr->StopEvent(entry);
|
|
||||||
LOG_INFO("disable", "Event entry {} was stopped because it has been disabled.", entry);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DISABLE_TYPE_LOOT:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_DisableMap[type].insert(DisableTypeMap::value_type(entry, data));
|
|
||||||
++total_count;
|
|
||||||
} while (result->NextRow());
|
|
||||||
|
|
||||||
LOG_INFO("server.loading", ">> Loaded {} Disables in {} ms", total_count, GetMSTimeDiffToNow(oldMSTime));
|
|
||||||
LOG_INFO("server.loading", " ");
|
LOG_INFO("server.loading", " ");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckQuestDisables()
|
Field* fields;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
uint32 oldMSTime = getMSTime();
|
fields = result->Fetch();
|
||||||
|
DisableType type = DisableType(fields[0].Get<uint32>());
|
||||||
uint32 count = m_DisableMap[DISABLE_TYPE_QUEST].size();
|
if (type >= MAX_DISABLE_TYPES)
|
||||||
if (!count)
|
|
||||||
{
|
{
|
||||||
LOG_INFO("server.loading", ">> Checked 0 quest disables.");
|
LOG_ERROR("sql.sql", "Invalid type {} specified in `disables` table, skipped.", type);
|
||||||
LOG_INFO("server.loading", " ");
|
continue;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check only quests, rest already done at startup
|
uint32 entry = fields[1].Get<uint32>();
|
||||||
for (DisableTypeMap::iterator itr = m_DisableMap[DISABLE_TYPE_QUEST].begin(); itr != m_DisableMap[DISABLE_TYPE_QUEST].end();)
|
uint8 flags = fields[2].Get<uint8>();
|
||||||
|
std::string params_0 = fields[3].Get<std::string>();
|
||||||
|
std::string params_1 = fields[4].Get<std::string>();
|
||||||
|
|
||||||
|
DisableData data;
|
||||||
|
data.flags = flags;
|
||||||
|
|
||||||
|
if (!HandleDisableType(type, entry, flags, params_0, params_1, data))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_DisableMap[type].insert(DisableTypeMap::value_type(entry, data));
|
||||||
|
++total_count;
|
||||||
|
} while (result->NextRow());
|
||||||
|
|
||||||
|
LOG_INFO("server.loading", ">> Loaded {} Disables in {} ms", total_count, GetMSTimeDiffToNow(oldMSTime));
|
||||||
|
LOG_INFO("server.loading", " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allow to add disables without adding it to the database. Useful for modules.
|
||||||
|
*
|
||||||
|
* @param type Disable type
|
||||||
|
* @param entry Entry of Spell/Quest/Map/BG/Achievement/Map/GameEvent/Item
|
||||||
|
* @param flags Flag depending on Type
|
||||||
|
* @param param0 MapId if DISABLE_TYPE_SPELL used, 0 for all maps.
|
||||||
|
* @param param1 AreaId if DISABLE_TYPE_SPELL used, 0 for all areas.
|
||||||
|
*/
|
||||||
|
void DisableMgr::AddDisable(DisableType type, uint32 entry, uint8 flags, std::string param0, std::string param1)
|
||||||
|
{
|
||||||
|
if (type >= MAX_DISABLE_TYPES)
|
||||||
|
{
|
||||||
|
LOG_ERROR("disables", "AddDisable: Invalid type {} specified for entry {}, skipped.", type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisableData data;
|
||||||
|
data.flags = flags;
|
||||||
|
|
||||||
|
if (!HandleDisableType(type, entry, flags, param0, param1, data))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_DisableMap[type].insert(DisableTypeMap::value_type(entry, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DisableMgr::HandleDisableType(DisableType type, uint32 entry, uint8 flags, std::string const& params_0, std::string const& params_1, DisableData& data)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DISABLE_TYPE_GO_LOS:
|
||||||
|
if (!sObjectMgr->GetGameObjectTemplate(entry))
|
||||||
{
|
{
|
||||||
const uint32 entry = itr->first;
|
LOG_ERROR("sql.sql", "Gameobject entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||||
if (!sObjectMgr->GetQuestTemplate(entry))
|
return false;
|
||||||
|
}
|
||||||
|
if (flags)
|
||||||
|
LOG_ERROR("sql.sql", "Disable flags specified for gameobject {}, useless data.", entry);
|
||||||
|
break;
|
||||||
|
case DISABLE_TYPE_SPELL:
|
||||||
|
if (!(sSpellMgr->GetSpellInfo(entry) || flags & SPELL_DISABLE_DEPRECATED_SPELL))
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Spell entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flags || flags > MAX_SPELL_DISABLE_TYPE)
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Disable flags for spell {} are invalid, skipped.", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & SPELL_DISABLE_MAP)
|
||||||
|
{
|
||||||
|
for (std::string_view mapStr : Acore::Tokenize(params_0, ',', true))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Quest entry {} from `disables` doesn't exist, skipped.", entry);
|
if (Optional<uint32> mapId = Acore::StringTo<uint32>(mapStr))
|
||||||
m_DisableMap[DISABLE_TYPE_QUEST].erase(itr++);
|
data.params[0].insert(*mapId);
|
||||||
continue;
|
else
|
||||||
|
LOG_ERROR("sql.sql", "Disable map '{}' for spell {} is invalid, skipped.", mapStr, entry);
|
||||||
}
|
}
|
||||||
if (itr->second.flags)
|
|
||||||
LOG_ERROR("sql.sql", "Disable flags specified for quest {}, useless data.", entry);
|
|
||||||
++itr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("server.loading", ">> Checked {} Quest Disables in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
if (flags & SPELL_DISABLE_AREA)
|
||||||
|
{
|
||||||
|
for (std::string_view areaStr : Acore::Tokenize(params_1, ',', true))
|
||||||
|
{
|
||||||
|
if (Optional<uint32> areaId = Acore::StringTo<uint32>(areaStr))
|
||||||
|
data.params[1].insert(*areaId);
|
||||||
|
else
|
||||||
|
LOG_ERROR("sql.sql", "Disable area '{}' for spell {} is invalid, skipped.", areaStr, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// xinef: if spell has disabled los, add flag
|
||||||
|
if (flags & SPELL_DISABLE_LOS)
|
||||||
|
{
|
||||||
|
SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->GetSpellInfo(entry));
|
||||||
|
spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
// checked later
|
||||||
|
case DISABLE_TYPE_QUEST:
|
||||||
|
break;
|
||||||
|
case DISABLE_TYPE_MAP:
|
||||||
|
case DISABLE_TYPE_LFG_MAP:
|
||||||
|
{
|
||||||
|
MapEntry const* mapEntry = sMapStore.LookupEntry(entry);
|
||||||
|
if (!mapEntry)
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Map entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool isFlagInvalid = false;
|
||||||
|
switch (mapEntry->map_type)
|
||||||
|
{
|
||||||
|
case MAP_COMMON:
|
||||||
|
if (flags)
|
||||||
|
isFlagInvalid = true;
|
||||||
|
break;
|
||||||
|
case MAP_INSTANCE:
|
||||||
|
case MAP_RAID:
|
||||||
|
if (flags & DUNGEON_STATUSFLAG_HEROIC && !GetMapDifficultyData(entry, DUNGEON_DIFFICULTY_HEROIC))
|
||||||
|
isFlagInvalid = true;
|
||||||
|
else if (flags & RAID_STATUSFLAG_10MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_10MAN_HEROIC))
|
||||||
|
isFlagInvalid = true;
|
||||||
|
else if (flags & RAID_STATUSFLAG_25MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_25MAN_HEROIC))
|
||||||
|
isFlagInvalid = true;
|
||||||
|
break;
|
||||||
|
case MAP_BATTLEGROUND:
|
||||||
|
case MAP_ARENA:
|
||||||
|
LOG_ERROR("sql.sql", "Battleground map {} specified to be disabled in map case, skipped.", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isFlagInvalid)
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Disable flags for map {} are invalid, skipped.", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DISABLE_TYPE_BATTLEGROUND:
|
||||||
|
if (!sBattlemasterListStore.LookupEntry(entry))
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Battleground entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (flags)
|
||||||
|
LOG_ERROR("sql.sql", "Disable flags specified for battleground {}, useless data.", entry);
|
||||||
|
break;
|
||||||
|
case DISABLE_TYPE_OUTDOORPVP:
|
||||||
|
if (entry > MAX_OUTDOORPVP_TYPES)
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "OutdoorPvPTypes value {} from `disables` is invalid, skipped.", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (flags)
|
||||||
|
LOG_ERROR("sql.sql", "Disable flags specified for outdoor PvP {}, useless data.", entry);
|
||||||
|
break;
|
||||||
|
case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
|
||||||
|
if (!sAchievementCriteriaStore.LookupEntry(entry))
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Achievement Criteria entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (flags)
|
||||||
|
LOG_ERROR("sql.sql", "Disable flags specified for Achievement Criteria {}, useless data.", entry);
|
||||||
|
break;
|
||||||
|
case DISABLE_TYPE_VMAP:
|
||||||
|
{
|
||||||
|
MapEntry const* mapEntry = sMapStore.LookupEntry(entry);
|
||||||
|
if (!mapEntry)
|
||||||
|
{
|
||||||
|
LOG_ERROR("sql.sql", "Map entry {} from `disables` doesn't exist in dbc, skipped.", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (mapEntry->map_type)
|
||||||
|
{
|
||||||
|
case MAP_COMMON:
|
||||||
|
if (flags & VMAP::VMAP_DISABLE_AREAFLAG)
|
||||||
|
LOG_INFO("disable", "Areaflag disabled for world map {}.", entry);
|
||||||
|
if (flags & VMAP::VMAP_DISABLE_LIQUIDSTATUS)
|
||||||
|
LOG_INFO("disable", "Liquid status disabled for world map {}.", entry);
|
||||||
|
break;
|
||||||
|
case MAP_INSTANCE:
|
||||||
|
case MAP_RAID:
|
||||||
|
if (flags & VMAP::VMAP_DISABLE_HEIGHT)
|
||||||
|
LOG_INFO("disable", "Height disabled for instance map {}.", entry);
|
||||||
|
if (flags & VMAP::VMAP_DISABLE_LOS)
|
||||||
|
LOG_INFO("disable", "LoS disabled for instance map {}.", entry);
|
||||||
|
break;
|
||||||
|
case MAP_BATTLEGROUND:
|
||||||
|
if (flags & VMAP::VMAP_DISABLE_HEIGHT)
|
||||||
|
LOG_INFO("disable", "Height disabled for battleground map {}.", entry);
|
||||||
|
if (flags & VMAP::VMAP_DISABLE_LOS)
|
||||||
|
LOG_INFO("disable", "LoS disabled for battleground map {}.", entry);
|
||||||
|
break;
|
||||||
|
case MAP_ARENA:
|
||||||
|
if (flags & VMAP::VMAP_DISABLE_HEIGHT)
|
||||||
|
LOG_INFO("disable", "Height disabled for arena map {}.", entry);
|
||||||
|
if (flags & VMAP::VMAP_DISABLE_LOS)
|
||||||
|
LOG_INFO("disable", "LoS disabled for arena map {}.", entry);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DISABLE_TYPE_GAME_EVENT:
|
||||||
|
{
|
||||||
|
GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList();
|
||||||
|
if (activeEvents.find(entry) != activeEvents.end())
|
||||||
|
{
|
||||||
|
sGameEventMgr->StopEvent(entry);
|
||||||
|
LOG_INFO("disable", "Event entry {} was stopped because it has been disabled.", entry);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DISABLE_TYPE_LOOT:
|
||||||
|
break;
|
||||||
|
case MAX_DISABLE_TYPES:
|
||||||
|
{
|
||||||
|
LOG_ERROR("disable", "SourceType out of range for entry {}, skipped", entry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisableMgr::CheckQuestDisables()
|
||||||
|
{
|
||||||
|
uint32 oldMSTime = getMSTime();
|
||||||
|
|
||||||
|
uint32 count = m_DisableMap[DISABLE_TYPE_QUEST].size();
|
||||||
|
if (!count)
|
||||||
|
{
|
||||||
|
LOG_INFO("server.loading", ">> Checked 0 quest disables.");
|
||||||
LOG_INFO("server.loading", " ");
|
LOG_INFO("server.loading", " ");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags)
|
// check only quests, rest already done at startup
|
||||||
|
for (DisableTypeMap::iterator itr = m_DisableMap[DISABLE_TYPE_QUEST].begin(); itr != m_DisableMap[DISABLE_TYPE_QUEST].end();)
|
||||||
{
|
{
|
||||||
if (type > MAX_DISABLE_TYPES)
|
const uint32 entry = itr->first;
|
||||||
|
if (!sObjectMgr->GetQuestTemplate(entry))
|
||||||
{
|
{
|
||||||
LOG_ERROR("server", "Disables::IsDisabledFor() called with unknown disable type {}! (entry {}, flags {}).", type, entry, flags);
|
LOG_ERROR("sql.sql", "Quest entry {} from `disables` doesn't exist, skipped.", entry);
|
||||||
return false;
|
m_DisableMap[DISABLE_TYPE_QUEST].erase(itr++);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (itr->second.flags)
|
||||||
|
LOG_ERROR("sql.sql", "Disable flags specified for quest {}, useless data.", entry);
|
||||||
|
++itr;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_DisableMap[type].empty())
|
LOG_INFO("server.loading", ">> Checked {} Quest Disables in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||||
return false;
|
LOG_INFO("server.loading", " ");
|
||||||
|
}
|
||||||
DisableTypeMap::iterator itr = m_DisableMap[type].find(entry);
|
|
||||||
if (itr == m_DisableMap[type].end()) // not disabled
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case DISABLE_TYPE_SPELL:
|
|
||||||
{
|
|
||||||
uint8 spellFlags = itr->second.flags;
|
|
||||||
if (unit)
|
|
||||||
{
|
|
||||||
if ((spellFlags & SPELL_DISABLE_PLAYER && unit->IsPlayer()) ||
|
|
||||||
(unit->IsCreature() && ((unit->IsPet() && spellFlags & SPELL_DISABLE_PET) || spellFlags & SPELL_DISABLE_CREATURE)))
|
|
||||||
{
|
|
||||||
if (spellFlags & SPELL_DISABLE_MAP)
|
|
||||||
{
|
|
||||||
std::set<uint32> const& mapIds = itr->second.params[0];
|
|
||||||
if (mapIds.find(unit->GetMapId()) != mapIds.end())
|
|
||||||
return true; // Spell is disabled on current map
|
|
||||||
|
|
||||||
if (!(spellFlags & SPELL_DISABLE_AREA))
|
|
||||||
return false; // Spell is disabled on another map, but not this one, return false
|
|
||||||
|
|
||||||
// Spell is disabled in an area, but not explicitly our current mapId. Continue processing.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spellFlags & SPELL_DISABLE_AREA)
|
|
||||||
{
|
|
||||||
std::set<uint32> const& areaIds = itr->second.params[1];
|
|
||||||
if (areaIds.find(unit->GetAreaId()) != areaIds.end())
|
|
||||||
return true; // Spell is disabled in this area
|
|
||||||
return false; // Spell is disabled in another area, but not this one, return false
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return true; // Spell disabled for all maps
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (spellFlags & SPELL_DISABLE_DEPRECATED_SPELL) // call not from spellcast
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DISABLE_TYPE_MAP:
|
|
||||||
case DISABLE_TYPE_LFG_MAP:
|
|
||||||
if (Player const* player = unit->ToPlayer())
|
|
||||||
{
|
|
||||||
MapEntry const* mapEntry = sMapStore.LookupEntry(entry);
|
|
||||||
if (mapEntry->IsDungeon())
|
|
||||||
{
|
|
||||||
uint8 disabledModes = itr->second.flags;
|
|
||||||
Difficulty targetDifficulty = player->GetDifficulty(mapEntry->IsRaid());
|
|
||||||
GetDownscaledMapDifficultyData(entry, targetDifficulty);
|
|
||||||
switch (targetDifficulty)
|
|
||||||
{
|
|
||||||
case DUNGEON_DIFFICULTY_NORMAL:
|
|
||||||
return disabledModes & DUNGEON_STATUSFLAG_NORMAL;
|
|
||||||
case DUNGEON_DIFFICULTY_HEROIC:
|
|
||||||
return disabledModes & DUNGEON_STATUSFLAG_HEROIC;
|
|
||||||
case RAID_DIFFICULTY_10MAN_HEROIC:
|
|
||||||
return disabledModes & RAID_STATUSFLAG_10MAN_HEROIC;
|
|
||||||
case RAID_DIFFICULTY_25MAN_HEROIC:
|
|
||||||
return disabledModes & RAID_STATUSFLAG_25MAN_HEROIC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mapEntry->map_type == MAP_COMMON)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case DISABLE_TYPE_QUEST:
|
|
||||||
return true;
|
|
||||||
case DISABLE_TYPE_BATTLEGROUND:
|
|
||||||
case DISABLE_TYPE_OUTDOORPVP:
|
|
||||||
case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
|
|
||||||
return true;
|
|
||||||
case DISABLE_TYPE_VMAP:
|
|
||||||
return flags & itr->second.flags;
|
|
||||||
case DISABLE_TYPE_GO_LOS:
|
|
||||||
return true;
|
|
||||||
case DISABLE_TYPE_GAME_EVENT:
|
|
||||||
return true;
|
|
||||||
case DISABLE_TYPE_LOOT:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
bool DisableMgr::IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags)
|
||||||
|
{
|
||||||
|
if (type >= MAX_DISABLE_TYPES)
|
||||||
|
{
|
||||||
|
LOG_ERROR("server", "Disables::IsDisabledFor() called with unknown disable type {}! (entry {}, flags {}).", type, entry, flags);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsVMAPDisabledFor(uint32 entry, uint8 flags)
|
if (m_DisableMap[type].empty())
|
||||||
{
|
return false;
|
||||||
return IsDisabledFor(DISABLE_TYPE_VMAP, entry, nullptr, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsPathfindingEnabled(const Map* map)
|
DisableTypeMap::iterator itr = m_DisableMap[type].find(entry);
|
||||||
|
if (itr == m_DisableMap[type].end()) // not disabled
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
{
|
{
|
||||||
if (!map)
|
case DISABLE_TYPE_SPELL:
|
||||||
|
{
|
||||||
|
uint8 spellFlags = itr->second.flags;
|
||||||
|
if (unit)
|
||||||
|
{
|
||||||
|
if ((spellFlags & SPELL_DISABLE_PLAYER && unit->IsPlayer()) ||
|
||||||
|
(unit->IsCreature() && ((unit->IsPet() && spellFlags & SPELL_DISABLE_PET) || spellFlags & SPELL_DISABLE_CREATURE)))
|
||||||
|
{
|
||||||
|
if (spellFlags & SPELL_DISABLE_MAP)
|
||||||
|
{
|
||||||
|
std::set<uint32> const& mapIds = itr->second.params[0];
|
||||||
|
if (mapIds.find(unit->GetMapId()) != mapIds.end())
|
||||||
|
return true; // Spell is disabled on current map
|
||||||
|
|
||||||
|
if (!(spellFlags & SPELL_DISABLE_AREA))
|
||||||
|
return false; // Spell is disabled on another map, but not this one, return false
|
||||||
|
|
||||||
|
// Spell is disabled in an area, but not explicitly our current mapId. Continue processing.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spellFlags & SPELL_DISABLE_AREA)
|
||||||
|
{
|
||||||
|
std::set<uint32> const& areaIds = itr->second.params[1];
|
||||||
|
if (areaIds.find(unit->GetAreaId()) != areaIds.end())
|
||||||
|
return true; // Spell is disabled in this area
|
||||||
|
return false; // Spell is disabled in another area, but not this one, return false
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return true; // Spell disabled for all maps
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (spellFlags & SPELL_DISABLE_DEPRECATED_SPELL) // call not from spellcast
|
||||||
|
return true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DISABLE_TYPE_MAP:
|
||||||
|
case DISABLE_TYPE_LFG_MAP:
|
||||||
|
if (Player const* player = unit->ToPlayer())
|
||||||
|
{
|
||||||
|
MapEntry const* mapEntry = sMapStore.LookupEntry(entry);
|
||||||
|
if (mapEntry->IsDungeon())
|
||||||
|
{
|
||||||
|
uint8 disabledModes = itr->second.flags;
|
||||||
|
Difficulty targetDifficulty = player->GetDifficulty(mapEntry->IsRaid());
|
||||||
|
GetDownscaledMapDifficultyData(entry, targetDifficulty);
|
||||||
|
switch (targetDifficulty)
|
||||||
|
{
|
||||||
|
case DUNGEON_DIFFICULTY_NORMAL:
|
||||||
|
return disabledModes & DUNGEON_STATUSFLAG_NORMAL;
|
||||||
|
case DUNGEON_DIFFICULTY_HEROIC:
|
||||||
|
return disabledModes & DUNGEON_STATUSFLAG_HEROIC;
|
||||||
|
case RAID_DIFFICULTY_10MAN_HEROIC:
|
||||||
|
return disabledModes & RAID_STATUSFLAG_10MAN_HEROIC;
|
||||||
|
case RAID_DIFFICULTY_25MAN_HEROIC:
|
||||||
|
return disabledModes & RAID_STATUSFLAG_25MAN_HEROIC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mapEntry->map_type == MAP_COMMON)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
|
case DISABLE_TYPE_VMAP:
|
||||||
return !MMAP::MMapFactory::forbiddenMaps[map->GetId()] && (sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) ? true : map->IsBattlegroundOrArena());
|
return flags & itr->second.flags;
|
||||||
|
case DISABLE_TYPE_QUEST:
|
||||||
|
case DISABLE_TYPE_BATTLEGROUND:
|
||||||
|
case DISABLE_TYPE_OUTDOORPVP:
|
||||||
|
case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
|
||||||
|
case DISABLE_TYPE_GO_LOS:
|
||||||
|
case DISABLE_TYPE_GAME_EVENT:
|
||||||
|
case DISABLE_TYPE_LOOT:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Namespace
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DisableMgr::IsVMAPDisabledFor(uint32 entry, uint8 flags)
|
||||||
|
{
|
||||||
|
return IsDisabledFor(DISABLE_TYPE_VMAP, entry, nullptr, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DisableMgr::IsPathfindingEnabled(Map const* map)
|
||||||
|
{
|
||||||
|
if (!map)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !MMAP::MMapFactory::forbiddenMaps[map->GetId()] && (sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) ? true : map->IsBattlegroundOrArena());
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ACORE_DISABLEMGR_H
|
#ifndef _DISABLEMGR_H
|
||||||
#define ACORE_DISABLEMGR_H
|
#define _DISABLEMGR_H
|
||||||
|
|
||||||
#include "Define.h"
|
#include "Define.h"
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
@@ -34,7 +34,8 @@ enum DisableType
|
|||||||
DISABLE_TYPE_GO_LOS = 7,
|
DISABLE_TYPE_GO_LOS = 7,
|
||||||
DISABLE_TYPE_LFG_MAP = 8,
|
DISABLE_TYPE_LFG_MAP = 8,
|
||||||
DISABLE_TYPE_GAME_EVENT = 9,
|
DISABLE_TYPE_GAME_EVENT = 9,
|
||||||
DISABLE_TYPE_LOOT = 10
|
DISABLE_TYPE_LOOT = 10,
|
||||||
|
MAX_DISABLE_TYPES
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SpellDisableTypes
|
enum SpellDisableTypes
|
||||||
@@ -46,18 +47,43 @@ enum SpellDisableTypes
|
|||||||
SPELL_DISABLE_MAP = 0x10,
|
SPELL_DISABLE_MAP = 0x10,
|
||||||
SPELL_DISABLE_AREA = 0x20,
|
SPELL_DISABLE_AREA = 0x20,
|
||||||
SPELL_DISABLE_LOS = 0x40,
|
SPELL_DISABLE_LOS = 0x40,
|
||||||
MAX_SPELL_DISABLE_TYPE = ( SPELL_DISABLE_PLAYER | SPELL_DISABLE_CREATURE | SPELL_DISABLE_PET |
|
MAX_SPELL_DISABLE_TYPE = (SPELL_DISABLE_PLAYER | SPELL_DISABLE_CREATURE | SPELL_DISABLE_PET |
|
||||||
SPELL_DISABLE_DEPRECATED_SPELL | SPELL_DISABLE_MAP | SPELL_DISABLE_AREA |
|
SPELL_DISABLE_DEPRECATED_SPELL | SPELL_DISABLE_MAP | SPELL_DISABLE_AREA |
|
||||||
SPELL_DISABLE_LOS)
|
SPELL_DISABLE_LOS)
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace DisableMgr
|
struct DisableData
|
||||||
{
|
{
|
||||||
void LoadDisables();
|
uint8 flags;
|
||||||
bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0);
|
std::set<uint32> params[2]; // params0, params1
|
||||||
void CheckQuestDisables();
|
};
|
||||||
bool IsVMAPDisabledFor(uint32 entry, uint8 flags);
|
|
||||||
bool IsPathfindingEnabled(const Map* map);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //ACORE_DISABLEMGR_H
|
class DisableMgr
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
DisableMgr();
|
||||||
|
~DisableMgr();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static DisableMgr* instance();
|
||||||
|
|
||||||
|
void LoadDisables();
|
||||||
|
void AddDisable(DisableType type, uint32 entry, uint8 flags, std::string param0, std::string param1);
|
||||||
|
bool HandleDisableType(DisableType type, uint32 entry, uint8 flags, std::string const& params_0, std::string const& params_1, DisableData& data);
|
||||||
|
static bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0);
|
||||||
|
void CheckQuestDisables();
|
||||||
|
static bool IsVMAPDisabledFor(uint32 entry, uint8 flags);
|
||||||
|
static bool IsPathfindingEnabled(Map const* map);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// single disables here with optional data
|
||||||
|
typedef std::map<uint32, DisableData> DisableTypeMap;
|
||||||
|
// global disable map by source
|
||||||
|
typedef std::map<DisableType, DisableTypeMap> DisableMap;
|
||||||
|
|
||||||
|
static DisableMap m_DisableMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define sDisableMgr DisableMgr::instance()
|
||||||
|
|
||||||
|
#endif //_DISABLEMGR_H
|
||||||
|
|||||||
@@ -410,9 +410,9 @@ namespace lfg
|
|||||||
uint32 lockData = 0;
|
uint32 lockData = 0;
|
||||||
if (dungeon->expansion > expansion || (onlySeasonalBosses && !dungeon->seasonal))
|
if (dungeon->expansion > expansion || (onlySeasonalBosses && !dungeon->seasonal))
|
||||||
lockData = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION;
|
lockData = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION;
|
||||||
else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player))
|
else if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player))
|
||||||
lockData = LFG_LOCKSTATUS_RAID_LOCKED;
|
lockData = LFG_LOCKSTATUS_RAID_LOCKED;
|
||||||
else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_LFG_MAP, dungeon->map, player))
|
else if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_LFG_MAP, dungeon->map, player))
|
||||||
lockData = LFG_LOCKSTATUS_RAID_LOCKED;
|
lockData = LFG_LOCKSTATUS_RAID_LOCKED;
|
||||||
else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && (!mapEntry || !mapEntry->IsRaid()) && sInstanceSaveMgr->PlayerIsPermBoundToInstance(player->GetGUID(), dungeon->map, Difficulty(dungeon->difficulty)))
|
else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && (!mapEntry || !mapEntry->IsRaid()) && sInstanceSaveMgr->PlayerIsPermBoundToInstance(player->GetGUID(), dungeon->map, Difficulty(dungeon->difficulty)))
|
||||||
lockData = LFG_LOCKSTATUS_RAID_LOCKED;
|
lockData = LFG_LOCKSTATUS_RAID_LOCKED;
|
||||||
|
|||||||
@@ -286,7 +286,9 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(),
|
|||||||
m_ProhibitSchoolTime[i] = 0;
|
m_ProhibitSchoolTime[i] = 0;
|
||||||
|
|
||||||
m_CreatureSpellCooldowns.clear();
|
m_CreatureSpellCooldowns.clear();
|
||||||
DisableReputationGain = false;
|
|
||||||
|
DisableReputationReward = false;
|
||||||
|
DisableLootReward = false;
|
||||||
|
|
||||||
m_SightDistance = sWorld->getFloatConfig(CONFIG_SIGHT_MONSTER);
|
m_SightDistance = sWorld->getFloatConfig(CONFIG_SIGHT_MONSTER);
|
||||||
m_CombatDistance = 0.0f;
|
m_CombatDistance = 0.0f;
|
||||||
|
|||||||
@@ -359,8 +359,10 @@ public:
|
|||||||
|
|
||||||
Unit* SelectVictim();
|
Unit* SelectVictim();
|
||||||
|
|
||||||
void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; }
|
void SetReputationRewardDisabled(bool disable) { DisableReputationReward = disable; }
|
||||||
[[nodiscard]] bool IsReputationGainDisabled() const { return DisableReputationGain; }
|
[[nodiscard]] bool IsReputationRewardDisabled() const { return DisableReputationReward; }
|
||||||
|
void SetLootRewardDisabled(bool disable) { DisableLootReward = disable; }
|
||||||
|
[[nodiscard]] bool IsLootRewardDisabled() const { return DisableLootReward; }
|
||||||
[[nodiscard]] bool IsDamageEnoughForLootingAndReward() const;
|
[[nodiscard]] bool IsDamageEnoughForLootingAndReward() const;
|
||||||
void LowerPlayerDamageReq(uint32 unDamage, bool damagedByPlayer = true);
|
void LowerPlayerDamageReq(uint32 unDamage, bool damagedByPlayer = true);
|
||||||
void ResetPlayerDamageReq();
|
void ResetPlayerDamageReq();
|
||||||
@@ -478,7 +480,8 @@ protected:
|
|||||||
Position m_homePosition;
|
Position m_homePosition;
|
||||||
Position m_transportHomePosition;
|
Position m_transportHomePosition;
|
||||||
|
|
||||||
bool DisableReputationGain;
|
bool DisableReputationReward;
|
||||||
|
bool DisableLootReward;
|
||||||
|
|
||||||
CreatureTemplate const* m_creatureInfo; // in difficulty mode > 0 can different from sObjectMgr->GetCreatureTemplate(GetEntry())
|
CreatureTemplate const* m_creatureInfo; // in difficulty mode > 0 can different from sObjectMgr->GetCreatureTemplate(GetEntry())
|
||||||
CreatureData const* m_creatureData;
|
CreatureData const* m_creatureData;
|
||||||
|
|||||||
@@ -2594,7 +2594,7 @@ void GameObject::EnableCollision(bool enable)
|
|||||||
GetMap()->InsertGameObjectModel(*m_model);*/
|
GetMap()->InsertGameObjectModel(*m_model);*/
|
||||||
|
|
||||||
uint32 phaseMask = 0;
|
uint32 phaseMask = 0;
|
||||||
if (enable && !DisableMgr::IsDisabledFor(DISABLE_TYPE_GO_LOS, GetEntry(), nullptr))
|
if (enable && !sDisableMgr->IsDisabledFor(DISABLE_TYPE_GO_LOS, GetEntry(), nullptr))
|
||||||
phaseMask = GetPhaseMask();
|
phaseMask = GetPhaseMask();
|
||||||
|
|
||||||
m_model->enable(phaseMask);
|
m_model->enable(phaseMask);
|
||||||
|
|||||||
@@ -1340,7 +1340,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, mapid, this))
|
if (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && sDisableMgr->IsDisabledFor(DISABLE_TYPE_MAP, mapid, this))
|
||||||
{
|
{
|
||||||
LOG_ERROR("entities.player", "Player ({}, name: {}) tried to enter a forbidden map {}", GetGUID().ToString(), GetName(), mapid);
|
LOG_ERROR("entities.player", "Player ({}, name: {}) tried to enter a forbidden map {}", GetGUID().ToString(), GetName(), mapid);
|
||||||
SendTransferAborted(mapid, TRANSFER_ABORT_MAP_NOT_ALLOWED);
|
SendTransferAborted(mapid, TRANSFER_ABORT_MAP_NOT_ALLOWED);
|
||||||
@@ -4493,6 +4493,9 @@ void Player::BuildPlayerRepop()
|
|||||||
|
|
||||||
void Player::ResurrectPlayer(float restore_percent, bool applySickness)
|
void Player::ResurrectPlayer(float restore_percent, bool applySickness)
|
||||||
{
|
{
|
||||||
|
if (!sScriptMgr->CanPlayerResurrect(this))
|
||||||
|
return;
|
||||||
|
|
||||||
WorldPacket data(SMSG_DEATH_RELEASE_LOC, 4 * 4); // remove spirit healer position
|
WorldPacket data(SMSG_DEATH_RELEASE_LOC, 4 * 4); // remove spirit healer position
|
||||||
data << uint32(-1);
|
data << uint32(-1);
|
||||||
data << float(0);
|
data << float(0);
|
||||||
@@ -5993,7 +5996,7 @@ void Player::RewardReputation(Unit* victim)
|
|||||||
if (!victim || victim->IsPlayer())
|
if (!victim || victim->IsPlayer())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (victim->ToCreature()->IsReputationGainDisabled())
|
if (victim->ToCreature()->IsReputationRewardDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ReputationOnKillEntry const* Rep = sObjectMgr->GetReputationOnKilEntry(victim->ToCreature()->GetCreatureTemplate()->Entry);
|
ReputationOnKillEntry const* Rep = sObjectMgr->GetReputationOnKilEntry(victim->ToCreature()->GetCreatureTemplate()->Entry);
|
||||||
@@ -8858,6 +8861,8 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sWorldState->FillInitialWorldStates(data, zoneid, areaid);
|
||||||
|
|
||||||
uint16 length = (data.wpos() - countPos) / 8;
|
uint16 length = (data.wpos() - countPos) / 8;
|
||||||
data.put<uint16>(countPos, length);
|
data.put<uint16>(countPos, length);
|
||||||
|
|
||||||
|
|||||||
@@ -1728,6 +1728,10 @@ public:
|
|||||||
[[nodiscard]] bool HasTalent(uint32 spell_id, uint8 spec) const;
|
[[nodiscard]] bool HasTalent(uint32 spell_id, uint8 spec) const;
|
||||||
|
|
||||||
[[nodiscard]] uint32 CalculateTalentsPoints() const;
|
[[nodiscard]] uint32 CalculateTalentsPoints() const;
|
||||||
|
void SetBonusTalentCount(uint32 count) { m_extraBonusTalentCount = count; };
|
||||||
|
uint32 GetBonusTalentCount() { return m_extraBonusTalentCount; };
|
||||||
|
void AddBonusTalent(uint32 count) { m_extraBonusTalentCount += count; };
|
||||||
|
void RemoveBonusTalent(uint32 count) { m_extraBonusTalentCount -= count; };
|
||||||
|
|
||||||
// Dual Spec
|
// Dual Spec
|
||||||
void UpdateSpecCount(uint8 count);
|
void UpdateSpecCount(uint8 count);
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ Quest const* Player::GetNextQuest(ObjectGuid guid, Quest const* quest)
|
|||||||
|
|
||||||
bool Player::CanSeeStartQuest(Quest const* quest)
|
bool Player::CanSeeStartQuest(Quest const* quest)
|
||||||
{
|
{
|
||||||
if (!DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this) && SatisfyQuestClass(quest, false) && SatisfyQuestRace(quest, false) &&
|
if (!sDisableMgr->IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this) && SatisfyQuestClass(quest, false) && SatisfyQuestRace(quest, false) &&
|
||||||
SatisfyQuestSkill(quest, false) && SatisfyQuestExclusiveGroup(quest, false) && SatisfyQuestReputation(quest, false) &&
|
SatisfyQuestSkill(quest, false) && SatisfyQuestExclusiveGroup(quest, false) && SatisfyQuestReputation(quest, false) &&
|
||||||
SatisfyQuestPreviousQuest(quest, false) && SatisfyQuestNextChain(quest, false) &&
|
SatisfyQuestPreviousQuest(quest, false) && SatisfyQuestNextChain(quest, false) &&
|
||||||
SatisfyQuestPrevChain(quest, false) && SatisfyQuestDay(quest, false) && SatisfyQuestWeek(quest, false) &&
|
SatisfyQuestPrevChain(quest, false) && SatisfyQuestDay(quest, false) && SatisfyQuestWeek(quest, false) &&
|
||||||
@@ -250,7 +250,7 @@ bool Player::CanSeeStartQuest(Quest const* quest)
|
|||||||
|
|
||||||
bool Player::CanTakeQuest(Quest const* quest, bool msg)
|
bool Player::CanTakeQuest(Quest const* quest, bool msg)
|
||||||
{
|
{
|
||||||
return !DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this)
|
return !sDisableMgr->IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this)
|
||||||
&& SatisfyQuestStatus(quest, msg) && SatisfyQuestExclusiveGroup(quest, msg)
|
&& SatisfyQuestStatus(quest, msg) && SatisfyQuestExclusiveGroup(quest, msg)
|
||||||
&& SatisfyQuestClass(quest, msg) && SatisfyQuestRace(quest, msg) && SatisfyQuestLevel(quest, msg)
|
&& SatisfyQuestClass(quest, msg) && SatisfyQuestRace(quest, msg) && SatisfyQuestLevel(quest, msg)
|
||||||
&& SatisfyQuestSkill(quest, msg) && SatisfyQuestReputation(quest, msg)
|
&& SatisfyQuestSkill(quest, msg) && SatisfyQuestReputation(quest, msg)
|
||||||
|
|||||||
@@ -5619,7 +5619,7 @@ bool Player::LoadFromDB(ObjectGuid playerGuid, CharacterDatabaseQueryHolder cons
|
|||||||
|
|
||||||
bool Player::isAllowedToLoot(Creature const* creature)
|
bool Player::isAllowedToLoot(Creature const* creature)
|
||||||
{
|
{
|
||||||
if (!creature->isDead() || !creature->IsDamageEnoughForLootingAndReward())
|
if (!creature->isDead() || !creature->IsDamageEnoughForLootingAndReward() || creature->IsLootRewardDisabled())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (HasPendingBind())
|
if (HasPendingBind())
|
||||||
@@ -6722,7 +6722,7 @@ bool Player::Satisfy(DungeonProgressionRequirements const* ar, uint32 target_map
|
|||||||
LevelMax = ar->levelMax;
|
LevelMax = ar->levelMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, target_map, this))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_MAP, target_map, this))
|
||||||
{
|
{
|
||||||
GetSession()->SendAreaTriggerMessage("{}", GetSession()->GetAcoreString(LANG_INSTANCE_CLOSED));
|
GetSession()->SendAreaTriggerMessage("{}", GetSession()->GetAcoreString(LANG_INSTANCE_CLOSED));
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -555,7 +555,7 @@ void Player::UpdateLocalChannels(uint32 newZone)
|
|||||||
|
|
||||||
if (channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY)
|
if (channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY)
|
||||||
currentNameExt = sObjectMgr->GetAcoreStringForDBCLocale(
|
currentNameExt = sObjectMgr->GetAcoreStringForDBCLocale(
|
||||||
LANG_CHANNEL_CITY);
|
LANG_CHANNEL_CITY).c_str();
|
||||||
else
|
else
|
||||||
currentNameExt = current_zone_name.c_str();
|
currentNameExt = current_zone_name.c_str();
|
||||||
|
|
||||||
|
|||||||
@@ -17798,7 +17798,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
|
|||||||
bool isRewardAllowed = true;
|
bool isRewardAllowed = true;
|
||||||
if (creature)
|
if (creature)
|
||||||
{
|
{
|
||||||
isRewardAllowed = creature->IsDamageEnoughForLootingAndReward();
|
isRewardAllowed = (creature->IsDamageEnoughForLootingAndReward() && !creature->IsLootRewardDisabled());
|
||||||
if (!isRewardAllowed)
|
if (!isRewardAllowed)
|
||||||
creature->SetLootRecipient(nullptr);
|
creature->SetLootRecipient(nullptr);
|
||||||
}
|
}
|
||||||
@@ -20444,7 +20444,7 @@ void Unit::PetSpellFail(SpellInfo const* spellInfo, Unit* target, uint32 result)
|
|||||||
if (!charmInfo || !IsCreature())
|
if (!charmInfo || !IsCreature())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((DisableMgr::IsPathfindingEnabled(GetMap()) || result != SPELL_FAILED_LINE_OF_SIGHT) && target)
|
if ((sDisableMgr->IsPathfindingEnabled(GetMap()) || result != SPELL_FAILED_LINE_OF_SIGHT) && target)
|
||||||
{
|
{
|
||||||
if ((result == SPELL_FAILED_LINE_OF_SIGHT || result == SPELL_FAILED_OUT_OF_RANGE) || !ToCreature()->HasReactState(REACT_PASSIVE))
|
if ((result == SPELL_FAILED_LINE_OF_SIGHT || result == SPELL_FAILED_OUT_OF_RANGE) || !ToCreature()->HasReactState(REACT_PASSIVE))
|
||||||
if (Unit* owner = GetOwner())
|
if (Unit* owner = GetOwner())
|
||||||
@@ -21355,6 +21355,12 @@ bool Unit::CanRestoreMana(SpellInfo const* spellInfo) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unit::SetShapeshiftForm(ShapeshiftForm form)
|
||||||
|
{
|
||||||
|
SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
|
||||||
|
sScriptMgr->OnUnitSetShapeshiftForm((Unit*)this, form);
|
||||||
|
}
|
||||||
|
|
||||||
bool Unit::IsInDisallowedMountForm() const
|
bool Unit::IsInDisallowedMountForm() const
|
||||||
{
|
{
|
||||||
if (SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(getTransForm()))
|
if (SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(getTransForm()))
|
||||||
|
|||||||
@@ -1869,10 +1869,7 @@ public:
|
|||||||
|
|
||||||
// ShapeShitForm (use by druid)
|
// ShapeShitForm (use by druid)
|
||||||
[[nodiscard]] ShapeshiftForm GetShapeshiftForm() const { return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_2, 3)); }
|
[[nodiscard]] ShapeshiftForm GetShapeshiftForm() const { return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_2, 3)); }
|
||||||
void SetShapeshiftForm(ShapeshiftForm form)
|
void SetShapeshiftForm(ShapeshiftForm form);
|
||||||
{
|
|
||||||
SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
|
|
||||||
}
|
|
||||||
bool IsAttackSpeedOverridenShapeShift() const;
|
bool IsAttackSpeedOverridenShapeShift() const;
|
||||||
[[nodiscard]] bool IsInFeralForm() const
|
[[nodiscard]] bool IsInFeralForm() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ void GameEventMgr::StartInternalEvent(uint16 event_id)
|
|||||||
|
|
||||||
bool GameEventMgr::StartEvent(uint16 event_id, bool overwrite)
|
bool GameEventMgr::StartEvent(uint16 event_id, bool overwrite)
|
||||||
{
|
{
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_GAME_EVENT, event_id, nullptr) && !overwrite)
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_GAME_EVENT, event_id, nullptr) && !overwrite)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3072,7 +3072,7 @@ void ObjectMgr::LoadItemTemplates()
|
|||||||
else if (itemTemplate.Spells[1].SpellId != -1)
|
else if (itemTemplate.Spells[1].SpellId != -1)
|
||||||
{
|
{
|
||||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[1].SpellId);
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[1].SpellId);
|
||||||
if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[1].SpellId, nullptr))
|
if (!spellInfo && !sDisableMgr->IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[1].SpellId, nullptr))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Item (Entry: {}) has wrong (not existing) spell in spellid_{} ({})", entry, 1 + 1, itemTemplate.Spells[1].SpellId);
|
LOG_ERROR("sql.sql", "Item (Entry: {}) has wrong (not existing) spell in spellid_{} ({})", entry, 1 + 1, itemTemplate.Spells[1].SpellId);
|
||||||
itemTemplate.Spells[0].SpellId = 0;
|
itemTemplate.Spells[0].SpellId = 0;
|
||||||
@@ -3120,7 +3120,7 @@ void ObjectMgr::LoadItemTemplates()
|
|||||||
if (itemTemplate.Spells[j].SpellId && itemTemplate.Spells[j].SpellId != -1)
|
if (itemTemplate.Spells[j].SpellId && itemTemplate.Spells[j].SpellId != -1)
|
||||||
{
|
{
|
||||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[j].SpellId);
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[j].SpellId);
|
||||||
if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[j].SpellId, nullptr))
|
if (!spellInfo && !sDisableMgr->IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[j].SpellId, nullptr))
|
||||||
{
|
{
|
||||||
LOG_ERROR("sql.sql", "Item (Entry: {}) has wrong (not existing) spell in spellid_{} ({})", entry, j + 1, itemTemplate.Spells[j].SpellId);
|
LOG_ERROR("sql.sql", "Item (Entry: {}) has wrong (not existing) spell in spellid_{} ({})", entry, j + 1, itemTemplate.Spells[j].SpellId);
|
||||||
itemTemplate.Spells[j].SpellId = 0;
|
itemTemplate.Spells[j].SpellId = 0;
|
||||||
@@ -4616,7 +4616,7 @@ void ObjectMgr::LoadQuests()
|
|||||||
for (QuestMap::iterator iter = _questTemplates.begin(); iter != _questTemplates.end(); ++iter)
|
for (QuestMap::iterator iter = _questTemplates.begin(); iter != _questTemplates.end(); ++iter)
|
||||||
{
|
{
|
||||||
// skip post-loading checks for disabled quests
|
// skip post-loading checks for disabled quests
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, iter->first, nullptr))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_QUEST, iter->first, nullptr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Quest* qinfo = iter->second;
|
Quest* qinfo = iter->second;
|
||||||
@@ -8770,19 +8770,20 @@ bool ObjectMgr::LoadAcoreStrings()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* ObjectMgr::GetAcoreString(uint32 entry, LocaleConstant locale) const
|
std::string ObjectMgr::GetAcoreString(uint32 entry, LocaleConstant locale) const
|
||||||
{
|
{
|
||||||
if (AcoreString const* ts = GetAcoreString(entry))
|
AcoreString const* as = GetAcoreString(entry);
|
||||||
|
if (as && !as->Content.empty())
|
||||||
{
|
{
|
||||||
if (ts->Content.size() > std::size_t(locale) && !ts->Content[locale].empty())
|
if (as->Content.size() > std::size_t(locale) && !as->Content[locale].empty())
|
||||||
return ts->Content[locale].c_str();
|
return as->Content[locale];
|
||||||
|
|
||||||
return ts->Content[DEFAULT_LOCALE].c_str();
|
return as->Content[DEFAULT_LOCALE];
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR("sql.sql", "Acore string entry {} not found in DB.", entry);
|
std::string msg = Acore::StringFormat("No entry for acore_string ({}) in DB.", entry);
|
||||||
|
LOG_ERROR("sql.sql", msg);
|
||||||
return "<error>";
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectMgr::LoadFishingBaseSkillLevel()
|
void ObjectMgr::LoadFishingBaseSkillLevel()
|
||||||
|
|||||||
@@ -1315,8 +1315,8 @@ public:
|
|||||||
|
|
||||||
return &itr->second;
|
return &itr->second;
|
||||||
}
|
}
|
||||||
[[nodiscard]] char const* GetAcoreString(uint32 entry, LocaleConstant locale) const;
|
[[nodiscard]] std::string GetAcoreString(uint32 entry, LocaleConstant locale) const;
|
||||||
[[nodiscard]] char const* GetAcoreStringForDBCLocale(uint32 entry) const { return GetAcoreString(entry, DBCLocaleIndex); }
|
[[nodiscard]] std::string GetAcoreStringForDBCLocale(uint32 entry) const { return GetAcoreString(entry, DBCLocaleIndex); }
|
||||||
[[nodiscard]] LocaleConstant GetDBCLocaleIndex() const { return DBCLocaleIndex; }
|
[[nodiscard]] LocaleConstant GetDBCLocaleIndex() const { return DBCLocaleIndex; }
|
||||||
void SetDBCLocaleIndex(LocaleConstant locale) { DBCLocaleIndex = locale; }
|
void SetDBCLocaleIndex(LocaleConstant locale) { DBCLocaleIndex = locale; }
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// chosen battleground type is disabled
|
// chosen battleground type is disabled
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, nullptr))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, nullptr))
|
||||||
{
|
{
|
||||||
ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED);
|
ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED);
|
||||||
return;
|
return;
|
||||||
@@ -721,7 +721,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// arenas disabled
|
// arenas disabled
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, nullptr))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, nullptr))
|
||||||
{
|
{
|
||||||
ChatHandler(this).PSendSysMessage(LANG_ARENA_DISABLED);
|
ChatHandler(this).PSendSysMessage(LANG_ARENA_DISABLED);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/)
|
|||||||
{
|
{
|
||||||
HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(entry);
|
HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(entry);
|
||||||
|
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_GAME_EVENT, sGameEventMgr->GetHolidayEventId(holiday->Id), nullptr))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_GAME_EVENT, sGameEventMgr->GetHolidayEventId(holiday->Id), nullptr))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Not let attack through obstructions
|
// Not let attack through obstructions
|
||||||
bool checkLos = !DisableMgr::IsPathfindingEnabled(pet->GetMap()) ||
|
bool checkLos = !sDisableMgr->IsPathfindingEnabled(pet->GetMap()) ||
|
||||||
(TargetUnit->IsCreature() && (TargetUnit->ToCreature()->isWorldBoss() || TargetUnit->ToCreature()->IsDungeonBoss()));
|
(TargetUnit->IsCreature() && (TargetUnit->ToCreature()->isWorldBoss() || TargetUnit->ToCreature()->IsDungeonBoss()));
|
||||||
|
|
||||||
if (checkLos && !pet->IsWithinLOSInMap(TargetUnit))
|
if (checkLos && !pet->IsWithinLOSInMap(TargetUnit))
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ bool LootItem::AllowedForPlayer(Player const* player, ObjectGuid source) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_LOOT, itemid, nullptr))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_LOOT, itemid, nullptr))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy)
|
|||||||
|
|
||||||
void Map::LoadMMap(int gx, int gy)
|
void Map::LoadMMap(int gx, int gy)
|
||||||
{
|
{
|
||||||
if (!DisableMgr::IsPathfindingEnabled(this)) // pussywizard
|
if (!sDisableMgr->IsPathfindingEnabled(this)) // pussywizard
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(GetId(), gx, gy);
|
int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(GetId(), gx, gy);
|
||||||
|
|||||||
@@ -1169,8 +1169,7 @@ enum AcoreStrings
|
|||||||
|
|
||||||
LANG_GM_SILENCE = 6616, // "Silence is ON for %s" - Spell 1852
|
LANG_GM_SILENCE = 6616, // "Silence is ON for %s" - Spell 1852
|
||||||
|
|
||||||
// Used for .string command
|
// Free strings 6617-7522
|
||||||
LANG_NO_ACORE_STRING_FOUND = 6617,
|
|
||||||
|
|
||||||
LANG_WORLD_CLOSED = 7523,
|
LANG_WORLD_CLOSED = 7523,
|
||||||
LANG_WORLD_OPENED = 7524,
|
LANG_WORLD_OPENED = 7524,
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ void HomeMovementGenerator<Creature>::_setTargetLocation(Creature* owner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
owner->UpdateAllowedPositionZ(x, y, z);
|
owner->UpdateAllowedPositionZ(x, y, z);
|
||||||
init.MoveTo(x, y, z, DisableMgr::IsPathfindingEnabled(owner->FindMap()), true);
|
init.MoveTo(x, y, z, sDisableMgr->IsPathfindingEnabled(owner->FindMap()), true);
|
||||||
init.SetWalk(_walk);
|
init.SetWalk(_walk);
|
||||||
init.Launch();
|
init.Launch();
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ PathGenerator::PathGenerator(WorldObject const* owner) :
|
|||||||
memset(_pathPolyRefs, 0, sizeof(_pathPolyRefs));
|
memset(_pathPolyRefs, 0, sizeof(_pathPolyRefs));
|
||||||
|
|
||||||
uint32 mapId = _source->GetMapId();
|
uint32 mapId = _source->GetMapId();
|
||||||
//if (DisableMgr::IsPathfindingEnabled(_sourceUnit->FindMap()))
|
//if (sDisableMgr->IsPathfindingEnabled(_sourceUnit->FindMap()))
|
||||||
{
|
{
|
||||||
MMAP::MMapMgr* mmap = MMAP::MMapFactory::createOrGetMMapMgr();
|
MMAP::MMapMgr* mmap = MMAP::MMapFactory::createOrGetMMapMgr();
|
||||||
_navMesh = mmap->GetNavMesh(mapId);
|
_navMesh = mmap->GetNavMesh(mapId);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ void OutdoorPvPMgr::InitOutdoorPvP()
|
|||||||
{
|
{
|
||||||
typeId = fields[0].Get<uint8>();
|
typeId = fields[0].Get<uint8>();
|
||||||
|
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_OUTDOORPVP, typeId, nullptr))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_OUTDOORPVP, typeId, nullptr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (typeId >= MAX_OUTDOORPVP_TYPES)
|
if (typeId >= MAX_OUTDOORPVP_TYPES)
|
||||||
|
|||||||
@@ -903,6 +903,11 @@ bool ScriptMgr::AnticheatCheckMovementInfo(Player* player, MovementInfo const& m
|
|||||||
CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ANTICHEAT_CHECK_MOVEMENT_INFO, !script->AnticheatCheckMovementInfo(player, movementInfo, mover, jump));
|
CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ANTICHEAT_CHECK_MOVEMENT_INFO, !script->AnticheatCheckMovementInfo(player, movementInfo, mover, jump));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ScriptMgr::CanPlayerResurrect(Player* player)
|
||||||
|
{
|
||||||
|
CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_RESURRECT, !script->CanPlayerResurrect(player));
|
||||||
|
}
|
||||||
|
|
||||||
PlayerScript::PlayerScript(const char* name, std::vector<uint16> enabledHooks)
|
PlayerScript::PlayerScript(const char* name, std::vector<uint16> enabledHooks)
|
||||||
: ScriptObject(name, PLAYERHOOK_END)
|
: ScriptObject(name, PLAYERHOOK_END)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -204,6 +204,7 @@ enum PlayerHook
|
|||||||
PLAYERHOOK_CAN_SEND_ERROR_ALREADY_LOOTED,
|
PLAYERHOOK_CAN_SEND_ERROR_ALREADY_LOOTED,
|
||||||
PLAYERHOOK_ON_AFTER_CREATURE_LOOT,
|
PLAYERHOOK_ON_AFTER_CREATURE_LOOT,
|
||||||
PLAYERHOOK_ON_AFTER_CREATURE_LOOT_MONEY,
|
PLAYERHOOK_ON_AFTER_CREATURE_LOOT_MONEY,
|
||||||
|
PLAYERHOOK_CAN_RESURRECT,
|
||||||
PLAYERHOOK_END
|
PLAYERHOOK_END
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -766,6 +767,15 @@ public:
|
|||||||
* @param player Contains information about the Player
|
* @param player Contains information about the Player
|
||||||
*/
|
*/
|
||||||
virtual void OnAfterCreatureLootMoney(Player* /*player*/) { }
|
virtual void OnAfterCreatureLootMoney(Player* /*player*/) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This hook is called, to avoid player resurrect
|
||||||
|
*
|
||||||
|
* @param player Contains information about the Player
|
||||||
|
*
|
||||||
|
* @return true if player is authorized to resurect
|
||||||
|
*/
|
||||||
|
virtual bool CanPlayerResurrect(Player* /*player*/) { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -148,6 +148,11 @@ void ScriptMgr::OnUnitDeath(Unit* unit, Unit* killer)
|
|||||||
CALL_ENABLED_HOOKS(UnitScript, UNITHOOK_ON_UNIT_DEATH, script->OnUnitDeath(unit, killer));
|
CALL_ENABLED_HOOKS(UnitScript, UNITHOOK_ON_UNIT_DEATH, script->OnUnitDeath(unit, killer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptMgr::OnUnitSetShapeshiftForm(Unit* unit, uint8 form)
|
||||||
|
{
|
||||||
|
CALL_ENABLED_HOOKS(UnitScript, UNITHOOK_ON_UNIT_SET_SHAPESHIFT_FORM, script->OnUnitSetShapeshiftForm(unit, form));
|
||||||
|
}
|
||||||
|
|
||||||
UnitScript::UnitScript(const char* name, bool addToScripts, std::vector<uint16> enabledHooks)
|
UnitScript::UnitScript(const char* name, bool addToScripts, std::vector<uint16> enabledHooks)
|
||||||
: ScriptObject(name, UNITHOOK_END)
|
: ScriptObject(name, UNITHOOK_END)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ enum UnitHook
|
|||||||
UNITHOOK_ON_UNIT_ENTER_EVADE_MODE,
|
UNITHOOK_ON_UNIT_ENTER_EVADE_MODE,
|
||||||
UNITHOOK_ON_UNIT_ENTER_COMBAT,
|
UNITHOOK_ON_UNIT_ENTER_COMBAT,
|
||||||
UNITHOOK_ON_UNIT_DEATH,
|
UNITHOOK_ON_UNIT_DEATH,
|
||||||
|
UNITHOOK_ON_UNIT_SET_SHAPESHIFT_FORM,
|
||||||
UNITHOOK_END
|
UNITHOOK_END
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,6 +116,7 @@ public:
|
|||||||
virtual void OnUnitEnterEvadeMode(Unit* /*unit*/, uint8 /*evadeReason*/) { }
|
virtual void OnUnitEnterEvadeMode(Unit* /*unit*/, uint8 /*evadeReason*/) { }
|
||||||
virtual void OnUnitEnterCombat(Unit* /*unit*/, Unit* /*victim*/) { }
|
virtual void OnUnitEnterCombat(Unit* /*unit*/, Unit* /*victim*/) { }
|
||||||
virtual void OnUnitDeath(Unit* /*unit*/, Unit* /*killer*/) { }
|
virtual void OnUnitDeath(Unit* /*unit*/, Unit* /*killer*/) { }
|
||||||
|
virtual void OnUnitSetShapeshiftForm(Unit* /*unit*/, uint8 /*form*/) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -492,6 +492,7 @@ public: /* PlayerScript */
|
|||||||
void OnAfterCreatureLoot(Player* player);
|
void OnAfterCreatureLoot(Player* player);
|
||||||
void OnAfterCreatureLootMoney(Player* player);
|
void OnAfterCreatureLootMoney(Player* player);
|
||||||
bool OnCanPlayerFlyInZone(Player* player, uint32 mapId, uint32 zoneId, SpellInfo const* bySpell);
|
bool OnCanPlayerFlyInZone(Player* player, uint32 mapId, uint32 zoneId, SpellInfo const* bySpell);
|
||||||
|
bool CanPlayerResurrect(Player* player);
|
||||||
|
|
||||||
// Anti cheat
|
// Anti cheat
|
||||||
void AnticheatSetCanFlybyServer(Player* player, bool apply);
|
void AnticheatSetCanFlybyServer(Player* player, bool apply);
|
||||||
@@ -589,6 +590,7 @@ public: /* UnitScript */
|
|||||||
void OnUnitEnterEvadeMode(Unit* unit, uint8 why);
|
void OnUnitEnterEvadeMode(Unit* unit, uint8 why);
|
||||||
void OnUnitEnterCombat(Unit* unit, Unit* victim);
|
void OnUnitEnterCombat(Unit* unit, Unit* victim);
|
||||||
void OnUnitDeath(Unit* unit, Unit* killer);
|
void OnUnitDeath(Unit* unit, Unit* killer);
|
||||||
|
void OnUnitSetShapeshiftForm(Unit* unit, uint8 form);
|
||||||
|
|
||||||
public: /* MovementHandlerScript */
|
public: /* MovementHandlerScript */
|
||||||
void OnPlayerMove(Player* player, MovementInfo movementInfo, uint32 opcode);
|
void OnPlayerMove(Player* player, MovementInfo movementInfo, uint32 opcode);
|
||||||
|
|||||||
@@ -830,7 +830,7 @@ bool WorldSession::DisallowHyperlinksAndMaybeKick(std::string_view str)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* WorldSession::GetAcoreString(uint32 entry) const
|
std::string WorldSession::GetAcoreString(uint32 entry) const
|
||||||
{
|
{
|
||||||
return sObjectMgr->GetAcoreString(entry, GetSessionDbLocaleIndex());
|
return sObjectMgr->GetAcoreString(entry, GetSessionDbLocaleIndex());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ public:
|
|||||||
void SendAreaTriggerMessage(std::string_view str);
|
void SendAreaTriggerMessage(std::string_view str);
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void SendAreaTriggerMessage(char const* fmt, Args&&... args)
|
void SendAreaTriggerMessage(std::string fmt, Args&&... args)
|
||||||
{
|
{
|
||||||
if (!m_playerLoading)
|
if (!m_playerLoading)
|
||||||
SendAreaTriggerMessage(Acore::StringFormat(fmt, std::forward<Args>(args)...));
|
SendAreaTriggerMessage(Acore::StringFormat(fmt, std::forward<Args>(args)...));
|
||||||
@@ -528,9 +528,9 @@ public:
|
|||||||
time_t m_muteTime;
|
time_t m_muteTime;
|
||||||
|
|
||||||
// Locales
|
// Locales
|
||||||
LocaleConstant GetSessionDbcLocale() const { return /*_isBot? LOCALE_enUS : */m_sessionDbcLocale; }
|
LocaleConstant GetSessionDbcLocale() const { return m_sessionDbcLocale; }
|
||||||
LocaleConstant GetSessionDbLocaleIndex() const { return /*_isBot? LOCALE_enUS : */m_sessionDbLocaleIndex; }
|
LocaleConstant GetSessionDbLocaleIndex() const { return m_sessionDbLocaleIndex; }
|
||||||
char const* GetAcoreString(uint32 entry) const;
|
std::string GetAcoreString(uint32 entry) const;
|
||||||
std::string const* GetModuleString(std::string module, uint32 id) const;
|
std::string const* GetModuleString(std::string module, uint32 id) const;
|
||||||
|
|
||||||
uint32 GetLatency() const { return m_latency; }
|
uint32 GetLatency() const { return m_latency; }
|
||||||
|
|||||||
@@ -3530,7 +3530,7 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const
|
|||||||
_spellEvent = new SpellEvent(this);
|
_spellEvent = new SpellEvent(this);
|
||||||
m_caster->m_Events.AddEvent(_spellEvent, m_caster->m_Events.CalculateTime(1));
|
m_caster->m_Events.AddEvent(_spellEvent, m_caster->m_Events.CalculateTime(1));
|
||||||
|
|
||||||
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, m_caster))
|
if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, m_caster))
|
||||||
{
|
{
|
||||||
SendCastResult(SPELL_FAILED_SPELL_UNAVAILABLE);
|
SendCastResult(SPELL_FAILED_SPELL_UNAVAILABLE);
|
||||||
finish(false);
|
finish(false);
|
||||||
@@ -6247,7 +6247,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||||||
return SPELL_FAILED_BAD_TARGETS;
|
return SPELL_FAILED_BAD_TARGETS;
|
||||||
// Xinef: Pass only explicit unit target spells
|
// Xinef: Pass only explicit unit target spells
|
||||||
// pussywizard:
|
// pussywizard:
|
||||||
if (DisableMgr::IsPathfindingEnabled(m_caster->FindMap()) && m_spellInfo->NeedsExplicitUnitTarget())
|
if (sDisableMgr->IsPathfindingEnabled(m_caster->FindMap()) && m_spellInfo->NeedsExplicitUnitTarget())
|
||||||
{
|
{
|
||||||
Unit* target = m_targets.GetUnitTarget();
|
Unit* target = m_targets.GetUnitTarget();
|
||||||
if (!target)
|
if (!target)
|
||||||
@@ -7960,7 +7960,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
|
|||||||
|
|
||||||
// if spell is triggered, need to check for LOS disable on the aura triggering it and inherit that behaviour
|
// if spell is triggered, need to check for LOS disable on the aura triggering it and inherit that behaviour
|
||||||
if (IsTriggered() && m_triggeredByAuraSpell && (m_triggeredByAuraSpell.spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) ||
|
if (IsTriggered() && m_triggeredByAuraSpell && (m_triggeredByAuraSpell.spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) ||
|
||||||
DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_triggeredByAuraSpell.spellInfo->Id, nullptr, SPELL_DISABLE_LOS)))
|
sDisableMgr->IsDisabledFor(DISABLE_TYPE_SPELL, m_triggeredByAuraSpell.spellInfo->Id, nullptr, SPELL_DISABLE_LOS)))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1602,6 +1602,7 @@ void SpellMgr::LoadSpellInfoCorrections()
|
|||||||
ApplySpellFix({ 44335 }, [](SpellInfo* spellInfo)
|
ApplySpellFix({ 44335 }, [](SpellInfo* spellInfo)
|
||||||
{
|
{
|
||||||
spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CHANGE_MAP;
|
spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CHANGE_MAP;
|
||||||
|
spellInfo->AttributesCu |= SPELL_ATTR0_CU_SINGLE_AURA_STACK;
|
||||||
});
|
});
|
||||||
|
|
||||||
ApplySpellFix({
|
ApplySpellFix({
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ void Acore::CustomChatTextBuilder::operator()(WorldPacket& data, LocaleConstant
|
|||||||
|
|
||||||
void Acore::AcoreStringChatBuilder::operator()(WorldPacket& data, LocaleConstant locale) const
|
void Acore::AcoreStringChatBuilder::operator()(WorldPacket& data, LocaleConstant locale) const
|
||||||
{
|
{
|
||||||
char const* text = sObjectMgr->GetAcoreString(_textId, locale);
|
std::string strtext = sObjectMgr->GetAcoreString(_textId, locale);
|
||||||
|
char const* text = strtext.c_str();
|
||||||
|
|
||||||
if (_args)
|
if (_args)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -422,6 +422,7 @@ enum WorldIntConfigs
|
|||||||
CONFIG_DAILY_RBG_MIN_LEVEL_AP_REWARD,
|
CONFIG_DAILY_RBG_MIN_LEVEL_AP_REWARD,
|
||||||
CONFIG_AUCTIONHOUSE_WORKERTHREADS,
|
CONFIG_AUCTIONHOUSE_WORKERTHREADS,
|
||||||
CONFIG_SPELL_QUEUE_WINDOW,
|
CONFIG_SPELL_QUEUE_WINDOW,
|
||||||
|
CONFIG_SUNSREACH_COUNTER_MAX,
|
||||||
INT_CONFIG_VALUE_COUNT
|
INT_CONFIG_VALUE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -572,7 +573,7 @@ public:
|
|||||||
virtual void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0;
|
virtual void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0;
|
||||||
virtual void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0;
|
virtual void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0;
|
||||||
virtual bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0;
|
virtual bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0;
|
||||||
virtual void SendZoneText(uint32 zone, const char* text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0;
|
virtual void SendZoneText(uint32 zone, std::string text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0;
|
||||||
virtual void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr) = 0;
|
virtual void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr) = 0;
|
||||||
[[nodiscard]] virtual bool IsShuttingDown() const = 0;
|
[[nodiscard]] virtual bool IsShuttingDown() const = 0;
|
||||||
[[nodiscard]] virtual uint32 GetShutDownTimeLeft() const = 0;
|
[[nodiscard]] virtual uint32 GetShutDownTimeLeft() const = 0;
|
||||||
|
|||||||
@@ -1499,6 +1499,8 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
_bool_configs[CONFIG_SPELL_QUEUE_ENABLED] = sConfigMgr->GetOption<bool>("SpellQueue.Enabled", true);
|
_bool_configs[CONFIG_SPELL_QUEUE_ENABLED] = sConfigMgr->GetOption<bool>("SpellQueue.Enabled", true);
|
||||||
_int_configs[CONFIG_SPELL_QUEUE_WINDOW] = sConfigMgr->GetOption<uint32>("SpellQueue.Window", 400);
|
_int_configs[CONFIG_SPELL_QUEUE_WINDOW] = sConfigMgr->GetOption<uint32>("SpellQueue.Window", 400);
|
||||||
|
|
||||||
|
_int_configs[CONFIG_SUNSREACH_COUNTER_MAX] = sConfigMgr->GetOption<uint32>("Sunsreach.CounterMax", 10000);
|
||||||
|
|
||||||
// call ScriptMgr if we're reloading the configuration
|
// call ScriptMgr if we're reloading the configuration
|
||||||
sScriptMgr->OnAfterConfigLoad(reload);
|
sScriptMgr->OnAfterConfigLoad(reload);
|
||||||
}
|
}
|
||||||
@@ -1720,7 +1722,7 @@ void World::SetInitialWorldSettings()
|
|||||||
LoadRandomEnchantmentsTable();
|
LoadRandomEnchantmentsTable();
|
||||||
|
|
||||||
LOG_INFO("server.loading", "Loading Disables");
|
LOG_INFO("server.loading", "Loading Disables");
|
||||||
DisableMgr::LoadDisables(); // must be before loading quests and items
|
sDisableMgr->LoadDisables(); // must be before loading quests and items
|
||||||
|
|
||||||
LOG_INFO("server.loading", "Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts
|
LOG_INFO("server.loading", "Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts
|
||||||
sObjectMgr->LoadItemTemplates();
|
sObjectMgr->LoadItemTemplates();
|
||||||
@@ -1801,7 +1803,7 @@ void World::SetInitialWorldSettings()
|
|||||||
sObjectMgr->LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
|
sObjectMgr->LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
|
||||||
|
|
||||||
LOG_INFO("server.loading", "Checking Quest Disables");
|
LOG_INFO("server.loading", "Checking Quest Disables");
|
||||||
DisableMgr::CheckQuestDisables(); // must be after loading quests
|
sDisableMgr->CheckQuestDisables(); // must be after loading quests
|
||||||
|
|
||||||
LOG_INFO("server.loading", "Loading Quest POI");
|
LOG_INFO("server.loading", "Loading Quest POI");
|
||||||
sObjectMgr->LoadQuestPOI();
|
sObjectMgr->LoadQuestPOI();
|
||||||
@@ -2126,6 +2128,9 @@ void World::SetInitialWorldSettings()
|
|||||||
LOG_INFO("server.loading", " ");
|
LOG_INFO("server.loading", " ");
|
||||||
sGameEventMgr->StartArenaSeason();
|
sGameEventMgr->StartArenaSeason();
|
||||||
|
|
||||||
|
LOG_INFO("server.loading", "Loading WorldState...");
|
||||||
|
sWorldState->Load();
|
||||||
|
|
||||||
sTicketMgr->Initialize();
|
sTicketMgr->Initialize();
|
||||||
|
|
||||||
///- Initialize Battlegrounds
|
///- Initialize Battlegrounds
|
||||||
@@ -2571,7 +2576,8 @@ namespace Acore
|
|||||||
explicit WorldWorldTextBuilder(uint32 textId, va_list* args = nullptr) : i_textId(textId), i_args(args) {}
|
explicit WorldWorldTextBuilder(uint32 textId, va_list* args = nullptr) : i_textId(textId), i_args(args) {}
|
||||||
void operator()(WorldPacketList& data_list, LocaleConstant loc_idx)
|
void operator()(WorldPacketList& data_list, LocaleConstant loc_idx)
|
||||||
{
|
{
|
||||||
char const* text = sObjectMgr->GetAcoreString(i_textId, loc_idx);
|
std::string strtext = sObjectMgr->GetAcoreString(i_textId, loc_idx);
|
||||||
|
char const* text = strtext.c_str();
|
||||||
|
|
||||||
if (i_args)
|
if (i_args)
|
||||||
{
|
{
|
||||||
@@ -2630,10 +2636,10 @@ bool World::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Send a System Message to all players in the zone (except self if mentioned)
|
/// Send a System Message to all players in the zone (except self if mentioned)
|
||||||
void World::SendZoneText(uint32 zone, const char* text, WorldSession* self, TeamId teamId)
|
void World::SendZoneText(uint32 zone, std::string text, WorldSession* self, TeamId teamId)
|
||||||
{
|
{
|
||||||
WorldPacket data;
|
WorldPacket data;
|
||||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text);
|
ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text.c_str());
|
||||||
SendZoneMessage(zone, &data, self, teamId);
|
SendZoneMessage(zone, &data, self, teamId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ public:
|
|||||||
void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override;
|
void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override;
|
||||||
void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override;
|
void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override;
|
||||||
bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override;
|
bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override;
|
||||||
void SendZoneText(uint32 zone, const char* text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override;
|
void SendZoneText(uint32 zone, std::string text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override;
|
||||||
void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr) override;
|
void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr) override;
|
||||||
|
|
||||||
/// Are we in the middle of a shutdown?
|
/// Are we in the middle of a shutdown?
|
||||||
|
|||||||
@@ -15,9 +15,11 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "GameEventMgr.h"
|
||||||
#include "MapMgr.h"
|
#include "MapMgr.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "SharedDefines.h"
|
#include "SharedDefines.h"
|
||||||
|
#include "Weather.h"
|
||||||
#include "WorldState.h"
|
#include "WorldState.h"
|
||||||
|
|
||||||
WorldState* WorldState::instance()
|
WorldState* WorldState::instance()
|
||||||
@@ -37,6 +39,82 @@ WorldState::~WorldState()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldState::Load()
|
||||||
|
{
|
||||||
|
QueryResult result = CharacterDatabase.Query("SELECT Id, Data FROM world_state");
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Field* fields = result->Fetch();
|
||||||
|
uint32 id = fields[0].Get<uint32>();
|
||||||
|
std::string data = fields[1].Get<std::string>();
|
||||||
|
std::istringstream loadStream(data);
|
||||||
|
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case SAVE_ID_QUEL_DANAS:
|
||||||
|
{
|
||||||
|
if (data.size())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
loadStream >> m_sunsReachData.m_phase >> m_sunsReachData.m_subphaseMask;
|
||||||
|
for (uint32 i = 0; i < COUNTERS_MAX; ++i)
|
||||||
|
loadStream >> m_sunsReachData.m_sunsReachReclamationCounters[i];
|
||||||
|
loadStream >> m_sunsReachData.m_gate;
|
||||||
|
for (uint32 i = 0; i < COUNTERS_MAX_GATES; ++i)
|
||||||
|
loadStream >> m_sunsReachData.m_gateCounters[i];
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
LOG_ERROR("scripts", "WorldState::Load: Exception reading SunsReach data {}", e.what());
|
||||||
|
m_sunsReachData.m_phase = 0;
|
||||||
|
m_sunsReachData.m_subphaseMask = 0;
|
||||||
|
memset(m_sunsReachData.m_sunsReachReclamationCounters, 0, sizeof(m_sunsReachData.m_sunsReachReclamationCounters));
|
||||||
|
m_sunsReachData.m_gate = SUNWELL_ALL_GATES_CLOSED;
|
||||||
|
memset(m_sunsReachData.m_gateCounters, 0, sizeof(m_sunsReachData.m_gateCounters));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_sunsReachData.m_phase = 0;
|
||||||
|
m_sunsReachData.m_subphaseMask = 0;
|
||||||
|
memset(m_sunsReachData.m_sunsReachReclamationCounters, 0, sizeof(m_sunsReachData.m_sunsReachReclamationCounters));
|
||||||
|
m_sunsReachData.m_gate = SUNWELL_ALL_GATES_CLOSED;
|
||||||
|
memset(m_sunsReachData.m_gateCounters, 0, sizeof(m_sunsReachData.m_gateCounters));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (result->NextRow());
|
||||||
|
}
|
||||||
|
StartSunsReachPhase(true);
|
||||||
|
StartSunwellGatePhase();
|
||||||
|
HandleSunsReachSubPhaseTransition(m_sunsReachData.m_subphaseMask, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::Save(WorldStateSaveIds saveId)
|
||||||
|
{
|
||||||
|
switch (saveId)
|
||||||
|
{
|
||||||
|
case SAVE_ID_QUEL_DANAS:
|
||||||
|
{
|
||||||
|
std::string expansionData = m_sunsReachData.GetData();
|
||||||
|
SaveHelper(expansionData, SAVE_ID_QUEL_DANAS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::SaveHelper(std::string& stringToSave, WorldStateSaveIds saveId)
|
||||||
|
{
|
||||||
|
CharacterDatabase.Execute("DELETE FROM world_state WHERE Id='{}'", saveId);
|
||||||
|
CharacterDatabase.Execute("INSERT INTO world_state(Id,Data) VALUES('{}','{}')", saveId, stringToSave.data());
|
||||||
|
}
|
||||||
|
|
||||||
bool WorldState::IsConditionFulfilled(WorldStateCondition conditionId, WorldStateConditionState state) const
|
bool WorldState::IsConditionFulfilled(WorldStateCondition conditionId, WorldStateConditionState state) const
|
||||||
{
|
{
|
||||||
switch (conditionId)
|
switch (conditionId)
|
||||||
@@ -140,6 +218,16 @@ void WorldState::HandlePlayerEnterZone(Player* player, WorldStateZoneId zoneId)
|
|||||||
else if (_isMagtheridonHeadSpawnedHorde && player->GetTeamId() == TEAM_HORDE)
|
else if (_isMagtheridonHeadSpawnedHorde && player->GetTeamId() == TEAM_HORDE)
|
||||||
player->CastSpell(player, SPELL_NAZGRELS_FAVOR, true);
|
player->CastSpell(player, SPELL_NAZGRELS_FAVOR, true);
|
||||||
break;
|
break;
|
||||||
|
case ZONEID_ISLE_OF_QUEL_DANAS:
|
||||||
|
case ZONEID_MAGISTERS_TERRACE:
|
||||||
|
case ZONEID_SUNWELL_PLATEAU:
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(m_sunsReachData.m_sunsReachReclamationMutex);
|
||||||
|
m_sunsReachData.m_sunsReachReclamationPlayers.push_back(player->GetGUID());
|
||||||
|
if (m_sunsReachData.m_subphaseMask == SUBPHASE_ALL)
|
||||||
|
player->CastSpell(player, SPELL_KIRU_SONG_OF_VICTORY, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -167,6 +255,17 @@ void WorldState::HandlePlayerLeaveZone(Player* player, WorldStateZoneId zoneId)
|
|||||||
else if (player->GetTeamId() == TEAM_HORDE)
|
else if (player->GetTeamId() == TEAM_HORDE)
|
||||||
player->RemoveAurasDueToSpell(SPELL_NAZGRELS_FAVOR);
|
player->RemoveAurasDueToSpell(SPELL_NAZGRELS_FAVOR);
|
||||||
break;
|
break;
|
||||||
|
case ZONEID_ISLE_OF_QUEL_DANAS:
|
||||||
|
case ZONEID_MAGISTERS_TERRACE:
|
||||||
|
case ZONEID_SUNWELL_PLATEAU:
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(m_sunsReachData.m_sunsReachReclamationMutex);
|
||||||
|
player->RemoveAurasDueToSpell(SPELL_KIRU_SONG_OF_VICTORY);
|
||||||
|
auto position = std::find(m_sunsReachData.m_sunsReachReclamationPlayers.begin(), m_sunsReachData.m_sunsReachReclamationPlayers.end(), player->GetGUID());
|
||||||
|
if (position != m_sunsReachData.m_sunsReachReclamationPlayers.end())
|
||||||
|
m_sunsReachData.m_sunsReachReclamationPlayers.erase(position);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -291,3 +390,699 @@ void WorldState::DispelAdalsSongOfBattle()
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldState::SendWorldstateUpdate(std::mutex& mutex, GuidVector const& guids, uint32 value, uint32 worldStateId)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
for (ObjectGuid const& guid : guids)
|
||||||
|
if (Player* player = ObjectAccessor::FindPlayer(guid))
|
||||||
|
player->SendUpdateWorldState(worldStateId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WorldStateSunsReachQuests
|
||||||
|
{
|
||||||
|
QUEST_ERRATIC_BEHAVIOR = 11524,
|
||||||
|
QUEST_SANCTUM_WARDS = 11496,
|
||||||
|
QUEST_BATTLE_FOR_THE_SUNS_REACH_ARMORY = 11538,
|
||||||
|
QUEST_DISTRACTION_AT_THE_DEAD_SCAR = 11532,
|
||||||
|
QUEST_INTERCEPTING_THE_MANA_CELLS = 11513,
|
||||||
|
QUEST_INTERCEPT_THE_REINFORCEMENTS = 11542,
|
||||||
|
QUEST_TAKING_THE_HARBOR = 11539,
|
||||||
|
QUEST_MAKING_READY = 11535,
|
||||||
|
QUEST_DISCOVERING_YOUR_ROOTS = 11520,
|
||||||
|
QUEST_A_CHARITABLE_DONATION = 11545,
|
||||||
|
QUEST_A_MAGNANIMOUS_BENEFACTOR = 11549,
|
||||||
|
COUNTER_MAX_VAL_REQ = 10000,
|
||||||
|
};
|
||||||
|
|
||||||
|
void WorldState::AddSunsReachProgress(uint32 questId)
|
||||||
|
{
|
||||||
|
uint32 counter = 0;
|
||||||
|
int32 otherCounter = -1;
|
||||||
|
int32 worldState = 0;
|
||||||
|
uint32 subPhaseMask = 0;
|
||||||
|
uint32 addedValue = 1;
|
||||||
|
switch (questId)
|
||||||
|
{
|
||||||
|
case QUEST_ERRATIC_BEHAVIOR:
|
||||||
|
counter = COUNTER_ERRATIC_BEHAVIOR;
|
||||||
|
otherCounter = COUNTER_SANCTUM_WARDS;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_SANCTUM;
|
||||||
|
break;
|
||||||
|
case QUEST_SANCTUM_WARDS:
|
||||||
|
counter = COUNTER_SANCTUM_WARDS;
|
||||||
|
otherCounter = COUNTER_SANCTUM_WARDS;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_SANCTUM;
|
||||||
|
break;
|
||||||
|
case QUEST_BATTLE_FOR_THE_SUNS_REACH_ARMORY:
|
||||||
|
counter = COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY;
|
||||||
|
otherCounter = COUNTER_DISTRACTION_AT_THE_DEAD_SCAR;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_ARMORY;
|
||||||
|
break;
|
||||||
|
case QUEST_DISTRACTION_AT_THE_DEAD_SCAR:
|
||||||
|
counter = COUNTER_DISTRACTION_AT_THE_DEAD_SCAR;
|
||||||
|
otherCounter = COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_ARMORY;
|
||||||
|
break;
|
||||||
|
case QUEST_INTERCEPTING_THE_MANA_CELLS:
|
||||||
|
counter = COUNTER_INTERCEPTING_THE_MANA_CELLS;
|
||||||
|
subPhaseMask = SUBPHASE_PORTAL;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_PORTAL;
|
||||||
|
break;
|
||||||
|
case QUEST_INTERCEPT_THE_REINFORCEMENTS:
|
||||||
|
counter = COUNTER_INTERCEPT_THE_REINFORCEMENTS;
|
||||||
|
otherCounter = COUNTER_TAKING_THE_HARBOR;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_HARBOR;
|
||||||
|
break;
|
||||||
|
case QUEST_TAKING_THE_HARBOR:
|
||||||
|
counter = COUNTER_TAKING_THE_HARBOR;
|
||||||
|
otherCounter = COUNTER_INTERCEPT_THE_REINFORCEMENTS;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_HARBOR;
|
||||||
|
break;
|
||||||
|
case QUEST_MAKING_READY:
|
||||||
|
counter = COUNTER_MAKING_READY;
|
||||||
|
subPhaseMask = SUBPHASE_ANVIL;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_ANVIL;
|
||||||
|
break;
|
||||||
|
case QUEST_DISCOVERING_YOUR_ROOTS:
|
||||||
|
counter = COUNTER_DISCOVERING_YOUR_ROOTS;
|
||||||
|
subPhaseMask = SUBPHASE_ALCHEMY_LAB;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_ALCHEMY_LAB;
|
||||||
|
break;
|
||||||
|
case QUEST_A_CHARITABLE_DONATION:
|
||||||
|
counter = COUNTER_A_CHARITABLE_DONATION;
|
||||||
|
subPhaseMask = SUBPHASE_MONUMENT;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_MONUMENT;
|
||||||
|
break;
|
||||||
|
case QUEST_A_MAGNANIMOUS_BENEFACTOR:
|
||||||
|
counter = COUNTER_A_CHARITABLE_DONATION;
|
||||||
|
subPhaseMask = SUBPHASE_MONUMENT;
|
||||||
|
worldState = WORLD_STATE_QUEL_DANAS_MONUMENT;
|
||||||
|
addedValue = 150;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 previousValue = 0;
|
||||||
|
uint32 newValue = 0;
|
||||||
|
|
||||||
|
if (!subPhaseMask)
|
||||||
|
previousValue = m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase);
|
||||||
|
else
|
||||||
|
previousValue = m_sunsReachData.GetSubPhasePercentage(subPhaseMask);
|
||||||
|
m_sunsReachData.m_sunsReachReclamationCounters[counter] += addedValue;
|
||||||
|
if (!subPhaseMask)
|
||||||
|
newValue = m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase);
|
||||||
|
else
|
||||||
|
newValue = m_sunsReachData.GetSubPhasePercentage(subPhaseMask);
|
||||||
|
if (previousValue != newValue)
|
||||||
|
SendWorldstateUpdate(m_sunsReachData.m_sunsReachReclamationMutex, m_sunsReachData.m_sunsReachReclamationPlayers, newValue, worldState);
|
||||||
|
|
||||||
|
bool save = true;
|
||||||
|
uint32 counterValue = m_sunsReachData.m_sunsReachReclamationCounters[counter];
|
||||||
|
uint32 modifier = 1;
|
||||||
|
if (otherCounter != -1)
|
||||||
|
{
|
||||||
|
modifier = 2;
|
||||||
|
counterValue += m_sunsReachData.m_sunsReachReclamationCounters[otherCounter];
|
||||||
|
}
|
||||||
|
if (counterValue >= sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX) * modifier)
|
||||||
|
{
|
||||||
|
save = false;
|
||||||
|
switch (questId)
|
||||||
|
{
|
||||||
|
case QUEST_ERRATIC_BEHAVIOR:
|
||||||
|
case QUEST_SANCTUM_WARDS:
|
||||||
|
{
|
||||||
|
if (m_sunsReachData.m_phase == SUNS_REACH_PHASE_1_STAGING_AREA)
|
||||||
|
HandleSunsReachPhaseTransition(SUNS_REACH_PHASE_2_SANCTUM);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUEST_BATTLE_FOR_THE_SUNS_REACH_ARMORY:
|
||||||
|
case QUEST_DISTRACTION_AT_THE_DEAD_SCAR:
|
||||||
|
{
|
||||||
|
if (m_sunsReachData.m_phase == SUNS_REACH_PHASE_2_SANCTUM)
|
||||||
|
HandleSunsReachPhaseTransition(SUNS_REACH_PHASE_3_ARMORY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUEST_INTERCEPTING_THE_MANA_CELLS:
|
||||||
|
{
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_PORTAL) == 0)
|
||||||
|
HandleSunsReachSubPhaseTransition(SUBPHASE_PORTAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUEST_INTERCEPT_THE_REINFORCEMENTS:
|
||||||
|
case QUEST_TAKING_THE_HARBOR:
|
||||||
|
{
|
||||||
|
if (m_sunsReachData.m_phase == SUNS_REACH_PHASE_3_ARMORY)
|
||||||
|
HandleSunsReachPhaseTransition(SUNS_REACH_PHASE_4_HARBOR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUEST_MAKING_READY:
|
||||||
|
{
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ANVIL) == 0)
|
||||||
|
HandleSunsReachSubPhaseTransition(SUBPHASE_ANVIL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUEST_DISCOVERING_YOUR_ROOTS:
|
||||||
|
{
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALCHEMY_LAB) == 0)
|
||||||
|
HandleSunsReachSubPhaseTransition(SUBPHASE_ALCHEMY_LAB);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUEST_A_CHARITABLE_DONATION:
|
||||||
|
case QUEST_A_MAGNANIMOUS_BENEFACTOR:
|
||||||
|
{
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_MONUMENT) == 0)
|
||||||
|
HandleSunsReachSubPhaseTransition(SUBPHASE_MONUMENT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (save)
|
||||||
|
Save(SAVE_ID_QUEL_DANAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::HandleSunsReachPhaseTransition(uint32 newPhase)
|
||||||
|
{
|
||||||
|
if (newPhase < m_sunsReachData.m_phase)
|
||||||
|
{
|
||||||
|
while (newPhase != m_sunsReachData.m_phase)
|
||||||
|
{
|
||||||
|
StopSunsReachPhase(newPhase > m_sunsReachData.m_phase);
|
||||||
|
--m_sunsReachData.m_phase;
|
||||||
|
}
|
||||||
|
StartSunsReachPhase();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StopSunsReachPhase(newPhase > m_sunsReachData.m_phase);
|
||||||
|
bool moreThanOne = newPhase > m_sunsReachData.m_phase + 1; // custom command case
|
||||||
|
m_sunsReachData.m_phase = newPhase;
|
||||||
|
StartSunsReachPhase(moreThanOne);
|
||||||
|
}
|
||||||
|
switch (m_sunsReachData.m_phase)
|
||||||
|
{
|
||||||
|
case SUNS_REACH_PHASE_2_SANCTUM: if ((m_sunsReachData.m_subphaseMask & SUBPHASE_PORTAL) == 0) sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_NO_PORTAL); break;
|
||||||
|
case SUNS_REACH_PHASE_3_ARMORY: if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ANVIL) == 0) sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_NO_ANVIL); break;
|
||||||
|
case SUNS_REACH_PHASE_4_HARBOR:
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALCHEMY_LAB) == 0) sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_NO_MONUMENT);
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_MONUMENT) == 0) sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_NO_ALCHEMY_LAB);
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
SendWorldstateUpdate(m_sunsReachData.m_sunsReachReclamationMutex, m_sunsReachData.m_sunsReachReclamationPlayers, m_sunsReachData.m_phase, WORLD_STATE_QUEL_DANAS_MUSIC);
|
||||||
|
Save(SAVE_ID_QUEL_DANAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::HandleSunsReachSubPhaseTransition(int32 subPhaseMask, bool initial)
|
||||||
|
{
|
||||||
|
bool start = true;
|
||||||
|
if (subPhaseMask < 0)
|
||||||
|
{
|
||||||
|
start = false;
|
||||||
|
subPhaseMask = -subPhaseMask;
|
||||||
|
}
|
||||||
|
bool all = false;
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
m_sunsReachData.m_subphaseMask |= subPhaseMask;
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALL) == SUBPHASE_ALL)
|
||||||
|
all = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALL) == SUBPHASE_ALL)
|
||||||
|
all = true;
|
||||||
|
m_sunsReachData.m_subphaseMask &= ~subPhaseMask;
|
||||||
|
}
|
||||||
|
if (initial)
|
||||||
|
{
|
||||||
|
if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_2_SANCTUM)
|
||||||
|
if ((subPhaseMask & SUBPHASE_PORTAL) == 0)
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_NO_PORTAL);
|
||||||
|
if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_3_ARMORY)
|
||||||
|
if ((subPhaseMask & SUBPHASE_ANVIL) == 0)
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_NO_ANVIL);
|
||||||
|
if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_4_HARBOR)
|
||||||
|
{
|
||||||
|
if ((subPhaseMask & SUBPHASE_ALCHEMY_LAB) == 0)
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_NO_ALCHEMY_LAB);
|
||||||
|
if ((subPhaseMask & SUBPHASE_MONUMENT) == 0)
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_NO_MONUMENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((subPhaseMask & SUBPHASE_PORTAL))
|
||||||
|
{
|
||||||
|
uint32 first = GAME_EVENT_QUEL_DANAS_PHASE_2_NO_PORTAL;
|
||||||
|
uint32 second = GAME_EVENT_QUEL_DANAS_PHASE_2_PORTAL;
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
sGameEventMgr->StopEvent(first);
|
||||||
|
sGameEventMgr->StartEvent(second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sGameEventMgr->StopEvent(second);
|
||||||
|
sGameEventMgr->StartEvent(first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((subPhaseMask & SUBPHASE_ANVIL))
|
||||||
|
{
|
||||||
|
uint32 first = GAME_EVENT_QUEL_DANAS_PHASE_3_NO_ANVIL;
|
||||||
|
uint32 second = GAME_EVENT_QUEL_DANAS_PHASE_3_ANVIL;
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
sGameEventMgr->StopEvent(first);
|
||||||
|
sGameEventMgr->StartEvent(second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sGameEventMgr->StopEvent(second);
|
||||||
|
sGameEventMgr->StartEvent(first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((subPhaseMask & SUBPHASE_ALCHEMY_LAB))
|
||||||
|
{
|
||||||
|
uint32 first = GAME_EVENT_QUEL_DANAS_PHASE_4_NO_ALCHEMY_LAB;
|
||||||
|
uint32 second = GAME_EVENT_QUEL_DANAS_PHASE_4_ALCHEMY_LAB;
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
sGameEventMgr->StopEvent(first);
|
||||||
|
sGameEventMgr->StartEvent(second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sGameEventMgr->StopEvent(second);
|
||||||
|
sGameEventMgr->StartEvent(first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((subPhaseMask & SUBPHASE_MONUMENT))
|
||||||
|
{
|
||||||
|
uint32 first = GAME_EVENT_QUEL_DANAS_PHASE_4_NO_MONUMENT;
|
||||||
|
uint32 second = GAME_EVENT_QUEL_DANAS_PHASE_4_MONUMENT;
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
sGameEventMgr->StopEvent(first);
|
||||||
|
sGameEventMgr->StartEvent(second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sGameEventMgr->StopEvent(second);
|
||||||
|
sGameEventMgr->StartEvent(first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (all)
|
||||||
|
{
|
||||||
|
if (start)
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_KIRU);
|
||||||
|
else
|
||||||
|
sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_KIRU);
|
||||||
|
|
||||||
|
if (!initial)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(m_sunsReachData.m_sunsReachReclamationMutex);
|
||||||
|
for (ObjectGuid& guid : m_sunsReachData.m_sunsReachReclamationPlayers)
|
||||||
|
if (Player* player = ObjectAccessor::FindPlayer(guid))
|
||||||
|
{
|
||||||
|
if (start)
|
||||||
|
player->CastSpell(player, SPELL_KIRU_SONG_OF_VICTORY, true);
|
||||||
|
else
|
||||||
|
player->RemoveAurasDueToSpell(SPELL_KIRU_SONG_OF_VICTORY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!initial)
|
||||||
|
Save(SAVE_ID_QUEL_DANAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::HandleSunwellGateTransition(uint32 newGate)
|
||||||
|
{
|
||||||
|
if (newGate < m_sunsReachData.m_gate)
|
||||||
|
{
|
||||||
|
while (newGate != m_sunsReachData.m_gate)
|
||||||
|
{
|
||||||
|
StopSunwellGatePhase();
|
||||||
|
--m_sunsReachData.m_gate;
|
||||||
|
}
|
||||||
|
StartSunwellGatePhase();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StopSunwellGatePhase();
|
||||||
|
m_sunsReachData.m_gate = newGate;
|
||||||
|
StartSunwellGatePhase();
|
||||||
|
}
|
||||||
|
int32 worldState = 0;
|
||||||
|
switch (newGate)
|
||||||
|
{
|
||||||
|
case SUNWELL_AGAMATH_GATE1_OPEN: worldState = WORLD_STATE_AGAMATH_THE_FIRST_GATE_HEALTH; break;
|
||||||
|
case SUNWELL_ROHENDOR_GATE2_OPEN: worldState = WORLD_STATE_ROHENDOR_THE_SECOND_GATE_HEALTH; break;
|
||||||
|
case SUNWELL_ARCHONISUS_GATE3_OPEN: worldState = WORLD_STATE_ARCHONISUS_THE_FINAL_GATE_HEALTH; break;
|
||||||
|
}
|
||||||
|
if (worldState)
|
||||||
|
SendWorldstateUpdate(m_sunsReachData.m_sunsReachReclamationMutex, m_sunsReachData.m_sunsReachReclamationPlayers, m_sunsReachData.m_gate, worldState);
|
||||||
|
|
||||||
|
Save(SAVE_ID_QUEL_DANAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::SetSunsReachCounter(SunsReachCounters index, uint32 value)
|
||||||
|
{
|
||||||
|
m_sunsReachData.m_sunsReachReclamationCounters[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::StopSunsReachPhase(bool forward)
|
||||||
|
{
|
||||||
|
switch (m_sunsReachData.m_phase)
|
||||||
|
{
|
||||||
|
case SUNS_REACH_PHASE_1_STAGING_AREA: sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_1); break;
|
||||||
|
case SUNS_REACH_PHASE_2_SANCTUM: sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_ONLY); if (!forward) sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT); break;
|
||||||
|
case SUNS_REACH_PHASE_3_ARMORY: sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_ONLY); if (!forward) sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_PERMANENT); break;
|
||||||
|
case SUNS_REACH_PHASE_4_HARBOR: sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_4); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::StartSunsReachPhase(bool initial)
|
||||||
|
{
|
||||||
|
switch (m_sunsReachData.m_phase)
|
||||||
|
{
|
||||||
|
case SUNS_REACH_PHASE_1_STAGING_AREA:
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_1);
|
||||||
|
if (Map* map = sMapMgr->FindBaseNonInstanceMap(530))
|
||||||
|
map->SetZoneWeather(ZONEID_ISLE_OF_QUEL_DANAS, WEATHER_STATE_MEDIUM_RAIN, 0.75f);
|
||||||
|
break;
|
||||||
|
case SUNS_REACH_PHASE_2_SANCTUM:
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_ONLY);
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT);
|
||||||
|
if (Map* map = sMapMgr->FindBaseNonInstanceMap(530))
|
||||||
|
map->SetZoneWeather(ZONEID_ISLE_OF_QUEL_DANAS, WEATHER_STATE_LIGHT_RAIN, 0.5f);
|
||||||
|
break;
|
||||||
|
case SUNS_REACH_PHASE_3_ARMORY:
|
||||||
|
if (initial)
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT);
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_ONLY); sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_PERMANENT);
|
||||||
|
// TODO: Should be id 2 0.25f?
|
||||||
|
if (Map* map = sMapMgr->FindBaseNonInstanceMap(530))
|
||||||
|
map->SetZoneWeather(ZONEID_ISLE_OF_QUEL_DANAS, WEATHER_STATE_LIGHT_RAIN, 0.25f);
|
||||||
|
break;
|
||||||
|
case SUNS_REACH_PHASE_4_HARBOR:
|
||||||
|
if (initial)
|
||||||
|
{
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT);
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_PERMANENT);
|
||||||
|
}
|
||||||
|
sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4);
|
||||||
|
if (Map* map = sMapMgr->FindBaseNonInstanceMap(530))
|
||||||
|
map->SetZoneWeather(ZONEID_ISLE_OF_QUEL_DANAS, WEATHER_STATE_FINE, 0.0f);
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string WorldState::GetSunsReachPrintout()
|
||||||
|
{
|
||||||
|
auto formatPhase = [this]() -> std::string {
|
||||||
|
std::string name;
|
||||||
|
switch (m_sunsReachData.m_phase)
|
||||||
|
{
|
||||||
|
case SUNS_REACH_PHASE_1_STAGING_AREA: name = "Phase 1: Staging Area"; break;
|
||||||
|
case SUNS_REACH_PHASE_2_SANCTUM: name = "Phase 2: Sanctum"; break;
|
||||||
|
case SUNS_REACH_PHASE_3_ARMORY: name = "Phase 3: Armory"; break;
|
||||||
|
case SUNS_REACH_PHASE_4_HARBOR: name = "Phase 4: Harbor"; break;
|
||||||
|
default: name = "Unknown"; break;
|
||||||
|
}
|
||||||
|
return "Phase: " + std::to_string(m_sunsReachData.m_phase) + " (" + name + ") " + std::to_string(m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase)) + "%\n";
|
||||||
|
};
|
||||||
|
|
||||||
|
auto formatSubPhase = [this](uint32 subPhase) -> std::string {
|
||||||
|
std::string name;
|
||||||
|
switch (subPhase)
|
||||||
|
{
|
||||||
|
case SUBPHASE_PORTAL: name = "Portal"; break;
|
||||||
|
case SUBPHASE_ANVIL: name = "Anvil"; break;
|
||||||
|
case SUBPHASE_ALCHEMY_LAB: name = "Alchemy Lab"; break;
|
||||||
|
case SUBPHASE_MONUMENT: name = "Monument"; break;
|
||||||
|
default: name = "Unknown"; break;
|
||||||
|
}
|
||||||
|
return name + ": " + (m_sunsReachData.m_subphaseMask & subPhase ? "100%" : std::to_string(m_sunsReachData.GetSubPhasePercentage(subPhase)) + "%");
|
||||||
|
};
|
||||||
|
|
||||||
|
auto formatCounter = [](uint32 counter, uint32 value) -> std::string {
|
||||||
|
switch (counter)
|
||||||
|
{
|
||||||
|
case COUNTER_ERRATIC_BEHAVIOR:
|
||||||
|
return "Erratic Behavior: " + std::to_string(value) + " (counts towards Phase 2: Sanctum)";
|
||||||
|
case COUNTER_SANCTUM_WARDS:
|
||||||
|
return "Sanctum Wards: " + std::to_string(value) + " (counts towards Phase 2: Sanctum)";
|
||||||
|
case COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY:
|
||||||
|
return "Battle for the Sun's Reach Armory: " + std::to_string(value) + " (counts towards Phase 3: Armory)";
|
||||||
|
case COUNTER_DISTRACTION_AT_THE_DEAD_SCAR:
|
||||||
|
return "Distraction at the Dead Scar: " + std::to_string(value) + " (counts towards Phase 3: Armory)";
|
||||||
|
case COUNTER_INTERCEPTING_THE_MANA_CELLS:
|
||||||
|
return "Intercepting the Mana Cells: " + std::to_string(value) + " (counts towards Subphase: Portal)";
|
||||||
|
case COUNTER_INTERCEPT_THE_REINFORCEMENTS:
|
||||||
|
return "Intercept the Reinforcements: " + std::to_string(value) + " (counts towards Phase 4: Harbor)";
|
||||||
|
case COUNTER_TAKING_THE_HARBOR:
|
||||||
|
return "Taking the Harbor: " + std::to_string(value) + " (counts towards Phase 4: Harbor)";
|
||||||
|
case COUNTER_MAKING_READY:
|
||||||
|
return "Making Ready: " + std::to_string(value) + " (counts towards Subphase: Anvil)";
|
||||||
|
case COUNTER_DISCOVERING_YOUR_ROOTS:
|
||||||
|
return "Discovering Your Roots: " + std::to_string(value) + " (counts towards Subphase: Alchemy Lab)";
|
||||||
|
case COUNTER_A_CHARITABLE_DONATION:
|
||||||
|
return "A Charitable Donation: " + std::to_string(value) + " (counts towards Subphase: Monument)";
|
||||||
|
default:
|
||||||
|
return "Unknown: " + std::to_string(value) + " (Unknown goal)";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string output = formatPhase();
|
||||||
|
output += "Subphase mask: " + std::to_string(m_sunsReachData.m_subphaseMask) + "\n";
|
||||||
|
for (uint32 i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
uint32 subPhaseMask = 1 << i;
|
||||||
|
output += " " + formatSubPhase(subPhaseMask) + "\n";
|
||||||
|
}
|
||||||
|
output += "Counters:\n";
|
||||||
|
output += " Sunsreach.CounterMax = " + std::to_string(sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX)) + "\n";
|
||||||
|
for (uint32 i = 0; i < COUNTERS_MAX; ++i)
|
||||||
|
output += " " + std::to_string(i) + ". " + formatCounter(i, m_sunsReachData.m_sunsReachReclamationCounters[i]) + "\n";
|
||||||
|
|
||||||
|
// Sunwell Gates
|
||||||
|
auto formatGatePhase = [](uint32 gate) -> std::string {
|
||||||
|
switch (gate)
|
||||||
|
{
|
||||||
|
case SUNWELL_ALL_GATES_CLOSED: return "All Gates Closed"; break;
|
||||||
|
case SUNWELL_AGAMATH_GATE1_OPEN: return "Gate 1 Agamath Open"; break;
|
||||||
|
case SUNWELL_ROHENDOR_GATE2_OPEN: return "Gate 2 Rohendar Open"; break;
|
||||||
|
case SUNWELL_ARCHONISUS_GATE3_OPEN: return "Gate 3 Archonisus Open"; break;
|
||||||
|
default: return "Unknown"; break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
output += "Sunwell Plateau Gate Phase " + std::to_string(m_sunsReachData.m_gate) + " (" + formatGatePhase(m_sunsReachData.m_gate) + ")" + ":\n";
|
||||||
|
output += " 0. Gate 1 (Agamath): " + std::string(m_sunsReachData.m_gate >= SUNWELL_AGAMATH_GATE1_OPEN ? "Open " : "Closed ") + std::to_string(m_sunsReachData.m_sunsReachReclamationCounters[COUNTER_AGAMATH_THE_FIRST_GATE]) + " (" + std::to_string(m_sunsReachData.GetSunwellGatePercentage(SUNWELL_ALL_GATES_CLOSED)) + "%)\n";
|
||||||
|
output += " 1. Gate 2 (Rohendor): " + std::string(m_sunsReachData.m_gate >= SUNWELL_ROHENDOR_GATE2_OPEN ? "Open " : "Closed ") + std::to_string(m_sunsReachData.m_sunsReachReclamationCounters[COUNTER_ROHENDOR_THE_SECOND_GATE]) + " (" + std::to_string(m_sunsReachData.GetSunwellGatePercentage(SUNWELL_AGAMATH_GATE1_OPEN)) + "%)\n";
|
||||||
|
output += " 2. Gate 3 (Archonisus): " + std::string(m_sunsReachData.m_gate >= SUNWELL_ARCHONISUS_GATE3_OPEN ? "Open " : "Closed ") + std::to_string(m_sunsReachData.m_sunsReachReclamationCounters[COUNTER_ARCHONISUS_THE_FINAL_GATE]) + " (" + std::to_string(m_sunsReachData.GetSunwellGatePercentage(SUNWELL_ROHENDOR_GATE2_OPEN)) + "%)\n";
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SunsReachReclamationData::GetData()
|
||||||
|
{
|
||||||
|
std::string output = std::to_string(m_phase) + " " + std::to_string(m_subphaseMask);
|
||||||
|
for (uint32 value : m_sunsReachReclamationCounters)
|
||||||
|
output += " " + std::to_string(value);
|
||||||
|
output += " " + std::to_string(m_gate);
|
||||||
|
for (uint32 value : m_gateCounters)
|
||||||
|
output += " " + std::to_string(value);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 SunsReachReclamationData::GetPhasePercentage(uint32 phase)
|
||||||
|
{
|
||||||
|
switch (phase)
|
||||||
|
{
|
||||||
|
case SUNS_REACH_PHASE_1_STAGING_AREA: return uint32((m_sunsReachReclamationCounters[COUNTER_ERRATIC_BEHAVIOR] + m_sunsReachReclamationCounters[COUNTER_SANCTUM_WARDS]) * 100 / (2 * sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX)));
|
||||||
|
case SUNS_REACH_PHASE_2_SANCTUM: return uint32((m_sunsReachReclamationCounters[COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY] + m_sunsReachReclamationCounters[COUNTER_DISTRACTION_AT_THE_DEAD_SCAR]) * 100 / (2 * sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX)));
|
||||||
|
case SUNS_REACH_PHASE_3_ARMORY: return uint32((m_sunsReachReclamationCounters[COUNTER_INTERCEPT_THE_REINFORCEMENTS] + m_sunsReachReclamationCounters[COUNTER_TAKING_THE_HARBOR]) * 100 / (2 * sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX)));
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 SunsReachReclamationData::GetSubPhasePercentage(uint32 subPhase)
|
||||||
|
{
|
||||||
|
switch (subPhase)
|
||||||
|
{
|
||||||
|
case SUBPHASE_PORTAL: return uint32(m_sunsReachReclamationCounters[COUNTER_INTERCEPTING_THE_MANA_CELLS] * 100 / sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX));
|
||||||
|
case SUBPHASE_ANVIL: return uint32(m_sunsReachReclamationCounters[COUNTER_MAKING_READY] * 100 / sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX));
|
||||||
|
case SUBPHASE_ALCHEMY_LAB: return uint32(m_sunsReachReclamationCounters[COUNTER_DISCOVERING_YOUR_ROOTS] * 100 / sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX));
|
||||||
|
case SUBPHASE_MONUMENT: return uint32(m_sunsReachReclamationCounters[COUNTER_A_CHARITABLE_DONATION] * 100 / sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX));
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WorldStateSunwellGateQuests
|
||||||
|
{
|
||||||
|
// Sunwell Plateau PTR progressive release gates
|
||||||
|
QUEST_AGAMATH_THE_FIRST_GATE = 11551,
|
||||||
|
QUEST_ROHENDOR_THE_SECOND_GATE = 11552,
|
||||||
|
QUEST_ARCHONISUS_THE_FINAL_GATE = 11553,
|
||||||
|
COUNTER_MAX_VAL_REQ_SWP_GATES = 80,
|
||||||
|
};
|
||||||
|
|
||||||
|
void WorldState::AddSunwellGateProgress(uint32 questId)
|
||||||
|
{
|
||||||
|
uint32 counter = 0;
|
||||||
|
int32 worldState = 0;
|
||||||
|
uint32 addedValue = 1;
|
||||||
|
switch (questId)
|
||||||
|
{
|
||||||
|
case QUEST_AGAMATH_THE_FIRST_GATE:
|
||||||
|
case QUEST_ROHENDOR_THE_SECOND_GATE:
|
||||||
|
case QUEST_ARCHONISUS_THE_FINAL_GATE:
|
||||||
|
break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
switch (m_sunsReachData.m_gate)
|
||||||
|
{
|
||||||
|
case SUNWELL_ALL_GATES_CLOSED: counter = COUNTER_AGAMATH_THE_FIRST_GATE; worldState = WORLD_STATE_AGAMATH_THE_FIRST_GATE_HEALTH; break;
|
||||||
|
case SUNWELL_AGAMATH_GATE1_OPEN: counter = COUNTER_ROHENDOR_THE_SECOND_GATE; worldState = WORLD_STATE_ROHENDOR_THE_SECOND_GATE_HEALTH; break;
|
||||||
|
case SUNWELL_ROHENDOR_GATE2_OPEN: counter = COUNTER_ARCHONISUS_THE_FINAL_GATE; worldState = WORLD_STATE_ARCHONISUS_THE_FINAL_GATE_HEALTH; break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
uint32 previousValue = m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate);
|
||||||
|
uint32 newValue = 0;
|
||||||
|
m_sunsReachData.m_gateCounters[counter] += addedValue;
|
||||||
|
newValue = m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate);
|
||||||
|
if (previousValue != newValue)
|
||||||
|
SendWorldstateUpdate(m_sunsReachData.m_sunsReachReclamationMutex, m_sunsReachData.m_sunsReachReclamationPlayers, newValue, worldState);
|
||||||
|
bool save = true;
|
||||||
|
if (m_sunsReachData.m_gateCounters[counter] >= COUNTER_MAX_VAL_REQ_SWP_GATES)
|
||||||
|
{
|
||||||
|
save = false;
|
||||||
|
switch (questId)
|
||||||
|
{
|
||||||
|
case QUEST_AGAMATH_THE_FIRST_GATE:
|
||||||
|
{
|
||||||
|
if (m_sunsReachData.m_gate == SUNWELL_ALL_GATES_CLOSED)
|
||||||
|
HandleSunwellGateTransition(SUNWELL_AGAMATH_GATE1_OPEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUEST_ROHENDOR_THE_SECOND_GATE:
|
||||||
|
{
|
||||||
|
if (m_sunsReachData.m_gate == SUNWELL_AGAMATH_GATE1_OPEN)
|
||||||
|
HandleSunwellGateTransition(SUNWELL_ROHENDOR_GATE2_OPEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUEST_ARCHONISUS_THE_FINAL_GATE:
|
||||||
|
{
|
||||||
|
if (m_sunsReachData.m_gate == SUNWELL_ROHENDOR_GATE2_OPEN)
|
||||||
|
HandleSunwellGateTransition(SUNWELL_ARCHONISUS_GATE3_OPEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (save)
|
||||||
|
Save(SAVE_ID_QUEL_DANAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::SetSunwellGateCounter(SunwellGateCounters index, uint32 value)
|
||||||
|
{
|
||||||
|
m_sunsReachData.m_gateCounters[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::StartSunwellGatePhase()
|
||||||
|
{
|
||||||
|
switch (m_sunsReachData.m_gate)
|
||||||
|
{
|
||||||
|
case SUNWELL_ALL_GATES_CLOSED: sGameEventMgr->StartEvent(GAME_EVENT_SWP_GATES_PHASE_0); break;
|
||||||
|
case SUNWELL_AGAMATH_GATE1_OPEN: sGameEventMgr->StartEvent(GAME_EVENT_SWP_GATES_PHASE_1); break;
|
||||||
|
case SUNWELL_ROHENDOR_GATE2_OPEN: sGameEventMgr->StartEvent(GAME_EVENT_SWP_GATES_PHASE_2); break;
|
||||||
|
case SUNWELL_ARCHONISUS_GATE3_OPEN: sGameEventMgr->StartEvent(GAME_EVENT_SWP_GATES_PHASE_3); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::StopSunwellGatePhase()
|
||||||
|
{
|
||||||
|
switch (m_sunsReachData.m_gate)
|
||||||
|
{
|
||||||
|
case SUNWELL_ALL_GATES_CLOSED: sGameEventMgr->StopEvent(GAME_EVENT_SWP_GATES_PHASE_0); break;
|
||||||
|
case SUNWELL_AGAMATH_GATE1_OPEN: sGameEventMgr->StopEvent(GAME_EVENT_SWP_GATES_PHASE_1); break;
|
||||||
|
case SUNWELL_ROHENDOR_GATE2_OPEN: sGameEventMgr->StopEvent(GAME_EVENT_SWP_GATES_PHASE_2); break;
|
||||||
|
case SUNWELL_ARCHONISUS_GATE3_OPEN: sGameEventMgr->StopEvent(GAME_EVENT_SWP_GATES_PHASE_3); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 SunsReachReclamationData::GetSunwellGatePercentage(uint32 gate)
|
||||||
|
{
|
||||||
|
int32 percentage = 0;
|
||||||
|
switch (gate)
|
||||||
|
{
|
||||||
|
case SUNWELL_ALL_GATES_CLOSED:
|
||||||
|
percentage = 100 - int32(m_gateCounters[COUNTER_AGAMATH_THE_FIRST_GATE] * 100 / COUNTER_MAX_VAL_REQ_SWP_GATES);
|
||||||
|
break;
|
||||||
|
case SUNWELL_AGAMATH_GATE1_OPEN:
|
||||||
|
percentage = 100 - int32(m_gateCounters[COUNTER_ROHENDOR_THE_SECOND_GATE] * 100 / COUNTER_MAX_VAL_REQ_SWP_GATES);
|
||||||
|
break;
|
||||||
|
case SUNWELL_ROHENDOR_GATE2_OPEN:
|
||||||
|
percentage = 100 - int32(m_gateCounters[COUNTER_ARCHONISUS_THE_FINAL_GATE] * 100 / COUNTER_MAX_VAL_REQ_SWP_GATES);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return percentage < 0 ? 0 : uint32(percentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldState::FillInitialWorldStates(ByteBuffer& data, uint32 zoneId, uint32 /*areaId*/)
|
||||||
|
{
|
||||||
|
switch (zoneId)
|
||||||
|
{
|
||||||
|
case ZONEID_ISLE_OF_QUEL_DANAS:
|
||||||
|
case ZONEID_MAGISTERS_TERRACE:
|
||||||
|
case ZONEID_SUNWELL_PLATEAU:
|
||||||
|
case ZONEID_SHATTRATH:
|
||||||
|
{
|
||||||
|
// Sunwell Reclamation
|
||||||
|
switch (m_sunsReachData.m_phase)
|
||||||
|
{
|
||||||
|
case SUNS_REACH_PHASE_1_STAGING_AREA:
|
||||||
|
data << WORLD_STATE_QUEL_DANAS_SANCTUM << m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase);
|
||||||
|
break;
|
||||||
|
case SUNS_REACH_PHASE_2_SANCTUM:
|
||||||
|
data << WORLD_STATE_QUEL_DANAS_ARMORY << m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase);
|
||||||
|
break;
|
||||||
|
case SUNS_REACH_PHASE_3_ARMORY:
|
||||||
|
data << WORLD_STATE_QUEL_DANAS_HARBOR << m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase);
|
||||||
|
break;
|
||||||
|
case SUNS_REACH_PHASE_4_HARBOR:
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALCHEMY_LAB) == 0)
|
||||||
|
data << WORLD_STATE_QUEL_DANAS_ALCHEMY_LAB << m_sunsReachData.GetSubPhasePercentage(SUBPHASE_ALCHEMY_LAB);
|
||||||
|
if ((m_sunsReachData.m_subphaseMask & SUBPHASE_MONUMENT) == 0)
|
||||||
|
data << WORLD_STATE_QUEL_DANAS_MONUMENT << m_sunsReachData.GetSubPhasePercentage(SUBPHASE_MONUMENT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_2_SANCTUM && (m_sunsReachData.m_subphaseMask & SUBPHASE_PORTAL) == 0)
|
||||||
|
data << WORLD_STATE_QUEL_DANAS_PORTAL << m_sunsReachData.GetSubPhasePercentage(SUBPHASE_PORTAL);
|
||||||
|
if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_3_ARMORY && (m_sunsReachData.m_subphaseMask & SUBPHASE_ANVIL) == 0)
|
||||||
|
data << WORLD_STATE_QUEL_DANAS_ANVIL << m_sunsReachData.GetSubPhasePercentage(SUBPHASE_ANVIL);
|
||||||
|
data << WORLD_STATE_QUEL_DANAS_MUSIC << m_sunsReachData.m_phase;
|
||||||
|
|
||||||
|
// Sunwell Gates
|
||||||
|
switch (m_sunsReachData.m_gate)
|
||||||
|
{
|
||||||
|
case SUNWELL_ALL_GATES_CLOSED:
|
||||||
|
data << WORLD_STATE_AGAMATH_THE_FIRST_GATE_HEALTH << m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate);
|
||||||
|
break;
|
||||||
|
case SUNWELL_AGAMATH_GATE1_OPEN:
|
||||||
|
data << WORLD_STATE_ROHENDOR_THE_SECOND_GATE_HEALTH << m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate);
|
||||||
|
break;
|
||||||
|
case SUNWELL_ROHENDOR_GATE2_OPEN:
|
||||||
|
data << WORLD_STATE_ARCHONISUS_THE_FINAL_GATE_HEALTH << m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,24 @@
|
|||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
// TODO: Move these to WorldStateDefines.h
|
||||||
|
enum WorldStateWorldStates
|
||||||
|
{
|
||||||
|
// Sun's Reach Reclamation
|
||||||
|
WORLD_STATE_QUEL_DANAS_MUSIC = 3426,
|
||||||
|
WORLD_STATE_QUEL_DANAS_HARBOR = 3238,
|
||||||
|
WORLD_STATE_QUEL_DANAS_ALCHEMY_LAB = 3223,
|
||||||
|
WORLD_STATE_QUEL_DANAS_ARMORY = 3233,
|
||||||
|
WORLD_STATE_QUEL_DANAS_SANCTUM = 3244,
|
||||||
|
WORLD_STATE_QUEL_DANAS_PORTAL = 3269,
|
||||||
|
WORLD_STATE_QUEL_DANAS_ANVIL = 3228,
|
||||||
|
WORLD_STATE_QUEL_DANAS_MONUMENT = 3275,
|
||||||
|
// Sunwell Gate
|
||||||
|
WORLD_STATE_AGAMATH_THE_FIRST_GATE_HEALTH = 3253, // guessed, potentially wrong
|
||||||
|
WORLD_STATE_ROHENDOR_THE_SECOND_GATE_HEALTH = 3255,
|
||||||
|
WORLD_STATE_ARCHONISUS_THE_FINAL_GATE_HEALTH = 3257,
|
||||||
|
};
|
||||||
|
|
||||||
enum WorldStateCondition
|
enum WorldStateCondition
|
||||||
{
|
{
|
||||||
WORLD_STATE_CONDITION_TROLLBANES_COMMAND = 39911,
|
WORLD_STATE_CONDITION_TROLLBANES_COMMAND = 39911,
|
||||||
@@ -56,6 +74,10 @@ enum WorldStateZoneId
|
|||||||
ZONEID_BLOOD_FURNACE = 3713,
|
ZONEID_BLOOD_FURNACE = 3713,
|
||||||
ZONEID_SHATTERED_HALLS = 3714,
|
ZONEID_SHATTERED_HALLS = 3714,
|
||||||
ZONEID_MAGTHERIDON_LAIR = 3836,
|
ZONEID_MAGTHERIDON_LAIR = 3836,
|
||||||
|
|
||||||
|
ZONEID_ISLE_OF_QUEL_DANAS = 4080,
|
||||||
|
ZONEID_MAGISTERS_TERRACE = 4131,
|
||||||
|
ZONEID_SUNWELL_PLATEAU = 4075,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum WorldStateSpells
|
enum WorldStateSpells
|
||||||
@@ -64,6 +86,105 @@ enum WorldStateSpells
|
|||||||
|
|
||||||
SPELL_TROLLBANES_COMMAND = 39911,
|
SPELL_TROLLBANES_COMMAND = 39911,
|
||||||
SPELL_NAZGRELS_FAVOR = 39913,
|
SPELL_NAZGRELS_FAVOR = 39913,
|
||||||
|
|
||||||
|
SPELL_KIRU_SONG_OF_VICTORY = 46302,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum WorldStateSaveIds
|
||||||
|
{
|
||||||
|
SAVE_ID_QUEL_DANAS = 20,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum WorldStateGameEvents
|
||||||
|
{
|
||||||
|
// Isle phases
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_1 = 101,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_2_ONLY = 102,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT = 103,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_2_NO_PORTAL = 104,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_2_PORTAL = 105,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_3_ONLY = 106,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_3_PERMANENT = 107,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_3_NO_ANVIL = 108,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_3_ANVIL = 109,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_4 = 110,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_4_NO_MONUMENT = 111,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_4_MONUMENT = 112,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_4_NO_ALCHEMY_LAB= 113,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_4_ALCHEMY_LAB = 114,
|
||||||
|
GAME_EVENT_QUEL_DANAS_PHASE_4_KIRU = 115,
|
||||||
|
// SWP Phases
|
||||||
|
GAME_EVENT_SWP_GATES_PHASE_0 = 116, // All Gates Closed
|
||||||
|
GAME_EVENT_SWP_GATES_PHASE_1 = 117, // First Gate Open
|
||||||
|
GAME_EVENT_SWP_GATES_PHASE_2 = 118, // Second Gate Open
|
||||||
|
GAME_EVENT_SWP_GATES_PHASE_3 = 119, // All Gates Open
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SunsReachPhases
|
||||||
|
{
|
||||||
|
SUNS_REACH_PHASE_1_STAGING_AREA,
|
||||||
|
SUNS_REACH_PHASE_2_SANCTUM,
|
||||||
|
SUNS_REACH_PHASE_3_ARMORY,
|
||||||
|
SUNS_REACH_PHASE_4_HARBOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SunsReachSubPhases
|
||||||
|
{
|
||||||
|
SUBPHASE_PORTAL = 0x01,
|
||||||
|
SUBPHASE_ANVIL = 0x02,
|
||||||
|
SUBPHASE_ALCHEMY_LAB = 0x04,
|
||||||
|
SUBPHASE_MONUMENT = 0x08,
|
||||||
|
SUBPHASE_ALL = SUBPHASE_PORTAL | SUBPHASE_ANVIL | SUBPHASE_ALCHEMY_LAB | SUBPHASE_MONUMENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SunsReachCounters
|
||||||
|
{
|
||||||
|
COUNTER_ERRATIC_BEHAVIOR,
|
||||||
|
COUNTER_SANCTUM_WARDS,
|
||||||
|
COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY,
|
||||||
|
COUNTER_DISTRACTION_AT_THE_DEAD_SCAR,
|
||||||
|
COUNTER_INTERCEPTING_THE_MANA_CELLS,
|
||||||
|
COUNTER_INTERCEPT_THE_REINFORCEMENTS,
|
||||||
|
COUNTER_TAKING_THE_HARBOR,
|
||||||
|
COUNTER_MAKING_READY,
|
||||||
|
COUNTER_DISCOVERING_YOUR_ROOTS,
|
||||||
|
COUNTER_A_CHARITABLE_DONATION,
|
||||||
|
COUNTERS_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SunwellGates
|
||||||
|
{
|
||||||
|
SUNWELL_ALL_GATES_CLOSED,
|
||||||
|
SUNWELL_AGAMATH_GATE1_OPEN,
|
||||||
|
SUNWELL_ROHENDOR_GATE2_OPEN,
|
||||||
|
SUNWELL_ARCHONISUS_GATE3_OPEN,
|
||||||
|
};
|
||||||
|
enum SunwellGateCounters
|
||||||
|
{
|
||||||
|
COUNTER_AGAMATH_THE_FIRST_GATE,
|
||||||
|
COUNTER_ROHENDOR_THE_SECOND_GATE,
|
||||||
|
COUNTER_ARCHONISUS_THE_FINAL_GATE,
|
||||||
|
COUNTERS_MAX_GATES,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SunsReachReclamationData
|
||||||
|
{
|
||||||
|
uint32 m_phase;
|
||||||
|
uint32 m_subphaseMask;
|
||||||
|
uint32 m_sunsReachReclamationCounters[COUNTERS_MAX];
|
||||||
|
GuidVector m_sunsReachReclamationPlayers;
|
||||||
|
std::mutex m_sunsReachReclamationMutex;
|
||||||
|
uint32 m_gate;
|
||||||
|
uint32 m_gateCounters[COUNTERS_MAX_GATES];
|
||||||
|
SunsReachReclamationData() : m_phase(SUNS_REACH_PHASE_1_STAGING_AREA), m_subphaseMask(0), m_gate(SUNWELL_ALL_GATES_CLOSED)
|
||||||
|
{
|
||||||
|
memset(m_sunsReachReclamationCounters, 0, sizeof(m_sunsReachReclamationCounters));
|
||||||
|
memset(m_gateCounters, 0, sizeof(m_gateCounters));
|
||||||
|
}
|
||||||
|
std::string GetData();
|
||||||
|
uint32 GetPhasePercentage(uint32 phase);
|
||||||
|
uint32 GetSubPhasePercentage(uint32 subPhase);
|
||||||
|
uint32 GetSunwellGatePercentage(uint32 gate);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Intended for implementing server wide scripts, note: all behaviour must be safeguarded towards multithreading
|
// Intended for implementing server wide scripts, note: all behaviour must be safeguarded towards multithreading
|
||||||
@@ -73,13 +194,30 @@ class WorldState
|
|||||||
WorldState();
|
WorldState();
|
||||||
virtual ~WorldState();
|
virtual ~WorldState();
|
||||||
static WorldState* instance();
|
static WorldState* instance();
|
||||||
|
void Load();
|
||||||
|
void Save(WorldStateSaveIds saveId);
|
||||||
|
void SaveHelper(std::string& stringToSave, WorldStateSaveIds saveId);
|
||||||
void HandlePlayerEnterZone(Player* player, WorldStateZoneId zoneId);
|
void HandlePlayerEnterZone(Player* player, WorldStateZoneId zoneId);
|
||||||
void HandlePlayerLeaveZone(Player* player, WorldStateZoneId zoneId);
|
void HandlePlayerLeaveZone(Player* player, WorldStateZoneId zoneId);
|
||||||
bool IsConditionFulfilled(WorldStateCondition conditionId, WorldStateConditionState state = WORLD_STATE_CONDITION_STATE_NONE) const;
|
bool IsConditionFulfilled(WorldStateCondition conditionId, WorldStateConditionState state = WORLD_STATE_CONDITION_STATE_NONE) const;
|
||||||
void HandleConditionStateChange(WorldStateCondition conditionId, WorldStateConditionState state);
|
void HandleConditionStateChange(WorldStateCondition conditionId, WorldStateConditionState state);
|
||||||
void HandleExternalEvent(WorldStateEvent eventId, uint32 param);
|
void HandleExternalEvent(WorldStateEvent eventId, uint32 param);
|
||||||
void Update(uint32 diff);
|
void Update(uint32 diff);
|
||||||
|
void AddSunwellGateProgress(uint32 questId);
|
||||||
|
void AddSunsReachProgress(uint32 questId);
|
||||||
|
std::string GetSunsReachPrintout();
|
||||||
|
void FillInitialWorldStates(ByteBuffer& data, uint32 zoneId, uint32 areaId);
|
||||||
|
void HandleSunsReachPhaseTransition(uint32 newPhase);
|
||||||
|
void HandleSunsReachSubPhaseTransition(int32 subPhaseMask, bool initial = false);
|
||||||
|
void SetSunsReachCounter(SunsReachCounters index, uint32 value);
|
||||||
|
void HandleSunwellGateTransition(uint32 newGate);
|
||||||
|
void SetSunwellGateCounter(SunwellGateCounters index, uint32 value);
|
||||||
private:
|
private:
|
||||||
|
void SendWorldstateUpdate(std::mutex& mutex, GuidVector const& guids, uint32 value, uint32 worldStateId);
|
||||||
|
void StopSunsReachPhase(bool forward);
|
||||||
|
void StartSunsReachPhase(bool initial = false);
|
||||||
|
void StartSunwellGatePhase();
|
||||||
|
void StopSunwellGatePhase();
|
||||||
void BuffAdalsSongOfBattle();
|
void BuffAdalsSongOfBattle();
|
||||||
void DispelAdalsSongOfBattle();
|
void DispelAdalsSongOfBattle();
|
||||||
uint32 _adalSongOfBattleTimer;
|
uint32 _adalSongOfBattleTimer;
|
||||||
@@ -87,6 +225,7 @@ class WorldState
|
|||||||
void DispelMagtheridonTeam(TeamId team);
|
void DispelMagtheridonTeam(TeamId team);
|
||||||
bool _isMagtheridonHeadSpawnedHorde;
|
bool _isMagtheridonHeadSpawnedHorde;
|
||||||
bool _isMagtheridonHeadSpawnedAlliance;
|
bool _isMagtheridonHeadSpawnedAlliance;
|
||||||
|
SunsReachReclamationData m_sunsReachData;
|
||||||
std::map<WorldStateCondition, std::atomic<WorldStateConditionState>> _transportStates; // atomic to avoid having to lock
|
std::map<WorldStateCondition, std::atomic<WorldStateConditionState>> _transportStates; // atomic to avoid having to lock
|
||||||
std::mutex _mutex; // all World State operations are threat unsafe
|
std::mutex _mutex; // all World State operations are threat unsafe
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ public:
|
|||||||
Player const* target = player->GetConnectedPlayer();
|
Player const* target = player->GetConnectedPlayer();
|
||||||
|
|
||||||
LocaleConstant loc = handler->GetSessionDbcLocale();
|
LocaleConstant loc = handler->GetSessionDbcLocale();
|
||||||
char const* knownStr = handler->GetAcoreString(LANG_KNOWN);
|
std::string knownStr = handler->GetAcoreString(LANG_KNOWN);
|
||||||
|
|
||||||
// Search in CharTitles.dbc
|
// Search in CharTitles.dbc
|
||||||
for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
|
for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
|
||||||
@@ -308,7 +308,7 @@ public:
|
|||||||
if (!*name)
|
if (!*name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
char const* activeStr = "";
|
std::string activeStr = "";
|
||||||
if (target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index)
|
if (target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index)
|
||||||
activeStr = handler->GetAcoreString(LANG_ACTIVE);
|
activeStr = handler->GetAcoreString(LANG_ACTIVE);
|
||||||
|
|
||||||
|
|||||||
@@ -61,28 +61,22 @@ public:
|
|||||||
GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
|
GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
|
||||||
GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList();
|
GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList();
|
||||||
|
|
||||||
char const* active = handler->GetAcoreString(LANG_ACTIVE);
|
std::string active = handler->GetAcoreString(LANG_ACTIVE);
|
||||||
|
|
||||||
for (uint16 eventId : activeEvents)
|
for (uint16 eventId : activeEvents)
|
||||||
{
|
{
|
||||||
GameEventData const& eventData = events[eventId];
|
GameEventData const& eventData = events[eventId];
|
||||||
|
|
||||||
if (handler->GetSession())
|
if (handler->GetSession())
|
||||||
{
|
|
||||||
handler->PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT, eventId, eventId, eventData.description, active);
|
handler->PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT, eventId, eventId, eventData.description, active);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
handler->PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE, eventId, eventData.description, active);
|
handler->PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE, eventId, eventData.description, active);
|
||||||
}
|
|
||||||
|
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter == 0)
|
if (counter == 0)
|
||||||
{
|
|
||||||
handler->SendSysMessage(LANG_NOEVENTFOUND);
|
handler->SendSysMessage(LANG_NOEVENTFOUND);
|
||||||
}
|
|
||||||
|
|
||||||
handler->SetSentErrorMessage(true);
|
handler->SetSentErrorMessage(true);
|
||||||
|
|
||||||
@@ -108,7 +102,7 @@ public:
|
|||||||
|
|
||||||
GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList();
|
GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList();
|
||||||
bool active = activeEvents.find(eventId) != activeEvents.end();
|
bool active = activeEvents.find(eventId) != activeEvents.end();
|
||||||
char const* activeStr = active ? handler->GetAcoreString(LANG_ACTIVE) : "";
|
std::string activeStr = active ? handler->GetAcoreString(LANG_ACTIVE) : "";
|
||||||
|
|
||||||
std::string startTimeStr = Acore::Time::TimeToTimestampStr(Seconds(eventData.start));
|
std::string startTimeStr = Acore::Time::TimeToTimestampStr(Seconds(eventData.start));
|
||||||
std::string endTimeStr = Acore::Time::TimeToTimestampStr(Seconds(eventData.end));
|
std::string endTimeStr = Acore::Time::TimeToTimestampStr(Seconds(eventData.end));
|
||||||
|
|||||||
@@ -460,8 +460,8 @@ public:
|
|||||||
|
|
||||||
wstrToLower(namePart);
|
wstrToLower(namePart);
|
||||||
|
|
||||||
char const* talentStr = handler->GetAcoreString(LANG_TALENT);
|
std::string talentStr = handler->GetAcoreString(LANG_TALENT);
|
||||||
char const* passiveStr = handler->GetAcoreString(LANG_PASSIVE);
|
std::string passiveStr = handler->GetAcoreString(LANG_PASSIVE);
|
||||||
|
|
||||||
Unit::AuraApplicationMap const& auras = unit->GetAppliedAuras();
|
Unit::AuraApplicationMap const& auras = unit->GetAppliedAuras();
|
||||||
handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, auras.size());
|
handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, auras.size());
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* active = activeEvents.find(id) != activeEvents.end() ? handler->GetAcoreString(LANG_ACTIVE) : "";
|
std::string active = activeEvents.find(id) != activeEvents.end() ? handler->GetAcoreString(LANG_ACTIVE) : "";
|
||||||
|
|
||||||
if (handler->GetSession())
|
if (handler->GetSession())
|
||||||
{
|
{
|
||||||
@@ -806,7 +806,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* statusStr = "";
|
std::string statusStr = "";
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
{
|
{
|
||||||
@@ -862,7 +862,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* statusStr = "";
|
std::string statusStr = "";
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
{
|
{
|
||||||
@@ -1498,20 +1498,16 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* knownStr = target && target->HasTitle(titleInfo) ? handler->GetAcoreString(LANG_KNOWN) : "";
|
std::string knownStr = target && target->HasTitle(titleInfo) ? handler->GetAcoreString(LANG_KNOWN) : "";
|
||||||
char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index ? handler->GetAcoreString(LANG_ACTIVE) : "";
|
std::string activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index ? handler->GetAcoreString(LANG_ACTIVE) : "";
|
||||||
|
|
||||||
std::string titleNameStr = Acore::StringFormat(name, targetName);
|
std::string titleNameStr = Acore::StringFormat(name, targetName);
|
||||||
|
|
||||||
// send title in "id (idx:idx) - [namedlink locale]" format
|
// send title in "id (idx:idx) - [namedlink locale]" format
|
||||||
if (handler->GetSession())
|
if (handler->GetSession())
|
||||||
{
|
|
||||||
handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, titleInfo->ID, titleInfo->bit_index, titleInfo->ID, titleNameStr, localeNames[locale], knownStr, activeStr);
|
handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, titleInfo->ID, titleInfo->bit_index, titleInfo->ID, titleNameStr, localeNames[locale], knownStr, activeStr);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, titleInfo->ID, titleInfo->bit_index, titleNameStr, localeNames[locale], knownStr, activeStr);
|
handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, titleInfo->ID, titleInfo->bit_index, titleNameStr, localeNames[locale], knownStr, activeStr);
|
||||||
}
|
|
||||||
|
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1992,8 +1992,8 @@ public:
|
|||||||
uint32 mapId;
|
uint32 mapId;
|
||||||
uint32 areaId;
|
uint32 areaId;
|
||||||
uint32 phase = 0;
|
uint32 phase = 0;
|
||||||
char const* areaName = nullptr;
|
std::string areaName = "";
|
||||||
char const* zoneName = nullptr;
|
std::string zoneName = "";
|
||||||
|
|
||||||
// Guild data print variables defined so that they exist, but are not necessarily used
|
// Guild data print variables defined so that they exist, but are not necessarily used
|
||||||
uint32 guildId = 0;
|
uint32 guildId = 0;
|
||||||
@@ -2325,19 +2325,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!zoneName)
|
if (zoneName.empty())
|
||||||
{
|
|
||||||
zoneName = handler->GetAcoreString(LANG_UNKNOWN);
|
zoneName = handler->GetAcoreString(LANG_UNKNOWN);
|
||||||
}
|
|
||||||
|
|
||||||
if (areaName)
|
if (!areaName.empty())
|
||||||
{
|
|
||||||
handler->PSendSysMessage(LANG_PINFO_CHR_MAP_WITH_AREA, map->name[locale], zoneName, areaName);
|
handler->PSendSysMessage(LANG_PINFO_CHR_MAP_WITH_AREA, map->name[locale], zoneName, areaName);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
handler->PSendSysMessage(LANG_PINFO_CHR_MAP, map->name[locale], zoneName);
|
handler->PSendSysMessage(LANG_PINFO_CHR_MAP, map->name[locale], zoneName);
|
||||||
}
|
|
||||||
|
|
||||||
// Output XVII. - XVIX. if they are not empty
|
// Output XVII. - XVIX. if they are not empty
|
||||||
if (!guildName.empty())
|
if (!guildName.empty())
|
||||||
@@ -3022,18 +3016,9 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* str = sObjectMgr->GetAcoreString(id, locale ? static_cast<LocaleConstant>(*locale) : DEFAULT_LOCALE);
|
std::string str = sObjectMgr->GetAcoreString(id, locale ? static_cast<LocaleConstant>(*locale) : DEFAULT_LOCALE);
|
||||||
|
handler->SendSysMessage(str);
|
||||||
if (!strcmp(str, "<error>"))
|
return true;
|
||||||
{
|
|
||||||
handler->PSendSysMessage(LANG_NO_ACORE_STRING_FOUND, id);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
handler->SendSysMessage(str);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool HandleOpenDoorCommand(ChatHandler* handler, Optional<float> range)
|
static bool HandleOpenDoorCommand(ChatHandler* handler, Optional<float> range)
|
||||||
|
|||||||
@@ -217,8 +217,7 @@ public:
|
|||||||
static bool HandleMmapStatsCommand(ChatHandler* handler)
|
static bool HandleMmapStatsCommand(ChatHandler* handler)
|
||||||
{
|
{
|
||||||
handler->PSendSysMessage("mmap stats:");
|
handler->PSendSysMessage("mmap stats:");
|
||||||
//handler->PSendSysMessage(" global mmap pathfinding is {}abled", DisableMgr::IsPathfindingEnabled(mapId) ? "en" : "dis");
|
//handler->PSendSysMessage(" global mmap pathfinding is {}abled", sDisableMgr->IsPathfindingEnabled(mapId) ? "en" : "dis");
|
||||||
|
|
||||||
MMAP::MMapMgr* manager = MMAP::MMapFactory::createOrGetMMapMgr();
|
MMAP::MMapMgr* manager = MMAP::MMapFactory::createOrGetMMapMgr();
|
||||||
handler->PSendSysMessage(" {} maps loaded with {} tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount());
|
handler->PSendSysMessage(" {} maps loaded with {} tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount());
|
||||||
|
|
||||||
|
|||||||
@@ -1063,9 +1063,9 @@ public:
|
|||||||
static bool HandleReloadDisablesCommand(ChatHandler* handler)
|
static bool HandleReloadDisablesCommand(ChatHandler* handler)
|
||||||
{
|
{
|
||||||
LOG_INFO("server.loading", "Reloading disables table...");
|
LOG_INFO("server.loading", "Reloading disables table...");
|
||||||
DisableMgr::LoadDisables();
|
sDisableMgr->LoadDisables();
|
||||||
LOG_INFO("server.loading", "Checking quest disables...");
|
LOG_INFO("server.loading", "Checking quest disables...");
|
||||||
DisableMgr::CheckQuestDisables();
|
sDisableMgr->CheckQuestDisables();
|
||||||
handler->SendGlobalGMSysMessage("DB table `disables` reloaded.");
|
handler->SendGlobalGMSysMessage("DB table `disables` reloaded.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ void AddSC_wp_commandscript();
|
|||||||
void AddSC_cache_commandscript();
|
void AddSC_cache_commandscript();
|
||||||
void AddSC_item_commandscript();
|
void AddSC_item_commandscript();
|
||||||
void AddSC_player_settings_commandscript();
|
void AddSC_player_settings_commandscript();
|
||||||
|
void AddSC_worldstate_commandscript();
|
||||||
|
|
||||||
// The name of this function should match:
|
// The name of this function should match:
|
||||||
// void Add${NameOfDirectory}Scripts()
|
// void Add${NameOfDirectory}Scripts()
|
||||||
@@ -113,4 +114,5 @@ void AddCommandsScripts()
|
|||||||
AddSC_cache_commandscript();
|
AddSC_cache_commandscript();
|
||||||
AddSC_item_commandscript();
|
AddSC_item_commandscript();
|
||||||
AddSC_player_settings_commandscript();
|
AddSC_player_settings_commandscript();
|
||||||
|
AddSC_worldstate_commandscript();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 3 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 Affero General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ScriptData
|
||||||
|
Name: worldstate_commandscript
|
||||||
|
%Complete: 100
|
||||||
|
Comment: All worldstate related commands
|
||||||
|
Category: commandscripts
|
||||||
|
EndScriptData */
|
||||||
|
|
||||||
|
#include "Chat.h"
|
||||||
|
#include "CommandScript.h"
|
||||||
|
#include "Common.h"
|
||||||
|
#include "WorldState.h"
|
||||||
|
|
||||||
|
using namespace Acore::ChatCommands;
|
||||||
|
|
||||||
|
class worldstate_commandscript : public CommandScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
worldstate_commandscript() : CommandScript("worldstate_commandscript") { }
|
||||||
|
|
||||||
|
ChatCommandTable GetCommands() const override
|
||||||
|
{
|
||||||
|
static ChatCommandTable sunsreachCommandTable =
|
||||||
|
{
|
||||||
|
{ "status", HandleSunsReachReclamationStatusCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||||
|
{ "phase", HandleSunsReachReclamationPhaseCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||||
|
{ "subphase", HandleSunsReachReclamationSubPhaseCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||||
|
{ "counter", HandleSunsReachReclamationCounterCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||||
|
{ "gate", HandleSunwellGateCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||||
|
{ "gatecounter", HandleSunwellGateCounterCommand, SEC_ADMINISTRATOR, Console::Yes },
|
||||||
|
};
|
||||||
|
|
||||||
|
static ChatCommandTable worldStateCommandTable =
|
||||||
|
{
|
||||||
|
{ "sunsreach", sunsreachCommandTable }
|
||||||
|
};
|
||||||
|
|
||||||
|
static ChatCommandTable commandTable =
|
||||||
|
{
|
||||||
|
{ "worldstate", worldStateCommandTable }
|
||||||
|
};
|
||||||
|
return commandTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HandleSunsReachReclamationStatusCommand(ChatHandler* handler )
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage(sWorldState->GetSunsReachPrintout());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HandleSunsReachReclamationPhaseCommand(ChatHandler* handler, uint32 phase)
|
||||||
|
{
|
||||||
|
if (phase > SUNS_REACH_PHASE_4_HARBOR)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage("Invalid phase, see \".worldstate sunsreach phase\" for usage");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sWorldState->HandleSunsReachPhaseTransition(phase);
|
||||||
|
handler->PSendSysMessage(sWorldState->GetSunsReachPrintout());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HandleSunsReachReclamationSubPhaseCommand(ChatHandler* handler, uint32 subphase)
|
||||||
|
{
|
||||||
|
if (subphase > SUBPHASE_ALL)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage("Invalid subphase, see \".worldstate sunsreach subphase\" for usage");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sWorldState->HandleSunsReachSubPhaseTransition(subphase);;
|
||||||
|
handler->PSendSysMessage(sWorldState->GetSunsReachPrintout());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HandleSunsReachReclamationCounterCommand(ChatHandler* handler, Optional<uint32> index, Optional<uint32> value)
|
||||||
|
{
|
||||||
|
if (!index || !value || index.value() >= COUNTERS_MAX)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage("Syntax: .worldstate sunsreach counter <index> <value>.");
|
||||||
|
handler->PSendSysMessage(sWorldState->GetSunsReachPrintout());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
sWorldState->SetSunsReachCounter(SunsReachCounters(index.value()), value.value());
|
||||||
|
handler->PSendSysMessage(sWorldState->GetSunsReachPrintout());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HandleSunwellGateCommand(ChatHandler* handler, uint32 newGate)
|
||||||
|
{
|
||||||
|
if (newGate > SUNWELL_ARCHONISUS_GATE3_OPEN)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage("Invalid phase, see \".worldstate sunsreach gate\" for usage");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sWorldState->HandleSunwellGateTransition(newGate);
|
||||||
|
handler->PSendSysMessage(sWorldState->GetSunsReachPrintout());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HandleSunwellGateCounterCommand(ChatHandler* handler, Optional<uint32> index, Optional<uint32> value)
|
||||||
|
{
|
||||||
|
if (!index || !value || index.value() >= COUNTERS_MAX_GATES)
|
||||||
|
{
|
||||||
|
handler->PSendSysMessage("Syntax: .worldstate sunsreach gatecounter <index> <value>.");
|
||||||
|
handler->PSendSysMessage(sWorldState->GetSunsReachPrintout());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
sWorldState->SetSunwellGateCounter(SunwellGateCounters(index.value()), value.value());
|
||||||
|
handler->PSendSysMessage(sWorldState->GetSunsReachPrintout());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void AddSC_worldstate_commandscript()
|
||||||
|
{
|
||||||
|
new worldstate_commandscript();
|
||||||
|
}
|
||||||
@@ -21,102 +21,120 @@
|
|||||||
|
|
||||||
enum Yells
|
enum Yells
|
||||||
{
|
{
|
||||||
SAY_AGGRO = 0,
|
SAY_AGGRO = 0, // Combat start
|
||||||
SAY_ENERGY = 1,
|
SAY_ENERGY = 1, // Pure energy spawn
|
||||||
SAY_OVERLOAD = 2,
|
SAY_OVERLOAD = 2, // Final phase
|
||||||
SAY_KILL = 3,
|
SAY_KILL = 3, // Player kill
|
||||||
EMOTE_DISCHARGE_ENERGY = 4
|
EMOTE_DISCHARGE_ENERGY = 4, // Energy discharge warning
|
||||||
|
EMOTE_OVERLOAD = 5 // Overload emote
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Spells
|
enum Spells
|
||||||
{
|
{
|
||||||
// Pure energy spell info
|
SPELL_ENERGY_FEEDBACK_CHANNEL = 44328, // Pure energy channel
|
||||||
SPELL_ENERGY_FEEDBACK_CHANNEL = 44328,
|
SPELL_ENERGY_FEEDBACK = 44335, // Pure energy death effect
|
||||||
SPELL_ENERGY_FEEDBACK = 44335,
|
SPELL_CHAIN_LIGHTNING = 44318, // Basic attack
|
||||||
|
SPELL_OVERLOAD = 44352, // Enrage ability
|
||||||
// Vexallus spell info
|
SPELL_ARCANE_SHOCK = 44319, // Basic attack
|
||||||
SPELL_CHAIN_LIGHTNING = 44318,
|
SPELL_SUMMON_PURE_ENERGY_N = 44322, // Normal mode summon
|
||||||
SPELL_OVERLOAD = 44352,
|
SPELL_SUMMON_PURE_ENERGY_H1 = 46154, // Heroic mode summon 1
|
||||||
SPELL_ARCANE_SHOCK = 44319,
|
SPELL_SUMMON_PURE_ENERGY_H2 = 46159 // Heroic mode summon 2
|
||||||
|
|
||||||
SPELL_SUMMON_PURE_ENERGY_N = 44322,
|
|
||||||
SPELL_SUMMON_PURE_ENERGY_H1 = 46154,
|
|
||||||
SPELL_SUMMON_PURE_ENERGY_H2 = 46159
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Misc
|
|
||||||
{
|
|
||||||
NPC_PURE_ENERGY = 24745
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct boss_vexallus : public BossAI
|
struct boss_vexallus : public BossAI
|
||||||
{
|
{
|
||||||
boss_vexallus(Creature* creature) : BossAI(creature, DATA_VEXALLUS), _energyCooldown(false) { }
|
boss_vexallus(Creature* creature) : BossAI(creature, DATA_VEXALLUS), _energyCooldown(false), _energyCount(0) { }
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
_Reset();
|
_Reset();
|
||||||
_energyCooldown = false;
|
_energyCooldown = false;
|
||||||
|
_energyCount = 0;
|
||||||
|
|
||||||
ScheduleHealthCheckEvent({ 85, 70, 55, 40, 25 }, [&]
|
ScheduleHealthCheckEvent({ 85, 70, 55, 40, 25 }, [&]
|
||||||
{
|
{
|
||||||
if (!_energyCooldown)
|
scheduler.Schedule(1s, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
Talk(SAY_ENERGY);
|
if (!_energyCooldown)
|
||||||
Talk(EMOTE_DISCHARGE_ENERGY);
|
|
||||||
|
|
||||||
if (IsHeroic())
|
|
||||||
{
|
{
|
||||||
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H1);
|
Talk(SAY_ENERGY);
|
||||||
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H2);
|
Talk(EMOTE_DISCHARGE_ENERGY);
|
||||||
|
if (IsHeroic())
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H1);
|
||||||
|
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_N);
|
||||||
|
|
||||||
|
_energyCooldown = true;
|
||||||
|
++_energyCount;
|
||||||
|
|
||||||
|
me->m_Events.AddEventAtOffset([&]
|
||||||
|
{
|
||||||
|
_energyCooldown = false;
|
||||||
|
}, 5s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_N);
|
context.Repeat(5s);
|
||||||
|
|
||||||
_energyCooldown = true;
|
});
|
||||||
scheduler.Schedule(5s, [this](TaskContext)
|
|
||||||
{
|
|
||||||
_energyCooldown = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ScheduleHealthCheckEvent(20, [&]
|
ScheduleHealthCheckEvent(20, [&]
|
||||||
{
|
{
|
||||||
scheduler.CancelAll();
|
scheduler.Schedule(1s, [this](TaskContext context)
|
||||||
DoCastSelf(SPELL_OVERLOAD, true);
|
{
|
||||||
|
if (_energyCount == 5 && !_energyCooldown)
|
||||||
|
{
|
||||||
|
scheduler.CancelAll();
|
||||||
|
Talk(SAY_OVERLOAD);
|
||||||
|
Talk(EMOTE_OVERLOAD);
|
||||||
|
DoCastSelf(SPELL_OVERLOAD, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
context.Repeat(5s);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JustDied(Unit*) override
|
||||||
|
{
|
||||||
|
_JustDied();
|
||||||
|
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ENERGY_FEEDBACK);
|
||||||
|
}
|
||||||
|
|
||||||
void KilledUnit(Unit* victim) override
|
void KilledUnit(Unit* victim) override
|
||||||
{
|
{
|
||||||
if (victim->IsPlayer())
|
if (victim->IsPlayer())
|
||||||
Talk(SAY_KILL);
|
Talk(SAY_KILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
void JustEngagedWith(Unit*) override
|
||||||
{
|
{
|
||||||
_JustEngagedWith();
|
_JustEngagedWith();
|
||||||
Talk(SAY_AGGRO);
|
Talk(SAY_AGGRO);
|
||||||
|
|
||||||
ScheduleTimedEvent(8s, [&]
|
ScheduleTimedEvent(5s, [&]
|
||||||
{
|
{
|
||||||
DoCastRandomTarget(SPELL_CHAIN_LIGHTNING);
|
DoCastRandomTarget(SPELL_CHAIN_LIGHTNING);
|
||||||
}, 8s, 8s);
|
}, 8s);
|
||||||
|
|
||||||
ScheduleTimedEvent(5s, [&]
|
ScheduleTimedEvent(5s, [&]
|
||||||
{
|
{
|
||||||
DoCastRandomTarget(SPELL_ARCANE_SHOCK);
|
DoCastRandomTarget(SPELL_ARCANE_SHOCK);
|
||||||
}, 8s, 8s);
|
}, 5s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* summon) override
|
void JustSummoned(Creature* summon) override
|
||||||
{
|
{
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||||
{
|
{
|
||||||
|
summon->SetReactState(REACT_PASSIVE);
|
||||||
summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
|
summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
|
||||||
summon->CastSpell(target, SPELL_ENERGY_FEEDBACK_CHANNEL, false);
|
summon->CastSpell(target, SPELL_ENERGY_FEEDBACK_CHANNEL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
summons.Summon(summon);
|
summons.Summon(summon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +148,7 @@ struct boss_vexallus : public BossAI
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool _energyCooldown;
|
bool _energyCooldown;
|
||||||
|
uint8 _energyCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_vexallus()
|
void AddSC_boss_vexallus()
|
||||||
|
|||||||
@@ -96,14 +96,6 @@ public:
|
|||||||
if (GameObject* gobj = GetGameObject(DATA_ICEBARRIER))
|
if (GameObject* gobj = GetGameObject(DATA_ICEBARRIER))
|
||||||
gobj->SendUpdateToPlayer(player);
|
gobj->SendUpdateToPlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnCreatureCreate(Creature* creature) override
|
|
||||||
{
|
|
||||||
if (creature->GetSpawnId() > 0 || !creature->GetOwnerGUID().IsPlayer())
|
|
||||||
creature->CastSpell(creature, SPELL_SUNWELL_RADIANCE, true);
|
|
||||||
|
|
||||||
InstanceScript::OnCreatureCreate(creature);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||||
|
|||||||
@@ -106,11 +106,6 @@ enum GameObjectIds
|
|||||||
GO_ORB_OF_THE_BLUE_DRAGONFLIGHT4 = 188116
|
GO_ORB_OF_THE_BLUE_DRAGONFLIGHT4 = 188116
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SpellIds
|
|
||||||
{
|
|
||||||
SPELL_SUNWELL_RADIANCE = 45769,
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class AI, class T>
|
template <class AI, class T>
|
||||||
inline AI* GetSunwellPlateauAI(T* obj)
|
inline AI* GetSunwellPlateauAI(T* obj)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -115,11 +115,13 @@ public:
|
|||||||
|
|
||||||
for (uint8 i = 0; i < RAND_VENDOR; ++i)
|
for (uint8 i = 0; i < RAND_VENDOR; ++i)
|
||||||
RandVendor[i] = NOT_STARTED;
|
RandVendor[i] = NOT_STARTED;
|
||||||
|
|
||||||
|
StorePersistentData(DATA_TIMED_RUN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnPlayerEnter(Player* /*player*/) override
|
void OnPlayerEnter(Player* /*player*/) override
|
||||||
{
|
{
|
||||||
if (!scheduler.IsGroupScheduled(GROUP_TIMED_RUN))
|
if (!scheduler.IsGroupScheduled(GROUP_TIMED_RUN) && GetPersistentData(DATA_TIMED_RUN))
|
||||||
DoAction(ACTION_START_TIMED_RUN);
|
DoAction(ACTION_START_TIMED_RUN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,53 +295,36 @@ public:
|
|||||||
if (!InstanceScript::SetBossState(type, state))
|
if (!InstanceScript::SetBossState(type, state))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (type)
|
if (state == DONE)
|
||||||
{
|
{
|
||||||
case DATA_NALORAKK:
|
switch (type)
|
||||||
if (state == DONE)
|
{
|
||||||
{
|
case DATA_NALORAKK:
|
||||||
if (uint32 timer = GetPersistentData(DATA_TIMED_RUN))
|
if (uint32 timer = GetPersistentData(DATA_TIMED_RUN))
|
||||||
{
|
{
|
||||||
StorePersistentData(DATA_TIMED_RUN, timer += 15);
|
StorePersistentData(DATA_TIMED_RUN, timer += 15);
|
||||||
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer);
|
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer);
|
||||||
}
|
}
|
||||||
SummonHostage(0);
|
SummonHostage(type);
|
||||||
}
|
break;
|
||||||
break;
|
case DATA_AKILZON:
|
||||||
case DATA_AKILZON:
|
|
||||||
if (state == DONE)
|
|
||||||
{
|
|
||||||
if (uint32 timer = GetPersistentData(DATA_TIMED_RUN))
|
if (uint32 timer = GetPersistentData(DATA_TIMED_RUN))
|
||||||
{
|
{
|
||||||
StorePersistentData(DATA_TIMED_RUN, timer += 10);
|
StorePersistentData(DATA_TIMED_RUN, timer += 10);
|
||||||
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer);
|
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer);
|
||||||
}
|
}
|
||||||
SummonHostage(1);
|
SummonHostage(type);
|
||||||
}
|
break;
|
||||||
break;
|
case DATA_JANALAI:
|
||||||
case DATA_JANALAI:
|
case DATA_HALAZZI:
|
||||||
if (state == DONE)
|
SummonHostage(type);
|
||||||
SummonHostage(2);
|
break;
|
||||||
break;
|
case DATA_HEXLORD:
|
||||||
case DATA_HALAZZI:
|
|
||||||
if (state == DONE)
|
|
||||||
SummonHostage(3);
|
|
||||||
break;
|
|
||||||
case DATA_HEXLORD:
|
|
||||||
if (state == IN_PROGRESS)
|
|
||||||
HandleGameObject(ObjectGuid::Empty, false, GetGameObject(DATA_HEXLORD_GATE));
|
|
||||||
else if (state == NOT_STARTED)
|
|
||||||
CheckInstanceStatus();
|
|
||||||
else if (state == DONE)
|
|
||||||
{
|
|
||||||
if (GameObject* zuljinGate = GetGameObject(DATA_ZULJIN_GATE))
|
if (GameObject* zuljinGate = GetGameObject(DATA_ZULJIN_GATE))
|
||||||
zuljinGate->RemoveGameObjectFlag(GO_FLAG_LOCKED);
|
zuljinGate->RemoveGameObjectFlag(GO_FLAG_LOCKED);
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (state == DONE)
|
|
||||||
{
|
|
||||||
if (GetPersistentData(DATA_TIMED_RUN) && AllBossesDone({ DATA_NALORAKK, DATA_AKILZON, DATA_JANALAI, DATA_HALAZZI }))
|
if (GetPersistentData(DATA_TIMED_RUN) && AllBossesDone({ DATA_NALORAKK, DATA_AKILZON, DATA_JANALAI, DATA_HALAZZI }))
|
||||||
{
|
{
|
||||||
StorePersistentData(DATA_TIMED_RUN, 0);
|
StorePersistentData(DATA_TIMED_RUN, 0);
|
||||||
@@ -348,6 +333,16 @@ public:
|
|||||||
|
|
||||||
CheckInstanceStatus();
|
CheckInstanceStatus();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (type == DATA_HEXLORD)
|
||||||
|
{
|
||||||
|
if (state == IN_PROGRESS)
|
||||||
|
HandleGameObject(ObjectGuid::Empty, false, GetGameObject(DATA_HEXLORD_GATE));
|
||||||
|
else if (state == NOT_STARTED)
|
||||||
|
CheckInstanceStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ public:
|
|||||||
if (creature->IsSummon() && _bossWave != TO_BE_DECIDED)
|
if (creature->IsSummon() && _bossWave != TO_BE_DECIDED)
|
||||||
{
|
{
|
||||||
if (_currentWave == 0)
|
if (_currentWave == 0)
|
||||||
creature->SetDisableReputationGain(true);
|
creature->SetReputationRewardDisabled(true);
|
||||||
DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, ++trash); // Update the instance wave count on new trash spawn
|
DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, ++trash); // Update the instance wave count on new trash spawn
|
||||||
_encounterNPCs.insert(creature->GetGUID()); // Used for despawning on wipe
|
_encounterNPCs.insert(creature->GetGUID()); // Used for despawning on wipe
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public:
|
|||||||
|
|
||||||
InstanceScript* pInstance;
|
InstanceScript* pInstance;
|
||||||
EventMap events;
|
EventMap events;
|
||||||
bool lock;
|
bool lock, inCenter;
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
int32 releaseLockTimer;
|
int32 releaseLockTimer;
|
||||||
|
|
||||||
@@ -134,6 +134,7 @@ public:
|
|||||||
me->CastSpell(me, SPELL_EVOCATION, true);
|
me->CastSpell(me, SPELL_EVOCATION, true);
|
||||||
events.Reset();
|
events.Reset();
|
||||||
lock = false;
|
lock = false;
|
||||||
|
inCenter = false;
|
||||||
x = 0.0f;
|
x = 0.0f;
|
||||||
y = 0.0f;
|
y = 0.0f;
|
||||||
z = 0.0f;
|
z = 0.0f;
|
||||||
@@ -222,9 +223,14 @@ public:
|
|||||||
{
|
{
|
||||||
pInstance->SetData(DATA_UROM, DONE);
|
pInstance->SetData(DATA_UROM, DONE);
|
||||||
}
|
}
|
||||||
me->SetCanFly(false);
|
|
||||||
me->SetDisableGravity(false);
|
// Body teleportation required only when boss is flying in the center
|
||||||
me->NearTeleportTo(x, y, z, 0.0f);
|
if (inCenter)
|
||||||
|
{
|
||||||
|
me->SetCanFly(false);
|
||||||
|
me->SetDisableGravity(false);
|
||||||
|
me->NearTeleportTo(x, y, z, 0.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KilledUnit(Unit* /*victim*/) override
|
void KilledUnit(Unit* /*victim*/) override
|
||||||
@@ -281,6 +287,7 @@ public:
|
|||||||
me->SetCanFly(true);
|
me->SetCanFly(true);
|
||||||
me->SetDisableGravity(true);
|
me->SetDisableGravity(true);
|
||||||
me->NearTeleportTo(1103.69f, 1048.76f, 512.279f, 1.16f);
|
me->NearTeleportTo(1103.69f, 1048.76f, 512.279f, 1.16f);
|
||||||
|
inCenter = true;
|
||||||
|
|
||||||
Talk(SAY_ARCANE_EXPLOSION);
|
Talk(SAY_ARCANE_EXPLOSION);
|
||||||
Talk(EMOTE_ARCANE_EXPLOSION);
|
Talk(EMOTE_ARCANE_EXPLOSION);
|
||||||
@@ -356,6 +363,7 @@ public:
|
|||||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||||
|
inCenter = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,6 +373,7 @@ public:
|
|||||||
me->SetCanFly(false);
|
me->SetCanFly(false);
|
||||||
me->SetDisableGravity(false);
|
me->SetDisableGravity(false);
|
||||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||||
|
inCenter = false;
|
||||||
ScriptedAI::EnterEvadeMode(why);
|
ScriptedAI::EnterEvadeMode(why);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 3 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 Affero 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 "CreatureScript.h"
|
||||||
|
#include "WorldState.h"
|
||||||
|
|
||||||
|
class npc_suns_reach_reclamation : public CreatureScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
npc_suns_reach_reclamation() : CreatureScript("npc_suns_reach_reclamation") { }
|
||||||
|
|
||||||
|
bool OnQuestReward(Player* /*player*/, Creature* /*creature*/, const Quest* quest, uint32 /*slot*/) override
|
||||||
|
{
|
||||||
|
sWorldState->AddSunsReachProgress(quest->GetQuestId());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class npc_sunwell_gate : public CreatureScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
npc_sunwell_gate() : CreatureScript("npc_sunwell_gate") { }
|
||||||
|
|
||||||
|
bool OnQuestReward(Player* /*player*/, Creature* /*creature*/, const Quest* quest, uint32 /*slot*/) override
|
||||||
|
{
|
||||||
|
sWorldState->AddSunwellGateProgress(quest->GetQuestId());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void AddSC_suns_reach_reclamation()
|
||||||
|
{
|
||||||
|
new npc_suns_reach_reclamation();
|
||||||
|
new npc_sunwell_gate();
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ void AddSC_player_scripts();
|
|||||||
void AddSC_npc_stave_of_ancients();
|
void AddSC_npc_stave_of_ancients();
|
||||||
void AddSC_server_mail();
|
void AddSC_server_mail();
|
||||||
void AddSC_transport_zeppelins();
|
void AddSC_transport_zeppelins();
|
||||||
|
void AddSC_suns_reach_reclamation();
|
||||||
|
|
||||||
// The name of this function should match:
|
// The name of this function should match:
|
||||||
// void Add${NameOfDirectory}Scripts()
|
// void Add${NameOfDirectory}Scripts()
|
||||||
@@ -55,4 +56,5 @@ void AddWorldScripts()
|
|||||||
AddSC_npc_stave_of_ancients();
|
AddSC_npc_stave_of_ancients();
|
||||||
AddSC_server_mail();
|
AddSC_server_mail();
|
||||||
AddSC_transport_zeppelins();
|
AddSC_transport_zeppelins();
|
||||||
|
AddSC_suns_reach_reclamation();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public:
|
|||||||
MOCK_METHOD(void, SendGlobalMessage, (WorldPacket const* packet, WorldSession* self, TeamId teamId), ());
|
MOCK_METHOD(void, SendGlobalMessage, (WorldPacket const* packet, WorldSession* self, TeamId teamId), ());
|
||||||
MOCK_METHOD(void, SendGlobalGMMessage, (WorldPacket const* packet, WorldSession* self, TeamId teamId), ());
|
MOCK_METHOD(void, SendGlobalGMMessage, (WorldPacket const* packet, WorldSession* self, TeamId teamId), ());
|
||||||
MOCK_METHOD(bool, SendZoneMessage, (uint32 zone, WorldPacket const* packet, WorldSession* self, TeamId teamId), ());
|
MOCK_METHOD(bool, SendZoneMessage, (uint32 zone, WorldPacket const* packet, WorldSession* self, TeamId teamId), ());
|
||||||
MOCK_METHOD(void, SendZoneText, (uint32 zone, const char* text, WorldSession* self, TeamId teamId), ());
|
MOCK_METHOD(void, SendZoneText, (uint32 zone, std::string text, WorldSession* self, TeamId teamId), ());
|
||||||
MOCK_METHOD(void, SendServerMessage, (ServerMessageType messageID, std::string stringParam, Player* player));
|
MOCK_METHOD(void, SendServerMessage, (ServerMessageType messageID, std::string stringParam, Player* player));
|
||||||
MOCK_METHOD(bool, IsShuttingDown, (), (const));
|
MOCK_METHOD(bool, IsShuttingDown, (), (const));
|
||||||
MOCK_METHOD(uint32, GetShutDownTimeLeft, (), (const));
|
MOCK_METHOD(uint32, GetShutDownTimeLeft, (), (const));
|
||||||
|
|||||||
Reference in New Issue
Block a user