mirror of
https://github.com/azerothcore/azerothcore-wotlk.git
synced 2025-11-10 21:04:26 +08:00
Merge branch 'master' into ovv/systemd-socket-activation
This commit is contained in:
commit
37e8e2102f
2
.github/workflows/codestyle.yml
vendored
2
.github/workflows/codestyle.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: Codestyle
|
||||
name: C++ Codestyle
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
|
||||
2
.github/workflows/sql-codestyle.yml
vendored
2
.github/workflows/sql-codestyle.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: Codestyle
|
||||
name: SQL Codestyle
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
|
||||
@ -28,7 +28,8 @@ results = {
|
||||
"INSERT & DELETE safety usage check": "Passed",
|
||||
"Missing semicolon check": "Passed",
|
||||
"Backtick check": "Passed",
|
||||
"Directory check": "Passed"
|
||||
"Directory check": "Passed",
|
||||
"Table engine check": "Passed"
|
||||
}
|
||||
|
||||
# Collect all files in all directories
|
||||
@ -78,6 +79,7 @@ def parsing_file(files: list) -> None:
|
||||
insert_delete_safety_check(file, file_path)
|
||||
semicolon_check(file, file_path)
|
||||
backtick_check(file, file_path)
|
||||
non_innodb_engine_check(file, file_path)
|
||||
except UnicodeDecodeError:
|
||||
print(f"\n❌ Could not decode file {file_path}")
|
||||
sys.exit(1)
|
||||
@ -383,6 +385,25 @@ def directory_check(file: io, file_path: str) -> None:
|
||||
error_handler = True
|
||||
results["Directory check"] = "Failed"
|
||||
|
||||
def non_innodb_engine_check(file: io, file_path: str) -> None:
|
||||
global error_handler, results
|
||||
file.seek(0)
|
||||
check_failed = False
|
||||
|
||||
engine_pattern = re.compile(r'ENGINE\s*=\s*([a-zA-Z0-9_]+)', re.IGNORECASE)
|
||||
|
||||
for line_number, line in enumerate(file, start=1):
|
||||
match = engine_pattern.search(line)
|
||||
if match:
|
||||
engine = match.group(1).lower()
|
||||
if engine != "innodb":
|
||||
print(f"❌ Non-InnoDB engine found: '{engine}' in {file_path} at line {line_number}")
|
||||
check_failed = True
|
||||
|
||||
if check_failed:
|
||||
error_handler = True
|
||||
results["Table engine check"] = "Failed"
|
||||
|
||||
# Collect all files from matching directories
|
||||
all_files = collect_files_from_directories(src_directory) + collect_files_from_directories(base_directory) + collect_files_from_directories(archive_directory)
|
||||
|
||||
|
||||
3
data/sql/updates/db_characters/2025_07_11_00.sql
Normal file
3
data/sql/updates/db_characters/2025_07_11_00.sql
Normal file
@ -0,0 +1,3 @@
|
||||
-- DB update 2025_03_09_00 -> 2025_07_11_00
|
||||
--
|
||||
ALTER TABLE `world_state` ENGINE = InnoDB;
|
||||
68
data/sql/updates/db_world/2025_07_08_00.sql
Normal file
68
data/sql/updates/db_world/2025_07_08_00.sql
Normal file
@ -0,0 +1,68 @@
|
||||
-- DB update 2025_07_07_00 -> 2025_07_08_00
|
||||
|
||||
-- Set Spell Script
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_chapter2_persuasive_strike';
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(52781, 'spell_chapter2_persuasive_strike');
|
||||
|
||||
-- Remove Flag Stunned from Scarlet Commanders
|
||||
UPDATE `creature_template` SET `unit_flags` = `unit_flags` &~ 262144 WHERE (`entry` = 28936);
|
||||
|
||||
-- Remove c++ script and set SmartAI for Scarlet Crusaders/Preachers/Commanders/Marksmen
|
||||
UPDATE `creature_template` SET `ScriptName` = '', `AIName` = 'SmartAI' WHERE `entry` IN (28610, 28936, 28939, 28940);
|
||||
|
||||
-- Scarlet Commander SmartAI
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28936) AND (`source_type` = 0) AND (`id` IN (0));
|
||||
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
|
||||
(28936, 0, 0, 0, 0, 0, 100, 0, 4000, 8000, 4000, 8000, 0, 0, 11, 52221, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander - In Combat - Cast \'Heroic Strike\'');
|
||||
|
||||
-- Scarlet Crusader SmartAI
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28940) AND (`source_type` = 0) AND (`id` IN (0));
|
||||
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
|
||||
(28940, 0, 0, 0, 0, 0, 100, 0, 4000, 8000, 4000, 8000, 0, 0, 11, 52221, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Crusader - In Combat - Cast \'Heroic Strike\'');
|
||||
|
||||
-- Scarlet Marksman SmartAI
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28610) AND (`source_type` = 0) AND (`id` IN (0));
|
||||
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
|
||||
(28610, 0, 0, 0, 0, 0, 100, 0, 4000, 8000, 4000, 8000, 0, 0, 11, 32915, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Marksman - In Combat - Cast \'Raptor Strike\'');
|
||||
|
||||
-- Scarlet Preacher SmartAI
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28939);
|
||||
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
|
||||
(28939, 0, 0, 0, 60, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 34809, 32, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Preacher - On Update - Cast \'Holy Fury\''),
|
||||
(28939, 0, 1, 0, 0, 0, 100, 0, 8000, 12000, 8000, 12000, 0, 0, 11, 34809, 33, 0, 1, 0, 0, 26, 10, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Preacher - In Combat - Cast \'Holy Fury\''),
|
||||
(28939, 0, 2, 0, 0, 0, 100, 0, 0, 0, 2500, 2500, 0, 0, 11, 15498, 64, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Preacher - In Combat - Cast \'Holy Smite\''),
|
||||
(28939, 0, 3, 0, 0, 0, 100, 0, 6000, 12000, 20000, 25000, 0, 0, 11, 19725, 32, 0, 1, 0, 0, 9, 28897, 0, 20, 1, 0, 0, 0, 0, 'Scarlet Preacher - In Combat - Cast \'Turn Undead\'');
|
||||
|
||||
-- Condition for Scarlet Commander
|
||||
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 17) AND (`SourceGroup` = 0) AND (`SourceEntry` = 52781) AND (`SourceId` = 0) AND (`ElseGroup` = 3) AND (`ConditionTypeOrReference` = 31) AND (`ConditionTarget` = 1) AND (`ConditionValue1` = 3) AND (`ConditionValue2` = 28936) AND (`ConditionValue3` = 0);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(17, 0, 52781, 0, 3, 31, 1, 3, 28936, 0, 0, 27, 0, '', 'Persuasive Strike - Scarlet Commander');
|
||||
|
||||
-- Condition for Jesseriah McCree
|
||||
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 17) AND (`SourceGroup` = 0) AND (`SourceEntry` = 52781) AND (`SourceId` = 0) AND (`ElseGroup` = 4) AND (`ConditionTypeOrReference` = 31) AND (`ConditionTarget` = 1) AND (`ConditionValue1` = 3) AND (`ConditionValue2` = 28964) AND (`ConditionValue3` = 0);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(17, 0, 52781, 0, 4, 31, 1, 3, 28964, 0, 0, 27, 0, '', 'Persuasive Strike - Scarlet Lord Jesseriah McCree');
|
||||
|
||||
-- Add Texts inside McCree's table (for a future implementation).
|
||||
DELETE FROM `creature_text` WHERE (`CreatureID` = 28964);
|
||||
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||
(28964, 1, 0, 'You\'ll be hanging in the gallows shortly, Scourge fiend!', 12, 0, 100, 0, 0, 0, 29160, 0, 'crusader SAY_CURSADER1'),
|
||||
(28964, 1, 1, 'You\'ll have to kill me, monster. I will tell you NOTHING!', 12, 0, 100, 0, 0, 0, 29142, 0, 'crusader SAY_CURSADER2'),
|
||||
(28964, 1, 2, 'You hit like a girl. Honestly. Is that the best you can do?', 12, 0, 100, 0, 0, 0, 29146, 0, 'crusader SAY_CURSADER3'),
|
||||
(28964, 1, 3, 'ARGH! You burned my last good tabard!', 12, 0, 100, 0, 0, 0, 29162, 0, 'crusader SAY_CURSADER4'),
|
||||
(28964, 1, 4, 'Argh... The pain... The pain is almost as unbearable as the lashings I received in grammar school when I was but a child.', 12, 0, 100, 0, 0, 0, 29143, 0, 'crusader SAY_CURSADER5'),
|
||||
(28964, 1, 5, 'I used to work for Grand Inquisitor Isillien! Your idea of pain is a normal mid-afternoon for me!', 12, 0, 100, 0, 0, 0, 29161, 0, 'crusader SAY_CURSADER6'),
|
||||
(28964, 2, 0, 'I\'ll tell you everything! STOP! PLEASE!', 12, 0, 100, 0, 0, 0, 29149, 0, 'break crusader SAY_PERSUADED1'),
|
||||
(28964, 3, 0, 'We... We have only been told that the "Crimson Dawn" is an awakening. You... You see, the Light speaks to the High General. It is the Light...', 12, 0, 100, 0, 0, 0, 29150, 0, 'break crusader SAY_PERSUADED2'),
|
||||
(28964, 4, 0, 'The Light that guides us. This movement was set in motion before you came... We... We do as we are told. It is what must be done.', 12, 0, 100, 0, 0, 0, 29151, 0, 'break crusader SAY_PERSUADED3'),
|
||||
(28964, 5, 0, 'I know very litte else... The High General chooses who may go and who must stay behind. There\'s nothing else... You must believe me!', 12, 0, 100, 0, 0, 0, 29152, 0, 'break crusader SAY_PERSUADED4'),
|
||||
(28964, 6, 0, 'LIES! The pain you are about to endure will be talked about for years to come!', 12, 0, 100, 0, 0, 0, 29163, 0, 'break crusader SAY_PERSUADED5'),
|
||||
(28964, 7, 0, 'NO! PLEASE! There is one more thing that I forgot to mention... A courier comes soon... From Hearthglen. It...', 12, 0, 100, 0, 0, 0, 29153, 0, 'break crusader SAY_PERSUADED6'),
|
||||
(28964, 8, 0, 'I\'ll tear the secrets from your soul! Tell me about the "Crimson Dawn" and your life may be spared!', 12, 0, 100, 0, 0, 0, 29138, 0, 'player SAY_PERSUADE1'),
|
||||
(28964, 8, 1, 'Tell me what you know about "Crimson Dawn" or the beatings will continue!', 12, 0, 100, 0, 0, 0, 29134, 0, 'player SAY_PERSUADE2'),
|
||||
(28964, 8, 2, 'I\'m through being courteous with your kind, human! What is the "Crimson Dawn?"', 12, 0, 100, 0, 0, 0, 29135, 0, 'player SAY_PERSUADE3'),
|
||||
(28964, 8, 3, 'Is your life worth so little? Just tell me what I need to know about "Crimson Dawn" and I\'ll end your suffering quickly.', 12, 0, 100, 0, 0, 0, 29139, 0, 'player SAY_PERSUADE4'),
|
||||
(28964, 8, 4, 'I can keep this up for a very long time, Scarlet dog! Tell me about the "Crimson Dawn!"', 12, 0, 100, 0, 0, 0, 29137, 0, 'player SAY_PERSUADE'),
|
||||
(28964, 8, 5, 'What is the "Crimson Dawn?"', 12, 0, 100, 0, 0, 0, 29133, 0, 'player SAY_PERSUADE6'),
|
||||
(28964, 8, 6, '"Crimson Dawn!" What is it! Speak!', 12, 0, 100, 0, 0, 0, 29136, 0, 'player SAY_PERSUADE7');
|
||||
97
data/sql/updates/db_world/2025_07_08_01.sql
Normal file
97
data/sql/updates/db_world/2025_07_08_01.sql
Normal file
@ -0,0 +1,97 @@
|
||||
-- DB update 2025_07_08_00 -> 2025_07_08_01
|
||||
DELETE FROM `creature_formations` WHERE `leaderGUID` IN (96764, 96786, 96763, 96776, 96775, 96828, 96825, 96831, 96778, 96777, 96824, 96780, 96767, 96769, 96773, 96779, 96771, 96781);
|
||||
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
|
||||
(96764, 96764, 0, 0, 3, 0, 0),
|
||||
(96764, 96765, 0, 0, 3, 0, 0),
|
||||
|
||||
(96786, 96786, 0, 0, 515, 0, 0),
|
||||
(96786, 96814, 2, 270, 515, 0, 0),
|
||||
|
||||
(96763, 96763, 0, 0, 3, 0, 0),
|
||||
(96763, 96788, 0, 0, 3, 0, 0),
|
||||
(96763, 96801, 0, 0, 3, 0, 0),
|
||||
(96763, 96816, 0, 0, 3, 0, 0),
|
||||
|
||||
(96776, 96776, 0, 0, 3, 0, 0),
|
||||
(96776, 96787, 0, 0, 3, 0, 0),
|
||||
(96776, 96799, 0, 0, 3, 0, 0),
|
||||
(96776, 96815, 0, 0, 3, 0, 0),
|
||||
|
||||
(96775, 96775, 0, 0, 3, 0, 0),
|
||||
(96775, 96813, 0, 0, 3, 0, 0),
|
||||
(96775, 96797, 0, 0, 3, 0, 0),
|
||||
(96775, 96785, 0, 0, 3, 0, 0),
|
||||
|
||||
(96828, 96828, 0, 0, 3, 0, 0),
|
||||
(96828, 96834, 0, 0, 3, 0, 0),
|
||||
(96828, 96829, 0, 0, 3, 0, 0),
|
||||
(96828, 96833, 0, 0, 3, 0, 0),
|
||||
(96828, 96837, 0, 0, 3, 0, 0),
|
||||
(96828, 96838, 0, 0, 3, 0, 0),
|
||||
|
||||
(96825, 96825, 0, 0, 3, 0, 0),
|
||||
(96825, 96830, 0, 0, 3, 0, 0),
|
||||
|
||||
(96831, 96831, 0, 0, 3, 0, 0),
|
||||
(96831, 96832, 0, 0, 3, 0, 0),
|
||||
(96831, 96826, 0, 0, 3, 0, 0),
|
||||
(96831, 96836, 0, 0, 3, 0, 0),
|
||||
(96831, 96827, 0, 0, 3, 0, 0),
|
||||
(96831, 96835, 0, 0, 3, 0, 0),
|
||||
|
||||
(96778, 96778, 0, 0, 3, 0, 0),
|
||||
(96778, 96805, 0, 0, 3, 0, 0),
|
||||
(96778, 96768, 0, 0, 3, 0, 0),
|
||||
(96778, 96843, 0, 0, 3, 0, 0),
|
||||
(96778, 96789, 0, 0, 3, 0, 0),
|
||||
|
||||
(96777, 96777, 0, 0, 3, 0, 0),
|
||||
(96777, 96802, 0, 0, 3, 0, 0),
|
||||
(96777, 96766, 0, 0, 3, 0, 0),
|
||||
(96777, 96817, 0, 0, 3, 0, 0),
|
||||
|
||||
(96824, 96824, 0, 0, 3, 0, 0),
|
||||
(96824, 96774, 0, 0, 3, 0, 0),
|
||||
(96824, 96796, 0, 0, 3, 0, 0),
|
||||
(96824, 96812, 0, 0, 3, 0, 0),
|
||||
|
||||
(96780, 96780, 0, 0, 3, 0, 0),
|
||||
(96780, 96808, 0, 0, 3, 0, 0),
|
||||
(96780, 96849, 0, 0, 3, 0, 0),
|
||||
(96780, 96791, 0, 0, 3, 0, 0),
|
||||
(96780, 96846, 0, 0, 3, 0, 0),
|
||||
|
||||
(96767, 96767, 0, 0, 3, 0, 0),
|
||||
(96767, 96839, 0, 0, 3, 0, 0),
|
||||
(96767, 96803, 0, 0, 3, 0, 0),
|
||||
(96767, 96818, 0, 0, 3, 0, 0),
|
||||
(96767, 96842, 0, 0, 3, 0, 0),
|
||||
|
||||
(96769, 96769, 0, 0, 3, 0, 0),
|
||||
(96769, 96806, 0, 0, 3, 0, 0),
|
||||
(96769, 96820, 0, 0, 3, 0, 0),
|
||||
(96769, 96840, 0, 0, 3, 0, 0),
|
||||
(96769, 96844, 0, 0, 3, 0, 0),
|
||||
|
||||
(96773, 96773, 0, 0, 3, 0, 0),
|
||||
(96773, 96784, 0, 0, 3, 0, 0),
|
||||
(96773, 96811, 0, 0, 3, 0, 0),
|
||||
(96773, 96795, 0, 0, 3, 0, 0),
|
||||
|
||||
(96779, 96779, 0, 0, 3, 0, 0),
|
||||
(96779, 96848, 0, 0, 3, 0, 0),
|
||||
(96779, 96807, 0, 0, 3, 0, 0),
|
||||
(96779, 96790, 0, 0, 3, 0, 0),
|
||||
(96779, 96845, 0, 0, 3, 0, 0),
|
||||
|
||||
(96771, 96771, 0, 0, 3, 0, 0),
|
||||
(96771, 96810, 0, 0, 3, 0, 0),
|
||||
(96771, 96793, 0, 0, 3, 0, 0),
|
||||
(96771, 96821, 0, 0, 3, 0, 0),
|
||||
|
||||
(96781, 96781, 0, 0, 3, 0, 0),
|
||||
(96781, 96850, 0, 0, 3, 0, 0),
|
||||
(96781, 96847, 0, 0, 3, 0, 0),
|
||||
(96781, 96770, 0, 0, 3, 0, 0),
|
||||
(96781, 96809, 0, 0, 3, 0, 0),
|
||||
(96781, 96841, 0, 0, 3, 0, 0);
|
||||
9
data/sql/updates/db_world/2025_07_09_00.sql
Normal file
9
data/sql/updates/db_world/2025_07_09_00.sql
Normal file
@ -0,0 +1,9 @@
|
||||
-- DB update 2025_07_08_01 -> 2025_07_09_00
|
||||
|
||||
-- Edit Spell_Area
|
||||
UPDATE `spell_area` SET `quest_start` = 12801, `quest_start_status` = `quest_start_status` &~ 10 WHERE `spell` = 58354;
|
||||
|
||||
-- Add the second Darion Mograine quest starter
|
||||
DELETE FROM `creature_queststarter` WHERE (`quest` = 13165) AND (`id` IN (31084));
|
||||
INSERT INTO `creature_queststarter` (`id`, `quest`) VALUES
|
||||
(31084, 13165);
|
||||
23
data/sql/updates/db_world/2025_07_10_00.sql
Normal file
23
data/sql/updates/db_world/2025_07_10_00.sql
Normal file
@ -0,0 +1,23 @@
|
||||
-- DB update 2025_07_09_00 -> 2025_07_10_00
|
||||
|
||||
-- Set SmartAI
|
||||
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE (`entry` IN (28610, 28936, 28940, 28939, 28964));
|
||||
|
||||
-- Scarlet Commander, Crusader and Marksman.
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` IN (28610, 28936, 28940)) AND (`source_type` = 0) AND (`id` IN (1));
|
||||
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
|
||||
(28610, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Marksman - On Respawn - Remove Flags Not Attackable'),
|
||||
(28940, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Crusader - On Respawn - Remove Flags Not Attackable'),
|
||||
(28936, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander - On Respawn - Remove Flags Not Attackable');
|
||||
|
||||
-- Scarlet Preacher
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28939) AND (`source_type` = 0) AND (`id` IN (4));
|
||||
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
|
||||
(28939, 0, 4, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Preacher - On Respawn - Remove Flags Not Attackable');
|
||||
|
||||
-- Scarlet Lord Jesseriah McCree.
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28964) AND (`source_type` = 0) AND (`id` IN (0, 1, 2));
|
||||
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
|
||||
(28964, 0, 0, 0, 0, 0, 100, 0, 4000, 8000, 8000, 12000, 0, 0, 11, 52835, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Lord Jesseriah McCree - In Combat - Cast \'Cleave\''),
|
||||
(28964, 0, 1, 0, 0, 0, 100, 0, 12000, 18000, 30000, 35000, 0, 0, 11, 52836, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Lord Jesseriah McCree - In Combat - Cast \'Holy Wrath\''),
|
||||
(28964, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Lord Jesseriah McCree - On Respawn - Remove Flags Not Attackable');
|
||||
@ -36,6 +36,7 @@ static const unsigned int DT_BUFFER_TOO_SMALL = 1 << 4; // Result buffer for the
|
||||
static const unsigned int DT_OUT_OF_NODES = 1 << 5; // Query ran out of nodes during search.
|
||||
static const unsigned int DT_PARTIAL_RESULT = 1 << 6; // Query did not reach the end location, returning best guess.
|
||||
static const unsigned int DT_ALREADY_OCCUPIED = 1 << 7; // A tile has already been assigned to the given x,y coordinate
|
||||
static const unsigned int DT_SLOPE_TOO_STEEP = 1 << 8; // Surface slope too steep to be walkable.
|
||||
|
||||
|
||||
// Returns true of status is success.
|
||||
|
||||
@ -1419,18 +1419,6 @@ CheckGameObjectLoS = 1
|
||||
|
||||
PreloadAllNonInstancedMapGrids = 0
|
||||
|
||||
#
|
||||
# SetAllCreaturesWithWaypointMovementActive
|
||||
# Description: Set all creatures with waypoint movement active. This means that they will start
|
||||
# movement once they are loaded (which happens on grid load) and keep moving even
|
||||
# when no player is near. This will increase CPU usage significantly and can be
|
||||
# used with enabled "PreloadAllNonInstancedMapGrids" to start waypoint movement on
|
||||
# server startup.
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
SetAllCreaturesWithWaypointMovementActive = 0
|
||||
|
||||
#
|
||||
# DontCacheRandomMovementPaths
|
||||
# Description: Random movement paths (calculated using MoveMaps) can be cached to save cpu time,
|
||||
@ -3856,11 +3844,18 @@ Arena.QueueAnnouncer.Detail = 3
|
||||
|
||||
#
|
||||
# Arena.ArenaStartRating
|
||||
# Description: Start rating for new arena teams.
|
||||
# Description: Start rating for new arena teams. (Applies to season 6 and higher)
|
||||
# Default: 0
|
||||
|
||||
Arena.ArenaStartRating = 0
|
||||
|
||||
#
|
||||
# Arena.LegacyArenaStartRating
|
||||
# Description: Start rating for new arena teams. (Only applies to season 1 - 5)
|
||||
# Default: 1500
|
||||
|
||||
Arena.LegacyArenaStartRating = 1500
|
||||
|
||||
#
|
||||
# Arena.ArenaStartPersonalRating
|
||||
# Description: Start personal rating when joining a team.
|
||||
|
||||
@ -36,7 +36,9 @@ ArenaTeam::ArenaTeam()
|
||||
Stats.WeekGames = 0;
|
||||
Stats.SeasonGames = 0;
|
||||
Stats.Rank = 0;
|
||||
Stats.Rating = sWorld->getIntConfig(CONFIG_ARENA_START_RATING);
|
||||
Stats.Rating = (sArenaSeasonMgr->GetCurrentSeason() < 6)
|
||||
? sWorld->getIntConfig(CONFIG_LEGACY_ARENA_START_RATING)
|
||||
: sWorld->getIntConfig(CONFIG_ARENA_START_RATING);
|
||||
Stats.WeekWins = 0;
|
||||
Stats.SeasonWins = 0;
|
||||
}
|
||||
|
||||
@ -419,6 +419,9 @@ TeamId BattlegroundAB::GetPrematureWinner()
|
||||
|
||||
bool BattlegroundAB::SetupBattleground()
|
||||
{
|
||||
_honorTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)) ? BG_AB_HONOR_TICK_WEEKEND : BG_AB_HONOR_TICK_NORMAL;
|
||||
_reputationTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)) ? BG_AB_REP_TICK_WEEKEND : BG_AB_REP_TICK_NORMAL;
|
||||
|
||||
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
|
||||
{
|
||||
AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + BG_AB_OBJECTS_PER_NODE * i, BG_AB_OBJECTID_NODE_BANNER_0 + i, BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, std::sin(BG_AB_NodePositions[i][3] / 2), cos(BG_AB_NodePositions[i][3] / 2), RESPAWN_ONE_DAY);
|
||||
@ -468,9 +471,6 @@ void BattlegroundAB::Init()
|
||||
|
||||
_bgEvents.Reset();
|
||||
|
||||
_honorTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)) ? BG_AB_HONOR_TICK_WEEKEND : BG_AB_HONOR_TICK_NORMAL;
|
||||
_reputationTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)) ? BG_AB_REP_TICK_WEEKEND : BG_AB_REP_TICK_NORMAL;
|
||||
|
||||
_capturePointInfo[BG_AB_NODE_STABLES]._iconNone = WORLD_STATE_BATTLEGROUND_AB_STABLE_ICON;
|
||||
_capturePointInfo[BG_AB_NODE_FARM]._iconNone = WORLD_STATE_BATTLEGROUND_AB_FARM_ICON;
|
||||
_capturePointInfo[BG_AB_NODE_BLACKSMITH]._iconNone = WORLD_STATE_BATTLEGROUND_AB_BLACKSMITH_ICON;
|
||||
|
||||
@ -166,7 +166,7 @@ enum BG_AB_Misc
|
||||
BG_AB_HONOR_TICK_NORMAL = 260,
|
||||
BG_AB_HONOR_TICK_WEEKEND = 160,
|
||||
BG_AB_REP_TICK_NORMAL = 160,
|
||||
BG_AB_REP_TICK_WEEKEND = 120,
|
||||
BG_AB_REP_TICK_WEEKEND = 150,
|
||||
|
||||
BG_AB_WARNING_NEAR_VICTORY_SCORE = 1400,
|
||||
BG_AB_MAX_TEAM_SCORE = 1600,
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "BattlegroundAV.h"
|
||||
#include "BattlegroundMgr.h"
|
||||
#include "CreatureTextMgr.h"
|
||||
#include "Formulas.h"
|
||||
#include "GameEventMgr.h"
|
||||
@ -56,6 +57,14 @@ BattlegroundAV::BattlegroundAV()
|
||||
|
||||
m_Mine_Timer = 0;
|
||||
|
||||
_reputationTower = 0;
|
||||
_reputationCaptain = 0;
|
||||
_reputationBoss = 0;
|
||||
_reputationPerOwnedGraveyard = 0;
|
||||
_reputationSurvivingCaptain = 0;
|
||||
_reputationSurvivingTower = 0;
|
||||
_reputationPerOwnedMine = 0;
|
||||
|
||||
for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i)
|
||||
InitNode(i, TEAM_NEUTRAL, false);
|
||||
|
||||
@ -93,7 +102,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
|
||||
if (entry == BG_AV_CreatureInfo[AV_NPC_A_BOSS])
|
||||
{
|
||||
CastSpellOnTeam(23658, TEAM_HORDE); //this is a spell which finishes a quest where a player has to kill the boss
|
||||
RewardReputationToTeam(729, BG_AV_REP_BOSS, TEAM_HORDE);
|
||||
RewardReputationToTeam(729, _reputationBoss, TEAM_HORDE);
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), TEAM_HORDE);
|
||||
EndBattleground(TEAM_HORDE);
|
||||
DelCreature(AV_CPLACE_TRIGGER17);
|
||||
@ -101,7 +110,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
|
||||
else if (entry == BG_AV_CreatureInfo[AV_NPC_H_BOSS])
|
||||
{
|
||||
CastSpellOnTeam(23658, TEAM_ALLIANCE); //this is a spell which finishes a quest where a player has to kill the boss
|
||||
RewardReputationToTeam(730, BG_AV_REP_BOSS, TEAM_ALLIANCE);
|
||||
RewardReputationToTeam(730, _reputationBoss, TEAM_ALLIANCE);
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), TEAM_ALLIANCE);
|
||||
EndBattleground(TEAM_ALLIANCE);
|
||||
DelCreature(AV_CPLACE_TRIGGER19);
|
||||
@ -114,7 +123,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
|
||||
return;
|
||||
}
|
||||
m_CaptainAlive[0] = false;
|
||||
RewardReputationToTeam(729, BG_AV_REP_CAPTAIN, TEAM_HORDE);
|
||||
RewardReputationToTeam(729, _reputationCaptain, TEAM_HORDE);
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), TEAM_HORDE);
|
||||
UpdateScore(TEAM_ALLIANCE, (-1)*BG_AV_RES_CAPTAIN);
|
||||
//spawn destroyed aura
|
||||
@ -132,7 +141,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
|
||||
return;
|
||||
}
|
||||
m_CaptainAlive[1] = false;
|
||||
RewardReputationToTeam(730, BG_AV_REP_CAPTAIN, TEAM_ALLIANCE);
|
||||
RewardReputationToTeam(730, _reputationCaptain, TEAM_ALLIANCE);
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), TEAM_ALLIANCE);
|
||||
UpdateScore(TEAM_HORDE, (-1)*BG_AV_RES_CAPTAIN);
|
||||
//spawn destroyed aura
|
||||
@ -174,7 +183,7 @@ void BattlegroundAV::HandleQuestComplete(uint32 questid, Player* player)
|
||||
{
|
||||
LOG_DEBUG("bg.battleground", "BG_AV Quest {} completed starting with unit upgrading..", questid);
|
||||
for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i)
|
||||
if (m_Nodes[i].OwnerId == player->GetTeamId() && m_Nodes[i].State == POINT_CONTROLED)
|
||||
if (m_Nodes[i].OwnerId == player->GetTeamId() && m_Nodes[i].State == POINT_CONTROLLED)
|
||||
{
|
||||
DePopulateNode(i);
|
||||
PopulateNode(i);
|
||||
@ -503,29 +512,49 @@ void BattlegroundAV::EndBattleground(TeamId winnerTeamId)
|
||||
//first towers:
|
||||
uint8 kills[2] = {0, 0}; // 0 = Alliance 1 = Horde
|
||||
uint8 rep[2] = {0, 0}; // 0 = Alliance 1 = Horde
|
||||
|
||||
if (BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)))
|
||||
kills[winnerTeamId] += 4;
|
||||
|
||||
for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i)
|
||||
{
|
||||
if (m_Nodes[i].State == POINT_CONTROLED)
|
||||
if (m_Nodes[i].State == POINT_CONTROLLED)
|
||||
{
|
||||
if (m_Nodes[i].OwnerId == TEAM_ALLIANCE)
|
||||
{
|
||||
rep[0] += BG_AV_REP_SURVIVING_TOWER;
|
||||
kills[0] += BG_AV_KILL_SURVIVING_TOWER;
|
||||
}
|
||||
if (m_Nodes[i].OwnerId == TEAM_NEUTRAL)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
rep[0] += BG_AV_KILL_SURVIVING_TOWER;
|
||||
kills[1] += BG_AV_KILL_SURVIVING_TOWER;
|
||||
rep[m_Nodes[i].OwnerId] += _reputationSurvivingTower;
|
||||
kills[m_Nodes[i].OwnerId] += BG_AV_KILL_SURVIVING_TOWER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i)
|
||||
{
|
||||
if (m_Nodes[i].State == POINT_CONTROLLED)
|
||||
{
|
||||
if (m_Nodes[i].OwnerId == TEAM_NEUTRAL)
|
||||
continue;
|
||||
else
|
||||
rep[m_Nodes[i].OwnerId] += _reputationPerOwnedGraveyard;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 mine = 0; mine < 2; mine++)
|
||||
{
|
||||
if (m_Mine_Owner[mine] == TEAM_NEUTRAL)
|
||||
continue;
|
||||
|
||||
rep[m_Mine_Owner[mine]] += _reputationPerOwnedMine;
|
||||
}
|
||||
|
||||
for (TeamId iTeamId = TEAM_ALLIANCE; iTeamId <= TEAM_HORDE; iTeamId = TeamId(iTeamId + 1))
|
||||
{
|
||||
if (m_CaptainAlive[iTeamId])
|
||||
{
|
||||
kills[iTeamId] += BG_AV_KILL_SURVIVING_CAPTAIN;
|
||||
rep[iTeamId] += BG_AV_REP_SURVIVING_CAPTAIN;
|
||||
rep[iTeamId] += _reputationSurvivingCaptain;
|
||||
}
|
||||
if (rep[iTeamId] != 0)
|
||||
RewardReputationToTeam(iTeamId == TEAM_ALLIANCE ? 730 : 729, rep[iTeamId], iTeamId);
|
||||
@ -629,7 +658,7 @@ void BattlegroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node)
|
||||
SpawnBGObject(BG_AV_OBJECT_BURN_DUNBALDAR_SOUTH + i + (tmp * 10), RESPAWN_IMMEDIATELY);
|
||||
|
||||
UpdateScore((ownerId == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE, -1 * BG_AV_RES_TOWER);
|
||||
RewardReputationToTeam(ownerId == TEAM_ALLIANCE ? 730 : 729, BG_AV_REP_TOWER, ownerId);
|
||||
RewardReputationToTeam(ownerId == TEAM_ALLIANCE ? 730 : 729, _reputationTower, ownerId);
|
||||
RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_TOWER), ownerId);
|
||||
|
||||
SpawnBGObject(static_cast<uint8>(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH) + ownerId + (2 * tmp), RESPAWN_ONE_DAY);
|
||||
@ -863,7 +892,7 @@ uint32 BattlegroundAV::GetObjectThroughNode(BG_AV_Nodes node)
|
||||
if (node >= BG_AV_NODES_ICEBLOOD_TOWER && node <= BG_AV_NODES_FROSTWOLF_WTOWER)
|
||||
return node + 7;
|
||||
}
|
||||
else if (m_Nodes[node].State == POINT_CONTROLED)
|
||||
else if (m_Nodes[node].State == POINT_CONTROLLED)
|
||||
if (node <= BG_AV_NODES_STONEHEART_BUNKER)
|
||||
return node;
|
||||
}
|
||||
@ -874,7 +903,7 @@ uint32 BattlegroundAV::GetObjectThroughNode(BG_AV_Nodes node)
|
||||
if (node <= BG_AV_NODES_STONEHEART_BUNKER)
|
||||
return node + 22;
|
||||
}
|
||||
else if (m_Nodes[node].State == POINT_CONTROLED)
|
||||
else if (m_Nodes[node].State == POINT_CONTROLLED)
|
||||
{
|
||||
if (node <= BG_AV_NODES_FROSTWOLF_HUT)
|
||||
return node + 33;
|
||||
@ -1010,7 +1039,7 @@ void BattlegroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object)
|
||||
}
|
||||
else if (m_Nodes[node].TotalOwnerId == TEAM_NEUTRAL) //recapping, when no team owns this node realy
|
||||
{
|
||||
if (!(m_Nodes[node].State != POINT_CONTROLED))
|
||||
if (!(m_Nodes[node].State != POINT_CONTROLLED))
|
||||
return;
|
||||
|
||||
if (teamId == TEAM_ALLIANCE)
|
||||
@ -1138,14 +1167,14 @@ uint8 BattlegroundAV::GetWorldStateType(uint8 state, TeamId teamId) //this is us
|
||||
//a_c a_a h_c h_a the positions in worldstate-array
|
||||
if (teamId == TEAM_ALLIANCE)
|
||||
{
|
||||
if (state == POINT_CONTROLED || state == POINT_DESTROYED)
|
||||
if (state == POINT_CONTROLLED || state == POINT_DESTROYED)
|
||||
return 0;
|
||||
if (state == POINT_ASSAULTED)
|
||||
return 1;
|
||||
}
|
||||
if (teamId == TEAM_HORDE)
|
||||
{
|
||||
if (state == POINT_DESTROYED || state == POINT_CONTROLED)
|
||||
if (state == POINT_DESTROYED || state == POINT_CONTROLLED)
|
||||
return 2;
|
||||
if (state == POINT_ASSAULTED)
|
||||
return 3;
|
||||
@ -1193,7 +1222,7 @@ GraveyardStruct const* BattlegroundAV::GetClosestGraveyard(Player* player)
|
||||
minDist = (pGraveyard->x - x) * (pGraveyard->x - x) + (pGraveyard->y - y) * (pGraveyard->y - y);
|
||||
|
||||
for (uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i)
|
||||
if (m_Nodes[i].OwnerId == player->GetTeamId() && m_Nodes[i].State == POINT_CONTROLED)
|
||||
if (m_Nodes[i].OwnerId == player->GetTeamId() && m_Nodes[i].State == POINT_CONTROLLED)
|
||||
{
|
||||
entry = sGraveyard->GetGraveyard(BG_AV_GraveyardIds[i]);
|
||||
if (entry)
|
||||
@ -1211,6 +1240,27 @@ GraveyardStruct const* BattlegroundAV::GetClosestGraveyard(Player* player)
|
||||
|
||||
bool BattlegroundAV::SetupBattleground()
|
||||
{
|
||||
if (sBattlegroundMgr->IsBGWeekend(GetBgTypeID(true)))
|
||||
{
|
||||
_reputationTower = 18;
|
||||
_reputationCaptain = 185;
|
||||
_reputationBoss = 525;
|
||||
_reputationPerOwnedGraveyard = 18;
|
||||
_reputationSurvivingCaptain = 175;
|
||||
_reputationSurvivingTower = 18;
|
||||
_reputationPerOwnedMine = 36;
|
||||
}
|
||||
else
|
||||
{
|
||||
_reputationTower = 12;
|
||||
_reputationCaptain = 125;
|
||||
_reputationBoss = sWorld->getIntConfig(CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH);
|
||||
_reputationPerOwnedGraveyard = 12;
|
||||
_reputationSurvivingCaptain = 125;
|
||||
_reputationSurvivingTower = 12;
|
||||
_reputationPerOwnedMine = 24;
|
||||
}
|
||||
|
||||
// Create starting objects
|
||||
|
||||
//spawn node-objects
|
||||
@ -1735,7 +1785,7 @@ void BattlegroundAV::DestroyNode(BG_AV_Nodes node)
|
||||
m_Nodes[node].TotalOwnerId = m_Nodes[node].OwnerId;
|
||||
m_Nodes[node].PrevOwnerId = m_Nodes[node].OwnerId;
|
||||
m_Nodes[node].PrevState = m_Nodes[node].State;
|
||||
m_Nodes[node].State = (m_Nodes[node].Tower) ? POINT_DESTROYED : POINT_CONTROLED;
|
||||
m_Nodes[node].State = (m_Nodes[node].Tower) ? POINT_DESTROYED : POINT_CONTROLLED;
|
||||
m_Nodes[node].Timer = 0;
|
||||
}
|
||||
|
||||
@ -1744,7 +1794,7 @@ void BattlegroundAV::InitNode(BG_AV_Nodes node, TeamId teamId, bool tower)
|
||||
m_Nodes[node].TotalOwnerId = teamId;
|
||||
m_Nodes[node].OwnerId = teamId;
|
||||
m_Nodes[node].PrevOwnerId = TEAM_NEUTRAL;
|
||||
m_Nodes[node].State = POINT_CONTROLED;
|
||||
m_Nodes[node].State = POINT_CONTROLLED;
|
||||
m_Nodes[node].PrevState = m_Nodes[node].State;
|
||||
m_Nodes[node].Timer = 0;
|
||||
m_Nodes[node].Tower = tower;
|
||||
@ -1754,11 +1804,11 @@ void BattlegroundAV::DefendNode(BG_AV_Nodes node, TeamId teamId)
|
||||
{
|
||||
ASSERT(m_Nodes[node].TotalOwnerId == teamId);
|
||||
ASSERT(m_Nodes[node].OwnerId != teamId);
|
||||
ASSERT(m_Nodes[node].State != POINT_CONTROLED && m_Nodes[node].State != POINT_DESTROYED);
|
||||
ASSERT(m_Nodes[node].State != POINT_CONTROLLED && m_Nodes[node].State != POINT_DESTROYED);
|
||||
m_Nodes[node].PrevOwnerId = m_Nodes[node].OwnerId;
|
||||
m_Nodes[node].OwnerId = teamId;
|
||||
m_Nodes[node].PrevState = m_Nodes[node].State;
|
||||
m_Nodes[node].State = POINT_CONTROLED;
|
||||
m_Nodes[node].State = POINT_CONTROLLED;
|
||||
m_Nodes[node].Timer = 0;
|
||||
}
|
||||
|
||||
@ -1805,7 +1855,7 @@ bool BattlegroundAV::IsAllTowersControlledAndCaptainAlive(TeamId teamId) const
|
||||
{
|
||||
for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) // alliance towers controlled
|
||||
{
|
||||
if (m_Nodes[i].State == POINT_CONTROLED)
|
||||
if (m_Nodes[i].State == POINT_CONTROLLED)
|
||||
{
|
||||
if (m_Nodes[i].OwnerId != TEAM_ALLIANCE)
|
||||
return false;
|
||||
@ -1824,7 +1874,7 @@ bool BattlegroundAV::IsAllTowersControlledAndCaptainAlive(TeamId teamId) const
|
||||
{
|
||||
for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) // horde towers controlled
|
||||
{
|
||||
if (m_Nodes[i].State == POINT_CONTROLED)
|
||||
if (m_Nodes[i].State == POINT_CONTROLLED)
|
||||
{
|
||||
if (m_Nodes[i].OwnerId != TEAM_HORDE)
|
||||
return false;
|
||||
|
||||
@ -29,23 +29,18 @@
|
||||
#define SEND_MSG_NEAR_LOSE 120
|
||||
|
||||
#define BG_AV_KILL_BOSS 4
|
||||
#define BG_AV_REP_BOSS (sWorld->getIntConfig(CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH)) // Blizzlike default is 350
|
||||
|
||||
#define BG_AV_KILL_CAPTAIN 3
|
||||
#define BG_AV_REP_CAPTAIN 125
|
||||
#define BG_AV_RES_CAPTAIN 100
|
||||
|
||||
#define BG_AV_KILL_TOWER 3
|
||||
#define BG_AV_REP_TOWER 12
|
||||
#define BG_AV_RES_TOWER 75
|
||||
|
||||
#define BG_AV_GET_COMMANDER 1 //for a safely returned wingcommander
|
||||
//bonushonor at the end
|
||||
#define BG_AV_KILL_SURVIVING_TOWER 2
|
||||
#define BG_AV_REP_SURVIVING_TOWER 12
|
||||
|
||||
#define BG_AV_KILL_SURVIVING_CAPTAIN 2
|
||||
#define BG_AV_REP_SURVIVING_CAPTAIN 125
|
||||
|
||||
#define AV_EVENT_START_BATTLE 9166 // Achievement: The Alterac Blitz
|
||||
|
||||
@ -1546,7 +1541,7 @@ enum BG_AV_States
|
||||
POINT_NEUTRAL = 0,
|
||||
POINT_ASSAULTED = 1,
|
||||
POINT_DESTROYED = 2,
|
||||
POINT_CONTROLED = 3
|
||||
POINT_CONTROLLED = 3
|
||||
};
|
||||
|
||||
//alliance_control neutral_control horde_control
|
||||
@ -1844,6 +1839,14 @@ private:
|
||||
uint32 m_CaptainBuffTimer[2] {};
|
||||
bool m_CaptainAlive[2] {};
|
||||
|
||||
uint32 _reputationTower = 0; // 12, 18
|
||||
uint32 _reputationCaptain = 0; // 125, 185
|
||||
uint32 _reputationBoss = 0; // 350, 525
|
||||
uint32 _reputationPerOwnedGraveyard = 0; // 12, 18
|
||||
uint32 _reputationSurvivingCaptain = 0; // 125, 175
|
||||
uint32 _reputationSurvivingTower = 0; // 12, 18
|
||||
uint32 _reputationPerOwnedMine = 0; // 24, 36
|
||||
|
||||
bool m_IsInformedNearVictory[2] {};
|
||||
};
|
||||
|
||||
|
||||
@ -263,6 +263,8 @@ void BattlegroundEY::HandleAreaTrigger(Player* player, uint32 trigger)
|
||||
|
||||
bool BattlegroundEY::SetupBattleground()
|
||||
{
|
||||
_honorTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)) ? BG_EY_HONOR_TICK_WEEKEND : BG_EY_HONOR_TICK_NORMAL;
|
||||
|
||||
// doors
|
||||
AddObject(BG_EY_OBJECT_DOOR_A, BG_OBJECT_A_DOOR_EY_ENTRY, 2527.6f, 1596.91f, 1262.13f, -3.12414f, -0.173642f, -0.001515f, 0.98477f, -0.008594f, RESPAWN_IMMEDIATELY);
|
||||
AddObject(BG_EY_OBJECT_DOOR_H, BG_OBJECT_H_DOOR_EY_ENTRY, 1803.21f, 1539.49f, 1261.09f, 3.14159f, 0.173648f, 0, 0.984808f, 0, RESPAWN_IMMEDIATELY);
|
||||
@ -355,7 +357,6 @@ void BattlegroundEY::Init()
|
||||
Battleground::Init();
|
||||
|
||||
_bgEvents.Reset();
|
||||
_honorTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID(true)) ? BG_EY_HONOR_TICK_WEEKEND : BG_EY_HONOR_TICK_NORMAL;
|
||||
_ownedPointsCount[TEAM_ALLIANCE] = 0;
|
||||
_ownedPointsCount[TEAM_HORDE] = 0;
|
||||
_flagKeeperGUID.Clear();
|
||||
|
||||
@ -426,6 +426,19 @@ void BattlegroundWS::HandleAreaTrigger(Player* player, uint32 trigger)
|
||||
|
||||
bool BattlegroundWS::SetupBattleground()
|
||||
{
|
||||
if (sBattlegroundMgr->IsBGWeekend(GetBgTypeID(true)))
|
||||
{
|
||||
_reputationCapture = 45;
|
||||
_honorWinKills = 3;
|
||||
_honorEndKills = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
_reputationCapture = 35;
|
||||
_honorWinKills = 1;
|
||||
_honorEndKills = 2;
|
||||
}
|
||||
|
||||
// flags
|
||||
AddObject(BG_WS_OBJECT_A_FLAG, BG_OBJECT_A_FLAG_WS_ENTRY, 1540.423f, 1481.325f, 351.8284f, 3.089233f, 0, 0, 0.9996573f, 0.02617699f, RESPAWN_IMMEDIATELY);
|
||||
AddObject(BG_WS_OBJECT_H_FLAG, BG_OBJECT_H_FLAG_WS_ENTRY, 916.0226f, 1434.405f, 345.413f, 0.01745329f, 0, 0, 0.008726535f, 0.9999619f, RESPAWN_IMMEDIATELY);
|
||||
@ -486,19 +499,6 @@ void BattlegroundWS::Init()
|
||||
_flagState[TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE;
|
||||
_lastFlagCaptureTeam = TEAM_NEUTRAL;
|
||||
|
||||
if (sBattlegroundMgr->IsBGWeekend(GetBgTypeID(true)))
|
||||
{
|
||||
_reputationCapture = 45;
|
||||
_honorWinKills = 3;
|
||||
_honorEndKills = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
_reputationCapture = 35;
|
||||
_honorWinKills = 1;
|
||||
_honorEndKills = 2;
|
||||
}
|
||||
|
||||
uint32 bgWarsongFlagsConfig = sWorld->getIntConfig(CONFIG_BATTLEGROUND_WARSONG_FLAGS);
|
||||
_configurableMaxTeamScore = bgWarsongFlagsConfig > 0
|
||||
? bgWarsongFlagsConfig
|
||||
|
||||
@ -1496,10 +1496,6 @@ namespace lfg
|
||||
{
|
||||
uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids
|
||||
|
||||
// Skip faction-specific locks if cross-faction is enabled
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && (it2->second == LFG_LOCKSTATUS_QUEST_NOT_COMPLETED || it2->second == LFG_LOCKSTATUS_MISSING_ITEM))
|
||||
continue;
|
||||
|
||||
LfgDungeonSet::iterator itDungeon = dungeons.find(dungeonId);
|
||||
if (itDungeon != dungeons.end())
|
||||
{
|
||||
@ -2687,24 +2683,17 @@ namespace lfg
|
||||
LFGQueue& LFGMgr::GetQueue(ObjectGuid guid)
|
||||
{
|
||||
uint8 queueId = 0;
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
if (guid.IsGroup())
|
||||
{
|
||||
queueId = TEAM_ALLIANCE;
|
||||
LfgGuidSet const& players = GetPlayers(guid);
|
||||
ObjectGuid pguid = players.empty() ? ObjectGuid::Empty : (*players.begin());
|
||||
if (pguid)
|
||||
queueId = GetTeam(pguid);
|
||||
else
|
||||
queueId = GetTeam(GetLeader(guid));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (guid.IsGroup())
|
||||
{
|
||||
LfgGuidSet const& players = GetPlayers(guid);
|
||||
ObjectGuid pguid = players.empty() ? ObjectGuid::Empty : (*players.begin());
|
||||
if (pguid)
|
||||
queueId = GetTeam(pguid);
|
||||
else
|
||||
queueId = GetTeam(GetLeader(guid));
|
||||
}
|
||||
else
|
||||
queueId = GetTeam(guid);
|
||||
}
|
||||
queueId = GetTeam(guid);
|
||||
return QueuesStore[queueId];
|
||||
}
|
||||
|
||||
|
||||
@ -2772,11 +2772,7 @@ bool Creature::LoadCreaturesAddon(bool reload)
|
||||
|
||||
//Load Path
|
||||
if (cainfo->path_id != 0)
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_SET_ALL_CREATURES_WITH_WAYPOINT_MOVEMENT_ACTIVE))
|
||||
setActive(true);
|
||||
m_path_id = cainfo->path_id;
|
||||
}
|
||||
|
||||
if (!cainfo->auras.empty())
|
||||
{
|
||||
@ -3896,3 +3892,27 @@ std::string Creature::GetDebugInfo() const
|
||||
<< " WaypointPath: " << GetWaypointPath() << " SpawnId: " << GetSpawnId();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
// Note: This is called in a tight (heavy) loop, is it critical that all checks are FAST and are hopefully only simple conditionals.
|
||||
bool Creature::IsUpdateNeeded()
|
||||
{
|
||||
if (WorldObject::IsUpdateNeeded())
|
||||
return true;
|
||||
|
||||
if (GetMap()->isCellMarked(GetCurrentCell().GetCellCoord().GetId()))
|
||||
return true;
|
||||
|
||||
if (IsInCombat())
|
||||
return true;
|
||||
|
||||
if (IsVisibilityOverridden())
|
||||
return true;
|
||||
|
||||
if (GetMotionMaster()->HasMovementGeneratorType(WAYPOINT_MOTION_TYPE))
|
||||
return true;
|
||||
|
||||
if (HasUnitState(UNIT_STATE_EVADE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ class CreatureGroup;
|
||||
|
||||
#define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY
|
||||
|
||||
class Creature : public Unit, public GridObject<Creature>, public MovableMapObject
|
||||
class Creature : public Unit, public GridObject<Creature>, public MovableMapObject, public UpdatableMapObject
|
||||
{
|
||||
public:
|
||||
explicit Creature(bool isWorldObject = false);
|
||||
@ -436,6 +436,8 @@ public:
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
bool IsUpdateNeeded() override;
|
||||
|
||||
protected:
|
||||
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 Entry, uint32 vehId, const CreatureData* data = nullptr);
|
||||
bool InitEntry(uint32 entry, const CreatureData* data = nullptr);
|
||||
|
||||
@ -31,7 +31,7 @@ enum DynamicObjectType
|
||||
DYNAMIC_OBJECT_FARSIGHT_FOCUS = 0x2,
|
||||
};
|
||||
|
||||
class DynamicObject : public WorldObject, public GridObject<DynamicObject>, public MovableMapObject
|
||||
class DynamicObject : public WorldObject, public GridObject<DynamicObject>, public MovableMapObject, public UpdatableMapObject
|
||||
{
|
||||
public:
|
||||
DynamicObject(bool isWorldObject);
|
||||
|
||||
@ -3076,3 +3076,21 @@ std::string GameObject::GetDebugInfo() const
|
||||
<< "SpawnId: " << GetSpawnId() << " GoState: " << std::to_string(GetGoState()) << " ScriptId: " << GetScriptId() << " AIName: " << GetAIName();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
// Note: This is called in a tight (heavy) loop, is it critical that all checks are FAST and are hopefully only simple conditionals.
|
||||
bool GameObject::IsUpdateNeeded()
|
||||
{
|
||||
if (WorldObject::IsUpdateNeeded())
|
||||
return true;
|
||||
|
||||
if (GetMap()->isCellMarked(GetCurrentCell().GetCellCoord().GetId()))
|
||||
return true;
|
||||
|
||||
if (IsVisibilityOverridden())
|
||||
return true;
|
||||
|
||||
if (IsTransport())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -116,7 +116,7 @@ enum LootState
|
||||
// 5 sec for bobber catch
|
||||
#define FISHING_BOBBER_READY_TIME 5
|
||||
|
||||
class GameObject : public WorldObject, public GridObject<GameObject>, public MovableMapObject
|
||||
class GameObject : public WorldObject, public GridObject<GameObject>, public MovableMapObject, public UpdatableMapObject
|
||||
{
|
||||
public:
|
||||
explicit GameObject();
|
||||
@ -362,6 +362,8 @@ public:
|
||||
void SaveStateToDB();
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
bool IsUpdateNeeded() override;
|
||||
protected:
|
||||
bool AIM_Initialize();
|
||||
GameObjectModel* CreateModel();
|
||||
|
||||
@ -1188,6 +1188,7 @@ void WorldObject::AddToWorld()
|
||||
{
|
||||
Object::AddToWorld();
|
||||
GetMap()->GetZoneAndAreaId(GetPhaseMask(), _zoneId, _areaId, GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
GetMap()->AddObjectToPendingUpdateList(this);
|
||||
}
|
||||
|
||||
void WorldObject::RemoveFromWorld()
|
||||
@ -3220,3 +3221,27 @@ void WorldObject::RemoveAllowedLooter(ObjectGuid guid)
|
||||
{
|
||||
_allowedLooters.erase(guid);
|
||||
}
|
||||
|
||||
bool WorldObject::IsUpdateNeeded()
|
||||
{
|
||||
if (isActiveObject())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WorldObject::CanBeAddedToMapUpdateList()
|
||||
{
|
||||
switch (GetTypeId())
|
||||
{
|
||||
case TYPEID_UNIT:
|
||||
return IsCreature();
|
||||
case TYPEID_DYNAMICOBJECT:
|
||||
case TYPEID_GAMEOBJECT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -230,6 +230,12 @@ public:
|
||||
|
||||
DataMap CustomData;
|
||||
|
||||
template<typename... T>
|
||||
[[nodiscard]] bool EntryEquals(T... entries) const
|
||||
{
|
||||
return ((GetEntry() == entries) || ...);
|
||||
}
|
||||
|
||||
protected:
|
||||
Object();
|
||||
|
||||
@ -399,14 +405,58 @@ class MovableMapObject
|
||||
protected:
|
||||
MovableMapObject() = default;
|
||||
|
||||
private:
|
||||
[[nodiscard]] Cell const& GetCurrentCell() const { return _currentCell; }
|
||||
|
||||
private:
|
||||
void SetCurrentCell(Cell const& cell) { _currentCell = cell; }
|
||||
|
||||
Cell _currentCell;
|
||||
MapObjectCellMoveState _moveState{MAP_OBJECT_CELL_MOVE_NONE};
|
||||
};
|
||||
|
||||
class UpdatableMapObject
|
||||
{
|
||||
friend class Map;
|
||||
|
||||
public:
|
||||
enum UpdateState : uint8
|
||||
{
|
||||
NotUpdating,
|
||||
PendingAdd,
|
||||
Updating
|
||||
};
|
||||
|
||||
protected:
|
||||
UpdatableMapObject() : _mapUpdateListOffset(0), _mapUpdateState(NotUpdating) { }
|
||||
|
||||
private:
|
||||
void SetMapUpdateListOffset(std::size_t const offset)
|
||||
{
|
||||
ASSERT(_mapUpdateState == Updating, "Attempted to set update list offset when object is not in map update list");
|
||||
_mapUpdateListOffset = offset;
|
||||
}
|
||||
|
||||
size_t GetMapUpdateListOffset() const
|
||||
{
|
||||
ASSERT(_mapUpdateState == Updating, "Attempted to get update list offset when object is not in map update list");
|
||||
return _mapUpdateListOffset;
|
||||
}
|
||||
|
||||
void SetUpdateState(UpdateState state)
|
||||
{
|
||||
_mapUpdateState = state;
|
||||
}
|
||||
|
||||
UpdateState GetUpdateState() const
|
||||
{
|
||||
return _mapUpdateState;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t _mapUpdateListOffset;
|
||||
UpdateState _mapUpdateState;
|
||||
};
|
||||
|
||||
class WorldObject : public Object, public WorldLocation
|
||||
{
|
||||
protected:
|
||||
@ -633,6 +683,9 @@ public:
|
||||
[[nodiscard]] GuidUnorderedSet const& GetAllowedLooters() const;
|
||||
void RemoveAllowedLooter(ObjectGuid guid);
|
||||
|
||||
virtual bool IsUpdateNeeded();
|
||||
bool CanBeAddedToMapUpdateList();
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
// Event handler
|
||||
|
||||
@ -1683,6 +1683,8 @@ template <class T>
|
||||
void Player::UpdateVisibilityOf(T* target, UpdateData& data,
|
||||
std::vector<Unit*>& visibleNow)
|
||||
{
|
||||
GetMap()->AddObjectToPendingUpdateList(target);
|
||||
|
||||
if (HaveAtClient(target))
|
||||
{
|
||||
if (!CanSeeOrDetect(target, false, true))
|
||||
|
||||
@ -13730,7 +13730,7 @@ void Unit::CombatStart(Unit* victim, bool initialAggro)
|
||||
victim->SetInCombatWith(this);
|
||||
|
||||
// Update leash timer when attacking creatures
|
||||
if (victim->IsCreature())
|
||||
if (victim->IsCreature() && this != victim)
|
||||
victim->ToCreature()->UpdateLeashExtensionTime();
|
||||
|
||||
// Xinef: If pet started combat - put owner in combat
|
||||
|
||||
@ -116,6 +116,9 @@ void GridObjectUnloader::Visit(GridRefMgr<T>& m)
|
||||
//Example: Flame Leviathan Turret 33139 is summoned when a creature is deleted
|
||||
//TODO: Check if that script has the correct logic. Do we really need to summons something before deleting?
|
||||
obj->CleanupsBeforeDelete();
|
||||
|
||||
obj->GetMap()->RemoveObjectFromMapUpdateList(obj);
|
||||
|
||||
///- object will get delinked from the manager when deleted
|
||||
delete obj;
|
||||
}
|
||||
|
||||
@ -354,19 +354,6 @@ void MessageDistDelivererToHostile::Visit(DynamicObjectMapType& m)
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ObjectUpdater::Visit(GridRefMgr<T>& m)
|
||||
{
|
||||
T* obj;
|
||||
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); )
|
||||
{
|
||||
obj = iter->GetSource();
|
||||
++iter;
|
||||
if (obj->IsInWorld() && (i_largeOnly == obj->IsVisibilityOverridden()))
|
||||
obj->Update(i_timeDiff);
|
||||
}
|
||||
}
|
||||
|
||||
bool AnyDeadUnitObjectInRangeCheck::operator()(Player* u)
|
||||
{
|
||||
return !u->IsAlive() && !u->HasGhostAura() && i_searchObj->IsWithinDistInMap(u, i_range);
|
||||
@ -396,7 +383,3 @@ bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Creature* u)
|
||||
{
|
||||
return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u);
|
||||
}
|
||||
|
||||
template void ObjectUpdater::Visit<Creature>(CreatureMapType&);
|
||||
template void ObjectUpdater::Visit<GameObject>(GameObjectMapType&);
|
||||
template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType&);
|
||||
|
||||
@ -154,16 +154,6 @@ namespace Acore
|
||||
}
|
||||
};
|
||||
|
||||
struct ObjectUpdater
|
||||
{
|
||||
uint32 i_timeDiff;
|
||||
bool i_largeOnly;
|
||||
explicit ObjectUpdater(const uint32 diff, bool largeOnly) : i_timeDiff(diff), i_largeOnly(largeOnly) {}
|
||||
template<class T> void Visit(GridRefMgr<T>& m);
|
||||
void Visit(PlayerMapType&) {}
|
||||
void Visit(CorpseMapType&) {}
|
||||
};
|
||||
|
||||
// SEARCHERS & LIST SEARCHERS & WORKERS
|
||||
|
||||
// WorldObject searchers & workers
|
||||
|
||||
@ -51,7 +51,7 @@ void GroupMgr::InitGroupIds()
|
||||
}
|
||||
}
|
||||
|
||||
void GroupMgr::RegisterGroupId(uint32 groupId)
|
||||
void GroupMgr::RegisterGroupId(ObjectGuid::LowType groupId)
|
||||
{
|
||||
// Allocation was done in InitGroupIds()
|
||||
_groupIds[groupId] = true;
|
||||
|
||||
@ -385,7 +385,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
|
||||
bool senderIsPlayer = AccountMgr::IsPlayerAccount(GetSecurity());
|
||||
bool receiverIsPlayer = AccountMgr::IsPlayerAccount(receiver ? receiver->GetSession()->GetSecurity() : SEC_PLAYER);
|
||||
|
||||
if (sender->GetLevel() < sWorld->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ) && receiver != sender)
|
||||
if (sender->GetLevel() < sWorld->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ) && receiver != sender && receiver && !receiver->IsGameMaster())
|
||||
{
|
||||
ChatHandler(this).SendNotification(LANG_WHISPER_REQ, sWorld->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ));
|
||||
return;
|
||||
|
||||
@ -80,6 +80,7 @@ Map::Map(uint32 id, uint32 InstanceId, uint8 SpawnMode, Map* _parent) :
|
||||
m_parentMap = (_parent ? _parent : this);
|
||||
|
||||
_zonePlayerCountMap.clear();
|
||||
_updatableObjectListRecheckTimer.SetInterval(UPDATABLE_OBJECT_LIST_RECHECK_TIMER);
|
||||
|
||||
//lets initialize visibility distance for map
|
||||
Map::InitVisibilityDistance();
|
||||
@ -492,45 +493,7 @@ bool Map::AddToMap(MotionTransport* obj, bool /*checkTransport*/)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Map::VisitNearbyCellsOfPlayer(Player* player, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor)
|
||||
{
|
||||
// check for valid position
|
||||
if (!player->IsPositionValid())
|
||||
return;
|
||||
|
||||
// check normal grid activation range of the player
|
||||
VisitNearbyCellsOf(player, gridVisitor, worldVisitor, largeGridVisitor, largeWorldVisitor);
|
||||
|
||||
// check maximum visibility distance for large creatures
|
||||
CellArea area = Cell::CalculateCellArea(player->GetPositionX(), player->GetPositionY(), MAX_VISIBILITY_DISTANCE);
|
||||
|
||||
for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
|
||||
{
|
||||
for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
|
||||
{
|
||||
// marked cells are those that have been visited
|
||||
// don't visit the same cell twice
|
||||
uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
|
||||
if (isCellMarkedLarge(cell_id))
|
||||
continue;
|
||||
|
||||
markCellLarge(cell_id);
|
||||
CellCoord pair(x, y);
|
||||
Cell cell(pair);
|
||||
|
||||
Visit(cell, largeGridVisitor);
|
||||
Visit(cell, largeWorldVisitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor)
|
||||
void Map::MarkNearbyCellsOf(WorldObject* obj)
|
||||
{
|
||||
// Check for valid position
|
||||
if (!obj->IsPositionValid())
|
||||
@ -538,30 +501,13 @@ void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Acore::Objec
|
||||
|
||||
// Update mobs/objects in ALL visible cells around object!
|
||||
CellArea area = Cell::CalculateCellArea(obj->GetPositionX(), obj->GetPositionY(), obj->GetGridActivationRange());
|
||||
|
||||
for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
|
||||
{
|
||||
for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
|
||||
{
|
||||
// marked cells are those that have been visited
|
||||
// don't visit the same cell twice
|
||||
uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
|
||||
if (isCellMarked(cell_id))
|
||||
continue;
|
||||
|
||||
markCell(cell_id);
|
||||
CellCoord pair(x, y);
|
||||
Cell cell(pair);
|
||||
|
||||
Visit(cell, gridVisitor);
|
||||
Visit(cell, worldVisitor);
|
||||
|
||||
if (!isCellMarkedLarge(cell_id))
|
||||
{
|
||||
markCellLarge(cell_id);
|
||||
Visit(cell, largeGridVisitor);
|
||||
Visit(cell, largeWorldVisitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -613,39 +559,10 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
return;
|
||||
}
|
||||
|
||||
/// update active cells around players and active objects
|
||||
_updatableObjectListRecheckTimer.Update(t_diff);
|
||||
resetMarkedCells();
|
||||
resetMarkedCellsLarge();
|
||||
|
||||
// Prepare object updaters
|
||||
Acore::ObjectUpdater updater(t_diff, false);
|
||||
|
||||
// For creature
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer> grid_object_update(updater);
|
||||
|
||||
// For pets
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer> world_object_update(updater);
|
||||
|
||||
// For large creatures
|
||||
Acore::ObjectUpdater largeObjectUpdater(t_diff, true);
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer> grid_large_object_update(largeObjectUpdater);
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer> world_large_object_update(largeObjectUpdater);
|
||||
|
||||
// pussywizard: container for far creatures in combat with players
|
||||
std::vector<Creature*> updateList;
|
||||
updateList.reserve(10);
|
||||
|
||||
// Update non-player active objects
|
||||
for (m_activeNonPlayersIter = m_activeNonPlayers.begin(); m_activeNonPlayersIter != m_activeNonPlayers.end();)
|
||||
{
|
||||
WorldObject* obj = *m_activeNonPlayersIter;
|
||||
++m_activeNonPlayersIter;
|
||||
|
||||
if (obj && obj->IsInWorld())
|
||||
VisitNearbyCellsOf(obj, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
|
||||
// Update players and their associated objects
|
||||
// Update players
|
||||
for (m_mapRefIter = m_mapRefMgr.begin(); m_mapRefIter != m_mapRefMgr.end(); ++m_mapRefIter)
|
||||
{
|
||||
Player* player = m_mapRefIter->GetSource();
|
||||
@ -654,53 +571,37 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
continue;
|
||||
|
||||
player->Update(s_diff);
|
||||
VisitNearbyCellsOfPlayer(player, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
|
||||
// If player is using far sight, update viewpoint
|
||||
if (WorldObject* viewPoint = player->GetViewpoint())
|
||||
if (_updatableObjectListRecheckTimer.Passed())
|
||||
{
|
||||
if (Creature* viewCreature = viewPoint->ToCreature())
|
||||
{
|
||||
VisitNearbyCellsOf(viewCreature, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
else if (DynamicObject* viewObject = viewPoint->ToDynObject())
|
||||
{
|
||||
VisitNearbyCellsOf(viewObject, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
}
|
||||
MarkNearbyCellsOf(player);
|
||||
|
||||
// handle updates for creatures in combat with player and are more than X yards away
|
||||
if (player->IsInCombat())
|
||||
{
|
||||
updateList.clear();
|
||||
float rangeSq = player->GetGridActivationRange() - 1.0f;
|
||||
rangeSq *= rangeSq;
|
||||
|
||||
HostileReference* ref = player->getHostileRefMgr().getFirst();
|
||||
while (ref)
|
||||
// If player is using far sight, update viewpoint
|
||||
if (WorldObject* viewPoint = player->GetViewpoint())
|
||||
{
|
||||
if (Unit* unit = ref->GetSource()->GetOwner())
|
||||
if (Creature* cre = unit->ToCreature())
|
||||
if (cre->FindMap() == player->FindMap() && cre->GetExactDist2dSq(player) > rangeSq)
|
||||
updateList.push_back(cre);
|
||||
ref = ref->next();
|
||||
if (Creature* viewCreature = viewPoint->ToCreature())
|
||||
MarkNearbyCellsOf(viewCreature);
|
||||
else if (DynamicObject* viewObject = viewPoint->ToDynObject())
|
||||
MarkNearbyCellsOf(viewObject);
|
||||
}
|
||||
|
||||
for (Creature* cre : updateList)
|
||||
VisitNearbyCellsOf(cre, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
}
|
||||
|
||||
// Update transports - pussywizard: transports updated after VisitNearbyCellsOf, grids around are loaded, everything ok
|
||||
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
|
||||
if (_updatableObjectListRecheckTimer.Passed())
|
||||
{
|
||||
MotionTransport* transport = *_transportsUpdateIter;
|
||||
++_transportsUpdateIter;
|
||||
// Mark all cells near active objects
|
||||
for (m_activeNonPlayersIter = m_activeNonPlayers.begin(); m_activeNonPlayersIter != m_activeNonPlayers.end(); ++m_activeNonPlayersIter)
|
||||
{
|
||||
WorldObject* obj = *m_activeNonPlayersIter;
|
||||
if (!obj || !obj->IsInWorld())
|
||||
continue;
|
||||
|
||||
if (transport->IsInWorld())
|
||||
transport->Update(t_diff);
|
||||
MarkNearbyCellsOf(obj);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateNonPlayerObjects(t_diff);
|
||||
|
||||
SendObjectUpdates();
|
||||
|
||||
///- Process necessary scripts
|
||||
@ -728,6 +629,101 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
METRIC_TAG("map_instanceid", std::to_string(GetInstanceId())));
|
||||
}
|
||||
|
||||
void Map::UpdateNonPlayerObjects(uint32 const diff)
|
||||
{
|
||||
for (WorldObject* obj : _pendingAddUpdatableObjectList)
|
||||
_AddObjectToUpdateList(obj);
|
||||
_pendingAddUpdatableObjectList.clear();
|
||||
|
||||
if (_updatableObjectListRecheckTimer.Passed())
|
||||
{
|
||||
for (uint32 i = 0; i < _updatableObjectList.size();)
|
||||
{
|
||||
WorldObject* obj = _updatableObjectList[i];
|
||||
if (!obj->IsInWorld())
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
obj->Update(diff);
|
||||
|
||||
if (!obj->IsUpdateNeeded())
|
||||
{
|
||||
_RemoveObjectFromUpdateList(obj);
|
||||
// Intentional no iteration here, obj is swapped with last element in
|
||||
// _updatableObjectList so next loop will update that object at the same index
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
_updatableObjectListRecheckTimer.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32 i = 0; i < _updatableObjectList.size(); ++i)
|
||||
{
|
||||
WorldObject* obj = _updatableObjectList[i];
|
||||
if (!obj->IsInWorld())
|
||||
continue;
|
||||
|
||||
obj->Update(diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::AddObjectToPendingUpdateList(WorldObject* obj)
|
||||
{
|
||||
if (!obj->CanBeAddedToMapUpdateList())
|
||||
return;
|
||||
|
||||
UpdatableMapObject* mapUpdatableObject = dynamic_cast<UpdatableMapObject*>(obj);
|
||||
if (mapUpdatableObject->GetUpdateState() != UpdatableMapObject::UpdateState::NotUpdating)
|
||||
return;
|
||||
|
||||
_pendingAddUpdatableObjectList.insert(obj);
|
||||
mapUpdatableObject->SetUpdateState(UpdatableMapObject::UpdateState::PendingAdd);
|
||||
}
|
||||
|
||||
// Internal use only
|
||||
void Map::_AddObjectToUpdateList(WorldObject* obj)
|
||||
{
|
||||
UpdatableMapObject* mapUpdatableObject = dynamic_cast<UpdatableMapObject*>(obj);
|
||||
ASSERT(mapUpdatableObject && mapUpdatableObject->GetUpdateState() == UpdatableMapObject::UpdateState::PendingAdd);
|
||||
|
||||
mapUpdatableObject->SetUpdateState(UpdatableMapObject::UpdateState::Updating);
|
||||
mapUpdatableObject->SetMapUpdateListOffset(_updatableObjectList.size());
|
||||
_updatableObjectList.push_back(obj);
|
||||
}
|
||||
|
||||
// Internal use only
|
||||
void Map::_RemoveObjectFromUpdateList(WorldObject* obj)
|
||||
{
|
||||
UpdatableMapObject* mapUpdatableObject = dynamic_cast<UpdatableMapObject*>(obj);
|
||||
ASSERT(mapUpdatableObject && mapUpdatableObject->GetUpdateState() == UpdatableMapObject::UpdateState::Updating);
|
||||
|
||||
if (obj != _updatableObjectList.back())
|
||||
{
|
||||
dynamic_cast<UpdatableMapObject*>(_updatableObjectList.back())->SetMapUpdateListOffset(mapUpdatableObject->GetMapUpdateListOffset());
|
||||
std::swap(_updatableObjectList[mapUpdatableObject->GetMapUpdateListOffset()], _updatableObjectList.back());
|
||||
}
|
||||
|
||||
_updatableObjectList.pop_back();
|
||||
mapUpdatableObject->SetUpdateState(UpdatableMapObject::UpdateState::NotUpdating);
|
||||
}
|
||||
|
||||
void Map::RemoveObjectFromMapUpdateList(WorldObject* obj)
|
||||
{
|
||||
if (!obj->CanBeAddedToMapUpdateList())
|
||||
return;
|
||||
|
||||
UpdatableMapObject* mapUpdatableObject = dynamic_cast<UpdatableMapObject*>(obj);
|
||||
if (mapUpdatableObject->GetUpdateState() == UpdatableMapObject::UpdateState::PendingAdd)
|
||||
_pendingAddUpdatableObjectList.erase(obj);
|
||||
else if (mapUpdatableObject->GetUpdateState() == UpdatableMapObject::UpdateState::Updating)
|
||||
_RemoveObjectFromUpdateList(obj);
|
||||
}
|
||||
|
||||
void Map::HandleDelayedVisibility()
|
||||
{
|
||||
if (i_objectsForDelayedVisibility.empty())
|
||||
@ -795,7 +791,10 @@ void Map::RemoveFromMap(T* obj, bool remove)
|
||||
obj->ResetMap();
|
||||
|
||||
if (remove)
|
||||
{
|
||||
RemoveObjectFromMapUpdateList(obj);
|
||||
DeleteFromWorld(obj);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
@ -831,6 +830,10 @@ void Map::RemoveFromMap(MotionTransport* obj, bool remove)
|
||||
|
||||
obj->ResetMap();
|
||||
|
||||
// Transports are never actually deleted, but it *should* be safe to clear
|
||||
// from update list when removing from world
|
||||
RemoveObjectFromMapUpdateList(obj);
|
||||
|
||||
if (remove)
|
||||
{
|
||||
// if option set then object already saved at this moment
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "Position.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "Timer.h"
|
||||
#include "GridTerrainData.h"
|
||||
#include <bitset>
|
||||
#include <list>
|
||||
@ -85,6 +86,7 @@ struct ScriptAction
|
||||
|
||||
#define DEFAULT_HEIGHT_SEARCH 50.0f // default search distance to find height at nearby locations
|
||||
#define MIN_UNLOAD_DELAY 1 // immediate unload
|
||||
#define UPDATABLE_OBJECT_LIST_RECHECK_TIMER 30 * IN_MILLISECONDS // Time to recheck update object list
|
||||
|
||||
struct PositionFullTerrainStatus
|
||||
{
|
||||
@ -181,14 +183,7 @@ public:
|
||||
template<class T> bool AddToMap(T*, bool checkTransport = false);
|
||||
template<class T> void RemoveFromMap(T*, bool);
|
||||
|
||||
void VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor);
|
||||
void VisitNearbyCellsOfPlayer(Player* player, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor);
|
||||
void MarkNearbyCellsOf(WorldObject* obj);
|
||||
|
||||
virtual void Update(const uint32, const uint32, bool thread = true);
|
||||
|
||||
@ -317,9 +312,6 @@ public:
|
||||
void resetMarkedCells() { marked_cells.reset(); }
|
||||
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
|
||||
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
|
||||
void resetMarkedCellsLarge() { marked_cells_large.reset(); }
|
||||
bool isCellMarkedLarge(uint32 pCellId) { return marked_cells_large.test(pCellId); }
|
||||
void markCellLarge(uint32 pCellId) { marked_cells_large.set(pCellId); }
|
||||
|
||||
[[nodiscard]] bool HavePlayers() const { return !m_mapRefMgr.IsEmpty(); }
|
||||
[[nodiscard]] uint32 GetPlayersCountExceptGMs() const;
|
||||
@ -512,6 +504,12 @@ public:
|
||||
uint32 GetCreatedCellsInGridCount(uint16 const x, uint16 const y);
|
||||
uint32 GetCreatedCellsInMapCount();
|
||||
|
||||
void AddObjectToPendingUpdateList(WorldObject* obj);
|
||||
void RemoveObjectFromMapUpdateList(WorldObject* obj);
|
||||
|
||||
typedef std::vector<WorldObject*> UpdatableObjectList;
|
||||
typedef std::unordered_set<WorldObject*> PendingAddUpdatableObjectList;
|
||||
|
||||
private:
|
||||
|
||||
template<class T> void InitializeObject(T* obj);
|
||||
@ -576,7 +574,6 @@ private:
|
||||
Map* m_parentMap;
|
||||
|
||||
std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP * TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells;
|
||||
std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP * TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells_large;
|
||||
|
||||
bool i_scriptLock;
|
||||
std::unordered_set<WorldObject*> i_objectsToRemove;
|
||||
@ -610,6 +607,11 @@ private:
|
||||
m_activeNonPlayers.erase(obj);
|
||||
}
|
||||
|
||||
void UpdateNonPlayerObjects(uint32 const diff);
|
||||
|
||||
void _AddObjectToUpdateList(WorldObject* obj);
|
||||
void _RemoveObjectFromUpdateList(WorldObject* obj);
|
||||
|
||||
std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t> _creatureRespawnTimes;
|
||||
std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t> _goRespawnTimes;
|
||||
|
||||
@ -637,6 +639,10 @@ private:
|
||||
std::unordered_set<Corpse*> _corpseBones;
|
||||
|
||||
std::unordered_set<Object*> _updateObjects;
|
||||
|
||||
UpdatableObjectList _updatableObjectList;
|
||||
PendingAddUpdatableObjectList _pendingAddUpdatableObjectList;
|
||||
IntervalTimer _updatableObjectListRecheckTimer;
|
||||
};
|
||||
|
||||
enum InstanceResetMethod
|
||||
|
||||
@ -926,6 +926,20 @@ MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const
|
||||
return Impl[slot]->GetMovementGeneratorType();
|
||||
}
|
||||
|
||||
bool MotionMaster::HasMovementGeneratorType(MovementGeneratorType type) const
|
||||
{
|
||||
if (empty() && type == IDLE_MOTION_TYPE)
|
||||
return true;
|
||||
|
||||
for (int i = _top; i >= 0; --i)
|
||||
{
|
||||
if (Impl[i] && Impl[i]->GetMovementGeneratorType() == type)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Xinef: Escort system
|
||||
uint32 MotionMaster::GetCurrentSplineId() const
|
||||
{
|
||||
|
||||
@ -240,6 +240,7 @@ public:
|
||||
|
||||
[[nodiscard]] MovementGeneratorType GetCurrentMovementGeneratorType() const;
|
||||
[[nodiscard]] MovementGeneratorType GetMotionSlotType(int slot) const;
|
||||
bool HasMovementGeneratorType(MovementGeneratorType type) const;
|
||||
[[nodiscard]] uint32 GetCurrentSplineId() const; // Xinef: Escort system
|
||||
|
||||
void propagateSpeedChange();
|
||||
|
||||
@ -137,9 +137,12 @@ void FleeingMovementGenerator<T>::SetTargetLocation(T* owner)
|
||||
_path->Clear();
|
||||
}
|
||||
|
||||
if (owner->IsPlayer())
|
||||
_path->SetSlopeCheck(true);
|
||||
|
||||
_path->SetPathLengthLimit(30.0f);
|
||||
bool result = _path->CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
|
||||
if (!result || (_path->GetPathType() & PathType(PATHFIND_NOPATH | PATHFIND_SHORTCUT | PATHFIND_FARFROMPOLY)))
|
||||
if (!result || (_path->GetPathType() & PathType(PATHFIND_NOPATH | PATHFIND_SHORTCUT | PATHFIND_FARFROMPOLY | PATHFIND_NOT_USING_PATH)))
|
||||
{
|
||||
_timer.Reset(100);
|
||||
return;
|
||||
|
||||
@ -564,6 +564,22 @@ void PathGenerator::BuildPointPath(const float* startPoint, const float* endPoin
|
||||
}
|
||||
else if (pointCount < 2 || dtStatusFailed(dtResult))
|
||||
{
|
||||
// If its too steep, just return incomplete path.
|
||||
if (pointCount > 0 && dtResult & DT_SLOPE_TOO_STEEP)
|
||||
{
|
||||
_pathPoints.resize(pointCount);
|
||||
for (uint32 i = 0; i < pointCount; ++i)
|
||||
_pathPoints[i] = G3D::Vector3(pathPoints[i * VERTEX_SIZE + 2], pathPoints[i * VERTEX_SIZE], pathPoints[i * VERTEX_SIZE + 1]);
|
||||
|
||||
NormalizePath();
|
||||
|
||||
// first point is always our current location - we need the next one
|
||||
SetActualEndPosition(_pathPoints[pointCount - 1]);
|
||||
|
||||
_type = PathType(_type | PATHFIND_INCOMPLETE);
|
||||
return;
|
||||
}
|
||||
|
||||
// only happens if pass bad data to findStraightPath or navmesh is broken
|
||||
// single point paths can be generated here
|
||||
/// @todo check the exact cases
|
||||
@ -884,7 +900,9 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
|
||||
|
||||
if (canCheckSlope && !IsSwimmableSegment(iterPos, steerPos) && !IsWalkableClimb(iterPos, steerPos))
|
||||
{
|
||||
return DT_FAILURE;
|
||||
nsmoothPath--;
|
||||
*smoothPathSize = nsmoothPath;
|
||||
return DT_FAILURE | DT_SLOPE_TOO_STEEP;
|
||||
}
|
||||
|
||||
// Handle end of path and off-mesh links when close enough.
|
||||
|
||||
@ -443,6 +443,7 @@ void WorldConfig::BuildConfigCache()
|
||||
SetConfigValue<uint32>(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, "Arena.AutoDistributeInterval", 7);
|
||||
SetConfigValue<uint32>(CONFIG_ARENA_GAMES_REQUIRED, "Arena.GamesRequired", 10);
|
||||
SetConfigValue<uint32>(CONFIG_ARENA_START_RATING, "Arena.ArenaStartRating", 0);
|
||||
SetConfigValue<uint32>(CONFIG_LEGACY_ARENA_START_RATING, "Arena.LegacyArenaStartRating", 1500);
|
||||
SetConfigValue<uint32>(CONFIG_LEGACY_ARENA_POINTS_CALC, "Arena.LegacyArenaPoints", 0);
|
||||
SetConfigValue<uint32>(CONFIG_ARENA_START_PERSONAL_RATING, "Arena.ArenaStartPersonalRating", 0);
|
||||
SetConfigValue<uint32>(CONFIG_ARENA_START_MATCHMAKER_RATING, "Arena.ArenaStartMatchmakerRating", 1500);
|
||||
|
||||
@ -281,6 +281,7 @@ enum ServerConfigs
|
||||
CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
|
||||
CONFIG_ARENA_GAMES_REQUIRED,
|
||||
CONFIG_ARENA_START_RATING,
|
||||
CONFIG_LEGACY_ARENA_START_RATING,
|
||||
CONFIG_LEGACY_ARENA_POINTS_CALC,
|
||||
CONFIG_ARENA_START_PERSONAL_RATING,
|
||||
CONFIG_ARENA_START_MATCHMAKER_RATING,
|
||||
|
||||
@ -28,161 +28,6 @@
|
||||
#include "ObjectAccessor.h"
|
||||
#include <limits>
|
||||
|
||||
//How to win friends and influence enemies
|
||||
// texts signed for creature 28939 but used for 28939, 28940, 28610
|
||||
enum win_friends
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_CRUSADER = 1,
|
||||
SAY_PERSUADED1 = 2,
|
||||
SAY_PERSUADED2 = 3,
|
||||
SAY_PERSUADED3 = 4,
|
||||
SAY_PERSUADED4 = 5,
|
||||
SAY_PERSUADED5 = 6,
|
||||
SAY_PERSUADED6 = 7,
|
||||
SAY_PERSUADE_RAND = 8,
|
||||
SPELL_PERSUASIVE_STRIKE = 52781,
|
||||
SPELL_THREAT_PULSE = 58111,
|
||||
QUEST_HOW_TO_WIN_FRIENDS = 12720,
|
||||
};
|
||||
|
||||
class npc_crusade_persuaded : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_crusade_persuaded() : CreatureScript("npc_crusade_persuaded") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_crusade_persuadedAI(creature);
|
||||
}
|
||||
|
||||
struct npc_crusade_persuadedAI : public CombatAI
|
||||
{
|
||||
npc_crusade_persuadedAI(Creature* creature) : CombatAI(creature) { }
|
||||
|
||||
const uint32 SAY_AGGRO_CHANCE = 33;
|
||||
const uint32 PERSUADE_SUCCESS_CHANCE = 3; // 30% chance
|
||||
const uint32 SPEECH_TIMER_DEFAULT = 1000;
|
||||
const uint32 SPEECH_TIMER_FOR_ROLEPLAY = 8000;
|
||||
const uint32 SPEECH_COUNTER_PREVENT_SUCCESS_ROLEPLAY = 0;
|
||||
const uint32 SPEECH_COUNTER_START_SUCCESS_ROLEPLAY = 1;
|
||||
|
||||
uint32 speechTimer;
|
||||
uint32 speechCounter;
|
||||
ObjectGuid playerGUID;
|
||||
bool persuaded;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
speechTimer = 0;
|
||||
speechCounter = SPEECH_COUNTER_PREVENT_SUCCESS_ROLEPLAY;
|
||||
playerGUID.Clear();
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RestoreFaction();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
if (roll_chance_i(SAY_AGGRO_CHANCE))
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_PERSUASIVE_STRIKE && caster->IsPlayer() && me->IsAlive() && !speechCounter)
|
||||
{
|
||||
if (Player* player = caster->ToPlayer())
|
||||
{
|
||||
playerGUID = player->GetGUID();
|
||||
speechTimer = SPEECH_TIMER_DEFAULT;
|
||||
speechCounter = SPEECH_COUNTER_START_SUCCESS_ROLEPLAY;
|
||||
uint32 persuadeRoll = urand(1, 10);
|
||||
|
||||
sCreatureTextMgr->SendChat(me, SAY_PERSUADE_RAND, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_NEUTRAL, false, player);
|
||||
|
||||
if (persuadeRoll <= PERSUADE_SUCCESS_CHANCE && player->GetQuestStatus(QUEST_HOW_TO_WIN_FRIENDS) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
persuaded = true;
|
||||
me->SetFaction(player->GetFaction());
|
||||
me->CombatStop(true);
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
else
|
||||
persuaded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (speechCounter)
|
||||
{
|
||||
if (speechTimer <= diff)
|
||||
{
|
||||
Player* player = ObjectAccessor::GetPlayer(*me, playerGUID);
|
||||
if (!player)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (persuaded)
|
||||
{
|
||||
switch (speechCounter)
|
||||
{
|
||||
case 1:
|
||||
Talk(SAY_PERSUADED1);
|
||||
speechTimer = SPEECH_TIMER_FOR_ROLEPLAY;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Talk(SAY_PERSUADED2);
|
||||
speechTimer = SPEECH_TIMER_FOR_ROLEPLAY;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
Talk(SAY_PERSUADED3);
|
||||
speechTimer = SPEECH_TIMER_FOR_ROLEPLAY;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
Talk(SAY_PERSUADED4);
|
||||
speechTimer = SPEECH_TIMER_FOR_ROLEPLAY;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
sCreatureTextMgr->SendChat(me, SAY_PERSUADED5, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_NEUTRAL, false, player);
|
||||
speechTimer = SPEECH_TIMER_FOR_ROLEPLAY;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
Talk(SAY_PERSUADED6);
|
||||
Unit::Kill(player, me);
|
||||
speechCounter = SPEECH_COUNTER_PREVENT_SUCCESS_ROLEPLAY;
|
||||
player->GroupEventHappens(QUEST_HOW_TO_WIN_FRIENDS, me);
|
||||
return;
|
||||
}
|
||||
|
||||
++speechCounter;
|
||||
}
|
||||
else
|
||||
{
|
||||
Talk(SAY_CRUSADER);
|
||||
speechCounter = SPEECH_COUNTER_PREVENT_SUCCESS_ROLEPLAY;
|
||||
}
|
||||
}
|
||||
else
|
||||
speechTimer = (speechTimer > diff) ? (speechTimer - diff) : 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CombatAI::UpdateAI(diff);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_koltira_deathweaver
|
||||
######*/
|
||||
@ -1098,12 +943,96 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//How to win friends and influence enemies
|
||||
// texts signed for creature 28939 but used for 28939, 28940, 28610
|
||||
enum win_friends
|
||||
{
|
||||
SAY_CRUSADER = 1,
|
||||
SAY_PERSUADED1 = 2,
|
||||
SAY_PERSUADED2 = 3,
|
||||
SAY_PERSUADED3 = 4,
|
||||
SAY_PERSUADED4 = 5,
|
||||
SAY_PERSUADED5 = 6,
|
||||
SAY_PERSUADED6 = 7,
|
||||
SAY_PERSUADE_RAND = 8,
|
||||
QUEST_HOW_TO_WIN_FRIENDS = 12720,
|
||||
|
||||
NPC_SCARLET_PREACHER = 28939,
|
||||
NPC_SCARLET_COMMANDER = 28936,
|
||||
NPC_SCARLET_CRUSADER = 28940,
|
||||
NPC_SCARLET_MARKSMAN = 28610,
|
||||
NPC_SCARLET_LORD_MCCREE = 28964
|
||||
};
|
||||
|
||||
// 52781 - Persuasive Strike
|
||||
class spell_chapter2_persuasive_strike : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_chapter2_persuasive_strike);
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
return GetCaster() && GetCaster()->IsPlayer()
|
||||
&& GetCaster()->ToPlayer()->GetQuestStatus(QUEST_HOW_TO_WIN_FRIENDS) == QUEST_STATUS_INCOMPLETE;
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Creature* creature = GetHitCreature();
|
||||
Player* player = GetCaster()->ToPlayer();
|
||||
|
||||
if (!creature || !player)
|
||||
return;
|
||||
|
||||
if (!creature->EntryEquals(NPC_SCARLET_PREACHER, NPC_SCARLET_COMMANDER, NPC_SCARLET_CRUSADER, NPC_SCARLET_MARKSMAN, NPC_SCARLET_LORD_MCCREE))
|
||||
return;
|
||||
|
||||
sCreatureTextMgr->SendChat(creature, SAY_PERSUADE_RAND, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_NEUTRAL, false, player);
|
||||
|
||||
if (roll_chance_f(30.0f))
|
||||
{
|
||||
creature->CombatStop(true);
|
||||
creature->GetMotionMaster()->MoveIdle();
|
||||
creature->SetImmuneToPC(true);
|
||||
creature->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
|
||||
creature->AI()->Talk(SAY_PERSUADED1, 8s);
|
||||
creature->AI()->Talk(SAY_PERSUADED2, 16s);
|
||||
creature->AI()->Talk(SAY_PERSUADED3, 24s);
|
||||
creature->AI()->Talk(SAY_PERSUADED4, 32s);
|
||||
|
||||
creature->m_Events.AddEventAtOffset([creature, player]
|
||||
{
|
||||
if (player)
|
||||
sCreatureTextMgr->SendChat(creature, SAY_PERSUADED5, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_NEUTRAL, false, player);
|
||||
}, 40s);
|
||||
|
||||
creature->m_Events.AddEventAtOffset([creature, player]
|
||||
{
|
||||
creature->AI()->Talk(SAY_PERSUADED6);
|
||||
if (player)
|
||||
{
|
||||
Unit::Kill(player, creature);
|
||||
player->GroupEventHappens(QUEST_HOW_TO_WIN_FRIENDS, creature);
|
||||
}
|
||||
}, 48s);
|
||||
}
|
||||
else
|
||||
creature->AI()->Talk(SAY_CRUSADER, 1s);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_chapter2_persuasive_strike::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_the_scarlet_enclave_c2()
|
||||
{
|
||||
new npc_crusade_persuaded();
|
||||
new npc_scarlet_courier();
|
||||
new npc_koltira_deathweaver();
|
||||
new npc_a_special_surprise();
|
||||
new npc_acherus_necromancer();
|
||||
new npc_gothik_the_harvester();
|
||||
RegisterSpellScript(spell_chapter2_persuasive_strike);
|
||||
}
|
||||
|
||||
@ -548,6 +548,7 @@ public:
|
||||
summons.DespawnAll();
|
||||
|
||||
me->SetImmuneToAll(true);
|
||||
me->LoadEquipment(1, true);
|
||||
me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetVisible(true);
|
||||
|
||||
@ -2726,6 +2726,245 @@ enum CreatureTypeFlags
|
||||
CREATURE_TYPE_FLAG_QUEST_BOSS = 0x80000000 // Not verified
|
||||
};
|
||||
|
||||
enum class CreatureStaticFlags : uint32
|
||||
{
|
||||
MOUNTABLE = 0x00000001,
|
||||
NO_XP = 0x00000002,
|
||||
NO_LOOT = 0x00000004,
|
||||
UNKILLABLE = 0x00000008,
|
||||
TAMEABLE = 0x00000010, // CREATURE_TYPE_FLAG_TAMEABLE
|
||||
IMMUNE_TO_PC = 0x00000020, // UNIT_FLAG_IMMUNE_TO_PC
|
||||
IMMUNE_TO_NPC = 0x00000040, // UNIT_FLAG_IMMUNE_TO_NPC
|
||||
CAN_WIELD_LOOT = 0x00000080,
|
||||
SESSILE = 0x00000100, // creature_template_movement.Rooted = 1
|
||||
UNINTERACTIBLE = 0x00000200, // UNIT_FLAG_UNINTERACTIBLE
|
||||
NO_AUTOMATIC_REGEN = 0x00000400, // Creatures with that flag uses no UNIT_FLAG2_REGENERATE_POWER
|
||||
DESPAWN_INSTANTLY = 0x00000800, // Creature instantly disappear when killed
|
||||
CORPSE_RAID = 0x00001000,
|
||||
CREATOR_LOOT = 0x00002000, // Lootable only by creator(engineering dummies)
|
||||
NO_DEFENSE = 0x00004000,
|
||||
NO_SPELL_DEFENSE = 0x00008000,
|
||||
BOSS_MOB = 0x00010000, // CREATURE_TYPE_FLAG_BOSS_MOB, original description: Raid Boss Mob
|
||||
COMBAT_PING = 0x00020000,
|
||||
AQUATIC = 0x00040000, // aka Water Only, creature_template_movement.Ground = 0
|
||||
AMPHIBIOUS = 0x00080000, // creature_template_movement.Swim = 1
|
||||
NO_MELEE_FLEE = 0x00100000, // Prevents melee and makes npc flee if it enters combat - also misused to just prevent melee on npcs that cant move
|
||||
VISIBLE_TO_GHOSTS = 0x00200000, // CREATURE_TYPE_FLAG_VISIBLE_TO_GHOSTS
|
||||
PVP_ENABLING = 0x00400000, // Old UNIT_FLAG_PVP_ENABLING, now UNIT_BYTES_2_OFFSET_PVP_FLAG from UNIT_FIELD_BYTES_2
|
||||
DO_NOT_PLAY_WOUND_ANIM = 0x00800000, // CREATURE_TYPE_FLAG_DO_NOT_PLAY_WOUND_ANIM
|
||||
NO_FACTION_TOOLTIP = 0x01000000, // CREATURE_TYPE_FLAG_NO_FACTION_TOOLTIP
|
||||
IGNORE_COMBAT = 0x02000000, // Actually only changes react state to passive
|
||||
ONLY_ATTACK_PVP_ENABLING = 0x04000000, // "Only attack targets that are PvP enabling"
|
||||
CALLS_GUARDS = 0x08000000, // Creature will summon a guard if player is within its aggro range (even if creature doesn't attack per se)
|
||||
CAN_SWIM = 0x10000000, // UnitFlags 0x8000 UNIT_FLAG_CAN_SWIM
|
||||
FLOATING = 0x20000000, // creature_template_movement.Flight = 1
|
||||
MORE_AUDIBLE = 0x40000000, // CREATURE_TYPE_FLAG_MORE_AUDIBLE
|
||||
LARGE_AOI = 0x80000000 // UnitFlags2 0x200000
|
||||
};
|
||||
|
||||
enum class CreatureStaticFlags2 : uint32
|
||||
{
|
||||
NO_PET_SCALING = 0x00000001,
|
||||
FORCE_PARTY_MEMBERS_INTO_COMBAT = 0x00000002, // Original description: Force Raid Combat
|
||||
LOCK_TAPPERS_TO_RAID_ON_DEATH = 0x00000004, // "Lock Tappers To Raid On Death", toggleable by 'Set "RAID_LOCK_ON_DEATH" flag for unit(s)' action, CREATURE_FLAG_EXTRA_INSTANCE_BIND
|
||||
SPELL_ATTACKABLE = 0x00000008, // CREATURE_TYPE_FLAG_SPELL_ATTACKABLE, original description(not valid anymore?): No Harmful Vertex Coloring
|
||||
NO_CRUSHING_BLOWS = 0x00000010,
|
||||
NO_OWNER_THREAT = 0x00000020,
|
||||
NO_WOUNDED_SLOWDOWN = 0x00000040,
|
||||
USE_CREATOR_BONUSES = 0x00000080,
|
||||
IGNORE_FEIGN_DEATH = 0x00000100,
|
||||
IGNORE_SANCTUARY = 0x00000200,
|
||||
ACTION_TRIGGERS_WHILE_CHARMED = 0x00000400,
|
||||
INTERACT_WHILE_DEAD = 0x00000800, // CREATURE_TYPE_FLAG_INTERACT_WHILE_DEAD
|
||||
NO_INTERRUPT_SCHOOL_COOLDOWN = 0x00001000,
|
||||
RETURN_SOUL_SHARD_TO_MASTER_OF_PET = 0x00002000,
|
||||
SKIN_WITH_HERBALISM = 0x00004000, // CREATURE_TYPE_FLAG_SKIN_WITH_HERBALISM
|
||||
SKIN_WITH_MINING = 0x00008000, // CREATURE_TYPE_FLAG_SKIN_WITH_MINING
|
||||
ALERT_CONTENT_TEAM_ON_DEATH = 0x00010000,
|
||||
ALERT_CONTENT_TEAM_AT_90_PCT_HP = 0x00020000,
|
||||
ALLOW_MOUNTED_COMBAT = 0x00040000, // CREATURE_TYPE_FLAG_ALLOW_MOUNTED_COMBAT
|
||||
PVP_ENABLING_OOC = 0x00080000,
|
||||
NO_DEATH_MESSAGE = 0x00100000, // CREATURE_TYPE_FLAG_NO_DEATH_MESSAGE
|
||||
IGNORE_PATHING_FAILURE = 0x00200000,
|
||||
FULL_SPELL_LIST = 0x00400000,
|
||||
DOES_NOT_REDUCE_REPUTATION_FOR_RAIDS = 0x00800000,
|
||||
IGNORE_MISDIRECTION = 0x01000000,
|
||||
HIDE_BODY = 0x02000000, // UNIT_FLAG2_HIDE_BODY
|
||||
SPAWN_DEFENSIVE = 0x04000000,
|
||||
SERVER_ONLY = 0x08000000,
|
||||
CAN_SAFE_FALL = 0x10000000, // Original description: No Collision
|
||||
CAN_ASSIST = 0x20000000, // CREATURE_TYPE_FLAG_CAN_ASSIST, original description: Player Can Heal/Buff
|
||||
NO_SKILL_GAINS = 0x40000000,
|
||||
NO_PET_BAR = 0x80000000 // CREATURE_TYPE_FLAG_NO_PET_BAR
|
||||
};
|
||||
|
||||
enum class CreatureStaticFlags3 : uint32
|
||||
{
|
||||
NO_DAMAGE_HISTORY = 0x00000001,
|
||||
DONT_PVP_ENABLE_OWNER = 0x00000002,
|
||||
DO_NOT_FADE_IN = 0x00000004, // UNIT_FLAG2_DO_NOT_FADE_IN
|
||||
MASK_UID = 0x00000008, // CREATURE_TYPE_FLAG_MASK_UID, original description: Non-Unique In Combat Log
|
||||
SKIN_WITH_ENGINEERING = 0x00000010, // CREATURE_TYPE_FLAG_SKIN_WITH_ENGINEERING
|
||||
NO_AGGRO_ON_LEASH = 0x00000020,
|
||||
NO_FRIENDLY_AREA_AURAS = 0x00000040,
|
||||
EXTENDED_CORPSE_DURATION = 0x00000080,
|
||||
CANNOT_SWIM = 0x00000100, // UNIT_FLAG_CANNOT_SWIM
|
||||
TAMEABLE_EXOTIC = 0x00000200, // CREATURE_TYPE_FLAG_TAMEABLE_EXOTIC
|
||||
GIGANTIC_AOI = 0x00000400, // Since MoP, creatures with that flag have UnitFlags2 0x400000
|
||||
INFINITE_AOI = 0x00000800, // Since MoP, creatures with that flag have UnitFlags2 0x40000000
|
||||
CANNOT_PENETRATE_WATER = 0x00001000, // Waterwalking
|
||||
NO_NAME_PLATE = 0x00002000, // CREATURE_TYPE_FLAG_NO_NAME_PLATE
|
||||
CHECKS_LIQUIDS = 0x00004000,
|
||||
NO_THREAT_FEEDBACK = 0x00008000,
|
||||
USE_MODEL_COLLISION_SIZE = 0x00010000, // CREATURE_TYPE_FLAG_USE_MODEL_COLLISION_SIZE
|
||||
ATTACKER_IGNORES_FACING = 0x00020000, // In 3.3.5 used only by Rocket Propelled Warhead
|
||||
ALLOW_INTERACTION_WHILE_IN_COMBAT = 0x00040000, // CREATURE_TYPE_FLAG_ALLOW_INTERACTION_WHILE_IN_COMBAT
|
||||
SPELL_CLICK_FOR_PARTY_ONLY = 0x00080000,
|
||||
FACTION_LEADER = 0x00100000,
|
||||
IMMUNE_TO_PLAYER_BUFFS = 0x00200000,
|
||||
COLLIDE_WITH_MISSILES = 0x00400000, // CREATURE_TYPE_FLAG_COLLIDE_WITH_MISSILES
|
||||
CAN_BE_MULTITAPPED = 0x00800000, // Original description: Do Not Tap (Credit to threat list)
|
||||
DO_NOT_PLAY_MOUNTED_ANIMATIONS = 0x01000000, // CREATURE_TYPE_FLAG_DO_NOT_PLAY_MOUNTED_ANIMATIONS, original description: Disable Dodge, Parry and Block Animations
|
||||
CANNOT_TURN = 0x02000000, // UNIT_FLAG2_CANNOT_TURN
|
||||
ENEMY_CHECK_IGNORES_LOS = 0x04000000,
|
||||
FOREVER_CORPSE_DURATION = 0x08000000, // 7 days
|
||||
PETS_ATTACK_WITH_3D_PATHING = 0x10000000, // "Pets attack with 3d pathing (Kologarn)"
|
||||
LINK_ALL = 0x20000000, // CREATURE_TYPE_FLAG_LINK_ALL
|
||||
AI_CAN_AUTO_TAKEOFF_IN_COMBAT = 0x40000000,
|
||||
AI_CAN_AUTO_LAND_IN_COMBAT = 0x80000000
|
||||
};
|
||||
|
||||
enum class CreatureStaticFlags4 : uint32
|
||||
{
|
||||
NO_BIRTH_ANIM = 0x00000001, // SMSG_UPDATE_OBJECT's "NoBirthAnim"
|
||||
TREAT_AS_PLAYER_FOR_DIMINISHING_RETURNS = 0x00000002, // Primarily used by ToC champions
|
||||
TREAT_AS_PLAYER_FOR_PVP_DEBUFF_DURATION = 0x00000004, // Primarily used by ToC champions
|
||||
INTERACT_ONLY_WITH_CREATOR = 0x00000008, // CREATURE_TYPE_FLAG_INTERACT_ONLY_WITH_CREATOR, original description: Only Display Gossip for Summoner
|
||||
DO_NOT_PLAY_UNIT_EVENT_SOUNDS = 0x00000010, // CREATURE_TYPE_FLAG_DO_NOT_PLAY_UNIT_EVENT_SOUNDS, original description: No Death Scream
|
||||
HAS_NO_SHADOW_BLOB = 0x00000020, // CREATURE_TYPE_FLAG_HAS_NO_SHADOW_BLOB, original description(wrongly linked type flag or behavior was changed?): Can be Healed by Enemies
|
||||
DEALS_TRIPLE_DAMAGE_TO_PC_CONTROLLED_PETS = 0x00000040,
|
||||
NO_NPC_DAMAGE_BELOW_85PTC = 0x00000080,
|
||||
OBEYS_TAUNT_DIMINISHING_RETURNS = 0x00000100, // CREATURE_FLAG_EXTRA_OBEYS_TAUNT_DIMINISHING_RETURNS
|
||||
NO_MELEE_APPROACH = 0x00000200,
|
||||
UPDATE_CREATURE_RECORD_WHEN_INSTANCE_CHANGES_DIFFICULTY = 0x00000400, // Used only by Snobold Vassal
|
||||
CANNOT_DAZE = 0x00000800, // "Cannot Daze (Combat Stun)"
|
||||
FLAT_HONOR_AWARD = 0x00001000,
|
||||
IGNORE_LOS_WHEN_CASTING_ON_ME = 0x00002000, // "Other objects can ignore line of sight requirements when casting spells on me", used only by Ice Tomb in 3.3.5
|
||||
GIVE_QUEST_KILL_CREDIT_WHILE_OFFLINE = 0x00004000,
|
||||
TREAT_AS_RAID_UNIT_FOR_HELPFUL_SPELLS = 0x00008000, // CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT, "Treat as Raid Unit For Helpful Spells (Instances ONLY)", used by Valithria Dreamwalker
|
||||
DONT_REPOSITION_IF_MELEE_TARGET_IS_TOO_CLOSE = 0x00010000, // "Don't reposition because melee target is too close"
|
||||
PET_OR_GUARDIAN_AI_DONT_GO_BEHIND_TARGET = 0x00020000,
|
||||
MINUTE_5_LOOT_ROLL_TIMER = 0x00040000, // Used by Lich King
|
||||
FORCE_GOSSIP = 0x00080000, // CREATURE_TYPE_FLAG_FORCE_GOSSIP
|
||||
DONT_REPOSITION_WITH_FRIENDS_IN_COMBAT = 0x00100000,
|
||||
DO_NOT_SHEATHE = 0x00200000, // CREATURE_TYPE_FLAG_DO_NOT_SHEATHE, original description: Manual Sheathing control
|
||||
IGNORE_SPELL_MIN_RANGE_RESTRICTIONS = 0x00400000, // UnitFlags2 0x8000000, original description: Attacker Ignores Minimum Ranges
|
||||
SUPPRESS_INSTANCE_WIDE_RELEASE_IN_COMBAT = 0x00800000,
|
||||
PREVENT_SWIM = 0x01000000, // UnitFlags2 0x1000000, original description: AI will only swim if target swims
|
||||
HIDE_IN_COMBAT_LOG = 0x02000000, // UnitFlags2 0x2000000, original description: Don't generate combat log when engaged with NPC's
|
||||
ALLOW_NPC_COMBAT_WHILE_UNINTERACTIBLE = 0x04000000,
|
||||
PREFER_NPCS_WHEN_SEARCHING_FOR_ENEMIES = 0x08000000,
|
||||
ONLY_GENERATE_INITIAL_THREAT = 0x10000000,
|
||||
DO_NOT_TARGET_ON_INTERACTION = 0x20000000, // CREATURE_TYPE_FLAG_DO_NOT_TARGET_ON_INTERACTION, original description: Doesn't change target on right click
|
||||
DO_NOT_RENDER_OBJECT_NAME = 0x40000000, // CREATURE_TYPE_FLAG_DO_NOT_RENDER_OBJECT_NAME, original description: Hide name in world frame
|
||||
QUEST_BOSS = 0x80000000 // CREATURE_TYPE_FLAG_QUEST_BOSS
|
||||
};
|
||||
|
||||
enum class CreatureStaticFlags5 : uint32
|
||||
{
|
||||
UNTARGETABLE_BY_CLIENT = 0x00000001, // UnitFlags2 0x4000000 UNIT_FLAG2_UNTARGETABLE_BY_CLIENT
|
||||
FORCE_SELF_MOUNTING = 0x00000002,
|
||||
UNINTERACTIBLE_IF_HOSTILE = 0x00000004, // UnitFlags2 0x10000000
|
||||
DISABLES_XP_AWARD = 0x00000008,
|
||||
DISABLE_AI_PREDICTION = 0x00000010,
|
||||
NO_LEAVECOMBAT_STATE_RESTORE = 0x00000020,
|
||||
BYPASS_INTERACT_INTERRUPTS = 0x00000040,
|
||||
DEGREE_BACK_ARC_240 = 0x00000080,
|
||||
INTERACT_WHILE_HOSTILE = 0x00000100, // UnitFlags2 0x4000 UNIT_FLAG2_INTERACT_WHILE_HOSTILE
|
||||
DONT_DISMISS_ON_FLYING_MOUNT = 0x00000200,
|
||||
PREDICTIVE_POWER_REGEN = 0x00000400, // CREATURE_TYPEFLAGS_2_UNK1
|
||||
HIDE_LEVEL_INFO_IN_TOOLTIP = 0x00000800, // CREATURE_TYPEFLAGS_2_UNK2
|
||||
HIDE_HEALTH_BAR_UNDER_TOOLTIP = 0x00001000, // CREATURE_TYPEFLAGS_2_UNK3
|
||||
SUPPRESS_HIGHLIGHT_WHEN_TARGETED_OR_MOUSED_OVER = 0x00002000, // UnitFlags2 0x80000
|
||||
AI_PREFER_PATHABLE_TARGETS = 0x00004000,
|
||||
FREQUENT_AREA_TRIGGER_CHECKS = 0x00008000,
|
||||
ASSIGN_KILL_CREDIT_TO_ENCOUNTER_LIST = 0x00010000,
|
||||
NEVER_EVADE = 0x00020000,
|
||||
AI_CANT_PATH_ON_STEEP_SLOPES = 0x00040000,
|
||||
AI_IGNORE_LOS_TO_MELEE_TARGET = 0x00080000,
|
||||
NO_TEXT_IN_CHAT_BUBBLE = 0x00100000, // "Never display emote or chat text in a chat bubble", CREATURE_TYPEFLAGS_2_UNK4
|
||||
CLOSE_IN_ON_UNPATHABLE_TARGET = 0x00200000, // "AI Pets close in on unpathable target"
|
||||
DONT_GO_BEHIND_ME = 0x00400000, // "Pet/Guardian AI Don't Go Behind Me (use on target)"
|
||||
NO_DEATH_THUD = 0x00800000, // CREATURE_TYPEFLAGS_2_UNK5
|
||||
CLIENT_LOCAL_CREATURE = 0x01000000,
|
||||
CAN_DROP_LOOT_WHILE_IN_A_CHALLENGE_MODE_INSTANCE = 0x02000000,
|
||||
HAS_SAFE_LOCATION = 0x04000000,
|
||||
NO_HEALTH_REGEN = 0x08000000,
|
||||
NO_POWER_REGEN = 0x10000000,
|
||||
NO_PET_UNIT_FRAME = 0x20000000,
|
||||
NO_INTERACT_ON_LEFT_CLICK = 0x40000000, // CREATURE_TYPEFLAGS_2_UNK6
|
||||
GIVE_CRITERIA_KILL_CREDIT_WHEN_CHARMED = 0x80000000
|
||||
};
|
||||
|
||||
enum class CreatureStaticFlags6 : uint32
|
||||
{
|
||||
DO_NOT_AUTO_RESUMMON = 0x00000001, // "Do not auto-resummon this companion creature"
|
||||
REPLACE_VISIBLE_UNIT_IF_AVAILABLE = 0x00000002, // "Smooth Phasing: Replace visible unit if available"
|
||||
IGNORE_REALM_COALESCING_HIDING_CODE = 0x00000004, // "Ignore the realm coalescing hiding code (always show)"
|
||||
TAPS_TO_FACTION = 0x00000008,
|
||||
ONLY_QUESTGIVER_FOR_SUMMONER = 0x00000010,
|
||||
AI_COMBAT_RETURN_PRECISE = 0x00000020,
|
||||
HOME_REALM_ONLY_LOOT = 0x00000040,
|
||||
NO_INTERACT_RESPONSE = 0x00000080, // TFLAG2_UNK7
|
||||
NO_INITIAL_POWER = 0x00000100,
|
||||
DONT_CANCEL_CHANNEL_ON_MASTER_MOUNTING = 0x00000200,
|
||||
CAN_TOGGLE_BETWEEN_DEATH_AND_PERSONAL_LOOT = 0x00000400,
|
||||
ALWAYS_STAND_ON_TOP_OF_TARGET = 0x00000800, // "Always, ALWAYS tries to stand right on top of his move to target. ALWAYS!!", toggleable by 'Set "Always Stand on Target" flag for unit(s)' or not same?
|
||||
UNCONSCIOUS_ON_DEATH = 0x00001000,
|
||||
DONT_REPORT_TO_LOCAL_DEFENSE_CHANNEL_ON_DEATH = 0x00002000,
|
||||
PREFER_UNENGAGED_MONSTERS = 0x00004000, // "Prefer unengaged monsters when picking a target"
|
||||
USE_PVP_POWER_AND_RESILIENCE = 0x00008000, // "Use PVP power and resilience when players attack this creature"
|
||||
DONT_CLEAR_DEBUFFS_ON_LEAVE_COMBAT = 0x00010000,
|
||||
PERSONAL_LOOT_HAS_FULL_SECURITY = 0x00020000, // "Personal loot has full security (guaranteed push/mail delivery)"
|
||||
TRIPLE_SPELL_VISUALS = 0x00040000,
|
||||
USE_GARRISON_OWNER_LEVEL = 0x00080000,
|
||||
IMMEDIATE_AOI_UPDATE_ON_SPAWN = 0x00100000,
|
||||
UI_CAN_GET_POSITION = 0x00200000,
|
||||
SEAMLESS_TRANSFER_PROHIBITED = 0x00400000,
|
||||
ALWAYS_USE_GROUP_LOOT_METHOD = 0x00800000,
|
||||
NO_BOSS_KILL_BANNER = 0x01000000,
|
||||
FORCE_TRIGGERING_PLAYER_LOOT_ONLY = 0x02000000,
|
||||
SHOW_BOSS_FRAME_WHILE_UNINTERACTABLE = 0x04000000,
|
||||
SCALES_TO_PLAYER_LEVEL = 0x08000000,
|
||||
AI_DONT_LEAVE_MELEE_FOR_RANGED_WHEN_TARGET_GETS_ROOTED = 0x10000000,
|
||||
DONT_USE_COMBAT_REACH_FOR_CHAINING = 0x20000000,
|
||||
DO_NOT_PLAY_PROCEDURAL_WOUND_ANIM = 0x40000000,
|
||||
APPLY_PROCEDURAL_WOUND_ANIM_TO_BASE = 0x80000000 // TFLAG2_UNK14
|
||||
};
|
||||
|
||||
enum class CreatureStaticFlags7 : uint32
|
||||
{
|
||||
IMPORTANT_NPC = 0x00000001,
|
||||
IMPORTANT_QUEST_NPC = 0x00000002,
|
||||
LARGE_NAMEPLATE = 0x00000004,
|
||||
TRIVIAL_PET = 0x00000008,
|
||||
AI_ENEMIES_DONT_BACKUP_WHEN_I_GET_ROOTED = 0x00000010,
|
||||
NO_AUTOMATIC_COMBAT_ANCHOR = 0x00000020,
|
||||
ONLY_TARGETABLE_BY_CREATOR = 0x00000040,
|
||||
TREAT_AS_PLAYER_FOR_ISPLAYERCONTROLLED = 0x00000080,
|
||||
GENERATE_NO_THREAT_OR_DAMAGE = 0x00000100,
|
||||
INTERACT_ONLY_ON_QUEST = 0x00000200,
|
||||
DISABLE_KILL_CREDIT_FOR_OFFLINE_PLAYERS = 0x00000400,
|
||||
AI_ADDITIONAL_PATHING = 0x00080000,
|
||||
};
|
||||
|
||||
enum class CreatureStaticFlags8 : uint32
|
||||
{
|
||||
FORCE_CLOSE_IN_ON_PATH_FAIL_BEHAVIOR = 0x00000002,
|
||||
USE_2D_CHASING_CALCULATION = 0x00000020,
|
||||
USE_FAST_CLASSIC_HEARTBEAT = 0x00000040,
|
||||
};
|
||||
|
||||
enum CreatureEliteType
|
||||
{
|
||||
CREATURE_ELITE_NORMAL = 0,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user