├── data └── sql │ ├── updates │ ├── char │ │ └── .dummy │ └── world │ │ └── .dummy │ ├── db-characters │ ├── zone_difficulty_completion_logs.sql │ └── zone_difficulty_char_tables.sql │ └── db-world │ ├── zone_difficulty_info.sql │ ├── zone_difficulty_mythicmode_ai.sql │ ├── zone_difficulty_mythicmode_instance_data.sql │ ├── zone_difficulty_mythicmode_ai_gruul_magtheridon.sql │ ├── zone_difficulty_mythicmode_creatureoverrides.sql │ ├── zone_difficulty_spelloverrides.sql │ ├── zone_difficulty_mythicmode_rewards_za.sql │ ├── zone_difficulty_mythicmode_rewards_hyjal.sql │ ├── zone_difficulty_mythicmode_ai_cavernsoftime.sql │ ├── zone_difficulty_disallowed_buffs.sql │ ├── zone_difficulty_mythicmode_t5_rewards.sql │ ├── zone_difficulty_mythicmode_swp_rewards.sql │ ├── zone_difficulty_mythicmode_t6_rewards.sql │ ├── zone_difficulty_info_content.sql │ ├── zone_difficulty_mythicmode_rewards.sql │ └── zone_difficulty_mythicmode_creatures.sql ├── .editorconfig ├── .github └── workflows │ └── core-build.yml ├── include.sh ├── src ├── mod_zone_difficulty_loader.cpp ├── cs_zone_difficulty.cpp ├── ZoneDifficulty.h └── mod_zone_difficulty_handler.cpp ├── .gitignore ├── conf ├── conf.sh.dist └── mod-zone-difficulty.conf.dist ├── .gitattributes ├── README.md └── LICENSE /data/sql/updates/char/.dummy: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /data/sql/updates/world/.dummy: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | indent_style = space 4 | indent_size = 4 5 | tab_width = 4 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | max_line_length = 80 9 | -------------------------------------------------------------------------------- /data/sql/db-characters/zone_difficulty_completion_logs.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `zone_difficulty_completion_logs` ( 2 | `guid` INT UNSIGNED NOT NULL, 3 | `type` TINYINT NOT NULL, 4 | `mode` TINYINT NOT NULL DEFAULT 0, 5 | PRIMARY KEY (`guid`, `type`) 6 | ); 7 | -------------------------------------------------------------------------------- /.github/workflows/core-build.yml: -------------------------------------------------------------------------------- 1 | name: core-build 2 | on: 3 | push: 4 | pull_request: 5 | 6 | jobs: 7 | build: 8 | uses: azerothcore/reusable-workflows/.github/workflows/core_build_modules.yml@main 9 | with: 10 | module_repo: ${{ github.event.repository.name }} 11 | -------------------------------------------------------------------------------- /include.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ## GETS THE CURRENT MODULE ROOT DIRECTORY 4 | MOD_SKELETON_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/" && pwd )" 5 | 6 | source $MOD_SKELETON_ROOT"/conf/conf.sh.dist" 7 | 8 | if [ -f $MOD_SKELETON_ROOT"/conf/conf.sh" ]; then 9 | source $MOD_SKELETON_ROOT"/conf/conf.sh" 10 | fi 11 | -------------------------------------------------------------------------------- /src/mod_zone_difficulty_loader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 3 | */ 4 | 5 | void AddModZoneDifficultyScripts(); 6 | void AddSC_zone_difficulty_commandscript(); 7 | 8 | void Addmod_zone_difficultyScripts() 9 | { 10 | AddModZoneDifficultyScripts(); 11 | AddSC_zone_difficulty_commandscript(); 12 | } 13 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_info.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `zone_difficulty_info`; 2 | CREATE TABLE `zone_difficulty_info` ( 3 | `MapID` INT NOT NULL DEFAULT 0, 4 | `PhaseMask` INT NOT NULL DEFAULT 0, 5 | `HealingNerfValue` FLOAT NOT NULL DEFAULT 1, 6 | `AbsorbNerfValue` FLOAT NOT NULL DEFAULT 1, 7 | `MeleeDmgBuffValue` FLOAT NOT NULL DEFAULT 1, 8 | `SpellDmgBuffValue` FLOAT NOT NULL DEFAULT 1, 9 | `Enabled` TINYINT DEFAULT 1, 10 | `Comment` TEXT, 11 | PRIMARY KEY (`MapID`, `PhaseMask`, `Enabled`) 12 | ); 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | 3 | # 4 | #Generic 5 | # 6 | 7 | .directory 8 | .mailmap 9 | *.orig 10 | *.rej 11 | *.*~ 12 | .hg/ 13 | *.kdev* 14 | .DS_Store 15 | CMakeLists.txt.user 16 | *.bak 17 | *.patch 18 | *.diff 19 | *.REMOTE.* 20 | *.BACKUP.* 21 | *.BASE.* 22 | *.LOCAL.* 23 | 24 | # 25 | # IDE & other softwares 26 | # 27 | /.settings/ 28 | /.externalToolBuilders/* 29 | # exclude in all levels 30 | nbproject/ 31 | .sync.ffs_db 32 | *.kate-swp 33 | 34 | # 35 | # Eclipse 36 | # 37 | *.pydevproject 38 | .metadata 39 | .gradle 40 | tmp/ 41 | *.tmp 42 | *.swp 43 | *~.nib 44 | local.properties 45 | .settings/ 46 | .loadpath 47 | .project 48 | .cproject 49 | .idea 50 | -------------------------------------------------------------------------------- /conf/conf.sh.dist: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ## CUSTOM SQL - Important file used by the db_assembler.sh 4 | ## Keep only the required variables (base sql files or updates, depending on the DB) 5 | 6 | ## BASE SQL 7 | 8 | DB_AUTH_CUSTOM_PATHS+=( 9 | "$MOD_SKELETON_ROOT/sql/auth/base/" 10 | ) 11 | 12 | DB_CHARACTERS_CUSTOM_PATHS+=( 13 | "$MOD_SKELETON_ROOT/sql/characters/base/" 14 | ) 15 | 16 | DB_WORLD_CUSTOM_PATHS+=( 17 | "$MOD_SKELETON_ROOT/sql/world/base/" 18 | ) 19 | 20 | ## UPDATES 21 | 22 | DB_AUTH_UPDATES_PATHS+=( 23 | "$MOD_SKELETON_ROOT/sql/auth/updates/" 24 | ) 25 | 26 | DB_CHARACTERS_UPDATES_PATHS+=( 27 | "$MOD_SKELETON_ROOT/sql/characters/updates/" 28 | ) 29 | 30 | DB_WORLD_UPDATES_PATHS+=( 31 | "$MOD_SKELETON_ROOT/sql/world/updates/" 32 | ) 33 | -------------------------------------------------------------------------------- /data/sql/db-characters/zone_difficulty_char_tables.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS `zone_difficulty_instance_saves`( 2 | `InstanceID` INT NOT NULL DEFAULT 0, 3 | `MythicmodeOn` TINYINT NOT NULL DEFAULT 0, 4 | `MythicmodePossible` TINYINT NOT NULL DEFAULT 1, 5 | PRIMARY KEY (`InstanceID`) 6 | ); 7 | 8 | CREATE TABLE IF NOT EXISTS `zone_difficulty_mythicmode_score`( 9 | `GUID` INT NOT NULL DEFAULT 0, 10 | `Type` TINYINT NOT NULL DEFAULT 0, 11 | `Score` INT NOT NULL DEFAULT 0, 12 | PRIMARY KEY (`GUID`, `Type`) 13 | ); 14 | 15 | CREATE TABLE IF NOT EXISTS `zone_difficulty_encounter_logs`( 16 | `InstanceId` INT NOT NULL DEFAULT 0, 17 | `TimestampStart` INT NOT NULL DEFAULT 0, 18 | `TimestampEnd` INT NOT NULL DEFAULT 0, 19 | `Map` INT NOT NULL DEFAULT 0, 20 | `BossId` INT NOT NULL DEFAULT 0, 21 | `PlayerGuid` INT NOT NULL DEFAULT 0, 22 | `Mode` INT NOT NULL DEFAULT 0, 23 | PRIMARY KEY (`InstanceId`, `TimestampStart`, `PlayerGuid`) 24 | ); 25 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ## AUTO-DETECT 2 | ## Handle line endings automatically for files detected as 3 | ## text and leave all files detected as binary untouched. 4 | ## This will handle all files NOT defined below. 5 | * text=auto eol=lf 6 | 7 | # Text 8 | *.conf text 9 | *.conf.dist text 10 | *.cmake text 11 | 12 | ## Scripts 13 | *.sh text 14 | *.fish text 15 | *.lua text 16 | 17 | ## SQL 18 | *.sql text 19 | 20 | ## C++ 21 | *.c text 22 | *.cc text 23 | *.cxx text 24 | *.cpp text 25 | *.c++ text 26 | *.hpp text 27 | *.h text 28 | *.h++ text 29 | *.hh text 30 | 31 | 32 | ## For documentation 33 | 34 | # Documents 35 | *.doc diff=astextplain 36 | *.DOC diff=astextplain 37 | *.docx diff=astextplain 38 | *.DOCX diff=astextplain 39 | *.dot diff=astextplain 40 | *.DOT diff=astextplain 41 | *.pdf diff=astextplain 42 | *.PDF diff=astextplain 43 | *.rtf diff=astextplain 44 | *.RTF diff=astextplain 45 | 46 | ## DOCUMENTATION 47 | *.markdown text 48 | *.md text 49 | *.mdwn text 50 | *.mdown text 51 | *.mkd text 52 | *.mkdn text 53 | *.mdtxt text 54 | *.mdtext text 55 | *.txt text 56 | AUTHORS text 57 | CHANGELOG text 58 | CHANGES text 59 | CONTRIBUTING text 60 | COPYING text 61 | copyright text 62 | *COPYRIGHT* text 63 | INSTALL text 64 | license text 65 | LICENSE text 66 | NEWS text 67 | readme text 68 | *README* text 69 | TODO text 70 | 71 | ## GRAPHICS 72 | *.ai binary 73 | *.bmp binary 74 | *.eps binary 75 | *.gif binary 76 | *.ico binary 77 | *.jng binary 78 | *.jp2 binary 79 | *.jpg binary 80 | *.jpeg binary 81 | *.jpx binary 82 | *.jxr binary 83 | *.pdf binary 84 | *.png binary 85 | *.psb binary 86 | *.psd binary 87 | *.svg text 88 | *.svgz binary 89 | *.tif binary 90 | *.tiff binary 91 | *.wbmp binary 92 | *.webp binary 93 | 94 | 95 | ## ARCHIVES 96 | *.7z binary 97 | *.gz binary 98 | *.jar binary 99 | *.rar binary 100 | *.tar binary 101 | *.zip binary 102 | 103 | ## EXECUTABLES 104 | *.exe binary 105 | *.pyc binary 106 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_ai.sql: -------------------------------------------------------------------------------- 1 | -- ************************************************************************ 2 | -- Possible values for `Target`: 3 | SET @TARGET_NONE = 0; -- For spells without target. 4 | SET @TARGET_SELF = 1; -- Self cast. 5 | SET @TARGET_VICTIM = 2; -- Our current target. (ie: highest aggro) 6 | SET @TARGET_HOSTILE_AGGRO_FROM_TOP= 3; -- Position (TargetArg2) in the threat list counted from top. TargetArg = max/min range. Fallback to GetVictim(). 7 | SET @TARGET_HOSTILE_AGGRO_FROM_BOTTOM = 4; -- Position (TargetArg2) in the threat list counted from bottom. TargetArg = max/min range. Fallback to GetVictim(). 8 | SET @TARGET_HOSTILE_RANDOM = 5; -- Just any random player on our threat list. TargetArg = max/min range. 9 | SET @TARGET_HOSTILE_RANDOM_NOT_TOP = 6; -- Just any random player on our threat list except the current target. TargetArg = max/min range. 10 | SET @TARGET_PLAYER_DISTANCE = 18; -- All players in range. TargetArg = max/min range. 11 | -- ************************************************************************ 12 | 13 | DROP TABLE IF EXISTS `zone_difficulty_mythicmode_ai`; 14 | CREATE TABLE `zone_difficulty_mythicmode_ai` ( 15 | `CreatureEntry` INT NOT NULL DEFAULT 0, 16 | `Chance` TINYINT NOT NULL DEFAULT 100, -- 0-100% chance for the creature to gain this spell 17 | `Spell` INT NOT NULL, -- spell id 18 | `Spellbp0` INT NOT NULL DEFAULT 0, -- custom spell value bp0 19 | `Spellbp1` INT NOT NULL DEFAULT 0, -- custom spell value bp1 20 | `Spellbp2` INT NOT NULL DEFAULT 0, -- custom spell value bp2 21 | `Target` TINYINT NOT NULL DEFAULT 1, -- see above 22 | `TargetArg` INT NOT NULL DEFAULT 0, -- optional argument for the target. Max/min range 23 | `TargetArg2` INT NOT NULL DEFAULT 0, -- optional argument for the target. Counter in the threat list for position 24 | `Delay` INT NOT NULL DEFAULT 1, -- time in ms before first cast 25 | `Cooldown` INT NOT NULL DEFAULT 1, -- time in ms between casts 26 | `Repetitions` TINYINT NOT NULL DEFAULT 0, -- 0 = forever, 1 = just once. Room for future counters. 27 | `Enabled` TINYINT DEFAULT 1, -- 0 = disabled, 1 = enabled 28 | `TriggeredCast` TINYINT DEFAULT 1, -- 0 = Not triggered, 1 = Triggered spell cast (no cast time, etc.) 29 | `Comment` TEXT 30 | ); 31 | -------------------------------------------------------------------------------- /conf/mod-zone-difficulty.conf.dist: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 3 | # 4 | 5 | [worldserver] 6 | 7 | ######################################## 8 | # ModZoneDifficulty 9 | ######################################## 10 | # 11 | # ModZoneDifficulty.Enable 12 | # Description: Enable my module. 13 | # Default: 0 - Disabled 14 | # 1 - Enabled 15 | # 16 | 17 | ModZoneDifficulty.Enable = 1 18 | 19 | # 20 | # ModZoneDifficulty.DebugInfo 21 | # Description: Displays debug data for absorbs. 22 | # Default: 0 - Disabled 23 | # 1 - Enabled 24 | # 25 | 26 | ModZoneDifficulty.DebugInfo = 0 27 | 28 | # 29 | # ModZoneDifficulty.UseVendorInterface 30 | # Description: Displays a vendor interface to claim rewards instead of gossips. 31 | # Default: 0 - Disabled 32 | # 1 - Enabled 33 | # 34 | 35 | ModZoneDifficulty.UseVendorInterface = 0 36 | 37 | # 38 | # ModZoneDifficulty.SpellBuff.OnlyBosses 39 | # Description: Spell damage buffs will only affect bosses. 40 | # Default: 0 - Disabled 41 | # 1 - Enabled 42 | # 43 | 44 | ModZoneDifficulty.SpellBuff.OnlyBosses = 0 45 | 46 | # 47 | # ModZoneDifficulty.MeleeBuff.OnlyBosses 48 | # Description: Melee damage buffs will only affect bosses. 49 | # Default: 0 - Disabled 50 | # 1 - Enabled 51 | # 52 | 53 | ModZoneDifficulty.MeleeBuff.OnlyBosses = 0 54 | 55 | # 56 | # ModZoneDifficulty.Mythicmode.Enable 57 | # Description: Enable or disable the mythic mode. 58 | # Default: 0 - Disabled 59 | # 1 - Enabled 60 | 61 | ModZoneDifficulty.Mythicmode.Enable = 0 62 | 63 | # 64 | # ModZoneDifficulty.Mythicmode.HpModifier 65 | # Description: Modifier for creature HP except bosses in mythic mode. 66 | # Possible to override per creature by adding data to `zone_difficulty_mythicmode_creatureoverrides`. 67 | # Default: 2.0 - 200% HP 68 | # 69 | 70 | ModZoneDifficulty.Mythicmode.HpModifier = 2.0 71 | 72 | # 73 | # ModZoneDifficulty.Mythicmode.InNormalDungeons 74 | # Description: Enable or disable mythic mode in non-heroic 5man dungeons. 75 | # Dungeonmaster NPCs still need to be spawned. They only appear in heroic 5mans and raids by default. 76 | # Default: 0 - Disabled 77 | # 1 - Enabled 78 | 79 | ModZoneDifficulty.Mythicmode.InNormalDungeons = 0 80 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_instance_data.sql: -------------------------------------------------------------------------------- 1 | -- TYPE_VANILLA = 1; 2 | -- TYPE_RAID_MC = 2; 3 | -- TYPE_RAID_ONY = 3; 4 | -- TYPE_RAID_BWL = 4; 5 | -- TYPE_RAID_ZG = 5; 6 | -- TYPE_RAID_AQ20 = 6; 7 | -- TYPE_RAID_AQ40 = 7; 8 | -- TYPE_HEROIC_TBC = 8; 9 | -- TYPE_RAID_T4 = 9; 10 | -- TYPE_RAID_T5 = 10; 11 | -- TYPE_RAID_T6 = 11; 12 | -- TYPE_HEROIC_WOTLK = 12; 13 | -- TYPE_RAID_T7 = 13; 14 | -- TYPE_RAID_T8 = 14; 15 | -- TYPE_RAID_T9 = 15; 16 | -- TYPE_RAID_T10 = 16; 17 | 18 | DROP TABLE IF EXISTS `zone_difficulty_mythicmode_instance_data`; 19 | CREATE TABLE `zone_difficulty_mythicmode_instance_data` ( 20 | `MapID` INT NOT NULL DEFAULT 0, 21 | `SourceEntry` INT NOT NULL, 22 | 23 | -- Bitmask `Override`: 24 | -- 0 = nothing 25 | -- 1 = no score, just log 26 | `Override` INT NOT NULL DEFAULT 0, 27 | `InstanceType` TINYINT NOT NULL DEFAULT 0, 28 | PRIMARY KEY (`MapID`, `SourceEntry`) 29 | ); 30 | 31 | INSERT INTO `zone_difficulty_mythicmode_instance_data` (`MapID`, `SourceEntry`, `Override`, `InstanceType`) VALUES 32 | -- TBC Raids 33 | (544, 17257, 0, 9), -- Magtheridon, Magtheridon's Lair 34 | (565, 18831, 0, 9), -- High King Maulgar, Gruul's Lair 35 | (565, 19044, 0, 9), -- Gruul, Gruul's Lair 36 | -- SSC 37 | (548, 21216, 0, 10), -- Hydross 38 | (548, 21217, 0, 10), -- Lurker 39 | (548, 21215, 0, 10), -- Leotheras 40 | (548, 21213, 0, 10), -- Morogrim 41 | (548, 21214, 0, 10), -- Karathress 42 | (548, 21212, 0, 10), -- Vashj 43 | -- Hyjal 44 | (534, 17767, 0, 18), -- Rage Winterchill 45 | (534, 17808, 0, 18), -- Anetheron 46 | (534, 17888, 0, 18), -- Kazrogal 47 | (534, 17842, 0, 18), -- Azgalor 48 | (534, 17968, 0, 18), -- Archimonde 49 | -- Black Temple 50 | (564, 22887, 0, 11), -- Najentus 51 | (564, 22898, 0, 11), -- Supremus 52 | (564, 22841, 0, 11), -- Akama 53 | (564, 22871, 0, 11), -- Teron 54 | (564, 22947, 0, 11), -- Mother Shahraz 55 | (564, 22948, 0, 11), -- Gurtogg 56 | (564, 22917, 0, 11), -- Illidan 57 | -- ZA 58 | (568, 23574, 0, 12), -- Akilzon 59 | (568, 23578, 0, 12), -- Janalai 60 | (568, 24239, 0, 12), -- Hexlord 61 | (568, 23577, 0, 12), -- Halazzi 62 | (568, 23576, 0, 12), -- Narolakk 63 | (568, 23863, 0, 12), -- Zuljin 64 | -- SWP 65 | (580, 24882, 0, 19), -- Brutallus 66 | (580, 25038, 0, 19), -- Felmyst 67 | (580, 25840, 0, 19), -- Muru 68 | (580, 25315, 0, 19), -- Kiljaeden 69 | -- TBC 5man Heroics 70 | (269, 17881, 0, 8), -- Aeonus, The Black Morass 71 | (540, 16808, 0, 8), -- Warchief Kargath Bladefist, Shattered Halls 72 | (542, 17377, 0, 8), -- Keli'dan the Breaker, Blood Furnace 73 | (543, 18433, 0, 8), -- Omor the Unscarred, Hellfire Ramparts 74 | (545, 17798, 0, 8), -- Warlord Kalithresh, The Steamvault 75 | (546, 17882, 0, 8), -- The Black Stalker, The Underbog 76 | (547, 17942, 0, 8), -- Quagmirran, Slave Pens 77 | (552, 20912, 0, 8), -- Harbinger Sykriss, The Arcatraz 78 | (553, 17977, 0, 8), -- Warp Splinter, The Botanica 79 | (554, 19220, 0, 8), -- Pathaleon the Calculator, The Mechanar 80 | (555, 18708, 0, 8), -- Murmur, Shadow Labyrinth 81 | (556, 18473, 0, 8), -- Talon King Ikiss, Sethekk Halls 82 | (557, 18344, 0, 8), -- Nexus-Prince Shaffar, Mana-Tombs 83 | (558, 18373, 0, 8), -- Talon King Ikiss, Auchenai Crypts 84 | (560, 18096, 0, 8), -- The Escape From Durnholde 85 | (585, 24664, 0, 8); -- Karl-Heinz Sonnenfurz, Magister's Terrace 86 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_ai_gruul_magtheridon.sql: -------------------------------------------------------------------------------- 1 | -- ************************************************************************ 2 | -- Possible values for `Target`: 3 | SET @TARGET_NONE = 0; -- For spells without target. 4 | SET @TARGET_SELF = 1; -- Self cast. 5 | SET @TARGET_VICTIM = 2; -- Our current target. (ie: highest aggro) 6 | SET @TARGET_HOSTILE_AGGRO_FROM_TOP= 3; -- Position (TargetArg2) in the threat list counted from top. TargetArg = max/min range. Fallback to GetVictim(). 7 | SET @TARGET_HOSTILE_AGGRO_FROM_BOTTOM = 4; -- Position (TargetArg2) in the threat list counted from bottom. TargetArg = max/min range. Fallback to GetVictim(). 8 | SET @TARGET_HOSTILE_RANDOM = 5; -- Just any random player on our threat list. TargetArg = max/min range. 9 | SET @TARGET_HOSTILE_RANDOM_NOT_TOP = 6; -- Just any random player on our threat list except the current target. TargetArg = max/min range. 10 | SET @TARGET_PLAYER_DISTANCE = 18; -- All players in range. TargetArg = max/min range. 11 | -- ************************************************************************ 12 | 13 | DELETE FROM `zone_difficulty_mythicmode_ai` WHERE `CreatureEntry` IN (18831, 18832, 18834, 19044, 19389, 21350, 17257); 14 | INSERT INTO `zone_difficulty_mythicmode_ai` (`CreatureEntry`, `Chance`, `Spell`, `Spellbp0`, `Spellbp1`, `Spellbp2`, `Target`, `TargetArg`, `TargetArg2`, `Delay`, `Cooldown`, `Repetitions`, `Enabled`, `TriggeredCast`, `Comment`) VALUES 15 | -- Magtheridon's Lair 16 | -- (17257, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 1, 1, 'Magtheridon, Magtheridon\'s Lair. - Nothing yet'); 17 | -- Gruul's Lair 18 | (18831, 100, 19784, 0, 0, 0, @TARGET_HOSTILE_RANDOM, 0, 0, 30000, 5000, 0, 1, 1, 'Maulgar, Gruul\'s Lair. Dark Iron Bomb on a random player after 30s every 5s.'), 19 | (18832, 100, 6726, 0, 0, 0, @TARGET_PLAYER_DISTANCE, 0, 50, 28000, 30000, 0, 1, 1, 'Krosh Firehand, Gruul\'s Lair. 5sec Silence on all players in 50m after 28s every 30s.'), 20 | (18834, 100, 69969, 0, 0, 0, @TARGET_PLAYER_DISTANCE, 0, 50, 58000, 60000, 0, 1, 1, 'Olm the Summoner, Gruul\'s Lair. Curse of Doom (12s) on all players in 50m after 58s every 60s.'), 21 | (19044, 100, 39965, 500, 0, 0, @TARGET_PLAYER_DISTANCE, 0, 10, 33000, 30000, 0, 1, 1, 'Gruul, Gruul\'s Lair. Frost Grenade on all players in 10m after 33s every 30s.'), 22 | (19044, 100, 51758, 0, 0, 0, @TARGET_SELF, 0, 0, 25000, 120000, 0, 1, 1, 'Gruul, Gruul\'s Lair. Fire Reflection on self after 25s every 120s.'), 23 | (19044, 100, 51763, 0, 0, 0, @TARGET_SELF, 0, 0, 55000, 120000, 0, 1, 1, 'Gruul, Gruul\'s Lair. Frost Reflection on self after 55s every 120s.'), 24 | (19044, 100, 51764, 0, 0, 0, @TARGET_SELF, 0, 0, 85000, 120000, 0, 1, 1, 'Gruul, Gruul\'s Lair. Shadow Reflection on self after 85s every 120s.'), 25 | (19044, 100, 51766, 0, 0, 0, @TARGET_SELF, 0, 0, 115000, 120000, 0, 1, 1, 'Gruul, Gruul\'s Lair. Arcane Reflection on self after 115s every 120s.'), 26 | (19389, 30, 20508, 0, 0, 0, @TARGET_HOSTILE_RANDOM_NOT_TOP, 0, 0, 5000, 12000, 0, 1, 1, 'Lair Brute, Gruul\'s Lair. Charge with AE knockback on a random player except the MT after 5s every 12s.'), 27 | (21350, 30, 851, 0, 0, 0, @TARGET_HOSTILE_RANDOM_NOT_TOP, 0, 0, 5000, 2000, 0, 1, 1, 'Gronn-Priest, Gruul\'s Lair. Sheep on a random player except the MT after 5s every 2s.'), 28 | (21350, 100, 38019, 0, 0, 0, @TARGET_SELF, 0, 0, 5000, 10000, 0, 1, 1,'Gronn-Priest, Gruul\'s Lair. Summon Water Elemental after 5s every 10s.'); 29 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_creatureoverrides.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `zone_difficulty_mythicmode_creatureoverrides`; 2 | CREATE TABLE `zone_difficulty_mythicmode_creatureoverrides` ( 3 | `CreatureEntry` INT NOT NULL DEFAULT 0, 4 | `HPModifier` FLOAT NOT NULL DEFAULT 1, 5 | `HPModifierNormal` FLOAT NOT NULL DEFAULT 1, 6 | `Enabled` TINYINT UNSIGNED DEFAULT 1, 7 | `Comment` TEXT 8 | ); 9 | 10 | DELETE FROM `zone_difficulty_mythicmode_creatureoverrides`; 11 | INSERT INTO `zone_difficulty_mythicmode_creatureoverrides` (`CreatureEntry`, `HPModifier`, `HPModifierNormal`, `Enabled`, `Comment`) VALUES 12 | (1128001, 1, 1, 1, 'Chromie NPC - prevent changing hp.'), 13 | (18831, 1.8, 1, 1, 'Maulgar, Gruul\'s Lair HPx1.8'), 14 | (19044, 1.8, 1, 1, 'Gruul, Gruul\'s Lair HPx1.8'), 15 | (17257, 1.8, 1, 1, 'Magtheridon, Magtheridon\'s Lair HPx1.8'), 16 | (17881, 3.2, 1, 1, 'Aeonus, Black Morass HPx3.2'), 17 | -- Serpentshrine Cavern 18 | (21216, 1.5, 1, 1, 'Hydross, SSC HPx3.5'), 19 | (21217, 1.5, 1, 1, 'Lurker, SSC HPx3.5'), 20 | (21215, 1.5, 1, 1, 'Leotheras, SSC HPx3.5'), 21 | (21213, 1.5, 1, 1, 'Morogrim, SSC HPx3.5'), 22 | (21214, 1.5, 1, 1, 'Karathress, SSC HPx3.5'), 23 | (21964, 1.5, 1, 1, 'Caribdis, SSC HPx2.5'), 24 | (21966, 1.5, 1, 1, 'Sharkkis, SSC HPx2.5'), 25 | (21965, 1.5, 1, 1, 'Tidalvess, SSC HPx2.5'), 26 | (21212, 1.5, 1, 1, 'Vashj, SSC HPx3.5'), 27 | -- Hyjal 28 | (17767, 1.5, 1, 1, 'Rage Winterchill HPx3.5'), 29 | (17808, 1.5, 1, 1, 'Anetheron SSC HPx3.5'), 30 | (17888, 1.5, 1, 1, 'Kazrogal, SSC HPx3.5'), 31 | (17842, 1.5, 1, 1, 'Azgalor, SSC HPx3.5'), 32 | (17968, 1.5, 1, 1, 'Archimonde, SSC HPx3.5'), 33 | -- Black Temple 34 | (22887, 3.5, 2.2, 1, 'Najentus, Black Temple HPx3.5'), 35 | (22898, 3.5, 2.2, 1, 'Supremus, Black Temple HPx3.5'), 36 | (22841, 3.5, 2.2, 1, 'Shade of Akama, Black Temple HPx3.5'), 37 | (22871, 3.2, 2.2, 1, 'Teron Gorefiend, Black Temple HPx3.2'), 38 | (23111, 1, 1, 1, 'Shadowy Construct - prevent changing hp.'), 39 | (22948, 3.2, 2.2, 1, 'Gurtogg Bloodboil, Black Temple HPx3.2'), 40 | (22856, 3, 2.2, 1, 'Reliquary of the Lost, Black Temple HPx3'), 41 | (23418, 3, 2.2, 1, 'Essence of Suffering, Black Temple HPx3'), 42 | (23419, 2, 1.5, 1, 'Essence of Desire, Black Temple HPx2'), 43 | (23420, 3, 2.2, 1, 'Essence of Anger, Black Temple HPx3'), 44 | (22947, 3.5, 2.3, 1, 'Mother Shahraz, Black Temple HPx3.5'), 45 | (23426, 3.5, 2.3, 1, 'Illidari Council, Black Temple HPx3.5'), 46 | (22949, 3.5, 2.3, 1, 'Gathios, Black Temple HPx3.5'), 47 | (22950, 3.5, 2.3, 1, 'Zerevor, Black Temple HPx3.5'), 48 | (22951, 3.5, 2.3, 1, 'Malande, Black Temple HPx3.5'), 49 | (22952, 3.5, 2.3, 1, 'Veras, Black Temple HPx3.5'), 50 | (22917, 3.2, 2.3, 1, 'Illidan, Black Temple HPx3.2'), 51 | -- Zul'aman 52 | (23574, 3.5, 2.3, 1, 'Akilzon 3.5x mythic 2.3x normal hp'), 53 | (23578, 3.5, 2.3, 1, 'Janalai 3.5x mythic 2.3x normal hp'), 54 | (24239, 3.5, 2.3, 1, 'Hexlord 3.5x mythic 2.3x normal hp'), 55 | (23577, 3.5, 2.3, 1, 'Halazzi (lynx) 3.5x mythic 2.3x normal hp'), 56 | (24144, 3.5, 2.3, 1, 'Halazzi (troll) 3.5x mythic 2.3x normal hp'), 57 | (24143, 3.5, 2.3, 1, 'Spirit of the Lynx 3.5x mythic 2.3x normal hp'), 58 | (23576, 3.5, 2.3, 1, 'Narolakk 3.5x mythic 2.3x normal hp'), 59 | (23863, 3.5, 2.5, 1, 'Zuljin 3.5x mythic 2.5x normal hp'), 60 | -- Sunwell Plateau 61 | (24850, 3.5, 2.3, 1, 'Kalecgos 3.5x mythic 2.3x normal hp'), 62 | (24891, 3.5, 2.3, 1, 'Kalec 3.5x mythic 2.3x normal hp'), 63 | (24892, 3.5, 2.3, 1, 'Sarthrovarr 3.5x mythic 2.3x normal hp'), 64 | (24882, 2.3, 1.8, 1, 'Brutallus 2.3x mythic 1.8x normal hp'), 65 | (25038, 2.3, 1.8, 1, 'Felmyst 2.3x mythic 1.8x normal hp'), 66 | (25166, 3.5, 2.5, 1, 'Alythess 3.5x mythic 2.5x normal hp'), 67 | (25165, 3.5, 2.5, 1, 'Sacrolash 3.5x mythic 2.5x normal hp'), 68 | (25741, 3.5, 2.5, 1, 'Muru 3.5x mythic 2.5x normal hp'), 69 | (25840, 3.5, 2.5, 1, 'Entropius 3.5x mythic 2.5x normal hp'), 70 | (25315, 3, 2.1, 1, 'Kiljaeden 3x mythic 2.1x normal hp'); 71 | 72 | -------------------------------------------------------------------------------- /src/cs_zone_difficulty.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 3 | */ 4 | 5 | #include "Chat.h" 6 | #include "ZoneDifficulty.h" 7 | 8 | using namespace Acore::ChatCommands; 9 | 10 | class zone_difficulty_commandscript : public CommandScript 11 | { 12 | public: 13 | zone_difficulty_commandscript() : CommandScript("zone_difficulty_commandscript") {} 14 | 15 | ChatCommandTable GetCommands() const override 16 | { 17 | static ChatCommandTable zonedifficultyTable = 18 | { 19 | { "tiers", HandleMythicTiers, SEC_GAMEMASTER, Console::Yes }, 20 | { "showpoints", HandleMythicShowPoints, SEC_GAMEMASTER, Console::Yes }, 21 | { "updatepoints", HandleMythicUpdatePoints, SEC_ADMINISTRATOR, Console::Yes }, 22 | }; 23 | 24 | static ChatCommandTable commandTable = 25 | { 26 | { "mythic", zonedifficultyTable }, 27 | }; 28 | 29 | return commandTable; 30 | } 31 | 32 | static bool HandleMythicShowPoints(ChatHandler* handler, Optional player) 33 | { 34 | if (!player) 35 | player = PlayerIdentifier::FromTargetOrSelf(handler); 36 | 37 | if (!player) 38 | return false; 39 | 40 | if (!player->IsConnected()) 41 | { 42 | std::string name; 43 | sCharacterCache->GetCharacterNameByGuid(player->GetGUID(), name); 44 | handler->SendErrorMessage(LANG_PLAYER_NOT_EXIST_OR_OFFLINE, name); 45 | return false; 46 | } 47 | 48 | bool hasAnyScore = false; 49 | for (int i = 1; i <= TYPE_MAX_TIERS; ++i) 50 | { 51 | if (uint32 score = player->GetConnectedPlayer()->GetPlayerSetting(ModZoneDifficultyString + "score", i).value) 52 | { 53 | handler->SendSysMessage(Acore::StringFormat("Found score {} for {} (Tier ID: {})", score, sZoneDifficulty->GetContentTypeString(i), i)); 54 | hasAnyScore = true; 55 | } 56 | } 57 | 58 | if (!hasAnyScore) 59 | handler->SendSysMessage("Player doesn't have any score in any category."); 60 | 61 | return true; 62 | } 63 | 64 | static bool HandleMythicUpdatePoints(ChatHandler* handler, Optional player, uint32 index, int32 points) 65 | { 66 | if (!player) 67 | player = PlayerIdentifier::FromTargetOrSelf(handler); 68 | 69 | if (!player) 70 | return false; 71 | 72 | if (!player->IsConnected()) 73 | { 74 | std::string name; 75 | sCharacterCache->GetCharacterNameByGuid(player->GetGUID(), name); 76 | handler->SendErrorMessage(LANG_PLAYER_NOT_EXIST_OR_OFFLINE, name); 77 | return false; 78 | } 79 | 80 | int32 score = player->GetConnectedPlayer()->GetPlayerSetting(ModZoneDifficultyString + "score", index).value + points; 81 | 82 | if (score < 0) 83 | score = 0; 84 | 85 | player->GetConnectedPlayer()->UpdatePlayerSetting(ModZoneDifficultyString + "score", index, score); 86 | 87 | if (points < 0) 88 | handler->SendSysMessage(Acore::StringFormat("Player {} has lost {} points in category {}.", player->GetName(), -points, sZoneDifficulty->GetContentTypeString(index))); 89 | else 90 | handler->SendSysMessage(Acore::StringFormat("Player {} has gained {} points in category {}.", player->GetName(), points, sZoneDifficulty->GetContentTypeString(index))); 91 | 92 | return true; 93 | } 94 | 95 | static bool HandleMythicTiers(ChatHandler* handler) 96 | { 97 | for (int i = 1; i <= TYPE_MAX_TIERS; ++i) 98 | handler->SendSysMessage(Acore::StringFormat("{} - {}", i, sZoneDifficulty->GetContentTypeString(i), i)); 99 | 100 | return true; 101 | } 102 | }; 103 | 104 | void AddSC_zone_difficulty_commandscript() 105 | { 106 | new zone_difficulty_commandscript(); 107 | } 108 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_spelloverrides.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `zone_difficulty_spelloverrides`; 2 | CREATE TABLE `zone_difficulty_spelloverrides` ( 3 | `SpellID` INT NOT NULL DEFAULT 0, 4 | `MapId` INT NOT NULL DEFAULT 0, -- ID of the map for this line to be relevant. 0 for all maps 5 | `NerfValue` FLOAT NOT NULL DEFAULT 1, 6 | `ModeMask` TINYINT DEFAULT 1, -- Modes for this multiplier to be enabled. 1 = normal 64 = mythic 0 = disabled 7 | `Comment` TEXT 8 | ); 9 | 10 | DELETE FROM `zone_difficulty_spelloverrides` WHERE `SpellID` IN (53652, 53654, 52752, 47753, 18562, 25516, 36240, 31850, 31851, 31852, 66235, 37641, 37036, 36132, 37120, 33031, 34121, 35181, 36971, 31249, 31250, 31304, 31341, 31944, 31608, 39878, 42052, 40314, 40175, 40175, 41303, 41360, 40827, 40869, 40870, 40871, 41001, 42005, 41078, 41131); 11 | INSERT INTO `zone_difficulty_spelloverrides` (`SpellID`, `MapId`, `NerfValue`, `ModeMask`, `Comment`) VALUES 12 | (53652, 0, 1, 65, 'Beacon of Light - Skip nerf.'), 13 | (53654, 0, 1, 65, 'Beacon of Light 2 (Flash of Light, Holy Shock) - Skip nerf.'), 14 | (52752, 0, 1, 65, 'Ancestral Awakening - Skip nerf.'), 15 | (47753, 0, 1, 65, 'Divine Aegis - Skip nerf.'), 16 | (18562, 0, 1, 65, 'Swiftmend - Skip nerf.'), 17 | (25516, 0, 1, 65, 'AQ20 Andorov Healing - Skip nerf.'), 18 | (36240, 0, 1, 65, 'Gruul Cave In - Skip buff.'), 19 | (34435, 0, 1, 65, 'Magtheridon - Warder - Rain of Fire Skip buff.'), 20 | (31850, 0, 1, 65, 'Ardent Defender - Absorb - Skip nerf'), 21 | (31851, 0, 1, 65, 'Ardent Defender - Absorb - Skip nerf'), 22 | (31852, 0, 1, 65, 'Ardent Defender - Absorb - Skip nerf'), 23 | (66235, 0, 1, 65, 'Ardent Defender - Heal - Skip nerf'), 24 | (37641, 548, 1, 65, 'Serpentshrine Cavern - Leotheras - Whirlwind (dot)'), 25 | (37036, 550, 0.20, 65, 'Tempest Keep - Master Engineer Telonicus Bomb Damage Nerf'), 26 | (36132, 550, 1, 65, 'Tempest Keep - Bloodwarder Marshal \'Whirlwind\''), 27 | (37120, 550, 1, 65, 'Tempest Keep - Tempest-Smith \'Fragmentation Bomb\''), 28 | (33031, 550, 1.15, 65, 'Tempest Keep - Solarian \'Arcane Missiles\''), 29 | (34121, 550, 1, 65, 'Tempest Keep - Al\'ar Flame Buffet'), 30 | (35181, 550, 2, 65, 'Tempest Keep - Al\'ar Dive Bomb spread damage'), 31 | (36971, 550, 1, 65, 'Tempest Keep - Grand Astromancer Capernian - Fireball'), 32 | (31249, 534, 1, 65, 'The Battle For Mount Hyjal - Rage Winterchill - Icebolt'), 33 | (31250, 534, 1, 65, 'The Battle For Mount Hyjal - Rage Winterchill - Frost Nova'), 34 | (31304, 534, 1, 65, 'The Battle For Mount Hyjal - Azgalor infernal - Immolation'), 35 | (31341, 534, 1, 65, 'The Battle For Mount Hyjal - Azgalor - Rain of Fire (effect)'), 36 | (31944, 534, 1, 65, 'The Battle For Mount Hyjal - Archimonde - Doomfire'), 37 | (31608, 534, 1, 65, 'The Battle For Mount Hyjal - Abomination - Disease Cloud (tick debuff)'), 38 | (39878, 564, 1, 65, 'Black Temple - Najentus - Tidal Burst Effect'), 39 | (42052, 564, 1, 65, 'Black Temple - Supremus - Volcanic Geyser'), 40 | (40314, 564, 1, 65, 'Black Temple - Vengeful Spirit - Spirit Volley'), 41 | (40175, 564, 1, 65, 'Black Temple - Vengeful Spirit - Spirit Chains'), 42 | (40157, 564, 1, 65, 'Black Temple - Vengeful Spirit - Spirit Lance'), 43 | (41303, 564, 1, 65, 'Black Temple - Reliquary of the Lost - Essence of Suffering - Soul Drain'), 44 | (41360, 564, 1, 65, 'Black Temple - Promenade Sentinel - Arcane charge'), -- may not work 45 | (40827, 564, 1, 65, 'Black Temple - Mother Shahraz - Sinful Beam'), 46 | (40869, 564, 1, 65, 'Black Temple - Mother Shahraz - Fatal Attraction'), 47 | (40870, 564, 1, 65, 'Black Temple - Mother Shahraz - Fatal Attraction'), 48 | (40871, 564, 1, 65, 'Black Temple - Mother Shahraz - Fatal Attraction'), 49 | (41001, 564, 1, 65, 'Black Temple - Mother Shahraz - Fatal Attraction'), 50 | (42005, 564, 1, 65, 'Black Temple - Gurtogg Bloodboil - Bloodboil'), 51 | (41078, 564, 1.1, 65, 'Black Temple - Illidan - Shadow Blast'), 52 | (41131, 564, 1.1, 65, 'Black Temple - Illidan - Flame Burst'), 53 | (43137, 568, 1, 65, 'Zul Aman - Zuljin - Zap'), 54 | (43121, 568, 1, 65, 'Zul Aman - Zuljin - Cyclone'), 55 | (43140, 568, 1, 65, 'Zul Aman - Janalai - Flame Breath'), 56 | (45662, 580, 1, 65, 'Felmyst - Encapsulate'), 57 | (45329, 580, 1, 65, 'Lady Sacrolash - Shadow Nova'), 58 | (45342, 580, 1, 65, 'Grand Warlock Alythess - Conflagration (Direct hit)'), 59 | (46768, 580, 1, 65, 'Grand Warlock Alythess - Conflagration (Area hit)'); 60 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_rewards_za.sql: -------------------------------------------------------------------------------- 1 | SET @PRICE := 24; 2 | SET @PRICE2 := 30; 3 | DELETE FROM `zone_difficulty_mythicmode_rewards` WHERE `ContentType` = 12; 4 | INSERT INTO `zone_difficulty_mythicmode_rewards` (`ContentType`, `ItemType`, `Entry`, `Price`, `Enchant`, `EnchantSlot`, `Achievement`, `Enabled`, `Comment`) VALUES 5 | (12, 1, 33281, @PRICE, 0, 0, 691, 1, 'Brooch of Nature\'s Mercy - Akil\'zon'), 6 | (12, 1, 33293, @PRICE, 0, 0, 691, 1, 'Signet of Ancient Magics - Akil\'zon'), 7 | (12, 1, 33297, @PRICE, 0, 0, 691, 1, 'The Savage\'s Choker - Halazzi'), 8 | (12, 1, 33592, @PRICE, 0, 0, 691, 1, 'Cloak of Ancient Rituals - Malacrass'), 9 | (12, 1, 33829, @PRICE, 0, 0, 691, 1, 'Hex Shrunken Head - Malacrass'), 10 | (12, 1, 34029, @PRICE, 0, 0, 691, 1, 'Tiny Voodoo Mask - Malacrass'), 11 | (12, 1, 33828, @PRICE, 0, 0, 691, 1, 'Tome of Diabolic Remedy - Malacrass'), 12 | (12, 1, 33830, @PRICE2, 0, 0, 691, 1, 'Ancient Aqir Artifact - Zul\'jin'), 13 | (12, 1, 33831, @PRICE2, 0, 0, 691, 1, 'Berserker\'s Call - Zul\'jin'), 14 | (12, 1, 33466, @PRICE2, 0, 0, 691, 1, 'Loop of Cursed Bones - Zul\'jin'), 15 | 16 | (12, 2, 33285, @PRICE, 0, 0, 691, 1, 'Fury of the Ursine - Nalorakk'), 17 | (12, 2, 33203, @PRICE, 0, 0, 691, 1, 'Robes of Heavenly Purpose - Nalorakk'), 18 | (12, 2, 33357, @PRICE, 0, 0, 691, 1, 'Footpads of Madness - Jan\'alai'), 19 | (12, 2, 33317, @PRICE, 0, 0, 691, 1, 'Robe of Departed Spirits - Halazzi'), 20 | (12, 2, 33453, @PRICE, 0, 0, 691, 1, 'Hood of Hexing - Malacrass'), 21 | (12, 2, 33463, @PRICE, 0, 0, 691, 1, 'Hood of the Third Eye - Malacrass'), 22 | (12, 2, 33471, @PRICE2, 0, 0, 691, 1, 'Two-toed Sandals - Zul\'jin'), 23 | 24 | (12, 3, 33211, @PRICE, 0, 0, 691, 1, 'Bladeangel\'s Money Belt - Nalorakk'), 25 | (12, 3, 33356, @PRICE, 0, 0, 691, 1, 'Helm of Natural Regeneration - Jan\'alai'), 26 | (12, 3, 33329, @PRICE, 0, 0, 691, 1, 'Shadowtooth Trollskin Cuirass - Jan\'alai'), 27 | (12, 3, 33322, @PRICE, 0, 0, 691, 1, 'Shimmer-pelt Vest - Halazzi'), 28 | (12, 3, 33300, @PRICE, 0, 0, 691, 1, 'Shoulderpads of Dancing Blades - Halazzi'), 29 | (12, 3, 33479, @PRICE2, 0, 0, 691, 1, 'Grimgrin Faceguard - Zul\'jin'), 30 | 31 | (12, 4, 33286, @PRICE, 0, 0, 691, 1, 'Mojo-mender\'s Mask - Akil\'zon'), 32 | (12, 4, 33206, @PRICE, 0, 0, 691, 1, 'Pauldrons of Primal Fury - Nalorakk'), 33 | (12, 4, 33328, @PRICE, 0, 0, 691, 1, 'Arrow-fall Chestguard - Jan\'alai'), 34 | (12, 4, 33533, @PRICE, 0, 0, 691, 1, 'Avalanche Leggings - Halazzi'), 35 | (12, 4, 33432, @PRICE, 0, 0, 691, 1, 'Coif of the Jungle Stalker - Malacrass'), 36 | (12, 4, 33464, @PRICE, 0, 0, 691, 1, 'Hex Lord\'s Voodoo Pauldrons - Malacrass'), 37 | (12, 4, 33469, @PRICE2, 0, 0, 691, 1, 'Hauberk of the Empire\'s Champion - Zul\'jin'), 38 | 39 | (12, 5, 33215, @PRICE, 0, 0, 691, 1, 'Bloodstained Elven Battlevest - Akil\'zon'), 40 | (12, 5, 33216, @PRICE, 0, 0, 691, 1, 'Chestguard of Hidden Purpose - Akil\'zon'), 41 | (12, 5, 33191, @PRICE, 0, 0, 691, 1, 'Jungle Stompers - Nalorakk'), 42 | (12, 5, 33327, @PRICE, 0, 0, 691, 1, 'Mask of Introspection - Nalorakk'), 43 | (12, 5, 33303, @PRICE, 0, 0, 691, 1, 'Skullshatter Warboots - Halazzi'), 44 | (12, 5, 33299, @PRICE, 0, 0, 691, 1, 'Spaulders of the Advocate - Halazzi'), 45 | (12, 5, 33421, @PRICE, 0, 0, 691, 1, 'Battleworn Tuskguard - Malacrass'), 46 | (12, 5, 33446, @PRICE, 0, 0, 691, 1, 'Girdle of Stromgarde\'s Hope - Malacrass'), 47 | (12, 5, 33473, @PRICE2, 0, 0, 691, 1, 'Chestguard of the Warlord - Zul\'jin'), 48 | 49 | (12, 6, 33214, @PRICE, 0, 0, 691, 1, 'Akil\'zon\'s Talonblade - Akil\'zon'), 50 | (12, 6, 33283, @PRICE, 0, 0, 691, 1, 'Amani Punisher - Akil\'zon'), 51 | (12, 6, 33640, @PRICE, 0, 0, 691, 1, 'Fury - Nalorakk'), 52 | (12, 6, 33326, @PRICE, 0, 0, 691, 1, 'Bulwark of the Amani Empire - Jan\'alai'), 53 | (12, 6, 33332, @PRICE, 0, 0, 691, 1, 'Enamelled Disc of Mojo - Jan\'alai'), 54 | (12, 6, 33354, @PRICE, 0, 0, 691, 1, 'Wub\'s Cursed Hexblade - Jan\'alai'), 55 | (12, 6, 33389, @PRICE, 0, 0, 691, 1, 'Dagger of Bad Mojo - Malacrass'), 56 | (12, 6, 33388, @PRICE, 0, 0, 691, 1, 'Heartless - Malacrass'), 57 | (12, 6, 33298, @PRICE, 0, 0, 691, 1, 'Prowler\' Strikeblade - Malacrass'), 58 | (12, 6, 33465, @PRICE, 0, 0, 691, 1, 'Staff of Primal Fury - Malacrass'), 59 | (12, 6, 33474, @PRICE2, 0, 0, 691, 1, 'Ancient Amani Longbow - Zul\'jin'), 60 | (12, 6, 33467, @PRICE2, 0, 0, 691, 1, 'Blade of Twisted Visions - Zul\'jin'), 61 | (12, 6, 33476, @PRICE2, 0, 0, 691, 1, 'Cleaver of the Unforgiving - Zul\'jin'), 62 | (12, 6, 33468, @PRICE2, 0, 0, 691, 1, 'Dark Blessing - Zul\'jin'), 63 | (12, 6, 33478, @PRICE2, 0, 0, 691, 1, 'Jin\'rohk, The Great Apocalypse - Zul\'jin'); 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zone Difficulty Module 2 | 3 | ## What is the purpose of this module? 4 | This module provides a way to nerf or debuff players in order to increase the difficulty of certain dungeons or balance battlegrounds/duels. 5 | 6 | ## How to use this module? 7 | This module reads data from the `zone_difficulty_info` and `zone_difficulty_spelloverrides` table. 8 | `_info` serves to apply nerfs/debuffs per map and per phase. For example, you can nerf healing 9 | by 90% and absorb-effects by 80% while increasing the melee damage players suffer by 50% and reducing the 10 | spell damage players suffer by 30%. That is only inside the Temple of Ahn'Qiraj dungeon (MapId 531) 11 | for all phases (0 = Skip PhaseMask check, 6 = phases 2 and 4) with the following query: 12 | 13 | ```sql 14 | INSERT INTO `zone_difficulty_info` (`MapId`, `PhaseMask`, `HealingNerfValue`, `AbsorbNerfValue`, `MeleeDmgBuffValue`, `SpellDmgBuffValue`, `Enabled`, `Comment`) VALUES 15 | (531, 0, '0.10', '0.20', '1.50', '0.70', 1, 'AQ40 Healing 50% / Absorb 50% Nerf / 50% physical & 30% spell damage buff'); 16 | ``` 17 | 18 | The heal-output will be multiplied by the value you input in `HealingNerfValue` as it follows: 19 | 20 | ```cpp 21 | output = output * HealingNerfValue 22 | ``` 23 | 24 | Using `MapId` 2147483647 will be used for all targets in duels while they're in the zone hardcoded as `DUEL_AREA` (default 2402: Forbidding Sea, Wetlands). 25 | PhaseMask must be 0 for Duels. 26 | 27 | You can also prevent certain spells from being affected at all. See `zone_difficulty_spelloverrides.sql` for examples. 28 | 29 | ## Changing values 30 | 31 | You can edit the `zone_difficulty_info_content.sql` file to apply changes. They will be applied by the autoupdater the next time you restart your server. 32 | Alternatively, you may edit the `zone_difficulty_info` table in your `world` database and use the `reload config` command to reload the values. 33 | 34 | # Mythicmode 35 | 36 | ## How does it work? 37 | 38 | For the Mythicmode, there is an NPC (id 1128001) spawned at the beginning of raids and the daily heroic dungeon, 39 | determined by the quest given from Wind Trader Zhareem in Shattrath. (Addition of WotlK heroics outstanding). 40 | The leader of the party can chose to activate the Mythicmode by talking to the NPC inside the heroic 41 | dungeon / raid. Single players can not use the Mythicmode. In Heroic dungeons, the NPC will despawn 42 | after 60 seconds. The party needs to decide, if they want to play the Mythicmode before this happens. 43 | The last boss of the heroic dungeon will award one score to every player in the heroic dungeon. 44 | 45 | In Raids, the NPC will stay indefinitely. As soon as one raidboss is defeated, the leader can still turn the 46 | Mythicmode off, but no longer on once it is deactivated. Every defeated raidboss grants one score in the 47 | respective category. 48 | 49 | ## Config 50 | 51 | `ModZoneDifficulty.Hardmode.HpModifier = 2.0` determines the default creature hp modifier for Mythicmode. 52 | 53 | ## Tables 54 | `zone_difficulty_instance_saves` creates the tables to store the Mythicmode status and the scores. 55 | No action required. 56 | 57 | `zone_difficulty_creatureoverrides` contains overrides for creature hp values. This is used to vary 58 | certain creatures health from the default value in the conf file. 59 | 60 | `zone_difficulty_mythicmode_creatures` contains gossips and creature positions for the NPCs inside dungeons. 61 | Requires spawning additional NPCs, if more heroic dungeons / raids should be added. 62 | 63 | In heroic dungeons, the default spawn mask should be 1024. The script will change the NPCs phasemask to 64 | 1, if the heroic dungeon is the current daily. In raids, the default spawn mask should be 1. 65 | 66 | `zone_difficulty_instance_data` contains the encounter IDs which should give scores 67 | for the Mythicmode. The encounter IDs are taken from the `creature_template` table. 68 | `OverrideGO` is reserved for future use. `InstanceType` refers to the content level, see the top 69 | of the file for a list. 70 | 71 | `zone_difficulty_mythicmode_rewards` holds the items which can be chosen as a reward for the Mythicmode. 72 | Tho gossips for the reward npc (id 1128002) will automatically expand, depending on the kind and 73 | amount of rows in the table. `ContentType` refers to the content level, `ItemType` refers to the item 74 | category. See the top of the file for a list for both. By adding an enchant id and a slot to the item, 75 | a custom enchant can be applied. 76 | 77 | ## Authors 78 | 79 | - [Nyeriah](https://github.com/Nyeriah) 80 | - [Honey](https://github.com/55Honey) 81 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_rewards_hyjal.sql: -------------------------------------------------------------------------------- 1 | SET @PRICE := 15; 2 | SET @PRICE2 := 20; 3 | DELETE FROM `zone_difficulty_mythicmode_rewards` WHERE `ContentType` = 18; 4 | INSERT INTO `zone_difficulty_mythicmode_rewards` (`ContentType`, `ItemType`, `Entry`, `Price`, `Enchant`, `EnchantSlot`, `Achievement`, `Enabled`, `Comment`) VALUES 5 | (18, 2, 30913, @PRICE2, 0, 0, 695, 1, 'Robes of Rhonin - Archimonde'), 6 | (18, 2, 30885, @PRICE, 0, 0, 695, 1, 'Archbishop\'s Slippers - Anetheron'), 7 | (18, 2, 30894, @PRICE, 0, 0, 695, 1, 'Blue Suede Shoes - Kazrogal'), 8 | (18, 2, 30912, @PRICE2, 0, 0, 695, 1, 'Leggings of Eternity - Archimonde'), 9 | (18, 2, 30916, @PRICE, 0, 0, 695, 1, 'Leggings of Channeled Elements - Kazrogal'), 10 | (18, 2, 30884, @PRICE, 0, 0, 695, 1, 'Hatefury Mantle - Anetheron'), 11 | (18, 2, 30888, @PRICE, 0, 0, 695, 1, 'Anetheron\'s Noose - Anetheron'), 12 | (18, 2, 30895, @PRICE, 0, 0, 695, 1, 'Angelista\'s Sash - Kazrogal'), 13 | (18, 2, 30870, @PRICE, 0, 0, 695, 1, 'Cuffs of Devastation - Rage Winterchill'), 14 | (18, 2, 30871, @PRICE, 0, 0, 695, 1, 'Bracers of Martyrdom - Rage Winterchill'), 15 | 16 | (18, 3, 30905, @PRICE2, 0, 0, 695, 1, 'Midnight Chestguard - Archimonde'), 17 | (18, 3, 30899, @PRICE, 0, 0, 695, 1, 'Don Rodrigo\'s Poncho - Azgalor'), 18 | (18, 3, 30886, @PRICE, 0, 0, 695, 1, 'Enchanted Leather Sandals - Anetheron'), 19 | (18, 3, 30891, @PRICE, 0, 0, 695, 1, 'Black Featherlight Boots - Kazrogal'), 20 | (18, 3, 30898, @PRICE, 0, 0, 695, 1, 'Shady Dealer\'s Pantaloons - Azgalor'), 21 | (18, 3, 30917, @PRICE, 0, 0, 695, 1, 'Razorfury Mantle - Kazrogal'), 22 | (18, 3, 30879, @PRICE, 0, 0, 695, 1, 'Don Alejandro\'s Money Belt - Anetheron'), 23 | (18, 3, 30914, @PRICE, 0, 0, 695, 1, 'Belt of the Crescent Moon - Kazrogal'), 24 | (18, 3, 30863, @PRICE, 0, 0, 695, 1, 'Deadly Cuffs - Rage Winterchill'), 25 | (18, 3, 30868, @PRICE, 0, 0, 695, 1, 'Rejuvenating Bracers - Rage Winterchill'), 26 | 27 | (18, 4, 30887, @PRICE, 0, 0, 695, 1, 'Golden Links of Restoration - Anetheron'), 28 | (18, 4, 30907, @PRICE2, 0, 0, 695, 1, 'Mail of Fevered Pursuit - Archimonde'), 29 | (18, 4, 30880, @PRICE, 0, 0, 695, 1, 'Quickstrider Moccasins - Anetheron'), 30 | (18, 4, 30873, @PRICE, 0, 0, 695, 1, 'Stillwater Boots - Rage Winterchill'), 31 | (18, 4, 30900, @PRICE, 0, 0, 695, 1, 'Bow-stitched Leggings - Azgalor'), 32 | (18, 4, 30893, @PRICE, 0, 0, 695, 1, 'Sun-touched Chain Leggings - Kaz\'rogal'), 33 | (18, 4, 30892, @PRICE, 0, 0, 695, 1, 'Beast-tamer\'s Shoulders - Kaz\'rogal'), 34 | (18, 4, 30919, @PRICE, 0, 0, 695, 1, 'Valestalker Girdle - Kaz\'rogal'), 35 | (18, 4, 30864, @PRICE, 0, 0, 695, 1, 'Bracers of the Pathfinder - Rage Winterchill'), 36 | (18, 4, 30869, @PRICE, 0, 0, 695, 1, 'Howling Wind Bracers - Rage Winterchill'), 37 | 38 | (18, 5, 30904, @PRICE2, 0, 0, 695, 1, 'Savior\'s Grasp - Archimonde'), 39 | (18, 5, 30896, @PRICE, 0, 0, 695, 1, 'Glory of the Defender - Azgalor'), 40 | (18, 5, 30903, @PRICE2, 0, 0, 695, 1, 'Legguards of Endless Rage - Archimonde'), 41 | (18, 5, 30878, @PRICE, 0, 0, 695, 1, 'Glimmering Steel Mantle - Anetheron'), 42 | (18, 5, 30866, @PRICE, 0, 0, 695, 1, 'Blood-stained Pauldrons - Rage Winterchill'), 43 | (18, 5, 30897, @PRICE, 0, 0, 695, 1, 'Girdle of Hope - Azgalor'), 44 | (18, 5, 30915, @PRICE, 0, 0, 695, 1, 'Belt of Seething Fury - Kaz\'rogal'), 45 | (18, 5, 30861, @PRICE, 0, 0, 695, 1, 'Furious Shackles - Rage Winterchill'), 46 | (18, 5, 30862, @PRICE, 0, 0, 695, 1, 'Blessed Adamantite Bracers - Rage Winterchill'), 47 | 48 | (18, 6, 30901, @PRICE, 0, 0, 695, 1, 'Boundless Agony - Azgalor'), 49 | (18, 6, 30865, @PRICE, 0, 0, 695, 1, 'Tracker\'s Blade - Rage Winterchill'), 50 | (18, 6, 30918, @PRICE, 0, 0, 695, 1, 'Hammer of Atonement - Kaz\'rogal'), 51 | (18, 6, 30910, @PRICE2, 0, 0, 695, 1, 'Tempest of Chaos - Archimonde'), 52 | (18, 6, 30874, @PRICE, 0, 0, 695, 1, 'The Unbreakable Will - Anetheron'), 53 | (18, 6, 30881, @PRICE, 0, 0, 695, 1, 'Blade of Infamy - Anetheron'), 54 | (18, 6, 30883, @PRICE, 0, 0, 695, 1, 'Pillar of Ferocity - Anetheron'), 55 | (18, 6, 30908, @PRICE2, 0, 0, 695, 1, 'Apostle of Argus - Archimonde'), 56 | (18, 6, 30902, @PRICE2, 0, 0, 695, 1, 'Cataclysm\'s Edge - Archimonde'), 57 | (18, 6, 30906, @PRICE2, 0, 0, 695, 1, 'Bristleblitz Striker - Archimonde'), 58 | (18, 6, 30911, @PRICE2, 0, 0, 695, 1, 'Scepter of Purification - Archimonde'), 59 | (18, 6, 30872, @PRICE, 0, 0, 695, 1, 'Chronicle of Dark Secrets - Rage Winterchill'), 60 | (18, 6, 30882, @PRICE, 0, 0, 695, 1, 'Bastion of Light - Anetheron'), 61 | (18, 6, 30909, @PRICE2, 0, 0, 695, 1, 'Antonidas\'s Aegis of Rapt Concentration - Archimonde'), 62 | (18, 6, 30889, @PRICE, 0, 0, 695, 1, 'Kaz\'rogal\'s Hardened Heart - Kaz\'rogal'); 63 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_ai_cavernsoftime.sql: -------------------------------------------------------------------------------- 1 | -- ************************************************************************ 2 | -- Possible values for `Target`: 3 | SET @TARGET_NONE = 0; -- For spells without target. 4 | SET @TARGET_SELF = 1; -- Self cast. 5 | SET @TARGET_VICTIM = 2; -- Our current target. (ie: highest aggro) 6 | SET @TARGET_HOSTILE_AGGRO_FROM_TOP= 3; -- Position (TargetArg2) in the threat list counted from top. TargetArg = max/min range. Fallback to GetVictim(). 7 | SET @TARGET_HOSTILE_AGGRO_FROM_BOTTOM = 4; -- Position (TargetArg2) in the threat list counted from bottom. TargetArg = max/min range. Fallback to GetVictim(). 8 | SET @TARGET_HOSTILE_RANDOM = 5; -- Just any random player on our threat list. TargetArg = max/min range. 9 | SET @TARGET_HOSTILE_RANDOM_NOT_TOP = 6; -- Just any random player on our threat list except the current target. TargetArg = max/min range. 10 | SET @TARGET_PLAYER_DISTANCE = 18; -- All players in range. TargetArg = max/min range. 11 | -- ************************************************************************ 12 | 13 | DELETE FROM `zone_difficulty_mythicmode_ai` WHERE CreatureEntry IN (21136, 21137, 21138, 21139, 17879, 17881, 18701, 21818); 14 | INSERT INTO `zone_difficulty_mythicmode_ai` (`CreatureEntry`, `Chance`, `Spell`, `Spellbp0`, `Spellbp1`, `Spellbp2`, `Target`, `TargetArg`, `TargetArg2`, `Delay`, `Cooldown`, `Repetitions`, `Enabled`, `TriggeredCast`, `Comment`) VALUES 15 | -- Black Morrass Trash 16 | (21136, 30, 43242, 0, 0, 0, @TARGET_SELF, 0, 0, 2000, 0, 1, 1, 1, 'Infinite Chronomancer, Black Morrass. Haste (Movement and cast) on self after 2 seconds once. 30% Chance.'), 17 | (21136, 15, 51758, 0, 0, 0, @TARGET_SELF, 0, 0, 2000, 20000, 0, 1, 1, 'Infinite Chronomancer, Black Morrass. Fire Reflection on self after 2s every 20s. 15% Chance'), 18 | (21136, 15, 51763, 0, 0, 0, @TARGET_SELF, 0, 0, 4000, 20000, 0, 1, 1, 'Infinite Chronomancer, Black Morrass. Frost Reflection on self after 4s every 20s. 15% Chance'), 19 | (21136, 15, 51764, 0, 0, 0, @TARGET_SELF, 0, 0, 6000, 20000, 0, 1, 1, 'Infinite Chronomancer, Black Morrass. Shadow Reflection on self after 6s every 20s. 15% Chance'), 20 | (21136, 15, 51766, 0, 0, 0, @TARGET_SELF, 0, 0, 8000, 20000, 0, 1, 1, 'Infinite Chronomancer, Black Morrass. Arcane Reflection on self after 8s every 20s. 15% Chance'), 21 | (21137, 30, 43242, 0, 0, 0, @TARGET_SELF, 0, 0, 2000, 0, 1, 1, 1, 'Infinite Assassin, Black Morrass. Haste (Movement and cast) on self after 2 seconds once. 30% chance.'), 22 | (21137, 15, 51758, 0, 0, 0, @TARGET_SELF, 0, 0, 2000, 20000, 0, 1, 1, 'Infinite Assassin, Black Morrass. Fire Reflection on self after 2s every 20s. 15% Chance'), 23 | (21137, 15, 51763, 0, 0, 0, @TARGET_SELF, 0, 0, 4000, 20000, 0, 1, 1, 'Infinite Assassin, Black Morrass. Frost Reflection on self after 4s every 20s. 15% Chance'), 24 | (21137, 15, 51764, 0, 0, 0, @TARGET_SELF, 0, 0, 6000, 20000, 0, 1, 1, 'Infinite Assassin, Black Morrass. Shadow Reflection on self after 6s every 20s. 15% Chance'), 25 | (21137, 15, 51766, 0, 0, 0, @TARGET_SELF, 0, 0, 8000, 20000, 0, 1, 1, 'Infinite Assassin, Black Morrass. Arcane Reflection on self after 8s every 20s. 15% Chance'), 26 | (21138, 30, 43242, 0, 0, 0, @TARGET_SELF, 0, 0, 2000, 0, 1, 1, 1, 'Infinite Executioner, Black Morrass. Haste (Movement and cast) on self after 2 seconds once. 30% chance.'), 27 | (21138, 30, 40545, 0, 0, 0, @TARGET_SELF, 0, 0, 1000, 20000, 0, 0, 1, 'Infinite Executioner, Black Morrass. Unholy Growth on self after 1s every 20s. 10s cast time. 30% chance.'), 28 | (21139, 30, 43242, 0, 0, 0, @TARGET_SELF, 0, 0, 2000, 0, 1, 1, 1, 'Infinite Vanquisher, Black Morrass. Haste (Movement and cast) on self after 2 seconds once. 30% chance.'), 29 | (21139, 30, 40545, 0, 0, 0, @TARGET_SELF, 0, 0, 1000, 20000, 0, 0, 1, 'Infinite Vanquisher, Black Morrass. Unholy Growth on self after 1s every 20s. 10s cast time. 30% chance.'), 30 | (21818, 20, 40545, 0, 0, 0, @TARGET_SELF, 0, 0, 1000, 20000, 0, 0, 1, 'Infinite Whelp, Black Morrass. Unholy Growth on self after 1s every 20s. 10s cast time. 20% chance.'), 31 | -- Black Morrass Bosses 32 | (17879, 100, 55948, 0, 0, 0, @TARGET_SELF, 0, 0, 15000, 10000, 0, 1, 1, 'Chrono Lord Deja, Black Morrass. Grow on self after 15s every 10s.'), 33 | (17881, 100, 32663, 0, 0, 0, @TARGET_SELF, 0, 0, 15000, 8000, 0, 1, 1, 'Aeonus, Black Morrass. Summon Dark Vortex after 15s every 8s.'), 34 | (18701, 100, 7, 0, 0, 0, @TARGET_SELF, 0, 2, 60000, 0, 1, 1, 1, 'Dark Vortex, summoned by Aeonus Black, Morrass (Line above). Kill self after 60s.'), 35 | (18701, 30, 9906, 0, 0, 0, @TARGET_SELF, 0, 2, 3000, 10000, 0, 1, 1, 'Dark Vortex, summoned by Aeonus Black, Morrass (Line above). Reflect for 5s every 10s after 3s. 30% Chance.'), 36 | (18701, 30, 63240, 0, 0, 0, @TARGET_SELF, 0, 2, 1000, 20000, 0, 1, 1, 'Dark Vorte, summoned by Aeonus Black, Morrass (Line above). Thorns for 10s every 20s after 1s. 30% Chance.'); 37 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_disallowed_buffs.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `zone_difficulty_disallowed_buffs`; 2 | CREATE TABLE `zone_difficulty_disallowed_buffs` ( 3 | `MapID` INT NOT NULL DEFAULT 0, 4 | `DisallowedBuffs` TEXT, 5 | `Enabled` TINYINT DEFAULT 1, 6 | `Comment` TEXT, 7 | PRIMARY KEY (`MapID`) 8 | ); 9 | 10 | DELETE FROM `zone_difficulty_disallowed_buffs`; 11 | INSERT INTO `zone_difficulty_disallowed_buffs` (`MapID`, `DisallowedBuffs`, `Enabled`, `Comment`) VALUES 12 | # BGs 13 | (30, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Alterac Valley: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 14 | (489, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Warsong Gulch: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 15 | (529, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Arathi Basin: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 16 | (556, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Eye of the Storm: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 17 | (559, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Ring of Trials: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 18 | (562, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Blade\'s Edge Arena: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 19 | (572, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Ruins of Lordaeron: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 20 | (617, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Dalaran Arena: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 21 | (618, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Ring of Valor: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 22 | # Raids 23 | # (229, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Blackrock Spire: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 24 | (409, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Molten Core: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 25 | (249, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Onyxia\'s Lair: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 26 | (469, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Blackwing Lair: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 27 | (509, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Ruins of Ahn\'Qiraj: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 28 | (309, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Zul Gurub: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'), 29 | (531, '15366 16609 22888 24425 22817 22818 22820 15123', 1, 'Forbid in Temple of Ahn\'Qiraj: Songflower Serenade, Warchiefs Blessing, Rallying Cry of the Dragonslayer, Spirit of Zandalar, Fengus\' Ferocity\', Mol\'dar\'s Moxie, Slip\'kik\'s Savvy, Resist Fire from Scarshield Spellbinder'); 30 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_t5_rewards.sql: -------------------------------------------------------------------------------- 1 | SET @PRICE := 18; 2 | SET @PRICE2 := 24; 3 | DELETE FROM `zone_difficulty_mythicmode_rewards` WHERE `ContentType` = 10; 4 | INSERT INTO `zone_difficulty_mythicmode_rewards` (`ContentType`, `ItemType`, `Entry`, `Price`, `Enchant`, `EnchantSlot`, `Achievement`, `Enabled`, `Comment`) VALUES 5 | (10, 1, 33055, @PRICE, 0, 0, 694, 1, 'Band of Vile Aggression - Hydross'), 6 | (10, 1, 30052, @PRICE, 0, 0, 694, 1, 'Ring of Lethality - Hydross'), 7 | (10, 1, 30051, @PRICE, 0, 0, 694, 1, 'Idol of the Crescent Goddess - Hydross'), 8 | (10, 1, 30061, @PRICE, 0, 0, 694, 1, 'Ancestral Ring of Conquest - Lurker'), 9 | (10, 1, 33054, @PRICE, 0, 0, 694, 1, 'The Seal of Danzalar - Lurker'), 10 | (10, 1, 30098, @PRICE, 0, 0, 694, 1, 'Razor-Scale Battlecloak - Morogrim'), 11 | (10, 1, 33058, @PRICE, 0, 0, 694, 1, 'Band of the Vigilant - Morogrim'), 12 | (10, 1, 30083, @PRICE, 0, 0, 694, 1, 'Ring of Sundered Souls - Morogrim'), 13 | (10, 1, 30110, @PRICE2, 0, 0, 694, 1, 'Coral Band of the Revived - Vashj'), 14 | (10, 1, 30109, @PRICE2, 0, 0, 694, 1, 'Ring of Endless Coils - Vashj'), 15 | 16 | (10, 1, 30664, @PRICE, 0, 0, 694, 1, 'Living Root of the Wildheart - Hydross'), 17 | (10, 1, 30629, @PRICE, 0, 0, 694, 1, 'Scarab of Displacement - Hydross'), 18 | (10, 1, 30665, @PRICE, 0, 0, 694, 1, 'Earring of Soulful Meditation - Lurker'), 19 | (10, 1, 30063, @PRICE, 0, 0, 694, 1, 'Libram of Absolute Truth - Lurker'), 20 | (10, 1, 30059, @PRICE, 0, 0, 694, 1, 'Choker of Animalistic Fury - Lurker'), 21 | (10, 1, 30627, @PRICE, 0, 0, 694, 1, 'Tsunami Talisman - Leotheras'), 22 | (10, 1, 30720, @PRICE, 0, 0, 694, 1, 'Serpent-Coil Braid - Morogrim'), 23 | (10, 1, 30008, @PRICE, 0, 0, 694, 1, 'Pendant of the Lost Ages - Morogrim'), 24 | (10, 1, 30099, @PRICE, 0, 0, 694, 1, 'Frayed Tether of the Drowned - Karathress'), 25 | (10, 1, 30663, @PRICE, 0, 0, 694, 1, 'Fathom-Brooch of the Tidewalker - Karathress'), 26 | (10, 1, 30626, @PRICE, 0, 0, 694, 1, 'Sextant of Unstable Currents - Karathress'), 27 | (10, 1, 30621, @PRICE2, 0, 0, 694, 1, 'Prism of Inner Calm - Vashj'), 28 | 29 | (10, 2, 30056, @PRICE, 0, 0, 694, 1, 'Robe of Hateful Echoes - Hydross'), 30 | (10, 2, 30050, @PRICE, 0, 0, 694, 1, 'Boots of the Shifting Nightmare - Hydross'), 31 | (10, 2, 32516, @PRICE, 0, 0, 694, 1, 'Wraps of Purification - Hydross'), 32 | (10, 2, 30064, @PRICE, 0, 0, 694, 1, 'Cord of Screaming Terrors - Lurker'), 33 | (10, 2, 30067, @PRICE, 0, 0, 694, 1, 'Velvet Boots of the Guardian - Lurker'), 34 | (10, 2, 30079, @PRICE, 0, 0, 694, 1, 'Illidari Shoulderpads - Morogrim'), 35 | (10, 2, 30100, @PRICE, 0, 0, 694, 1, 'Soul-Strider Boots - Karathress'), 36 | (10, 2, 30107, @PRICE2, 0, 0, 694, 1, 'Vestments of the Sea-Witch - Vashj'), 37 | 38 | (10, 3, 30055, @PRICE, 0, 0, 694, 1, 'Shoulderpads of the Stranger - Hydross'), 39 | (10, 3, 30060, @PRICE, 0, 0, 694, 1, 'Boots of Effortless Striking - Lurker'), 40 | (10, 3, 30062, @PRICE, 0, 0, 694, 1, 'Grove-Bands of Remulos - Lurker'), 41 | (10, 3, 30092, @PRICE, 0, 0, 694, 1, 'Orca-Hide Boots - Leotheras'), 42 | (10, 3, 30075, @PRICE, 0, 0, 694, 1, 'Gnarled Chestpiece of the Ancients - Morogrim'), 43 | (10, 3, 30101, @PRICE, 0, 0, 694, 1, 'Bloodsea Brigands Vest - Karathress'), 44 | (10, 3, 30106, @PRICE2, 0, 0, 694, 1, 'Belt of One-Hundred Deaths - Vashj'), 45 | (10, 3, 30111, @PRICE2, 0, 0, 694, 1, 'Runetotems Mantle - Vashj'), 46 | 47 | (10, 4, 30054, @PRICE, 0, 0, 694, 1, 'Ranger-Generals Chestguard - Hydross'), 48 | (10, 4, 30047, @PRICE, 0, 0, 694, 1, 'Blackfathom Warbands - Hydross'), 49 | (10, 4, 30066, @PRICE, 0, 0, 694, 1, 'Tempest-Strider Boots - Lurker'), 50 | (10, 4, 30097, @PRICE, 0, 0, 694, 1, 'Coral-Barbed Shoulderpads - Leotheras'), 51 | (10, 4, 30091, @PRICE, 0, 0, 694, 1, 'True-Aim Stalker Bands - Leotheras'), 52 | (10, 4, 30068, @PRICE, 0, 0, 694, 1, 'Girdle of the Tidal Call - Morogrim'), 53 | (10, 4, 30085, @PRICE, 0, 0, 694, 1, 'Mantle of the Tireless Tracker - Morogrim'), 54 | (10, 4, 30104, @PRICE2, 0, 0, 694, 1, 'Cobra-Lash Boots - Vashj'), 55 | 56 | (10, 5, 30048, @PRICE, 0, 0, 694, 1, 'Brighthelm of Justice - Hydross'), 57 | (10, 5, 30053, @PRICE, 0, 0, 694, 1, 'Pauldrons of the Wardancer - Hydross'), 58 | (10, 5, 30057, @PRICE, 0, 0, 694, 1, 'Bracers of Eradication - Lurker'), 59 | (10, 5, 30065, @PRICE, 0, 0, 694, 1, 'Glowing Breastplate of Truth - Lurker'), 60 | (10, 5, 30096, @PRICE, 0, 0, 694, 1, 'Girdle of the Invulnerable - Leotheras'), 61 | (10, 5, 30084, @PRICE, 0, 0, 694, 1, 'Pauldrons of the Argent Sentinel - Morogrim'), 62 | (10, 5, 30081, @PRICE, 0, 0, 694, 1, 'Warboots of Obliteration - Morogrim'), 63 | (10, 5, 30112, @PRICE2, 0, 0, 694, 1, 'Glorious Gauntlets of Crestfall - Vashj'), 64 | (10, 5, 30102, @PRICE2, 0, 0, 694, 1, 'Krakken-Heart Breastplate - Vashj'), 65 | 66 | (10, 6, 30049, @PRICE, 0, 0, 694, 1, 'Fathomstone - Hydross'), 67 | (10, 6, 30058, @PRICE, 0, 0, 694, 1, 'Mallet of the Tides - Lurker'), 68 | (10, 6, 30095, @PRICE, 0, 0, 694, 1, 'Fang of the Leviathan - Leotheras'), 69 | (10, 6, 30080, @PRICE, 0, 0, 694, 1, 'Luminescent Rod of the Naaru - Morogrim'), 70 | (10, 6, 30082, @PRICE, 0, 0, 694, 1, 'Talon of Azshara - Morogrim'), 71 | (10, 6, 30090, @PRICE, 0, 0, 694, 1, 'World Breaker - Karathress'), 72 | (10, 6, 30108, @PRICE2, 0, 0, 694, 1, 'Lightfathom Scepter - Vashj'), 73 | (10, 6, 30103, @PRICE2, 0, 0, 694, 1, 'Fang of Vashj - Vashj'), 74 | (10, 6, 30105, @PRICE2, 0, 0, 694, 1, 'Serpent Spine Longbow - Vashj'); 75 | 76 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_swp_rewards.sql: -------------------------------------------------------------------------------- 1 | SET @PRICE := 24; 2 | SET @PRICE2 := 30; 3 | DELETE FROM `zone_difficulty_mythicmode_rewards` WHERE `ContentType` = 19; 4 | INSERT INTO `zone_difficulty_mythicmode_rewards` (`ContentType`, `ItemType`, `Entry`, `Price`, `Enchant`, `EnchantSlot`, `Achievement`, `Enabled`, `Comment`) VALUES 5 | (19, 1, 34166, @PRICE, 0, 0, 698, 1, 'Band of Lucent Beams - Sathrovarr'), 6 | (19, 1, 34177, @PRICE, 0, 0, 698, 1, 'Clutch of Demise - Brutallus'), 7 | (19, 1, 34178, @PRICE, 0, 0, 698, 1, 'Collar of the Pit Lord - Brutallus'), 8 | (19, 1, 34184, @PRICE, 0, 0, 698, 1, 'Brooch of the Highborne - Felmyst'), 9 | (19, 1, 34204, @PRICE, 0, 0, 698, 1, 'Amulet of Unfettered Magics - Eredar Twins'), 10 | (19, 1, 34189, @PRICE, 0, 0, 698, 1, 'Band of Ruinous Delight - Eredar Twins'), 11 | (19, 1, 34190, @PRICE, 0, 0, 698, 1, 'Crimson Paragon\'s Cover - Eredar Twins'), 12 | (19, 1, 34205, @PRICE, 0, 0, 698, 1, 'Shroud of Redeemed Souls - Eredar Twins'), 13 | (19, 1, 35292, @PRICE, 0, 0, 698, 1, 'Sin\'dorei Pendant of Triumph - Eredar Twins'), 14 | (19, 1, 35291, @PRICE, 0, 0, 698, 1, 'Sin\'dorei Pendant of Salvation - Eredar Twins'), 15 | (19, 1, 35290, @PRICE, 0, 0, 698, 1, 'Sin\'dorei Pendant of Conquest - Eredar Twins'), 16 | (19, 1, 35282, @PRICE, 0, 0, 698, 1, 'Sin\'dorei Band of Dominance - Entropius'), 17 | (19, 1, 35283, @PRICE, 0, 0, 698, 1, 'Sin\'dorei Band of Salvation - Entropius'), 18 | (19, 1, 35284, @PRICE, 0, 0, 698, 1, 'Sin\'dorei Band of Triumph - Entropius'), 19 | (19, 1, 34427, @PRICE, 0, 0, 698, 1, 'Blackened Naaru Sliver - Entropius'), 20 | (19, 1, 34430, @PRICE, 0, 0, 698, 1, 'Glimmering Naaru Sliver - Entropius'), 21 | (19, 1, 34213, @PRICE, 0, 0, 698, 1, 'Ring of Hardened Resolve - Entropius'), 22 | (19, 1, 34230, @PRICE, 0, 0, 698, 1, 'Ring of Omnipotence - Entropius'), 23 | (19, 1, 34429, @PRICE, 0, 0, 698, 1, 'Shifting Naaru Sliver - Entropius'), 24 | (19, 1, 34428, @PRICE, 0, 0, 698, 1, 'Steely Naaru Sliver - Entropius'), 25 | (19, 1, 34241, @PRICE2, 0, 0, 698, 1, 'Cloak of Unforgivable Sin - Kil\'jaeden'), 26 | (19, 1, 34242, @PRICE2, 0, 0, 698, 1, 'Tattered Cape of Antonidas - Kil\'jaeden'), 27 | 28 | (19, 2, 34170, @PRICE, 0, 0, 698, 1, 'Pantaloons of Calming Strife - Sathrovarr'), 29 | (19, 2, 34181, @PRICE, 0, 0, 698, 1, 'Leggings of Calamity - Brutallus'), 30 | (19, 2, 34210, @PRICE, 0, 0, 698, 1, 'Amice of the Convoker - Eredar Twins'), 31 | (19, 2, 34202, @PRICE, 0, 0, 698, 1, 'Shawl of Wonderment - Eredar Twins'), 32 | (19, 2, 34232, @PRICE, 0, 0, 698, 1, 'Fel Conquerer Raiments - Entropius'), 33 | (19, 2, 34233, @PRICE, 0, 0, 698, 1, 'Robes of Faltered Light - Entropius'), 34 | (19, 2, 34339, @PRICE2, 0, 0, 698, 1, 'Cowl of Light\'s Purity - Kil\'jaeden'), 35 | (19, 2, 34340, @PRICE2, 0, 0, 698, 1, 'Dark Conjuror\'s Collar - Kil\'jaeden'), 36 | (19, 2, 34344, @PRICE2, 0, 0, 698, 1, 'Handguards of Defiled Worlds - Kil\'jaeden'), 37 | (19, 2, 34342, @PRICE2, 0, 0, 698, 1, 'Handguards of the Dawn - Kil\'jaeden'), 38 | 39 | (19, 3, 34169, @PRICE, 0, 0, 698, 1, 'Breeches of Natural Aggression - Sathrovarr'), 40 | (19, 3, 34188, @PRICE, 0, 0, 698, 1, 'Leggings of the Immortal Night - Felmyst'), 41 | (19, 3, 34195, @PRICE, 0, 0, 698, 1, 'Shoulderpads of Vehemence - Eredar Twins'), 42 | (19, 3, 34209, @PRICE, 0, 0, 698, 1, 'Spaulders of Reclamation - Eredar Twins'), 43 | (19, 3, 34211, @PRICE, 0, 0, 698, 1, 'Harness of Carnal Instinct - Entropius'), 44 | (19, 3, 34234, @PRICE, 0, 0, 698, 1, 'Shadowed Gauntlets of Paroxysm - Entropius'), 45 | (19, 3, 34212, @PRICE, 0, 0, 698, 1, 'Sunglow Vest - Entropius'), 46 | (19, 3, 34245, @PRICE2, 0, 0, 698, 1, 'Cover of Ursol the Wise - Kil\'jaeden'), 47 | (19, 3, 34244, @PRICE2, 0, 0, 698, 1, 'Duplicitous Guise - Kil\'jaeden'), 48 | 49 | (19, 4, 34168, @PRICE, 0, 0, 698, 1, 'Starstalker Legguards - Sathrovarr'), 50 | (19, 4, 34186, @PRICE, 0, 0, 698, 1, 'Chain Links of the Tumultuous Storm - Felmyst'), 51 | (19, 4, 34208, @PRICE, 0, 0, 698, 1, 'Equilibrium Epaulets - Eredar Twins'), 52 | (19, 4, 34194, @PRICE, 0, 0, 698, 1, 'Mantle of the Golden Forest - Eredar Twins'), 53 | (19, 4, 34229, @PRICE, 0, 0, 698, 1, 'Garments of Serene Shores - Entropius'), 54 | (19, 4, 34228, @PRICE, 0, 0, 698, 1, 'Vicious Hawkstrider Hauberk - Entropius'), 55 | (19, 4, 34333, @PRICE2, 0, 0, 698, 1, 'Coif of Alleria - Kil\'jaeden'), 56 | (19, 4, 34332, @PRICE2, 0, 0, 698, 1, 'Cowl of Gul\'dan - Kil\'jaeden'), 57 | (19, 4, 34343, @PRICE2, 0, 0, 698, 1, 'Thalassian Ranger Gauntlets - Kil\'jaeden'), 58 | 59 | (19, 5, 34167, @PRICE, 0, 0, 698, 1, 'Legplates of the Holy Juggernaut - Sathrovarr'), 60 | (19, 5, 34180, @PRICE, 0, 0, 698, 1, 'Felfury Legplates - Brutallus'), 61 | (19, 5, 34352, @PRICE, 0, 0, 698, 1, 'Borderland Fortress Grips - Felmyst'), 62 | (19, 5, 34192, @PRICE, 0, 0, 698, 1, 'Pauldrons of Perseverance - Eredar Twins'), 63 | (19, 5, 34193, @PRICE, 0, 0, 698, 1, 'Spaulders of the Thalassian Savior - Eredar Twins'), 64 | (19, 5, 34240, @PRICE, 0, 0, 698, 1, 'Gauntlets of the Soothed Soul - Entropius'), 65 | (19, 5, 34216, @PRICE, 0, 0, 698, 1, 'Heroic Judicator\'s Chestguard - Entropius'), 66 | (19, 5, 34215, @PRICE, 0, 0, 698, 1, 'Warharness of Reckless Fury - Entropius'), 67 | (19, 5, 34341, @PRICE2, 0, 0, 698, 1, 'Borderland Paingrips - Kil\'jaeden'), 68 | (19, 5, 34345, @PRICE2, 0, 0, 698, 1, 'Crown of Anasterian - Kil\'jaeden'), 69 | (19, 5, 34243, @PRICE2, 0, 0, 698, 1, 'Helm of Burning Righteousness - Kil\'jaeden'), 70 | 71 | (19, 6, 34164, @PRICE, 0, 0, 698, 1, 'Dragonscale-Encrusted Longblade - Sathrovarr'), 72 | (19, 6, 34165, @PRICE, 0, 0, 698, 1, 'Fang of Kalecgos - Sathrovarr'), 73 | (19, 6, 34179, @PRICE, 0, 0, 698, 1, 'Heart of the Pit - Brutallus'), 74 | (19, 6, 34176, @PRICE, 0, 0, 698, 1, 'Reign of Misery - Brutallus'), 75 | (19, 6, 34182, @PRICE, 0, 0, 698, 1, 'Grand Magister\'s Staff of Torrents - Felmyst'), 76 | (19, 6, 34185, @PRICE, 0, 0, 698, 1, 'Sword Breaker\'s Bulwark - Felmyst'), 77 | (19, 6, 34199, @PRICE, 0, 0, 698, 1, 'Archon\'s Gavel - Eredar Twins'), 78 | (19, 6, 34206, @PRICE, 0, 0, 698, 1, 'Book of Highborne Hymns - Eredar Twins'), 79 | (19, 6, 34196, @PRICE, 0, 0, 698, 1, 'Golden Bow of Quel\'Thalas - Eredar Twins'), 80 | (19, 6, 34203, @PRICE, 0, 0, 698, 1, 'Grip of Mannoroth - Eredar Twins'), 81 | (19, 6, 34197, @PRICE, 0, 0, 698, 1, 'Shiv of Exsanguination - Eredar Twins'), 82 | (19, 6, 34198, @PRICE, 0, 0, 698, 1, 'Stanchion of Primal Instinct - Eredar Twins'), 83 | (19, 6, 34231, @PRICE, 0, 0, 698, 1, 'Aegis of Angelic Fortune - Entropius'), 84 | (19, 6, 34214, @PRICE, 0, 0, 698, 1, 'Muramasa - Entropius'), 85 | (19, 6, 34247, @PRICE2, 0, 0, 698, 1, 'Apolyon, the Soul-Render - Kil\'jaeden'), 86 | (19, 6, 34329, @PRICE2, 0, 0, 698, 1, 'Crux of the Apocalypse - Kil\'jaeden'), 87 | (19, 6, 34337, @PRICE2, 0, 0, 698, 1, 'Golden Staff of the Sin\'dorei - Kil\'jaeden'), 88 | (19, 6, 34335, @PRICE2, 0, 0, 698, 1, 'Hammer of Sanctification - Kil\'jaeden'), 89 | (19, 6, 34331, @PRICE2, 0, 0, 698, 1, 'Hand of the Deceiver - Kil\'jaeden'), 90 | (19, 6, 34336, @PRICE2, 0, 0, 698, 1, 'Sunflare - Kil\'jaeden'); 91 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_t6_rewards.sql: -------------------------------------------------------------------------------- 1 | SET @PRICE := 36; 2 | SET @ILLIDANPRICE := 45; 3 | DELETE FROM `zone_difficulty_mythicmode_rewards` WHERE `ContentType` = 11; 4 | INSERT INTO `zone_difficulty_mythicmode_rewards` (`ContentType`, `ItemType`, `Entry`, `Price`, `Enchant`, `EnchantSlot`, `Achievement`, `Enabled`, `Comment`) VALUES 5 | (11, 1, 32337, @PRICE, 0, 0, 697, 1, 'Shroud of Forgiveness - Gurtogg'), 6 | (11, 1, 32524, @ILLIDANPRICE, 0, 0, 697, 1, 'Shroud of the Highborne - Illidan'), 7 | (11, 1, 32323, @PRICE, 0, 0, 697, 1, 'Shadowmoon Destroyer Drape - Teron'), 8 | (11, 1, 32370, @PRICE, 0, 0, 697, 1, 'Nadina Pendant of Purity - Shahraz'), 9 | (11, 1, 32349, @PRICE, 0, 0, 697, 1, 'Translucent Spellthread Necklace - Reliquary'), 10 | (11, 1, 32260, @PRICE, 0, 0, 697, 1, 'Choker of Endless Nightmares - Supremus'), 11 | (11, 1, 32368, @PRICE, 0, 0, 697, 1, 'Tome of the Lightbringer - Shahraz'), 12 | (11, 1, 32257, @PRICE, 0, 0, 697, 1, 'Idol of the White Stag - Supremus'), 13 | (11, 1, 32330, @PRICE, 0, 0, 697, 1, 'Totem of Astral Guidance - Teron'), 14 | (11, 1, 32335, @PRICE, 0, 0, 697, 1, 'Unstoppable Aggressor Ring - Gurtogg'), 15 | (11, 1, 32238, @PRICE, 0, 0, 697, 1, 'Ring of Calming Waves - Najentus'), 16 | (11, 1, 32497, @ILLIDANPRICE, 0, 0, 697, 1, 'Stormrage Signet - Illidan'), 17 | (11, 1, 32261, @PRICE, 0, 0, 697, 1, 'Band of the Abyssal - Supremus'), 18 | (11, 1, 32247, @PRICE, 0, 0, 697, 1, 'Ring of Captured Storms - Najentus'), 19 | (11, 1, 32266, @PRICE, 0, 0, 697, 1, 'Ring of Deceitful Intent - Akama'), 20 | (11, 1, 32362, @PRICE, 0, 0, 697, 1, 'Pendant of Titans - Reliquary'), 21 | (11, 1, 32331, @PRICE, 0, 0, 697, 1, 'Cloak of the Illidari Council - Council'), 22 | 23 | (11, 1, 32501, @PRICE, 0, 0, 697, 1, 'Shadowmoon Insignia - Gurtogg'), 24 | (11, 1, 32496, @ILLIDANPRICE, 0, 0, 697, 1, 'Memento of Tyrande - Illidan'), 25 | (11, 1, 32483, @ILLIDANPRICE, 0, 0, 697, 1, 'Skull of Guldan - Illidan'), 26 | (11, 1, 32505, @PRICE, 0, 0, 697, 1, 'Madness of the Betrayer - Council'), 27 | 28 | (11, 2, 32340, @PRICE, 0, 0, 697, 1, 'Garment of Temperance - Gurtog'), 29 | (11, 2, 32327, @PRICE, 0, 0, 697, 1, 'Robe of the Shadow Countil - Teron'), 30 | (11, 2, 32239, @PRICE, 0, 0, 697, 1, 'Slippers of the Seacaller - Najentus'), 31 | (11, 2, 32353, @PRICE, 0, 0, 697, 1, 'Gloves of Unfailing Faith - Reliquary'), 32 | (11, 2, 32525, @ILLIDANPRICE, 0, 0, 697, 1, 'Cown of the Illidari High Lord - Illidan'), 33 | (11, 2, 32329, @PRICE, 0, 0, 697, 1, 'Cowl of Benevolence - Teron'), 34 | (11, 2, 32367, @PRICE, 0, 0, 697, 1, 'Leggins of Devastation - Shahraz'), 35 | (11, 2, 32338, @PRICE, 0, 0, 697, 1, 'Blood-cursed Shoulderpads - Gurtogg'), 36 | (11, 2, 32273, @PRICE, 0, 0, 697, 1, 'Amice of Brilliant Light - Akama'), 37 | (11, 2, 32256, @PRICE, 0, 0, 697, 1, 'Waistwrap of Infinity - Supremus'), 38 | (11, 2, 32270, @PRICE, 0, 0, 697, 1, 'Focused Mana Bindings - Akama'), 39 | (11, 2, 32513, @PRICE, 0, 0, 697, 1, 'Wristbands of Divine Influence - Akama'), 40 | (11, 2, 32519, @PRICE, 0, 0, 697, 1, 'Belt of Divine Guidance - Council'), 41 | 42 | (11, 3, 32252, @PRICE, 0, 0, 697, 1, 'Nether Shadow Tunic - Supremus'), 43 | (11, 3, 32366, @PRICE, 0, 0, 697, 1, 'Shadowmaster Boots - Shahraz'), 44 | (11, 3, 32347, @PRICE, 0, 0, 697, 1, 'Grips of Damnation - Reliquary'), 45 | (11, 3, 32328, @PRICE, 0, 0, 697, 1, 'Botanist Gloves - Teron'), 46 | (11, 3, 32240, @PRICE, 0, 0, 697, 1, 'Guise of the Tidal Lurker - Najentus'), 47 | (11, 3, 32235, @ILLIDANPRICE, 0, 0, 697, 1, 'Cursed Vision of Sargeras - Illidan'), 48 | (11, 3, 32271, @PRICE, 0, 0, 697, 1, 'Kilt of Immortal Nature - Akama'), 49 | (11, 3, 32377, @PRICE, 0, 0, 697, 1, 'Mantle of Darkness - Najentus'), 50 | (11, 3, 32518, @PRICE, 0, 0, 697, 1, 'Veil of Turning Leaves - Council'), 51 | (11, 3, 32339, @PRICE, 0, 0, 697, 1, 'Belt of Primal Majesty - Gurtog'), 52 | (11, 3, 32265, @PRICE, 0, 0, 697, 1, 'Shadow-walker Cord - Akama'), 53 | (11, 3, 32324, @PRICE, 0, 0, 697, 1, 'Insidious Bands - Teron'), 54 | (11, 3, 32351, @PRICE, 0, 0, 697, 1, 'Elunite Empowered Bracers - Reliquary'), 55 | (11, 3, 32352, @PRICE, 0, 0, 697, 1, 'Naturewarden\'s Treads - Reliquary'), 56 | 57 | (11, 4, 32334, @PRICE, 0, 0, 697, 1, 'Vest of the Mounting Assault - Gurtog'), 58 | (11, 4, 32242, @PRICE, 0, 0, 697, 1, 'Boots of Oceanic Fury - Najentus'), 59 | (11, 4, 32510, @PRICE, 0, 0, 697, 1, 'Softstep Boots of Tracking - Teron'), 60 | (11, 4, 32234, @PRICE, 0, 0, 697, 1, 'Fists of Mukoa - Najentus'), 61 | (11, 4, 32275, @PRICE, 0, 0, 697, 1, 'Spiritwalker Gauntlets - Akama'), 62 | (11, 4, 32241, @PRICE, 0, 0, 697, 1, 'Helm of Soothing Currents - Najentus'), 63 | (11, 4, 32517, @PRICE, 0, 0, 697, 1, 'The Wavemender Mantle - Reliquary'), 64 | (11, 4, 32264, @PRICE, 0, 0, 697, 1, 'Shoulders of the Hidden Predator - Akama'), 65 | (11, 4, 32276, @PRICE, 0, 0, 697, 1, 'Flashfire Girdle - Akama'), 66 | (11, 4, 32258, @PRICE, 0, 0, 697, 1, 'Naturalist Preserving Cinch - Supremus'), 67 | (11, 4, 32259, @PRICE, 0, 0, 697, 1, 'Bands of the Coming Storm - Supremus'), 68 | (11, 4, 32251, @PRICE, 0, 0, 697, 1, 'Wraps of Precise Flight - Supremus'), 69 | (11, 4, 32346, @PRICE, 0, 0, 697, 1, 'Boneweave Girdle - Reliquary'), 70 | (11, 4, 32376, @PRICE, 0, 0, 697, 1, 'Forest Prowler\'s Helm - Council'), 71 | 72 | (11, 5, 32365, @PRICE, 0, 0, 697, 1, 'Heartshatter Breastplate - Shahraz'), 73 | (11, 5, 32243, @PRICE, 0, 0, 697, 1, 'Pearl Inlaid Boots - Najentus'), 74 | (11, 5, 32245, @PRICE, 0, 0, 697, 1, 'Tide-stomper Greaves - Najentus'), 75 | (11, 5, 32345, @PRICE, 0, 0, 697, 1, 'Dreadbots of the Legion - Reliquary'), 76 | (11, 5, 32268, @PRICE, 0, 0, 697, 1, 'Myrmidon Treads - Akama'), 77 | (11, 5, 32278, @PRICE, 0, 0, 697, 1, 'Grips of Silent Justice - Akama'), 78 | (11, 5, 32280, @PRICE, 0, 0, 697, 1, 'Gauntlets of Enforcement - Teron'), 79 | (11, 5, 32521, @ILLIDANPRICE, 0, 0, 697, 1, 'Faceplate of the Impenetrable - Illidan'), 80 | (11, 5, 32354, @PRICE, 0, 0, 697, 1, 'Crowd of the Empowered Fate - Reliquary'), 81 | (11, 5, 32341, @PRICE, 0, 0, 697, 1, 'Leggins of the Divine Retribution - Gurtog'), 82 | (11, 5, 32263, @PRICE, 0, 0, 697, 1, 'Praetorian Legguards - Akama'), 83 | (11, 5, 32250, @PRICE, 0, 0, 697, 1, 'Pauldrons of the Abyssal Fury - Supremus'), 84 | (11, 5, 32342, @PRICE, 0, 0, 697, 1, 'Girdle of the Mighty Resolve - Gurtog'), 85 | (11, 5, 32333, @PRICE, 0, 0, 697, 1, 'Girdle of Stability - Gurtog'), 86 | (11, 5, 32512, @PRICE, 0, 0, 697, 1, 'Girdle of Lordaeron Fall - Teron'), 87 | (11, 5, 32232, @PRICE, 0, 0, 697, 1, 'Eternium Shell Bracers - Najentus'), 88 | (11, 5, 32279, @PRICE, 0, 0, 697, 1, 'The Seeker Wristguards - Akama'), 89 | (11, 5, 32373, @PRICE, 0, 0, 697, 1, 'Helm of the Illidari Shatterer - Council'), 90 | 91 | (11, 6, 32236, @PRICE, 0, 0, 697, 1, 'Rising Tide - Najentus'), 92 | (11, 6, 32254, @PRICE, 0, 0, 697, 1, 'The Brutalizer - Supremus'), 93 | (11, 6, 32269, @PRICE, 0, 0, 697, 1, 'Messenger of Fate - Gurtogg'), 94 | (11, 6, 32237, @PRICE, 0, 0, 697, 1, 'The Maelstrom Fury - Najentus'), 95 | (11, 6, 32471, @ILLIDANPRICE, 0, 0, 697, 1, 'Shard of Azzinoth - Illidan'), 96 | (11, 6, 32500, @ILLIDANPRICE, 0, 0, 697, 1, 'Crystal Spire of karabor - Illidan'), 97 | (11, 6, 32262, @PRICE, 0, 0, 697, 1, 'Syphon of the Nathrezim - Supremus'), 98 | (11, 6, 32369, @PRICE, 0, 0, 697, 1, 'Blade of Savagery - Shahraz'), 99 | (11, 6, 32348, @PRICE, 0, 0, 697, 1, 'Soul Cleaver - Teron'), 100 | (11, 6, 32332, @PRICE, 0, 0, 697, 1, 'Torch of the Damned - Reliquary'), 101 | (11, 6, 32248, @PRICE, 0, 0, 697, 1, 'Halberd of Desolation - Najentus'), 102 | (11, 6, 32344, @PRICE, 0, 0, 697, 1, 'Staff of Immaculate Recovery - Gurtogg'), 103 | (11, 6, 32374, @ILLIDANPRICE, 0, 0, 697, 1, 'Zhardoom Greatstaff of the Devourer - Illidan'), 104 | (11, 6, 32253, @PRICE, 0, 0, 697, 1, 'Legionkiller - Supremus'), 105 | (11, 6, 32325, @PRICE, 0, 0, 697, 1, 'Rifle of the Stoic Guardian - Teron'), 106 | (11, 6, 32336, @ILLIDANPRICE, 0, 0, 697, 1, 'Black bow of the Betrayer - Illidan'), 107 | (11, 6, 32326, @PRICE, 0, 0, 697, 1, 'Twisted Blades of Zarak - Teron'), 108 | (11, 6, 32343, @PRICE, 0, 0, 697, 1, 'Wand of Prismatic Focus - Gurtogg'), 109 | (11, 6, 32363, @PRICE, 0, 0, 697, 1, 'Naaru-Blessed Life Rod - Reliquary'), 110 | (11, 6, 32350, @PRICE, 0, 0, 697, 1, 'Touch of Inspiration - Reliquary'), 111 | (11, 6, 32361, @PRICE, 0, 0, 697, 1, 'Blind-seers Icon - Akama'), 112 | (11, 6, 32375, @ILLIDANPRICE, 0, 0, 697, 1, 'Bulwark of Azzinoth - Illidan'), 113 | (11, 6, 32255, @PRICE, 0, 0, 697, 1, 'Felstone Bulwark - Supremus'); 114 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_info_content.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM `zone_difficulty_info`; 2 | INSERT INTO `zone_difficulty_info` (`MapId`, `PhaseMask`, `HealingNerfValue`, `AbsorbNerfValue`, `MeleeDmgBuffValue`, `SpellDmgBuffValue`, `Enabled`, `Comment`) VALUES 3 | -- Vanilla Raids 4 | (531, 0, '0.50', '0.50', '1.50', '1.30', 0, 'AQ40 Healing 50% / Absorb 50% Nerf / 50% physical & 30% spell damage buff'), 5 | (509, 0, '0.50', '0.50', '1.60', '1.30', 0, 'AQ20 Healing 50% / Absorb 50% Nerf / 60% physical & 30% spell damage buff'), 6 | (309, 0, '0.50', '0.50', '1.50', '1.10', 0, 'ZG20 Healing 50% / Absorb 50% Nerf / 50% physical & 10% spell damage buff'), 7 | (469, 0, '0.50', '0.50', '1.50', '1.50', 0, 'BWL Healing 50% / Absorb 50% Nerf / 50% physical & 50% spell damage buff'), 8 | (249, 0, '0.50', '0.50', '1.40', '1.40', 0, 'ONY Healing 50% / Absorb 50% Nerf / 40% physical & 40% spell damage buff'), 9 | (409, 0, '0.50', '0.50', '1.50', '1.50', 0, 'MC Healing 50% / Absorb 50% Nerf / 50% physical & 50% spell damage buff'), 10 | -- TBC Raids 11 | (565, 0, 0.90, 0.90, 1.10, 1.10, 1, 'Normal Mode Gruul Healing 90% / Absorb 90% Nerf / 10% physical & 10% spell damage buff'), 12 | (565, 0, 0.80, 0.80, 1.20, 1.20, 64, 'Mythic Mode Gruul Healing 80% / Absorb 80% Nerf / 20% physical & 20% spell damage buff'), 13 | (544, 0, 0.90, 0.90, 1.10, 1.10, 1, 'Normal Mode Magtheridon Healing 90% / Absorb 90% Nerf / 10% physical & 10% spell damage buff'), 14 | (544, 0, 0.80, 0.80, 1.20, 1.20, 64, 'Mythic Mode Magtheridon Healing 80% / Absorb 80% Nerf / 20% physical & 20% spell damage buff'), 15 | (532, 0, 0.75, 0.75, 1.15, 1.15, 1, 'Karazhan'), 16 | (548, 0, 0.75, 0.75, 1.20, 1.15, 1, 'Normal SSC Healing 75% / Absorb 75% Nerf / 20% physical & 15% spell damage buff'), 17 | (548, 0, 0.75, 0.75, 1.34, 1.32, 64, 'Mythic SSC Healing 75% / Absorb 75% Nerf / 34% physical & 32% spell damage buff'), 18 | (534, 0, 0.75, 0.75, 1.35, 1.2, 1, 'The Battle For Mount Hyjal'), 19 | (534, 0, 0.75, 0.75, 1.48, 1.35, 64, 'Mythic The Battle For Mount Hyjal'), 20 | (550, 0, 0.75, 0.75, 1.30, 1.30, 1, 'Tempest Keep'), 21 | (564, 0, 0.75, 0.75, 1.20, 1.15, 1, 'Normal Mode Black Temple Healing 75% / Absorb 75% Nerf / 20% physical & 15% spell damage buff'), 22 | (564, 0, 0.75, 0.75, 1.34, 1.32, 64, 'Mythic Mode Black Temple Healing 75% / Absorb 75% Nerf / 34% physical & 32% spell damage buff'), 23 | (568, 0, 0.75, 0.75, 1.20, 1.15, 1, 'Normal ZA Healing 75% / Absorb 75% Nerf / 20% physical & 15% spell damage buff'), 24 | (568, 0, 0.75, 0.75, 1.34, 1.32, 64, 'Mythic ZA Healing 75% / Absorb 75% Nerf / 34% physical & 32% spell damage buff'), 25 | (580, 0, 0.75, 0.75, 1.20, 1.15, 1, 'Normal SWP Healing 75% / Absorb 75% Nerf / 20% physical & 15% spell damage buff'), 26 | (580, 0, 0.75, 0.75, 1.34, 1.32, 64, 'Mythic SWP Healing 75% / Absorb 75% Nerf / 34% physical & 32% spell damage buff'), 27 | 28 | -- TBC Heroics 29 | (269, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Black Morass Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 30 | -- (269, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Black Morass Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 31 | (540, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Shattered Halls Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 32 | -- (540, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Shattered Halls Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 33 | (542, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Blood Furnace Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 34 | -- (542, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Blood Furnace Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 35 | (543, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Hellfire Ramparts Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 36 | -- (543, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Hellfire Ramparts Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 37 | (545, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode The Steamvault Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 38 | -- (545, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode The Steamvault Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 39 | (546, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode The Underbog Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 40 | -- (546, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode The Underbog Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 41 | (547, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Slave Pens Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 42 | -- (547, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Slave Pens Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 43 | (552, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode The Arcatraz Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 44 | -- (552, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode The Arcatraz Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 45 | (553, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode The Botanica Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 46 | -- (553, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode The Botanica Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 47 | (554, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode The Mechanar Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 48 | -- (554, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode The Mechanar Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 49 | (555, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Shadow Labyrinth Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 50 | -- (555, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Shadow Labyrinth Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 51 | (556, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Sethekk Halls Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 52 | -- (556, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Sethekk Halls Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 53 | (557, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Mana Tombs Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 54 | -- (557, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Mana Tombs Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 55 | (558, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Auchenai Crypts Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 56 | -- (558, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Auchenai Crypts Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 57 | (560, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode The Escape From Durnholde Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 58 | -- (560, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode The Escape From Durnholde Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 59 | (585, 0, '0.90', '0.90', '1.20', '1.10', 0, 'Heroic Mode Magister\'s Terrace Healing 90% / Absorb 90% Nerf / 20% physical & 10% spell damage buff'), 60 | -- (585, 0, '0.80', '0.80', '1.30', '1.20', 64, 'Mythic Mode Magister\'s Terrace Healing 80% / Absorb 80% Nerf / 30% physical & 20% spell damage buff'), 61 | -- Battlegrounds 62 | (30, 0, '0.80', '0.80', '0.70', '0.70', 0, 'AV Healing 20% / Absorb 20% / 30% physical & spell damage nerf'), 63 | (489, 0, '0.80', '0.80', '0.70', '0.70', 0, 'WSG Healing 20% / Absorb 20% / 30% physical & spell damage nerf'), 64 | (529, 0, '0.80', '0.80', '0.70', '0.70', 0, 'AB Healing 20% / Absorb 20% / 30% physical & spell damage nerf'), 65 | (566, 0, '0.80', '0.80', '0.70', '0.70', 0, 'EotS Healing 20% / Absorb 20% / 30% physical & spell damage nerf'), 66 | -- arenas 67 | (559, 0, '0.80', '0.80', '0.70', '0.70', 0, 'Ring of Trials Healing 20% / Absorb 20% / 30% physical & spell damage nerf'), 68 | (562, 0, '0.80', '0.80', '0.70', '0.70', 0, 'Blades Edge Arena Healing 20% / Absorb 20% / 30% physical & spell damage nerf'), 69 | (572, 0, '0.80', '0.80', '0.70', '0.70', 0, 'Ruins of Lordaeron Healing 20% / Absorb 20% / 30% physical & spell damage nerf'), 70 | (617, 0, '0.80', '0.80', '0.70', '0.70', 0, 'Dalaran Arena Healing 20% / Absorb 20% / 30% physical & spell damage nerf'), 71 | (618, 0, '0.80', '0.80', '0.70', '0.70', 0, 'Ring of Valor Healing 20% / Absorb 20% / 30% physical & spell damage nerf'), 72 | -- Duels in Forbidding Sea (Wetlands) 73 | (2147483647, 0, '0.80', '0.80', '0.70', '0.70', 1, 'Zone 2402 Duel Healing 20% / Absorb 20% Nerf / 30% physical & spell damage nerf'); 74 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_rewards.sql: -------------------------------------------------------------------------------- 1 | -- Content types: 2 | -- TYPE_VANILLA = 1; 3 | -- TYPE_RAID_MC = 2; 4 | -- TYPE_RAID_ONY = 3; 5 | -- TYPE_RAID_BWL = 4; 6 | -- TYPE_RAID_ZG = 5; 7 | -- TYPE_RAID_AQ20 = 6; 8 | -- TYPE_RAID_AQ40 = 7; 9 | -- TYPE_HEROIC_TBC = 8; 10 | -- TYPE_RAID_T4 = 9; 11 | -- TYPE_RAID_T5 = 10; 12 | -- TYPE_RAID_T6 = 11; 13 | -- TYPE_HEROIC_WOTLK = 12; 14 | -- TYPE_RAID_T7 = 13; 15 | -- TYPE_RAID_T8 = 14; 16 | -- TYPE_RAID_T9 = 15; 17 | -- TYPE_RAID_T10 = 16; 18 | 19 | -- Item types: 20 | -- Back, Finger, Trinket, Neck = 1 21 | -- Cloth = 2 22 | -- Leather = 3 23 | -- Mail = 4 24 | -- Plate = 5 25 | -- Weapons, Holdables, Shields = 6 26 | 27 | DROP TABLE IF EXISTS `zone_difficulty_mythicmode_rewards`; 28 | CREATE TABLE `zone_difficulty_mythicmode_rewards` ( 29 | `ContentType` INT NOT NULL DEFAULT 0, 30 | `ItemType` INT NOT NULL DEFAULT 0, 31 | `Entry` INT NOT NULL DEFAULT 0, 32 | `Price` INT NOT NULL DEFAULT 0, 33 | `Enchant` INT NOT NULL DEFAULT 0, 34 | `EnchantSlot` TINYINT NOT NULL DEFAULT 0, 35 | `Achievement` INT NOT NULL DEFAULT 0, -- indicates a full-tier-clearance reward if negative 36 | `Enabled` TINYINT DEFAULT 0, 37 | `Comment` TEXT, 38 | PRIMARY KEY (`ContentType`, `Entry`, `Enchant`) 39 | ); 40 | 41 | INSERT INTO `zone_difficulty_mythicmode_rewards` (`ContentType`, `ItemType`, `Entry`, `Price`, `Enchant`, `EnchantSlot`, `Achievement`, `Enabled`, `Comment`) VALUES 42 | -- Full Tier Rewards: 43 | (8, 0, 13584, 20, 0, 0, -1, 1, 'Mini Diablo for clearing all TBC heroics on Mythicmode'), 44 | (9, 0, 13583, 20, 0, 0, -1, 1, 'Panda Cub for clearing all T4 raids on Mythicmode'), 45 | 46 | -- TYPE_HEROIC_TBC = 8; 47 | -- Back, Finger, Trinket, Neck = 1 48 | (8, 1, 29347, 10, 211, 11, 668, 1, 'Talisman of the Breaker +7 SP'), 49 | (8, 1, 29349, 10, 1588, 11, 669, 1, 'Adamantine Chain of the Unbroken +14 AP'), 50 | (8, 1, 29352, 10, 211, 11, 671, 1, 'Cobalt Band of Tyrigosa +7 SP'), 51 | (8, 1, 31919, 10, 1588, 11, 671, 1, 'Nexus-Prince\'s Ring of Balance +14 AP'), 52 | (8, 1, 31920, 10, 1588, 11, 671, 1, 'Shaffar\'s Band of Brutality +14 AP'), 53 | (8, 1, 31921, 10, 211, 11, 671, 1, 'Yor\'s Collapsing Band +7 SP'), 54 | (8, 1, 31922, 10, 211, 11, 671, 1, 'Ring of Conflict Survival +7 SP'), 55 | (8, 1, 31923, 10, 211, 11, 671, 1, 'Band of the Crystalline Void +7 SP'), 56 | (8, 1, 31924, 10, 2730, 11, 671, 1, 'Yor\'s Revenge +8 Dodge'), 57 | (8, 1, 32081, 10, 1588, 11, 670, 1, 'Eye of the Stalker +14 AP'), 58 | (8, 1, 29354, 10, 211, 11, 672, 1, 'Light-Touched Stole of Altruism +7 SP'), 59 | -- Cloth = 2 60 | (8, 2, 29240, 10, 211, 11, 671, 1, 'Bands of Negation +7 SP'), 61 | (8, 2, 29241, 10, 211, 11, 681, 1, 'Belt of Depravity +7 SP'), 62 | (8, 2, 29242, 10, 211, 11, 669, 1, 'Boots of Blasphemy +7 SP'), 63 | (8, 2, 29249, 10, 211, 11, 672, 1, 'Bands of the Benevolent +7 SP'), 64 | (8, 2, 29250, 10, 211, 11, 673, 1, 'Cord of Sanctification +7 SP'), 65 | (8, 2, 29251, 10, 211, 11, 679, 1, 'Boots of the Pious +7 SP'), 66 | (8, 2, 29255, 10, 211, 11, 678, 1, 'Bands of Rarefied Magic +7 SP'), 67 | (8, 2, 29257, 10, 211, 11, 672, 1, 'Sash of Arcane Visions +7 SP'), 68 | (8, 2, 29258, 10, 211, 11, 680, 1, 'Boots of Ethereal Manipulation +7 SP'), 69 | (8, 2, 30531, 10, 211, 11, 676, 1, 'Breeches of the Occultist +7 SP'), 70 | (8, 2, 30532, 10, 211, 11, 675, 1, 'Kirin Tor Master\'s Trousers +7 SP'), 71 | (8, 2, 30543, 10, 211, 11, 677, 1, 'Pontifex Kilt +7 SP'), 72 | -- Leather = 3 73 | (8, 3, 29246, 10, 1588, 11, 673, 1, 'Nightfall Wristguards +14 AP'), 74 | (8, 3, 29247, 10, 1588, 11, 676, 1, 'Girdle of the Deathdealer +14 AP'), 75 | (8, 3, 29248, 10, 1588, 11, 681, 1, 'Shadowstep Striders +14 AP'), 76 | (8, 3, 29263, 10, 1588, 11, 678, 1, 'Forestheart Bracers +14 AP'), 77 | (8, 3, 29264, 10, 1588, 11, 667, 1, 'Tree-Mender\'s Belt +14 AP'), 78 | (8, 3, 29265, 10, 1588, 11, 670, 1, 'Barkchip Boots +14 AP'), 79 | (8, 3, 29357, 10, 1588, 11, 675, 1, 'Master Thief\'s Gloves +14 AP'), 80 | (8, 3, 30535, 10, 1588, 11, 671, 1, 'Forestwalker Kilt +14 AP'), 81 | (8, 3, 30538, 10, 1588, 11, 669, 1, 'Midnight Legguards +14 AP'), 82 | (8, 3, 32080, 10, 1588, 11, 668, 1, 'Mantle of Shadowy Embrace +14 AP'), 83 | -- Mail = 4 84 | (8, 4, 29243, 10, 211, 11, 677, 1, 'Wave-Fury Vambraces +7 SP'), 85 | (8, 4, 29244, 10, 211, 11, 672, 1, 'Wave-Song Girdle +7 SP'), 86 | (8, 4, 29245, 10, 211, 11, 668, 1, 'Wave-Crest Striders +7 SP'), 87 | (8, 4, 29259, 10, 1588, 11, 674, 1, 'Bracers of the Hunt +14 AP'), 88 | (8, 4, 29261, 10, 1588, 11, 675, 1, 'Girdle of Ferocity +14 AP'), 89 | (8, 4, 29262, 10, 1588, 11, 680, 1, 'Boots of the Endless Hunt +14 AP'), 90 | (8, 4, 30534, 10, 1588, 11, 673, 1, 'Wyrmscale Greaves +14 AP'), 91 | (8, 4, 30541, 10, 211, 11, 670, 1, 'Stormsong Kilt +7 SP'), 92 | (8, 4, 32076, 10, 1588, 11, 679, 1, 'Handguards of the Steady +14 AP'), 93 | (8, 4, 32077, 10, 211, 11, 667, 1, 'Wrath Infused Gauntlets +7 SP'), 94 | (8, 4, 32078, 10, 211, 11, 669, 1, 'Pauldrons of Wild Magic +7 SP'), 95 | -- Plate = 5 96 | (8, 5, 29238, 10, 2730, 11, 667, 1, 'Lion\'s Heart Girdle +8 Dodge'), 97 | (8, 5, 29239, 10, 2730, 11, 668, 1, 'Eaglecrest Warboots +8 Dodge'), 98 | (8, 5, 29252, 10, 2730, 11, 671, 1, 'Bracers of Dignity +8 Dodge'), 99 | (8, 5, 29253, 10, 2730, 11, 676, 1, 'Girdle of Valorous Deeds +8 Dodge'), 100 | (8, 5, 29254, 10, 2730, 11, 678, 1, 'Boots of the Righteous Path +8 Dodge'), 101 | (8, 5, 29463, 10, 2730, 11, 677, 1, 'Amber Bands of the Aggressor +8 Dodge'), 102 | (8, 5, 30533, 10, 1588, 11, 679, 1, 'Vanquisher\'s Legplates +14 AP'), 103 | (8, 5, 30536, 10, 1588, 11, 673, 1, 'Greaves of the Martyr +14 AP'), 104 | (8, 5, 32072, 10, 2730, 11, 680, 1, 'Gauntlets of Dissension +8 Dodge'), 105 | (8, 5, 32073, 10, 2730, 11, 674, 1, 'Spaulders of Dementia +8 Dodge'), 106 | -- Weapons, Holdables, Shields = 6 107 | (8, 6, 32082, 10, 2730, 11, 671, 1, 'The Fel Barrier +8 Dodge'), 108 | (8, 6, 29362, 10, 2730, 11, 679, 1, 'The Sun Eater +8 Dodge'), 109 | (8, 6, 29356, 10, 1588, 11, 676, 1, 'Quantum Blade +14 AP'), 110 | (8, 6, 29355, 10, 211, 11, 674, 1, 'Terokk\'s Shadowstaff +7 SP'), 111 | (8, 6, 29359, 10, 1588, 11, 680, 1, 'Feral Staff of Lashing +14 AP'), 112 | (8, 6, 29348, 10, 1588, 11, 678, 1, 'The Bladefist +14 AP'), 113 | (8, 6, 29346, 10, 1588, 11, 667, 1, 'Feltooth Eviscerator +14 AP'), 114 | (8, 6, 29360, 10, 1588, 11, 681, 1, 'Vileblade of the Betrayer +14 AP'), 115 | (8, 6, 29350, 10, 211, 11, 670, 1, 'The Black Stalk +7 SP'), 116 | (8, 6, 29351, 10, 1588, 11, 677, 1, 'Wrathtide Longbow +14 AP'), 117 | (8, 6, 29353, 10, 211, 11, 675, 1, 'Shockwave Truncheon +7 SP'), 118 | 119 | -- TYPE_RAID_T4 = 9; 120 | -- Back, Finger, Trinket, Neck = 1 121 | (9, 1, 28797, 10, 211, 11, 692, 1, 'Brute Cloak of the Ogre-Magi +7 SP'), 122 | (9, 1, 28830, 10, 1588, 11, 692, 1, 'Dragonspine Trophy +14 AP'), 123 | (9, 1, 28823, 10, 211, 11, 692, 1, 'Eye of Gruul +7 SP'), 124 | (9, 1, 28822, 10, 211, 11, 692, 1, 'Teeth of Gruul +7 SP'), 125 | (9, 1, 28777, 10, 211, 11, 693, 1, 'Cloak of the Pit Stalker +7 SP'), 126 | (9, 1, 28789, 10, 211, 11, 693, 1, 'Eye of Magtheridon +7 SP'), 127 | -- Cloth = 2 128 | (9, 2, 28799, 10, 211, 11, 692, 1, 'Belt of Divine Inspiration +7 SP'), 129 | (9, 2, 28804, 10, 211, 11, 692, 1, 'Collar of Cho\'gall +7 SP'), 130 | (9, 2, 28780, 10, 211, 11, 693, 1, 'Soul-Eater\'s Handwraps +7 SP'), 131 | -- Leather = 3 132 | (9, 3, 28796, 10, 1588, 11, 692, 1, 'Malefic Mask of the Shadows +14 AP'), 133 | (9, 3, 28803, 10, 211, 11, 692, 1, 'Cowl of Nature\'s Breath +7 SP'), 134 | (9, 3, 28828, 10, 1588, 11, 692, 1, 'Gronn-Stitched Girdle +14 AP'), 135 | (9, 3, 28776, 10, 211, 11, 693, 1, 'Liar\'s Tongue Gloves +14 AP'), 136 | -- Mail = 4 137 | (9, 4, 28801, 10, 1588, 11, 692, 1, 'Maulgar\'s Warhelm +14 AP'), 138 | (9, 4, 28827, 10, 1588, 11, 692, 1, 'Gauntlets of the Dragonslayer +14 AP'), 139 | (9, 4, 28810, 10, 211, 11, 692, 1, 'Windshear Boots +7 SP'), 140 | (9, 4, 28778, 10, 1588, 11, 693, 1, 'Terror Pit Girdle +14 AP'), 141 | -- Plate = 5 142 | (9, 5, 28795, 10, 1588, 11, 692, 1, 'Bladespire Warbands +14 AP'), 143 | (9, 5, 28824, 10, 1588, 11, 692, 1, 'Gauntlets of Martial Perfection +14 AP'), 144 | (9, 5, 28779, 10, 1588, 11, 693, 1, 'Girdle of the Endless Pit +14 AP'), 145 | (9, 5, 28775, 10, 1588, 11, 693, 1, 'Thundering Greathelm +14 AP'), 146 | -- Weapons, Holdables, Shields = 6 147 | (9, 6, 28800, 10, 1588, 11, 692, 1, 'Hammer of the Naaru +14 AP'), 148 | (9, 6, 28825, 10, 1588, 11, 692, 1, 'Aldori Legacy Defender +14 AP'), 149 | (9, 6, 28794, 10, 1588, 11, 692, 1, 'Axe of the Gronn Lords +14 AP'), 150 | (9, 6, 28802, 10, 211, 11, 692, 1, 'Bloodmaw Magus-Blade +7 SP'), 151 | (9, 6, 28826, 10, 1588, 11, 692, 1, 'Shuriken of Negation +14 AP'), 152 | (9, 6, 29458, 10, 211, 11, 693, 1, 'Aegis of the Vindicator +7 SP'), 153 | (9, 6, 28782, 10, 211, 11, 693, 1, 'Crystalheart Pulse-Staff +7 SP'), 154 | (9, 6, 28783, 10, 211, 11, 693, 1, 'Eredar Wand of Obliteration +7 SP'), 155 | (9, 6, 28774, 10, 1588, 11, 693, 1, 'Glaive of the Pit +14 AP'), 156 | (9, 6, 28781, 10, 211, 11, 693, 1, 'Karaborian Talisman +7 SP'); 157 | -------------------------------------------------------------------------------- /src/ZoneDifficulty.h: -------------------------------------------------------------------------------- 1 | #ifndef DEF_ZONEDIFFICULTY_H 2 | #define DEF_ZONEDIFFICULTY_H 3 | 4 | #include "Player.h" 5 | #include "Config.h" 6 | #include "InstanceScript.h" 7 | #include "ScriptMgr.h" 8 | #include "ScriptedGossip.h" 9 | 10 | struct ZoneDifficultyNerfData 11 | { 12 | float HealingNerfPct = 1.0f; 13 | float AbsorbNerfPct = 1.0f; 14 | float SpellDamageBuffPct = 1.0f; 15 | float MeleeDamageBuffPct = 1.0f; 16 | int8 Enabled = 1; 17 | float HealingNerfPctHard = 1.0f; 18 | float AbsorbNerfPctHard = 1.0f; 19 | float SpellDamageBuffPctHard = 1.0f; 20 | float MeleeDamageBuffPctHard = 1.0f; 21 | }; 22 | 23 | struct ZoneDifficulySpellOverrideData 24 | { 25 | float NerfPct; 26 | uint32 ModeMask; // 1=normal, 64=mythic (bitmask) 27 | }; 28 | 29 | struct ZoneDifficultyMythicmodeMapData 30 | { 31 | uint32 EncounterEntry; 32 | uint32 Override; 33 | uint32 RewardType; 34 | }; 35 | 36 | struct ZoneDifficultyRewardData 37 | { 38 | uint32 Entry; 39 | uint32 Price; 40 | uint32 Enchant; 41 | uint8 EnchantSlot; 42 | int32 Achievement; 43 | }; 44 | 45 | struct ZoneDifficultyHAI 46 | { 47 | uint8 Chance; 48 | uint32 Spell; 49 | int32 Spellbp0; 50 | int32 Spellbp1; 51 | int32 Spellbp2; 52 | uint8 Target; 53 | int8 TargetArg; 54 | uint8 TargetArg2; 55 | Milliseconds Delay; 56 | Milliseconds Cooldown; 57 | uint8 Repetitions; 58 | bool TriggeredCast; 59 | }; 60 | 61 | struct VendorSelectionData 62 | { 63 | uint8 category; 64 | uint8 slot; 65 | }; 66 | 67 | struct CreatureOverrideData 68 | { 69 | float NormalOverride = 1.0f; 70 | float MythicOverride = 1.0f; 71 | }; 72 | 73 | int32 const DUEL_INDEX = 0x7FFFFFFF; 74 | int32 const DUEL_AREA = 2402; // Forbidding Sea (Wetlands) 75 | 76 | uint32 const NPC_TEXT_LEADER_NORMAL = 91301; 77 | uint32 const NPC_TEXT_OTHER = 91302; 78 | uint32 const NPC_TEXT_LEADER_HARD = 91303; 79 | uint32 const NPC_TEXT_LEADER_FINAL = 91304; 80 | uint32 const NPC_TEXT_OFFER = 91305; 81 | uint32 const NPC_TEXT_CATEGORY = 91306; 82 | uint32 const NPC_TEXT_ITEM = 91307; 83 | uint32 const NPC_TEXT_CONFIRM = 91308; 84 | uint32 const NPC_TEXT_GRANT = 91309; 85 | uint32 const NPC_TEXT_DENIED = 91310; 86 | uint32 const NPC_TEXT_SCORE = 91311; 87 | 88 | int32 const MODE_NORMAL = 1; 89 | int32 const MODE_HARD = 64; 90 | 91 | // EVENT_GROUP is used for unit->m_Events.AddEventAtOffset 92 | uint8 const EVENT_GROUP = 64; 93 | 94 | uint32 const ITEMTYPE_MISC = 1; 95 | uint32 const ITEMTYPE_CLOTH = 2; 96 | uint32 const ITEMTYPE_LEATHER = 3; 97 | uint32 const ITEMTYPE_MAIL = 4; 98 | uint32 const ITEMTYPE_PLATE = 5; 99 | uint32 const ITEMTYPE_WEAPONS = 6; 100 | 101 | uint32 const TARGET_NONE = 0; 102 | uint32 const TARGET_SELF = 1; 103 | uint32 const TARGET_VICTIM = 2; // current target 104 | uint32 const TARGET_HOSTILE_AGGRO_FROM_TOP = 3; // count TargetArg highest aggro from top within TargetArg2 distance 105 | uint32 const TARGET_HOSTILE_AGGRO_FROM_BOTTOM = 4; // count TargetArg lowest aggro from bottom within TargetArg2 distance 106 | uint32 const TARGET_HOSTILE_RANDOM = 5; // any random player from the threat list 107 | uint32 const TARGET_HOSTILE_RANDOM_NOT_TOP = 6; // any random player from the threat list except the current target 108 | uint32 const TARGET_PLAYER_DISTANCE = 18; // a random player within TargetArg range 109 | 110 | const std::string REWARD_MAIL_SUBJECT = "Chromie's Reward for you"; 111 | const std::string REWARD_MAIL_BODY = "Enjoy your new item!"; 112 | 113 | const std::string ModZoneDifficultyString = "mod-zone-difficulty#"; 114 | 115 | enum ZoneDifficultySettings 116 | { 117 | // Score settings 118 | TYPE_NONE = 0, 119 | TYPE_VANILLA = 1, 120 | TYPE_RAID_MC = 2, 121 | TYPE_RAID_ONY = 3, 122 | TYPE_RAID_BWL = 4, 123 | TYPE_RAID_ZG = 5, 124 | TYPE_RAID_AQ20 = 6, 125 | TYPE_RAID_AQ40 = 7, 126 | TYPE_HEROIC_TBC = 8, 127 | TYPE_RAID_T4 = 9, 128 | TYPE_RAID_SSC = 10, 129 | TYPE_RAID_T6 = 11, 130 | TYPE_RAID_ZA = 12, 131 | TYPE_HEROIC_WOTLK = 13, 132 | TYPE_RAID_T7 = 14, 133 | TYPE_RAID_T8 = 15, 134 | TYPE_RAID_T9 = 16, 135 | TYPE_RAID_T10 = 17, 136 | TYPE_RAID_HYJAL = 18, 137 | TYPE_RAID_SWP = 19, 138 | 139 | TYPE_MAX_TIERS, 140 | 141 | // Completed tiers settings 142 | SETTING_BLACK_TEMPLE = 0, 143 | SETTING_ZULAMAN = 1, 144 | SETTING_SSC = 2, 145 | SETTING_HYJAL = 3, 146 | SETTING_SWP = 4 147 | }; 148 | 149 | enum Misc 150 | { 151 | NPC_ILLIDAN_STORMRAGE = 22917, 152 | NPC_LADY_VASHJ = 21212, 153 | NPC_ARCHIMONDE = 17968, 154 | NPC_ZULJIN = 23863, 155 | NPC_KILJAEDEN = 25315, 156 | NPC_REWARD_CHROMIE = 1128002, 157 | }; 158 | 159 | class ZoneDifficulty 160 | { 161 | public: 162 | static ZoneDifficulty* instance(); 163 | 164 | void LoadMapDifficultySettings(); 165 | void SaveMythicmodeInstanceData(uint32 instanceId); 166 | void LoadMythicmodeInstanceData(); 167 | void LoadMythicmodeScoreData(); 168 | void SendWhisperToRaid(std::string message, Creature* creature, Player* player); 169 | std::string GetItemTypeString(uint32 type); 170 | std::string GetContentTypeString(uint32 type); 171 | void AddMythicmodeScore(Map* map, uint32 type, uint32 score); 172 | void DeductMythicmodeScore(Player* player, uint32 type, uint32 score); 173 | void SendItem(Player* player, ZoneDifficultyRewardData data); 174 | std::list GetTargetList(Unit* unit, uint32 entry, uint32 key); 175 | void MythicmodeEvent(Unit* unit, uint32 entry, uint32 key); 176 | bool HasNormalMode(int8 mode) { return (mode & MODE_NORMAL) == MODE_NORMAL; } 177 | bool HasMythicmode(int8 mode) { return (mode & MODE_HARD) == MODE_HARD; } 178 | bool HasCompletedFullTier(uint32 category, uint32 playerGUID); 179 | bool OverrideModeMatches(uint32 instanceId, uint32 spellId, uint32 mapId); 180 | [[nodiscard]] bool CheckCompletionStatus(Creature* creature, Player* player, uint32 category) const; 181 | [[nodiscard]] bool IsValidNerfTarget(Unit* target); 182 | [[nodiscard]] bool VectorContainsUint32(std::vector vec, uint32 element); 183 | [[nodiscard]] bool IsMythicmodeMap(uint32 mapid); 184 | [[nodiscard]] bool ShouldNerfInDuels(Unit* target); 185 | [[nodiscard]] bool ShouldNerfMap(uint32 mapId) { return NerfInfo.find(mapId) != NerfInfo.end(); }; 186 | [[nodiscard]] int32 GetLowestMatchingPhase(uint32 mapId, uint32 phaseMask); 187 | void RewardItem(Player* player, uint8 category, uint8 itemType, uint8 counter, Creature* creature, uint32 itemEntry); 188 | void LogAndAnnounceKill(Map* map, bool isMythic); 189 | void ProcessCreatureDeath(Map* map, uint32 entry); 190 | 191 | bool IsEnabled{ false }; 192 | bool IsDebugInfoEnabled{ false }; 193 | float MythicmodeHpModifier{ 2.0 }; 194 | bool MythicmodeEnable{ false }; 195 | bool MythicmodeInNormalDungeons{ false }; 196 | bool UseVendorInterface{ false }; 197 | bool IsBlackTempleDone{ false }; 198 | bool IsSunwellPlateauDone{ false }; 199 | std::vector DailyHeroicQuests; 200 | std::map HeroicTBCQuestMapList; 201 | std::map EncounterCounter; 202 | std::map Expansion; 203 | std::map CreatureOverrides; 204 | std::map EncountersInProgress; 205 | std::map ItemIcons; 206 | std::map TierRewards; 207 | 208 | typedef std::map > ZoneDifficultyNerfDataMap; 209 | ZoneDifficultyNerfDataMap NerfInfo; 210 | typedef std::map > ZoneDifficultySpellNerfMap; 211 | ZoneDifficultySpellNerfMap SpellNerfOverrides; 212 | typedef std::map > ZoneDifficultyDisablesMap; 213 | ZoneDifficultyDisablesMap DisallowedBuffs; 214 | typedef std::map ZoneDifficultyMythicmodeInstDataMap; 215 | ZoneDifficultyMythicmodeInstDataMap MythicmodeInstanceData; 216 | typedef std::map > ZoneDifficultyMythicmodeLootMap; 217 | ZoneDifficultyMythicmodeLootMap MythicmodeLoot; 218 | typedef std::map > ZoneDifficultyDualUintMap; 219 | ZoneDifficultyDualUintMap MythicmodeScore; // Deprecated, to be removed. 220 | typedef std::map > > ZoneDifficultyRewardMap; 221 | ZoneDifficultyRewardMap Rewards; 222 | typedef std::map > ZoneDifficultyHAIMap; 223 | ZoneDifficultyHAIMap MythicmodeAI; 224 | typedef std::map > > ZoneDifficultyEncounterLogMap; 225 | ZoneDifficultyEncounterLogMap Logs; 226 | typedef std::unordered_map ZoneDifficultyVendorSelectionMap; 227 | ZoneDifficultyVendorSelectionMap SelectionCache; 228 | }; 229 | 230 | #define sZoneDifficulty ZoneDifficulty::instance() 231 | 232 | #endif 233 | -------------------------------------------------------------------------------- /data/sql/db-world/zone_difficulty_mythicmode_creatures.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM `creature_template` WHERE `entry` IN (1128001,1128002); 2 | DELETE FROM `creature_template_model` WHERE `CreatureID` IN (1128001,1128002); 3 | 4 | DELETE FROM `creature` WHERE `guid` IN 5 | (303000,303001,303002,303003,303004,303005,303006,303007,303008,303009,303010,303011,303012,303013,303014,303015,303016,303017,303018, 303019, 303020, 303021, 303022, 303023); 6 | 7 | DELETE FROM `npc_text` WHERE `ID` IN (91301,91302,91303,91304,91305,91306,91307,91308,91309,91310,91311); 8 | 9 | INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `name`, `subname`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `DamageModifier`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_spell`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `HoverHeight`, `HealthModifier`, `ManaModifier`, `ArmorModifier`, `RacialLeader`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `spell_school_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES 10 | (1128001, 0, 0, 0, 0, 0, 'Chromie', '', 0, 63, 63, 0, 35, 1, 1, 1.14286, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 33536, 2048, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1.35, 1, 1, 0, 0, 1, 0, 0, 2, 'mod_zone_difficulty_dungeonmaster', 0), 11 | (1128002, 0, 0, 0, 0, 0, 'Chromie', '', 0, 63, 63, 0, 35, 1, 1, 1.14286, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 33536, 2048, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1.35, 1, 1, 0, 0, 1, 0, 0, 2, 'mod_zone_difficulty_rewardnpc', 0); 12 | 13 | INSERT INTO `creature_template_model` (`CreatureID`, `Idx`, `CreatureDisplayID`, `DisplayScale`, `Probability`, `VerifiedBuild`) VALUES 14 | (1128001, 0, 10008, 1, 1, 0), 15 | (1128002, 0, 27568, 1, 1, 0); 16 | 17 | INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES 18 | -- Reward NPC 19 | (303000, 1128002, 0, 0, 530, 3703, 3703, 1, 1, 0, -1809.08, 5294.03, -12.4, 1.98, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 20 | -- Gruul's Lair 21 | (303001, 1128001, 0, 0, 565, 3923, 3923, 1, 1, 0, 76.64, 55.82, -5.38, 3.29, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 22 | -- Magtheridon's Lair 23 | (303002, 1128001, 0, 0, 544, 3836, 3836, 1, 1, 0, 232.00, 9.90, 68.03, 3.17, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 24 | -- Blood Furnace 25 | (303003, 1128001, 0, 0, 542, 3713, 3713, 2, 1024, 0, -9.9, 7.28, -44.6, 0.45, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 26 | -- Hellfire Ramparts 27 | (303004, 1128001, 0, 0, 543, 3562, 3562, 2, 1024, 0, -1362.3, 1650.80, 68.42, 5.77, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 28 | -- Slave Pens 29 | (303005, 1128001, 0, 0, 547, 3717, 3717, 2, 1024, 0, 135.1, -121.3, -1.56, 2.86, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 30 | -- The Underbog 31 | (303006, 1128001, 0, 0, 546, 3716, 3716, 2, 1024, 0, 11.9, -29.06, -2.75, 0.99, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 32 | -- Mana-Tombs 33 | (303007, 1128001, 0, 0, 557, 3792, 3792, 2, 1024, 0, -3.57, -6.31, -0.95, 1.59, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 34 | -- Auchenai Crypts 35 | (303008, 1128001, 0, 0, 558, 3790, 3790, 2, 1024, 0, -17.65, 7.91, -0.12, 4.72, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 36 | -- The Escape From Durnholde 37 | (303009, 1128001, 0, 0, 560, 2367, 2367, 2, 1024, 0, 2705.16, 1320.52, 14.06, 5.82, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 38 | -- Sethekk Halls 39 | (303010, 1128001, 0, 0, 556, 3791, 3791, 2, 1024, 0, 1.56, 7.91, 0.01, 4.88, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 40 | -- Magisters' Terrace 41 | (303011, 1128001, 0, 0, 585, 4131, 4131, 2, 1024, 0, 6.79, 9.90, -2.81, 4.74, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 42 | -- Shadow Labyrinth 43 | (303012, 1128001, 0, 0, 555, 3789, 3789, 2, 1024, 0, -3.26, -8.02, -1.12, 1.46, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 44 | -- Shattered Halls 45 | (303013, 1128001, 0, 0, 540, 3714, 3714, 2, 1024, 0, -35.76, -16.70, -13.87, 2.93, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 46 | -- The Arcatraz 47 | (303014, 1128001, 0, 0, 552, 3848, 3848, 2, 1024, 0, 20.11, 6.33, -0.16, 4.56, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 48 | -- The Black Morass 49 | (303015, 1128001, 0, 0, 269, 2366, 2366, 2, 1024, 0, -1483.39, 7069.76, 32.80, 3.77, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 50 | -- The Botanica 51 | (303016, 1128001, 0, 0, 553, 3847, 3847, 2, 1024, 0, 26.34, -23.81, -1.06, 0.58, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 52 | -- The Mechanar 53 | (303017, 1128001, 0, 0, 554, 3849, 3849, 2, 1024, 0, -25.95, 14.52, -1.81, 5.08, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 54 | -- The Steamvault 55 | (303018, 1128001, 0, 0, 545, 3715, 3715, 2, 1024, 0, 9.83, 9.14, -3.86, 3.32, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 56 | -- The Black Temple 57 | (303019, 1128001, 0, 0, 564, 3959, 3959, 1, 1, 0, 106.39765, 1010.8968, -83.56905, 3.9945135, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 58 | -- ZA 59 | (303020, 1128001, 0, 0, 568, 3805, 3805, 1, 1, 0, 133.56032, 1636.4084, 42.022434, 2.8486438, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 60 | -- SWP 61 | (303021, 1128001, 0, 0, 580, 3805, 3805, 1, 1, 0, 1788.5121, 909.6668, 15.415432, 2.8752437, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 62 | -- Serpentshrine's Cavern 63 | (303022, 1128001, 0, 0, 548, 3607, 3607, 1, 1, 0, 8.319, 20.91, 823.9, 4.519, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0), 64 | -- hyjal 65 | (303023, 1128001, 0, 0, 534, 3607, 3607, 1, 1, 0, 4236.634, -4227.246, 870.4103, 1.0385315, 1000000, 0, 0, 0, 0, 0, 0, 0, 0, '', 0); 66 | 67 | INSERT INTO `npc_text` (`ID`, `text0_0`, `BroadcastTextID0`, `lang0`, `Probability0`, `em0_0`, `em0_1`, `em0_2`, `em0_3`, `em0_4`, `em0_5`, `BroadcastTextID1`, `lang1`, `Probability1`, `em1_0`, `em1_1`, `em1_2`, `em1_3`, `em1_4`, `em1_5`, `BroadcastTextID2`, `lang2`, `Probability2`, `em2_0`, `em2_1`, `em2_2`, `em2_3`, `em2_4`, `em2_5`, `BroadcastTextID3`, `lang3`, `Probability3`, `em3_0`, `em3_1`, `em3_2`, `em3_3`, `em3_4`, `em3_5`, `BroadcastTextID4`, `lang4`, `Probability4`, `em4_0`, `em4_1`, `em4_2`, `em4_3`, `em4_4`, `em4_5`, `BroadcastTextID5`, `lang5`, `Probability5`, `em5_0`, `em5_1`, `em5_2`, `em5_3`, `em5_4`, `em5_5`, `BroadcastTextID6`, `lang6`, `Probability6`, `em6_0`, `em6_1`, `em6_2`, `em6_3`, `em6_4`, `em6_5`, `BroadcastTextID7`, `lang7`, `Probability7`, `em7_0`, `em7_1`, `em7_2`, `em7_3`, `em7_4`, `em7_5`, `VerifiedBuild`) VALUES 68 | (91301, 'Hello, $n. How strong do you think you are? I am offering 2 different versions to witness the events of the past. If you don\'t tell me otherwise, i will show you the cinematic one.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 69 | (91302, 'Hello, $n. The leader of your party will have the final say about what you\'re going for.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 70 | (91303, 'Hello, $n. So you and your mates are after a challenge? I appreciate that. I will show you the real experience. Better be prepared!', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 71 | (91304, 'Are you sure you wish to leave the historic path? There will be no turning back for this time.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 72 | (91305, 'My pleasure to meet you, $n. I am offering rewards for the strongest and the toughest of all time-travelers. Did you stabilise the timeline enough to receive one of my rewards? What course did you run?', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 73 | (91306, 'Please pick a category for the item you desire?', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 74 | (91307, 'Which item would you like to obtain?', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 75 | (91308, 'Are you sure this is the right item? I don\'t do refunds!', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 76 | (91309, 'I can grant that wish! Please check your mail and enjoy!', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 77 | (91310, 'I\'m afraid that is beyond my capabilities for now. You should finish fixing the timeline before you request this.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 78 | (91311, 'Of course! Listen well, $n.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /src/mod_zone_difficulty_handler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 3 | */ 4 | 5 | #include "Config.h" 6 | #include "Chat.h" 7 | #include "GameTime.h" 8 | #include "ItemTemplate.h" 9 | #include "MapMgr.h" 10 | #include "Pet.h" 11 | #include "Player.h" 12 | #include "PoolMgr.h" 13 | #include "ScriptedCreature.h" 14 | #include "ScriptMgr.h" 15 | #include "SpellAuras.h" 16 | #include "SpellAuraEffects.h" 17 | #include "StringConvert.h" 18 | #include "TaskScheduler.h" 19 | #include "Tokenize.h" 20 | #include "Unit.h" 21 | #include "ZoneDifficulty.h" 22 | 23 | ZoneDifficulty* ZoneDifficulty::instance() 24 | { 25 | static ZoneDifficulty instance; 26 | return &instance; 27 | } 28 | 29 | void ZoneDifficulty::LoadMapDifficultySettings() 30 | { 31 | if (!sZoneDifficulty->IsEnabled) 32 | return; 33 | 34 | sZoneDifficulty->Rewards.clear(); 35 | sZoneDifficulty->MythicmodeAI.clear(); 36 | sZoneDifficulty->CreatureOverrides.clear(); 37 | sZoneDifficulty->DailyHeroicQuests.clear(); 38 | sZoneDifficulty->MythicmodeLoot.clear(); 39 | sZoneDifficulty->DisallowedBuffs.clear(); 40 | sZoneDifficulty->SpellNerfOverrides.clear(); 41 | sZoneDifficulty->NerfInfo.clear(); 42 | 43 | // Default values for when there is no entry in the db for duels (index 0xFFFFFFFF) 44 | NerfInfo[DUEL_INDEX][0].HealingNerfPct = 1; 45 | NerfInfo[DUEL_INDEX][0].AbsorbNerfPct = 1; 46 | NerfInfo[DUEL_INDEX][0].MeleeDamageBuffPct = 1; 47 | NerfInfo[DUEL_INDEX][0].SpellDamageBuffPct = 1; 48 | NerfInfo[DUEL_INDEX][0].HealingNerfPctHard = 1; 49 | NerfInfo[DUEL_INDEX][0].AbsorbNerfPctHard = 1; 50 | NerfInfo[DUEL_INDEX][0].MeleeDamageBuffPctHard = 1; 51 | NerfInfo[DUEL_INDEX][0].SpellDamageBuffPctHard = 1; 52 | 53 | // Heroic Quest -> MapId Translation 54 | HeroicTBCQuestMapList[542] = 11362; // Blood Furnace 55 | HeroicTBCQuestMapList[543] = 11354; // Hellfire Ramparts 56 | HeroicTBCQuestMapList[547] = 11368; // Slave Pens 57 | HeroicTBCQuestMapList[546] = 11369; // The Underbog 58 | HeroicTBCQuestMapList[557] = 11373; // Mana-Tombs 59 | HeroicTBCQuestMapList[558] = 11374; // Auchenai Crypts 60 | HeroicTBCQuestMapList[560] = 11378; // The Escape From Durnholde 61 | HeroicTBCQuestMapList[556] = 11372; // Sethekk Halls 62 | HeroicTBCQuestMapList[585] = 11499; // Magisters' Terrace 63 | HeroicTBCQuestMapList[555] = 11375; // Shadow Labyrinth 64 | HeroicTBCQuestMapList[540] = 11363; // Shattered Halls 65 | HeroicTBCQuestMapList[552] = 11388; // The Arcatraz 66 | HeroicTBCQuestMapList[269] = 11382; // The Black Morass 67 | HeroicTBCQuestMapList[553] = 11384; // The Botanica 68 | HeroicTBCQuestMapList[554] = 11386; // The Mechanar 69 | HeroicTBCQuestMapList[545] = 11370; // The Steamvault 70 | 71 | // Category 8 72 | EncounterCounter[542] = 3; // Blood Furnace 73 | EncounterCounter[543] = 3; // Hellfire Ramparts 74 | EncounterCounter[547] = 3; // Slave Pens 75 | EncounterCounter[546] = 4; // The Underbog 76 | EncounterCounter[557] = 4; // Mana-Tombs 77 | EncounterCounter[558] = 2; // Auchenai Crypts 78 | EncounterCounter[560] = 3; // The Escape From Durnholde 79 | EncounterCounter[556] = 3; // Sethekk Halls 80 | //EncounterCounter[585] = 4; // Magisters' Terrace 81 | EncounterCounter[555] = 4; // Shadow Labyrinth 82 | EncounterCounter[540] = 4; // Shattered Halls 83 | EncounterCounter[552] = 4; // The Arcatraz 84 | EncounterCounter[269] = 3; // The Black Morass 85 | EncounterCounter[553] = 5; // The Botanica 86 | EncounterCounter[554] = 3; // The Mechanar 87 | EncounterCounter[545] = 3; // The Steamvault 88 | 89 | // Category 9 90 | EncounterCounter[565] = 2; // Gruul's Lair 91 | EncounterCounter[544] = 1; // Magtheridon's Lair 92 | EncounterCounter[532] = 12; // Karazhan 93 | 94 | // Category 10 95 | EncounterCounter[548] = 7; // Serpentshrine Cavern 96 | 97 | // Category 11 98 | EncounterCounter[564] = 9; // Black Temple 99 | 100 | // Category 12 101 | EncounterCounter[568] = 6; // Zul'Aman 102 | 103 | // Category 18 104 | EncounterCounter[534] = 5; // Hyjal Summit 105 | 106 | // Category 19 107 | EncounterCounter[580] = 6; // Sunwell Plateau 108 | 109 | // Icons 110 | sZoneDifficulty->ItemIcons[ITEMTYPE_MISC] = "|TInterface\\icons\\inv_misc_cape_17:15|t |TInterface\\icons\\inv_misc_gem_topaz_02:15|t |TInterface\\icons\\inv_jewelry_ring_51naxxramas:15|t "; 111 | sZoneDifficulty->ItemIcons[ITEMTYPE_CLOTH] = "|TInterface\\icons\\inv_chest_cloth_42:15|t "; 112 | sZoneDifficulty->ItemIcons[ITEMTYPE_LEATHER] = "|TInterface\\icons\\inv_helmet_41:15|t "; 113 | sZoneDifficulty->ItemIcons[ITEMTYPE_MAIL] = "|TInterface\\icons\\inv_chest_chain_13:15|t "; 114 | sZoneDifficulty->ItemIcons[ITEMTYPE_PLATE] = "|TInterface\\icons\\inv_chest_plate12:15|t "; 115 | sZoneDifficulty->ItemIcons[ITEMTYPE_WEAPONS] = "|TInterface\\icons\\inv_mace_25:15|t |TInterface\\icons\\inv_shield_27:15|t |TInterface\\icons\\inv_weapon_crossbow_04:15|t "; 116 | 117 | if (QueryResult result = WorldDatabase.Query("SELECT * FROM zone_difficulty_info WHERE Enabled > 0")) 118 | { 119 | do 120 | { 121 | uint32 mapId = (*result)[0].Get(); 122 | uint32 phaseMask = (*result)[1].Get(); 123 | ZoneDifficultyNerfData data; 124 | int8 mode = (*result)[6].Get(); 125 | 126 | if (sZoneDifficulty->HasNormalMode(mode)) 127 | { 128 | data.HealingNerfPct = (*result)[2].Get(); 129 | data.AbsorbNerfPct = (*result)[3].Get(); 130 | data.MeleeDamageBuffPct = (*result)[4].Get(); 131 | data.SpellDamageBuffPct = (*result)[5].Get(); 132 | data.Enabled = data.Enabled | mode; 133 | sZoneDifficulty->NerfInfo[mapId][phaseMask].HealingNerfPct = data.HealingNerfPct; 134 | sZoneDifficulty->NerfInfo[mapId][phaseMask].AbsorbNerfPct = data.AbsorbNerfPct; 135 | sZoneDifficulty->NerfInfo[mapId][phaseMask].MeleeDamageBuffPct = data.MeleeDamageBuffPct; 136 | sZoneDifficulty->NerfInfo[mapId][phaseMask].SpellDamageBuffPct = data.SpellDamageBuffPct; 137 | sZoneDifficulty->NerfInfo[mapId][phaseMask].Enabled |= mode; 138 | } 139 | if (sZoneDifficulty->HasMythicmode(mode) && sZoneDifficulty->MythicmodeEnable) 140 | { 141 | data.HealingNerfPctHard = (*result)[2].Get(); 142 | data.AbsorbNerfPctHard = (*result)[3].Get(); 143 | data.MeleeDamageBuffPctHard = (*result)[4].Get(); 144 | data.SpellDamageBuffPctHard = (*result)[5].Get(); 145 | data.Enabled = data.Enabled | mode; 146 | sZoneDifficulty->NerfInfo[mapId][phaseMask].HealingNerfPctHard = data.HealingNerfPctHard; 147 | sZoneDifficulty->NerfInfo[mapId][phaseMask].AbsorbNerfPctHard = data.AbsorbNerfPctHard; 148 | sZoneDifficulty->NerfInfo[mapId][phaseMask].MeleeDamageBuffPctHard = data.MeleeDamageBuffPctHard; 149 | sZoneDifficulty->NerfInfo[mapId][phaseMask].SpellDamageBuffPctHard = data.SpellDamageBuffPctHard; 150 | sZoneDifficulty->NerfInfo[mapId][phaseMask].Enabled |= mode; 151 | } 152 | if ((mode & MODE_HARD) != MODE_HARD && (mode & MODE_NORMAL) != MODE_NORMAL) 153 | { 154 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Invalid mode {} used in Enabled for mapId {}, ignored.", mode, mapId); 155 | } 156 | 157 | // duels do not check for phases. Only 0 is allowed. 158 | if (mapId == DUEL_INDEX && phaseMask != 0) 159 | { 160 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Table `zone_difficulty_info` for criteria (duel mapId: {}) has wrong value ({}), must be 0 for duels.", mapId, phaseMask); 161 | } 162 | 163 | } while (result->NextRow()); 164 | } 165 | 166 | if (QueryResult result = WorldDatabase.Query("SELECT * FROM zone_difficulty_spelloverrides")) 167 | { 168 | do 169 | { 170 | if ((*result)[3].Get() > 0) 171 | { 172 | sZoneDifficulty->SpellNerfOverrides[(*result)[0].Get()][(*result)[1].Get()].NerfPct = (*result)[2].Get(); 173 | sZoneDifficulty->SpellNerfOverrides[(*result)[0].Get()][(*result)[1].Get()].ModeMask = (*result)[3].Get(); 174 | } 175 | 176 | } while (result->NextRow()); 177 | } 178 | 179 | if (QueryResult result = WorldDatabase.Query("SELECT * FROM zone_difficulty_disallowed_buffs")) 180 | { 181 | do 182 | { 183 | std::vector debuffs; 184 | uint32 mapId = 0; 185 | if ((*result)[2].Get()) 186 | { 187 | std::string spellString = (*result)[1].Get(); 188 | std::vector tokens = Acore::Tokenize(spellString, ' ', false); 189 | 190 | mapId = (*result)[0].Get(); 191 | for (auto token : tokens) 192 | { 193 | if (token.empty()) 194 | continue; 195 | 196 | uint32 spell = 0; 197 | if ((spell = Acore::StringTo(token).value())) 198 | debuffs.push_back(spell); 199 | else 200 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Disabling buffs for spell '{}' is invalid, skipped.", spell); 201 | } 202 | sZoneDifficulty->DisallowedBuffs[mapId] = debuffs; 203 | } 204 | } while (result->NextRow()); 205 | } 206 | 207 | if (QueryResult result = WorldDatabase.Query("SELECT * FROM zone_difficulty_mythicmode_instance_data")) 208 | { 209 | do 210 | { 211 | ZoneDifficultyMythicmodeMapData data; 212 | uint32 MapID = (*result)[0].Get(); 213 | data.EncounterEntry = (*result)[1].Get(); 214 | data.Override = (*result)[2].Get(); 215 | data.RewardType = (*result)[3].Get(); 216 | 217 | sZoneDifficulty->MythicmodeLoot[MapID].push_back(data); 218 | //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: New creature for map {} with entry: {}", MapID, data.EncounterEntry); 219 | 220 | Expansion[MapID] = data.RewardType; 221 | 222 | } while (result->NextRow()); 223 | } 224 | else 225 | { 226 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Query failed: SELECT * FROM zone_difficulty_mythicmode_instance_data"); 227 | } 228 | 229 | if (QueryResult result = WorldDatabase.Query("SELECT entry FROM `pool_quest` WHERE `pool_entry`=356")) 230 | { 231 | do 232 | { 233 | sZoneDifficulty->DailyHeroicQuests.push_back((*result)[0].Get()); 234 | //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Adding daily heroic quest with id {}.", (*result)[0].Get()); 235 | } while (result->NextRow()); 236 | } 237 | else 238 | { 239 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Query failed: SELECT entry FROM `pool_quest` WHERE `pool_entry`=356"); 240 | } 241 | 242 | if (QueryResult result = WorldDatabase.Query("SELECT * FROM zone_difficulty_mythicmode_creatureoverrides")) 243 | { 244 | do 245 | { 246 | uint32 creatureEntry = (*result)[0].Get(); 247 | float hpModifier = (*result)[1].Get(); 248 | float hpModifierNormal = (*result)[2].Get(); 249 | bool enabled = (*result)[3].Get(); 250 | 251 | if (enabled) 252 | { 253 | CreatureOverrideData data; 254 | if (hpModifier) 255 | data.MythicOverride = hpModifier; 256 | 257 | if (hpModifierNormal) 258 | data.NormalOverride = hpModifierNormal; 259 | 260 | sZoneDifficulty->CreatureOverrides[creatureEntry] = data; 261 | //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: New creature with entry: {} has exception for hp: {}", creatureEntry, hpModifier); 262 | } 263 | } while (result->NextRow()); 264 | } 265 | else 266 | { 267 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Query failed: SELECT * FROM zone_difficulty_mythicmode_creatureoverrides"); 268 | } 269 | 270 | if (QueryResult result = WorldDatabase.Query("SELECT * FROM zone_difficulty_mythicmode_ai")) 271 | { 272 | do 273 | { 274 | bool enabled = (*result)[12].Get(); 275 | 276 | if (enabled) 277 | { 278 | uint32 creatureEntry = (*result)[0].Get(); 279 | ZoneDifficultyHAI data; 280 | data.Chance = (*result)[1].Get(); 281 | data.Spell = (*result)[2].Get(); 282 | data.Spellbp0 = (*result)[3].Get(); 283 | data.Spellbp1 = (*result)[4].Get(); 284 | data.Spellbp2 = (*result)[5].Get(); 285 | data.Target = (*result)[6].Get(); 286 | data.TargetArg = (*result)[7].Get(); 287 | data.TargetArg2 = (*result)[8].Get(); 288 | data.Delay = (*result)[9].Get(); 289 | data.Cooldown = (*result)[10].Get(); 290 | data.Repetitions = (*result)[11].Get(); 291 | data.TriggeredCast = (*result)[13].Get(); 292 | 293 | if (data.Chance != 0 && data.Spell != 0 && ((data.Target >= 1 && data.Target <= 6) || data.Target == 18)) 294 | { 295 | sZoneDifficulty->MythicmodeAI[creatureEntry].push_back(data); 296 | LOG_INFO("module", "MOD-ZONE-DIFFICULTY: New AI for entry {} with spell {}", creatureEntry, data.Spell); 297 | } 298 | else 299 | { 300 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Unknown type for `Target`: {} in zone_difficulty_mythicmode_ai", data.Target); 301 | } 302 | //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: New creature with entry: {} has exception for hp: {}", creatureEntry, hpModifier); 303 | } 304 | } while (result->NextRow()); 305 | } 306 | else 307 | { 308 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Query failed: SELECT * FROM zone_difficulty_mythicmode_ai"); 309 | } 310 | 311 | //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Starting load of rewards."); 312 | if (QueryResult result = WorldDatabase.Query("SELECT ContentType, ItemType, Entry, Price, Enchant, EnchantSlot, Achievement, Enabled FROM zone_difficulty_mythicmode_rewards")) 313 | { 314 | /* debug 315 | * uint32 i = 0; 316 | * end debug 317 | */ 318 | do 319 | { 320 | /* debug 321 | * ++i; 322 | * end debug 323 | */ 324 | ZoneDifficultyRewardData data; 325 | uint32 contentType = (*result)[0].Get(); 326 | uint32 itemType = (*result)[1].Get(); 327 | data.Entry = (*result)[2].Get(); 328 | data.Price = (*result)[3].Get(); 329 | data.Enchant = (*result)[4].Get(); 330 | data.EnchantSlot = (*result)[5].Get(); 331 | data.Achievement = (*result)[6].Get(); 332 | bool enabled = (*result)[7].Get(); 333 | 334 | if (enabled) 335 | { 336 | if (data.Achievement >= 0) 337 | { 338 | sZoneDifficulty->Rewards[contentType][itemType].push_back(data); 339 | //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Loading item with entry {} has enchant {} in slot {}. contentType: {} itemType: {}", data.Entry, data.Enchant, data.EnchantSlot, contentType, itemType); 340 | } 341 | else 342 | { 343 | sZoneDifficulty->TierRewards[contentType] = data; 344 | //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Loading tier reward with entry {} has enchant {} in slot {}. contentType: {} itemType: {}", data.Entry, data.Enchant, data.EnchantSlot, contentType, itemType); 345 | } 346 | } 347 | //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Total items in Rewards map: {}.", i); 348 | } while (result->NextRow()); 349 | } 350 | else 351 | { 352 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Query failed: SELECT ContentType, ItemType, Entry, Price, Enchant, EnchantSlot, Achievement, Enabled FROM zone_difficulty_mythicmode_rewards"); 353 | } 354 | } 355 | 356 | /** 357 | * @brief Loads the MythicmodeInstanceData from the database. Fetch from zone_difficulty_instance_saves. 358 | * 359 | * `InstanceID` INT NOT NULL DEFAULT 0, 360 | * `MythicmodeOn` TINYINT NOT NULL DEFAULT 0, 361 | * 362 | * Exclude data not in the IDs stored in GetInstanceIDs() and delete 363 | * zone_difficulty_instance_saves for instances that no longer exist. 364 | */ 365 | void ZoneDifficulty::LoadMythicmodeInstanceData() 366 | { 367 | std::vector instanceIDs = sMapMgr->GetInstanceIDs(); 368 | /* debugging 369 | * for (int i = 0; i < int(instanceIDs.size()); i++) 370 | * { 371 | * LOG_INFO("module", "MOD-ZONE-DIFFICULTY: ZoneDifficulty::LoadMythicmodeInstanceData: id {} exists: {}:", i, instanceIDs[i]); 372 | * } 373 | * end debugging 374 | */ 375 | if (QueryResult result = CharacterDatabase.Query("SELECT * FROM zone_difficulty_instance_saves")) 376 | { 377 | do 378 | { 379 | uint32 InstanceId = (*result)[0].Get(); 380 | bool MythicmodeOn = (*result)[1].Get(); 381 | 382 | if (instanceIDs[InstanceId]) 383 | { 384 | LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Loading from DB for instanceId {}: MythicmodeOn = {}", InstanceId, MythicmodeOn); 385 | sZoneDifficulty->MythicmodeInstanceData[InstanceId] = MythicmodeOn; 386 | } 387 | else 388 | { 389 | CharacterDatabase.Execute("DELETE FROM zone_difficulty_instance_saves WHERE InstanceID = {}", InstanceId); 390 | } 391 | 392 | 393 | } while (result->NextRow()); 394 | } 395 | } 396 | 397 | /** 398 | * @brief Loads the score data and encounter logs from the database. 399 | * Fetch from zone_difficulty_mythicmode_score. 400 | * 401 | * `CharacterGuid` INT NOT NULL DEFAULT 0, 402 | * `Type` TINYINT NOT NULL DEFAULT 0, 403 | * `Score` INT NOT NULL DEFAULT 0, 404 | * 405 | * Fetch from zone_difficulty_encounter_logs. 406 | * `InstanceId` INT NOT NULL DEFAULT 0, 407 | * `TimestampStart` INT NOT NULL DEFAULT 0, 408 | * `TimestampEnd` INT NOT NULL DEFAULT 0, 409 | * `Map` INT NOT NULL DEFAULT 0, 410 | * `BossId` INT NOT NULL DEFAULT 0, 411 | * `PlayerGuid` INT NOT NULL DEFAULT 0, 412 | * `Mode` INT NOT NULL DEFAULT 0, 413 | * 414 | */ 415 | void ZoneDifficulty::LoadMythicmodeScoreData() 416 | { 417 | if (QueryResult result = CharacterDatabase.Query("SELECT * FROM zone_difficulty_mythicmode_score")) 418 | { 419 | do 420 | { 421 | uint32 GUID = (*result)[0].Get(); 422 | uint8 Type = (*result)[1].Get(); 423 | uint32 Score = (*result)[2].Get(); 424 | 425 | //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Loading from DB for player with GUID {}: Type = {}, Score = {}", GUID, Type, Score); 426 | sZoneDifficulty->MythicmodeScore[GUID][Type] = Score; 427 | 428 | } while (result->NextRow()); 429 | } 430 | 431 | if (QueryResult result = CharacterDatabase.Query("SELECT `Map`, `BossId`, `PlayerGuid` FROM zone_difficulty_encounter_logs WHERE `Mode` = 64")) 432 | { 433 | do 434 | { 435 | uint32 MapId = (*result)[0].Get(); 436 | uint8 BossID = (*result)[1].Get(); 437 | uint32 PlayerGuid = (*result)[2].Get(); 438 | 439 | // Set all BossID which aren't true to false for that mapID 440 | if (sZoneDifficulty->Logs[PlayerGuid].find(MapId) == sZoneDifficulty->Logs[PlayerGuid].end()) 441 | { 442 | for (int i = 0; i < sZoneDifficulty->EncounterCounter[MapId]; ++i) 443 | sZoneDifficulty->Logs[PlayerGuid][MapId][i] = false; 444 | } 445 | sZoneDifficulty->Logs[PlayerGuid][MapId][BossID] = true; 446 | } while (result->NextRow()); 447 | } 448 | } 449 | 450 | /** 451 | * @brief Sends a whisper to all members of the player's raid in the same instance as the creature. 452 | * 453 | * @param message The message which should be sent to the . 454 | * @param creature The creature who sends the whisper. 455 | * @param player The object of the player, whose whole group should receive the message. 456 | */ 457 | void ZoneDifficulty::SendWhisperToRaid(std::string message, Creature* creature, Player* player) 458 | { 459 | if (Map* map = creature->GetMap()) 460 | { 461 | map->DoForAllPlayers([&, player, creature](Player* mapPlayer) { 462 | if (creature && player) 463 | { 464 | if (mapPlayer->IsInSameGroupWith(player)) 465 | creature->Whisper(message, LANG_UNIVERSAL, mapPlayer); 466 | } 467 | }); 468 | } 469 | } 470 | 471 | std::string ZoneDifficulty::GetItemTypeString(uint32 type) 472 | { 473 | std::string typestring; 474 | switch (type) 475 | { 476 | case ITEMTYPE_MISC: 477 | typestring = "Back, Finger, Neck, and Trinket"; 478 | break; 479 | case ITEMTYPE_CLOTH: 480 | typestring = "Cloth"; 481 | break; 482 | case ITEMTYPE_LEATHER: 483 | typestring = "Leather"; 484 | break; 485 | case ITEMTYPE_MAIL: 486 | typestring = "Mail"; 487 | break; 488 | case ITEMTYPE_PLATE: 489 | typestring = "Plate"; 490 | break; 491 | case ITEMTYPE_WEAPONS: 492 | typestring = "Weapons and Shields"; 493 | break; 494 | default: 495 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Unknown type {} in ZoneDifficulty::GetItemTypeString.", type); 496 | } 497 | return typestring; 498 | } 499 | 500 | std::string ZoneDifficulty::GetContentTypeString(uint32 type) 501 | { 502 | std::string typestring; 503 | switch (type) 504 | { 505 | case TYPE_VANILLA: 506 | typestring = "for Vanilla dungeons."; 507 | break; 508 | case TYPE_RAID_MC: 509 | typestring = "for Molten Core."; 510 | break; 511 | case TYPE_RAID_ONY: 512 | typestring = "for Onyxia."; 513 | break; 514 | case TYPE_RAID_BWL: 515 | typestring = "for Blackwing Lair."; 516 | break; 517 | case TYPE_RAID_ZG: 518 | typestring = "for Zul Gurub."; 519 | break; 520 | case TYPE_RAID_AQ20: 521 | typestring = "for Ruins of Ahn'Qiraj."; 522 | break; 523 | case TYPE_RAID_AQ40: 524 | typestring = "for Temple of Ahn'Qiraj."; 525 | break; 526 | case TYPE_HEROIC_TBC: 527 | typestring = "for Heroic TBC dungeons."; 528 | break; 529 | case TYPE_RAID_T4: 530 | typestring = "for T4 Raids."; 531 | break; 532 | case TYPE_RAID_SSC: 533 | typestring = "for Serpentshrine Cavern."; 534 | break; 535 | case TYPE_RAID_T6: 536 | typestring = "for T6 Raids."; 537 | break; 538 | case TYPE_RAID_ZA: 539 | typestring = "for Zul'Aman."; 540 | break; 541 | case TYPE_HEROIC_WOTLK: 542 | typestring = "for Heroic WotLK dungeons."; 543 | break; 544 | case TYPE_RAID_T7: 545 | typestring = "for T7 Raids."; 546 | break; 547 | case TYPE_RAID_T8: 548 | typestring = "for T8 Raids."; 549 | break; 550 | case TYPE_RAID_T9: 551 | typestring = "for T9 Raids."; 552 | break; 553 | case TYPE_RAID_T10: 554 | typestring = "for T10 Raids."; 555 | break; 556 | case TYPE_RAID_HYJAL: 557 | typestring = "for Battle for Mount Hyjal."; 558 | break; 559 | case TYPE_RAID_SWP: 560 | typestring = "for Sunwell Plateau."; 561 | break; 562 | default: 563 | typestring = "-"; 564 | } 565 | return typestring; 566 | } 567 | 568 | /** 569 | * @brief Grants every player in the group one score for the Mythicmode. 570 | * 571 | * @param map The map where the player is currently. 572 | * @param type The type of instance the score is awarded for. 573 | */ 574 | void ZoneDifficulty::AddMythicmodeScore(Map* map, uint32 type, uint32 score) 575 | { 576 | if (!map) 577 | { 578 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: No object for map in AddMythicmodeScore."); 579 | return; 580 | } 581 | if (type > 255) 582 | { 583 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Wrong value for type: {} in AddMythicmodeScore for map with id {}.", type, map->GetInstanceId()); 584 | return; 585 | } 586 | 587 | map->DoForAllPlayers([&](Player* player) 588 | { 589 | uint32 previousScore = player->GetPlayerSetting(ModZoneDifficultyString + "score", type).value; 590 | player->UpdatePlayerSetting(ModZoneDifficultyString + "score", type, previousScore + score); 591 | std::string typestring = sZoneDifficulty->GetContentTypeString(type); 592 | ChatHandler(player->GetSession()).PSendSysMessage("You have received Mythicmode score {} New score: {}", typestring, previousScore + score); 593 | }); 594 | } 595 | 596 | /** 597 | * @brief Reduce the score of players when they pay for rewards. 598 | * 599 | * @param player The one who pays with their score. 600 | * @param type The type of instance the score is deducted for. 601 | */ 602 | void ZoneDifficulty::DeductMythicmodeScore(Player* player, uint32 type, uint32 score) 603 | { 604 | // NULL check happens in the calling function 605 | if (sZoneDifficulty->IsDebugInfoEnabled) 606 | { 607 | LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Reducing score with type {} from player with guid {} by {}.", type, player->GetGUID().GetCounter(), score); 608 | } 609 | 610 | uint32 val = player->GetPlayerSetting(ModZoneDifficultyString + "score", type).value - score; 611 | player->UpdatePlayerSetting(ModZoneDifficultyString + "score", type, val); 612 | } 613 | 614 | /** 615 | * @brief Send and item to the player using the data from sZoneDifficulty->Rewards. 616 | * 617 | * @param player The recipient of the mail. 618 | * @param data The reward data e.g item entry, etc. 619 | */ 620 | void ZoneDifficulty::SendItem(Player* player, ZoneDifficultyRewardData data) 621 | { 622 | //Check if a full tier cleareance reward is meant (itemType 99) 623 | ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(data.Entry); 624 | 625 | if (!itemTemplate) 626 | { 627 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: itemTemplate could not be constructed in sZoneDifficulty->SendItem for item {}.", data.Entry); 628 | return; 629 | } 630 | 631 | ObjectGuid::LowType senderGuid = player->GetGUID().GetCounter(); 632 | 633 | // fill mail 634 | MailDraft draft(REWARD_MAIL_SUBJECT, REWARD_MAIL_BODY); 635 | MailSender sender(MAIL_NORMAL, senderGuid, MAIL_STATIONERY_GM); 636 | CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); 637 | 638 | if (Item* item = Item::CreateItem(data.Entry, 1, player)) 639 | { 640 | if (data.EnchantSlot != 0 && data.Enchant != 0) 641 | { 642 | item->SetEnchantment(EnchantmentSlot(data.EnchantSlot), data.Enchant, 0, 0, player->GetGUID()); 643 | player->ApplyEnchantment(item, EnchantmentSlot(data.EnchantSlot), true, true, true); 644 | } 645 | item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted 646 | draft.AddItem(item); 647 | } 648 | 649 | draft.SendMailTo(trans, MailReceiver(player, senderGuid), sender); 650 | CharacterDatabase.CommitTransaction(trans); 651 | } 652 | 653 | /** 654 | * @brief Check if the map has assigned any data to tune it. 655 | * 656 | * @param map The ID of the to check. 657 | * @return The result as bool. 658 | */ 659 | bool ZoneDifficulty::IsMythicmodeMap(uint32 mapId) 660 | { 661 | if (!sZoneDifficulty->MythicmodeEnable) 662 | return false; 663 | 664 | if (sZoneDifficulty->MythicmodeLoot.find(mapId) == sZoneDifficulty->MythicmodeLoot.end()) 665 | return false; 666 | 667 | return true; 668 | } 669 | 670 | /** 671 | * @brief Check if the target is a player, a pet or a guardian. 672 | * 673 | * @param target The affected 674 | * @return The result as bool. True for , or . 675 | */ 676 | bool ZoneDifficulty::IsValidNerfTarget(Unit* target) 677 | { 678 | return target->IsPlayer() || target->IsPet() || target->IsGuardian(); 679 | } 680 | 681 | /** 682 | * @brief Checks if the element is one of the uint32 values in the vector. 683 | * 684 | * @param vec A vector 685 | * @param element One element which can potentially be part of the values in the vector 686 | * @return The result as bool 687 | */ 688 | bool ZoneDifficulty::VectorContainsUint32(std::vector vec, uint32 element) 689 | { 690 | return find(vec.begin(), vec.end(), element) != vec.end(); 691 | } 692 | 693 | /** 694 | * @brief Checks if the instance and spelloverride have matching modes 695 | * 696 | * @param instanceId 697 | * @param spellId 698 | * @param mapId 699 | * @return The result as bool 700 | */ 701 | bool ZoneDifficulty::OverrideModeMatches(uint32 instanceId, uint32 spellId, uint32 mapId) 702 | { 703 | if ((sZoneDifficulty->HasMythicmode(sZoneDifficulty->SpellNerfOverrides[spellId][mapId].ModeMask) && sZoneDifficulty->MythicmodeInstanceData[instanceId]) || 704 | (sZoneDifficulty->HasNormalMode(sZoneDifficulty->SpellNerfOverrides[spellId][mapId].ModeMask) && !sZoneDifficulty->MythicmodeInstanceData[instanceId])) 705 | { 706 | return true; 707 | } 708 | else 709 | { 710 | return false; 711 | } 712 | } 713 | 714 | /** 715 | * @brief Checks if the target is in a duel while residing in the DUEL_AREA and their opponent is a valid object. 716 | * Used to determine when the duel-specific nerfs should be applied. 717 | * 718 | * @param target The affected 719 | * @return The result as bool 720 | */ 721 | bool ZoneDifficulty::ShouldNerfInDuels(Unit* target) 722 | { 723 | if (target->GetAreaId() != DUEL_AREA) 724 | return false; 725 | 726 | if (target->ToTempSummon() && target->ToTempSummon()->GetSummoner()) 727 | target = target->ToTempSummon()->GetSummoner()->ToUnit(); 728 | 729 | if (!target->GetAffectingPlayer()) 730 | return false; 731 | 732 | if (!target->GetAffectingPlayer()->duel) 733 | return false; 734 | 735 | if (target->GetAffectingPlayer()->duel->State != DUEL_STATE_IN_PROGRESS) 736 | return false; 737 | 738 | if (!target->GetAffectingPlayer()->duel->Opponent) 739 | return false; 740 | 741 | return true; 742 | } 743 | 744 | /** 745 | * @brief Find the lowest phase for the target's mapId, which has a db entry for the target's map 746 | * and at least partly matches the target's phase. 747 | * 748 | * `mapId` can be the id of a map or `DUEL_INDEX` to use the duel specific settings. 749 | * Return -1 if none found. 750 | * 751 | * @param mapId 752 | * @param phaseMask Bitmask of all phases where the unit is currently visible 753 | * @return the lowest phase which should be altered for this map and the unit is visible in 754 | */ 755 | int32 ZoneDifficulty::GetLowestMatchingPhase(uint32 mapId, uint32 phaseMask) 756 | { 757 | // Check if there is an entry for the mapId at all 758 | if (sZoneDifficulty->ShouldNerfMap(mapId)) 759 | { 760 | 761 | // Check if 0 is assigned as a phase to cover all phases 762 | if (sZoneDifficulty->NerfInfo[mapId].find(0) != sZoneDifficulty->NerfInfo[mapId].end()) 763 | { 764 | return 0; 765 | } 766 | 767 | for (auto const& [key, value] : sZoneDifficulty->NerfInfo[mapId]) 768 | { 769 | if (key & phaseMask) 770 | { 771 | return key; 772 | } 773 | } 774 | } 775 | return -1; 776 | } 777 | 778 | /** 779 | * @brief Store the MythicmodeInstanceData in the database for the given instance id. 780 | * zone_difficulty_instance_saves is used to store the data. 781 | * 782 | * @param InstanceID INT NOT NULL DEFAULT 0, 783 | */ 784 | void ZoneDifficulty::SaveMythicmodeInstanceData(uint32 instanceId) 785 | { 786 | if (sZoneDifficulty->MythicmodeInstanceData.find(instanceId) == sZoneDifficulty->MythicmodeInstanceData.end()) 787 | { 788 | return; 789 | } 790 | CharacterDatabase.Execute("REPLACE INTO zone_difficulty_instance_saves (InstanceID, MythicmodeOn) VALUES ({}, {})", instanceId, sZoneDifficulty->MythicmodeInstanceData[instanceId]); 791 | } 792 | 793 | void ZoneDifficulty::MythicmodeEvent(Unit* unit, uint32 entry, uint32 key) 794 | { 795 | if (unit && unit->IsAlive()) 796 | { 797 | if (!unit->IsInCombat()) 798 | { 799 | unit->m_Events.CancelEventGroup(EVENT_GROUP); 800 | return; 801 | } 802 | 803 | // Try again in 1s if the unit is currently casting 804 | if (unit->HasUnitState(UNIT_STATE_CASTING)) 805 | { 806 | unit->m_Events.AddEventAtOffset([unit, entry, key]() 807 | { 808 | sZoneDifficulty->MythicmodeEvent(unit, entry, key); 809 | }, 1s, EVENT_GROUP); 810 | return; 811 | } 812 | 813 | if (sZoneDifficulty->MythicmodeAI[entry][key].Repetitions == 0) 814 | { 815 | unit->m_Events.AddEventAtOffset([unit, entry, key]() 816 | { 817 | sZoneDifficulty->MythicmodeEvent(unit, entry, key); 818 | }, sZoneDifficulty->MythicmodeAI[entry][key].Cooldown, EVENT_GROUP); 819 | } 820 | 821 | ZoneDifficultyHAI mythicAI = sZoneDifficulty->MythicmodeAI[entry][key]; 822 | bool has_bp0 = mythicAI.Spellbp0; 823 | bool has_bp1 = mythicAI.Spellbp1; 824 | bool has_bp2 = mythicAI.Spellbp2; 825 | 826 | if (mythicAI.Target == TARGET_PLAYER_DISTANCE) 827 | { 828 | auto const& threatlist = unit->GetThreatMgr().GetThreatList(); 829 | 830 | for (auto itr = threatlist.begin(); itr != threatlist.end(); ++itr) 831 | { 832 | Unit* target = (*itr)->getTarget(); 833 | if (!unit->IsWithinDist(target, mythicAI.TargetArg)) 834 | continue; 835 | 836 | std::string targetName = target ? target->GetName() : "NoTarget"; 837 | if (!has_bp0 && !has_bp1 && !has_bp2) 838 | unit->CastSpell(target, mythicAI.Spell, mythicAI.TriggeredCast); 839 | else 840 | { 841 | unit->CastCustomSpell(target, mythicAI.Spell, 842 | has_bp0 ? &mythicAI.Spellbp0 : NULL, 843 | has_bp1 ? &mythicAI.Spellbp1 : NULL, 844 | has_bp2 ? &mythicAI.Spellbp2 : NULL, 845 | mythicAI.TriggeredCast); 846 | } 847 | } 848 | return; 849 | } 850 | 851 | // Select target 852 | Unit* target = nullptr; 853 | if (mythicAI.Target == TARGET_SELF) 854 | target = unit; 855 | else if (mythicAI.Target == TARGET_VICTIM) 856 | target = unit->GetVictim(); 857 | else 858 | { 859 | switch (mythicAI.Target) 860 | { 861 | case TARGET_HOSTILE_AGGRO_FROM_TOP: 862 | { 863 | float range = 200.0f; 864 | if (mythicAI.TargetArg > 0) 865 | range = mythicAI.TargetArg; 866 | 867 | target = unit->GetAI()->SelectTarget(SelectTargetMethod::MaxThreat, mythicAI.TargetArg2, range, true); 868 | 869 | if (!target) 870 | target = unit->GetVictim(); 871 | 872 | break; 873 | } 874 | case TARGET_HOSTILE_AGGRO_FROM_BOTTOM: 875 | { 876 | float range = 200.0f; 877 | if (mythicAI.TargetArg2 > 0) 878 | range = mythicAI.TargetArg2; 879 | 880 | target = unit->GetAI()->SelectTarget(SelectTargetMethod::MinThreat, mythicAI.TargetArg, range, true); 881 | 882 | if (!target) 883 | target = unit->GetVictim(); 884 | 885 | break; 886 | } 887 | case TARGET_HOSTILE_RANDOM: 888 | { 889 | target = unit->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, mythicAI.TargetArg, true); 890 | break; 891 | } 892 | case TARGET_HOSTILE_RANDOM_NOT_TOP: 893 | { 894 | target = unit->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, mythicAI.TargetArg, true, false); 895 | break; 896 | } 897 | default: 898 | { 899 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Unknown type for Target: {} in zone_difficulty_mythicmode_ai", mythicAI.Target); 900 | } 901 | } 902 | } 903 | 904 | if (!target && mythicAI.Target != TARGET_NONE) 905 | { 906 | Unit* victim = nullptr; 907 | if (mythicAI.TargetArg > 0) 908 | { 909 | if (unit->IsInRange(victim, 0, mythicAI.TargetArg, true)) 910 | target = victim; 911 | } 912 | else if (mythicAI.TargetArg < 0) 913 | { 914 | if (unit->IsInRange(victim, mythicAI.TargetArg, 0, true)) 915 | target = victim; 916 | } 917 | 918 | } 919 | 920 | if (target || mythicAI.Target == TARGET_NONE) 921 | { 922 | std::string targetName = target ? target->GetName() : "NoTarget"; 923 | 924 | if (!has_bp0 && !has_bp1 && !has_bp2) 925 | { 926 | unit->CastSpell(target, mythicAI.Spell, mythicAI.TriggeredCast); 927 | } 928 | else 929 | { 930 | unit->CastCustomSpell(target, mythicAI.Spell, 931 | has_bp0 ? &mythicAI.Spellbp0 : NULL, 932 | has_bp1 ? &mythicAI.Spellbp1 : NULL, 933 | has_bp2 ? &mythicAI.Spellbp2 : NULL, 934 | mythicAI.TriggeredCast); 935 | } 936 | } 937 | else 938 | { 939 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: No target could be found for unit with entry {} and harmodeAI key {}.", entry, key); 940 | } 941 | } 942 | } 943 | 944 | bool ZoneDifficulty::HasCompletedFullTier(uint32 category, uint32 playerGuid) 945 | { 946 | std::vector MapList; 947 | switch (category) 948 | { 949 | case TYPE_HEROIC_TBC: 950 | //585 is Magister's Terrace. Only add when released. 951 | MapList = { 269, 540, 542, 543, 545, 547, 546, 552, 553, 554, 555, 556, 557, 558, 560/*, 585*/ }; 952 | break; 953 | case TYPE_RAID_T4: 954 | MapList = { 532, 544, 565}; 955 | break; 956 | case TYPE_RAID_T6: 957 | MapList = { 564 }; 958 | break; 959 | case TYPE_RAID_ZA: 960 | MapList = { 568 }; 961 | break; 962 | case TYPE_RAID_SSC: 963 | MapList = { 548 }; 964 | break; 965 | case TYPE_RAID_HYJAL: 966 | MapList = { 534 }; 967 | break; 968 | case TYPE_RAID_SWP: 969 | MapList = { 580 }; 970 | break; 971 | default: 972 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Category without data requested in ZoneDifficulty::HasCompletedFullTier {}", category); 973 | return false; 974 | break; 975 | } 976 | 977 | for (uint32 mapId : MapList) 978 | { 979 | if (sZoneDifficulty->EncounterCounter.find(mapId) == sZoneDifficulty->EncounterCounter.end()) 980 | { 981 | LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Map without data requested in ZoneDifficulty::HasCompletedFullTier {}", mapId); 982 | return false; 983 | } 984 | for (uint8 i = 0; i < sZoneDifficulty->EncounterCounter[mapId]; ++i) 985 | { 986 | if (!sZoneDifficulty->Logs[playerGuid][mapId][i]) 987 | return false; 988 | } 989 | } 990 | return true; 991 | } 992 | 993 | void ZoneDifficulty::RewardItem(Player* player, uint8 category, uint8 itemType, uint8 counter, Creature* creature, uint32 itemEntry) 994 | { 995 | if (!sZoneDifficulty->CheckCompletionStatus(creature, player, category)) 996 | return; 997 | 998 | uint32 availableScore = player->GetPlayerSetting(ModZoneDifficultyString + "score", category).value; 999 | 1000 | auto reward = sZoneDifficulty->Rewards[category][itemType][counter]; 1001 | 1002 | if (itemEntry) 1003 | { 1004 | for (auto const& item : sZoneDifficulty->Rewards[category][itemType]) 1005 | { 1006 | if (item.Entry == itemEntry) 1007 | reward = item; 1008 | } 1009 | } 1010 | 1011 | if (availableScore < reward.Price) 1012 | { 1013 | if (player->GetSession()) 1014 | player->GetSession()->SendAreaTriggerMessage("Not enough points."); 1015 | 1016 | return; 1017 | } 1018 | 1019 | if (reward.Achievement) 1020 | { 1021 | if (!player->HasAchieved(reward.Achievement)) 1022 | { 1023 | std::string gossip = "You do not have the required achievement with ID "; 1024 | gossip.append(std::to_string(reward.Achievement)); 1025 | gossip.append(" to receive this item. Before i can give it to you, you need to complete the whole dungeon where it can be obtained."); 1026 | creature->Whisper(gossip, LANG_UNIVERSAL, player); 1027 | CloseGossipMenuFor(player); 1028 | return; 1029 | } 1030 | } 1031 | 1032 | sZoneDifficulty->DeductMythicmodeScore(player, category, reward.Price); 1033 | sZoneDifficulty->SendItem(player, reward); 1034 | 1035 | if (player->GetSession()) 1036 | if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(reward.Entry)) 1037 | player->GetSession()->SendAreaTriggerMessage("You were rewarded %s for %u points.", proto->Name1.c_str(), reward.Price); 1038 | }; 1039 | 1040 | void ZoneDifficulty::LogAndAnnounceKill(Map* map, bool isMythic) 1041 | { 1042 | if (map->GetId() == 564) 1043 | { 1044 | if (sZoneDifficulty->IsBlackTempleDone) 1045 | return; 1046 | 1047 | sZoneDifficulty->IsBlackTempleDone = true; 1048 | 1049 | ChatHandler(nullptr).SendWorldText("Congrats on conquering Black Temple ({}) and defeating Illidan Stormrage! Well done, champions!", isMythic ? "Mythic" : "Normal"); 1050 | 1051 | std::string names = "Realm first group: "; 1052 | 1053 | map->DoForAllPlayers([&](Player* mapPlayer) { 1054 | if (!mapPlayer->IsGameMaster()) 1055 | { 1056 | names.append(mapPlayer->GetName() + ", "); 1057 | CharacterDatabase.Execute("INSERT INTO zone_difficulty_completion_logs (guid, type, mode) VALUES ({}, {}, {})", mapPlayer->GetGUID().GetCounter(), TYPE_RAID_T6, 1); 1058 | } 1059 | }); 1060 | 1061 | ChatHandler(nullptr).SendWorldText(names.c_str()); 1062 | } else if (map->GetId() == 580) 1063 | { 1064 | if (sZoneDifficulty->IsSunwellPlateauDone) 1065 | return; 1066 | 1067 | sZoneDifficulty->IsSunwellPlateauDone = true; 1068 | 1069 | ChatHandler(nullptr).SendWorldText("Congrats on conquering Sunwell Plateau ({}) and defeating Kil'jaeden! Well done, champions!", isMythic ? "Mythic" : "Normal"); 1070 | 1071 | std::string names = "Realm first group: "; 1072 | 1073 | map->DoForAllPlayers([&](Player* mapPlayer) { 1074 | if (!mapPlayer->IsGameMaster()) 1075 | { 1076 | names.append(mapPlayer->GetName() + ", "); 1077 | CharacterDatabase.Execute("INSERT INTO zone_difficulty_completion_logs (guid, type, mode) VALUES ({}, {}, {})", mapPlayer->GetGUID().GetCounter(), TYPE_RAID_SWP, 1); 1078 | } 1079 | }); 1080 | 1081 | ChatHandler(nullptr).SendWorldText(names.c_str()); 1082 | } 1083 | }; 1084 | 1085 | bool ZoneDifficulty::CheckCompletionStatus(Creature* creature, Player* player, uint32 category) const 1086 | { 1087 | struct MythicRequirement 1088 | { 1089 | uint32 category; 1090 | uint32 setting; 1091 | char const* bossName; 1092 | }; 1093 | 1094 | static constexpr std::array requirements 1095 | { 1096 | MythicRequirement{ TYPE_RAID_SSC, SETTING_SSC, "Lady Vashj" }, 1097 | MythicRequirement{ TYPE_RAID_T6, SETTING_BLACK_TEMPLE, "Illidan Stormrage" }, 1098 | MythicRequirement{ TYPE_RAID_ZA, SETTING_ZULAMAN, "Zul'jin" }, 1099 | MythicRequirement{ TYPE_RAID_HYJAL, SETTING_HYJAL, "Archimonde" }, 1100 | MythicRequirement{ TYPE_RAID_SWP, SETTING_SWP, "Kil'jaeden" }, 1101 | }; 1102 | 1103 | for (auto const& req : requirements) 1104 | { 1105 | if (req.category != category) 1106 | continue; 1107 | 1108 | if (player->GetPlayerSetting(ModZoneDifficultyString + "ct", req.setting).value) 1109 | return true; 1110 | 1111 | creature->Whisper( 1112 | Acore::StringFormat("Ah, hero! The threads of fate bring you to me. To claim the rewards you desire, you must first confront {} on Mythic difficulty.", req.bossName), 1113 | LANG_UNIVERSAL, player); 1114 | return false; 1115 | } 1116 | 1117 | return true; 1118 | } 1119 | 1120 | void ZoneDifficulty::ProcessCreatureDeath(Map* map, uint32 entry) 1121 | { 1122 | constexpr std::array>, 5> deathData = 1123 | { 1124 | std::pair{ NPC_ILLIDAN_STORMRAGE, std::tuple{ SETTING_BLACK_TEMPLE, "Black Temple" } }, 1125 | std::pair{ NPC_ZULJIN, std::tuple{ SETTING_ZULAMAN, "Zul'Aman" } }, 1126 | std::pair{ NPC_ARCHIMONDE, std::tuple{ SETTING_HYJAL, "Battle for Mount Hyjal" } }, 1127 | std::pair{ NPC_LADY_VASHJ, std::tuple{ SETTING_SSC, "Serpentshrine Cavern" } }, 1128 | std::pair{ NPC_KILJAEDEN, std::tuple{ SETTING_SWP, "Sunwell Plateau" } } 1129 | }; 1130 | 1131 | for (auto const& [npcId, data] : deathData) 1132 | { 1133 | if (npcId != entry) 1134 | continue; 1135 | 1136 | uint32 setting; 1137 | const char* zoneName; 1138 | std::tie(setting, zoneName) = data; 1139 | 1140 | map->DoForAllPlayers([setting, zoneName](Player* player) 1141 | { 1142 | player->UpdatePlayerSetting(ModZoneDifficultyString + "ct", setting, 1); 1143 | player->SendSystemMessage(Acore::StringFormat("Congratulations on completing {}!", zoneName)); 1144 | }); 1145 | 1146 | sZoneDifficulty->LogAndAnnounceKill(map, true); 1147 | break; 1148 | } 1149 | } 1150 | --------------------------------------------------------------------------------