From 0fc355fb7fec42ce9654bc5a0300c5ea34b858ca Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 24 Sep 2026 05:31:50 +0200 Subject: [PATCH] Changed attack behaviour of dungeonbot and fixed two more hillsbrad quests --- Ausgabe.txt | 332 ++++ .../scripts/Custom/viano_adventurers.cpp | 337 +++- .../zone_hillsbrad_foothills.cpp | 504 +++++ ...s.cpp.bak_welcome_scene_v2_20260921_172948 | 1744 +++++++++++++++++ 4 files changed, 2897 insertions(+), 20 deletions(-) create mode 100644 Ausgabe.txt create mode 100644 src/server/scripts/EasternKingdoms/zone_hillsbrad_foothills.cpp.bak_welcome_scene_v2_20260921_172948 diff --git a/Ausgabe.txt b/Ausgabe.txt new file mode 100644 index 0000000000..2d16862b66 --- /dev/null +++ b/Ausgabe.txt @@ -0,0 +1,332 @@ +157:(@OGUID+71, 61065, 0, 1, 1, -1351.477, -1261.028, 49.89219, 0.7941251, 0, 0, 0.9081432, 0.4186599, 120, 255, 1), -- Wooden Chair (Area: Dun Garok) +160:(@OGUID+74, 61043, 0, 1, 1, -1341.57, -1272.628, 49.89219, 0.7941251, 0, 0, 0.9081432, 0.4186599, 120, 255, 1), -- Wooden Chair (Area: Dun Garok) +472:(@OGUID+379, 180682, 0, 1, 1, -1251.7, 415.6858, 0, 3.141593, 0, 0, 0, 1, 120, 255, 1), -- Oily Blackmouth School (Area: Purgation Isle) +525:(@OGUID+432, 3800, 0, 1, 1, -140.4041, 222.1251, 54.17424, 4.694937, 0, 0, 0.7071069, 0.7071066, 120, 255, 1), -- Cozy Fire (Area: 0) +761:UPDATE `creature_template` SET `minlevel`=19, `maxlevel`=20, `faction_A`=2030, `faction_H`=2030, `speed_walk`=1.142857, `speed_run`=1, `baseattacktime`=2000, `rangeattacktime`=2000, `VehicleId`=1251 WHERE `entry`=47204; -- Infested Bear +762:UPDATE `creature_template` SET `faction_A`=7, `faction_H`=7, `speed_run`=1, `baseattacktime`=2000, `rangeattacktime`=2000 WHERE `entry`=47203; -- Creeper Egg +870:DELETE FROM `creature_template_addon` WHERE `entry` IN (49245, 49245, 49245, 49268, 49245, 49251, 49251, 49245, 49245, 49245, 49251, 49266, 49245, 883, 49245, 49249, 883, 49778, 49245, 49245, 49245, 49249, 49249, 48180, 883, 883, 48180, 883, 49778, 721, 48180, 49251, 49249, 49245, 48180, 49269, 2345, 49269, 49269, 2345, 2346, 2345, 49269, 2344, 49269, 49269, 2344, 49269, 2344, 2344, 2345, 2344, 2345, 2344, 49251, 49269, 49269, 2346, 2344, 2344, 2345, 2344, 49269, 2344, 2344, 2344, 49269, 2344, 2345, 2344, 2345, 14275, 2344, 2344, 49269, 49240, 2344, 2346, 2344, 49269, 2344, 2346, 2345, 2344, 2346, 2346, 2344, 2345, 2344, 2344, 2345, 49269, 49269, 2344, 49269, 2344, 49269, 2344, 2344, 49269, 49249, 49269, 49269, 16090, 2368, 2370, 2368, 2370, 2368, 2368, 2368, 2370, 2368, 2368, 2368, 2370, 2370, 5185, 2371, 2368, 2370, 2370, 2370, 2370, 2368, 2368, 2370, 2368, 2368, 48180, 49249, 49245, 48180, 48180, 48180, 4075, 4075, 49251, 49263, 721, 49245, 49245, 49245, 49245, 721, 49251, 49251, 883, 883, 2473, 49245, 4075, 49265, 620, 4075, 620, 49251, 49264, 49251, 49245, 721, 49778, 48180, 49245, 49249, 49249, 49245, 49245, 48180, 883, 48180, 49251, 883, 721, 49245, 48180, 48180, 49249, 2368, 2368, 2370, 2368, 32520, 32520, 32520, 32520, 2369, 2368, 2369, 883, 49245, 2474, 5951, 49245, 22480, 49245, 49251, 3536, 49778, 49778, 4075, 4075, 4075, 4075, 49245, 49245, 49245, 49249, 49245, 883, 48180, 49249, 721, 49251, 49245, 2373, 49245, 48180, 2369, 2369, 2369, 2371, 2371, 2371, 2369, 4075, 4075, 2373, 2372, 2372, 2372, 14278, 2372, 4075, 2372, 49245, 48180, 2371, 32520, 32520, 32520, 32520, 2369, 2371, 2369, 2371, 2371, 2371, 883, 2373, 2372, 2373, 4075, 620, 2373, 2373, 2372, 721, 49245, 883, 49245, 49245, 4075, 48180, 49245, 49251, 2369, 2371, 2371, 2369, 2371, 2372, 2373, 2372, 2372, 2372, 620, 2372, 2373, 49245, 48180, 48180, 49778, 49245, 49245, 721, 49251, 49778, 49245, 49245, 48180, 721, 48180, 2371, 2371, 2371, 2371, 2371, 2369, 32520, 32520, 32520, 32520, 49245, 48180, 49245, 6779, 11776, 55783, 55783, 6777, 7325, 55783, 13085, 6771, 8309, 6771, 55783, 6707, 6771, 6771, 55808, 45423, 45423, 41178, 41178, 46418, 5951, 6771, 6771, 6768, 7323, 55783, 55783, 7324, 45439, 55783, 55808, 55808, 55783, 49245, 883, 48180, 883, 49245, 883, 48180, 49245, 48180, 48180, 883, 48180, 49249, 49778, 2238, 49236, 49201, 49236, 49434, 49435, 48180, 2239, 49348, 49349, 49243, 49245, 49431, 48180, 47661, 49433, 49778, 48180, 49430, 49778, 48180, 48180, 2369, 2377, 2369, 2371, 2371, 2371, 2369, 2369, 2369, 2369, 2369, 2369, 721, 2371, 2371, 883, 6653, 883, 1933, 48180, 721, 49245, 48180, 721, 48180, 883, 48180, 55808, 13936, 883, 883, 49778, 14280, 48180, 48180, 1420, 2408, 6653, 14223, 2408, 48180, 48180, 32520, 32520, 32520, 32520, 48180, 48180, 48180, 1420, 6653, 6653, 2408, 48180, 883, 48180, 48180, 49778, 2350, 2350, 2350, 2350, 49778, 41178, 2350, 2350, 2350, 6176, 883, 6653, 48180, 721, 48180, 48180, 48180, 6653, 6653, 1420, 2408, 2408, 1420, 48180, 2408, 6653, 48180, 48180, 6653, 1420, 2408, 48180, 1420, 6653, 48180, 6653, 2408, 2408, 1420, 1420, 48272, 48272, 48136, 48272, 2377, 2376, 2376, 2376, 2377, 2376, 2377, 2377, 2376, 2377, 2377, 2376, 2376, 2376, 2377, 48272, 4075, 4075, 48136, 48319, 4075, 48319, 48319, 721, 16030, 16030, 4075, 48268, 4075, 4075, 4075, 4075, 4075, 48269, 48319, 4075, 48136, 620, 48136, 620, 620, 4075, 16030, 16030, 16030, 4075, 16030, 2442, 2442, 2442, 16030, 16030, 16030, 2442, 721, 16030, 4075, 16030, 1420, 2408, 48136, 6653, 1420, 2408, 48272, 883, 48272, 2408, 48180, 49778, 6653, 49778, 48272, 48180, 48184, 48187, 48180, 48180, 48180, 48180, 48180, 48180, 721, 48180, 48180, 49778, 6653, 1420, 2408, 6653, 48180, 883, 24110, 6653, 1420, 1420, 48180, 2408, 48180, 1420, 6653, 2408, 6653, 1420, 1420, 2408, 2408, 2408, 2408, 2408, 6653, 2408, 2408, 1420, 2408, 2408, 883, 2408, 6653, 2408, 2408, 2350, 6653, 6653, 2408, 2408, 1420, 883, 2350, 2350, 32520, 32520, 32520, 32520, 49778, 2350, 49778, 2408, 2350, 6653, 2350, 2408, 1420, 2350, 6653, 6653, 2408, 2350, 49778, 2408, 2350, 2350, 883, 2398, 48180, 47214, 47214, 48545, 2392, 2770, 3982, 16030, 2397, 2388, 16030, 16030, 2229, 47214, 2399, 2394, 47214, 4075, 3539, 2278, 2418, 2393, 16030, 2395, 4075, 2437, 4075, 16030, 4075, 2396, 16030, 47214, 17092, 47214, 2401, 2390, 2402, 10057, 4075, 3544, 2419, 721, 48180, 49778, 16030, 4075, 48180, 4075, 2400, 16030, 48180, 4075, 16030, 48180, 48180, 16030, 49778, 883, 48184, 48187, 48187, 48187, 48180, 721, 883, 49778, 48269, 48272, 48268, 48268, 48269, 48269, 48268, 883, 48269, 48272, 48272, 48272, 48268, 48269, 48268, 48268, 48268, 48269, 48158, 48129, 2391, 47644, 4075, 48158, 48158, 16030, 48136, 48136, 4075, 4075, 48136, 620, 16030, 16030, 48136, 48136, 4075, 4075, 16030, 4075, 4075, 48319, 48269, 48268, 48272, 48272, 3537, 2350, 883, 2429, 2410, 48269, 48269, 32520, 32520, 32520, 32520, 48268, 48272, 48272, 48158, 48136, 721, 16030, 48136, 48319, 48272, 48136, 4075, 4075, 4075, 48319, 48319, 48322, 1933, 48136, 48319, 2376, 2377, 2377, 48272, 2376, 2377, 2376, 2377, 2376, 2377, 2376, 2377, 2376, 2377, 2377, 48272, 48272, 48272, 48136, 48272, 48268, 48269, 47484, 48269, 48268, 48268, 48269, 48269, 48268, 48268, 48272, 721, 3538, 48180, 16030, 4075, 47214, 47214, 49778, 47214, 2389, 4075, 47214, 4075, 47214, 47214, 47214, 883, 2350, 13817, 13776, 14285, 14285, 721, 2350, 48742, 48741, 48741, 48741, 48742, 48741, 48741, 48741, 883, 49778, 47214, 47214, 721, 48180, 48180, 48180, 48180, 48180, 48180, 48180, 48180, 48187, 48187, 48184, 2385, 2385, 48268, 48269, 48272, 48269, 48268, 48268, 48269, 48268, 48269, 721, 14279, 2376, 2377, 2377, 2375, 2376, 2376, 2376, 2377, 2377, 2375, 2377, 2377, 2376, 2377, 2376, 883, 2376, 2350, 2350, 2350, 1933, 883, 48272, 48272, 2350, 47791, 883, 48272, 48272, 48272, 48269, 48268, 721, 48272, 48272, 48272, 48272, 48272, 48269, 48268, 49778, 49778, 48272, 48272, 48269, 48272, 48272, 48268, 48187, 2385, 48187, 48187, 32520, 32520, 32520, 32520, 48741, 13219, 14962, 14285, 14285, 883, 13840, 14285, 14285, 48741, 48741, 48862, 48742, 48741, 48742, 49778, 48184, 1412, 48187, 48184, 48184, 48187, 2385, 48272, 48272, 883, 48272, 47789, 48272, 48268, 48269, 2356, 49778, 48268, 2350, 2356, 2356, 2350, 1933, 883, 2375, 2376, 2377, 2374, 2375, 2375, 2374, 2375, 2375, 2375, 2375, 2375, 2375, 2374, 2375, 2375, 2375, 2374, 2375, 2375, 2375, 2375, 2375, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2350, 883, 2356, 49778, 2350, 2356, 2350, 2356, 2350, 2356, 721, 2356, 49778, 49778, 2350, 2350, 2350, 2356, 2350, 49778, 49778, 2356, 47793, 47792, 47790, 49778, 48187, 48187, 48184, 2385, 48187, 48184, 48184, 2385, 2385, 2248, 2385, 2248, 48628, 48628, 49111, 49111, 49111, 49111, 49111, 49111, 2248, 2248, 48184, 48187, 2385, 2248, 2248, 2248, 48628, 2248, 2248, 2385, 14281, 48878, 721, 48878, 48878, 48878, 48878, 48878, 48878, 48878, 48878, 49778, 48880, 48878, 48878, 48878, 48878, 48878, 48878, 48864, 48878, 48878, 48878, 883, 883, 48742, 48742, 48742, 2350, 2098, 883, 14285, 14285, 19906, 2350, 2350, 2350, 883, 883, 883, 48742, 2350, 883, 721, 48878, 721, 883, 2248, 2385, 2385, 48628, 2248, 48628, 49111, 49111, 49111, 2385, 48187, 32520, 32520, 32520, 32520, 2375, 2374, 2375, 2375, 2374, 2374, 2375, 2375, 2374, 2374, 14276, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 49778, 2349, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 49778, 2349, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 883, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2356, 2269, 49778, 47205, 2269, 2269, 2503, 14881, 14881, 2269, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 49778, 2269, 2350, 47871, 47871, 47871, 16030, 16030, 47872, 47872, 47872, 47872, 47861, 48184, 48184, 48187, 48187, 2385, 47871, 16030, 47859, 47872, 47786, 47786, 47786, 47786, 47786, 49778, 47861, 47861, 48187, 2385, 48184, 2248, 48187, 2385, 20615, 20615, 20615, 20615, 20615, 20615, 20615, 20615, 2248, 14222, 2248, 2248, 49111, 49778, 48628, 48628, 2248, 48628, 48628, 2248, 48628, 2248, 48628, 48628, 48628, 48628, 721, 48878, 48878, 48878, 48878, 48878, 1933, 721, 1933, 721, 48742, 2350, 41178, 2252, 47665, 2316, 2318, 4075, 14285, 2258, 2319, 2318, 2319, 2319, 2098, 2319, 721, 32520, 32520, 32520, 32520, 2350, 2318, 2319, 2319, 4075, 2318, 2319, 2319, 4075, 2252, 2252, 721, 49778, 48628, 48912, 48912, 48924, 48912, 48912, 48912, 48912, 48912, 48922, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48628, 48187, 2385, 2385, 2385, 48187, 48187, 48184, 48017, 47859, 47859, 47861, 47861, 4075, 47871, 47861, 47943, 47859, 16030, 16030, 47872, 47872, 16030, 16030, 47872, 47872, 47872, 16030, 16030, 47872, 721, 47871, 47872, 47872, 47872, 47859, 47872, 47872, 47872, 16030, 47872, 47872, 47872, 47861, 16030, 16030, 47872, 16030, 47872, 47872, 47872, 47872, 47871, 16030, 16030, 47872, 47872, 47859, 16030, 47861, 47872, 49778, 2269, 2356, 883, 721, 14881, 2269, 2503, 14881, 47681, 721, 49778, 2269, 883, 883, 2374, 2374, 2375, 2374, 2375, 47759, 2374, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2374, 2374, 14881, 2349, 14881, 47205, 2270, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 2269, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47205, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 47205, 2269, 14881, 14881, 2269, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2503, 2269, 2503, 2269, 2269, 14881, 14881, 14881, 14881, 14881, 2503, 14881, 2269, 14881, 2349, 49778, 47205, 2269, 2503, 2269, 883, 14881, 2269, 2350, 2269, 14881, 2269, 2269, 14881, 14881, 2503, 2269, 14881, 14881, 2269, 2269, 2269, 47786, 47786, 47871, 47786, 47786, 47786, 47859, 47871, 47861, 47859, 47861, 47871, 47861, 47871, 47859, 47871, 47871, 16030, 47871, 47861, 47859, 2385, 47859, 47859, 47859, 47861, 4075, 4075, 48017, 48017, 48017, 48017, 48017, 48017, 48017, 2385, 48184, 49778, 48923, 49778, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48912, 48865, 13217, 13841, 2386, 14961, 2386, 13816, 2252, 2252, 2252, 2253, 2252, 2252, 2253, 2253, 2252, 2252, 2252, 2253, 2252, 2253, 2252, 2318, 2252, 2252, 2253, 2252, 14221, 2350, 721, 1933, 2350, 2242, 2242, 2253, 2252, 2253, 2252, 2253, 2251, 2251, 2251, 2250, 2250, 2251, 2251, 2250, 2250, 14284, 14284, 14284, 14284, 14284, 14284, 14284, 14284, 13777, 14284, 14284, 16392, 721, 32520, 32520, 32520, 32520, 41178, 49116, 49116, 49116, 49116, 49116, 49116, 49116, 49116, 49116, 49116, 49116, 883, 49778, 883, 16030, 16030, 16030, 16030, 4075, 4075, 16030, 48017, 47859, 48017, 48009, 47870, 47859, 48017, 48017, 47861, 4075, 47861, 47861, 48017, 47871, 47861, 47871, 47871, 47861, 47861, 47859, 49778, 14881, 2269, 14881, 2269, 2270, 2503, 14881, 49778, 14881, 48484, 48484, 48484, 48484, 48484, 48484, 48482, 48482, 48484, 48484, 48482, 48482, 48484, 48484, 48484, 48483, 48484, 2375, 2375, 2375, 2374, 2375, 2374, 2375, 2374, 2375, 47214, 47214, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47214, 47565, 47551, 47554, 14881, 2270, 2270, 14881, 2270, 2270, 2270, 47205, 2269, 47205, 47205, 2270, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2269, 14881, 2269, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 2269, 14881, 14881, 2269, 2269, 14881, 14881, 14881, 47205, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2269, 2349, 14881, 2269, 2503, 14881, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2269, 47205, 14881, 2503, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2269, 14881, 14881, 2269, 47859, 47861, 47871, 47861, 47861, 47871, 47871, 47859, 47871, 47861, 47871, 47871, 47861, 47871, 47786, 47786, 47786, 47786, 47786, 4075, 47861, 47861, 47861, 47859, 47786, 2385, 2251, 2252, 2253, 2253, 2252, 2252, 2252, 2252, 2253, 2253, 2252, 2356, 2350, 721, 2098, 2350, 2318, 2318, 2350, 1933, 721, 1933, 721, 2350, 2252, 2356, 2252, 2252, 2253, 2252, 2253, 2253, 2252, 2252, 26614, 2251, 2251, 41178, 2250, 2251, 2250, 2452, 2250, 2251, 2251, 2250, 2251, 2250, 26614, 19907, 14284, 14284, 14284, 14284, 49116, 49116, 49116, 49116, 49116, 49116, 49116, 49116, 49116, 883, 48867, 47859, 47859, 47786, 47943, 47943, 47943, 47943, 47943, 47943, 4075, 47943, 47943, 47943, 47943, 47943, 4075, 4075, 47943, 47943, 47943, 47943, 47943, 4075, 47786, 47786, 47899, 47943, 47786, 49397, 47786, 16030, 47786, 47786, 16030, 47786, 16030, 47781, 16030, 47786, 47943, 49395, 49394, 49401, 49398, 49404, 49403, 47861, 47861, 47861, 47786, 47786, 47786, 47786, 2350, 14881, 2349, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 32520, 32520, 32520, 32520, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2349, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 14881, 14881, 2375, 2374, 2374, 48484, 48484, 48482, 48482, 48483, 48483, 48482, 48482, 48483, 48484, 48484, 48484, 48484, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 14881, 2349, 2349, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 2356, 47943, 47943, 47943, 47943, 47943, 47861, 47786, 47861, 47861, 47786, 47786, 47786, 47786, 47859, 47859, 721, 2356, 883, 721, 49778, 2250, 2250, 2350, 2350, 2350, 721, 2356, 49778, 2350, 721, 49778, 2350, 2356, 2350, 2350, 2350, 2356, 2350, 2350, 2350, 2350, 2356, 49778, 2356, 2356, 2350, 721, 2356, 2350, 2350, 2350, 2350, 883, 721, 2356, 2356, 49778, 2350, 14881, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2349, 14881, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 2349, 47204, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 47203, 14881, 883, 2349, 47655, 47668, 47432, 47214, 47214, 47214, 47214, 47712, 47214, 47433, 47433, 47214, 47214, 47214, 47433, 47445, 47214, 2215, 47214, 49778, 1412, 1412, 721, 4075, 721, 49693, 49693, 2356, 2350, 2356, 2350, 883, 2250, 2350, 2250, 32520, 32520, 32520, 32520, 2287, 2256, 26614, 2287, 2287, 2256, 2256, 2287, 2254, 2287, 2254, 2254, 2254, 2254, 2255, 2253, 2253, 2253, 26614, 26614, 26614, 2252, 2252, 2252, 2252, 2318, 2318, 2318, 2356, 2350, 2350, 2350, 2318, 2318, 1933, 2350, 2350, 2356, 1933, 721, 2252, 2252, 2252, 2252, 2253, 2253, 2253, 2253, 2252, 2255, 2254, 2254, 2254, 2255, 2254, 2256, 2254, 2420, 2256, 2287, 2256, 2416, 2416, 2287, 2287, 2256, 2250, 2350, 2356, 883, 49687, 49691, 49697, 49692, 49691, 49692, 49696, 49696, 2356, 49778, 883, 2356, 721, 883, 883, 883, 2350, 2356, 883, 2350, 2350, 883, 2350, 2350, 2250, 2250, 2251, 2287, 2287, 2287, 2257, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2287, 2256, 2256, 2255, 2256, 2255, 2256, 2417, 1933, 2350, 26614, 2453, 2252, 2252, 2252, 26614, 2254, 2254, 2254, 2421, 2287, 2287, 2287, 2256, 2287, 2356, 49778, 4075, 2628, 45734, 4075, 2628, 2628, 2628, 2628, 2628, 2628, 2628, 4075, 2628, 2358, 2358, 4075, 2350, 2358, 2356, 32520, 32520, 32520, 32520, 2251, 2250, 2256, 2255, 2422, 2254, 2255, 2252, 26614, 2253, 2356, 2098, 2350, 2350, 26614, 2253, 2252, 721, 49778, 2628, 4075, 4075, 2628, 2628, 2628, 2628, 4075, 2358, 2358, 4075, 4075, 4075, 2628, 2628, 4075, 4075, 45728, 2358, 2358, 2358, 45728, 45728, 45728, 47010, 2358, 45728, 2358, 45728, 45728, 883, 2628, 2628, 4075, 2628, 2350, 2356, 49778, 2251, 2350, 2251, 2251, 2251, 26614, 2251, 2251, 2098, 2255, 2254, 2480, 2254, 2253, 2252, 2350, 2318, 2318, 2356, 2356, 2350, 2350, 2252, 2098, 26614, 2251, 2251, 2251, 2251, 2251, 2251, 2628, 2628, 4075, 45728, 2358, 4075, 45728, 4075, 45728, 45728, 45728, 45728, 45728, 4075, 2628, 2358, 2358, 2628, 2628, 2628, 45728, 4075, 1412, 2628, 2628, 45728, 2358, 2358, 2628, 45728, 45728, 45728, 45728, 45728, 45728, 2358, 2628, 2628, 2358, 4075, 2350, 49778, 2628, 2628, 2628, 2350, 2350, 2350, 2251, 2251, 2350, 2350, 2350, 2350, 2350, 2356, 2350, 2350, 2350, 32520, 32520, 32520, 32520, 2098, 2350, 2350, 2408, 2408, 2408, 2350, 2408, 2408, 2408, 2408, 2408, 2408, 2408, 2408, 2408, 2408, 2408, 2408, 1768, 2350, 2350, 2356, 2356, 2408, 2628, 2628, 2628, 4075, 1412, 2408, 2408, 2350, 2358, 2628, 2628, 4075, 4075, 4075, 2628, 2628, 45728, 45728, 45728, 2628, 45728, 45728, 45728, 45728, 45728, 45728, 2358, 45728, 45728, 45728, 2358, 2408, 883, 18165, 45728, 2358, 10780, 721, 45728, 45728, 2358, 45728); +1017:(47203, 0, 0x0, 0x1, '87978 84461'), -- Creeper Egg - Creeper Egg, Sparkle Aura +1018:(47204, 0, 0x0, 0x1, ''), -- Infested Bear +1019:-- (47204, 0, 0x0, 0x1, '87966 29266'), -- Infested Bear - Feeding the Brood, Permanent Feign Death +1020:-- (47204, 0, 0x0, 0x1, '87966'), -- Infested Bear - Feeding the Brood +1362:(@CGUID+84, 2346, 0, 1, 1, -1321.69, -1251.97, 32.20713, 0.4712389, 120, 0, 0), -- Dun Garok Priest (Area: Dun Garok) +1400:(@CGUID+122, 2370, 0, 1, 1, -1251.422, -945.7887, 2.313909, 1.205165, 120, 0, 0), -- Daggerspine Screamer (Area: Eastern Strand) (possible waypoints or random movement) +1446:(@CGUID+168, 48180, 0, 1, 1, -868.6961, -1251.224, 52.94703, 3.077103, 120, 0, 0), -- Wild Horse (Area: 0) (possible waypoints or random movement) +1689:(@CGUID+411, 1420, 0, 1, 1, -327.5721, -1114.4, 37.27813, 4.125154, 120, 0, 0), -- Toad (Area: Durnholde Keep) +2264:(@CGUID+986, 47204, 0, 1, 1, -1046.352, 76.34468, 52.1014, 2.331338, 120, 0, 0), -- Infested Bear (Area: Western Strand) +2265:(@CGUID+987, 47203, 0, 1, 1, -1045.487, 75.43577, 54.8305, 2.331338, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2266:(@CGUID+988, 47203, 0, 1, 1, -1045.912, 75.44631, 54.6805, 5.472933, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2267:(@CGUID+989, 47203, 0, 1, 1, -1045.477, 75.8599, 54.6805, 5.472933, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2268:(@CGUID+990, 47203, 0, 1, 1, -1045.694, 75.65311, 54.8305, 5.298393, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2269:(@CGUID+991, 47203, 0, 1, 1, -1045.498, 75.01163, 54.6805, 2.331338, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2270:(@CGUID+992, 47203, 0, 1, 1, -1045.063, 75.42522, 54.6805, 2.331338, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2271:(@CGUID+993, 47203, 0, 1, 1, -1045.216, 75.69426, 54.8305, 3.902138, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2272:(@CGUID+994, 47203, 0, 1, 1, -1045.759, 75.17728, 54.8305, 0.7605376, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2273:(@CGUID+995, 47204, 0, 1, 1, -1052.322, 87.23633, 55.31487, 5.46741, 120, 0, 0), -- Infested Bear (Area: Western Strand) +2274:(@CGUID+996, 47203, 0, 1, 1, -1053.182, 88.15, 58.04396, 5.46741, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2275:(@CGUID+997, 47203, 0, 1, 1, -1052.758, 88.13712, 57.89397, 2.325819, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2276:(@CGUID+998, 47203, 0, 1, 1, -1053.195, 87.72593, 57.89397, 2.325819, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2277:(@CGUID+999, 47203, 0, 1, 1, -1052.976, 87.93152, 58.04396, 2.15128, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2278:(@CGUID+1000, 47203, 0, 1, 1, -1053.169, 88.57407, 57.89397, 5.46741, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2279:(@CGUID+1001, 47203, 0, 1, 1, -1053.606, 88.16289, 57.89397, 5.46741, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2280:(@CGUID+1002, 47203, 0, 1, 1, -1053.455, 87.89301, 58.04396, 0.7550244, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2281:(@CGUID+1003, 47203, 0, 1, 1, -1052.909, 88.40699, 58.04396, 3.896611, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2413:(@CGUID+1135, 47204, 0, 1, 1, -1042.742, 172.7796, 65.47237, 3.116208, 120, 0, 0), -- Infested Bear (Area: Western Strand) +2414:(@CGUID+1136, 47203, 0, 1, 1, -1041.487, 172.7477, 68.20148, 3.116208, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2415:(@CGUID+1137, 47203, 0, 1, 1, -1041.795, 172.4554, 68.05148, 6.257803, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2416:(@CGUID+1138, 47203, 0, 1, 1, -1041.78, 173.0553, 68.05148, 6.257803, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2417:(@CGUID+1139, 47203, 0, 1, 1, -1041.787, 172.7553, 68.20148, 6.083263, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2418:(@CGUID+1140, 47203, 0, 1, 1, -1041.195, 172.4402, 68.05148, 3.116208, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2419:(@CGUID+1141, 47203, 0, 1, 1, -1041.18, 173.04, 68.05148, 3.116208, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2420:(@CGUID+1142, 47203, 0, 1, 1, -1041.478, 173.1226, 68.20148, 4.687007, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2421:(@CGUID+1143, 47203, 0, 1, 1, -1041.497, 172.3728, 68.20148, 1.545408, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2424:(@CGUID+1146, 47204, 0, 1, 1, -1015.088, 113.433, 53.79728, 4.627599, 120, 0, 0), -- Infested Bear (Area: Western Strand) +2425:(@CGUID+1147, 47203, 0, 1, 1, -1014.982, 114.6831, 56.52638, 4.627599, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2426:(@CGUID+1148, 47203, 0, 1, 1, -1014.708, 114.3587, 56.37638, 1.486009, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2427:(@CGUID+1149, 47203, 0, 1, 1, -1015.306, 114.4096, 56.37638, 1.486009, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2428:(@CGUID+1150, 47203, 0, 1, 1, -1015.007, 114.3841, 56.52638, 1.31147, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2429:(@CGUID+1151, 47203, 0, 1, 1, -1014.657, 114.9566, 56.37638, 4.627599, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2430:(@CGUID+1152, 47203, 0, 1, 1, -1015.255, 115.0074, 56.37638, 4.627599, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2431:(@CGUID+1153, 47203, 0, 1, 1, -1015.355, 114.7148, 56.52638, 6.198399, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2432:(@CGUID+1154, 47203, 0, 1, 1, -1014.608, 114.6513, 56.52638, 3.056799, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2435:(@CGUID+1157, 47204, 0, 1, 1, -981.9716, 79.79846, 52.35743, 2.018549, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +2436:(@CGUID+1158, 47203, 0, 1, 1, -981.4285, 78.66753, 55.08653, 2.018549, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2437:(@CGUID+1159, 47203, 0, 1, 1, -981.8287, 78.80808, 54.93653, 5.160144, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2438:(@CGUID+1160, 47203, 0, 1, 1, -981.2879, 79.06785, 54.93653, 5.160144, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2439:(@CGUID+1161, 47203, 0, 1, 1, -981.5583, 78.93797, 55.08653, 4.985604, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2440:(@CGUID+1162, 47203, 0, 1, 1, -981.569, 78.26723, 54.93653, 2.018549, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2441:(@CGUID+1163, 47203, 0, 1, 1, -981.0281, 78.52699, 54.93653, 2.018549, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2442:(@CGUID+1164, 47203, 0, 1, 1, -981.0904, 78.82989, 55.08653, 3.589349, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2443:(@CGUID+1165, 47203, 0, 1, 1, -981.7665, 78.50519, 55.08653, 0.4477491, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2445:(@CGUID+1167, 47204, 0, 1, 1, -880.4624, 79.44542, 36.07406, 5.727381, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +2446:(@CGUID+1168, 47203, 0, 1, 1, -881.5281, 80.10738, 38.79871, 5.727381, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2447:(@CGUID+1169, 47203, 0, 1, 1, -881.1151, 80.20393, 38.64871, 2.585791, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2448:(@CGUID+1170, 47203, 0, 1, 1, -881.4316, 79.69425, 38.64871, 2.585791, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2449:(@CGUID+1171, 47203, 0, 1, 1, -881.2733, 79.94909, 38.79871, 2.411252, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2450:(@CGUID+1172, 47203, 0, 1, 1, -881.6247, 80.52051, 38.64871, 5.727381, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2451:(@CGUID+1173, 47203, 0, 1, 1, -881.9413, 80.01083, 38.64871, 5.727381, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2452:(@CGUID+1174, 47203, 0, 1, 1, -881.726, 79.78883, 38.79871, 1.014996, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2453:(@CGUID+1175, 47203, 0, 1, 1, -881.3303, 80.42593, 38.79871, 4.156581, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2454:(@CGUID+1176, 47204, 0, 1, 1, -844.042, 72.5851, 37.76933, 4.118977, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +2455:(@CGUID+1177, 47203, 0, 1, 1, -843.3405, 73.62521, 40.49843, 4.118977, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2456:(@CGUID+1178, 47203, 0, 1, 1, -843.2595, 73.20874, 40.34843, 0.977387, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2457:(@CGUID+1179, 47203, 0, 1, 1, -843.7569, 73.54426, 40.34843, 0.977387, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2458:(@CGUID+1180, 47203, 0, 1, 1, -843.5082, 73.3765, 40.49843, 0.8028474, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2459:(@CGUID+1181, 47203, 0, 1, 1, -842.924, 73.70616, 40.34843, 4.118977, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2460:(@CGUID+1182, 47203, 0, 1, 1, -843.4214, 74.04168, 40.34843, 4.118977, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2461:(@CGUID+1183, 47203, 0, 1, 1, -843.6513, 73.83491, 40.49843, 5.689777, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2462:(@CGUID+1184, 47203, 0, 1, 1, -843.0295, 73.41551, 40.49843, 2.548177, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2473:(@CGUID+1195, 47204, 0, 1, 1, -896.134, 106.207, 39.30183, 0.9599311, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +2474:(@CGUID+1196, 47203, 0, 1, 1, -896.8536, 105.1793, 42.03093, 0.9599311, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2475:(@CGUID+1197, 47203, 0, 1, 1, -896.9272, 105.5971, 41.88093, 4.101526, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2476:(@CGUID+1198, 47203, 0, 1, 1, -896.4358, 105.253, 41.88093, 4.101526, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2477:(@CGUID+1199, 47203, 0, 1, 1, -896.6815, 105.425, 42.03093, 3.926987, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2478:(@CGUID+1200, 47203, 0, 1, 1, -897.2714, 105.1056, 41.88093, 0.9599311, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2479:(@CGUID+1201, 47203, 0, 1, 1, -896.7799, 104.7615, 41.88093, 0.9599311, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2480:(@CGUID+1202, 47203, 0, 1, 1, -896.5464, 104.9642, 42.03093, 2.530731, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2481:(@CGUID+1203, 47203, 0, 1, 1, -897.1608, 105.3944, 42.03093, 5.672317, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2529:(@CGUID+1251, 2248, 0, 1, 1, -297.924, -300.81, 43.4171, 6.071205, 120, 0, 0), -- Cave Yeti (Area: 0) +2695:(@CGUID+1417, 47204, 0, 1, 1, -960.3278, 157.5009, 46.79146, 3.748002, 120, 0, 0), -- Infested Bear (Area: Western Strand) +2696:(@CGUID+1418, 47203, 0, 1, 1, -959.2969, 158.2159, 49.51065, 3.748002, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2697:(@CGUID+1419, 47203, 0, 1, 1, -959.3724, 157.7984, 49.36065, 0.6064115, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2698:(@CGUID+1420, 47203, 0, 1, 1, -959.7144, 158.2914, 49.36065, 0.6064115, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2699:(@CGUID+1421, 47203, 0, 1, 1, -959.5433, 158.0449, 49.51065, 0.4318719, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2700:(@CGUID+1422, 47203, 0, 1, 1, -958.8794, 158.1404, 49.36065, 3.748002, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2701:(@CGUID+1423, 47203, 0, 1, 1, -959.2213, 158.6334, 49.36065, 3.748002, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2702:(@CGUID+1424, 47203, 0, 1, 1, -959.5106, 158.524, 49.51065, 5.318801, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2703:(@CGUID+1425, 47203, 0, 1, 1, -959.0831, 157.9078, 49.51065, 2.177202, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +2712:(@CGUID+1434, 47204, 0, 1, 1, -841.781, 131.703, 38.70893, 4.607669, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +2713:(@CGUID+1435, 47203, 0, 1, 1, -841.6498, 132.9507, 41.43803, 4.607669, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2714:(@CGUID+1436, 47203, 0, 1, 1, -841.3829, 132.621, 41.28803, 1.466079, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2715:(@CGUID+1437, 47203, 0, 1, 1, -841.9796, 132.6837, 41.28803, 1.466079, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2716:(@CGUID+1438, 47203, 0, 1, 1, -841.6812, 132.6524, 41.43803, 1.29154, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2717:(@CGUID+1439, 47203, 0, 1, 1, -841.3201, 133.2177, 41.28803, 4.607669, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2718:(@CGUID+1440, 47203, 0, 1, 1, -841.9169, 133.2804, 41.28803, 4.607669, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2719:(@CGUID+1441, 47203, 0, 1, 1, -842.0228, 132.9899, 41.43803, 6.178469, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2720:(@CGUID+1442, 47203, 0, 1, 1, -841.2769, 132.9115, 41.43803, 3.03687, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2724:(@CGUID+1446, 47204, 0, 1, 1, -821.7272, 117.3276, 40.78638, 3.074433, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +2725:(@CGUID+1447, 47203, 0, 1, 1, -820.4755, 117.2434, 43.51548, 3.074433, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2726:(@CGUID+1448, 47203, 0, 1, 1, -820.7949, 116.9642, 43.36548, 6.216028, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2727:(@CGUID+1449, 47203, 0, 1, 1, -820.7546, 117.5629, 43.36548, 6.216028, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2728:(@CGUID+1450, 47203, 0, 1, 1, -820.7748, 117.2636, 43.51548, 6.041489, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2729:(@CGUID+1451, 47203, 0, 1, 1, -820.1963, 116.924, 43.36548, 3.074433, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2730:(@CGUID+1452, 47203, 0, 1, 1, -820.156, 117.5226, 43.36548, 3.074433, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2731:(@CGUID+1453, 47203, 0, 1, 1, -820.4503, 117.6176, 43.51548, 4.645233, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2732:(@CGUID+1454, 47203, 0, 1, 1, -820.5006, 116.8693, 43.51548, 1.503633, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2733:(@CGUID+1455, 47204, 0, 1, 1, -805.9108, 142.4732, 43.20799, 3.294687, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +2734:(@CGUID+1456, 47203, 0, 1, 1, -804.6709, 142.6645, 45.93709, 3.294687, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2735:(@CGUID+1457, 47203, 0, 1, 1, -804.9216, 142.3222, 45.78709, 0.1530967, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2736:(@CGUID+1458, 47203, 0, 1, 1, -805.0131, 142.9152, 45.78709, 0.1530967, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2737:(@CGUID+1459, 47203, 0, 1, 1, -804.9674, 142.6187, 45.93709, 6.261742, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2738:(@CGUID+1460, 47203, 0, 1, 1, -804.3287, 142.4137, 45.78709, 3.294687, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2739:(@CGUID+1461, 47203, 0, 1, 1, -804.4202, 143.0067, 45.78709, 3.294687, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2740:(@CGUID+1462, 47203, 0, 1, 1, -804.7281, 143.0351, 45.93709, 4.865487, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2741:(@CGUID+1463, 47203, 0, 1, 1, -804.6137, 142.2939, 45.93709, 1.723887, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2743:(@CGUID+1465, 47204, 0, 1, 1, -782.1827, 84.27602, 38.05173, 5.262589, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +2744:(@CGUID+1466, 47203, 0, 1, 1, -782.8387, 85.34546, 40.78083, 5.262589, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2745:(@CGUID+1467, 47203, 0, 1, 1, -782.4261, 85.2466, 40.63083, 2.120999, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2746:(@CGUID+1468, 47203, 0, 1, 1, -782.9375, 84.93288, 40.63083, 2.120999, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2747:(@CGUID+1469, 47203, 0, 1, 1, -782.6818, 85.08974, 40.78083, 1.946459, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2748:(@CGUID+1470, 47203, 0, 1, 1, -782.7398, 85.75805, 40.63083, 5.262589, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2749:(@CGUID+1471, 47203, 0, 1, 1, -783.2512, 85.44433, 40.63083, 5.262589, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2750:(@CGUID+1472, 47203, 0, 1, 1, -783.1583, 85.14939, 40.78083, 0.5502033, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2751:(@CGUID+1473, 47203, 0, 1, 1, -782.519, 85.54153, 40.78083, 3.691789, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2758:(@CGUID+1480, 47204, 0, 1, 1, -776.9836, 124.4102, 42.95721, 5.563659, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +2759:(@CGUID+1481, 47203, 0, 1, 1, -777.9272, 125.237, 45.68631, 5.563659, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2760:(@CGUID+1482, 47203, 0, 1, 1, -777.5038, 125.2649, 45.53631, 2.422069, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2761:(@CGUID+1483, 47203, 0, 1, 1, -777.8993, 124.8136, 45.53631, 2.422069, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2762:(@CGUID+1484, 47203, 0, 1, 1, -777.7015, 125.0393, 45.68631, 2.24753, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2763:(@CGUID+1485, 47203, 0, 1, 1, -777.9551, 125.6603, 45.53631, 5.563659, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2764:(@CGUID+1486, 47203, 0, 1, 1, -778.3505, 125.209, 45.53631, 5.563659, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2765:(@CGUID+1487, 47203, 0, 1, 1, -778.1743, 124.9549, 45.68631, 0.8512735, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +2766:(@CGUID+1488, 47203, 0, 1, 1, -777.6801, 125.519, 45.68631, 3.992859, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3002:(@CGUID+1724, 47204, 0, 1, 1, -904.166, 279.166, 30.58176, 4.255208, 120, 0, 0), -- Infested Bear (Area: Western Strand) +3003:(@CGUID+1725, 47203, 0, 1, 1, -903.6122, 280.2918, 33.31086, 4.255208, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +3004:(@CGUID+1726, 47203, 0, 1, 1, -903.4755, 279.8902, 33.16087, 1.113618, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +3005:(@CGUID+1727, 47203, 0, 1, 1, -904.0139, 280.155, 33.16087, 1.113618, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +3006:(@CGUID+1728, 47203, 0, 1, 1, -903.7446, 280.0226, 33.31086, 0.9390779, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +3007:(@CGUID+1729, 47203, 0, 1, 1, -903.2106, 280.4285, 33.16087, 4.255208, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +3008:(@CGUID+1730, 47203, 0, 1, 1, -903.749, 280.6934, 33.16087, 4.255208, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +3009:(@CGUID+1731, 47203, 0, 1, 1, -903.9487, 280.4573, 33.31086, 5.826008, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +3010:(@CGUID+1732, 47203, 0, 1, 1, -903.2757, 280.1263, 33.31086, 2.684409, 120, 0, 0), -- Creeper Egg (Area: Western Strand) +3027:(@CGUID+1749, 47204, 0, 1, 1, -834.153, 275.146, 38.50253, 5.585053, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3028:(@CGUID+1750, 47203, 0, 1, 1, -834.6915, 275.9894, 41.08163, 2.443463, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3029:(@CGUID+1751, 47203, 0, 1, 1, -835.5367, 275.9155, 41.08163, 5.585053, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3030:(@CGUID+1752, 47203, 0, 1, 1, -835.3552, 275.6652, 41.23163, 0.8726678, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3031:(@CGUID+1753, 47203, 0, 1, 1, -834.873, 276.2397, 41.23163, 4.014254, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3032:(@CGUID+1754, 47203, 0, 1, 1, -835.1141, 275.9524, 41.23163, 5.585053, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3033:(@CGUID+1755, 47203, 0, 1, 1, -835.0771, 275.5298, 41.08163, 2.443463, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3034:(@CGUID+1756, 47203, 0, 1, 1, -834.8843, 275.7596, 41.23163, 2.268923, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3035:(@CGUID+1757, 47203, 0, 1, 1, -835.1511, 276.3751, 41.08163, 5.585053, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3039:(@CGUID+1761, 47204, 0, 1, 1, -806.825, 226.569, 37.51473, 2.007129, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3040:(@CGUID+1762, 47203, 0, 1, 1, -806.2948, 225.4319, 40.24383, 2.007129, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3041:(@CGUID+1763, 47203, 0, 1, 1, -806.6935, 225.5771, 40.09383, 5.148724, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3042:(@CGUID+1764, 47203, 0, 1, 1, -806.1497, 225.8306, 40.09383, 5.148724, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3043:(@CGUID+1765, 47203, 0, 1, 1, -806.4216, 225.7038, 40.24383, 4.974184, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3044:(@CGUID+1766, 47203, 0, 1, 1, -806.4399, 225.0333, 40.09383, 2.007129, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3045:(@CGUID+1767, 47203, 0, 1, 1, -805.8961, 225.2868, 40.09383, 2.007129, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3046:(@CGUID+1768, 47203, 0, 1, 1, -805.955, 225.5904, 40.24383, 3.577929, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3047:(@CGUID+1769, 47203, 0, 1, 1, -806.6346, 225.2735, 40.24383, 0.4363289, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3058:(@CGUID+1780, 47204, 0, 1, 1, -754.682, 202.569, 54.61083, 0, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3059:(@CGUID+1781, 47203, 0, 1, 1, -756.2366, 202.869, 57.18993, 0, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3060:(@CGUID+1782, 47203, 0, 1, 1, -755.9366, 202.569, 57.33993, 0, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3061:(@CGUID+1783, 47203, 0, 1, 1, -755.6366, 202.869, 57.18993, 3.141595, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3062:(@CGUID+1784, 47203, 0, 1, 1, -755.6366, 202.269, 57.18993, 3.141595, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3063:(@CGUID+1785, 47203, 0, 1, 1, -755.6366, 202.569, 57.33993, 2.967056, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3064:(@CGUID+1786, 47203, 0, 1, 1, -756.2366, 202.269, 57.18993, 0, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3065:(@CGUID+1787, 47203, 0, 1, 1, -755.9366, 202.194, 57.33993, 1.5708, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3066:(@CGUID+1788, 47203, 0, 1, 1, -755.9366, 202.944, 57.33993, 4.712386, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3067:(@CGUID+1789, 47204, 0, 1, 1, -745.6191, 187.4171, 50.34536, 1.206932, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3068:(@CGUID+1790, 47203, 0, 1, 1, -746.0656, 186.2446, 53.07446, 1.206932, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3069:(@CGUID+1791, 47203, 0, 1, 1, -746.2393, 186.6317, 52.92446, 4.348527, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3070:(@CGUID+1792, 47203, 0, 1, 1, -745.6785, 186.4182, 52.92446, 4.348527, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3071:(@CGUID+1793, 47203, 0, 1, 1, -745.9589, 186.525, 53.07446, 4.173987, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3072:(@CGUID+1794, 47203, 0, 1, 1, -746.4528, 186.071, 52.92446, 1.206932, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3073:(@CGUID+1795, 47203, 0, 1, 1, -745.892, 185.8575, 52.92446, 1.206932, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3074:(@CGUID+1796, 47203, 0, 1, 1, -745.7152, 186.1111, 53.07446, 2.777732, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3075:(@CGUID+1797, 47203, 0, 1, 1, -746.4161, 186.3781, 53.07446, 5.919317, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3083:(@CGUID+1805, 47204, 0, 1, 1, -730.002, 117.028, 42.29953, 3.647738, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3084:(@CGUID+1806, 47203, 0, 1, 1, -728.9047, 117.6362, 45.02863, 3.647738, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3085:(@CGUID+1807, 47203, 0, 1, 1, -729.0217, 117.2284, 44.87864, 0.5061479, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3086:(@CGUID+1808, 47203, 0, 1, 1, -729.3126, 117.7532, 44.87864, 0.5061479, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3087:(@CGUID+1809, 47203, 0, 1, 1, -729.1671, 117.4908, 45.02863, 0.3316083, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3088:(@CGUID+1810, 47203, 0, 1, 1, -728.4969, 117.5193, 44.87864, 3.647738, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3089:(@CGUID+1811, 47203, 0, 1, 1, -728.7878, 118.0441, 44.87864, 3.647738, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3090:(@CGUID+1812, 47203, 0, 1, 1, -729.0865, 117.9642, 45.02863, 5.218538, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3091:(@CGUID+1813, 47203, 0, 1, 1, -728.7229, 117.3083, 45.02863, 2.076938, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3097:(@CGUID+1819, 47204, 0, 1, 1, -707.6761, 161.4365, 46.60545, 3.793098, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3098:(@CGUID+1820, 47203, 0, 1, 1, -706.6785, 162.1973, 49.33455, 3.793098, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3099:(@CGUID+1821, 47203, 0, 1, 1, -706.7352, 161.7768, 49.18455, 0.6515079, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3100:(@CGUID+1822, 47203, 0, 1, 1, -707.099, 162.2539, 49.18455, 0.6515079, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3101:(@CGUID+1823, 47203, 0, 1, 1, -706.9171, 162.0154, 49.33455, 0.4769683, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3102:(@CGUID+1824, 47203, 0, 1, 1, -706.2581, 162.1406, 49.18455, 3.793098, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3103:(@CGUID+1825, 47203, 0, 1, 1, -706.6219, 162.6178, 49.18455, 3.793098, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3104:(@CGUID+1826, 47203, 0, 1, 1, -706.9059, 162.4955, 49.33455, 5.363898, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3105:(@CGUID+1827, 47203, 0, 1, 1, -706.4511, 161.8991, 49.33455, 2.222298, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3258:(@CGUID+1980, 47204, 0, 1, 1, -714.244, 220.6793, 51.0158, 0.2047469, 120, 0, 0), -- Infested Bear (Area: 0) +3259:(@CGUID+1981, 47203, 0, 1, 1, -715.4724, 220.4242, 53.7449, 0.2047469, 120, 0, 0), -- Creeper Egg (Area: 0) +3260:(@CGUID+1982, 47203, 0, 1, 1, -715.2396, 220.7789, 53.5949, 3.346342, 120, 0, 0), -- Creeper Egg (Area: 0) +3261:(@CGUID+1983, 47203, 0, 1, 1, -715.1176, 220.1914, 53.5949, 3.346342, 120, 0, 0), -- Creeper Egg (Area: 0) +3262:(@CGUID+1984, 47203, 0, 1, 1, -715.1786, 220.4852, 53.7449, 3.171803, 120, 0, 0), -- Creeper Egg (Area: 0) +3263:(@CGUID+1985, 47203, 0, 1, 1, -715.8271, 220.6569, 53.5949, 0.2047469, 120, 0, 0), -- Creeper Egg (Area: 0) +3264:(@CGUID+1986, 47203, 0, 1, 1, -715.7051, 220.0694, 53.5949, 0.2047469, 120, 0, 0), -- Creeper Egg (Area: 0) +3265:(@CGUID+1987, 47203, 0, 1, 1, -715.3961, 220.057, 53.7449, 1.775547, 120, 0, 0), -- Creeper Egg (Area: 0) +3266:(@CGUID+1988, 47203, 0, 1, 1, -715.5486, 220.7913, 53.7449, 4.917132, 120, 0, 0), -- Creeper Egg (Area: 0) +3269:(@CGUID+1991, 47204, 0, 1, 1, -703.069, 245.036, 50.67043, 3.630285, 120, 0, 0), -- Infested Bear (Area: 0) +3270:(@CGUID+1992, 47203, 0, 1, 1, -701.9612, 245.625, 53.39953, 3.630285, 120, 0, 0), -- Creeper Egg (Area: 0) +3271:(@CGUID+1993, 47203, 0, 1, 1, -702.0853, 245.2193, 53.24953, 0.4886947, 120, 0, 0), -- Creeper Egg (Area: 0) +3272:(@CGUID+1994, 47203, 0, 1, 1, -702.3669, 245.749, 53.24953, 0.4886947, 120, 0, 0), -- Creeper Egg (Area: 0) +3273:(@CGUID+1995, 47203, 0, 1, 1, -702.2261, 245.4841, 53.39953, 0.3141551, 120, 0, 0), -- Creeper Egg (Area: 0) +3274:(@CGUID+1996, 47203, 0, 1, 1, -701.5555, 245.5009, 53.24953, 3.630285, 120, 0, 0), -- Creeper Egg (Area: 0) +3275:(@CGUID+1997, 47203, 0, 1, 1, -701.8372, 246.0307, 53.24953, 3.630285, 120, 0, 0), -- Creeper Egg (Area: 0) +3276:(@CGUID+1998, 47203, 0, 1, 1, -702.1373, 245.9561, 53.39953, 5.201085, 120, 0, 0), -- Creeper Egg (Area: 0) +3277:(@CGUID+1999, 47203, 0, 1, 1, -701.7852, 245.2939, 53.39953, 2.059485, 120, 0, 0), -- Creeper Egg (Area: 0) +3283:(@CGUID+2005, 47204, 0, 1, 1, -770.2559, 252.9648, 45.72102, 1.306202, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3284:(@CGUID+2006, 47203, 0, 1, 1, -770.584, 251.7539, 48.45012, 1.306202, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3285:(@CGUID+2007, 47203, 0, 1, 1, -770.7951, 252.1219, 48.30013, 4.447797, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3286:(@CGUID+2008, 47203, 0, 1, 1, -770.216, 251.965, 48.30013, 4.447797, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3287:(@CGUID+2009, 47203, 0, 1, 1, -770.5056, 252.0434, 48.45012, 4.273257, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3288:(@CGUID+2010, 47203, 0, 1, 1, -770.952, 251.5428, 48.30013, 1.306202, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3289:(@CGUID+2011, 47203, 0, 1, 1, -770.3729, 251.3859, 48.30013, 1.306202, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3290:(@CGUID+2012, 47203, 0, 1, 1, -770.222, 251.6558, 48.45012, 2.877002, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3291:(@CGUID+2013, 47203, 0, 1, 1, -770.946, 251.8519, 48.45012, 6.018587, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3293:(@CGUID+2015, 47204, 0, 1, 1, -723.9033, 270.7157, 49.37264, 1.797724, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3294:(@CGUID+2016, 47203, 0, 1, 1, -723.621, 269.4933, 52.05125, 1.797724, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3295:(@CGUID+2017, 47203, 0, 1, 1, -723.9808, 269.7181, 51.90125, 4.93932, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3296:(@CGUID+2018, 47203, 0, 1, 1, -723.3962, 269.8531, 51.90125, 4.93932, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3297:(@CGUID+2019, 47203, 0, 1, 1, -723.6885, 269.7856, 52.05125, 4.76478, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3298:(@CGUID+2020, 47203, 0, 1, 1, -723.8459, 269.1335, 51.90125, 1.797724, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3299:(@CGUID+2021, 47203, 0, 1, 1, -723.2612, 269.2685, 51.90125, 1.797724, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3300:(@CGUID+2022, 47203, 0, 1, 1, -723.2557, 269.5776, 52.05125, 3.368525, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3301:(@CGUID+2023, 47203, 0, 1, 1, -723.9865, 269.4089, 52.05125, 0.2269244, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3304:(@CGUID+2026, 47204, 0, 1, 1, -762.295, 289.806, 46.96553, 0, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3305:(@CGUID+2027, 47203, 0, 1, 1, -763.5496, 289.806, 49.69463, 0, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3306:(@CGUID+2028, 47203, 0, 1, 1, -763.2496, 290.106, 49.54463, 3.141595, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3307:(@CGUID+2029, 47203, 0, 1, 1, -763.2496, 289.506, 49.54463, 3.141595, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3308:(@CGUID+2030, 47203, 0, 1, 1, -763.2496, 289.806, 49.69463, 2.967056, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3309:(@CGUID+2031, 47203, 0, 1, 1, -763.8496, 290.106, 49.54463, 0, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3310:(@CGUID+2032, 47203, 0, 1, 1, -763.8496, 289.506, 49.54463, 0, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3311:(@CGUID+2033, 47203, 0, 1, 1, -763.5496, 289.431, 49.69463, 1.5708, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3312:(@CGUID+2034, 47203, 0, 1, 1, -763.5496, 290.181, 49.69463, 4.712386, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3314:(@CGUID+2036, 47204, 0, 1, 1, -831.9563, 302.3047, 44.78557, 4.09967, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3315:(@CGUID+2037, 47203, 0, 1, 1, -831.2348, 303.3311, 47.51467, 4.09967, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3316:(@CGUID+2038, 47203, 0, 1, 1, -831.1619, 302.9131, 47.36467, 0.9580803, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3317:(@CGUID+2039, 47203, 0, 1, 1, -831.6528, 303.2581, 47.36467, 0.9580803, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3318:(@CGUID+2040, 47203, 0, 1, 1, -831.4073, 303.0856, 47.51467, 0.7835402, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3319:(@CGUID+2041, 47203, 0, 1, 1, -830.8168, 303.404, 47.36467, 4.09967, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3320:(@CGUID+2042, 47203, 0, 1, 1, -831.3077, 303.749, 47.36467, 4.09967, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3321:(@CGUID+2043, 47203, 0, 1, 1, -831.5416, 303.5467, 47.51467, 5.67047, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3322:(@CGUID+2044, 47203, 0, 1, 1, -830.928, 303.1154, 47.51467, 2.52887, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3342:(@CGUID+2064, 47204, 0, 1, 1, -817.971, 349.337, 53.96453, 4.729842, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3343:(@CGUID+2065, 47203, 0, 1, 1, -817.9929, 350.5914, 56.69363, 4.729842, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3344:(@CGUID+2066, 47203, 0, 1, 1, -817.6877, 350.2967, 56.54363, 1.588252, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3345:(@CGUID+2067, 47203, 0, 1, 1, -818.2876, 350.2862, 56.54363, 1.588252, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3346:(@CGUID+2068, 47203, 0, 1, 1, -817.9877, 350.2915, 56.69363, 1.413712, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3347:(@CGUID+2069, 47203, 0, 1, 1, -817.6982, 350.8966, 56.54363, 4.729842, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3348:(@CGUID+2070, 47203, 0, 1, 1, -818.2981, 350.8861, 56.54363, 4.729842, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3349:(@CGUID+2071, 47203, 0, 1, 1, -818.3679, 350.5849, 56.69363, 0.01745653, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3350:(@CGUID+2072, 47203, 0, 1, 1, -817.618, 350.598, 56.69363, 3.159043, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3351:(@CGUID+2073, 47204, 0, 1, 1, -788.7335, 317.7348, 52.07045, 4.025625, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3352:(@CGUID+2074, 47203, 0, 1, 1, -787.938, 318.705, 54.77511, 4.025625, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3353:(@CGUID+2075, 47203, 0, 1, 1, -787.8962, 318.2828, 54.62511, 0.8840351, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3354:(@CGUID+2076, 47203, 0, 1, 1, -788.3602, 318.6632, 54.62511, 0.8840351, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3355:(@CGUID+2077, 47203, 0, 1, 1, -788.1282, 318.473, 54.77511, 0.7094951, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3356:(@CGUID+2078, 47203, 0, 1, 1, -787.5158, 318.7468, 54.62511, 4.025625, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3357:(@CGUID+2079, 47203, 0, 1, 1, -787.9798, 319.1272, 54.62511, 4.025625, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3358:(@CGUID+2080, 47203, 0, 1, 1, -788.228, 318.9427, 54.77511, 5.596425, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3359:(@CGUID+2081, 47203, 0, 1, 1, -787.648, 318.4672, 54.77511, 2.454825, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3364:(@CGUID+2086, 47204, 0, 1, 1, -682.4318, 282.3712, 48.95128, 2.816738, 120, 0, 0), -- Infested Bear (Area: Azurelode Mine) +3365:(@CGUID+2087, 47203, 0, 1, 1, -681.2429, 281.9707, 51.68038, 2.816738, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3366:(@CGUID+2088, 47203, 0, 1, 1, -681.6229, 281.7822, 51.53038, 5.958333, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3367:(@CGUID+2089, 47203, 0, 1, 1, -681.4314, 282.3508, 51.53038, 5.958333, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3368:(@CGUID+2090, 47203, 0, 1, 1, -681.5272, 282.0665, 51.68038, 5.783793, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3369:(@CGUID+2091, 47203, 0, 1, 1, -681.0543, 281.5907, 51.53038, 2.816738, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3370:(@CGUID+2092, 47203, 0, 1, 1, -680.8628, 282.1593, 51.53038, 2.816738, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3371:(@CGUID+2093, 47203, 0, 1, 1, -681.1232, 282.3261, 51.68038, 4.387537, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3372:(@CGUID+2094, 47203, 0, 1, 1, -681.3625, 281.6153, 51.68038, 1.245938, 120, 0, 0), -- Creeper Egg (Area: Azurelode Mine) +3435:(@CGUID+2157, 47204, 0, 1, 1, -692.9782, 362.038, 61.96234, 4.127269, 120, 0, 0), -- Infested Bear (Area: 0) +3436:(@CGUID+2158, 47203, 0, 1, 1, -692.2853, 363.0839, 64.68867, 4.127269, 120, 0, 0), -- Creeper Egg (Area: 0) +3437:(@CGUID+2159, 47203, 0, 1, 1, -692.2009, 362.6681, 64.53867, 0.9856787, 120, 0, 0), -- Creeper Egg (Area: 0) +3438:(@CGUID+2160, 47203, 0, 1, 1, -692.701, 362.9995, 64.53867, 0.9856787, 120, 0, 0), -- Creeper Egg (Area: 0) +3439:(@CGUID+2161, 47203, 0, 1, 1, -692.451, 362.8338, 64.68867, 0.8111386, 120, 0, 0), -- Creeper Egg (Area: 0) +3440:(@CGUID+2162, 47203, 0, 1, 1, -691.8695, 363.1683, 64.53867, 4.127269, 120, 0, 0), -- Creeper Egg (Area: 0) +3441:(@CGUID+2163, 47203, 0, 1, 1, -692.3697, 363.4997, 64.53867, 4.127269, 120, 0, 0), -- Creeper Egg (Area: 0) +3442:(@CGUID+2164, 47203, 0, 1, 1, -692.5979, 363.291, 64.68867, 5.698069, 120, 0, 0), -- Creeper Egg (Area: 0) +3443:(@CGUID+2165, 47203, 0, 1, 1, -691.9727, 362.8768, 64.68867, 2.556469, 120, 0, 0), -- Creeper Egg (Area: 0) +3444:(@CGUID+2166, 47204, 0, 1, 1, -723.3301, 322.3311, 48.96287, 2.171204, 120, 0, 0), -- Infested Bear (Area: 0) +3445:(@CGUID+2167, 47203, 0, 1, 1, -722.6213, 321.296, 51.69197, 2.171204, 120, 0, 0), -- Creeper Egg (Area: 0) +3446:(@CGUID+2168, 47203, 0, 1, 1, -723.0383, 321.374, 51.54197, 5.312799, 120, 0, 0), -- Creeper Egg (Area: 0) +3447:(@CGUID+2169, 47203, 0, 1, 1, -722.5433, 321.713, 51.54197, 5.312799, 120, 0, 0), -- Creeper Egg (Area: 0) +3448:(@CGUID+2170, 47203, 0, 1, 1, -722.7908, 321.5435, 51.69197, 5.138259, 120, 0, 0), -- Creeper Egg (Area: 0) +3449:(@CGUID+2171, 47203, 0, 1, 1, -722.6993, 320.8789, 51.54197, 2.171204, 120, 0, 0), -- Creeper Egg (Area: 0) +3450:(@CGUID+2172, 47203, 0, 1, 1, -722.2043, 321.2179, 51.54197, 2.171204, 120, 0, 0), -- Creeper Egg (Area: 0) +3451:(@CGUID+2173, 47203, 0, 1, 1, -722.3119, 321.5078, 51.69197, 3.742004, 120, 0, 0), -- Creeper Egg (Area: 0) +3452:(@CGUID+2174, 47203, 0, 1, 1, -722.9307, 321.0841, 51.69197, 0.6004043, 120, 0, 0), -- Creeper Egg (Area: 0) +3455:(@CGUID+2177, 47204, 0, 1, 1, -711.852, 413.797, 74.94383, 1.448623, 120, 0, 0), -- Infested Bear (Area: 0) +3456:(@CGUID+2178, 47203, 0, 1, 1, -712.0049, 412.5518, 77.67294, 1.448623, 120, 0, 0), -- Creeper Egg (Area: 0) +3457:(@CGUID+2179, 47203, 0, 1, 1, -712.2661, 412.8861, 77.52293, 4.590219, 120, 0, 0), -- Creeper Egg (Area: 0) +3458:(@CGUID+2180, 47203, 0, 1, 1, -711.6705, 412.813, 77.52293, 4.590219, 120, 0, 0), -- Creeper Egg (Area: 0) +3459:(@CGUID+2181, 47203, 0, 1, 1, -711.9683, 412.8495, 77.67294, 4.415679, 120, 0, 0), -- Creeper Egg (Area: 0) +3460:(@CGUID+2182, 47203, 0, 1, 1, -712.3392, 412.2906, 77.52293, 1.448623, 120, 0, 0), -- Creeper Egg (Area: 0) +3461:(@CGUID+2183, 47203, 0, 1, 1, -711.7437, 412.2174, 77.52293, 1.448623, 120, 0, 0), -- Creeper Egg (Area: 0) +3462:(@CGUID+2184, 47203, 0, 1, 1, -711.6327, 412.506, 77.67294, 3.019423, 120, 0, 0), -- Creeper Egg (Area: 0) +3463:(@CGUID+2185, 47203, 0, 1, 1, -712.3771, 412.5974, 77.67294, 6.161009, 120, 0, 0), -- Creeper Egg (Area: 0) +3466:(@CGUID+2188, 47204, 0, 1, 1, -747.4617, 407.7327, 72.22845, 2.430848, 120, 0, 0), -- Infested Bear (Area: 0) +3467:(@CGUID+2189, 47203, 0, 1, 1, -746.5109, 406.9142, 74.89583, 2.430848, 120, 0, 0), -- Creeper Egg (Area: 0) +3468:(@CGUID+2190, 47203, 0, 1, 1, -746.9339, 406.8826, 74.74583, 5.572443, 120, 0, 0), -- Creeper Egg (Area: 0) +3469:(@CGUID+2191, 47203, 0, 1, 1, -746.5425, 407.3373, 74.74583, 5.572443, 120, 0, 0), -- Creeper Egg (Area: 0) +3470:(@CGUID+2192, 47203, 0, 1, 1, -746.7382, 407.11, 74.89583, 5.397903, 120, 0, 0), -- Creeper Egg (Area: 0) +3471:(@CGUID+2193, 47203, 0, 1, 1, -746.4792, 406.4911, 74.74583, 2.430848, 120, 0, 0), -- Creeper Egg (Area: 0) +3472:(@CGUID+2194, 47203, 0, 1, 1, -746.0878, 406.9459, 74.74583, 2.430848, 120, 0, 0), -- Creeper Egg (Area: 0) +3473:(@CGUID+2195, 47203, 0, 1, 1, -746.2662, 407.1984, 74.89583, 4.001648, 120, 0, 0), -- Creeper Egg (Area: 0) +3474:(@CGUID+2196, 47203, 0, 1, 1, -746.7555, 406.63, 74.89583, 0.8600478, 120, 0, 0), -- Creeper Egg (Area: 0) +3476:(@CGUID+2198, 47204, 0, 1, 1, -791.8065, 361.1562, 60.70994, 2.947737, 120, 0, 0), -- Infested Bear (Area: 0) +3477:(@CGUID+2199, 47203, 0, 1, 1, -790.5754, 360.9145, 63.43904, 2.947737, 120, 0, 0), -- Creeper Egg (Area: 0) +3478:(@CGUID+2200, 47203, 0, 1, 1, -790.9276, 360.6779, 63.28904, 6.089333, 120, 0, 0), -- Creeper Egg (Area: 0) +3479:(@CGUID+2201, 47203, 0, 1, 1, -790.812, 361.2666, 63.28904, 6.089333, 120, 0, 0), -- Creeper Egg (Area: 0) +3480:(@CGUID+2202, 47203, 0, 1, 1, -790.8698, 360.9723, 63.43904, 5.914793, 120, 0, 0), -- Creeper Egg (Area: 0) +3481:(@CGUID+2203, 47203, 0, 1, 1, -790.3388, 360.5623, 63.28904, 2.947737, 120, 0, 0), -- Creeper Egg (Area: 0) +3482:(@CGUID+2204, 47203, 0, 1, 1, -790.2233, 361.1511, 63.28904, 2.947737, 120, 0, 0), -- Creeper Egg (Area: 0) +3483:(@CGUID+2205, 47203, 0, 1, 1, -790.5032, 361.2824, 63.43904, 4.518537, 120, 0, 0), -- Creeper Egg (Area: 0) +3484:(@CGUID+2206, 47203, 0, 1, 1, -790.6476, 360.5465, 63.43904, 1.376937, 120, 0, 0), -- Creeper Egg (Area: 0) +3798:(@CGUID+2520, 1412, 0, 1, 1, 47.61954, 499.8362, 42.0326, 6.125181, 120, 0, 0), -- Squirrel (Area: Dalaran Crater) diff --git a/src/server/scripts/Custom/viano_adventurers.cpp b/src/server/scripts/Custom/viano_adventurers.cpp index 3e7f50df7b..cd28a8c62b 100644 --- a/src/server/scripts/Custom/viano_adventurers.cpp +++ b/src/server/scripts/Custom/viano_adventurers.cpp @@ -9,6 +9,7 @@ #include "Player.h" #include "TemporarySummon.h" #include "MotionMaster.h" +#include "Log.h" namespace VianoAdventurers { @@ -16,6 +17,24 @@ namespace VianoAdventurers static constexpr float FOLLOW_ANGLE = 3.14159265f; static constexpr float TELEPORT_DISTANCE = 45.0f; static constexpr uint32 UPDATE_INTERVAL = 500; + static constexpr uint32 DIAGNOSTIC_INTERVAL = 2000; + + // VIANO_DD_PROFILE_V1_5 + enum AdventurerSpells : uint32 + { + SPELL_ADVENTURER_MORTAL_STRIKE = 65926, + SPELL_ADVENTURER_OVERPOWER = 65924, + SPELL_ADVENTURER_BLADESTORM = 65947 + }; + + enum AdventurerEvents : uint32 + { + EVENT_ADVENTURER_MORTAL_STRIKE = 1, + EVENT_ADVENTURER_OVERPOWER, + EVENT_ADVENTURER_BLADESTORM + }; + + // VIANO_AI_DIAGNOSTICS_V1 class npc_horde_adventurer_melee : public CreatureScript { @@ -27,8 +46,10 @@ namespace VianoAdventurers npc_horde_adventurer_meleeAI(Creature* creature) : ScriptedAI(creature) { } ObjectGuid ownerGuid; + EventMap combatEvents; uint32 updateTimer = 0; - + uint32 diagnosticTimer = 0; + uint32 recoveryTimer = 1000; Player* GetOwnerPlayer() const { if (!ownerGuid) @@ -45,6 +66,121 @@ namespace VianoAdventurers me->GetMotionMaster()->MoveFollow(owner, FOLLOW_DISTANCE, FOLLOW_ANGLE); } + void ResetCombatEvents() + { + combatEvents.Reset(); + + combatEvents.ScheduleEvent(EVENT_ADVENTURER_MORTAL_STRIKE, 2 * IN_MILLISECONDS); + combatEvents.ScheduleEvent(EVENT_ADVENTURER_OVERPOWER, 5 * IN_MILLISECONDS); + combatEvents.ScheduleEvent(EVENT_ADVENTURER_BLADESTORM, 12 * IN_MILLISECONDS); + } + + void HandleCombatActions(uint32 diff) + { + Unit* victim = me->GetVictim(); + if (!victim || !victim->IsAlive()) + return; + + combatEvents.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + if (uint32 eventId = combatEvents.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ADVENTURER_MORTAL_STRIKE: + TC_LOG_INFO("scripts", "[VianoAI] cast Mortal Strike: target='%s'(%u)", + UnitName(victim), UnitEntry(victim)); + DoCastVictim(SPELL_ADVENTURER_MORTAL_STRIKE); + combatEvents.ScheduleEvent(EVENT_ADVENTURER_MORTAL_STRIKE, + urand(6 * IN_MILLISECONDS, 8 * IN_MILLISECONDS)); + return; + + case EVENT_ADVENTURER_OVERPOWER: + TC_LOG_INFO("scripts", "[VianoAI] cast Overpower: target='%s'(%u)", + UnitName(victim), UnitEntry(victim)); + DoCastVictim(SPELL_ADVENTURER_OVERPOWER); + combatEvents.ScheduleEvent(EVENT_ADVENTURER_OVERPOWER, + urand(10 * IN_MILLISECONDS, 14 * IN_MILLISECONDS)); + return; + + case EVENT_ADVENTURER_BLADESTORM: + TC_LOG_INFO("scripts", "[VianoAI] cast Bladestorm: target='%s'(%u)", + UnitName(victim), UnitEntry(victim)); + DoCastVictim(SPELL_ADVENTURER_BLADESTORM); + combatEvents.ScheduleEvent(EVENT_ADVENTURER_BLADESTORM, + urand(30 * IN_MILLISECONDS, 45 * IN_MILLISECONDS)); + return; + + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + void HandleOutOfCombatRecovery(uint32 diff) + { + if (!me->IsAlive()) + { + recoveryTimer = 1000; + return; + } + + // Keine künstliche Regeneration während eines Kampfes. + if (me->IsInCombat()) + { + recoveryTimer = 1000; + return; + } + + if (recoveryTimer > diff) + { + recoveryTimer -= diff; + return; + } + + recoveryTimer = 1000; + + // 10 % der maximalen Lebenspunkte pro Sekunde. + uint32 maxHealth = me->GetMaxHealth(); + + if (me->GetHealth() < maxHealth) + { + uint32 healthGain = maxHealth / 10; + + if (healthGain == 0) + healthGain = 1; + + uint32 newHealth = me->GetHealth() + healthGain; + + if (newHealth > maxHealth) + newHealth = maxHealth; + + me->SetHealth(newHealth); + } + + // 10 % des maximalen Manas pro Sekunde. + uint32 maxMana = me->GetMaxPower(POWER_MANA); + + if (maxMana > 0 && me->GetPower(POWER_MANA) < maxMana) + { + uint32 manaGain = maxMana / 10; + + if (manaGain == 0) + manaGain = 1; + + uint32 newMana = me->GetPower(POWER_MANA) + manaGain; + + if (newMana > maxMana) + newMana = maxMana; + + me->SetPower(POWER_MANA, newMana); + } +} + void InitializeAI() override { ScriptedAI::InitializeAI(); @@ -71,12 +207,40 @@ namespace VianoAdventurers me->SetLevel(owner->getLevel()); me->UpdateLevelDependantStats(); - me->SetReactState(REACT_PASSIVE); + + static constexpr uint32 HORDE_ADVENTURER_MODELS[] = + { + 30063, + 30064, + 30065, + 30066 + }; + uint32 displayId = HORDE_ADVENTURER_MODELS[urand(0, 3)]; + + me->SetDisplayId(displayId, true); + + TC_LOG_INFO("scripts","[VianoAI] Horde adventurer display selected: %u", displayId); + + // REACT_PASSIVE lets AttackStart() briefly set a victim, but the + // core subsequently drops that victim again. We already suppress + // autonomous proximity aggro in MoveInLineOfSight(), so DEFENSIVE + // keeps an explicitly assigned assist target without making the + // adventurer independently pull nearby creatures. + me->SetReactState(REACT_DEFENSIVE); + + TC_LOG_INFO("scripts", + "[VianoAI] initialized me='%s' entry=%u owner='%s' ownerGuid=%s meFaction=%u ownerFaction=%u level=%u", + me->GetName().c_str(), me->GetEntry(), owner->GetName().c_str(), ownerGuid.ToString().c_str(), + me->GetFaction(), owner->GetFaction(), uint32(me->getLevel())); + + ResetCombatEvents(); FollowOwner(owner); } void Reset() override { + ResetCombatEvents(); + if (Player* owner = GetOwnerPlayer()) FollowOwner(owner); } @@ -85,30 +249,147 @@ namespace VianoAdventurers { } - Unit* SelectAssistTarget(Player* owner) + char const* UnitName(Unit* unit) const + { + return unit ? unit->GetName().c_str() : ""; + } + + uint32 UnitEntry(Unit* unit) const + { + return unit ? unit->GetEntry() : 0; + } + + bool IsValidCandidate(Unit* unit) const + { + return unit && unit->IsAlive() && me->IsValidAttackTarget(unit); + } + + void LogDiagnostics(Player* owner) { if (!owner) - return nullptr; + return; - if (Unit* target = owner->GetVictim()) - if (target->IsAlive() && me->IsValidAttackTarget(target)) - return target; + Unit* ownerVictim = owner->GetVictim(); + Unit* selected = owner->GetSelectedUnit(); + Unit* meVictim = me->GetVictim(); + Unit* firstOwnerAttacker = nullptr; for (Unit* attacker : owner->getAttackers()) - if (attacker && attacker->IsAlive() && me->IsValidAttackTarget(attacker)) - return attacker; + { + if (attacker) + { + firstOwnerAttacker = attacker; + break; + } + } - return nullptr; + Unit* firstMeAttacker = nullptr; + for (Unit* attacker : me->getAttackers()) + { + if (attacker) + { + firstMeAttacker = attacker; + break; + } + } + + TC_LOG_INFO("scripts", + "[VianoAI] me='%s' entry=%u lvl=%u faction=%u react=%u alive=%u combat=%u hp=%u/%u victim='%s'(%u) attackers=%u distance=%.2f", + me->GetName().c_str(), me->GetEntry(), uint32(me->getLevel()), me->GetFaction(), uint32(me->GetReactState()), + me->IsAlive() ? 1u : 0u, me->IsInCombat() ? 1u : 0u, me->GetHealth(), me->GetMaxHealth(), + UnitName(meVictim), UnitEntry(meVictim), uint32(me->getAttackers().size()), me->GetDistance(owner)); + + TC_LOG_INFO("scripts", + "[VianoAI] owner='%s' lvl=%u faction=%u alive=%u combat=%u victim='%s'(%u) selected='%s'(%u) attackers=%u", + owner->GetName().c_str(), uint32(owner->getLevel()), owner->GetFaction(), owner->IsAlive() ? 1u : 0u, + owner->IsInCombat() ? 1u : 0u, UnitName(ownerVictim), UnitEntry(ownerVictim), UnitName(selected), UnitEntry(selected), + uint32(owner->getAttackers().size())); + + if (ownerVictim) + TC_LOG_INFO("scripts", "[VianoAI] ownerVictim='%s' entry=%u faction=%u validForBot=%u botCanAttack=%u ownerCanAttack=%u victim='%s'(%u)", + ownerVictim->GetName().c_str(), ownerVictim->GetEntry(), ownerVictim->GetFaction(), IsValidCandidate(ownerVictim) ? 1u : 0u, + me->IsValidAttackTarget(ownerVictim) ? 1u : 0u, owner->IsValidAttackTarget(ownerVictim) ? 1u : 0u, + UnitName(ownerVictim->GetVictim()), UnitEntry(ownerVictim->GetVictim())); + + if (selected) + TC_LOG_INFO("scripts", "[VianoAI] selected='%s' entry=%u faction=%u validForBot=%u botCanAttack=%u ownerCanAttack=%u victim='%s'(%u)", + selected->GetName().c_str(), selected->GetEntry(), selected->GetFaction(), IsValidCandidate(selected) ? 1u : 0u, + me->IsValidAttackTarget(selected) ? 1u : 0u, owner->IsValidAttackTarget(selected) ? 1u : 0u, + UnitName(selected->GetVictim()), UnitEntry(selected->GetVictim())); + + if (firstOwnerAttacker) + TC_LOG_INFO("scripts", "[VianoAI] firstOwnerAttacker='%s' entry=%u faction=%u validForBot=%u botCanAttack=%u ownerCanAttack=%u victim='%s'(%u)", + firstOwnerAttacker->GetName().c_str(), firstOwnerAttacker->GetEntry(), firstOwnerAttacker->GetFaction(), IsValidCandidate(firstOwnerAttacker) ? 1u : 0u, + me->IsValidAttackTarget(firstOwnerAttacker) ? 1u : 0u, owner->IsValidAttackTarget(firstOwnerAttacker) ? 1u : 0u, + UnitName(firstOwnerAttacker->GetVictim()), UnitEntry(firstOwnerAttacker->GetVictim())); + + if (firstMeAttacker) + TC_LOG_INFO("scripts", "[VianoAI] firstMeAttacker='%s' entry=%u faction=%u victim='%s'(%u)", + firstMeAttacker->GetName().c_str(), firstMeAttacker->GetEntry(), firstMeAttacker->GetFaction(), + UnitName(firstMeAttacker->GetVictim()), UnitEntry(firstMeAttacker->GetVictim())); } + Unit* SelectAssistTarget(Player* owner) +{ + if (!owner) + return nullptr; + + // 1. Ein aktives Ziel des Besitzers ist eine ausdrückliche + // Zielanweisung und darf das aktuelle Bot-Ziel überschreiben. + if (Unit* target = owner->GetVictim()) + if (IsValidCandidate(target)) + return target; + + // GetVictim() ist beim Spieler nicht immer zuverlässig gesetzt. + // Während eines bereits laufenden Kampfes darf deshalb auch ein + // bewusst ausgewähltes lebendes Feindziel als Anweisung gelten. + // Reines Anwählen außerhalb des Kampfes darf weiterhin NICHT pullen. + if (owner->IsInCombat()) + { + if (Unit* target = owner->GetSelectedUnit()) + if (IsValidCandidate(target)) + return target; + } + + // 2. Sobald der Bot selbst einen gültigen Gegner bekämpft, + // hält er an diesem Ziel fest. ESC, eine Leiche als Target oder + // fehlendes Spielertarget beendet den Kampf dadurch nicht mehr. + if (Unit* target = me->GetVictim()) + if (IsValidCandidate(target)) + return target; + + // 3. Falls das bisherige Ziel tot/ungültig ist, helfen wir dem + // Besitzer gegen einen Gegner, der ihn bereits angreift. + for (Unit* attacker : owner->getAttackers()) + if (IsValidCandidate(attacker)) + return attacker; + + // 4. Danach übernimmt der Bot einen Gegner, der ihn selbst angreift. + // Besonders wichtig, wenn sein vorheriges Ziel gerade gestorben ist. + for (Unit* attacker : me->getAttackers()) + if (IsValidCandidate(attacker)) + return attacker; + + return nullptr; +} + void UpdateAI(uint32 diff) override { + HandleOutOfCombatRecovery(diff); + if (diagnosticTimer > diff) + diagnosticTimer -= diff; + else + diagnosticTimer = 0; + if (updateTimer > diff) { updateTimer -= diff; - if (UpdateVictim()) - DoMeleeAttackIfReady(); + // VIANO_TARGET_CONTROL_V1_4 + // Keep the explicitly assigned victim. UpdateVictim() may + // select another creature from the threat list. + if (me->GetVictim()) + HandleCombatActions(diff); return; } @@ -118,10 +399,17 @@ namespace VianoAdventurers Player* owner = GetOwnerPlayer(); if (!owner || !owner->IsInWorld() || !me->IsInMap(owner)) { + TC_LOG_INFO("scripts", "[VianoAI] despawn: owner invalid or not on same map (ownerFound=%u)", owner ? 1u : 0u); me->DespawnOrUnsummon(); return; } + if (diagnosticTimer == 0) + { + diagnosticTimer = DIAGNOSTIC_INTERVAL; + LogDiagnostics(owner); + } + if (me->getLevel() != owner->getLevel()) { me->SetLevel(owner->getLevel()); @@ -149,20 +437,29 @@ namespace VianoAdventurers if (desiredTarget) { if (me->GetVictim() != desiredTarget) + { + TC_LOG_INFO("scripts", + "[VianoAI] AttackStart requested: target='%s' entry=%u targetFaction=%u valid=%u meCombatBefore=%u", + desiredTarget->GetName().c_str(), desiredTarget->GetEntry(), desiredTarget->GetFaction(), + me->IsValidAttackTarget(desiredTarget) ? 1u : 0u, me->IsInCombat() ? 1u : 0u); + AttackStart(desiredTarget); + + Unit* afterVictim = me->GetVictim(); + TC_LOG_INFO("scripts", "[VianoAI] AttackStart result: meCombatAfter=%u victim='%s'(%u)", + me->IsInCombat() ? 1u : 0u, UnitName(afterVictim), UnitEntry(afterVictim)); + } } - else if (me->IsInCombat()) - { - me->CombatStop(true); - FollowOwner(owner); - } - else if (!me->GetVictim()) + else if (!me->IsInCombat() && !me->GetVictim()) { FollowOwner(owner); } - if (UpdateVictim()) - DoMeleeAttackIfReady(); + // VIANO_TARGET_CONTROL_V1_4 + // Keep the explicitly assigned victim. UpdateVictim() may + // select another creature from the threat list. + if (me->GetVictim()) + HandleCombatActions(diff); } }; diff --git a/src/server/scripts/EasternKingdoms/zone_hillsbrad_foothills.cpp b/src/server/scripts/EasternKingdoms/zone_hillsbrad_foothills.cpp index 8ae0b9663c..e1a1768223 100644 --- a/src/server/scripts/EasternKingdoms/zone_hillsbrad_foothills.cpp +++ b/src/server/scripts/EasternKingdoms/zone_hillsbrad_foothills.cpp @@ -25,6 +25,7 @@ #include "Player.h" #include "PhasingHandler.h" #include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "SpellScript.h" #include "SpellMgr.h" #include "SpellHistory.h" @@ -1296,6 +1297,506 @@ class spell_brazie_spit : public SpellScript OnObjectAreaTargetSelect.Register(&spell_brazie_spit::FilterTargets, EFFECT_ALL, TARGET_UNIT_CONE_CASTER_TO_DEST_ENEMY); } }; + +// WOW-PRIVATE-SERVER PATCH: Welcome to the Machine (28096) +// +// Restores the missing Hillsbrad quest scene around High Executor Darthalia's +// skeletal steed. Spoken lines are provided through creature_text rows that +// reference the original BroadcastText IDs, so existing locales remain usable. +enum WelcomeToTheMachine +{ + QUEST_WELCOME_TO_THE_MACHINE = 28096, + + NPC_HIGH_EXECUTOR_DARTHALIA = 2215, + NPC_JOHNNY_AWESOME = 47442, + NPC_KINGSLAYER_ORKUS = 47443, + NPC_DUMASS = 47444, + NPC_SKELETAL_STEED = 47445, + + DATA_WELCOME_STAGE = 1, + + STAGE_IDLE = 0, + STAGE_DUMASS_GOSSIP = 1, + STAGE_ORKUS_GOSSIP = 2, + STAGE_JOHNNY_GOSSIP = 3, + STAGE_FINISHED = 4, + + ACTION_DUMASS_DONE = 1, + ACTION_ORKUS_DONE = 2, + ACTION_JOHNNY_DONE = 3, + + GOSSIP_ACTION_DUMASS_1 = GOSSIP_ACTION_INFO_DEF + 101, + GOSSIP_ACTION_DUMASS_2 = GOSSIP_ACTION_INFO_DEF + 102, + GOSSIP_ACTION_ORKUS_1 = GOSSIP_ACTION_INFO_DEF + 103, + GOSSIP_ACTION_ORKUS_2 = GOSSIP_ACTION_INFO_DEF + 104, + GOSSIP_ACTION_ORKUS_3 = GOSSIP_ACTION_INFO_DEF + 105, + GOSSIP_ACTION_JOHNNY_1 = GOSSIP_ACTION_INFO_DEF + 106, + GOSSIP_ACTION_JOHNNY_2 = GOSSIP_ACTION_INFO_DEF + 107, + GOSSIP_ACTION_JOHNNY_3 = GOSSIP_ACTION_INFO_DEF + 108, + + GOSSIP_MENU_DUMASS_1 = 12273, + GOSSIP_MENU_DUMASS_2 = 12272, + GOSSIP_MENU_ORKUS_1 = 12276, + GOSSIP_MENU_ORKUS_2 = 12275, + GOSSIP_MENU_ORKUS_3 = 12274, + GOSSIP_MENU_JOHNNY_1 = 12279, + GOSSIP_MENU_JOHNNY_2 = 12278, + GOSSIP_MENU_JOHNNY_3 = 12277, + + SAY_DARTHALIA_STAND_TALL = 50, + SAY_DARTHALIA_FIRST_ONE = 51, + SAY_DARTHALIA_DUMASS_COMMENT = 52, + SAY_DARTHALIA_ORKUS_WARNING = 53, + SAY_DARTHALIA_ORKUS_COMMENT = 54, + SAY_DARTHALIA_JOHNNY_WARNING = 55, + + SAY_DUMASS_HELLO = 50, + SAY_DUMASS_NEW = 51, + SAY_DUMASS_WAIT = 52, + SAY_DUMASS_NORTH = 53, + + SAY_ORKUS_LOKTAR = 50, + SAY_ORKUS_PUNY = 51, + SAY_ORKUS_WHAT_HAVE_YOU_GOT = 52, + SAY_ORKUS_BOAST = 53, + SAY_ORKUS_RISK = 54, + SAY_ORKUS_WILL_DO_IT = 55, + SAY_ORKUS_FAREWELL = 56, + + SAY_JOHNNY_ARRIVED = 50, + SAY_JOHNNY_HEIRLOOMS = 51, + SAY_JOHNNY_WHAT_ELSE = 52, + SAY_JOHNNY_ONE_QUEST = 53, + SAY_JOHNNY_FAREWELL = 54 +}; + +enum WelcomeToTheMachineEvents +{ + EVENT_WELCOME_DARTHALIA_1 = 1, + EVENT_WELCOME_DARTHALIA_2, + EVENT_WELCOME_SUMMON_DUMASS, + EVENT_WELCOME_DUMASS_1, + EVENT_WELCOME_DUMASS_2, + EVENT_WELCOME_ENABLE_DUMASS, + EVENT_WELCOME_DARTHALIA_DUMASS_COMMENT, + EVENT_WELCOME_DARTHALIA_ORKUS_WARNING, + EVENT_WELCOME_SUMMON_ORKUS, + EVENT_WELCOME_ORKUS_1, + EVENT_WELCOME_ORKUS_2, + EVENT_WELCOME_ORKUS_3, + EVENT_WELCOME_ORKUS_4, + EVENT_WELCOME_ENABLE_ORKUS, + EVENT_WELCOME_DARTHALIA_ORKUS_COMMENT, + EVENT_WELCOME_DARTHALIA_JOHNNY_WARNING, + EVENT_WELCOME_SUMMON_JOHNNY, + EVENT_WELCOME_JOHNNY_1, + EVENT_WELCOME_JOHNNY_2, + EVENT_WELCOME_ENABLE_JOHNNY +}; + +struct npc_hillsbrad_welcome_steed : public VehicleAI +{ + npc_hillsbrad_welcome_steed(Creature* creature) + : VehicleAI(creature), _summons(me), _stage(STAGE_IDLE) { } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + } + + void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override + { + Player* player = passenger ? passenger->ToPlayer() : nullptr; + if (!player) + return; + + if (!apply) + { + ResetScene(); + return; + } + + if (player->GetQuestStatus(QUEST_WELCOME_TO_THE_MACHINE) != QUEST_STATUS_INCOMPLETE) + return; + + _playerGuid = player->GetGUID(); + _stage = STAGE_IDLE; + _events.Reset(); + _summons.DespawnAll(); + + // WOW-PRIVATE-SERVER PATCH: 28096 scene pacing v2 + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_1, 500ms); + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_2, 6s); + _events.ScheduleEvent(EVENT_WELCOME_SUMMON_DUMASS, 10s); + _events.ScheduleEvent(EVENT_WELCOME_DUMASS_1, 14s); + _events.ScheduleEvent(EVENT_WELCOME_DUMASS_2, 18s); + _events.ScheduleEvent(EVENT_WELCOME_ENABLE_DUMASS, 28s); + } + + uint32 GetData(uint32 type) const override + { + if (type == DATA_WELCOME_STAGE) + return _stage; + + return 0; + } + + void DoAction(int32 action) override + { + Player* player = GetScenePlayer(); + if (!player || player->GetQuestStatus(QUEST_WELCOME_TO_THE_MACHINE) != QUEST_STATUS_INCOMPLETE) + return; + + switch (action) + { + case ACTION_DUMASS_DONE: + if (_stage != STAGE_DUMASS_GOSSIP) + return; + + _stage = STAGE_IDLE; + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_DUMASS_COMMENT, 4s); + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_ORKUS_WARNING, 10s); + _events.ScheduleEvent(EVENT_WELCOME_SUMMON_ORKUS, 15s); + _events.ScheduleEvent(EVENT_WELCOME_ORKUS_1, 19s); + _events.ScheduleEvent(EVENT_WELCOME_ORKUS_2, 24s); + _events.ScheduleEvent(EVENT_WELCOME_ORKUS_3, 30s); + _events.ScheduleEvent(EVENT_WELCOME_ORKUS_4, 36s); + _events.ScheduleEvent(EVENT_WELCOME_ENABLE_ORKUS, 50s); + break; + + case ACTION_ORKUS_DONE: + if (_stage != STAGE_ORKUS_GOSSIP) + return; + + _stage = STAGE_IDLE; + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_ORKUS_COMMENT, 4s); + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_JOHNNY_WARNING, 10s); + _events.ScheduleEvent(EVENT_WELCOME_SUMMON_JOHNNY, 15s); + _events.ScheduleEvent(EVENT_WELCOME_JOHNNY_1, 19s); + _events.ScheduleEvent(EVENT_WELCOME_JOHNNY_2, 25s); + _events.ScheduleEvent(EVENT_WELCOME_ENABLE_JOHNNY, 39s); + break; + + case ACTION_JOHNNY_DONE: + if (_stage == STAGE_JOHNNY_GOSSIP) + _stage = STAGE_FINISHED; + break; + + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + Player* player = GetScenePlayer(); + if (!player || player->GetQuestStatus(QUEST_WELCOME_TO_THE_MACHINE) != QUEST_STATUS_INCOMPLETE) + { + ResetScene(); + return; + } + + switch (eventId) + { + case EVENT_WELCOME_DARTHALIA_1: TalkDarthalia(SAY_DARTHALIA_STAND_TALL, player); break; + case EVENT_WELCOME_DARTHALIA_2: TalkDarthalia(SAY_DARTHALIA_FIRST_ONE, player); break; + case EVENT_WELCOME_SUMMON_DUMASS: SummonActor(NPC_DUMASS); break; + case EVENT_WELCOME_DUMASS_1: TalkActor(NPC_DUMASS, SAY_DUMASS_HELLO, player); break; + case EVENT_WELCOME_DUMASS_2: TalkActor(NPC_DUMASS, SAY_DUMASS_NEW, player); break; + case EVENT_WELCOME_ENABLE_DUMASS: + _stage = STAGE_DUMASS_GOSSIP; + OpenActorGossip(player, NPC_DUMASS, GOSSIP_MENU_DUMASS_1, GOSSIP_ACTION_DUMASS_1); + break; + + case EVENT_WELCOME_DARTHALIA_DUMASS_COMMENT: TalkDarthalia(SAY_DARTHALIA_DUMASS_COMMENT, player); break; + case EVENT_WELCOME_DARTHALIA_ORKUS_WARNING: TalkDarthalia(SAY_DARTHALIA_ORKUS_WARNING, player); break; + case EVENT_WELCOME_SUMMON_ORKUS: SummonActor(NPC_KINGSLAYER_ORKUS); break; + case EVENT_WELCOME_ORKUS_1: TalkActor(NPC_KINGSLAYER_ORKUS, SAY_ORKUS_LOKTAR, player); break; + case EVENT_WELCOME_ORKUS_2: TalkActor(NPC_KINGSLAYER_ORKUS, SAY_ORKUS_PUNY, player); break; + case EVENT_WELCOME_ORKUS_3: TalkActor(NPC_KINGSLAYER_ORKUS, SAY_ORKUS_WHAT_HAVE_YOU_GOT, player); break; + case EVENT_WELCOME_ORKUS_4: TalkActor(NPC_KINGSLAYER_ORKUS, SAY_ORKUS_BOAST, player); break; + case EVENT_WELCOME_ENABLE_ORKUS: + _stage = STAGE_ORKUS_GOSSIP; + OpenActorGossip(player, NPC_KINGSLAYER_ORKUS, GOSSIP_MENU_ORKUS_1, GOSSIP_ACTION_ORKUS_1); + break; + + case EVENT_WELCOME_DARTHALIA_ORKUS_COMMENT: TalkDarthalia(SAY_DARTHALIA_ORKUS_COMMENT, player); break; + case EVENT_WELCOME_DARTHALIA_JOHNNY_WARNING: TalkDarthalia(SAY_DARTHALIA_JOHNNY_WARNING, player); break; + case EVENT_WELCOME_SUMMON_JOHNNY: SummonActor(NPC_JOHNNY_AWESOME); break; + case EVENT_WELCOME_JOHNNY_1: TalkActor(NPC_JOHNNY_AWESOME, SAY_JOHNNY_ARRIVED, player); break; + case EVENT_WELCOME_JOHNNY_2: TalkActor(NPC_JOHNNY_AWESOME, SAY_JOHNNY_HEIRLOOMS, player); break; + case EVENT_WELCOME_ENABLE_JOHNNY: + _stage = STAGE_JOHNNY_GOSSIP; + OpenActorGossip(player, NPC_JOHNNY_AWESOME, GOSSIP_MENU_JOHNNY_1, GOSSIP_ACTION_JOHNNY_1); + break; + default: break; + } + } + } + +private: + Player* GetScenePlayer() + { + return ObjectAccessor::GetPlayer(*me, _playerGuid); + } + + Creature* GetSceneActor(uint32 entry) + { + for (ObjectGuid const& guid : _summons) + if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + if (summon->GetEntry() == entry) + return summon; + + return nullptr; + } + + void SummonActor(uint32 entry) + { + if (GetSceneActor(entry)) + return; + + // Spawn the temporary adventurer far enough away to make the approach visible. + // We use the steed's facing direction so the repair remains independent from + // hard-coded map coordinates. + float const orientation = me->GetOrientation(); + float const spawnX = me->GetPositionX() + cos(orientation) * 20.0f; + float const spawnY = me->GetPositionY() + sin(orientation) * 20.0f; + float const targetX = me->GetPositionX() + cos(orientation) * 3.0f; + float const targetY = me->GetPositionY() + sin(orientation) * 3.0f; + float const z = me->GetPositionZ(); + + if (Creature* actor = me->SummonCreature(entry, spawnX, spawnY, z, orientation, TEMPSUMMON_MANUAL_DESPAWN)) + { + actor->SetReactState(REACT_PASSIVE); + actor->SetWalk(false); + + Position target; + target.Relocate(targetX, targetY, z, orientation); + actor->GetMotionMaster()->MovePoint(1, target, false); + } + } + + void TalkActor(uint32 entry, uint8 groupId, Player* player) + { + if (Creature* actor = GetSceneActor(entry)) + if (actor->IsAIEnabled()) + actor->AI()->Talk(groupId, player); + } + + void TalkDarthalia(uint8 groupId, Player* player) + { + if (Creature* darthalia = me->FindNearestCreature(NPC_HIGH_EXECUTOR_DARTHALIA, 40.0f, true)) + if (darthalia->IsAIEnabled()) + darthalia->AI()->Talk(groupId, player); + } + + void OpenActorGossip(Player* player, uint32 entry, uint32 menuId, uint32 action) + { + Creature* actor = GetSceneActor(entry); + if (!actor) + return; + + actor->SetFacingToObject(me); + ClearGossipMenuFor(player); + AddGossipItemFor(player, menuId, 0, GOSSIP_SENDER_MAIN, action); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, actor->GetGUID()); + } + + void ResetScene() + { + _events.Reset(); + _summons.DespawnAll(); + _playerGuid.Clear(); + _stage = STAGE_IDLE; + } + + EventMap _events; + SummonList _summons; + ObjectGuid _playerGuid; + uint8 _stage; +}; + +struct npc_hillsbrad_welcome_actor : public ScriptedAI +{ + npc_hillsbrad_welcome_actor(Creature* creature) : ScriptedAI(creature) { } + + bool GossipHello(Player* player) override + { + if (!IsValidScenePlayer(player)) + return false; + + Creature* vehicle = player->GetVehicleCreatureBase(); + if (!vehicle || !vehicle->IsAIEnabled()) + return false; + + uint32 stage = vehicle->AI()->GetData(DATA_WELCOME_STAGE); + + ClearGossipMenuFor(player); + + switch (me->GetEntry()) + { + case NPC_DUMASS: + if (stage != STAGE_DUMASS_GOSSIP) + return false; + + AddGossipItemFor(player, GOSSIP_MENU_DUMASS_1, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_DUMASS_1); + break; + + case NPC_KINGSLAYER_ORKUS: + if (stage != STAGE_ORKUS_GOSSIP) + return false; + + AddGossipItemFor(player, GOSSIP_MENU_ORKUS_1, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_ORKUS_1); + break; + + case NPC_JOHNNY_AWESOME: + if (stage != STAGE_JOHNNY_GOSSIP) + return false; + + AddGossipItemFor(player, GOSSIP_MENU_JOHNNY_1, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_JOHNNY_1); + break; + + default: + return false; + } + + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + } + + bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override + { + if (!IsValidScenePlayer(player)) + return false; + + Creature* vehicle = player->GetVehicleCreatureBase(); + if (!vehicle || !vehicle->IsAIEnabled()) + return false; + + uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId); + ClearGossipMenuFor(player); + + switch (action) + { + case GOSSIP_ACTION_DUMASS_1: + Talk(SAY_DUMASS_WAIT, player); + AddGossipItemFor(player, GOSSIP_MENU_DUMASS_2, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_DUMASS_2); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_DUMASS_2: + Talk(SAY_DUMASS_NORTH, player); + player->KilledMonsterCredit(NPC_DUMASS); + CloseGossipMenuFor(player); + me->DespawnOrUnsummon(6s); + vehicle->AI()->DoAction(ACTION_DUMASS_DONE); + return true; + + case GOSSIP_ACTION_ORKUS_1: + Talk(SAY_ORKUS_RISK, player); + AddGossipItemFor(player, GOSSIP_MENU_ORKUS_2, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_ORKUS_2); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_ORKUS_2: + Talk(SAY_ORKUS_WILL_DO_IT, player); + AddGossipItemFor(player, GOSSIP_MENU_ORKUS_3, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_ORKUS_3); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_ORKUS_3: + Talk(SAY_ORKUS_FAREWELL, player); + player->KilledMonsterCredit(NPC_KINGSLAYER_ORKUS); + CloseGossipMenuFor(player); + me->DespawnOrUnsummon(6s); + vehicle->AI()->DoAction(ACTION_ORKUS_DONE); + return true; + + case GOSSIP_ACTION_JOHNNY_1: + Talk(SAY_JOHNNY_WHAT_ELSE, player); + AddGossipItemFor(player, GOSSIP_MENU_JOHNNY_2, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_JOHNNY_2); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_JOHNNY_2: + Talk(SAY_JOHNNY_ONE_QUEST, player); + AddGossipItemFor(player, GOSSIP_MENU_JOHNNY_3, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_JOHNNY_3); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_JOHNNY_3: + Talk(SAY_JOHNNY_FAREWELL, player); + player->KilledMonsterCredit(NPC_JOHNNY_AWESOME); + CloseGossipMenuFor(player); + me->DespawnOrUnsummon(6s); + vehicle->AI()->DoAction(ACTION_JOHNNY_DONE); + return true; + + default: + return false; + } + } + +private: + bool IsValidScenePlayer(Player* player) const + { + if (!player || player->GetQuestStatus(QUEST_WELCOME_TO_THE_MACHINE) != QUEST_STATUS_INCOMPLETE) + return false; + + Creature* vehicle = player->GetVehicleCreatureBase(); + return vehicle && vehicle->GetEntry() == NPC_SKELETAL_STEED; + } +}; + +enum GloriousHarvest +{ + QUEST_GLORIOUS_HARVEST = 28114, + ITEM_CREEPER_EGG = 63029 +}; + +struct npc_hillsbrad_creeper_egg : public ScriptedAI +{ + npc_hillsbrad_creeper_egg(Creature* creature) : ScriptedAI(creature) { } + + void OnSpellClick(Unit* clicker, bool& result) override +{ + if (!result) + return; + + Player* player = clicker->ToPlayer(); + if (!player) + { + result = false; + return; + } + + if (player->GetQuestStatus(QUEST_GLORIOUS_HARVEST) != QUEST_STATUS_INCOMPLETE) + { + result = false; + return; + } + + // Wir erledigen die komplette Aktion selbst. + // Der SpellClick-Spell 89960 soll danach nicht mehr ausgeführt werden. + result = false; + + if (player->AddItem(ITEM_CREEPER_EGG, 1)) + me->DespawnOrUnsummon(); +} +}; + } void AddSC_hillsbrad_foothills() @@ -1306,6 +1807,9 @@ void AddSC_hillsbrad_foothills() RegisterCreatureAI(npc_brazie_spot); RegisterCreatureAI(npc_brazie_zombie); RegisterCreatureAI(npc_brazie_vehicle_notifier); + RegisterCreatureAI(npc_hillsbrad_welcome_steed); + RegisterCreatureAI(npc_hillsbrad_welcome_actor); + RegisterCreatureAI(npc_hillsbrad_creeper_egg); RegisterSpellScript(spell_brazie_summon_plant); RegisterSpellScript(spell_brazie_highlight); RegisterSpellScript(spell_brazie_create_random_seed_sack); diff --git a/src/server/scripts/EasternKingdoms/zone_hillsbrad_foothills.cpp.bak_welcome_scene_v2_20260921_172948 b/src/server/scripts/EasternKingdoms/zone_hillsbrad_foothills.cpp.bak_welcome_scene_v2_20260921_172948 new file mode 100644 index 0000000000..bf10e0206e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zone_hillsbrad_foothills.cpp.bak_welcome_scene_v2_20260921_172948 @@ -0,0 +1,1744 @@ +/* +* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ + +#include "ScriptMgr.h" +#include "CellImpl.h" +#include "CreatureAIImpl.h" +#include "CombatAI.h" +#include "GridNotifiersImpl.h" +#include "MotionMaster.h" +#include "ObjectAccessor.h" +#include "Player.h" +#include "PhasingHandler.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "SpellScript.h" +#include "SpellMgr.h" +#include "SpellHistory.h" +#include "TemporarySummon.h" +#include "Vehicle.h" + +namespace HillsbradFoothills +{ +enum PlansVsZombies +{ + // Quest related + QUEST_BASIC_BOTANY = 28733, + CREDIT_BASIC_BOTANY = 49189, + + QUEST_FLOWER_POWER = 28617, + CREDIT_FLOWER_POWER = 49542, + + // Brazie Vehicle + SPELL_PROGRESS_BAR = 92259, + SPELL_50_POWER = 91987, + SPELL_CREATE_LAWMOWER = 91680, + SPELL_CREATE_EMPTY_SPOT = 91676, + SPELL_CREATE_SPITTER_TARGET = 91988, + SPELL_CREATE_GOAL_STALKER = 91740, + SPELL_CREATE_BATTERY = 92816, + SPELL_CREATE_RANDOM_SUN_POWER = 91741, + SPELL_SPITTER_HIGHLIGHT = 92276, + SPELL_SUNFLOWER_HIGHLIGHT = 94032, + SPELL_EJECT_ALL_PASSENGERS = 68576, + + SPELL_PLANT_SPITTER = 91649, + SPELL_PLANT_SUNFLOWER = 91646, + SPELL_PLANT_FREEZYA = 92440, + + // Player Spells + SPELL_CREATE_BOTANISTS_VEHICLE = 91683, + SPELL_CREATE_ZOMBIE = 91739, + SPELL_CREATE_GHOUL = 91834, + SPELL_CREATE_RANDOM_FREEZYA_SACK = 92435, + SPELL_GET_FREEZYA_SEEDS = 92434, + + NPC_SPITTER_TARGET = 49385, + NPC_EMPTY_SPOT = 49190, + NPC_PLACE_IT_HERE = 51098, + NPC_SOLAR_POWER = 49194, + NPC_SPITTER = 49200, + NPC_SUNFLOWER = 49193, + NPC_ZOMBIE = 49209, + NPC_GHOUL = 49232, + NPC_FREEZYA_SEEDS = 49604, + NPC_FREEZYA = 49618, + NPC_GOAL_STALKER = 49210, + NPC_FERTILITIZE_O_TRON_2000 = 49192, + + // Empty Spot + SPELL_HEALTH_TRIGGER = 93006, + SPELL_VENOM_SPIT = 91748, + SPELL_SUNLIGHT = 93968, + SPELL_FREEZYA_BLAST = 92441, + + // Solar Power + SPELL_GAIN_SOLAR_POWER_SPELLCLICK = 91687, + SPELL_GAIN_SOLAR_POWER_ENERGIZE = 94068, + + // Zombie + SPELL_ZOMBIE_GROWL = 93961, + // SPELL_HEALTH_TRIGGER = 93006, + SPELL_LEAKING_GUTS = 93244, + SPELL_GHOUL_GROWL = 93962, + SPELL_BUCKET_HEAD = 93230, + SPELL_BUCKET = 93236, + + // Fertilitize-o-tron 2000 + SPELL_LAWNMOWER_STARTUP_SOUND = 93969, + SPELL_DAZED = 1604, + SPELL_PLAGUE_GAS = 92084, + + // Texts + SAY_ANNOUNCE_TUTORIAL_1 = 49559, + SAY_ANNOUNCE_TUTORIAL_2 = 49553, + SAY_ANNOUNCE_TUTORIAL_3 = 49558, + SAY_ANNOUNCE_TUTORIAL_4 = 49552, + SAY_ANNOUNCE_MASSIVE_WAVE = 49409, + SAY_ANNOUNCE_PLANT_SUNFLOWER = 49566, + SAY_ANNOUNCE_PLANT_MORE_SUNFLOWERS = 49567, + SAY_ANNOUNCE_DROPPED_SEED = 49685, + SAY_ANNOUNCE_LEVEL_1_COMPLETE = 49551, + + SAY_ANNOUNCE_GAINED_FREEZYA_SEEDS = 0, + SAY_ANNOUNCE_GAINED_STRANGLER_SEEDS = 1, + SAY_ANNOUNCE_ZOMBIES_ATE_BRAIN = 2, + + // Events + EVENT_SPITTER_HIGHLIGHT = 1, + EVENT_SUMMON_SOLAR_POWER = 2, + EVENT_CREATE_ZOMBIE = 3, + EVENT_MOVE_TO_GOAL_POSITION = 4, + EVENT_CHECK_VICTIM_STATE = 5, + EVENT_ANNOUNCE_GOOD_JOB = 6, + EVENT_ANNOUNCE_PLACING_SPITTERS = 7, + EVENT_ANNOUNCE_MASSIVE_WAVE = 8, + EVENT_ANNOUNCE_LEVEL_COMPLETED = 9, + EVENT_EJECT_PASSENGER = 10, + EVENT_SUNFLOWER_HIGHLIGHT = 11, + EVENT_ANNOUNCE_PLANT_MORE_FLOWERS = 12, + EVENT_SUNLIGHT = 13, + EVENT_CREATE_GHOUL = 14, + EVENT_KILL_LANE = 15, + EVENT_PLAGUE_GAS = 16, + + // Actions + ACTION_FIRST_SPITTER_PLANTED = 1, + ACTION_FIRST_SUNFLOWER_PLANTED = 2, + ACTION_ZOMBIE_DAMAGED = 3, + ACTION_ZOMBIE_DIED = 4, + ACTION_GHOUL_DAMAGED = 5, + ACTION_QUEST_FAILED = 6, + + // Misc + SEAT_0 = 0, + + MAX_TARGET_POSITIONS = 5, + MAX_EMPTY_SPOT_POSITIONS = 40, + CENTER_ZOMBIE_LANE_INDEX = 2, + + POINT_GOAL_STALKER = 1, + POINT_SPITTER_TARGET = 2, + + DATA_CURRENT_ENTRY = 1, + + PHASE_ID_QUEST = 365, + + // Levels + LEVEL_TUTORIAL = 0, + LEVEL_1 = 1 +}; + +Position const LawnMowerPositions[MAX_TARGET_POSITIONS] +{ + { -116.5816f, 237.6823f, 53.2755f }, + { -116.2934f, 228.9896f, 53.2755f }, + { -116.0833f, 220.7691f, 53.2755f }, + { -116.2674f, 213.0243f, 53.2755f }, + { -115.9132f, 204.6198f, 53.2755f } +}; + +Position const GoalStalkerPositions[MAX_TARGET_POSITIONS] +{ + { -116.5816f, 237.6823f, 53.2755f }, + { -116.2934f, 228.9896f, 53.2755f }, + { -116.0833f, 220.7691f, 53.2755f }, + { -116.2674f, 213.0243f, 53.2755f }, + { -115.9132f, 204.6198f, 53.2755f } +}; + +Position const SpitterTargetPositions[MAX_TARGET_POSITIONS] +{ + { -39.83333f, 237.441f, 53.27685f }, + { -40.13715f, 229.6163f, 53.33047f }, + { -40.10764f, 221.4618f, 53.27604f }, + { -40.06424f, 212.9444f, 53.3602f }, + { -40.14236f, 205.0538f, 53.27604f } +}; + +Position const EmptySpotPositions[MAX_EMPTY_SPOT_POSITIONS] +{ + { -108.7604f, 221.0226f, 53.35883f }, + { -108.3733f, 212.9219f, 53.35883f }, + { -108.3108f, 229.2309f, 53.35883f }, + { -107.9792f, 203.8629f, 53.35883f }, + { -100.1684f, 220.6615f, 53.35883f }, + { -99.92188f, 212.1406f, 53.35883f }, + { -99.9375f, 204.8385f, 53.35883f }, + { -100.0399f, 229.7882f, 53.35883f }, + { -108.5486f, 237.4844f, 53.35883f }, + { -91.59549f, 220.8715f, 53.35883f }, + { -91.51563f, 212.7379f, 53.35883f }, + { -100.3385f, 237.2656f, 53.35883f }, + { -91.68056f, 229.1997f, 53.35883f }, + { -91.32291f, 204.5434f, 53.35883f }, + { -91.77604f, 237.5816f, 53.35883f }, + { -83.93403f, 213.066f, 53.35883f }, + { -83.21354f, 220.8542f, 53.35883f }, + { -83.61459f, 204.592f, 53.35883f }, + { -83.80903f, 229.6788f, 53.35883f }, + { -83.52257f, 237.217f, 53.35883f }, + { -75.24827f, 213.3108f, 53.35883f }, + { -75.00174f, 220.9861f, 53.35883f }, + { -75.34375f, 204.5382f, 53.35883f }, + { -75.25521f, 229.5278f, 53.35883f }, + { -75.10416f, 238.0816f, 53.35883f }, + { -66.7934f, 213.071f, 53.35883f }, + { -66.5469f, 220.747f, 53.35883f }, + { -66.8889f, 204.299f, 53.35883f }, + { -66.8003f, 229.288f, 53.35883f }, + { -66.6493f, 237.842f, 53.35883f }, + { -58.4965f, 212.372f, 53.35883f }, + { -58.25f, 220.047f, 53.35883f }, + { -58.5035f, 228.589f, 53.35883f }, + { -58.592f, 203.599f, 53.35883f }, + { -58.3524f, 237.142f, 53.35883f }, + { -49.6059f, 212.569f, 53.35883f }, + { -49.3594f, 220.245f, 53.35883f }, + { -49.6128f, 228.786f, 53.35883f }, + { -49.7014f, 203.797f, 53.35883f }, + { -49.4618f, 237.34f, 53.35883f } +}; + +float const EmptySpotOrientation = 6.143559f; +float const LawnmowerOrientation = 6.178465f; +float const SpitterTargetOrientation = 6.232892f; +float const GoalStalkerOrientation = 6.178465f; + +Position const SolarPowerJumpPos = { -64.24827f, 181.3004f, 53.97961f }; +Position const FreezyaSeedSummonPos = { -49.3594f, 220.245f, 56.35883f, 0.01745329f }; +Position const FreezyaSeedJumpPos = { -116.2847f, 216.7865f, 53.2755f }; + +struct npc_brazie_the_bonatist_vehicle : public VehicleAI +{ + npc_brazie_the_bonatist_vehicle(Creature* creature) : VehicleAI(creature), _summons(me), _currentLevel(LEVEL_TUTORIAL), + _deadZombieCount(0), _damagedZombieCount(0), _damagedGhoulCount(0), _currentStage(0), _timeUntilNextSolarPower(0s) { } + + void InizializeAI() + { + // Figure out at what level we currently are + InitializeLevel(); + + // Add available plants to vehicle action bar depending on level progress + SetupActionBar(); + + // Start events for each corresponding level + switch (_currentLevel) + { + case LEVEL_TUTORIAL: + _timeUntilNextSolarPower = 4s; + _events.ScheduleEvent(EVENT_SPITTER_HIGHLIGHT, 1s); + _events.ScheduleEvent(EVENT_SUMMON_SOLAR_POWER, 1s); + break; + case LEVEL_1: + _timeUntilNextSolarPower = 5s; + _events.ScheduleEvent(EVENT_SUNFLOWER_HIGHLIGHT, 1s); + _events.ScheduleEvent(EVENT_SUMMON_SOLAR_POWER, _timeUntilNextSolarPower + 500ms); + _events.ScheduleEvent(EVENT_CREATE_ZOMBIE, 41s); + break; + default: + break; + } + } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + + if (summon->GetEntry() == NPC_EMPTY_SPOT) + _spotGUIDs.push_back(summon->GetGUID()); + } + + void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override + { + if (!passenger || passenger->GetTypeId() != TYPEID_PLAYER || !me->GetCharmerOrOwner()) + return; + + if (apply) + { + PhasingHandler::AddPhase(passenger, PHASE_ID_QUEST, true); + passenger->CastSpell(passenger, SPELL_PROGRESS_BAR, true); + SetupSpawns(); + } + else + { + _events.Reset(); + passenger->RemoveAurasDueToSpell(SPELL_PROGRESS_BAR); + passenger->RemoveAurasDueToSpell(SPELL_CREATE_BOTANISTS_VEHICLE); + PhasingHandler::RemovePhase(passenger, PHASE_ID_QUEST, true); + _summons.DespawnAll(); + me->DespawnOrUnsummon(100ms); + } + } + + void SpellHit(WorldObject* caster, SpellInfo const* spell) override + { + switch (spell->Id) + { + case SPELL_GET_FREEZYA_SEEDS: + me->m_spells[2] = SPELL_PLANT_FREEZYA; + if (Player* player = caster->ToPlayer()) + { + Talk(SAY_ANNOUNCE_GAINED_FREEZYA_SEEDS, player); + player->VehicleSpellInitialize(); + } + break; + default: + break; + } + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_FIRST_SPITTER_PLANTED: + me->RemoveAurasDueToSpell(SPELL_SPITTER_HIGHLIGHT); + _events.ScheduleEvent(EVENT_CREATE_ZOMBIE, 500ms); + if (Creature* highlight = me->FindNearestCreature(NPC_PLACE_IT_HERE, 100.0f, true)) + highlight->DespawnOrUnsummon(); + break; + case ACTION_FIRST_SUNFLOWER_PLANTED: + me->RemoveAurasDueToSpell(SPELL_SUNFLOWER_HIGHLIGHT); + if (Creature* highlight = me->FindNearestCreature(NPC_PLACE_IT_HERE, 100.0f, true)) + highlight->DespawnOrUnsummon(); + break; + case ACTION_ZOMBIE_DAMAGED: + _damagedZombieCount++; + switch (_currentLevel) + { + case LEVEL_TUTORIAL: + if (_currentStage < 2) + EnterNextStage(); + break; + case LEVEL_1: + if (_currentStage == 0 && _damagedZombieCount == 1) + EnterNextStage(); + if (_currentStage == 1 && _damagedZombieCount == 2) + EnterNextStage(); + break; + default: + break; + } + break; + case ACTION_ZOMBIE_DIED: + _deadZombieCount++; + switch (_currentLevel) + { + case LEVEL_TUTORIAL: + if (_deadZombieCount == 3) + EnterNextStage(); + if (_deadZombieCount == 8) + EnterNextStage(); + break; + case LEVEL_1: + if (_deadZombieCount == 4 && _currentStage == 2) + EnterNextStage(); + if (_deadZombieCount == 11 && _currentStage == 3) + EnterNextStage(); + if (_deadZombieCount == 27 && _currentStage == 4) + EnterNextStage(); + break; + default: + break; + } + break; + case ACTION_GHOUL_DAMAGED: + _damagedGhoulCount++; + switch (_currentLevel) + { + case LEVEL_1: + if (_damagedGhoulCount == 1) + { + if (Player* player = GetPlayer()) + { + player->Whisper(SAY_ANNOUNCE_DROPPED_SEED, player, true); + player->CastSpell(player, SPELL_CREATE_RANDOM_FREEZYA_SACK, true); + } + } + break; + default: + break; + } + break; + case ACTION_QUEST_FAILED: + if (Player* player = GetPlayer()) + { + switch (_currentLevel) + { + case LEVEL_TUTORIAL: + player->FailQuest(QUEST_BASIC_BOTANY); + break; + case LEVEL_1: + player->FailQuest(QUEST_FLOWER_POWER); + break; + default: + break; + } + } + Talk(SAY_ANNOUNCE_ZOMBIES_ATE_BRAIN); + _summons.DespawnEntry(NPC_ZOMBIE); + _summons.DespawnEntry(NPC_GHOUL); + _events.Reset(); + _events.ScheduleEvent(EVENT_EJECT_PASSENGER, 2s + 300ms); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SPITTER_HIGHLIGHT: + case EVENT_SUNFLOWER_HIGHLIGHT: + { + uint32 textId = 0; + uint32 spellId = 0; + + switch (eventId) + { + case EVENT_SPITTER_HIGHLIGHT: + textId = SAY_ANNOUNCE_TUTORIAL_1; + spellId = SPELL_SPITTER_HIGHLIGHT; + break; + case EVENT_SUNFLOWER_HIGHLIGHT: + textId = SAY_ANNOUNCE_PLANT_SUNFLOWER; + spellId = SPELL_SUNFLOWER_HIGHLIGHT; + break; + default: + break; + } + + if (Player* player = GetPlayer()) + { + player->Whisper(textId, player, true); + player->CastSpell(player, spellId, true); + } + if (eventId == EVENT_SUNFLOWER_HIGHLIGHT) + _events.ScheduleEvent(EVENT_ANNOUNCE_PLANT_MORE_FLOWERS, 1s); + break; + } + case EVENT_SUMMON_SOLAR_POWER: + { + uint8 randomPositionIndex = urand(0, MAX_EMPTY_SPOT_POSITIONS - 1); + Position pos = EmptySpotPositions[randomPositionIndex]; + float angle = frand(0, float(M_PI * 2)); + float x = pos.GetPositionX() + cos(angle) * 3; + float y = pos.GetPositionY() + sin(angle) * 3; + + if (Player* player = GetPlayer()) + player->CastSpell(Position{ x, y, pos.GetPositionZ() + 50.0f }, SPELL_CREATE_RANDOM_SUN_POWER, true); + + switch (_currentLevel) + { + case LEVEL_TUTORIAL: + _events.Repeat(_timeUntilNextSolarPower); + break; + case LEVEL_1: + if (_timeUntilNextSolarPower == 5s) + _timeUntilNextSolarPower = 10s; + else + _timeUntilNextSolarPower = 5s; + _events.Repeat(_timeUntilNextSolarPower); + break; + default: + break; + } + break; + } + case EVENT_CREATE_ZOMBIE: + case EVENT_CREATE_GHOUL: + { + // The tutorial quest only spawns zombies in the center lane + uint8 index = _currentLevel == LEVEL_TUTORIAL ? static_cast(CENTER_ZOMBIE_LANE_INDEX) : static_cast(urand(0, MAX_TARGET_POSITIONS - 1)); + Position const& pos = SpitterTargetPositions[index]; + float angle = pos.GetAngle(GoalStalkerPositions[index]); + + uint32 spellId = 0; + switch (eventId) + { + case EVENT_CREATE_ZOMBIE: + spellId = SPELL_CREATE_ZOMBIE; + break; + case EVENT_CREATE_GHOUL: + spellId = SPELL_CREATE_GHOUL; + break; + default: + break; + } + + if (Player* player = GetPlayer()) + player->CastSpell(Position{ pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), angle }, spellId, true); + break; + } + case EVENT_ANNOUNCE_GOOD_JOB: + if (Player* player = GetPlayer()) + player->Whisper(SAY_ANNOUNCE_TUTORIAL_2, player, true); + _events.ScheduleEvent(EVENT_CREATE_ZOMBIE, 1ms); + break; + case EVENT_ANNOUNCE_PLACING_SPITTERS: + if (Player* player = GetPlayer()) + player->Whisper(SAY_ANNOUNCE_TUTORIAL_3, player, true); + _events.ScheduleEvent(EVENT_CREATE_ZOMBIE, 1ms); + break; + case EVENT_ANNOUNCE_MASSIVE_WAVE: + if (Player* player = GetPlayer()) + player->Whisper(SAY_ANNOUNCE_MASSIVE_WAVE, player, true); + break; + case EVENT_ANNOUNCE_LEVEL_COMPLETED: + { + if (Player* player = GetPlayer()) + { + uint32 textId = 0; + uint32 creditEntry = 0; + switch (_currentLevel) + { + case LEVEL_TUTORIAL: + textId = SAY_ANNOUNCE_TUTORIAL_4; + creditEntry = CREDIT_BASIC_BOTANY; + break; + case LEVEL_1: + textId = SAY_ANNOUNCE_LEVEL_1_COMPLETE; + creditEntry = CREDIT_FLOWER_POWER; + break; + default: + break; + } + + player->Whisper(textId, player, true); + player->RemoveAurasDueToSpell(SPELL_PROGRESS_BAR); + player->KilledMonsterCredit(creditEntry); + } + break; + } + case EVENT_EJECT_PASSENGER: + DoCastSelf(SPELL_EJECT_ALL_PASSENGERS, true); + break; + case EVENT_ANNOUNCE_PLANT_MORE_FLOWERS: + if (Player* player = GetPlayer()) + player->Whisper(SAY_ANNOUNCE_PLANT_MORE_SUNFLOWERS, player, true); + break; + default: + break; + } + } + + } + +public: + bool IsSpotFree(Position const pos) + { + for (ObjectGuid guid : _spotGUIDs) + { + if (Creature* spot = ObjectAccessor::GetCreature(*me, guid)) + if (spot->GetDistance(pos) <= 5.0f) + if (spot->IsAIEnabled()) + if (spot->AI()->GetData(DATA_CURRENT_ENTRY) == NPC_EMPTY_SPOT) + return true; + } + + return false; + } + +private: + Player* GetPlayer() + { + if (Unit* creator = ObjectAccessor::GetUnit(*me, me->GetCreatorGUID())) + return creator->ToPlayer(); + + return nullptr; + } + + void SetupSpawns() + { + Unit* charmer = me->GetCharmerOrOwner(); + if (!charmer) + return; + + for (uint8 i = 0; i < MAX_TARGET_POSITIONS; i++) + { + Position pos = LawnMowerPositions[i]; + charmer->CastSpell(Position{ pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), LawnmowerOrientation }, SPELL_CREATE_LAWMOWER, true); + + pos = GoalStalkerPositions[i]; + charmer->CastSpell(Position{ pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), GoalStalkerOrientation }, SPELL_CREATE_GOAL_STALKER, true); + + pos = SpitterTargetPositions[i]; + charmer->CastSpell(Position{ pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), SpitterTargetOrientation }, SPELL_CREATE_SPITTER_TARGET, true); + } + + for (uint8 i = 0; i < MAX_EMPTY_SPOT_POSITIONS; i++) + { + Position pos = EmptySpotPositions[i]; + charmer->CastSpell(Position{ pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), EmptySpotOrientation }, SPELL_CREATE_EMPTY_SPOT, true); + } + } + + void InitializeLevel() + { + if (Player* player = GetPlayer()) + { + if (player->GetQuestStatus(QUEST_BASIC_BOTANY) == QUEST_STATUS_REWARDED + && player->GetQuestStatus(QUEST_FLOWER_POWER) != QUEST_STATUS_REWARDED) + _currentLevel = LEVEL_1; + } + } + + void SetupActionBar() + { + if (_currentLevel == LEVEL_TUTORIAL) + me->m_spells[0] = SPELL_PLANT_SPITTER; + else if (_currentLevel == LEVEL_1) + { + me->m_spells[0] = SPELL_PLANT_SUNFLOWER; + me->m_spells[1] = SPELL_PLANT_SPITTER; + } + } + + void EnterNextStage() + { + _currentStage++; + + switch (_currentLevel) + { + case LEVEL_TUTORIAL: + if (_currentStage == 1) + _events.ScheduleEvent(EVENT_ANNOUNCE_GOOD_JOB, 1ms); + else if (_currentStage == 2) + _events.ScheduleEvent(EVENT_ANNOUNCE_PLACING_SPITTERS, 1ms); + else if (_currentStage == 3) + StartMassiveWave(); + else if (_currentStage == 4) + { + FinishLevel(); + return; + } + break; + case LEVEL_1: + if (_currentStage == 1) + CreateZombies(2, 5s, 7s); + else if (_currentStage == 2) + CreateZombies(3, 8s, 7s); + else if (_currentStage == 3) + { + CreateZombies(3, 35s, 5s); + CreateGhouls(2, 6s, 39s); + } + else if (_currentStage == 4) + StartMassiveWave(); + else if (_currentStage == 5) + { + FinishLevel(); + return; + } + break; + default: + break; + } + + if (Player* player = GetPlayer()) + player->ModifyPower(POWER_ALTERNATE_POWER, 1); + } + + void StartMassiveWave() + { + switch (_currentLevel) + { + case LEVEL_TUTORIAL: + _events.ScheduleEvent(EVENT_ANNOUNCE_MASSIVE_WAVE, 1ms); + CreateZombies(5, 1s + 800ms, 3s); + break; + case LEVEL_1: + _events.ScheduleEvent(EVENT_ANNOUNCE_MASSIVE_WAVE, 500ms); + CreateZombies(2, 2s, 3s); + CreateZombies(5, 2s, 3s); + CreateZombies(1, 20s, 0s); + CreateZombies(2, 20s, 2s); + CreateZombies(1, 29s, 0s); + CreateZombies(1, 29s, 0s); + + CreateGhouls(2, 8s, 3s); + CreateGhouls(1, 26s, 0s); + CreateGhouls(1, 26s, 0s); + break; + default: + break; + } + } + + void FinishLevel() + { + _events.Reset(); + _events.ScheduleEvent(EVENT_ANNOUNCE_LEVEL_COMPLETED, 1ms); + _events.ScheduleEvent(EVENT_EJECT_PASSENGER, 1s + 600ms); + } + + void CreateZombies(uint8 amount, Milliseconds const& delay, Milliseconds const& repeatTimer) + { + for (uint8 i = 0; i < amount; i++) + _events.ScheduleEvent(EVENT_CREATE_ZOMBIE, delay + (repeatTimer * i)); + } + + void CreateGhouls(uint8 amount, Milliseconds const& delay, Milliseconds const& repeatTimer) + { + for (uint8 i = 0; i < amount; i++) + _events.ScheduleEvent(EVENT_CREATE_GHOUL, delay + (repeatTimer * i)); + } + + EventMap _events; + SummonList _summons; + GuidVector _spotGUIDs; + uint8 _currentLevel; + uint8 _deadZombieCount; + uint8 _damagedZombieCount; + uint8 _damagedGhoulCount; + uint8 _currentStage; + Seconds _timeUntilNextSolarPower; +}; + +struct npc_brazie_fertilitize_o_tron_2000 : public ScriptedAI +{ + npc_brazie_fertilitize_o_tron_2000(Creature* creature) : ScriptedAI(creature) { } + + void IsSummonedBy(Unit* summoner) override + { + me->SetDisplayFromModel(1); + + if (Creature* vehicle = summoner->GetVehicleCreatureBase()) + if (vehicle->IsAIEnabled()) + vehicle->AI()->JustSummoned(me); + } + + void AttackStart(Unit* who) override + { + if (me->GetPosition().GetExactDist(who->GetPosition()) > 3.0f) + return; + + if (Creature* spitterTarget = me->FindNearestCreature(NPC_SPITTER_TARGET, 150.0f, true)) + { + Position pos = me->GetPosition(); + pos.SetOrientation(pos.GetAngle(spitterTarget)); + + if (pos.HasInLine(who, 5.0f, 0.f)) + CreatureAI::AttackStart(who); + } + } + + void JustEngagedWith(Unit* who) override + { + DoCast(who, SPELL_DAZED, true); + DoCastSelf(SPELL_LAWNMOWER_STARTUP_SOUND, true); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + _events.ScheduleEvent(EVENT_KILL_LANE, Milliseconds(300)); + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) + return; + + if (id == POINT_SPITTER_TARGET) + me->DespawnOrUnsummon(); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_KILL_LANE: + if (Creature* spitterTarget = me->FindNearestCreature(NPC_SPITTER_TARGET, 150.0f, true)) + me->GetMotionMaster()->MovePoint(POINT_SPITTER_TARGET, spitterTarget->GetPosition(), false); + _events.ScheduleEvent(EVENT_PLAGUE_GAS, Milliseconds(200)); + break; + case EVENT_PLAGUE_GAS: + DoCastAOE(SPELL_PLAGUE_GAS, true); + _events.Repeat(Milliseconds(500)); + break; + default: + break; + } + } + + } +private: + EventMap _events; +}; + +struct npc_brazie_spot : public ScriptedAI +{ + npc_brazie_spot(Creature* creature) : ScriptedAI(creature) + { + Initialize(); + } + + void Initialize() + { + _currentEntry = me->GetEntry(); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (damage >= me->GetHealth()) + { + damage = 0; + + me->SetFullHealth(); + me->UpdateEntry(NPC_EMPTY_SPOT); + _currentEntry = NPC_EMPTY_SPOT; + me->SetDisplayFromModel(0); + me->AttackStop(); + me->SetFacingTo(me->GetHomePosition().GetOrientation()); + _events.Reset(); + } + } + + void IsSummonedBy(Unit* summoner) override + { + me->m_SightDistance = 150.0f; + me->m_CombatDistance = 150.0f; + + me->SetDisplayFromModel(0); + + if (Creature* vehicle = summoner->GetVehicleCreatureBase()) + if (vehicle->IsAIEnabled()) + vehicle->AI()->JustSummoned(me); + } + + void AttackStart(Unit* who) override + { + if (_currentEntry == NPC_EMPTY_SPOT || _currentEntry == NPC_SUNFLOWER) + return; + + if (who->GetEntry() != NPC_ZOMBIE && who->GetEntry() != NPC_GHOUL) + return; + + if (Creature* spitterTarget = me->FindNearestCreature(NPC_SPITTER_TARGET, 150.0f, true)) + { + Position pos = me->GetPosition(); + pos.SetOrientation(pos.GetAngle(spitterTarget)); + + if (pos.HasInLine(who, 5.0f, 0.f)) + { + me->SetFacingToObject(spitterTarget); + me->SetNoCallAssistance(true); + CreatureAI::AttackStart(who); + } + } + } + + uint32 GetData(uint32 type) const override + { + if (type == DATA_CURRENT_ENTRY) + return _currentEntry; + + return 0; + } + + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spell) override + { + switch (spell->Id) + { + case SPELL_PLANT_SPITTER: + me->UpdateEntry(NPC_SPITTER); + _currentEntry = NPC_SPITTER; + break; + case SPELL_PLANT_SUNFLOWER: + me->UpdateEntry(NPC_SUNFLOWER); + _currentEntry = NPC_SUNFLOWER; + _events.ScheduleEvent(EVENT_SUNLIGHT, 16s); + break; + case SPELL_PLANT_FREEZYA: + me->UpdateEntry(NPC_FREEZYA); + _currentEntry = NPC_FREEZYA; + break; + default: + break; + } + + if (spell->Id != SPELL_PLAGUE_GAS) + me->SetDisplayFromModel(1); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SUNLIGHT: + DoCastSelf(SPELL_SUNLIGHT, true); + if (TempSummon* summon = me->ToTempSummon()) + { + if (Unit* summoner = summon->GetSummoner()) + { + uint8 randomPositionIndex = urand(0, MAX_EMPTY_SPOT_POSITIONS - 1); + Position pos = EmptySpotPositions[randomPositionIndex]; + float angle = frand(0, float(M_PI * 2)); + float x = pos.GetPositionX() + cos(angle) * 3; + float y = pos.GetPositionY() + sin(angle) * 3; + + summoner->CastSpell(Position{ x, y, pos.GetPositionZ() + 50.0f }, SPELL_CREATE_RANDOM_SUN_POWER, true); + } + } + _events.Repeat(17s); + break; + default: + break; + } + } + + if (_currentEntry == NPC_SPITTER) + DoSpellAttackIfReady(SPELL_VENOM_SPIT); + else if (_currentEntry == NPC_FREEZYA) + DoSpellAttackIfReady(SPELL_FREEZYA_BLAST); + } + +private: + EventMap _events; + uint32 _currentEntry; + GuidVector _zombieGuids; +}; + +struct npc_brazie_zombie : public ScriptedAI +{ + npc_brazie_zombie(Creature* creature) : ScriptedAI(creature), _pathIndex(0), _notifiedLowHealth(false) + { + } + + void IsSummonedBy(Unit* summoner) override + { + me->m_SightDistance = 3.0f; + me->m_CombatDistance = 3.0f; + + me->SetWalk(true); + + if (Creature* vehicle = summoner->GetVehicleCreatureBase()) + if (vehicle->IsAIEnabled()) + vehicle->AI()->JustSummoned(me); + + for (uint8 i = 0; i < MAX_TARGET_POSITIONS; i++) + if (me->GetPosition().GetExactDist(SpitterTargetPositions[i]) <= 1.0f) + _pathIndex = i; + + if (me->GetEntry() == NPC_ZOMBIE) + DoCastSelf(SPELL_ZOMBIE_GROWL); + else if (me->GetEntry() == NPC_GHOUL) + { + me->SetDisplayFromModel(3); + DoCastSelf(SPELL_GHOUL_GROWL, true); + DoCastSelf(SPELL_BUCKET_HEAD, true); + } + + _events.ScheduleEvent(EVENT_MOVE_TO_GOAL_POSITION, 2s + 400ms); + } + + void AttackStart(Unit* who) override + { + // Just to make sure that a zombie wont call nearby zombies for aid + if (who->GetDistance(me) > 3.0f) + return; + + // If we have a plant very close to us we assume that this plant has been added afterwards + if (me->GetPosition().GetExactDist(who) < 3.0f) + return; + + // Do not attack plants behind me if they got replanted + if (!who->isInFront(me, 1.8f)) + return; + + Position pos = me->GetPosition(); + pos.SetOrientation(pos.GetAngle(GoalStalkerPositions[_pathIndex])); + + if (pos.HasInLine(who, 4.8f, 0.f)) + { + if (Creature* target = who->ToCreature()) + { + if (target->IsAIEnabled()) + { + if (target->AI()->GetData(DATA_CURRENT_ENTRY) != NPC_EMPTY_SPOT || target->GetEntry() == NPC_FERTILITIZE_O_TRON_2000) + { + me->SetNoCallAssistance(true); + me->StopMoving(); + CreatureAI::AttackStart(who); + } + } + } + } + } + + void JustDied(Unit* /*killer*/) override + { + if (TempSummon* summon = me->ToTempSummon()) + if (Unit* summoner = summon->GetSummoner()) + if (Creature* vehicle = summoner->GetVehicleCreatureBase()) + if (vehicle->IsAIEnabled()) + vehicle->AI()->DoAction(ACTION_ZOMBIE_DIED); + + me->DespawnOrUnsummon(4s); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (me->HealthBelowPctDamaged(50, damage) && !_notifiedLowHealth) + { + if (me->GetEntry() == NPC_ZOMBIE) + DoCastSelf(SPELL_LEAKING_GUTS, true); + else if (me->GetEntry() == NPC_GHOUL) + { + me->RemoveAurasDueToSpell(SPELL_BUCKET_HEAD); + DoCastSelf(SPELL_BUCKET, true); + } + + if (TempSummon* summon = me->ToTempSummon()) + { + if (Unit* summoner = summon->GetSummoner()) + { + if (Creature* vehicle = summoner->GetVehicleCreatureBase()) + { + if (vehicle->IsAIEnabled()) + { + if (me->GetEntry() == NPC_ZOMBIE) + vehicle->AI()->DoAction(ACTION_ZOMBIE_DAMAGED); + else if (me->GetEntry() == NPC_GHOUL) + vehicle->AI()->DoAction(ACTION_GHOUL_DAMAGED); + } + } + } + } + + _notifiedLowHealth = true; + } + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) + return; + + if (id == POINT_GOAL_STALKER) + if (me->GetPosition().GetExactDist(GoalStalkerPositions[_pathIndex]) <= 0.1f) + if (TempSummon* summon = me->ToTempSummon()) + if (Unit* summoner = summon->GetSummoner()) + if (Creature* vehicle = summoner->GetVehicleCreatureBase()) + if (vehicle->IsAIEnabled()) + vehicle->AI()->DoAction(ACTION_QUEST_FAILED); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MOVE_TO_GOAL_POSITION: + me->GetMotionMaster()->MovePoint(POINT_GOAL_STALKER, GoalStalkerPositions[_pathIndex], false); + _events.ScheduleEvent(EVENT_CHECK_VICTIM_STATE, 1s); + break; + case EVENT_CHECK_VICTIM_STATE: + if (Unit* victim = me->GetVictim()) + { + if (Creature* target = victim->ToCreature()) + { + if (target->IsAIEnabled()) + { + if (target->AI()->GetData(DATA_CURRENT_ENTRY) == NPC_EMPTY_SPOT) + { + me->AttackStop(); + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_GOAL_STALKER, GoalStalkerPositions[_pathIndex], false); + } + } + } + } + _events.Repeat(1s); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + + } +private: + EventMap _events; + uint8 _pathIndex; + bool _notifiedLowHealth; +}; + +struct npc_brazie_vehicle_notifier : public ScriptedAI +{ + npc_brazie_vehicle_notifier(Creature* creature) : ScriptedAI(creature) { } + + void IsSummonedBy(Unit* summoner) override + { + switch (me->GetEntry()) + { + case NPC_SOLAR_POWER: + case NPC_FREEZYA_SEEDS: + me->SetDisplayFromModel(1); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + break; + case NPC_PLACE_IT_HERE: + me->Relocate(EmptySpotPositions[0]); + me->SetDisplayFromModel(1); + break; + default: + me->SetDisplayFromModel(0); + break; + } + + if (Creature* vehicle = summoner->GetVehicleCreatureBase()) + if (vehicle->IsAIEnabled()) + vehicle->AI()->JustSummoned(me); + } + + void SpellHit(WorldObject* caster, SpellInfo const* spell) override + { + if (!caster || !caster->IsUnit()) + return; + + switch (spell->Id) + { + case SPELL_GAIN_SOLAR_POWER_SPELLCLICK: + if (Unit* vehicle = caster->ToUnit()->GetVehicleCreatureBase()) + DoCast(vehicle, SPELL_GAIN_SOLAR_POWER_ENERGIZE, true); + me->GetMotionMaster()->MoveJump(SolarPowerJumpPos, 45.0f, 20.0f); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + me->DespawnOrUnsummon(Seconds(2)); + break; + case SPELL_GET_FREEZYA_SEEDS: + me->GetMotionMaster()->MoveJump(FreezyaSeedJumpPos, 45.0f, 20.0f); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + me->DespawnOrUnsummon(Seconds(2)); + break; + default: + break; + } + } +}; + +class spell_brazie_summon_plant : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_SUNFLOWER_HIGHLIGHT, + SPELL_SPITTER_HIGHLIGHT + }); + } + + SpellCastResult CheckLocation() + { + if (Creature* creature = GetCaster()->ToCreature()) + if (CAST_AI(npc_brazie_the_bonatist_vehicle, + creature->AI())->IsSpotFree(GetExplTargetDest()->GetPosition())) + return SPELL_CAST_OK; + + return SPELL_FAILED_BAD_TARGETS; + } + + void PreventEffect(SpellEffIndex effIndex) + { + PreventHitEffect(effIndex); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + if (!caster || caster->GetTypeId() != TYPEID_UNIT) + return; + + Creature* creature = caster->ToCreature(); + + if (creature->IsAIEnabled()) + { + if (creature->HasAura(SPELL_SUNFLOWER_HIGHLIGHT)) + creature->AI()->DoAction(ACTION_FIRST_SUNFLOWER_PLANTED); + + if (creature->HasAura(SPELL_SPITTER_HIGHLIGHT)) + creature->AI()->DoAction(ACTION_FIRST_SPITTER_PLANTED); + } + } + + void Register() override + { + OnCheckCast.Register(&spell_brazie_summon_plant::CheckLocation); + OnEffectHitTarget.Register(&spell_brazie_summon_plant::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); + OnEffectHit.Register(&spell_brazie_summon_plant::PreventEffect, EFFECT_0, SPELL_EFFECT_TRANS_DOOR); + } +}; + +class spell_brazie_highlight : public SpellScript +{ + void SetDest(SpellDestination& dest) + { + dest.Relocate(EmptySpotPositions[0]); + } + + void Register() override + { + OnDestinationTargetSelect.Register(&spell_brazie_highlight::SetDest, EFFECT_1, TARGET_DEST_NEARBY_ENTRY); + } +}; + +class spell_brazie_create_random_seed_sack : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_CREATE_RANDOM_FREEZYA_SACK }); + } + + void SetDest(SpellDestination& dest) + { + if (GetSpellInfo()->Id == SPELL_CREATE_RANDOM_FREEZYA_SACK) + dest.Relocate(FreezyaSeedSummonPos); + } + + void Register() override + { + OnDestinationTargetSelect.Register(&spell_brazie_create_random_seed_sack::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); + } +}; + +class spell_brazie_spit : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_VENOM_SPIT, + SPELL_FREEZYA_BLAST + }); + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + if (GetSpellInfo()->Id == SPELL_VENOM_SPIT) + { + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), true)); + targets.resize(1); + } + else + { + std::list targetsBackup = targets; + targetsBackup.remove_if(Trinity::UnitAuraCheck(true, SPELL_FREEZYA_BLAST)); + if (targetsBackup.empty()) + { + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), true)); + targets.resize(1); + } + else + { + targets = targetsBackup; + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), true)); + targets.resize(1); + } + } + } + + void Register() override + { + OnObjectAreaTargetSelect.Register(&spell_brazie_spit::FilterTargets, EFFECT_ALL, TARGET_UNIT_CONE_CASTER_TO_DEST_ENEMY); + } +}; + +// WOW-PRIVATE-SERVER PATCH: Welcome to the Machine (28096) +// +// Restores the missing Hillsbrad quest scene around High Executor Darthalia's +// skeletal steed. Spoken lines are provided through creature_text rows that +// reference the original BroadcastText IDs, so existing locales remain usable. +enum WelcomeToTheMachine +{ + QUEST_WELCOME_TO_THE_MACHINE = 28096, + + NPC_HIGH_EXECUTOR_DARTHALIA = 2215, + NPC_JOHNNY_AWESOME = 47442, + NPC_KINGSLAYER_ORKUS = 47443, + NPC_DUMASS = 47444, + NPC_SKELETAL_STEED = 47445, + + DATA_WELCOME_STAGE = 1, + + STAGE_IDLE = 0, + STAGE_DUMASS_GOSSIP = 1, + STAGE_ORKUS_GOSSIP = 2, + STAGE_JOHNNY_GOSSIP = 3, + STAGE_FINISHED = 4, + + ACTION_DUMASS_DONE = 1, + ACTION_ORKUS_DONE = 2, + ACTION_JOHNNY_DONE = 3, + + GOSSIP_ACTION_DUMASS_1 = GOSSIP_ACTION_INFO_DEF + 101, + GOSSIP_ACTION_DUMASS_2 = GOSSIP_ACTION_INFO_DEF + 102, + GOSSIP_ACTION_ORKUS_1 = GOSSIP_ACTION_INFO_DEF + 103, + GOSSIP_ACTION_ORKUS_2 = GOSSIP_ACTION_INFO_DEF + 104, + GOSSIP_ACTION_ORKUS_3 = GOSSIP_ACTION_INFO_DEF + 105, + GOSSIP_ACTION_JOHNNY_1 = GOSSIP_ACTION_INFO_DEF + 106, + GOSSIP_ACTION_JOHNNY_2 = GOSSIP_ACTION_INFO_DEF + 107, + GOSSIP_ACTION_JOHNNY_3 = GOSSIP_ACTION_INFO_DEF + 108, + + GOSSIP_MENU_DUMASS_1 = 12273, + GOSSIP_MENU_DUMASS_2 = 12272, + GOSSIP_MENU_ORKUS_1 = 12276, + GOSSIP_MENU_ORKUS_2 = 12275, + GOSSIP_MENU_ORKUS_3 = 12274, + GOSSIP_MENU_JOHNNY_1 = 12279, + GOSSIP_MENU_JOHNNY_2 = 12278, + GOSSIP_MENU_JOHNNY_3 = 12277, + + SAY_DARTHALIA_STAND_TALL = 50, + SAY_DARTHALIA_FIRST_ONE = 51, + SAY_DARTHALIA_DUMASS_COMMENT = 52, + SAY_DARTHALIA_ORKUS_WARNING = 53, + SAY_DARTHALIA_ORKUS_COMMENT = 54, + SAY_DARTHALIA_JOHNNY_WARNING = 55, + + SAY_DUMASS_HELLO = 50, + SAY_DUMASS_NEW = 51, + SAY_DUMASS_WAIT = 52, + SAY_DUMASS_NORTH = 53, + + SAY_ORKUS_LOKTAR = 50, + SAY_ORKUS_PUNY = 51, + SAY_ORKUS_WHAT_HAVE_YOU_GOT = 52, + SAY_ORKUS_BOAST = 53, + SAY_ORKUS_RISK = 54, + SAY_ORKUS_WILL_DO_IT = 55, + SAY_ORKUS_FAREWELL = 56, + + SAY_JOHNNY_ARRIVED = 50, + SAY_JOHNNY_HEIRLOOMS = 51, + SAY_JOHNNY_WHAT_ELSE = 52, + SAY_JOHNNY_ONE_QUEST = 53, + SAY_JOHNNY_FAREWELL = 54 +}; + +enum WelcomeToTheMachineEvents +{ + EVENT_WELCOME_DARTHALIA_1 = 1, + EVENT_WELCOME_DARTHALIA_2, + EVENT_WELCOME_SUMMON_DUMASS, + EVENT_WELCOME_DUMASS_1, + EVENT_WELCOME_DUMASS_2, + EVENT_WELCOME_ENABLE_DUMASS, + EVENT_WELCOME_DARTHALIA_DUMASS_COMMENT, + EVENT_WELCOME_DARTHALIA_ORKUS_WARNING, + EVENT_WELCOME_SUMMON_ORKUS, + EVENT_WELCOME_ORKUS_1, + EVENT_WELCOME_ORKUS_2, + EVENT_WELCOME_ORKUS_3, + EVENT_WELCOME_ORKUS_4, + EVENT_WELCOME_ENABLE_ORKUS, + EVENT_WELCOME_DARTHALIA_ORKUS_COMMENT, + EVENT_WELCOME_DARTHALIA_JOHNNY_WARNING, + EVENT_WELCOME_SUMMON_JOHNNY, + EVENT_WELCOME_JOHNNY_1, + EVENT_WELCOME_JOHNNY_2, + EVENT_WELCOME_ENABLE_JOHNNY +}; + +struct npc_hillsbrad_welcome_steed : public VehicleAI +{ + npc_hillsbrad_welcome_steed(Creature* creature) + : VehicleAI(creature), _summons(me), _stage(STAGE_IDLE) { } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + } + + void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override + { + Player* player = passenger ? passenger->ToPlayer() : nullptr; + if (!player) + return; + + if (!apply) + { + ResetScene(); + return; + } + + if (player->GetQuestStatus(QUEST_WELCOME_TO_THE_MACHINE) != QUEST_STATUS_INCOMPLETE) + return; + + _playerGuid = player->GetGUID(); + _stage = STAGE_IDLE; + _events.Reset(); + _summons.DespawnAll(); + + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_1, 500ms); + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_2, 3s); + _events.ScheduleEvent(EVENT_WELCOME_SUMMON_DUMASS, 5s); + _events.ScheduleEvent(EVENT_WELCOME_DUMASS_1, 6s); + _events.ScheduleEvent(EVENT_WELCOME_DUMASS_2, 8s); + _events.ScheduleEvent(EVENT_WELCOME_ENABLE_DUMASS, 11s); + } + + uint32 GetData(uint32 type) const override + { + if (type == DATA_WELCOME_STAGE) + return _stage; + + return 0; + } + + void DoAction(int32 action) override + { + Player* player = GetScenePlayer(); + if (!player || player->GetQuestStatus(QUEST_WELCOME_TO_THE_MACHINE) != QUEST_STATUS_INCOMPLETE) + return; + + switch (action) + { + case ACTION_DUMASS_DONE: + if (_stage != STAGE_DUMASS_GOSSIP) + return; + + _stage = STAGE_IDLE; + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_DUMASS_COMMENT, 2s); + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_ORKUS_WARNING, 5s); + _events.ScheduleEvent(EVENT_WELCOME_SUMMON_ORKUS, 7s); + _events.ScheduleEvent(EVENT_WELCOME_ORKUS_1, 8s); + _events.ScheduleEvent(EVENT_WELCOME_ORKUS_2, 10s); + _events.ScheduleEvent(EVENT_WELCOME_ORKUS_3, 12s); + _events.ScheduleEvent(EVENT_WELCOME_ORKUS_4, 15s); + _events.ScheduleEvent(EVENT_WELCOME_ENABLE_ORKUS, 18s); + break; + + case ACTION_ORKUS_DONE: + if (_stage != STAGE_ORKUS_GOSSIP) + return; + + _stage = STAGE_IDLE; + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_ORKUS_COMMENT, 2s); + _events.ScheduleEvent(EVENT_WELCOME_DARTHALIA_JOHNNY_WARNING, 5s); + _events.ScheduleEvent(EVENT_WELCOME_SUMMON_JOHNNY, 7s); + _events.ScheduleEvent(EVENT_WELCOME_JOHNNY_1, 8s); + _events.ScheduleEvent(EVENT_WELCOME_JOHNNY_2, 11s); + _events.ScheduleEvent(EVENT_WELCOME_ENABLE_JOHNNY, 15s); + break; + + case ACTION_JOHNNY_DONE: + if (_stage == STAGE_JOHNNY_GOSSIP) + _stage = STAGE_FINISHED; + break; + + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + Player* player = GetScenePlayer(); + if (!player || player->GetQuestStatus(QUEST_WELCOME_TO_THE_MACHINE) != QUEST_STATUS_INCOMPLETE) + { + ResetScene(); + return; + } + + switch (eventId) + { + case EVENT_WELCOME_DARTHALIA_1: TalkDarthalia(SAY_DARTHALIA_STAND_TALL, player); break; + case EVENT_WELCOME_DARTHALIA_2: TalkDarthalia(SAY_DARTHALIA_FIRST_ONE, player); break; + case EVENT_WELCOME_SUMMON_DUMASS: SummonActor(NPC_DUMASS); break; + case EVENT_WELCOME_DUMASS_1: TalkActor(NPC_DUMASS, SAY_DUMASS_HELLO, player); break; + case EVENT_WELCOME_DUMASS_2: TalkActor(NPC_DUMASS, SAY_DUMASS_NEW, player); break; + case EVENT_WELCOME_ENABLE_DUMASS: _stage = STAGE_DUMASS_GOSSIP; break; + + case EVENT_WELCOME_DARTHALIA_DUMASS_COMMENT: TalkDarthalia(SAY_DARTHALIA_DUMASS_COMMENT, player); break; + case EVENT_WELCOME_DARTHALIA_ORKUS_WARNING: TalkDarthalia(SAY_DARTHALIA_ORKUS_WARNING, player); break; + case EVENT_WELCOME_SUMMON_ORKUS: SummonActor(NPC_KINGSLAYER_ORKUS); break; + case EVENT_WELCOME_ORKUS_1: TalkActor(NPC_KINGSLAYER_ORKUS, SAY_ORKUS_LOKTAR, player); break; + case EVENT_WELCOME_ORKUS_2: TalkActor(NPC_KINGSLAYER_ORKUS, SAY_ORKUS_PUNY, player); break; + case EVENT_WELCOME_ORKUS_3: TalkActor(NPC_KINGSLAYER_ORKUS, SAY_ORKUS_WHAT_HAVE_YOU_GOT, player); break; + case EVENT_WELCOME_ORKUS_4: TalkActor(NPC_KINGSLAYER_ORKUS, SAY_ORKUS_BOAST, player); break; + case EVENT_WELCOME_ENABLE_ORKUS: _stage = STAGE_ORKUS_GOSSIP; break; + + case EVENT_WELCOME_DARTHALIA_ORKUS_COMMENT: TalkDarthalia(SAY_DARTHALIA_ORKUS_COMMENT, player); break; + case EVENT_WELCOME_DARTHALIA_JOHNNY_WARNING: TalkDarthalia(SAY_DARTHALIA_JOHNNY_WARNING, player); break; + case EVENT_WELCOME_SUMMON_JOHNNY: SummonActor(NPC_JOHNNY_AWESOME); break; + case EVENT_WELCOME_JOHNNY_1: TalkActor(NPC_JOHNNY_AWESOME, SAY_JOHNNY_ARRIVED, player); break; + case EVENT_WELCOME_JOHNNY_2: TalkActor(NPC_JOHNNY_AWESOME, SAY_JOHNNY_HEIRLOOMS, player); break; + case EVENT_WELCOME_ENABLE_JOHNNY: _stage = STAGE_JOHNNY_GOSSIP; break; + default: break; + } + } + } + +private: + Player* GetScenePlayer() + { + return ObjectAccessor::GetPlayer(*me, _playerGuid); + } + + Creature* GetSceneActor(uint32 entry) + { + for (ObjectGuid const& guid : _summons) + if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + if (summon->GetEntry() == entry) + return summon; + + return nullptr; + } + + void SummonActor(uint32 entry) + { + if (GetSceneActor(entry)) + return; + + float x = me->GetPositionX() + 4.0f; + float y = me->GetPositionY() + 4.0f; + float z = me->GetPositionZ(); + + if (Creature* actor = me->SummonCreature(entry, x, y, z, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN)) + { + actor->SetReactState(REACT_PASSIVE); + actor->SetFacingToObject(me); + } + } + + void TalkActor(uint32 entry, uint8 groupId, Player* player) + { + if (Creature* actor = GetSceneActor(entry)) + if (actor->IsAIEnabled()) + actor->AI()->Talk(groupId, player); + } + + void TalkDarthalia(uint8 groupId, Player* player) + { + if (Creature* darthalia = me->FindNearestCreature(NPC_HIGH_EXECUTOR_DARTHALIA, 40.0f, true)) + if (darthalia->IsAIEnabled()) + darthalia->AI()->Talk(groupId, player); + } + + void ResetScene() + { + _events.Reset(); + _summons.DespawnAll(); + _playerGuid.Clear(); + _stage = STAGE_IDLE; + } + + EventMap _events; + SummonList _summons; + ObjectGuid _playerGuid; + uint8 _stage; +}; + +struct npc_hillsbrad_welcome_actor : public ScriptedAI +{ + npc_hillsbrad_welcome_actor(Creature* creature) : ScriptedAI(creature) { } + + bool GossipHello(Player* player) override + { + if (!IsValidScenePlayer(player)) + return false; + + Creature* vehicle = player->GetVehicleCreatureBase(); + if (!vehicle || !vehicle->IsAIEnabled()) + return false; + + uint32 stage = vehicle->AI()->GetData(DATA_WELCOME_STAGE); + + ClearGossipMenuFor(player); + + switch (me->GetEntry()) + { + case NPC_DUMASS: + if (stage != STAGE_DUMASS_GOSSIP) + return false; + + AddGossipItemFor(player, GOSSIP_MENU_DUMASS_1, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_DUMASS_1); + break; + + case NPC_KINGSLAYER_ORKUS: + if (stage != STAGE_ORKUS_GOSSIP) + return false; + + AddGossipItemFor(player, GOSSIP_MENU_ORKUS_1, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_ORKUS_1); + break; + + case NPC_JOHNNY_AWESOME: + if (stage != STAGE_JOHNNY_GOSSIP) + return false; + + AddGossipItemFor(player, GOSSIP_MENU_JOHNNY_1, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_JOHNNY_1); + break; + + default: + return false; + } + + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + } + + bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override + { + if (!IsValidScenePlayer(player)) + return false; + + Creature* vehicle = player->GetVehicleCreatureBase(); + if (!vehicle || !vehicle->IsAIEnabled()) + return false; + + uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId); + ClearGossipMenuFor(player); + + switch (action) + { + case GOSSIP_ACTION_DUMASS_1: + Talk(SAY_DUMASS_WAIT, player); + AddGossipItemFor(player, GOSSIP_MENU_DUMASS_2, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_DUMASS_2); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_DUMASS_2: + Talk(SAY_DUMASS_NORTH, player); + player->KilledMonsterCredit(NPC_DUMASS); + CloseGossipMenuFor(player); + vehicle->AI()->DoAction(ACTION_DUMASS_DONE); + return true; + + case GOSSIP_ACTION_ORKUS_1: + Talk(SAY_ORKUS_RISK, player); + AddGossipItemFor(player, GOSSIP_MENU_ORKUS_2, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_ORKUS_2); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_ORKUS_2: + Talk(SAY_ORKUS_WILL_DO_IT, player); + AddGossipItemFor(player, GOSSIP_MENU_ORKUS_3, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_ORKUS_3); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_ORKUS_3: + Talk(SAY_ORKUS_FAREWELL, player); + player->KilledMonsterCredit(NPC_KINGSLAYER_ORKUS); + CloseGossipMenuFor(player); + vehicle->AI()->DoAction(ACTION_ORKUS_DONE); + return true; + + case GOSSIP_ACTION_JOHNNY_1: + Talk(SAY_JOHNNY_WHAT_ELSE, player); + AddGossipItemFor(player, GOSSIP_MENU_JOHNNY_2, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_JOHNNY_2); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_JOHNNY_2: + Talk(SAY_JOHNNY_ONE_QUEST, player); + AddGossipItemFor(player, GOSSIP_MENU_JOHNNY_3, 0, + GOSSIP_SENDER_MAIN, GOSSIP_ACTION_JOHNNY_3); + SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me->GetGUID()); + return true; + + case GOSSIP_ACTION_JOHNNY_3: + Talk(SAY_JOHNNY_FAREWELL, player); + player->KilledMonsterCredit(NPC_JOHNNY_AWESOME); + CloseGossipMenuFor(player); + vehicle->AI()->DoAction(ACTION_JOHNNY_DONE); + return true; + + default: + return false; + } + } + +private: + bool IsValidScenePlayer(Player* player) const + { + if (!player || player->GetQuestStatus(QUEST_WELCOME_TO_THE_MACHINE) != QUEST_STATUS_INCOMPLETE) + return false; + + Creature* vehicle = player->GetVehicleCreatureBase(); + return vehicle && vehicle->GetEntry() == NPC_SKELETAL_STEED; + } +}; + +} + +void AddSC_hillsbrad_foothills() +{ + using namespace HillsbradFoothills; + RegisterCreatureAI(npc_brazie_the_bonatist_vehicle); + RegisterCreatureAI(npc_brazie_fertilitize_o_tron_2000); + RegisterCreatureAI(npc_brazie_spot); + RegisterCreatureAI(npc_brazie_zombie); + RegisterCreatureAI(npc_brazie_vehicle_notifier); + RegisterCreatureAI(npc_hillsbrad_welcome_steed); + RegisterCreatureAI(npc_hillsbrad_welcome_actor); + RegisterSpellScript(spell_brazie_summon_plant); + RegisterSpellScript(spell_brazie_highlight); + RegisterSpellScript(spell_brazie_create_random_seed_sack); + RegisterSpellScript(spell_brazie_spit); +}