diff options
23 files changed, 274 insertions, 88 deletions
diff --git a/apps/installer/includes/functions.sh b/apps/installer/includes/functions.sh index 3c9b2edba2..79fbb355d9 100644 --- a/apps/installer/includes/functions.sh +++ b/apps/installer/includes/functions.sh @@ -155,7 +155,7 @@ function inst_simple_restarter { function inst_download_client_data { # change the following version when needed - local VERSION=v18.0 + local VERSION=v19 echo "#######################" echo "Client data downloader" diff --git a/data/sql/updates/pending_db_world/rev_1764203353826128556.sql b/data/sql/updates/db_world/2025_12_01_05.sql index d0c3ed0532..81ce9a5adb 100644 --- a/data/sql/updates/pending_db_world/rev_1764203353826128556.sql +++ b/data/sql/updates/db_world/2025_12_01_05.sql @@ -1,3 +1,4 @@ +-- DB update 2025_12_01_04 -> 2025_12_01_05 -- -- Wolfsbane Root (189313) - Despawn on use via SmartAI -- Closes https://github.com/azerothcore/azerothcore-wotlk/issues/23904 diff --git a/data/sql/updates/db_world/2025_12_02_00.sql b/data/sql/updates/db_world/2025_12_02_00.sql new file mode 100644 index 0000000000..ca9e7aea3a --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_00.sql @@ -0,0 +1,4 @@ +-- DB update 2025_12_01_05 -> 2025_12_02_00 + +-- Remove double spawn point +DELETE FROM `creature` WHERE (`id1` = 32250) AND (`guid` IN (125031)); diff --git a/data/sql/updates/db_world/2025_12_02_01.sql b/data/sql/updates/db_world/2025_12_02_01.sql new file mode 100644 index 0000000000..63705b3fcf --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_01.sql @@ -0,0 +1,38 @@ +-- DB update 2025_12_02_00 -> 2025_12_02_01 +-- +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 29796) AND (`source_type` = 0) AND (`id` IN (0)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(29796, 0, 0, 0, 19, 0, 100, 0, 12886, 0, 0, 0, 0, 0, 11, 55253, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Gretta the Arbiter - On Quest \'The Drakkensryd\' Taken - Cast \'Force Cast Initial Proto-Drake\''); + +UPDATE `creature_template` SET `speed_run` = 3.2 WHERE (`entry` = 29679); + +-- 55971 Eagle Flight +UPDATE `creature_template_addon` SET `auras` = '55971' WHERE (`entry` = 29679); + +-- Update comments, Exit vehicle on death +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 29694) AND (`source_type` = 0) AND (`id` IN (0, 1, 2)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(29694, 0, 0, 0, 0, 0, 100, 0, 2000, 5000, 5000, 9000, 0, 0, 11, 32736, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Drakerider - In Combat - Cast \'Mortal Strike\''), +(29694, 0, 1, 2, 6, 0, 100, 512, 0, 0, 0, 0, 0, 0, 33, 29800, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Drakerider - On Just Died - Quest Credit \'null\''), +(29694, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Drakerider - On Just Died - Exit vehicle'); + +-- Hyldsmeet Drakerider eject NPC passenger vertically +DELETE FROM `vehicle_seat_addon` WHERE (`SeatEntry` = 2101); +INSERT INTO `vehicle_seat_addon` (`SeatEntry`, `SeatOrientation`, `ExitParamX`, `ExitParamY`, `ExitParamZ`, `ExitParamO`, `ExitParamValue`) VALUES +(2101, 0, 0, 0, 4, 0, 1); + +-- Update Comments, Reduce despawn time from 2s to 1s +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 29679) AND (`source_type` = 0) AND (`id` IN (0, 1, 2)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(29679, 0, 0, 0, 60, 0, 100, 513, 1000, 1000, 0, 0, 0, 0, 53, 2, 29679, 0, 0, 1000, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Proto-Drake - On Update - Start Waypoint Path 29679 (No Repeat)'), +(29679, 0, 1, 0, 60, 0, 100, 513, 500, 500, 0, 0, 0, 0, 60, 1, 500, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Proto-Drake - On Update - Set Fly On (No Repeat)'), +(29679, 0, 2, 0, 28, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 1000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Proto-Drake - On Passenger Removed - Despawn In 1000 ms'); + +DELETE FROM `spell_area` WHERE `spell` IN (55012, 72914) AND `area` IN (4430, 4431, 4432) AND `quest_start` = 12886; +INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES +(55012, 4430, 12886, 0, 0, 0, 2, 1, 10, 0), +(55012, 4431, 12886, 0, 0, 0, 2, 1, 10, 0), +(55012, 4432, 12886, 0, 0, 0, 2, 1, 10, 0), +(72914, 4430, 12886, 0, 0, 0, 2, 1, 10, 0), +(72914, 4431, 12886, 0, 0, 0, 2, 1, 10, 0), +(72914, 4432, 12886, 0, 0, 0, 2, 1, 10, 0); diff --git a/data/sql/updates/db_world/2025_12_02_02.sql b/data/sql/updates/db_world/2025_12_02_02.sql new file mode 100644 index 0000000000..e2f4488bda --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_02.sql @@ -0,0 +1,66 @@ +-- DB update 2025_12_02_01 -> 2025_12_02_02 +-- Makes all Everfrost Chips spawns 45 minutes (before 30 and 1 hour). +UPDATE `gameobject` SET `spawntimesecs` = 2700 WHERE `id` = 193997; + +DELETE FROM `pool_template` WHERE `entry` IN (150, 151, 152); +INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES +(150, 8, "Everfrost Chip - Valley of Ancient Winters"), -- Total 30 / 4 = 7.5 rounded to 8 +(151, 4, "Everfrost Chip - Frostfield Lake"), -- Total 16 / 4 = 4 +(152, 2, "Everfrost Chip - Dun Niffelem"); -- Total 08 / 4 = 2 + +DELETE FROM `pool_gameobject` WHERE `pool_entry` IN (150, 151, 152) AND `guid` IN (221000, 221002, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 221001); +INSERT INTO `pool_gameobject` (`guid`, `pool_entry`, `chance`, `description`) VALUES +(3728, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3751, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3761, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3721, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3734, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3755, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3724, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1170, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3732, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3723, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3729, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3746, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3752, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1161, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3722, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3756, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3731, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1162, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1163, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3737, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3730, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3726, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3727, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(1169, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3736, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(221002, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3749, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(221000, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3743, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3725, 150, 0, "Everfrost Chip - Valley of Ancient Winters"), +(3759, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3733, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3753, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3758, 151, 0, "Everfrost Chip - Frostfield Lake"), +(221001, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3735, 151, 0, "Everfrost Chip - Frostfield Lake"), +(1168, 151, 0, "Everfrost Chip - Frostfield Lake"), +(1167, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3760, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3745, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3741, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3744, 151, 0, "Everfrost Chip - Frostfield Lake"), +(1166, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3739, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3757, 151, 0, "Everfrost Chip - Frostfield Lake"), +(3748, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3740, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3738, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3750, 152, 0, "Everfrost Chip - Dun Niffelem"), +(1164, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3747, 152, 0, "Everfrost Chip - Dun Niffelem"), +(1165, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3742, 152, 0, "Everfrost Chip - Dun Niffelem"), +(3754, 152, 0, "Everfrost Chip - Dun Niffelem"); diff --git a/data/sql/updates/db_world/2025_12_02_03.sql b/data/sql/updates/db_world/2025_12_02_03.sql new file mode 100644 index 0000000000..7dc7171969 --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_03.sql @@ -0,0 +1,3 @@ +-- DB update 2025_12_02_02 -> 2025_12_02_03 +-- From: "from that $r" to "from that troll" as refers to the troll (Drakkari prisoner) and not the player's race. +UPDATE `quest_offer_reward` SET `RewardText` = 'You\'ve done it!$B$BThe intelligence gathered from that troll will undoubtedly be of great value. I\'ll be certain to make mention of your efforts in my report to the commander.$B$BThank you, $N.' WHERE `ID` = 12541; diff --git a/data/sql/updates/db_world/2025_12_02_04.sql b/data/sql/updates/db_world/2025_12_02_04.sql new file mode 100644 index 0000000000..d4388331db --- /dev/null +++ b/data/sql/updates/db_world/2025_12_02_04.sql @@ -0,0 +1,23 @@ +-- DB update 2025_12_02_03 -> 2025_12_02_04 +-- Seething Revenant (30387) - Add missing loot +-- Closes https://github.com/azerothcore/azerothcore-wotlk/issues/23807 + +UPDATE `creature_loot_template` SET `Chance` = 0.04 WHERE `Entry` = 30387 AND `Item` = 45912; + +DELETE FROM `creature_loot_template` WHERE `Entry` = 30387 AND `Item` IN (39512, 42780, 37702, 39513, 43624, 42173, 42175, 26001, 26002, 26013, 26014, 26015, 26027, 26028, 35074); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(30387, 39512, 0, 56, 0, 1, 0, 1, 1, 'Seething Revenant - Hoary Crystals'), +(30387, 42780, 0, 26, 0, 1, 0, 1, 1, 'Seething Revenant - Relic of Ulduar'), +(30387, 37702, 0, 19, 0, 1, 0, 1, 2, 'Seething Revenant - Crystallized Fire'), +(30387, 39513, 0, 14, 0, 1, 0, 1, 1, 'Seething Revenant - Efflorescing Shards'), +(30387, 43624, 0, 0.01, 0, 1, 0, 1, 1, 'Seething Revenant - Titanium Lockbox'), +(30387, 42173, 0, 0.005, 0, 1, 0, 1, 1, 'Seething Revenant - Pattern: Blue Lumberjack Shirt'), +(30387, 42175, 0, 0.005, 0, 1, 0, 1, 1, 'Seething Revenant - Pattern: Green Lumberjack Shirt'), +(30387, 26001, 26001, 3, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26002, 26002, 3, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26013, 26013, 1, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26014, 26014, 1, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26015, 26015, 1, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26027, 26027, 0.5, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 26028, 26028, 0.5, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'), +(30387, 35074, 35074, 0.1, 0, 1, 1, 1, 1, 'Seething Revenant - (ReferenceTable)'); diff --git a/data/sql/updates/db_world/2025_12_04_00.sql b/data/sql/updates/db_world/2025_12_04_00.sql new file mode 100644 index 0000000000..a57036c8ae --- /dev/null +++ b/data/sql/updates/db_world/2025_12_04_00.sql @@ -0,0 +1,4 @@ +-- DB update 2025_12_02_04 -> 2025_12_04_00 + +UPDATE `creature_template` SET `exp` = 2 WHERE (`entry` = 32263); +UPDATE `creature` SET `curhealth` = 10080 WHERE (`id1` = 32263) AND `guid` = 85056; diff --git a/src/common/Collision/Maps/MapDefines.h b/src/common/Collision/Maps/MapDefines.h index d928c51721..a3527f16c2 100644 --- a/src/common/Collision/Maps/MapDefines.h +++ b/src/common/Collision/Maps/MapDefines.h @@ -26,7 +26,7 @@ #define SIZE_OF_GRIDS 533.3333f #define MMAP_MAGIC 0x4d4d4150 // 'MMAP' -#define MMAP_VERSION 18 +#define MMAP_VERSION 19 struct MmapTileRecastConfig { diff --git a/src/common/Collision/VMapDefinitions.h b/src/common/Collision/VMapDefinitions.h index 623dea5020..b8026d9496 100644 --- a/src/common/Collision/VMapDefinitions.h +++ b/src/common/Collision/VMapDefinitions.h @@ -22,8 +22,8 @@ namespace VMAP { - const char VMAP_MAGIC[] = "VMAP_4.7"; - const char RAW_VMAP_MAGIC[] = "VMAP047"; // used in extracted vmap files with raw data + const char VMAP_MAGIC[] = "VMAP_4.8"; + const char RAW_VMAP_MAGIC[] = "VMAP048"; // used in extracted vmap files with raw data const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree"; // defined in TileAssembler.cpp currently... diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index f888403491..3c952a42d9 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -858,7 +858,7 @@ void SmartAI::AttackStart(Unit* who) return; } - if (who && me->Attack(who, me->IsWithinMeleeRange(who))) + if (who && me->Attack(who, me->IsWithinMeleeRange(who) || _currentRangeMode)) { if (!me->HasUnitState(UNIT_STATE_NO_COMBAT_MOVEMENT)) { @@ -870,7 +870,7 @@ void SmartAI::AttackStart(Unit* who) me->GetMotionMaster()->Clear(false); } - me->GetMotionMaster()->MoveChase(who); + me->GetMotionMaster()->MoveChase(who, _attackDistance); } } } @@ -941,6 +941,35 @@ void SmartAI::PassengerBoarded(Unit* who, int8 seatId, bool apply) void SmartAI::InitializeAI() { GetScript()->OnInitialize(me); + + for (SmartScriptHolder const& event : GetScript()->GetEvents()) + { + if (event.GetActionType() != SMART_ACTION_CAST) + continue; + + if (!(event.action.cast.castFlags & SMARTCAST_MAIN_SPELL)) + continue; + + SetMainSpell(event.action.cast.spell); + break; + } + + // Fallback: use first SMARTCAST_COMBAT_MOVE if no MAIN_SPELL found + if (!_currentRangeMode) + { + for (SmartScriptHolder const& event : GetScript()->GetEvents()) + { + if (event.GetActionType() != SMART_ACTION_CAST) + continue; + + if (!(event.action.cast.castFlags & SMARTCAST_COMBAT_MOVE)) + continue; + + SetMainSpell(event.action.cast.spell); + break; + } + } + if (!me->isDead()) { mJustReset = true; @@ -1083,6 +1112,20 @@ void SmartAI::SetCurrentRangeMode(bool on, float range) me->GetMotionMaster()->MoveChase(victim, _attackDistance); } +void SmartAI::SetMainSpell(uint32 spellId) +{ + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo) + return; + + float maxRange = spellInfo->GetMaxRange(false); + if (maxRange <= NOMINAL_MELEE_RANGE) + return; + + _attackDistance = std::max(maxRange - NOMINAL_MELEE_RANGE, 0.0f); + _currentRangeMode = true; +} + void SmartAI::DistanceYourself(float range) { Unit* victim = me->GetVictim(); diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index d6b957cc00..0876336458 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -67,6 +67,7 @@ public: void SetAutoAttack(bool on) { mCanAutoAttack = on; } void SetCombatMovement(bool on, bool stopOrStartMovement); void SetCurrentRangeMode(bool on, float range = 0.f); + void SetMainSpell(uint32 spellId); void DistanceYourself(float range); void SetFollow(Unit* target, float dist = 0.0f, float angle = 0.0f, uint32 credit = 0, uint32 end = 0, uint32 creditType = 0, bool aliveState = true); void StopFollow(bool complete); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index e7a5c4fd84..2f66b4ac11 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -707,7 +707,6 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u continue; } - // Let us not try to cast spell if we know it is going to fail anyway. Stick to chasing and continue. if (distanceToTarget > spellMaxRange && isWithinLOSInMap) { failedSpellCast = true; @@ -745,12 +744,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.action.cast.castFlags & SMARTCAST_COMBAT_MOVE) { - // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed unless target is outside spell range, out of mana, or LOS. - if (result == SPELL_FAILED_OUT_OF_RANGE || result == SPELL_CAST_OK) - // if we are just out of range, we only chase until we are back in spell range. + if (result == SPELL_FAILED_OUT_OF_RANGE) CAST_AI(SmartAI, me->AI())->SetCurrentRangeMode(true, std::max(spellMaxRange - NOMINAL_MELEE_RANGE, 0.0f)); - else // move into melee on any other fail - // if spell fail for any other reason, we chase to melee range, or stay where we are if spellcast was successful. + else if (result != SPELL_CAST_OK) CAST_AI(SmartAI, me->AI())->SetCurrentRangeMode(false, 0.f); } diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index e0f32438c8..250fdd775a 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -207,6 +207,8 @@ public: void AddCreatureSummon(ObjectGuid const& guid); void RemoveCreatureSummon(ObjectGuid const& guid); + SmartAIEventList const& GetEvents() const { return mEvents; } + private: void IncPhase(uint32 p); void DecPhase(uint32 p); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 5e8e5e9e0c..8dd177dfa6 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1932,16 +1932,17 @@ enum SmartEventFlags enum SmartCastFlags { - SMARTCAST_INTERRUPT_PREVIOUS = 0x001, // Interrupt any spell casting - SMARTCAST_TRIGGERED = 0x002, // Triggered (this makes spell cost zero mana and have no cast time) - //CAST_FORCE_CAST = 0x004, // Forces cast even if creature is out of mana or out of range - //CAST_NO_MELEE_IF_OOM = 0x008, // Prevents creature from entering melee if out of mana or out of range - //CAST_FORCE_TARGET_SELF = 0x010, // Forces the target to cast this spell on itself - SMARTCAST_AURA_NOT_PRESENT = 0x020, // Only casts the spell if the target does not have an aura from the spell - SMARTCAST_COMBAT_MOVE = 0x040, // Prevents combat movement if cast successful. Allows movement on range, OOM, LOS - SMARTCAST_THREATLIST_NOT_SINGLE = 0x080, // Only cast if the source's threatlist is higher than one. This includes pets (see Skeram's True Fulfillment) - SMARTCAST_TARGET_POWER_MANA = 0x100, // Only cast if the target has power type mana (e.g. Mana Drain) - SMARTCAST_ENABLE_COMBAT_MOVE_ON_LOS = 0x200, + SMARTCAST_INTERRUPT_PREVIOUS = 0x001, // Interrupt any spell casting + SMARTCAST_TRIGGERED = 0x002, // Triggered (this makes spell cost zero mana and have no cast time) + //CAST_FORCE_CAST = 0x004, // Forces cast even if creature is out of mana or out of range + //CAST_NO_MELEE_IF_OOM = 0x008, // Prevents creature from entering melee if out of mana or out of range + //CAST_FORCE_TARGET_SELF = 0x010, // Forces the target to cast this spell on itself + SMARTCAST_AURA_NOT_PRESENT = 0x020, // Only casts the spell if the target does not have an aura from the spell + SMARTCAST_COMBAT_MOVE = 0x040, // Prevents combat movement if cast successful. Allows movement on range, OOM, LOS + SMARTCAST_THREATLIST_NOT_SINGLE = 0x080, // Only cast if the source's threatlist is higher than one. This includes pets (see Skeram's True Fulfillment) + SMARTCAST_TARGET_POWER_MANA = 0x100, // Only cast if the target has power type mana (e.g. Mana Drain) + SMARTCAST_ENABLE_COMBAT_MOVE_ON_LOS = 0x200, // Allows combat movement when not in line of sight + SMARTCAST_MAIN_SPELL = 0x400, // Sets this spell's max range as the creature's chase distance on spawn }; enum SmartFollowType diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index b88d04c65e..b48138a8ba 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -688,7 +688,7 @@ namespace lfg // xinef: dont check compatibile dungeons for already running group (bind problems) if (!isContinue) { - GetCompatibleDungeons(dungeons, players, joinData.lockmap); + GetCompatibleDungeons(dungeons, players, joinData.lockmap, rDungeonId); if (dungeons.empty()) joinData.result = grp ? LFG_JOIN_PARTY_NOT_MEET_REQS : LFG_JOIN_NOT_MEET_REQS; } @@ -1485,7 +1485,7 @@ namespace lfg @param[in] players Set of players to check their dungeon restrictions @param[out] lockMap Map of players Lock status info of given dungeons (Empty if dungeons is not empty) */ - void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap) + void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap, bool isRDF) { lockMap.clear(); for (LfgGuidSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it) @@ -1496,6 +1496,9 @@ namespace lfg { uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids + if (it2->second == LFG_LOCKSTATUS_RAID_LOCKED && isRDF) + continue; + LfgDungeonSet::iterator itDungeon = dungeons.find(dungeonId); if (itDungeon != dungeons.end()) { @@ -1762,10 +1765,8 @@ namespace lfg else { // RDF removes all binds to that map - if (randomDungeon && !sInstanceSaveMgr->PlayerIsPermBoundToInstance(player->GetGUID(), dungeon->map, player->GetDungeonDifficulty())) - { + if (randomDungeon) sInstanceSaveMgr->PlayerUnbindInstance(player->GetGUID(), dungeon->map, player->GetDungeonDifficulty(), true); - } } playersTeleported.push_back(player); diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 426f0c679a..e52bbda7dd 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -589,7 +589,7 @@ namespace lfg void DecreaseKicksLeft(ObjectGuid guid); void SetState(ObjectGuid guid, LfgState state); void SetCanOverrideRBState(ObjectGuid guid, bool val); - void GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap); + void GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap, bool isRDF = false); void _SaveToDB(ObjectGuid guid); LFGDungeonData const* GetLFGDungeon(uint32 id); diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index 5c208f1187..836469a3e8 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -915,72 +915,40 @@ public: } }; -class npc_hyldsmeet_protodrake : public CreatureScript +enum HyldsmeetProtoDrake { - enum NPCs - { - NPC_HYLDSMEET_DRAKERIDER = 29694 - }; + NPC_HYLDSMEET_DRAKERIDER = 29694 +}; -public: - npc_hyldsmeet_protodrake() : CreatureScript("npc_hyldsmeet_protodrake") { } +struct npc_hyldsmeet_protodrake : public CreatureAI +{ + explicit npc_hyldsmeet_protodrake(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0) { } - class npc_hyldsmeet_protodrakeAI : public CreatureAI + void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override { - public: - npc_hyldsmeet_protodrakeAI(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0), _vehicleKit(creature->GetVehicleKit()) { } - - void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override - { - if (apply) - { - class DelayedTransportPositionOffsets : public BasicEvent - { - public: - DelayedTransportPositionOffsets(Unit* owner) : _owner(owner) { } - - bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override - { - _owner->m_movementInfo.transport.pos.Relocate(-3.5f, 0.f, -0.2f, 0.f); - return true; - } - - private: - Unit* _owner; - }; - - if (who->IsPlayer()) - who->m_Events.AddEventAtOffset(new DelayedTransportPositionOffsets(who), 500ms); - - return; - } + if (apply) + return; - if (who->GetEntry() == NPC_HYLDSMEET_DRAKERIDER) - _accessoryRespawnTimer = 5 * MINUTE * IN_MILLISECONDS; - } + if (who->GetEntry() == NPC_HYLDSMEET_DRAKERIDER) + _accessoryRespawnTimer = 5 * MINUTE * IN_MILLISECONDS; + } - void UpdateAI(uint32 diff) override + void UpdateAI(uint32 diff) override + { + //! We need to manually reinstall accessories because the vehicle itself is friendly to players, + //! so EnterEvadeMode is never triggered. The accessory on the other hand is hostile and killable. + Vehicle* vehicleKit = me->GetVehicleKit(); + if (_accessoryRespawnTimer && _accessoryRespawnTimer <= diff && vehicleKit) { - //! We need to manually reinstall accessories because the vehicle itself is friendly to players, - //! so EnterEvadeMode is never triggered. The accessory on the other hand is hostile and killable. - if (_accessoryRespawnTimer && _accessoryRespawnTimer <= diff && _vehicleKit) - { - _vehicleKit->InstallAllAccessories(true); - _accessoryRespawnTimer = 0; - } - else - _accessoryRespawnTimer -= diff; + vehicleKit->InstallAllAccessories(true); + _accessoryRespawnTimer = 0; } - - private: - uint32 _accessoryRespawnTimer; - Vehicle* _vehicleKit; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_hyldsmeet_protodrakeAI(creature); + else + _accessoryRespawnTimer -= diff; } + +private: + uint32 _accessoryRespawnTimer; }; enum CloseRift @@ -1215,7 +1183,7 @@ void AddSC_storm_peaks() new npc_brunnhildar_prisoner(); new npc_freed_protodrake(); new npc_icefang(); - new npc_hyldsmeet_protodrake(); + RegisterCreatureAI(npc_hyldsmeet_protodrake); RegisterSpellScript(spell_close_rift_aura); new npc_vehicle_d16_propelled_delivery(); RegisterSpellScript(spell_q12823_remove_collapsing_cave_aura); diff --git a/src/tools/mmaps_generator/mmaps-config.yaml b/src/tools/mmaps_generator/mmaps-config.yaml index 2a0aba1fc9..7adcee64cf 100644 --- a/src/tools/mmaps_generator/mmaps-config.yaml +++ b/src/tools/mmaps_generator/mmaps-config.yaml @@ -119,6 +119,11 @@ mmapsConfig: # https://github.com/azerothcore/azerothcore-wotlk/pull/22462#issuecomment-3067024680 walkableSlopeAngle: 45 + "530": # Outland + tilesOverrides: + "32,30": # Dark portal + walkableSlopeAngle: 45 # https://github.com/chromiecraft/chromiecraft/issues/8404#issuecomment-3476012660 + # debugOutput generates debug files in the `meshes` directory for use with RecastDemo. # This is useful for inspecting and debugging mmap generation visually. # diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 3b6e5a5be4..52f4983f8d 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -144,6 +144,7 @@ bool ExtractSingleWmo(std::string& fname) WMODoodadData& doodads = WmoDoodads[plain_name]; std::swap(doodads, froot.DoodadData); int Wmo_nVertices = 0; + uint32 groupCount = 0; //printf("root has %d groups\n", froot->nGroups); if (froot.nGroups != 0) { @@ -170,7 +171,11 @@ bool ExtractSingleWmo(std::string& fname) break; } + if (fgroup.ShouldSkip(&froot)) + continue; + Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, preciseVectorData); + ++groupCount; for (uint16 groupReference : fgroup.DoodadReferences) { if (groupReference >= doodads.Spawns.size()) @@ -187,6 +192,8 @@ bool ExtractSingleWmo(std::string& fname) fseek(output, 8, SEEK_SET); // store the correct no of vertices fwrite(&Wmo_nVertices, sizeof(int), 1, output); + // store the correct no of groups + fwrite(&groupCount, sizeof(uint32), 1, output); fclose(output); // Delete the extracted file in the case of an error diff --git a/src/tools/vmap4_extractor/vmapexport.h b/src/tools/vmap4_extractor/vmapexport.h index bf0872bfa9..fc84339968 100644 --- a/src/tools/vmap4_extractor/vmapexport.h +++ b/src/tools/vmap4_extractor/vmapexport.h @@ -24,8 +24,8 @@ namespace VMAP { - const char VMAP_MAGIC[] = "VMAP_4.7"; - const char RAW_VMAP_MAGIC[] = "VMAP047"; // used in extracted vmap files with raw data + const char VMAP_MAGIC[] = "VMAP_4.8"; + const char RAW_VMAP_MAGIC[] = "VMAP048"; // used in extracted vmap files with raw data } enum ModelFlags diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 0a25367949..ed20db1196 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -103,6 +103,11 @@ bool WMORoot::open() DoodadData.Spawns.resize(size / sizeof(WMO::MODD)); f.read(DoodadData.Spawns.data(), size); } + else if (!strcmp(fourcc, "MOGN")) + { + GroupNames.resize(size); + f.read(GroupNames.data(), size); + } /* else if (!strcmp(fourcc,"MOTX")) { @@ -497,6 +502,22 @@ uint32 WMOGroup::GetLiquidTypeId(uint32 liquidTypeId) return liquidTypeId; } +bool WMOGroup::ShouldSkip(WMORoot const* root) const +{ + // skip unreachable + if (mogpFlags & 0x80) + return true; + + // skip antiportals + if (mogpFlags & 0x4000000) + return true; + + if (groupName < int32(root->GroupNames.size()) && !strcmp(&root->GroupNames[groupName], "antiportal")) + return true; + + return false; +} + WMOGroup::~WMOGroup() { delete [] MOPY; diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index dc44331e32..4d00b11cea 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -85,6 +85,7 @@ public: float bbcorn1[3]; float bbcorn2[3]; + std::vector<char> GroupNames; WMODoodadData DoodadData; std::unordered_set<uint32> ValidDoodadNames; @@ -154,6 +155,7 @@ public: bool open(WMORoot* rootWMO); int ConvertToVMAPGroupWmo(FILE* output, bool preciseVectorData); uint32 GetLiquidTypeId(uint32 liquidTypeId); + bool ShouldSkip(WMORoot const* root) const; }; namespace MapObject |
