This commit is contained in:
Subv
2012-10-19 17:57:30 -05:00
77 changed files with 2991 additions and 2223 deletions
+32 -6
View File
@@ -14,7 +14,9 @@ Thanks to the WCell team (especially Ralek) for research on realm reconnect
sequence, item scaling stats algorithm, gameobject rotation issues.
Thanks go out to the following people for various patches/code (listed in the
order they were added): w12x, dythzer, XEQT, death420, balrok, TOM_RUS,
order they were added) (there may be duplicates or invalid names, most of them
were extracted from commits):
w12x, dythzer, XEQT, death420, balrok, TOM_RUS,
runningnak3d, Seline, KingPin, raczman, bogie, Neo2003, NoFantasy, Derex,
freghar, toilet1, megamage, MadJack, WarHead, gvcoman, Ntsc, arrai, jrkpote,
Seraphim, vagoth, KerchumA222, Rognar, Blaymoira, DragonHunter, Molius, ApoC,
@@ -33,9 +35,9 @@ teacher4, zhenya, Albrecht de Endrau, Phacops, Naicisum, thenecromancer, shax,
cryingcloud, freeganja, Foks, daveh, Az@zel, evilstar, Corfen, Astellar, Maxxie,
DEN_North, StarJoker, Nezemnoy, X-Savior, subhuman_bob, Ambal, Brueggus, sparc,
jojo, Trojan, tvaroh, Genars, BombermaG, Bulkin, nesocip, xILOSWag, SilverIce,
Uruviel, timmit, SeT, Seizerkiller, Stokrotka, JoN0, Tanatos, Hunteee, Alyen,
Uruviel, timmit, Seizerkiller, Stokrotka, JoN0, Tanatos, Hunteee, Alyen,
Farah, Them, DaGNU, arthurcik, BudIcePenguin, Amok, Amit86, onkelz28, Azrael,
Larva, Roland, DerDyddye, Vicos, PSZ, CRAZyBUg, irish, Sephiroth1984, hunuza,
Larva, Roland, DerDyddye, Vicos, PSZ, CRAZyBUg, irish, Sephiroth1984,
mike753, Xlybriem, Paytheo, ArticDevil, FearX, Beaste, bufferoverflow, Jeniczek,
Den, bobaz, crackm, seirge, D_Skywalk, mknjc, Christyan, Saeba, Nevan, tlexii,
liszt, duckman, Joro, Charlie, smellbee, bigjohnson4, maxdestroyer, Destalker,
@@ -64,7 +66,7 @@ footman, elron103, make_the_king, destros, MetaphysicalDrama, disassebler,
Malcrom, Vladmimír Lipták, retriman, hyriuu, Smakapotatis, PainKiller,
bkhorizon, n0n4m3, Chesterfield, Frankir, Wowka321, Morpheux, p0wer,
Ouden, toshik, laise, yavi, Splinter, Syntec, Arthas, denyde, unholy,
Vaughner, blackmanos, edrinn, Liberate, Shauren, dr.tenma, click, silverice,
Vaughner, blackmanos, edrinn, Liberate, Shauren, dr.tenma, click,
SupaBad, Xanadu, Socolin, Shocker, Silinoron, 0xFuture, xK1, Ramus, menke,
wowgargamel, Dark0r, Kierkegaard, Leak, ge0rg, StormByte, joshwhedon,
BlackCat0110, JuliuSZS, n4rk0, filip.havlicek, m.ax, laviniu, LordJZ, Scazzato88,
@@ -72,5 +74,29 @@ svannon, jurkovic.nikola, Willian Krueger, BioHazard, Ille000, Erocoloco,
terrorbringer, antihrists, Havenard, scarymovie87, D3VIL, FaTe753, PrinceCreed,
spgm, Dakeyras, sombre88, 19Maxx83, moriquendu, Ille, breakerfly,
zthoreen, clement.roussel, p.alexej, Ceris, Nayre, Kiper, announce, thmarth,
Ner'zhul, DarkXuan, leak, linencloth, SnakeIce, Supabad, Tome, Nay, Kaelima,
Svannon
Ner'zhul, DarkXuan, linencloth, SnakeIce, Tome, Nay, Kaelima,
Subv, Tuxity, tibbi, Gigatotem, Nexflame, trickerer, zxbiohazardzx, w1sht0l1v3,
Warpten, CeIa, Kandera, horn, Dimitro, thesensei, Sovak, Vincent-Michael,
Xanvial, faq, Gacko, Geodar, hexa-, MacWarrior, cyberbrest, Myran2, Northstrider,
AFROM, CrYser, Kretol, Bizzy, nelegalno, Kinzcool, armano2, Tomas, Aristoo, Trista,
[email protected], oMadMano, Kiddie, blub, Santiago, tobmaps, Mik43l, danik, Souler,
joschiwald, CDawg, WishToDie, gecko32, gadge, neuro_999, Stefo, dr.skull, NTX, Hexit,
Stalker-Riddick, thomas33, Manuel Carrasco, Imprtat, Chaplain, teyrnon, zorix, Greymane,
Venugh, e000, Amit, Alternative, Exodius, Jorge, shlomi1515, tharaca, Alestaan, Valcorb,
Odyssey, Chipsi, Pesthuf, stfx, Yaki Khadafi, David Klepá�ek, SignFinder, unknown,
NNN666, AliveShiro, 4m1g0, mweinelt, Abdollah Hasan, Xees, zori, warriorpoetex, qaywsx,
ghost, Discovered, faq_, Jildor, The Game, Kezo90, Helias, Frca, Ramusik, elecyb, Joni,
Multivitamin, faramir118, cookta2012, Gyx, ShinDarth, Lopin, Martin Weinelt,
Bezo, frozenarmor, E. van Harten, LiMCrosS, Albis, Go6o, Pitcrawler, Matthew Goff, neurorulez,
Ka0z, glkrlos, zwerg, Merlin2010, furion, Giuseppe Montesanto, LihO, Bootz, PKX, burnham,
Drake Fish, Vlad, Discover, Heisenberg, Kapoeira, Emo Norfik, tREAk, zoidmann, Wilds, weclub,
Jon, Cron, Alexander, Vinolentus, LaserJet, mns, Stalker_Riddick, Yelvann, draco, Geekotron,
bytewarrior, Fredi Machado, Studioworks, 3kids, idostyle@zoit, Sebastián Orellana, DemiDroL,
n4ndo, et2012, Rochet2, Grobi, Google, Wispeckt, hacknowledge, wonopon, Naga,
Joeri Thissen, Payn, Fest, insider42, DrTenma, L30m4nc3r, Akama, Jesper Meyer, Kiperr,
maanuel, vcrx6, Furion89, Mark07, lost-illusion, SeTM, TCKiper, vlad852, tehmarto, boom,
Per Wilhelmsen, telsamat, Various, erimioa, Sawiner, zergtmn, SimonDMII, pek2011, alexbolotsin,
laly, mrquickfx, Koord, amnell, GWRde, EdwinDW, gildor, darkstalker, Feanordev, _manuel_,
thymuswisewood, sohrab, Lazzalf, Taser, Ottowayne, Exordian, nucleartux, John Holiver, j4r0d,
Trazom62, Brian, enjoi, teacher, Alex Bolotsin, Troy, silver1ce, nihal, arcanzic, Chaz Brown,
pendragon, aven_coda, cca220v, ArcticDevil, derex_tri
+3 -1
View File
@@ -618,7 +618,7 @@ DROP TABLE IF EXISTS `character_glyphs`;
CREATE TABLE `character_glyphs` (
`guid` int(10) unsigned NOT NULL,
`spec` tinyint(3) unsigned NOT NULL DEFAULT '0',
`glyph1` smallint(5) unsigned NOT NULL DEFAULT '0',
`glyph1` smallint(5) unsigned DEFAULT '0',
`glyph2` smallint(5) unsigned DEFAULT '0',
`glyph3` smallint(5) unsigned DEFAULT '0',
`glyph4` smallint(5) unsigned DEFAULT '0',
@@ -1429,9 +1429,11 @@ CREATE TABLE `gm_tickets` (
`closedBy` int(10) NOT NULL DEFAULT '0',
`assignedTo` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'GUID of admin to whom ticket is assigned',
`comment` text NOT NULL,
`response` text NOT NULL,
`completed` tinyint(3) unsigned NOT NULL DEFAULT '0',
`escalated` tinyint(3) unsigned NOT NULL DEFAULT '0',
`viewed` tinyint(3) unsigned NOT NULL DEFAULT '0',
`haveTicket` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`ticketId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -0,0 +1 @@
ALTER TABLE character_glyphs CHANGE glyph1 glyph1 smallint(5) unsigned DEFAULT '0';
@@ -0,0 +1,3 @@
ALTER TABLE `gm_tickets`
ADD COLUMN `response` text NOT NULL AFTER `comment`,
ADD COLUMN `haveTicket` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `viewed`;
@@ -0,0 +1,2 @@
-- increase droprate for Plump Buzzard Wing
UPDATE `creature_loot_template` SET `chanceOrQuestChance`=-50 WHERE `item`=23239;
@@ -0,0 +1 @@
UPDATE `spell_proc_event` SET `procflags`=0x15510 WHERE `entry`=53386;
@@ -0,0 +1,9 @@
-- Improved Scorch, Improved Shadow Bolt and Winter's Chill effect should not stack
DELETE FROM `spell_group` WHERE `id`=1037;
INSERT INTO `spell_group`(`id`,`spell_id`) VALUES
(1037,22959),
(1037,17800),
(1037,12579);
DELETE FROM `spell_group_stack_rules` WHERE `group_id`=1037;
INSERT INTO `spell_group_stack_rules`(`group_id`,`stack_rule`) VALUES (1037,3);
@@ -0,0 +1,11 @@
-- Blood Frenzy (Warrior) and Savage Combat effect should not stack
DELETE FROM `spell_group` WHERE `id`=1119;
INSERT INTO `spell_group`(`id`,`spell_id`) VALUES
(1119,30069),
(1119,58684);
DELETE FROM `spell_group_stack_rules` WHERE `group_id`=1119;
INSERT INTO `spell_group_stack_rules`(`group_id`,`stack_rule`) VALUES (1119,3);
-- Remove invalid spell_groups
DELETE FROM `spell_group` WHERE `id` IN (1038,1039);
@@ -0,0 +1,9 @@
SET @GROUP := 1120;
-- Totem of Wrath and Heart of the Crusader effect should not stack
DELETE FROM `spell_group` WHERE `id`=@GROUP;
INSERT INTO `spell_group`(`id`,`spell_id`) VALUES
(@GROUP,21183),
(@GROUP,30708);
DELETE FROM `spell_group_stack_rules` WHERE `group_id`=@GROUP;
INSERT INTO `spell_group_stack_rules`(`group_id`,`stack_rule`) VALUES (@GROUP,3);
@@ -0,0 +1,2 @@
-- Remove all bgs from e1bee86ee6f5c3ab7b1da6d1b54c98c2851f11ec
DELETE FROM `battleground_template` WHERE `id` = 6; -- all Bgs
@@ -0,0 +1,92 @@
SET @GUID = 74685;
SET @MAP = 571;
DELETE FROM `gameobject` WHERE (`id` IN (192254,192255,192269,192284,192285,192336,192338,192339,192349,192350,192351,192352,192353,192354,192355,192356,192357,192358,192359,192360,192361,192362,192363,192364,192366,192367,192368,192369,192370,192371,192372,192373,192374,192375,192378,192379,192416,192488,192501) AND `guid` != 67250) OR `guid` BETWEEN @GUID AND @GUID+87;
INSERT INTO `gameobject` (`guid`,`id`,`map`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`) VALUES
(@GUID+0, 192488, @MAP, 64, 5262.540039, 3047.949951, 432.054993, 3.106650), -- Flag on tower
(@GUID+1, 192501, @MAP, 128, 5262.540039, 3047.949951, 432.054993, 3.106650), -- Flag on tower
(@GUID+2, 192374, @MAP, 64, 5272.939941, 2976.550049, 444.492004, 3.124120), -- Flag on Wall Intersect
(@GUID+3, 192416, @MAP, 128, 5272.939941, 2976.550049, 444.492004, 3.124120), -- Flag on Wall Intersect
(@GUID+4, 192375, @MAP, 64, 5235.189941, 2941.899902, 444.278015, 1.588250), -- Flag on Wall Intersect
(@GUID+5, 192416, @MAP, 128, 5235.189941, 2941.899902, 444.278015, 1.588250), -- Flag on Wall Intersect
(@GUID+6, 192488, @MAP, 64, 5163.129883, 2952.590088, 433.502991, 1.535890), -- Flag on tower
(@GUID+7, 192501, @MAP, 128, 5163.129883, 2952.590088, 433.502991, 1.535890), -- Flag on tower
(@GUID+8, 192488, @MAP, 64, 5145.109863, 2935.000000, 433.385986, 3.141590), -- Flag on tower
(@GUID+9, 192501, @MAP, 128, 5145.109863, 2935.000000, 433.385986, 3.141590), -- Flag on tower
(@GUID+10, 192488, @MAP, 64, 5158.810059, 2883.129883, 431.618011, 3.141590), -- Flag on wall
(@GUID+11, 192416, @MAP, 128, 5158.810059, 2883.129883, 431.618011, 3.141590), -- Flag on wall
(@GUID+12, 192336, @MAP, 64, 5154.490234, 2862.149902, 445.011993, 3.141590), -- Flag on Wall Intersect
(@GUID+13, 192416, @MAP, 128, 5154.490234, 2862.149902, 445.011993, 3.141590), -- Flag on Wall Intersect
(@GUID+14, 192255, @MAP, 64, 5154.520020, 2853.310059, 409.183014, 3.141590), -- Flag on the floor
(@GUID+15, 192269, @MAP, 128, 5154.520020, 2853.310059, 409.183014, 3.141590), -- Flag on the floor
(@GUID+16, 192254, @MAP, 64, 5154.459961, 2828.939941, 409.188995, 3.141590), -- Flag on the floor
(@GUID+17, 192269, @MAP, 128, 5154.459961, 2828.939941, 409.188995, 3.141590), -- Flag on the floor
(@GUID+18, 192349, @MAP, 64, 5155.310059, 2820.739990, 444.979004, -3.13286), -- Flag on wall intersect
(@GUID+19, 192416, @MAP, 128, 5155.310059, 2820.739990, 444.979004, -3.13286), -- Flag on wall intersect
(@GUID+20, 192488, @MAP, 64, 5160.339844, 2798.610107, 430.769012, 3.141590), -- Flag on wall
(@GUID+21, 192416, @MAP, 128, 5160.339844, 2798.610107, 430.769012, 3.141590), -- Flag on wall
(@GUID+22, 192488, @MAP, 64, 5146.040039, 2747.209961, 433.584015, 3.071770), -- Flag on tower
(@GUID+23, 192501, @MAP, 128, 5146.040039, 2747.209961, 433.584015, 3.071770), -- Flag on tower
(@GUID+24, 192488, @MAP, 64, 5163.779785, 2729.679932, 433.394012, -1.58825), -- Flag on tower
(@GUID+25, 192501, @MAP, 128, 5163.779785, 2729.679932, 433.394012, -1.58825), -- Flag on tower
(@GUID+26, 192366, @MAP, 64, 5236.270020, 2739.459961, 444.992004, -1.59698), -- Flag on wall intersect
(@GUID+27, 192416, @MAP, 128, 5236.270020, 2739.459961, 444.992004, -1.59698), -- Flag on wall intersect
(@GUID+28, 192367, @MAP, 64, 5271.799805, 2704.870117, 445.183014, -3.13286), -- Flag on wall intersect
(@GUID+29, 192416, @MAP, 128, 5271.799805, 2704.870117, 445.183014, -3.13286), -- Flag on wall intersect
(@GUID+30, 192488, @MAP, 64, 5260.819824, 2631.800049, 433.324005, 3.054330), -- Flag on tower
(@GUID+31, 192501, @MAP, 128, 5260.819824, 2631.800049, 433.324005, 3.054330), -- Flag on tower
(@GUID+32, 192488, @MAP, 64, 5278.379883, 2613.830078, 433.408997, -1.58825), -- Flag on tower
(@GUID+33, 192501, @MAP, 128, 5278.379883, 2613.830078, 433.408997, -1.58825), -- Flag on tower
(@GUID+34, 192364, @MAP, 64, 5350.879883, 2622.719971, 444.686005, -1.57080), -- Flag on wall intersect
(@GUID+35, 192416, @MAP, 128, 5350.879883, 2622.719971, 444.686005, -1.57080), -- Flag on wall intersect
(@GUID+36, 192370, @MAP, 64, 5392.270020, 2639.739990, 435.330994, 1.509710), -- Flag on wall intersect
(@GUID+37, 192416, @MAP, 128, 5392.270020, 2639.739990, 435.330994, 1.509710), -- Flag on wall intersect
(@GUID+38, 192369, @MAP, 64, 5350.950195, 2640.360107, 435.407990, 1.570800), -- Flag on wall intersect
(@GUID+39, 192416, @MAP, 128, 5350.950195, 2640.360107, 435.407990, 1.570800), -- Flag on wall intersect
(@GUID+40, 192368, @MAP, 64, 5289.459961, 2704.679932, 435.875000, -0.01745), -- Flag on wall intersect
(@GUID+41, 192416, @MAP, 128, 5289.459961, 2704.679932, 435.875000, -0.01745), -- Flag on wall intersect
(@GUID+42, 192362, @MAP, 64, 5322.120117, 2763.610107, 444.973999, -1.55334), -- Flag on wall intersect
(@GUID+43, 192416, @MAP, 128, 5322.120117, 2763.610107, 444.973999, -1.55334), -- Flag on wall intersect
(@GUID+44, 192363, @MAP, 64, 5363.609863, 2763.389893, 445.023987, -1.54462), -- Flag on wall intersect
(@GUID+45, 192416, @MAP, 128, 5363.609863, 2763.389893, 445.023987, -1.54462), -- Flag on wall intersect
(@GUID+46, 192379, @MAP, 64, 5363.419922, 2781.030029, 435.763000, 1.570800), -- Flag on wall intersect
(@GUID+47, 192416, @MAP, 128, 5363.419922, 2781.030029, 435.763000, 1.570800), -- Flag on wall intersect
(@GUID+48, 192378, @MAP, 64, 5322.020020, 2781.129883, 435.811005, 1.570800), -- Flag on wall intersect
(@GUID+49, 192416, @MAP, 128, 5322.020020, 2781.129883, 435.811005, 1.570800), -- Flag on wall intersect
(@GUID+50, 192355, @MAP, 64, 5288.919922, 2820.219971, 435.721008, 0.017452), -- Flag on wall intersect
(@GUID+51, 192416, @MAP, 128, 5288.919922, 2820.219971, 435.721008, 0.017452), -- Flag on wall intersect
(@GUID+52, 192354, @MAP, 64, 5288.410156, 2861.790039, 435.721008, 0.017452), -- Flag on wall intersect
(@GUID+53, 192416, @MAP, 128, 5288.410156, 2861.790039, 435.721008, 0.017452), -- Flag on wall intersect
(@GUID+54, 192358, @MAP, 64, 5322.229980, 2899.429932, 435.808014, -1.58825), -- Flag on wall intersect
(@GUID+55, 192416, @MAP, 128, 5322.229980, 2899.429932, 435.808014, -1.58825), -- Flag on wall intersect
(@GUID+56, 192359, @MAP, 64, 5364.350098, 2899.399902, 435.838989, -1.57080), -- Flag on wall intersect
(@GUID+57, 192416, @MAP, 128, 5364.350098, 2899.399902, 435.838989, -1.57080), -- Flag on wall intersect
(@GUID+58, 192338, @MAP, 64, 5397.759766, 2873.080078, 455.460999, 3.106650), -- Flag on keep
(@GUID+59, 192416, @MAP, 128, 5397.759766, 2873.080078, 455.460999, 3.106650), -- Flag on keep
(@GUID+60, 192339, @MAP, 64, 5397.390137, 2809.330078, 455.343994, 3.106650), -- Flag on keep
(@GUID+61, 192416, @MAP, 128, 5397.390137, 2809.330078, 455.343994, 3.106650), -- Flag on keep
(@GUID+62, 192284, @MAP, 64, 5372.479980, 2862.500000, 409.049011, 3.141590), -- Flag on floor
(@GUID+63, 192269, @MAP, 128, 5372.479980, 2862.500000, 409.049011, 3.141590), -- Flag on floor
(@GUID+64, 192285, @MAP, 64, 5371.490234, 2820.800049, 409.177002, 3.141590), -- Flag on floor
(@GUID+65, 192269, @MAP, 128, 5371.490234, 2820.800049, 409.177002, 3.141590), -- Flag on floor
(@GUID+66, 192371, @MAP, 64, 5364.290039, 2916.939941, 445.330994, 1.579520), -- Flag on wall intersect
(@GUID+67, 192416, @MAP, 128, 5364.290039, 2916.939941, 445.330994, 1.579520), -- Flag on wall intersect
(@GUID+68, 192372, @MAP, 64, 5322.859863, 2916.949951, 445.153992, 1.562070), -- Flag on wall intersect
(@GUID+69, 192416, @MAP, 128, 5322.859863, 2916.949951, 445.153992, 1.562070), -- Flag on wall intersect
(@GUID+70, 192373, @MAP, 64, 5290.350098, 2976.560059, 435.221008, 0.017452), -- Flag on wall intersect
(@GUID+71, 192416, @MAP, 128, 5290.350098, 2976.560059, 435.221008, 0.017452), -- Flag on wall intersect
(@GUID+72, 192360, @MAP, 64, 5352.370117, 3037.090088, 435.252014, -1.57080), -- Flag on wall intersect
(@GUID+73, 192416, @MAP, 128, 5352.370117, 3037.090088, 435.252014, -1.57080), -- Flag on wall intersect
(@GUID+74, 192361, @MAP, 64, 5392.649902, 3037.110107, 433.713013, -1.52716), -- Flag on wall intersect
(@GUID+75, 192416, @MAP, 128, 5392.649902, 3037.110107, 433.713013, -1.52716), -- Flag on wall intersect
(@GUID+76, 192356, @MAP, 64, 5237.069824, 2757.030029, 435.795990, 1.518440), -- Flag on wall intersect
(@GUID+77, 192416, @MAP, 128, 5237.069824, 2757.030029, 435.795990, 1.518440), -- Flag on wall intersect
(@GUID+78, 192352, @MAP, 64, 5173.020020, 2820.929932, 435.720001, 0.017452), -- Flag on wall intersect
(@GUID+79, 192416, @MAP, 128, 5173.020020, 2820.929932, 435.720001, 0.017452), -- Flag on wall intersect
(@GUID+80, 192353, @MAP, 64, 5172.109863, 2862.570068, 435.721008, 0.017452), -- Flag on wall intersect
(@GUID+81, 192416, @MAP, 128, 5172.109863, 2862.570068, 435.721008, 0.017452), -- Flag on wall intersect
(@GUID+82, 192357, @MAP, 64, 5235.339844, 2924.340088, 435.040009, -1.57080), -- Flag on wall intersect
(@GUID+83, 192416, @MAP, 128, 5235.339844, 2924.340088, 435.040009, -1.57080), -- Flag on wall intersect
(@GUID+84, 192350, @MAP, 64, 5270.689941, 2861.780029, 445.058014, -3.11539), -- Flag on wall intersect
(@GUID+85, 192416, @MAP, 128, 5270.689941, 2861.780029, 445.058014, -3.11539), -- Flag on wall intersect
(@GUID+86, 192351, @MAP, 64, 5271.279785, 2820.159912, 445.200989, -3.13286), -- Flag on wall intersect
(@GUID+87, 192416, @MAP, 128, 5271.279785, 2820.159912, 445.200989, -3.13286); -- Flag on wall intersect
@@ -0,0 +1,25 @@
-- Orb rotation focus
UPDATE `creature_template` SET `modelid1`=11868,`modelid2`=169,`minlevel`=80,`maxlevel`=80,`faction_A`=14,`faction_H`=14,`speed_walk`=2.2,`speed_run`=0.785714,`baseattacktime`=2000,`unit_flags`=33554688 WHERE `entry` IN(43280,43281,43282);
UPDATE `creature_template` SET `difficulty_entry_1`=43280, `difficulty_entry_2`=43281,`difficulty_entry_3`=43282 WHERE `entry`=40091;
-- Orb carrier
UPDATE `creature_template` SET `minlevel`=80,`maxlevel`=80,`exp`=2,`faction_A`=14,`faction_H`=14,`speed_walk`=1.2,`speed_run`=1.14286,`baseattacktime`=2000 WHERE `entry` IN(40470,40471,40472);
UPDATE `creature_template` SET `difficulty_entry_1`=40470, `difficulty_entry_2`=40471,`difficulty_entry_3`=40472 WHERE `entry`=40081;
-- Saviana Ragefire
UPDATE `creature_template` SET `exp`=2 WHERE `entry`=39823;
-- General Zarithrian
UPDATE `creature_template` SET `exp`=2 WHERE `entry`=39805;
-- Twilight Halion
UPDATE `creature_template` SET `difficulty_entry_1`=40143, `difficulty_entry_2`=40144,`difficulty_entry_3`=40145 WHERE `entry`=40142;
UPDATE `creature_template` SET `minlevel`=83,`maxlevel`=83,`speed_walk`=1.6,`speed_run`=1.42857,`baseattacktime`=1800,`unit_flags`=559168,`dynamicflags`=12 WHERE `entry` IN(40143,40144,40145);
-- Halion
UPDATE `creature_template` SET `speed_walk`=1.6,`speed_run`=1.42857,`baseattacktime`=1500,`unit_flags`=32832,`dynamicflags`=12,`flags_extra`=1 WHERE `entry` IN(39864,39944,39945);
UPDATE `creature_template` SET `dmg_multiplier`=50 WHERE `entry`=39944;
UPDATE `creature_template` SET `dmg_multiplier`=85 WHERE `entry`=39945;
-- Onyx Flamecaller
UPDATE `creature_template` SET `minlevel`=82,`maxlevel`=82,`faction_A`=103,`faction_H`=103,`exp`=2,`speed_walk`=0.88888,`speed_run`=1.42857,`baseattacktime`=2000,`unit_flags`=32768,`equipment_id`=2468 WHERE `entry`=39815;
@@ -0,0 +1,4 @@
ALTER TABLE `spell_area` ADD COLUMN `quest_start_status` INT(11) NOT NULL DEFAULT 64; -- default is QUEST_STATUS_REWARDED
ALTER TABLE `spell_area` ADD COLUMN `quest_end_status` INT(11) NOT NULL DEFAULT 11; -- default is QUEST_STATUS_COMPLETE | QUEST_STATUS_NONE | QUEST_STATUS_INCOMPLETE
UPDATE spell_area SET `quest_start_status` = (1 << 6) | (1 << 3) | (1 << 1) WHERE `quest_start_active` = 1;
ALTER TABLE spell_area DROP COLUMN `quest_start_active`;
@@ -0,0 +1,17 @@
DELETE FROM `trinity_string` WHERE `entry` IN (9986, 9987, 9989, 9990, 9991, 9992, 9993, 9994, 9995, 9996, 9997, 9998, 9999);
INSERT INTO `trinity_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`)
VALUES
(9986, 'Error', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9987, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9988, 'Leader', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9989, 'Dps', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9990, 'Healer', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9991, 'Tank', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9992, 'Raid browser', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9993, 'Finished dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9994, 'In dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9995, 'Vote kick', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9996, 'Proposal', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9997, 'Queued', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9998, 'Role check', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9999, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
@@ -0,0 +1,36 @@
-- Gnomeregan/Blastmaster Emi Shortfuse's event
DELETE FROM `script_texts` WHERE `entry` BETWEEN -1090028 AND -1090000;
DELETE FROM `creature_text` WHERE `entry` IN (7361,7998);
INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES
-- Emi Shortfuse
(7998,0,0, 'With your help, I can evaluate these tunnels.',12,0,100,0,0,0, 'SAY_BLASTMASTER_0'),
(7998,1,0, 'Let''s see if we can find out where these Troggs are coming from... and put a stop to the invasion!',12,0,100,0,0,0, 'SAY_BLASTMASTER_1'),
(7998,2,0, 'Such devastation... what horrible mess...',12,0,100,0,0,0, 'SAY_BLASTMASTER_2'),
(7998,3,0, 'It''s quiet here...',12,0,100,0,0,0, 'SAY_BLASTMASTER_3'),
(7998,4,0, '...too quiet.',12,0,100,0,0,0, 'SAY_BLASTMASTER_4'),
(7998,5,0, 'Look! Over there at the tunnel wall!',12,0,100,0,0,0, 'SAY_BLASTMASTER_5'),
(7998,6,0, 'Trogg incrusion! Defend me while I blast the hole closed!',12,0,100,0,0,0, 'SAY_BLASTMASTER_6'),
(7998,7,0, 'The charges are set. Get back before they blow!',12,0,100,0,0,0, 'SAY_BLASTMASTER_7'),
(7998,8,0, 'Incoming blast in 10 seconds!',14,0,100,0,0,0, 'SAY_BLASTMASTER_8'),
(7998,9,0, 'Incoming blast in 5 seconds. Clear the tunnel!',14,0,100,0,0,0, 'SAY_BLASTMASTER_9'),
(7998,10,0, 'FIRE IN THE HOLE!',14,0,100,0,0,0, 'SAY_BLASTMASTER_10'),
(7998,11,0, 'Well done! Without your help I would have never been able to thwart that wave of troggs.',12,0,100,0,0,0, 'SAY_BLASTMASTER_11'),
(7998,12,0, 'Did you hear something?',12,0,100,0,0,0, 'SAY_BLASTMASTER_12'),
(7998,13,0, 'I heard something over there.',12,0,100,0,0,0, 'SAY_BLASTMASTER_13'),
(7998,14,0, 'More troggs! Ward them off as I prepare the explosives!',12,0,100,0,0,0, 'SAY_BLASTMASTER_14'),
(7998,15,0, 'The final charge is set. Stand back!',12,0,100,0,0,0, 'SAY_BLASTMASTER_15'),
(7998,16,0, 'The final charge is set. Stand back!',12,0,100,0,0,0, 'SAY_BLASTMASTER_16'),
(7998,17,0, 'Incoming blast in 10 seconds!',14,0,100,0,0,0, 'SAY_BLASTMASTER_17'),
(7998,18,0, 'Incoming blast in 5 seconds. Clear the tunnel!',14,0,100,0,0,0, 'SAY_BLASTMASTER_18'),
(7998,19,0, 'I don''t think one charge is going to cut it. Keep fending them off!',12,0,100,0,0,0, 'SAY_BLASTMASTER_19'),
(7998,20,0, 'FIRE IN THE HOLE!',14,0,100,0,0,0, 'SAY_BLASTMASTER_20'),
(7998,21,0, 'Well done! Without your help I would have never been able to thwart that wave of troggs.',12,0,100,0,0,0, 'SAY_BLASTMASTER_21'),
(7998,22,0, 'Did you hear something?',12,0,100,0,0,0, 'SAY_BLASTMASTER_22'),
(7998,23,0, 'I heard something over there.',12,0,100,0,0,0, 'SAY_BLASTMASTER_23'),
(7998,24,0, 'More troggs! Ward them off as I prepare the explosives!',12,0,100,0,0,0, 'SAY_BLASTMASTER_24'),
(7998,25,0, 'The final charge is set. Stand back!',12,0,100,0,0,0, 'SAY_BLASTMASTER_25'),
(7998,26,0, '10 seconds to blast! Stand back!!!',14,0,100,0,0,0, 'SAY_BLASTMASTER_26'),
(7998,27,0, '5 seconds until detonation!!',14,0,100,0,0,0, 'SAY_BLASTMASTER_27'),
(7998,28,0, 'Superb! Because of your help, my people stand a chance of re-taking our belowed city. Three cheers to you!',12,0,100,0,0,0, 'SAY_BLASTMASTER_28'),
-- Grubbis
(7361,0,0, 'We come from below! You can never stop us!',14,0,100,0,0,0, 'SAY_GRUBBIS');
+14 -2
View File
@@ -71,6 +71,8 @@ void PetAI::_stopAttack()
}
me->AttackStop();
me->InterruptNonMeleeSpells(false);
me->SendMeleeAttackStop(); // Should stop pet's attack button from flashing
me->GetCharmInfo()->SetIsCommandAttack(false);
HandleReturnMovement();
}
@@ -89,7 +91,8 @@ void PetAI::UpdateAI(const uint32 diff)
m_updateAlliesTimer -= diff;
// me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc.
if (me->getVictim())
// Must also check if victim is alive
if (me->getVictim() && me->getVictim()->isAlive())
{
// is only necessary to stop casting, the pet must not exit combat
if (me->getVictim()->HasBreakableByDamageCrowdControlAura(me))
@@ -121,11 +124,17 @@ void PetAI::UpdateAI(const uint32 diff)
if (nextTarget)
AttackStart(nextTarget);
else
{
me->GetCharmInfo()->SetIsCommandAttack(false);
HandleReturnMovement();
}
}
else
{
me->GetCharmInfo()->SetIsCommandAttack(false);
HandleReturnMovement();
}
}
else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim
HandleReturnMovement();
@@ -301,7 +310,7 @@ void PetAI::KilledUnit(Unit* victim)
// Can't use _stopAttack() because that activates movement handlers and ignores
// next target selection
me->AttackStop();
me->GetCharmInfo()->SetIsCommandAttack(false);
me->InterruptNonMeleeSpells(false);
me->SendMeleeAttackStop(); // Stops the pet's 'Attack' button from flashing
Unit* nextTarget = SelectNextTarget();
@@ -309,7 +318,10 @@ void PetAI::KilledUnit(Unit* victim)
if (nextTarget)
AttackStart(nextTarget);
else
{
me->GetCharmInfo()->SetIsCommandAttack(false);
HandleReturnMovement(); // Return
}
}
void PetAI::AttackStart(Unit* target)
-2
View File
@@ -32,8 +32,6 @@ class PetAI : public CreatureAI
explicit PetAI(Creature* c);
void EnterEvadeMode();
void JustDied(Unit* /*who*/) { _stopAttack(); }
void UpdateAI(const uint32);
static int Permissible(const Creature*);
@@ -2821,10 +2821,12 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
case SMART_EVENT_UPDATE:
case SMART_EVENT_UPDATE_IC:
case SMART_EVENT_UPDATE_OOC:
case SMART_EVENT_OOC_LOS:
case SMART_EVENT_IC_LOS:
RecalcTimer(e, e.event.minMaxRepeat.min, e.event.minMaxRepeat.max);
break;
case SMART_EVENT_IC_LOS:
case SMART_EVENT_OOC_LOS:
RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax);
break;
default:
e.active = true;
break;
@@ -1596,6 +1596,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
{
// Check map id requirement
if (miscValue1 == achievementCriteria->win_arena.mapID)
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
// std case: not exist in DBC, not triggered in code as result
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
@@ -1606,7 +1613,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
break;
// FIXME: not triggered in code as result, need to implement
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
@@ -1749,6 +1755,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
return progress->counter >= achievementCriteria->use_lfg.dungeonsComplete;
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
return progress->counter >= achievementCriteria->get_killing_blow.killCount;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
return achievementCriteria->win_arena.count && progress->counter >= achievementCriteria->win_arena.count;
// handle all statistic-only criteria here
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
@@ -188,29 +188,6 @@ bool BattlefieldWG::SetupBattlefield()
go->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[GetDefenderTeam()]);
}
// Spawn banners in the keep
for (uint8 i = 0; i < WG_KEEPGAMEOBJECT_MAX; i++)
{
if (GameObject* go = SpawnGameObject(WGKeepGameObject[i].entryHorde, WGKeepGameObject[i].x, WGKeepGameObject[i].y, WGKeepGameObject[i].z, WGKeepGameObject[i].o))
{
go->SetRespawnTime(GetDefenderTeam()? RESPAWN_ONE_DAY : RESPAWN_IMMEDIATELY);
m_KeepGameObject[1].insert(go);
}
if (GameObject* go = SpawnGameObject(WGKeepGameObject[i].entryAlliance, WGKeepGameObject[i].x, WGKeepGameObject[i].y, WGKeepGameObject[i].z, WGKeepGameObject[i].o))
{
go->SetRespawnTime(GetDefenderTeam()? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY);
m_KeepGameObject[0].insert(go);
}
}
// Show defender banner in keep
for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetDefenderTeam()].begin(); itr != m_KeepGameObject[GetDefenderTeam()].end(); ++itr)
(*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY);
// Hide attackant banner in keep
for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetAttackerTeam()].begin(); itr != m_KeepGameObject[GetAttackerTeam()].end(); ++itr)
(*itr)->SetRespawnTime(RESPAWN_ONE_DAY);
UpdateCounterVehicle(true);
return true;
}
@@ -440,10 +440,9 @@ uint32 const VehNumWorldState[] = { 3680, 3490 };
uint32 const MaxVehNumWorldState[] = { 3681, 3491 };
uint32 const ClockWorldState[] = { 3781, 4354 };
uint32 const WintergraspFaction[] = { 1732, 1735, 35 };
float const WintergraspStalkerPos[] = { 0, 0, 0, 0 };
float const WintergraspStalkerPos[] = { 4948.985f, 2937.789f, 550.5172f, 1.815142f };
uint8 const WG_MAX_OBJ = 32;
uint8 const WG_KEEPGAMEOBJECT_MAX = 44;
uint8 const WG_MAX_TURRET = 15;
uint8 const WG_MAX_KEEP_NPC = 39;
uint8 const WG_MAX_OUTSIDE_NPC = 14;
@@ -580,6 +579,19 @@ struct WintergraspBuildingSpawnData
uint32 nameId;
};
struct WintergraspRebuildableBuildingData
{
uint32 entry;
uint64 Guid;
uint32 WorldState;
float x;
float y;
float z;
float o;
uint32 type;
uint32 nameId;
};
const WintergraspBuildingSpawnData WGGameObjectBuilding[WG_MAX_OBJ] =
{
// Wall (Not spawned in db)
@@ -628,99 +640,6 @@ const WintergraspBuildingSpawnData WGGameObjectBuilding[WG_MAX_OBJ] =
{ GO_WINTERGRASP_VAULT_GATE, 3773, 5397.11f, 2841.54f, 425.899f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST, 0 },
};
// *********************************************************
// **********Keep Element(GameObject,Creature)**************
// *********************************************************
// Keep gameobject
// 192488 : 10 in sql, 19 in header
// 192501 : 12 in sql, 17 in header
// 192416 : 1 in sql, 33 in header
// 192374 : 1 in sql, 1 in header
// 192375 : 1 in sql, 1 in header
// 192336 : 1 in sql, 1 in header
// 192255 : 1 in sql, 1 in header
// 192269 : 1 in sql, 7 in header
// 192254 : 1 in sql, 1 in header
// 192349 : 1 in sql, 1 in header
// 192366 : 1 in sql, 3 in header
// 192367 : 1 in sql, 1 in header
// 192364 : 1 in sql, 1 in header
// 192370 : 1 in sql, 1 in header
// 192369 : 1 in sql, 1 in header
// 192368 : 1 in sql, 1 in header
// 192362 : 1 in sql, 1 in header
// 192363 : 1 in sql, 1 in header
// 192379 : 1 in sql, 1 in header
// 192378 : 1 in sql, 1 in header
// 192355 : 1 in sql, 1 in header
// 192354 : 1 in sql, 1 in header
// 192358 : 1 in sql, 1 in header
// 192359 : 1 in sql, 1 in header
// 192338 : 1 in sql, 1 in header
// 192339 : 1 in sql, 1 in header
// 192284 : 1 in sql, 1 in header
// 192285 : 1 in sql, 1 in header
// 192371 : 1 in sql, 1 in header
// 192372 : 1 in sql, 1 in header
// 192373 : 1 in sql, 1 in header
// 192360 : 1 in sql, 1 in header
// 192361 : 1 in sql, 1 in header
// 192356 : 1 in sql, 1 in header
// 192352 : 1 in sql, 1 in header
// 192353 : 1 in sql, 1 in header
// 192357 : 1 in sql, 1 in header
// 192350 : 1 in sql, 1 in header
// 192351 : 1 in sql, 1 in header
const WintergraspObjectPositionData WGKeepGameObject[WG_KEEPGAMEOBJECT_MAX] =
{
{ 5262.540039f, 3047.949951f, 432.054993f, 3.106650f, 192488, 192501 }, // Flag on tower
{ 5272.939941f, 2976.550049f, 444.492004f, 3.124120f, 192374, 192416 }, // Flag on Wall Intersect
{ 5235.189941f, 2941.899902f, 444.278015f, 1.588250f, 192375, 192416 }, // Flag on Wall Intersect
{ 5163.129883f, 2952.590088f, 433.502991f, 1.535890f, 192488, 192501 }, // Flag on tower
{ 5145.109863f, 2935.000000f, 433.385986f, 3.141590f, 192488, 192501 }, // Flag on tower
{ 5158.810059f, 2883.129883f, 431.618011f, 3.141590f, 192488, 192416 }, // Flag on wall
{ 5154.490234f, 2862.149902f, 445.011993f, 3.141590f, 192336, 192416 }, // Flag on Wall Intersect
{ 5154.520020f, 2853.310059f, 409.183014f, 3.141590f, 192255, 192269 }, // Flag on the floor
{ 5154.459961f, 2828.939941f, 409.188995f, 3.141590f, 192254, 192269 }, // Flag on the floor
{ 5155.310059f, 2820.739990f, 444.979004f, -3.13286f, 192349, 192416 }, // Flag on wall intersect
{ 5160.339844f, 2798.610107f, 430.769012f, 3.141590f, 192488, 192416 }, // Flag on wall
{ 5146.040039f, 2747.209961f, 433.584015f, 3.071770f, 192488, 192501 }, // Flag on tower
{ 5163.779785f, 2729.679932f, 433.394012f, -1.58825f, 192488, 192501 }, // Flag on tower
{ 5236.270020f, 2739.459961f, 444.992004f, -1.59698f, 192366, 192416 }, // Flag on wall intersect
{ 5271.799805f, 2704.870117f, 445.183014f, -3.13286f, 192367, 192416 }, // Flag on wall intersect
{ 5260.819824f, 2631.800049f, 433.324005f, 3.054330f, 192488, 192501 }, // Flag on tower
{ 5278.379883f, 2613.830078f, 433.408997f, -1.58825f, 192488, 192501 }, // Flag on tower
{ 5350.879883f, 2622.719971f, 444.686005f, -1.57080f, 192364, 192416 }, // Flag on wall intersect
{ 5392.270020f, 2639.739990f, 435.330994f, 1.509710f, 192370, 192416 }, // Flag on wall intersect
{ 5350.950195f, 2640.360107f, 435.407990f, 1.570800f, 192369, 192416 }, // Flag on wall intersect
{ 5289.459961f, 2704.679932f, 435.875000f, -0.01745f, 192368, 192416 }, // Flag on wall intersect
{ 5322.120117f, 2763.610107f, 444.973999f, -1.55334f, 192362, 192416 }, // Flag on wall intersect
{ 5363.609863f, 2763.389893f, 445.023987f, -1.54462f, 192363, 192416 }, // Flag on wall intersect
{ 5363.419922f, 2781.030029f, 435.763000f, 1.570800f, 192379, 192416 }, // Flag on wall intersect
{ 5322.020020f, 2781.129883f, 435.811005f, 1.570800f, 192378, 192416 }, // Flag on wall intersect
{ 5288.919922f, 2820.219971f, 435.721008f, 0.017452f, 192355, 192416 }, // Flag on wall intersect
{ 5288.410156f, 2861.790039f, 435.721008f, 0.017452f, 192354, 192416 }, // Flag on wall intersect
{ 5322.229980f, 2899.429932f, 435.808014f, -1.58825f, 192358, 192416 }, // Flag on wall intersect
{ 5364.350098f, 2899.399902f, 435.838989f, -1.57080f, 192359, 192416 }, // Flag on wall intersect
{ 5397.759766f, 2873.080078f, 455.460999f, 3.106650f, 192338, 192416 }, // Flag on keep
{ 5397.390137f, 2809.330078f, 455.343994f, 3.106650f, 192339, 192416 }, // Flag on keep
{ 5372.479980f, 2862.500000f, 409.049011f, 3.141590f, 192284, 192269 }, // Flag on floor
{ 5371.490234f, 2820.800049f, 409.177002f, 3.141590f, 192285, 192269 }, // Flag on floor
{ 5364.290039f, 2916.939941f, 445.330994f, 1.579520f, 192371, 192416 }, // Flag on wall intersect
{ 5322.859863f, 2916.949951f, 445.153992f, 1.562070f, 192372, 192416 }, // Flag on wall intersect
{ 5290.350098f, 2976.560059f, 435.221008f, 0.017452f, 192373, 192416 }, // Flag on wall intersect
{ 5352.370117f, 3037.090088f, 435.252014f, -1.57080f, 192360, 192416 }, // Flag on wall intersect
{ 5392.649902f, 3037.110107f, 433.713013f, -1.52716f, 192361, 192416 }, // Flag on wall intersect
{ 5237.069824f, 2757.030029f, 435.795990f, 1.518440f, 192356, 192416 }, // Flag on wall intersect
{ 5173.020020f, 2820.929932f, 435.720001f, 0.017452f, 192352, 192416 }, // Flag on wall intersect
{ 5172.109863f, 2862.570068f, 435.721008f, 0.017452f, 192353, 192416 }, // Flag on wall intersect
{ 5235.339844f, 2924.340088f, 435.040009f, -1.57080f, 192357, 192416 }, // Flag on wall intersect
{ 5270.689941f, 2861.780029f, 445.058014f, -3.11539f, 192350, 192416 }, // Flag on wall intersect
{ 5271.279785f, 2820.159912f, 445.200989f, -3.13286f, 192351, 192416 } // Flag on wall intersect
};
const Position WGTurret[WG_MAX_TURRET] =
{
{ 5391.19f, 3060.8f, 419.616f, 1.69557f },
@@ -523,6 +523,8 @@ inline void Battleground::_ProcessJoin(uint32 diff)
player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
player->ResetAllPowers();
if (!player->isGameMaster())
{
// remove auras with duration lower than 30s
Unit::AuraApplicationMap & auraMap = player->GetAppliedAuras();
for (Unit::AuraApplicationMap::iterator iter = auraMap.begin(); iter != auraMap.end();)
@@ -539,6 +541,7 @@ inline void Battleground::_ProcessJoin(uint32 diff)
++iter;
}
}
}
CheckArenaWinConditions();
}
@@ -856,6 +859,7 @@ void Battleground::EndBattleground(uint32 winner)
// update achievement BEFORE personal rating update
uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot());
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA, GetMapId());
winnerArenaTeam->MemberWon(player, loserMatchmakerRating, winnerMatchmakerChange);
}
@@ -74,7 +74,7 @@ bool BattlegroundSA::ResetObjs()
uint32 atF = BG_SA_Factions[Attackers];
uint32 defF = BG_SA_Factions[Attackers ? TEAM_ALLIANCE : TEAM_HORDE];
for (uint8 i = 0; i <BG_SA_MAXOBJ; i++)
for (uint8 i = 0; i < BG_SA_MAXOBJ; i++)
DelObject(i);
for (uint8 i = 0; i < BG_SA_MAXNPC; i++)
@@ -94,14 +94,16 @@ bool BattlegroundSA::ResetObjs()
for (uint8 i = BG_SA_BOAT_ONE; i < BG_SA_SIGIL_1; i++)
{
uint32 boatid=0;
uint32 boatid = 0;
switch (i)
{
case BG_SA_BOAT_ONE:
boatid= Attackers ? BG_SA_BOAT_ONE_H : BG_SA_BOAT_ONE_A;
boatid = Attackers ? BG_SA_BOAT_ONE_H : BG_SA_BOAT_ONE_A;
break;
case BG_SA_BOAT_TWO:
boatid= Attackers ? BG_SA_BOAT_TWO_H : BG_SA_BOAT_TWO_A;
boatid = Attackers ? BG_SA_BOAT_TWO_H : BG_SA_BOAT_TWO_A;
break;
default:
break;
}
if (!AddObject(i, boatid, BG_SA_ObjSpawnlocs[i][0],
@@ -110,6 +112,7 @@ bool BattlegroundSA::ResetObjs()
BG_SA_ObjSpawnlocs[i][3], 0, 0, 0, 0, RESPAWN_ONE_DAY))
return false;
}
for (uint8 i = BG_SA_SIGIL_1; i < BG_SA_CENTRAL_FLAG; i++)
{
if (!AddObject(i, BG_SA_ObjEntries[i],
@@ -127,7 +130,7 @@ bool BattlegroundSA::ResetObjs()
//Cannons and demolishers - NPCs are spawned
//By capturing GYs.
for (uint8 i = 0; i < BG_SA_NPC_SPARKLIGHT; i++)
for (uint8 i = 0; i < BG_SA_DEMOLISHER_5; i++)
{
if (!AddCreature(BG_SA_NpcEntries[i], i, (Attackers == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE),
BG_SA_NpcSpawnlocs[i][0], BG_SA_NpcSpawnlocs[i][1],
@@ -153,8 +156,8 @@ bool BattlegroundSA::ResetObjs()
TotalTime = 0;
ShipsStarted = false;
//Graveyards!
for (uint8 i = 0;i < BG_SA_MAX_GY; i++)
//Graveyards
for (uint8 i = 0; i < BG_SA_MAX_GY; i++)
{
WorldSafeLocsEntry const* sg = NULL;
sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
@@ -181,7 +184,7 @@ bool BattlegroundSA::ResetObjs()
//GY capture points
for (uint8 i = BG_SA_CENTRAL_FLAG; i < BG_SA_PORTAL_DEFFENDER_BLUE; i++)
{
AddObject(i, (BG_SA_ObjEntries[i] - (Attackers == TEAM_ALLIANCE ? 1:0)),
AddObject(i, (BG_SA_ObjEntries[i] - (Attackers == TEAM_ALLIANCE ? 1 : 0)),
BG_SA_ObjSpawnlocs[i][0], BG_SA_ObjSpawnlocs[i][1],
BG_SA_ObjSpawnlocs[i][2], BG_SA_ObjSpawnlocs[i][3],
0, 0, 0, 0, RESPAWN_ONE_DAY);
@@ -206,14 +209,14 @@ bool BattlegroundSA::ResetObjs()
GetBGObject(i)->SetUInt32Value(GAMEOBJECT_FACTION, atF);
}
//Player may enter BEFORE we set up bG - lets update his worldstates anyway...
UpdateWorldState(BG_SA_RIGHT_GY_HORDE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE?1:0);
UpdateWorldState(BG_SA_LEFT_GY_HORDE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE?1:0);
UpdateWorldState(BG_SA_CENTER_GY_HORDE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE?1:0);
//Player may enter BEFORE we set up BG - lets update his worldstates anyway...
UpdateWorldState(BG_SA_RIGHT_GY_HORDE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
UpdateWorldState(BG_SA_LEFT_GY_HORDE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
UpdateWorldState(BG_SA_CENTER_GY_HORDE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0);
UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0);
UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0);
UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
if (Attackers == TEAM_ALLIANCE)
{
@@ -254,6 +257,9 @@ bool BattlegroundSA::ResetObjs()
if (Player* player = ObjectAccessor::FindPlayer(itr->first))
SendTransportInit(player);
// set status manually so preparation is cast correctly in 2nd round too
SetStatus(STATUS_WAIT_JOIN);
TeleportPlayers();
return true;
}
@@ -295,7 +301,8 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
InitSecondRound = false;
SendMessageToAll(LANG_BG_SA_ROUND_TWO_ONE_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
}else
}
else
{
UpdateWaitTimer -= diff;
return;
@@ -312,7 +319,7 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
ToggleTimer();
DemolisherStartState(false);
Status = BG_SA_ROUND_ONE;
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE)?23748:21702);
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702);
}
if (TotalTime >= BG_SA_BOAT_START)
StartShips();
@@ -332,7 +339,12 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
ToggleTimer();
DemolisherStartState(false);
Status = BG_SA_ROUND_TWO;
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE)?23748:21702);
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702);
// status was set to STATUS_WAIT_JOIN manually for Preparation, set it back now
SetStatus(STATUS_IN_PROGRESS);
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if (Player* p = ObjectAccessor::FindPlayer(itr->first))
p->RemoveAurasDueToSpell(SPELL_PREPARATION);
}
if (TotalTime >= 30000)
{
@@ -371,7 +383,6 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
{
RoundScores[1].time = BG_SA_ROUNDLENGTH;
RoundScores[1].winner = (Attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE;
if (RoundScores[0].time == RoundScores[1].time)
EndBattleground(0);
else if (RoundScores[0].time < RoundScores[1].time)
@@ -411,7 +422,7 @@ void BattlegroundSA::FillInitialWorldStates(WorldPacket& data)
data << uint32(BG_SA_BONUS_TIMER) << uint32(0);
data << uint32(BG_SA_HORDE_ATTACKS)<< horde_attacks;
data << uint32(BG_SA_HORDE_ATTACKS) << horde_attacks;
data << uint32(BG_SA_ALLY_ATTACKS) << ally_attacks;
//Time will be sent on first update...
@@ -420,13 +431,13 @@ void BattlegroundSA::FillInitialWorldStates(WorldPacket& data)
data << uint32(BG_SA_TIMER_SEC_TENS) << uint32(0);
data << uint32(BG_SA_TIMER_SEC_DECS) << uint32(0);
data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE?1:0);
data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE?1:0);
data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE?1:0);
data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0);
data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0);
data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0);
data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0);
data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0);
data << uint32(BG_SA_HORDE_DEFENCE_TOKEN) << ally_attacks;
data << uint32(BG_SA_ALLIANCE_DEFENCE_TOKEN) << horde_attacks;
@@ -450,9 +461,9 @@ void BattlegroundSA::AddPlayer(Player* player)
player->CastSpell(player, 12438, true);//Without this player falls before boat loads...
if (urand(0, 1))
player->TeleportTo(607, 2682.936f, -830.368f, 50.0f, 2.895f, 0);
player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
else
player->TeleportTo(607, 2577.003f, 980.261f, 50.0f, 0.807f, 0);
player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
}
else
@@ -513,14 +524,18 @@ void BattlegroundSA::TeleportPlayers()
player->ResetAllPowers();
player->CombatStopWithPets(true);
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if (Player* p = ObjectAccessor::FindPlayer(itr->first))
p->CastSpell(p, SPELL_PREPARATION, true);
if (player->GetTeamId() == Attackers)
{
player->CastSpell(player, 12438, true); //Without this player falls before boat loads...
if (urand(0, 1))
player->TeleportTo(607, 2682.936f, -830.368f, 50.0f, 2.895f, 0);
player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
else
player->TeleportTo(607, 2577.003f, 980.261f, 50.0f, 0.807f, 0);
player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
}
else
player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
@@ -572,13 +587,13 @@ void BattlegroundSA::OverrideGunFaction()
if (!BgCreatures[0])
return;
for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10;i++)
for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10; i++)
{
if (Creature* gun = GetBGCreature(i))
gun->setFaction(BG_SA_Factions[Attackers? TEAM_ALLIANCE : TEAM_HORDE]);
gun->setFaction(BG_SA_Factions[Attackers ? TEAM_ALLIANCE : TEAM_HORDE]);
}
for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4;i++)
for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++)
{
if (Creature* dem = GetBGCreature(i))
dem->setFaction(BG_SA_Factions[Attackers]);
@@ -590,6 +605,7 @@ void BattlegroundSA::DemolisherStartState(bool start)
if (!BgCreatures[0])
return;
// set flags only for the demolishers on the beach, factory ones dont need it
for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++)
{
if (Creature* dem = GetBGCreature(i))
@@ -636,6 +652,8 @@ void BattlegroundSA::DestroyGate(Player* player, GameObject* go)
if (GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED)
rewardHonor = false;
break;
default:
break;
}
if (i < 5)
@@ -663,7 +681,7 @@ WorldSafeLocsEntry const* BattlegroundSA::GetClosestGraveYard(Player* player)
safeloc = BG_SA_GYEntries[BG_SA_DEFENDER_LAST_GY];
closest = sWorldSafeLocsStore.LookupEntry(safeloc);
nearest = sqrt((closest->x - x)*(closest->x - x) + (closest->y - y)*(closest->y - y)+(closest->z - z)*(closest->z - z));
nearest = sqrt((closest->x - x)*(closest->x - x) + (closest->y - y)*(closest->y - y) + (closest->z - z)*(closest->z - z));
for (uint8 i = BG_SA_RIGHT_CAPTURABLE_GY; i < BG_SA_MAX_GY; i++)
{
@@ -671,7 +689,7 @@ WorldSafeLocsEntry const* BattlegroundSA::GetClosestGraveYard(Player* player)
continue;
ret = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
dist = sqrt((ret->x - x)*(ret->x - x) + (ret->y - y)*(ret->y - y)+(ret->z - z)*(ret->z - z));
dist = sqrt((ret->x - x)*(ret->x - x) + (ret->y - y)*(ret->y - y) + (ret->z - z)*(ret->z - z));
if (dist < nearest)
{
closest = ret;
@@ -737,7 +755,7 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
case BG_SA_LEFT_CAPTURABLE_GY:
flag = BG_SA_LEFT_FLAG;
DelObject(flag);
AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0:1)),
AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)),
BG_SA_ObjSpawnlocs[flag][0], BG_SA_ObjSpawnlocs[flag][1],
BG_SA_ObjSpawnlocs[flag][2], BG_SA_ObjSpawnlocs[flag][3], 0, 0, 0, 0, RESPAWN_ONE_DAY);
@@ -746,8 +764,18 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1],
BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]);
UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0));
UpdateWorldState(BG_SA_LEFT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1));
for (uint8 j = BG_SA_DEMOLISHER_7; j <= BG_SA_DEMOLISHER_8; j++)
{
AddCreature(BG_SA_NpcEntries[j], j, (Attackers == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE),
BG_SA_NpcSpawnlocs[j][0], BG_SA_NpcSpawnlocs[j][1],
BG_SA_NpcSpawnlocs[j][2], BG_SA_NpcSpawnlocs[j][3], 600);
if (Creature* dem = GetBGCreature(j))
dem->setFaction(BG_SA_Factions[Attackers]);
}
UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 1 : 0));
UpdateWorldState(BG_SA_LEFT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 0 : 1));
if (Source->GetTeamId() == TEAM_ALLIANCE)
SendWarningToAll(LANG_BG_SA_A_GY_WEST);
else
@@ -756,7 +784,7 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
case BG_SA_RIGHT_CAPTURABLE_GY:
flag = BG_SA_RIGHT_FLAG;
DelObject(flag);
AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0:1)),
AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)),
BG_SA_ObjSpawnlocs[flag][0], BG_SA_ObjSpawnlocs[flag][1],
BG_SA_ObjSpawnlocs[flag][2], BG_SA_ObjSpawnlocs[flag][3], 0, 0, 0, 0, RESPAWN_ONE_DAY);
@@ -765,8 +793,18 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1],
BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]);
UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0));
UpdateWorldState(BG_SA_RIGHT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1));
for (uint8 j = BG_SA_DEMOLISHER_5; j <= BG_SA_DEMOLISHER_6; j++)
{
AddCreature(BG_SA_NpcEntries[j], j, (Attackers == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE),
BG_SA_NpcSpawnlocs[j][0], BG_SA_NpcSpawnlocs[j][1],
BG_SA_NpcSpawnlocs[j][2], BG_SA_NpcSpawnlocs[j][3], 600);
if (Creature* dem = GetBGCreature(j))
dem->setFaction(BG_SA_Factions[Attackers]);
}
UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 1 : 0));
UpdateWorldState(BG_SA_RIGHT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 0 : 1));
if (Source->GetTeamId() == TEAM_ALLIANCE)
SendWarningToAll(LANG_BG_SA_A_GY_EAST);
else
@@ -775,12 +813,12 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
case BG_SA_CENTRAL_CAPTURABLE_GY:
flag = BG_SA_CENTRAL_FLAG;
DelObject(flag);
AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0:1)),
AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)),
BG_SA_ObjSpawnlocs[flag][0], BG_SA_ObjSpawnlocs[flag][1],
BG_SA_ObjSpawnlocs[flag][2], BG_SA_ObjSpawnlocs[flag][3], 0, 0, 0, 0, RESPAWN_ONE_DAY);
UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0));
UpdateWorldState(BG_SA_CENTER_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1));
UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 1 : 0));
UpdateWorldState(BG_SA_CENTER_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE ? 0 : 1));
if (Source->GetTeamId() == TEAM_ALLIANCE)
SendWarningToAll(LANG_BG_SA_A_GY_SOUTH);
else
@@ -794,7 +832,11 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
void BattlegroundSA::EventPlayerUsedGO(Player* Source, GameObject* object)
{
if (object->GetEntry() == BG_SA_ObjEntries[BG_SA_TITAN_RELIC] && GateStatus[BG_SA_ANCIENT_GATE] == BG_SA_GATE_DESTROYED && GateStatus[BG_SA_YELLOW_GATE] == BG_SA_GATE_DESTROYED && (GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED) && (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED))
if (object->GetEntry() == BG_SA_ObjEntries[BG_SA_TITAN_RELIC] &&
GateStatus[BG_SA_ANCIENT_GATE] == BG_SA_GATE_DESTROYED &&
GateStatus[BG_SA_YELLOW_GATE] == BG_SA_GATE_DESTROYED &&
(GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED) &&
(GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED))
{
if (Source->GetTeamId() == Attackers)
{
@@ -872,7 +914,7 @@ void BattlegroundSA::EndBattleground(uint32 winner)
void BattlegroundSA::UpdateDemolisherSpawns()
{
for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++)
for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_8; i++)
{
if (BgCreatures[i])
{
@@ -881,19 +923,14 @@ void BattlegroundSA::UpdateDemolisherSpawns()
if (Demolisher->isDead())
{
// Demolisher is not in list
if (DemoliserRespawnList.find(i)==DemoliserRespawnList.end())
if (DemoliserRespawnList.find(i) == DemoliserRespawnList.end())
{
DemoliserRespawnList[i]=getMSTime()+30000;
DemoliserRespawnList[i] = getMSTime()+30000;
}
else
{
if (DemoliserRespawnList[i] < getMSTime())
{
uint8 gy = (i >= BG_SA_DEMOLISHER_3 ? 3 : 2);
if (GraveyardStatus[gy] == Attackers)
Demolisher->Relocate(BG_SA_NpcSpawnlocs[i + 11][0], BG_SA_NpcSpawnlocs[i + 11][1],
BG_SA_NpcSpawnlocs[i + 11][2], BG_SA_NpcSpawnlocs[i + 11][3]);
else
Demolisher->Relocate(BG_SA_NpcSpawnlocs[i][0], BG_SA_NpcSpawnlocs[i][1],
BG_SA_NpcSpawnlocs[i][2], BG_SA_NpcSpawnlocs[i][3]);
@@ -126,15 +126,19 @@ enum BG_SA_NPCs
BG_SA_GUN_8,
BG_SA_GUN_9,
BG_SA_GUN_10,
BG_SA_DEMOLISHER_1,
BG_SA_DEMOLISHER_2,
BG_SA_DEMOLISHER_3,
BG_SA_DEMOLISHER_4,
BG_SA_NPC_TRIGGER_1,
BG_SA_NPC_TRIGGER_2,
BG_SA_NPC_TRIGGER_3,
BG_SA_NPC_TRIGGER_4,
BG_SA_NPC_TRIGGER_5,
BG_SA_DEMOLISHER_1,
BG_SA_DEMOLISHER_2,
BG_SA_DEMOLISHER_3,
BG_SA_DEMOLISHER_4,
BG_SA_DEMOLISHER_5,
BG_SA_DEMOLISHER_6,
BG_SA_DEMOLISHER_7,
BG_SA_DEMOLISHER_8,
BG_SA_NPC_SPARKLIGHT,
BG_SA_NPC_RIGSPARK,
BG_SA_MAXNPC
@@ -160,17 +164,22 @@ uint32 const BG_SA_NpcEntries[BG_SA_MAXNPC] =
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
NPC_ANTI_PERSONNAL_CANNON,
// 4 beach demolishers
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
// Triggers
23472,
23472,
23472,
23472,
23472,
// 4 beach demolishers
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
// 4 factory demolishers
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
NPC_DEMOLISHER_SA,
// Used Demolisher Salesman
NPC_RIGGER_SPARKLIGHT,
NPC_GORGRIL_RIGSPARK
@@ -189,25 +198,25 @@ float const BG_SA_NpcSpawnlocs[BG_SA_MAXNPC + BG_SA_DEMOLISHER_AMOUNT][4] =
{ 1249.634f, -224.189f, 66.72f, 0.635f },
{ 1236.213f, 92.287f, 64.965f, 5.751f },
{ 1215.11f, 57.772f, 64.739f, 5.78f },
// Demolishers
{ 1611.597656f, -117.270073f, 8.719355f, 2.513274f},
{ 1575.562500f, -158.421875f, 5.024450f, 2.129302f},
{ 1618.047729f, 61.424641f, 7.248210f, 3.979351f},
{ 1575.103149f, 98.873344f, 2.830360f, 3.752458f},
// Triggers
{ 1453.49f, -250.453f, 30.896f, 4.2883f},
{ 1377.05f, 97.036f, 30.8605f, 2.46539f},
{ 1186.05f, 58.8048f, 56.5491f, 2.75992f},
{ 1042.83f, -72.839f, 84.8145f, 3.58615f},
{ 1233.62f, -250.49f, 55.4036f, 3.7016f},
// Npcs
{ 1348.644165f, -298.786469f, 31.080130f, 1.710423f},
{ 1358.191040f, 195.527786f, 31.018187f, 4.171337f},
// Demolishers
{ 1611.597656f, -117.270073f, 8.719355f, 2.513274f},
{ 1575.562500f, -158.421875f, 5.024450f, 2.129302f},
{ 1618.047729f, 61.424641f, 7.248210f, 3.979351f},
{ 1575.103149f, 98.873344f, 2.830360f, 3.752458f},
// Demolishers 2
{ 1371.055786f, -317.071136f, 35.007359f, 1.947460f},
{ 1424.034912f, -260.195190f, 31.084425f, 2.820013f},
{ 1353.139893f, 223.745438f, 35.265411f, 4.343684f},
{ 1404.809570f, 197.027237f, 32.046032f, 3.605401f}
{ 1404.809570f, 197.027237f, 32.046032f, 3.605401f},
// Npcs
{ 1348.644165f, -298.786469f, 31.080130f, 1.710423f},
{ 1358.191040f, 195.527786f, 31.018187f, 4.171337f}
};
enum BG_SA_Objects
+2 -1
View File
@@ -222,6 +222,7 @@ struct AchievementCriteriaEntry
struct
{
uint32 mapID; // 3 Reference to Map.dbc
uint32 count; // 4 Number of times that the arena must be won.
} win_arena;
// ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33
@@ -1195,7 +1196,7 @@ struct ItemSetEntry
struct LFGDungeonEntry
{
uint32 ID; // 0
//char* name[16]; // 1-17 Name lang
char* name[16]; // 1-17 Name lang
uint32 minlevel; // 18
uint32 maxlevel; // 19
uint32 reclevel; // 20
+99 -99
View File
@@ -19,111 +19,111 @@
#ifndef TRINITY_DBCSFRM_H
#define TRINITY_DBCSFRM_H
const char Achievementfmt[]="niixssssssssssssssssxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxii";
char const Achievementfmt[]="niixssssssssssssssssxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxii";
const std::string CustomAchievementfmt="pppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaapapaaaaaaaaaaaaaaaaaapp";
const std::string CustomAchievementIndex = "ID";
const char AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiiiix";
const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxiiiiixxx";
const char AreaGroupEntryfmt[]="niiiiiii";
const char AreaPOIEntryfmt[]="niiiiiiiiiiifffixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
const char AreaTriggerEntryfmt[]="niffffffff";
const char AuctionHouseEntryfmt[]="niiixxxxxxxxxxxxxxxxx";
const char BankBagSlotPricesEntryfmt[]="ni";
const char BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
const char BattlemasterListEntryfmt[]="niiiiiiiiixssssssssssssssssxiixx";
const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char CharTitlesEntryfmt[]="nxssssssssssssssssxxxxxxxxxxxxxxxxxxi";
const char ChatChannelsEntryfmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
char const AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiiiix";
char const AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxiiiiixxx";
char const AreaGroupEntryfmt[]="niiiiiii";
char const AreaPOIEntryfmt[]="niiiiiiiiiiifffixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
char const AreaTriggerEntryfmt[]="niffffffff";
char const AuctionHouseEntryfmt[]="niiixxxxxxxxxxxxxxxxx";
char const BankBagSlotPricesEntryfmt[]="ni";
char const BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
char const BattlemasterListEntryfmt[]="niiiiiiiiixssssssssssssssssxiixx";
char const CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const CharTitlesEntryfmt[]="nxssssssssssssssssxxxxxxxxxxxxxxxxxxi";
char const ChatChannelsEntryfmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
// ChatChannelsEntryfmt, index not used (more compact store)
const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
const char ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
const char CinematicSequencesEntryfmt[]="nxxxxxxxxx";
const char CreatureDisplayInfofmt[]="nixxfxxxxxxxxxxx";
const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx";
const char CreatureModelDatafmt[]="nxxxfxxxxxxxxxxffxxxxxxxxxxx";
const char CreatureSpellDatafmt[]="niiiixxxx";
const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx";
const char CurrencyTypesfmt[]="xnxi";
const char DestructibleModelDatafmt[]="nxxixxxixxxixxxixxx";
const char DungeonEncounterfmt[]="niixissssssssssssssssxx";
const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
const char DurabilityQualityfmt[]="nf";
const char EmotesEntryfmt[]="nxxiiix";
const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx";
const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx";
const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
const char GameObjectDisplayInfofmt[]="nsxxxxxxxxxxffffffx";
const char GemPropertiesEntryfmt[]="nixxi";
const char GlyphPropertiesfmt[]="niii";
const char GlyphSlotfmt[]="nii";
const char GtBarberShopCostBasefmt[]="f";
const char GtCombatRatingsfmt[]="f";
const char GtChanceToMeleeCritBasefmt[]="f";
const char GtChanceToMeleeCritfmt[]="f";
const char GtChanceToSpellCritBasefmt[]="f";
const char GtChanceToSpellCritfmt[]="f";
const char GtOCTClassCombatRatingScalarfmt[]="df";
const char GtOCTRegenHPfmt[]="f";
//const char GtOCTRegenMPfmt[]="f";
const char GtRegenHPPerSptfmt[]="f";
const char GtRegenMPPerSptfmt[]="f";
const char Holidaysfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix";
const char Itemfmt[]="niiiiiii";
const char ItemBagFamilyfmt[]="nxxxxxxxxxxxxxxxxx";
//const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx";
//const char ItemCondExtCostsEntryfmt[]="xiii";
const char ItemExtendedCostEntryfmt[]="niiiiiiiiiiiiiix";
const char ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
const char ItemRandomPropertiesfmt[]="nxiiixxssssssssssssssssx";
const char ItemRandomSuffixfmt[]="nssssssssssssssssxxiiixxiiixx";
const char ItemSetEntryfmt[]="dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii";
const char LFGDungeonEntryfmt[]="nxxxxxxxxxxxxxxxxxiiiiiiiiixxixixxxxxxxxxxxxxxxxx";
const char LiquidTypefmt[]="nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxssssssssssssssssx";
const char MapEntryfmt[]="nxixxssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxiix";
const char MapDifficultyEntryfmt[]="diisxxxxxxxxxxxxxxxxiix";
const char MovieEntryfmt[]="nxx";
const char OverrideSpellDatafmt[]="niiiiiiiiiix";
const char QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx";
const char QuestXPfmt[]="niiiiiiiiii";
const char QuestFactionRewardfmt[]="niiiiiiiiii";
const char PvPDifficultyfmt[]="diiiii";
const char RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii";
const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii";
const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiiiiiiii";
const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi";
const char SkillLineAbilityfmt[]="niiiixxiiiiixx";
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char SpellCastTimefmt[]="nixx";
const char SpellDifficultyfmt[]="niiii";
char const ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
char const ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
char const CinematicSequencesEntryfmt[]="nxxxxxxxxx";
char const CreatureDisplayInfofmt[]="nixxfxxxxxxxxxxx";
char const CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx";
char const CreatureModelDatafmt[]="nxxxfxxxxxxxxxxffxxxxxxxxxxx";
char const CreatureSpellDatafmt[]="niiiixxxx";
char const CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx";
char const CurrencyTypesfmt[]="xnxi";
char const DestructibleModelDatafmt[]="nxxixxxixxxixxxixxx";
char const DungeonEncounterfmt[]="niixissssssssssssssssxx";
char const DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
char const DurabilityQualityfmt[]="nf";
char const EmotesEntryfmt[]="nxxiiix";
char const EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx";
char const FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx";
char const FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
char const GameObjectDisplayInfofmt[]="nsxxxxxxxxxxffffffx";
char const GemPropertiesEntryfmt[]="nixxi";
char const GlyphPropertiesfmt[]="niii";
char const GlyphSlotfmt[]="nii";
char const GtBarberShopCostBasefmt[]="f";
char const GtCombatRatingsfmt[]="f";
char const GtChanceToMeleeCritBasefmt[]="f";
char const GtChanceToMeleeCritfmt[]="f";
char const GtChanceToSpellCritBasefmt[]="f";
char const GtChanceToSpellCritfmt[]="f";
char const GtOCTClassCombatRatingScalarfmt[]="df";
char const GtOCTRegenHPfmt[]="f";
//char const GtOCTRegenMPfmt[]="f";
char const GtRegenHPPerSptfmt[]="f";
char const GtRegenMPPerSptfmt[]="f";
char const Holidaysfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix";
char const Itemfmt[]="niiiiiii";
char const ItemBagFamilyfmt[]="nxxxxxxxxxxxxxxxxx";
//char const ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx";
//char const ItemCondExtCostsEntryfmt[]="xiii";
char const ItemExtendedCostEntryfmt[]="niiiiiiiiiiiiiix";
char const ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
char const ItemRandomPropertiesfmt[]="nxiiixxssssssssssssssssx";
char const ItemRandomSuffixfmt[]="nssssssssssssssssxxiiixxiiixx";
char const ItemSetEntryfmt[]="dssssssssssssssssxiiiiiiiiiixxxxxxxiiiiiiiiiiiiiiiiii";
char const LFGDungeonEntryfmt[]="nssssssssssssssssxiiiiiiiiixxixixxxxxxxxxxxxxxxxx";
char const LiquidTypefmt[]="nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
char const MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxssssssssssssssssx";
char const MapEntryfmt[]="nxixxssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxiix";
char const MapDifficultyEntryfmt[]="diisxxxxxxxxxxxxxxxxiix";
char const MovieEntryfmt[]="nxx";
char const OverrideSpellDatafmt[]="niiiiiiiiiix";
char const QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx";
char const QuestXPfmt[]="niiiiiiiiii";
char const QuestFactionRewardfmt[]="niiiiiiiiii";
char const PvPDifficultyfmt[]="diiiii";
char const RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii";
char const ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii";
char const ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiiiiiiii";
char const SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi";
char const SkillLineAbilityfmt[]="niiiixxiiiiixx";
char const SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const SpellCastTimefmt[]="nixx";
char const SpellDifficultyfmt[]="niiii";
const std::string CustomSpellDifficultyfmt="ppppp";
const std::string CustomSpellDifficultyIndex="id";
const char SpellDurationfmt[]="niii";
const char SpellEntryfmt[]="niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx";
char const SpellDurationfmt[]="niii";
char const SpellEntryfmt[]="niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx";
const std::string CustomSpellEntryfmt="papppppppppppapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa";
const std::string CustomSpellEntryIndex = "Id";
const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiiiii";
const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";
const char SpellRadiusfmt[]="nfxf";
const char SpellRangefmt[]="nffffixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char SpellRuneCostfmt[]="niiii";
const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixiiixxiiiiiiii";
const char StableSlotPricesfmt[] = "ni";
const char SummonPropertiesfmt[] = "niiiii";
const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx";
const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix";
const char TaxiNodesEntryfmt[]="nifffssssssssssssssssxii";
const char TaxiPathEntryfmt[]="niii";
const char TaxiPathNodeEntryfmt[]="diiifffiiii";
const char TeamContributionPointsfmt[]="df";
const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx";
const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx";
const char WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx";
const char WorldMapAreaEntryfmt[]="xinxffffixx";
const char WorldMapOverlayEntryfmt[]="nxiiiixxxxxxxxxxx";
const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx";
char const SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
char const SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiiiii";
char const SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";
char const SpellRadiusfmt[]="nfxf";
char const SpellRangefmt[]="nffffixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const SpellRuneCostfmt[]="niiii";
char const SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixiiixxiiiiiiii";
char const StableSlotPricesfmt[] = "ni";
char const SummonPropertiesfmt[] = "niiiii";
char const TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx";
char const TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix";
char const TaxiNodesEntryfmt[]="nifffssssssssssssssssxii";
char const TaxiPathEntryfmt[]="niii";
char const TaxiPathNodeEntryfmt[]="diiifffiiii";
char const TeamContributionPointsfmt[]="df";
char const TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
char const VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx";
char const VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx";
char const WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx";
char const WorldMapAreaEntryfmt[]="xinxffffixx";
char const WorldMapOverlayEntryfmt[]="nxiiiixxxxxxxxxxx";
char const WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx";
#endif
+26 -14
View File
@@ -20,19 +20,26 @@
#include "Common.h"
enum LFGEnum
{
LFG_TANKS_NEEDED = 1,
LFG_HEALERS_NEEDED = 1,
LFG_DPS_NEEDED = 3
};
enum LfgRoles
{
ROLE_NONE = 0x00,
ROLE_LEADER = 0x01,
ROLE_TANK = 0x02,
ROLE_HEALER = 0x04,
ROLE_DAMAGE = 0x08
PLAYER_ROLE_NONE = 0x00,
PLAYER_ROLE_LEADER = 0x01,
PLAYER_ROLE_TANK = 0x02,
PLAYER_ROLE_HEALER = 0x04,
PLAYER_ROLE_DAMAGE = 0x08
};
enum LfgUpdateType
{
LFG_UPDATETYPE_DEFAULT = 0, // Internal Use
LFG_UPDATETYPE_LEADER = 1,
LFG_UPDATETYPE_LEADER_UNK1 = 1, // FIXME: At group leave
LFG_UPDATETYPE_ROLECHECK_ABORTED = 4,
LFG_UPDATETYPE_JOIN_PROPOSAL = 5,
LFG_UPDATETYPE_ROLECHECK_FAILED = 6,
@@ -44,7 +51,7 @@ enum LfgUpdateType
LFG_UPDATETYPE_PROPOSAL_BEGIN = 13,
LFG_UPDATETYPE_CLEAR_LOCK_LIST = 14,
LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 15,
LFG_UPDATETYPE_GROUP_DISBAND = 16
LFG_UPDATETYPE_GROUP_DISBAND_UNK16 = 16, // FIXME: Sometimes at group disband
};
enum LfgState
@@ -62,7 +69,6 @@ enum LfgState
/// Instance lock types
enum LfgLockStatusType
{
LFG_LOCKSTATUS_OK = 0, // Internal use only
LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION = 1,
LFG_LOCKSTATUS_TOO_LOW_LEVEL = 2,
LFG_LOCKSTATUS_TOO_HIGH_LEVEL = 3,
@@ -73,18 +79,24 @@ enum LfgLockStatusType
LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL = 1002,
LFG_LOCKSTATUS_QUEST_NOT_COMPLETED = 1022,
LFG_LOCKSTATUS_MISSING_ITEM = 1025,
LFG_LOCKSTATUS_NOT_IN_SEASON = 1031
LFG_LOCKSTATUS_NOT_IN_SEASON = 1031,
LFG_LOCKSTATUS_MISSING_ACHIEVEMENT = 1034
};
/// Dungeon and reason why player can't join
struct LfgLockStatus
/// Answer state (Also used to check compatibilites)
enum LfgAnswer
{
uint32 dungeon; ///< Dungeon Id
LfgLockStatusType lockstatus; ///< Lock type
LFG_ANSWER_PENDING = -1,
LFG_ANSWER_DENY = 0,
LFG_ANSWER_AGREE = 1
};
typedef std::set<uint32> LfgDungeonSet;
typedef std::map<uint32, LfgLockStatusType> LfgLockMap;
typedef std::map<uint32, uint32> LfgLockMap;
typedef std::map<uint64, LfgLockMap> LfgLockPartyMap;
typedef std::set<uint64> LfgGuidSet;
typedef std::list<uint64> LfgGuidList;
typedef std::map<uint64, uint8> LfgRolesMap;
typedef std::map<uint64, uint64> LfgGroupsMap;
#endif
+46 -11
View File
@@ -18,23 +18,25 @@
#include "LFG.h"
#include "LFGGroupData.h"
LfgGroupData::LfgGroupData():
m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), m_Dungeon(0),
m_VotesNeeded(LFG_GROUP_KICK_VOTES_NEEDED), m_KicksLeft(LFG_GROUP_MAX_KICKS)
{
}
LfgGroupData::LfgGroupData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE),
m_Leader(0), m_Dungeon(0), m_KicksLeft(LFG_GROUP_MAX_KICKS)
{ }
LfgGroupData::~LfgGroupData()
{ }
bool LfgGroupData::IsLfgGroup()
{
return m_OldState != LFG_STATE_NONE;
}
void LfgGroupData::SetState(LfgState state)
{
switch (state)
{
case LFG_STATE_FINISHED_DUNGEON:
case LFG_STATE_NONE:
case LFG_STATE_DUNGEON:
case LFG_STATE_FINISHED_DUNGEON:
m_OldState = state;
// No break on purpose
default:
@@ -47,6 +49,29 @@ void LfgGroupData::RestoreState()
m_State = m_OldState;
}
void LfgGroupData::AddPlayer(uint64 guid)
{
m_Players.insert(guid);
}
uint8 LfgGroupData::RemovePlayer(uint64 guid)
{
LfgGuidSet::iterator it = m_Players.find(guid);
if (it != m_Players.end())
m_Players.erase(it);
return uint8(m_Players.size());
}
void LfgGroupData::RemoveAllPlayers()
{
m_Players.clear();
}
void LfgGroupData::SetLeader(uint64 guid)
{
m_Leader = guid;
}
void LfgGroupData::SetDungeon(uint32 dungeon)
{
m_Dungeon = dungeon;
@@ -63,6 +88,21 @@ LfgState LfgGroupData::GetState() const
return m_State;
}
LfgState LfgGroupData::GetOldState() const
{
return m_OldState;
}
const LfgGuidSet &LfgGroupData::GetPlayers() const
{
return m_Players;
}
uint64 LfgGroupData::GetLeader() const
{
return m_Leader;
}
uint32 LfgGroupData::GetDungeon(bool asId /* = true */) const
{
if (asId)
@@ -71,11 +111,6 @@ uint32 LfgGroupData::GetDungeon(bool asId /* = true */) const
return m_Dungeon;
}
uint8 LfgGroupData::GetVotesNeeded() const
{
return m_VotesNeeded;
}
uint8 LfgGroupData::GetKicksLeft() const
{
return m_KicksLeft;
+15 -4
View File
@@ -23,7 +23,6 @@
enum LfgGroupEnum
{
LFG_GROUP_MAX_KICKS = 3,
LFG_GROUP_KICK_VOTES_NEEDED = 3
};
/**
@@ -35,31 +34,43 @@ class LfgGroupData
LfgGroupData();
~LfgGroupData();
bool IsLfgGroup();
// General
void SetState(LfgState state);
void RestoreState();
void AddPlayer(uint64 guid);
uint8 RemovePlayer(uint64 guid);
void RemoveAllPlayers();
void SetLeader(uint64 guid);
// Dungeon
void SetDungeon(uint32 dungeon);
// VoteKick
void SetVotesNeeded(uint8 votes);
void DecreaseKicksLeft();
// General
LfgState GetState() const;
LfgState GetOldState() const;
LfgGuidSet const& GetPlayers() const;
uint64 GetLeader() const;
// Dungeon
uint32 GetDungeon(bool asId = true) const;
// VoteKick
uint8 GetVotesNeeded() const;
uint8 GetKicksLeft() const;
private:
// General
LfgState m_State; ///< State if group in LFG
LfgState m_OldState; ///< Old State
uint64 m_Leader; ///< Leader GUID
LfgGuidSet m_Players; ///< Players in group
// Dungeon
uint32 m_Dungeon; ///< Dungeon entry
// Vote Kick
uint8 m_VotesNeeded; ///< Votes need to kick success
uint8 m_KicksLeft; ///< Number of kicks left
};
File diff suppressed because it is too large Load Diff
+151 -123
View File
@@ -21,24 +21,23 @@
#include "Common.h"
#include <ace/Singleton.h>
#include "LFG.h"
#include "LFGQueue.h"
#include "LFGGroupData.h"
#include "LFGPlayerData.h"
class LfgGroupData;
class LfgPlayerData;
class Group;
class Player;
enum LFGenum
enum LFGMgrEnum
{
LFG_TIME_ROLECHECK = 40*IN_MILLISECONDS,
LFG_TIME_BOOT = 2*MINUTE,
LFG_TIME_PROPOSAL = 2*MINUTE,
LFG_TANKS_NEEDED = 1,
LFG_HEALERS_NEEDED = 1,
LFG_DPS_NEEDED = 3,
LFG_QUEUEUPDATE_INTERVAL = 15*IN_MILLISECONDS,
LFG_TIME_ROLECHECK = 40 * IN_MILLISECONDS,
LFG_TIME_BOOT = 120,
LFG_TIME_PROPOSAL = 120,
LFG_QUEUEUPDATE_INTERVAL = 15 * IN_MILLISECONDS,
LFG_SPELL_DUNGEON_COOLDOWN = 71328,
LFG_SPELL_DUNGEON_DESERTER = 71041,
LFG_SPELL_LUCK_OF_THE_DRAW = 72221
LFG_SPELL_LUCK_OF_THE_DRAW = 72221,
LFG_GROUP_KICK_VOTES_NEEDED = 3
};
enum LfgFlags
@@ -52,11 +51,9 @@ enum LfgFlags
/// Determines the type of instance
enum LfgType
{
LFG_TYPE_NONE = 0, // Internal use only
LFG_TYPE_NONE = 0,
LFG_TYPE_DUNGEON = 1,
LFG_TYPE_RAID = 2,
LFG_TYPE_QUEST = 3,
LFG_TYPE_ZONE = 4,
LFG_TYPE_HEROIC = 5,
LFG_TYPE_RANDOM = 6
};
@@ -72,13 +69,14 @@ enum LfgProposalState
/// Teleport errors
enum LfgTeleportError
{
// 3, 7, 8 = "You can't do that right now" | 5 = No client reaction
// 7 = "You can't do that right now" | 5 = No client reaction
LFG_TELEPORTERROR_OK = 0, // Internal use
LFG_TELEPORTERROR_PLAYER_DEAD = 1,
LFG_TELEPORTERROR_FALLING = 2,
LFG_TELEPORTERROR_DONT_REPORT = 3,
LFG_TELEPORTERROR_IN_VEHICLE = 3,
LFG_TELEPORTERROR_FATIGUE = 4,
LFG_TELEPORTERROR_INVALID_LOCATION = 6
LFG_TELEPORTERROR_INVALID_LOCATION = 6,
LFG_TELEPORTERROR_CHARMING = 8 // FIXME - It can be 7 or 8 (Need proper data)
};
/// Queue join results
@@ -116,42 +114,27 @@ enum LfgRoleCheckState
LFG_ROLECHECK_NO_ROLE = 6 // Someone selected no role
};
/// Answer state (Also used to check compatibilites)
enum LfgAnswer
{
LFG_ANSWER_PENDING = -1,
LFG_ANSWER_DENY = 0,
LFG_ANSWER_AGREE = 1
};
// Forward declaration (just to have all typedef together)
struct LFGDungeonData;
struct LfgReward;
struct LfgLockStatus;
struct LfgQueueInfo;
struct LfgRoleCheck;
struct LfgProposal;
struct LfgProposalPlayer;
struct LfgPlayerBoot;
typedef std::set<uint64> LfgGuidSet;
typedef std::list<uint64> LfgGuidList;
typedef std::map<uint8, LfgGuidList> LfgGuidListMap;
typedef std::set<Player*> PlayerSet;
typedef std::list<Player*> LfgPlayerList;
typedef std::map<uint8, LfgQueue> LfgQueueMap;
typedef std::multimap<uint32, LfgReward const*> LfgRewardMap;
typedef std::pair<LfgRewardMap::const_iterator, LfgRewardMap::const_iterator> LfgRewardMapBounds;
typedef std::map<std::string, LfgAnswer> LfgCompatibleMap;
typedef std::map<uint64, LfgDungeonSet> LfgDungeonMap;
typedef std::map<uint64, uint8> LfgRolesMap;
typedef std::map<uint8, LfgDungeonSet> LfgCachedDungeonMap;
typedef std::map<uint64, LfgAnswer> LfgAnswerMap;
typedef std::map<uint64, LfgRoleCheck*> LfgRoleCheckMap;
typedef std::map<uint64, LfgQueueInfo*> LfgQueueInfoMap;
typedef std::map<uint32, LfgProposal*> LfgProposalMap;
typedef std::map<uint64, LfgProposalPlayer*> LfgProposalPlayerMap;
typedef std::map<uint32, LfgPlayerBoot*> LfgPlayerBootMap;
typedef std::map<uint64, LfgRoleCheck> LfgRoleCheckMap;
typedef std::map<uint32, LfgProposal> LfgProposalMap;
typedef std::map<uint64, LfgProposalPlayer> LfgProposalPlayerMap;
typedef std::map<uint64, LfgPlayerBoot> LfgPlayerBootMap;
typedef std::map<uint64, LfgGroupData> LfgGroupDataMap;
typedef std::map<uint64, LfgPlayerData> LfgPlayerDataMap;
typedef std::map<uint32, Position> LfgEntrancePositionMap;
typedef UNORDERED_MAP<uint32, LFGDungeonData> LFGDungeonMap;
// Data needed by SMSG_LFG_JOIN_RESULT
struct LfgJoinResultData
@@ -167,7 +150,7 @@ struct LfgJoinResultData
struct LfgUpdateData
{
LfgUpdateData(LfgUpdateType _type = LFG_UPDATETYPE_DEFAULT): updateType(_type), comment("") {}
LfgUpdateData(LfgUpdateType _type, const LfgDungeonSet& _dungeons, std::string _comment):
LfgUpdateData(LfgUpdateType _type, LfgDungeonSet const& _dungeons, std::string _comment):
updateType(_type), dungeons(_dungeons), comment(_comment) {}
LfgUpdateType updateType;
@@ -175,6 +158,26 @@ struct LfgUpdateData
std::string comment;
};
// Data needed by SMSG_LFG_QUEUE_STATUS
struct LfgQueueStatusData
{
LfgQueueStatusData(uint32 _dungeonId = 0, int32 _waitTime = -1, int32 _waitTimeAvg = -1, int32 _waitTimeTank = -1, int32 _waitTimeHealer = -1,
int32 _waitTimeDps = -1, uint32 _queuedTime = 0, uint8 _tanks = 0, uint8 _healers = 0, uint8 _dps = 0) :
dungeonId(_dungeonId), waitTime(_waitTime), waitTimeAvg(_waitTimeAvg), waitTimeTank(_waitTimeTank), waitTimeHealer(_waitTimeHealer),
waitTimeDps(_waitTimeDps), queuedTime(_queuedTime), tanks(_tanks), healers(_healers), dps(_dps) {}
uint32 dungeonId;
int32 waitTime;
int32 waitTimeAvg;
int32 waitTimeTank;
int32 waitTimeHealer;
int32 waitTimeDps;
uint32 queuedTime;
uint8 tanks;
uint8 healers;
uint8 dps;
};
/// Reward info
struct LfgReward
{
@@ -198,45 +201,31 @@ struct LfgReward
}
};
/// Stores player or group queue info
struct LfgQueueInfo
{
LfgQueueInfo(): joinTime(0), tanks(LFG_TANKS_NEEDED), healers(LFG_HEALERS_NEEDED), dps(LFG_DPS_NEEDED) {};
time_t joinTime; ///< Player queue join time (to calculate wait times)
uint8 tanks; ///< Tanks needed
uint8 healers; ///< Healers needed
uint8 dps; ///< Dps needed
LfgDungeonSet dungeons; ///< Selected Player/Group Dungeon/s
LfgRolesMap roles; ///< Selected Player Role/s
};
/// Stores player data related to proposal to join
struct LfgProposalPlayer
{
LfgProposalPlayer(): role(0), accept(LFG_ANSWER_PENDING), groupLowGuid(0) {};
LfgProposalPlayer(): role(0), accept(LFG_ANSWER_PENDING), group(0) { }
uint8 role; ///< Proposed role
LfgAnswer accept; ///< Accept status (-1 not answer | 0 Not agree | 1 agree)
uint32 groupLowGuid; ///< Original group guid (Low guid) 0 if no original group
uint64 group; ///< Original group guid. 0 if no original group
};
/// Stores group data related to proposal to join
struct LfgProposal
{
LfgProposal(uint32 dungeon = 0): dungeonId(dungeon), state(LFG_PROPOSAL_INITIATING), groupLowGuid(0), leader(0), cancelTime(0) {}
LfgProposal(uint32 dungeon = 0): dungeonId(dungeon), state(LFG_PROPOSAL_INITIATING),
group(0), leader(0), cancelTime(0), encounters(0), isNew(true)
{ }
~LfgProposal()
{
for (LfgProposalPlayerMap::iterator it = players.begin(); it != players.end(); ++it)
delete it->second;
};
uint32 dungeonId; ///< Dungeon to join
LfgProposalState state; ///< State of the proposal
uint32 groupLowGuid; ///< Proposal group (0 if new)
uint64 group; ///< Proposal group (0 if new)
uint64 leader; ///< Leader guid.
time_t cancelTime; ///< Time when we will cancel this proposal
uint32 encounters; ///< Dungeon Encounters
bool isNew; ///< Determines if it's new group or not
LfgGuidList queues; ///< Queue Ids to remove/readd
LfgProposalPlayerMap players; ///< Players data
};
/// Stores all rolecheck info of a group that wants to join
@@ -257,10 +246,36 @@ struct LfgPlayerBoot
bool inProgress; ///< Vote in progress
LfgAnswerMap votes; ///< Player votes (-1 not answer | 0 Not agree | 1 agree)
uint64 victim; ///< Player guid to be kicked (can't vote)
uint8 votedNeeded; ///< Votes needed to kick the player
std::string reason; ///< kick reason
};
struct LFGDungeonData
{
LFGDungeonData(): id(0), name(""), map(0), type(0), expansion(0), group(0), minlevel(0),
maxlevel(0), difficulty(REGULAR_DIFFICULTY), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f)
{ }
LFGDungeonData(LFGDungeonEntry const* dbc): id(dbc->ID), name(dbc->name[0]), map(dbc->map),
type(dbc->type), expansion(dbc->expansion), group(dbc->grouptype),
minlevel(dbc->minlevel), maxlevel(dbc->maxlevel), difficulty(Difficulty(dbc->difficulty)),
seasonal(dbc->flags & LFG_FLAG_SEASONAL), x(0.0f), y(0.0f), z(0.0f), o(0.0f)
{ }
uint32 id;
std::string name;
uint16 map;
uint8 type;
uint8 expansion;
uint8 group;
uint8 minlevel;
uint8 maxlevel;
Difficulty difficulty;
bool seasonal;
float x, y, z, o;
// Helpers
uint32 Entry() const { return id + (type << 24); }
};
class LFGMgr
{
friend class ACE_Singleton<LFGMgr, ACE_Null_Mutex>;
@@ -274,108 +289,121 @@ class LFGMgr
// Reward
void LoadRewards();
void RewardDungeonDoneFor(const uint32 dungeonId, Player* player);
void RewardDungeonDoneFor(uint32 const dungeonId, Player* player);
LfgReward const* GetRandomDungeonReward(uint32 dungeon, uint8 level);
// Queue
void Join(Player* player, uint8 roles, const LfgDungeonSet& dungeons, const std::string& comment);
void Leave(Player* player, Group* grp = NULL);
void JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, std::string const& comment);
void LeaveLfg(uint64 guid);
// Role Check
void UpdateRoleCheck(uint64 gguid, uint64 guid = 0, uint8 roles = ROLE_NONE);
void UpdateRoleCheck(uint64 gguid, uint64 guid = 0, uint8 roles = PLAYER_ROLE_NONE);
// Group Matching
static bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true);
void GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap);
// Proposals
uint32 AddProposal(LfgProposal const& proposal);
void UpdateProposal(uint32 proposalId, uint64 guid, bool accept);
// Teleportation
void LoadEntrancePositions();
void TeleportPlayer(Player* player, bool out, bool fromOpcode = false);
// Vote kick
void InitBoot(Group* grp, uint64 kguid, uint64 vguid, std::string reason);
void UpdateBoot(Player* player, bool accept);
void OfferContinue(Group* grp);
void InitBoot(uint64 gguid, uint64 kguid, uint64 vguid, std::string const& reason);
void UpdateBoot(uint64 guid, bool accept);
HolidayIds GetDungeonSeason(uint32 dungeonId);
void InitializeLockedDungeons(Player* player, uint8 level = 0);
void InitializeLockedDungeons(Player* player);
void SetRoles(uint64 guid, uint8 roles);
void SetComment(uint64 guid, std::string const& comment);
void SetTeam(uint64 guid, uint8 team);
void SetGroup(uint64 guid, uint64 group);
void SetLeader(uint64 gguid, uint64 leader);
void SetState(uint64 guid, LfgState state);
void SetSelectedDungeons(uint64 guid, LfgDungeonSet const& dungeons);
void _LoadFromDB(Field* fields, uint64 guid);
void _SaveToDB(uint64 guid, uint32 db_guid);
void SetComment(uint64 guid, const std::string& comment);
const LfgLockMap& GetLockedDungeons(uint64 guid);
LfgState GetState(uint64 guid);
const LfgDungeonSet& GetSelectedDungeons(uint64 guid);
uint32 GetDungeon(uint64 guid, bool asId = true);
void SetState(uint64 guid, LfgState state);
void ClearState(uint64 guid);
void RemovePlayerData(uint64 guid);
void RemoveGroupData(uint64 guid);
uint8 GetKicksLeft(uint64 gguid);
uint8 GetVotesNeeded(uint64 gguid);
bool IsTeleported(uint64 pguid);
void SetRoles(uint64 guid, uint8 roles);
void SetSelectedDungeons(uint64 guid, const LfgDungeonSet& dungeons);
uint8 RemovePlayerFromGroup(uint64 gguid, uint64 guid);
void AddPlayerToGroup(uint64 gguid, uint64 guid);
LfgLockMap const& GetLockedDungeons(uint64 guid);
LfgDungeonSet const& GetSelectedDungeons(uint64 guid);
uint32 GetDungeon(uint64 guid, bool asId = true);
LfgState GetState(uint64 guid);
uint8 GetKicksLeft(uint64 gguid);
uint64 GetLeader(uint64 guid);
bool IsLfgGroup(uint64 guid);
uint8 GetRoles(uint64 guid);
std::string const& GetComment(uint64 gguid);
LfgGuidSet const& GetPlayers(uint64 guid);
bool IsTeleported(uint64 guid);
bool AllQueued(LfgGuidList const& check);
static bool HasIgnore(uint64 guid1, uint64 guid2);
static void SendLfgQueueStatus(uint64 guid, LfgQueueStatusData const& data);
bool IsSeasonActive(uint32 dungeonId);
static std::string ConcatenateDungeons(LfgDungeonSet const& dungeons);
static std::string GetRolesString(uint8 roles);
static char const * GetStateString(LfgState state);
void LoadLFGDungeons(bool reload = false);
LFGDungeonData const* GetLFGDungeon(uint32 id);
LFGDungeonMap& GetLFGDungeonMap();
void ClearState(uint64 guid, char const *debugMsg);
private:
uint8 GetRoles(uint64 guid);
const std::string& GetComment(uint64 gguid);
void RestoreState(uint64 guid);
void SetDungeon(uint64 guid, uint32 dungeon);
void SetLockedDungeons(uint64 guid, const LfgLockMap& lock);
void DecreaseKicksLeft(uint64 guid);
uint8 GetTeam(uint64 guid);
uint64 GetGroup(uint64 guid);
void RestoreState(uint64 guid, char const *debugMsg);
// Queue
void AddToQueue(uint64 guid, uint8 queueId);
bool RemoveFromQueue(uint64 guid);
void SetDungeon(uint64 guid, uint32 dungeon);
void SetLockedDungeons(uint64 guid, LfgLockMap const& lock);
void DecreaseKicksLeft(uint64 guid);
// Proposals
void RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType type);
// Group Matching
LfgProposal* FindNewGroups(LfgGuidList& check, LfgGuidList& all);
bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true);
bool CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal);
void GetCompatibleDungeons(LfgDungeonSet& dungeons, const PlayerSet& players, LfgLockPartyMap& lockMap);
void SetCompatibles(std::string concatenatedGuids, bool compatibles);
LfgAnswer GetCompatibles(std::string concatenatedGuids);
void RemoveFromCompatibles(uint64 guid);
void MakeNewGroup(LfgProposal const& proposal);
// Generic
const LfgDungeonSet& GetDungeonsByRandom(uint32 randomdungeon);
LfgQueue &GetQueue(uint64 guid);
LfgDungeonSet const& GetDungeonsByRandom(uint32 randomdungeon);
LfgType GetDungeonType(uint32 dungeon);
std::string ConcatenateGuids(LfgGuidList check);
void SendLfgBootProposalUpdate(uint64 guid, LfgPlayerBoot const& boot);
void SendLfgJoinResult(uint64 guid, LfgJoinResultData const& data);
void SendLfgRoleChosen(uint64 guid, uint64 pguid, uint8 roles);
void SendLfgRoleCheckUpdate(uint64 guid, LfgRoleCheck const& roleCheck);
void SendLfgUpdateParty(uint64 guid, LfgUpdateData const& data);
void SendLfgUpdatePlayer(uint64 guid, LfgUpdateData const& data);
void SendLfgUpdateProposal(uint64 guid, uint32 proposalId, LfgProposal const& proposal);
// General variables
bool m_update; ///< Doing an update?
uint32 m_QueueTimer; ///< used to check interval of update
uint32 m_lfgProposalId; ///< used as internal counter for proposals
int32 m_WaitTimeAvg; ///< Average wait time to find a group queuing as multiple roles
int32 m_WaitTimeTank; ///< Average wait time to find a group queuing as tank
int32 m_WaitTimeHealer; ///< Average wait time to find a group queuing as healer
int32 m_WaitTimeDps; ///< Average wait time to find a group queuing as dps
uint32 m_NumWaitTimeAvg; ///< Num of players used to calc avs wait time
uint32 m_NumWaitTimeTank; ///< Num of players used to calc tank wait time
uint32 m_NumWaitTimeHealer; ///< Num of players used to calc healers wait time
uint32 m_NumWaitTimeDps; ///< Num of players used to calc dps wait time
LfgDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType
LfgEntrancePositionMap m_entrancePositions; ///< Stores special entrance positions
uint32 m_options; ///< Stores config options
LfgQueueMap m_Queues; ///< Queues
LfgCachedDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType
// Reward System
LfgRewardMap m_RewardMap; ///< Stores rewards for random dungeons
// Queue
LfgQueueInfoMap m_QueueInfoMap; ///< Queued groups
LfgGuidListMap m_currentQueue; ///< Ordered list. Used to find groups
LfgGuidListMap m_newToQueue; ///< New groups to add to queue
LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons
LfgGuidList m_teleport; ///< Players being teleported
LFGDungeonMap m_LfgDungeonMap;
// Rolecheck - Proposal - Vote Kicks
LfgRoleCheckMap m_RoleChecks; ///< Current Role checks
LfgProposalMap m_Proposals; ///< Current Proposals
LfgPlayerBootMap m_Boots; ///< Current player kicks
LfgPlayerDataMap m_Players; ///< Player data
LfgGroupDataMap m_Groups; ///< Group data
LfgGuidList m_teleport; ///< Players being teleported
};
#define sLFGMgr ACE_Singleton<LFGMgr, ACE_Null_Mutex>::instance()
@@ -17,8 +17,8 @@
#include "LFGPlayerData.h"
LfgPlayerData::LfgPlayerData():
m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), m_Roles(0), m_Comment("")
LfgPlayerData::LfgPlayerData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE),
m_Team(0), m_Group(0), m_Roles(0), m_Comment("")
{}
LfgPlayerData::~LfgPlayerData()
@@ -30,8 +30,11 @@ void LfgPlayerData::SetState(LfgState state)
switch (state)
{
case LFG_STATE_NONE:
case LFG_STATE_DUNGEON:
case LFG_STATE_FINISHED_DUNGEON:
m_Roles = 0;
m_SelectedDungeons.clear();
// No break on purpose
case LFG_STATE_DUNGEON:
m_OldState = state;
// No break on purpose
default:
@@ -51,6 +54,16 @@ void LfgPlayerData::SetLockedDungeons(const LfgLockMap& lockStatus)
m_LockedDungeons = lockStatus;
}
void LfgPlayerData::SetTeam(uint8 team)
{
m_Team = team;
}
void LfgPlayerData::SetGroup(uint64 group)
{
m_Group = group;
}
void LfgPlayerData::SetRoles(uint8 roles)
{
m_Roles = roles;
@@ -66,21 +79,31 @@ void LfgPlayerData::SetSelectedDungeons(const LfgDungeonSet& dungeons)
m_SelectedDungeons = dungeons;
}
void LfgPlayerData::ClearSelectedDungeons()
{
m_SelectedDungeons.clear();
}
LfgState LfgPlayerData::GetState() const
{
return m_State;
}
const LfgLockMap & LfgPlayerData::GetLockedDungeons() const
LfgState LfgPlayerData::GetOldState() const
{
return m_OldState;
}
const LfgLockMap& LfgPlayerData::GetLockedDungeons() const
{
return m_LockedDungeons;
}
uint8 LfgPlayerData::GetTeam() const
{
return m_Team;
}
uint64 LfgPlayerData::GetGroup() const
{
return m_Group;
}
uint8 LfgPlayerData::GetRoles() const
{
return m_Roles;
+15 -7
View File
@@ -18,7 +18,6 @@
#ifndef _LFGPLAYERDATA_H
#define _LFGPLAYERDATA_H
#include "Common.h"
#include "LFG.h"
/**
@@ -33,20 +32,26 @@ class LfgPlayerData
// General
void SetState(LfgState state);
void ClearState();
void SetLockedDungeons(const LfgLockMap& lock);
void SetLockedDungeons(LfgLockMap const& lock);
void SetTeam(uint8 team);
void SetGroup(uint64 group);
// Queue
void SetRoles(uint8 roles);
void SetComment(const std::string& comment);
void SetComment(std::string const& comment);
void SetSelectedDungeons(const LfgDungeonSet& dungeons);
void ClearSelectedDungeons();
// General
LfgState GetState() const;
const LfgLockMap& GetLockedDungeons() const;
LfgState GetOldState() const;
LfgLockMap const& GetLockedDungeons() const;
uint8 GetTeam() const;
uint64 GetGroup() const;
// Queue
uint8 GetRoles() const;
const std::string& GetComment() const;
const LfgDungeonSet& GetSelectedDungeons() const;
std::string const& GetComment() const;
LfgDungeonSet const& GetSelectedDungeons() const;
private:
// General
@@ -54,6 +59,9 @@ class LfgPlayerData
LfgState m_OldState; ///< Old State
// Player
LfgLockMap m_LockedDungeons; ///< Dungeons player can't do and reason
uint8 m_Team; ///< Player team - determines the queue to join
uint64 m_Group; ///< Original group of player when joined LFG
// Queue
uint8 m_Roles; ///< Roles the player selected when joined LFG
std::string m_Comment; ///< Player comment used when joined LFG
+539
View File
@@ -0,0 +1,539 @@
/*
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "ObjectDefines.h"
#include "Containers.h"
#include "DBCStructure.h"
#include "DBCStores.h"
#include "Group.h"
#include "LFGQueue.h"
#include "LFGMgr.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "World.h"
/**
Given a list of guids returns the concatenation using | as delimiter
@param[in] check list of guids
@returns Concatenated string
*/
std::string ConcatenateGuids(LfgGuidList const& check)
{
if (check.empty())
return "";
// need the guids in order to avoid duplicates
LfgGuidSet guids(check.begin(), check.end());
std::ostringstream o;
LfgGuidSet::const_iterator it = guids.begin();
o << (*it);
for (++it; it != guids.end(); ++it)
o << '|' << (*it);
return o.str();
}
char const * GetCompatibleString(LfgCompatibility compatibles)
{
switch (compatibles)
{
case LFG_COMPATIBILITY_PENDING:
return "Pending";
case LFG_COMPATIBLES_BAD_STATES:
return "Compatibles (Bad States)";
case LFG_COMPATIBLES_MATCH:
return "Match";
case LFG_COMPATIBLES_WITH_LESS_PLAYERS:
return "Compatibles (Not enough players)";
case LFG_INCOMPATIBLES_HAS_IGNORES:
return "Has ignores";
case LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS:
return "Multiple Lfg Groups";
case LFG_INCOMPATIBLES_NO_DUNGEONS:
return "Incompatible dungeons";
case LFG_INCOMPATIBLES_NO_ROLES:
return "Incompatible roles";
case LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS:
return "Too much players";
case LFG_INCOMPATIBLES_WRONG_GROUP_SIZE:
return "Wrong group size";
default:
return "Unknown";
}
}
void LfgQueue::AddToQueue(uint64 guid)
{
LfgQueueDataMap::iterator itQueue = m_QueueDataMap.find(guid);
if (itQueue == m_QueueDataMap.end())
{
sLog->outError(LOG_FILTER_LFG, "LfgQueue::AddToQueue: Queue data not found for [" UI64FMTD "]", guid);
return;
}
AddToNewQueue(guid);
}
void LfgQueue::RemoveFromQueue(uint64 guid)
{
RemoveFromNewQueue(guid);
RemoveFromCurrentQueue(guid);
RemoveFromCompatibles(guid);
RemoveQueueData(guid);
}
void LfgQueue::AddToNewQueue(uint64 guid)
{
m_newToQueue.push_back(guid);
}
void LfgQueue::RemoveFromNewQueue(uint64 guid)
{
m_newToQueue.remove(guid);
}
void LfgQueue::AddToCurrentQueue(uint64 guid)
{
m_currentQueue.push_back(guid);
}
void LfgQueue::RemoveFromCurrentQueue(uint64 guid)
{
m_currentQueue.remove(guid);
}
void LfgQueue::AddQueueData(uint64 guid, time_t joinTime, const LfgDungeonSet &dungeons, const LfgRolesMap &rolesMap)
{
m_QueueDataMap[guid] = LfgQueueData(joinTime, dungeons, rolesMap);
AddToQueue(guid);
}
void LfgQueue::RemoveQueueData(uint64 guid)
{
LfgQueueDataMap::iterator it = m_QueueDataMap.find(guid);
if (it != m_QueueDataMap.end())
m_QueueDataMap.erase(it);
}
void LfgQueue::UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId)
{
LfgWaitTime &wt = m_waitTimesAvg[dungeonId];
uint32 old_number = wt.number++;
wt.time = int32((wt.time * old_number + waitTime) / wt.number);
}
void LfgQueue::UpdateWaitTimeTank(int32 waitTime, uint32 dungeonId)
{
LfgWaitTime &wt = m_waitTimesTank[dungeonId];
uint32 old_number = wt.number++;
wt.time = int32((wt.time * old_number + waitTime) / wt.number);
}
void LfgQueue::UpdateWaitTimeHealer(int32 waitTime, uint32 dungeonId)
{
LfgWaitTime &wt = m_waitTimesHealer[dungeonId];
uint32 old_number = wt.number++;
wt.time = int32((wt.time * old_number + waitTime) / wt.number);
}
void LfgQueue::UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId)
{
LfgWaitTime &wt = m_waitTimesDps[dungeonId];
uint32 old_number = wt.number++;
wt.time = int32((wt.time * old_number + waitTime) / wt.number);
}
/**
Remove from cached compatible dungeons any entry that contains the given guid
@param[in] guid Guid to remove from compatible cache
*/
void LfgQueue::RemoveFromCompatibles(uint64 guid)
{
std::stringstream out;
out << guid;
std::string strGuid = out.str();
sLog->outDebug(LOG_FILTER_LFG, "LfgQueue::RemoveFromCompatibles: Removing [" UI64FMTD "]", guid);
for (LfgCompatibleMap::iterator itNext = m_CompatibleMap.begin(); itNext != m_CompatibleMap.end();)
{
LfgCompatibleMap::iterator it = itNext++;
if (it->first.find(strGuid) != std::string::npos) // Found, remove it
m_CompatibleMap.erase(it);
}
}
/**
Stores the compatibility of a list of guids
@param[in] key String concatenation of guids (| used as separator)
@param[in] compatibles type of compatibility
*/
void LfgQueue::SetCompatibles(const std::string &key, LfgCompatibility compatibles)
{
m_CompatibleMap[key] = compatibles;
}
/**
Get the compatibility of a group of guids
@param[in] key String concatenation of guids (| used as separator)
@return LfgCompatibility type of compatibility
*/
LfgCompatibility LfgQueue::GetCompatibles(std::string const& key)
{
LfgCompatibleMap::iterator it = m_CompatibleMap.find(key);
if (it != m_CompatibleMap.end())
return it->second;
return LFG_COMPATIBILITY_PENDING;
}
uint8 LfgQueue::FindGroups()
{
uint8 proposals = 0;
LfgGuidList firstNew;
while (!m_newToQueue.empty())
{
uint64 frontguid = m_newToQueue.front();
sLog->outDebug(LOG_FILTER_LFG, "LfgQueue::FindGroups: checking [" UI64FMTD "] newToQueue(%u), currentQueue(%u)", frontguid, uint32(m_newToQueue.size()), uint32(m_currentQueue.size()));
firstNew.clear();
firstNew.push_back(frontguid);
RemoveFromNewQueue(frontguid);
LfgGuidList temporalList = m_currentQueue;
LfgCompatibility compatibles = FindNewGroups(firstNew, temporalList);
if (compatibles == LFG_COMPATIBLES_MATCH)
++proposals;
else
AddToCurrentQueue(frontguid); // Lfg group not found, add this group to the queue.
}
return proposals;
}
/**
Checks que main queue to try to form a Lfg group. Returns first match found (if any)
@param[in] check List of guids trying to match with other groups
@param[in] all List of all other guids in main queue to match against
@return LfgCompatibility type of compatibility between groups
*/
LfgCompatibility LfgQueue::FindNewGroups(LfgGuidList& check, LfgGuidList& all)
{
std::string strGuids = ConcatenateGuids(check);
LfgCompatibility compatibles = GetCompatibles(strGuids);
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::FindNewGroup: (%s): %s - all(%s)", strGuids.c_str(), GetCompatibleString(compatibles), ConcatenateGuids(all).c_str());
if (compatibles == LFG_COMPATIBILITY_PENDING || compatibles == LFG_COMPATIBLES_BAD_STATES) // Not previously cached, calculate
compatibles = CheckCompatibility(check);
if (compatibles != LFG_COMPATIBLES_WITH_LESS_PLAYERS)
return compatibles;
// Try to match with queued groups
while (!all.empty())
{
check.push_back(all.front());
all.pop_front();
LfgCompatibility subcompatibility = FindNewGroups(check, all);
if (subcompatibility == LFG_COMPATIBLES_MATCH)
return LFG_COMPATIBLES_MATCH;
check.pop_back();
}
return compatibles;
}
/**
Check compatibilities between groups. If group is Matched proposal will be created
@param[in] check List of guids to check compatibilities
@return LfgCompatibility type of compatibility
*/
LfgCompatibility LfgQueue::CheckCompatibility(LfgGuidList check)
{
std::string strGuids = ConcatenateGuids(check);
LfgProposal proposal;
LfgDungeonSet proposalDungeons;
LfgGroupsMap proposalGroups;
LfgRolesMap proposalRoles;
// Check for correct size
if (check.size() > MAXGROUPSIZE || check.empty())
{
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s): Size wrong - Not compatibles", strGuids.c_str());
return LFG_INCOMPATIBLES_WRONG_GROUP_SIZE;
}
// Player joining alone always compatible
if (check.size() == 1 && IS_PLAYER_GUID(check.front()))
return LFG_COMPATIBLES_WITH_LESS_PLAYERS;
// Check all-but-new compatiblitity
if (check.size() > 2)
{
uint64 frontGuid = check.front();
check.pop_front();
// Check all-but-new compatibilities (New, A, B, C, D) --> check(A, B, C, D)
LfgCompatibility child_compatibles = CheckCompatibility(check);
if (child_compatibles < LFG_COMPATIBLES_WITH_LESS_PLAYERS) // Group not compatible
{
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) child %s not compatibles", strGuids.c_str(), ConcatenateGuids(check).c_str());
SetCompatibles(strGuids, child_compatibles);
return child_compatibles;
}
check.push_front(frontGuid);
}
// Check if more than one LFG group and number of players joining
uint8 numPlayers = 0;
uint8 numLfgGroups = 0;
for (LfgGuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++it)
{
uint64 guid = (*it);
LfgQueueDataMap::iterator itQueue = m_QueueDataMap.find(guid);
if (itQueue == m_QueueDataMap.end())
{
sLog->outError(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: [" UI64FMTD "] is not queued but listed as queued!", guid);
RemoveFromQueue(guid);
return LFG_COMPATIBILITY_PENDING;
}
// Store group so we don't need to call Mgr to get it later (if it's player group will be 0 otherwise would have joined as group)
for (LfgRolesMap::const_iterator it2 = itQueue->second.roles.begin(); it2 != itQueue->second.roles.end(); ++it2)
proposalGroups[it2->first] = IS_GROUP(itQueue->first) ? itQueue->first : 0;
numPlayers += itQueue->second.roles.size();
if (sLFGMgr->IsLfgGroup(guid))
{
if (!numLfgGroups)
proposal.group = guid;
++numLfgGroups;
}
}
// Group with less that MAXGROUPSIZE members always compatible
if (check.size() == 1 && numPlayers != MAXGROUPSIZE)
{
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) sigle group. Compatibles", strGuids.c_str());
return LFG_COMPATIBLES_WITH_LESS_PLAYERS;
}
if (numLfgGroups > 1)
{
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) More than one Lfggroup (%u)", strGuids.c_str(), numLfgGroups);
SetCompatibles(strGuids, LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS);
return LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS;
}
if (numPlayers > MAXGROUPSIZE)
{
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) Too much players (%u)", strGuids.c_str(), numPlayers);
SetCompatibles(strGuids, LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS);
return LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS;
}
// If it's single group no need to check for duplicate players, ignores, bad roles or bad dungeons as it's been checked before joining
if (check.size() > 1)
{
for (LfgGuidList::const_iterator it = check.begin(); it != check.end(); ++it)
{
const LfgRolesMap &roles = m_QueueDataMap[(*it)].roles;
for (LfgRolesMap::const_iterator itRoles = roles.begin(); itRoles != roles.end(); ++itRoles)
{
LfgRolesMap::const_iterator itPlayer;
for (itPlayer = proposalRoles.begin(); itPlayer != proposalRoles.end(); ++itPlayer)
{
if (itRoles->first == itPlayer->first)
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: ERROR! Player multiple times in queue! [" UI64FMTD "]", itRoles->first);
else if (sLFGMgr->HasIgnore(itRoles->first, itPlayer->first))
break;
}
if (itPlayer == proposalRoles.end())
proposalRoles[itRoles->first] = itRoles->second;
}
}
if (uint8 playersize = numPlayers - proposalRoles.size())
{
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) not compatible, %u players are ignoring each other", strGuids.c_str(), playersize);
SetCompatibles(strGuids, LFG_INCOMPATIBLES_HAS_IGNORES);
return LFG_INCOMPATIBLES_HAS_IGNORES;
}
LfgRolesMap debugRoles = proposalRoles; // DEBUG
if (!LFGMgr::CheckGroupRoles(proposalRoles))
{
std::ostringstream o;
for (LfgRolesMap::const_iterator it = debugRoles.begin(); it != debugRoles.end(); ++it)
o << ", " << it->first << ": " << sLFGMgr->GetRolesString(it->second);
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) Roles not compatible%s", strGuids.c_str(), o.str().c_str());
SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_ROLES);
return LFG_INCOMPATIBLES_NO_ROLES;
}
LfgGuidList::iterator itguid = check.begin();
proposalDungeons = m_QueueDataMap[*itguid].dungeons;
std::ostringstream o;
o << ", " << *itguid << ": (" << sLFGMgr->ConcatenateDungeons(proposalDungeons) << ")";
for (++itguid; itguid != check.end(); ++itguid)
{
LfgDungeonSet temporal;
LfgDungeonSet &dungeons = m_QueueDataMap[*itguid].dungeons;
o << ", " << *itguid << ": (" << sLFGMgr->ConcatenateDungeons(dungeons) << ")";
std::set_intersection(proposalDungeons.begin(), proposalDungeons.end(), dungeons.begin(), dungeons.end(), std::inserter(temporal, temporal.begin()));
proposalDungeons = temporal;
}
if (proposalDungeons.empty())
{
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) No compatible dungeons%s", strGuids.c_str(), o.str().c_str());
SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_DUNGEONS);
return LFG_INCOMPATIBLES_NO_DUNGEONS;
}
}
else
{
uint64 gguid = *check.begin();
const LfgQueueData &queue = m_QueueDataMap[gguid];
proposalDungeons = queue.dungeons;
proposalRoles = queue.roles;
LFGMgr::CheckGroupRoles(proposalRoles); // assing new roles
}
// Enough players?
if (numPlayers != MAXGROUPSIZE)
{
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) Compatibles but not enough players(%u)", strGuids.c_str(), numPlayers);
SetCompatibles(strGuids, LFG_COMPATIBLES_WITH_LESS_PLAYERS);
return LFG_COMPATIBLES_WITH_LESS_PLAYERS;
}
proposal.queues = check;
if (check.size() == 1)
{
for (LfgGroupsMap::const_iterator it = proposalGroups.begin(); it != proposalGroups.end(); ++it)
if (proposal.group && it->second != proposal.group)
proposal.isNew = false;
}
if (!sLFGMgr->AllQueued(check))
{
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) Group MATCH but can't create proposal!", strGuids.c_str());
SetCompatibles(strGuids, LFG_COMPATIBLES_BAD_STATES);
return LFG_COMPATIBLES_BAD_STATES;
}
// Create a new proposal
proposal.cancelTime = time(NULL) + LFG_TIME_PROPOSAL;
proposal.state = LFG_PROPOSAL_INITIATING;
proposal.leader = 0;
proposal.dungeonId = Trinity::Containers::SelectRandomContainerElement(proposalDungeons);
bool leader = false;
for (LfgRolesMap::const_iterator itRoles = proposalRoles.begin(); itRoles != proposalRoles.end(); ++itRoles)
{
// Assing new leader
if (itRoles->second & PLAYER_ROLE_LEADER)
{
if (!leader || !proposal.leader || urand(0, 1))
proposal.leader = itRoles->first;
leader = true;
}
else if (!leader && (!proposal.leader || urand(0, 1)))
proposal.leader = itRoles->first;
// Assing player data and roles
LfgProposalPlayer &data = proposal.players[itRoles->first];
data.role = itRoles->second;
data.group = proposalGroups.find(itRoles->first)->second;
if (!proposal.isNew && data.group && data.group == proposal.group) // Player from existing group, autoaccept
data.accept = LFG_ANSWER_AGREE;
}
// Mark proposal members as not queued (but not remove queue data)
for (LfgGuidList::const_iterator itQueue = proposal.queues.begin(); itQueue != proposal.queues.end(); ++itQueue)
{
uint64 guid = (*itQueue);
RemoveFromNewQueue(guid);
RemoveFromCurrentQueue(guid);
}
sLFGMgr->AddProposal(proposal);
sLog->outDebug(LOG_FILTER_LFG, "LFGQueue::CheckCompatibility: (%s) MATCH! Group formed", strGuids.c_str());
SetCompatibles(strGuids, LFG_COMPATIBLES_MATCH);
return LFG_COMPATIBLES_MATCH;
}
void LfgQueue::UpdateQueueTimers(time_t currTime)
{
for (LfgQueueDataMap::const_iterator itQueue = m_QueueDataMap.begin(); itQueue != m_QueueDataMap.end(); ++itQueue)
{
const LfgQueueData &queueinfo = itQueue->second;
uint32 dungeonId = (*queueinfo.dungeons.begin());
uint32 queuedTime = uint32(currTime - queueinfo.joinTime);
uint8 role = PLAYER_ROLE_NONE;
int32 waitTime = -1;
int32 wtTank = m_waitTimesTank[dungeonId].time;
int32 wtHealer = m_waitTimesHealer[dungeonId].time;
int32 wtDps = m_waitTimesDps[dungeonId].time;
int32 wtAvg = m_waitTimesAvg[dungeonId].time;
for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer)
role |= itPlayer->second;
role &= ~PLAYER_ROLE_LEADER;
switch (role)
{
case PLAYER_ROLE_NONE: // Should not happen - just in case
waitTime = -1;
break;
case PLAYER_ROLE_TANK:
waitTime = wtTank;
break;
case PLAYER_ROLE_HEALER:
waitTime = wtHealer;
break;
case PLAYER_ROLE_DAMAGE:
waitTime = wtDps;
break;
default:
waitTime = wtAvg;
break;
}
LfgQueueStatusData queueData(dungeonId, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps);
for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer)
{
uint64 pguid = itPlayer->first;
LFGMgr::SendLfgQueueStatus(pguid, queueData);
}
}
}
time_t LfgQueue::GetJoinTime(uint64 guid)
{
return m_QueueDataMap[guid].joinTime;
}
+139
View File
@@ -0,0 +1,139 @@
/*
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _LFGQUEUE_H
#define _LFGQUEUE_H
#include "LFG.h"
enum LfgCompatibility
{
LFG_COMPATIBILITY_PENDING,
LFG_INCOMPATIBLES_WRONG_GROUP_SIZE,
LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS,
LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS,
LFG_INCOMPATIBLES_HAS_IGNORES,
LFG_INCOMPATIBLES_NO_ROLES,
LFG_INCOMPATIBLES_NO_DUNGEONS,
LFG_COMPATIBLES_WITH_LESS_PLAYERS, // Values under this = not compatible (do not modify order)
LFG_COMPATIBLES_BAD_STATES,
LFG_COMPATIBLES_MATCH // Must be the last one
};
/// Stores player or group queue info
struct LfgQueueData
{
LfgQueueData(): joinTime(time_t(time(NULL))), tanks(LFG_TANKS_NEEDED),
healers(LFG_HEALERS_NEEDED), dps(LFG_DPS_NEEDED)
{ }
LfgQueueData(time_t _joinTime, const LfgDungeonSet &_dungeons, const LfgRolesMap &_roles)
{
joinTime = _joinTime;
dungeons = _dungeons;
roles = _roles;
tanks = LFG_TANKS_NEEDED;
healers = LFG_HEALERS_NEEDED;
dps = LFG_DPS_NEEDED;
for (LfgRolesMap::const_iterator it = roles.begin(); it != roles.end(); ++it)
{
uint8 role = it->second;
if (role & PLAYER_ROLE_TANK)
--tanks;
else if (role & PLAYER_ROLE_HEALER)
--healers;
else
--dps;
}
}
time_t joinTime; ///< Player queue join time (to calculate wait times)
uint8 tanks; ///< Tanks needed
uint8 healers; ///< Healers needed
uint8 dps; ///< Dps needed
LfgDungeonSet dungeons; ///< Selected Player/Group Dungeon/s
LfgRolesMap roles; ///< Selected Player Role/s
};
struct LfgWaitTime
{
LfgWaitTime(): time(-1), number(0) {}
int32 time; ///< Wait time
uint32 number; ///< Number of people used to get that wait time
};
typedef std::map<uint32, LfgWaitTime> LfgWaitTimesMap;
typedef std::map<std::string, LfgCompatibility> LfgCompatibleMap;
typedef std::map<uint64, LfgQueueData> LfgQueueDataMap;
/**
Stores all data related to queue
*/
class LfgQueue
{
public:
// Add/Remove from queue
void AddToQueue(uint64 guid);
void RemoveFromQueue(uint64 guid);
void AddQueueData(uint64 guid, time_t joinTime, const LfgDungeonSet &dungeons, const LfgRolesMap &rolesMap);
void RemoveQueueData(uint64 guid);
// Update Timers (when proposal success)
void UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId);
void UpdateWaitTimeTank(int32 waitTime, uint32 dungeonId);
void UpdateWaitTimeHealer(int32 waitTime, uint32 dungeonId);
void UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId);
// Update Queue timers
void UpdateQueueTimers(time_t currTime);
time_t GetJoinTime(uint64 guid);
// Find new group
uint8 FindGroups();
// Just for debugging purposes
LfgCompatibleMap const& GetCompatibleMap();
std::string DumpQueueInfo() const;
std::string DumpCompatibleInfo() const;
private:
void AddToNewQueue(uint64 guid);
void AddToCurrentQueue(uint64 guid);
void RemoveFromNewQueue(uint64 guid);
void RemoveFromCurrentQueue(uint64 guid);
void SetCompatibles(std::string const& key, LfgCompatibility compatibles);
LfgCompatibility GetCompatibles(std::string const& key);
void RemoveFromCompatibles(uint64 guid);
LfgCompatibility FindNewGroups(LfgGuidList& check, LfgGuidList& all);
LfgCompatibility CheckCompatibility(LfgGuidList check);
// Queue
LfgQueueDataMap m_QueueDataMap; ///< Queued groups
LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons
LfgWaitTimesMap m_waitTimesAvg; ///< Average wait time to find a group queuing as multiple roles
LfgWaitTimesMap m_waitTimesTank; ///< Average wait time to find a group queuing as tank
LfgWaitTimesMap m_waitTimesHealer; ///< Average wait time to find a group queuing as healer
LfgWaitTimesMap m_waitTimesDps; ///< Average wait time to find a group queuing as dps
LfgGuidList m_currentQueue; ///< Ordered list. Used to find groups
LfgGuidList m_newToQueue; ///< New groups to add to queue
};
#endif
+58 -54
View File
@@ -39,12 +39,12 @@ void LFGPlayerScript::OnLevelChanged(Player* player, uint8 /*oldLevel*/)
void LFGPlayerScript::OnLogout(Player* player)
{
sLFGMgr->Leave(player);
uint64 guid = player->GetGUID();
sLFGMgr->LeaveLfg(guid);
LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
player->GetSession()->SendLfgUpdateParty(updateData);
player->GetSession()->SendLfgUpdatePlayer(updateData);
player->GetSession()->SendLfgUpdateSearch(false);
uint64 guid = player->GetGUID();
player->GetSession()->SendLfgLfrList(false);
// TODO - Do not remove, add timer before deleting
sLFGMgr->RemovePlayerData(guid);
}
@@ -52,6 +52,7 @@ void LFGPlayerScript::OnLogout(Player* player)
void LFGPlayerScript::OnLogin(Player* player)
{
sLFGMgr->InitializeLockedDungeons(player);
sLFGMgr->SetTeam(player->GetGUID(), player->GetTeam());
// TODO - Restore LfgPlayerData and send proper status to player if it was in a group
}
@@ -69,10 +70,18 @@ LFGGroupScript::LFGGroupScript() : GroupScript("LFGGroupScript")
void LFGGroupScript::OnAddMember(Group* group, uint64 guid)
{
uint64 gguid = group->GetGUID();
if (!gguid)
return;
uint64 leader = group->GetLeaderGUID();
sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "]", gguid, guid);
if (leader == guid)
{
sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "] leader " UI64FMTD "]", gguid, guid, leader);
sLFGMgr->SetLeader(gguid, guid);
}
else
{
LfgState gstate = sLFGMgr->GetState(gguid);
LfgState state = sLFGMgr->GetState(guid);
sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "] leader " UI64FMTD "] gstate: %u, state: %u", gguid, guid, leader, gstate, state);
LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_CLEAR_LOCK_LIST);
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
{
@@ -83,61 +92,67 @@ void LFGGroupScript::OnAddMember(Group* group, uint64 guid)
}
}
// TODO - if group is queued and new player is added convert to rolecheck without notify the current players queued
if (sLFGMgr->GetState(gguid) == LFG_STATE_QUEUED)
sLFGMgr->Leave(NULL, group);
if (state == LFG_STATE_QUEUED)
sLFGMgr->LeaveLfg(guid);
if (sLFGMgr->GetState(guid) == LFG_STATE_QUEUED)
if (Player* player = ObjectAccessor::FindPlayer(guid))
sLFGMgr->Leave(player);
// TODO - if group is queued and new player is added convert to rolecheck without notify the current players queued
if (gstate == LFG_STATE_QUEUED)
sLFGMgr->LeaveLfg(gguid);
}
sLFGMgr->SetGroup(guid, gguid);
sLFGMgr->AddPlayerToGroup(gguid, guid);
}
void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod method, uint64 kicker, char const* reason)
{
uint64 gguid = group->GetGUID();
if (!gguid || method == GROUP_REMOVEMETHOD_DEFAULT)
return;
sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnRemoveMember [" UI64FMTD "]: remove [" UI64FMTD "] Method: %d Kicker: [" UI64FMTD "] Reason: %s", gguid, guid, method, kicker, (reason ? reason : ""));
if (sLFGMgr->GetState(gguid) == LFG_STATE_QUEUED)
{
// TODO - Do not remove, just remove the one leaving and rejoin queue with all other data
sLFGMgr->Leave(NULL, group);
}
if (!group->isLFGGroup())
return;
bool isLFG = group->isLFGGroup();
if (method == GROUP_REMOVEMETHOD_KICK) // Player have been kicked
if (isLFG && method == GROUP_REMOVEMETHOD_KICK) // Player have been kicked
{
// TODO - Update internal kick cooldown of kicker
std::string str_reason = "";
if (reason)
str_reason = std::string(reason);
sLFGMgr->InitBoot(group, kicker, guid, str_reason);
sLFGMgr->InitBoot(gguid, kicker, guid, str_reason);
return;
}
uint32 state = sLFGMgr->GetState(gguid);
sLFGMgr->ClearState(guid);
LfgState state = sLFGMgr->GetState(gguid);
// If group is being formed after proposal success do nothing more
if (state == LFG_STATE_PROPOSAL && method == GROUP_REMOVEMETHOD_DEFAULT)
{
// LfgData: Remove player from group
sLFGMgr->SetGroup(guid, 0);
sLFGMgr->RemovePlayerFromGroup(gguid, guid);
return;
}
sLFGMgr->LeaveLfg(guid);
sLFGMgr->SetState(guid, LFG_STATE_NONE);
sLFGMgr->SetGroup(guid, 0);
uint8 players = sLFGMgr->RemovePlayerFromGroup(gguid, guid);
if (Player* player = ObjectAccessor::FindPlayer(guid))
{
if (method == GROUP_REMOVEMETHOD_LEAVE && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON && sLFGMgr->GetDungeon(gguid, false))
if (method == GROUP_REMOVEMETHOD_LEAVE && state == LFG_STATE_DUNGEON &&
players >= LFG_GROUP_KICK_VOTES_NEEDED)
player->CastSpell(player, LFG_SPELL_DUNGEON_DESERTER, true);
/*
else if (group->isLfgKickActive())
//else if (state == LFG_STATE_BOOT)
// Update internal kick cooldown of kicked
*/
LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER);
player->GetSession()->SendLfgUpdateParty(updateData);
if (player->GetMap()->IsDungeon()) // Teleport player out the dungeon
player->GetSession()->SendLfgUpdateParty(LfgUpdateData(LFG_UPDATETYPE_LEADER_UNK1));
if (isLFG && player->GetMap()->IsDungeon()) // Teleport player out the dungeon
sLFGMgr->TeleportPlayer(player, true);
}
if (state != LFG_STATE_FINISHED_DUNGEON)// Need more players to finish the dungeon
sLFGMgr->OfferContinue(group);
if (isLFG && state != LFG_STATE_FINISHED_DUNGEON) // Need more players to finish the dungeon
if (Player* leader = ObjectAccessor::FindPlayer(sLFGMgr->GetLeader(gguid)))
leader->GetSession()->SendLfgOfferContinue(sLFGMgr->GetDungeon(gguid, false));
}
void LFGGroupScript::OnDisband(Group* group)
@@ -151,30 +166,19 @@ void LFGGroupScript::OnDisband(Group* group)
void LFGGroupScript::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid)
{
uint64 gguid = group->GetGUID();
if (!gguid)
return;
sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnChangeLeader [" UI64FMTD "]: old [" UI64FMTD "] new [" UI64FMTD "]", gguid, newLeaderGuid, oldLeaderGuid);
Player* player = ObjectAccessor::FindPlayer(newLeaderGuid);
LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER);
if (player)
player->GetSession()->SendLfgUpdateParty(updateData);
player = ObjectAccessor::FindPlayer(oldLeaderGuid);
if (player)
{
updateData.updateType = LFG_UPDATETYPE_GROUP_DISBAND;
player->GetSession()->SendLfgUpdateParty(updateData);
}
sLFGMgr->SetLeader(gguid, newLeaderGuid);
}
void LFGGroupScript::OnInviteMember(Group* group, uint64 guid)
{
uint64 gguid = group->GetGUID();
if (!gguid)
return;
sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, group->GetLeaderGUID());
sLFGMgr->Leave(NULL, group);
uint64 leader = group->GetLeaderGUID();
sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, leader);
// No gguid == new group being formed
// No leader == after group creation first invite is new leader
// leader and no gguid == first invite after leader is added to new group (this is the real invite)
if (leader && !gguid)
sLFGMgr->LeaveLfg(leader);
}
@@ -1522,14 +1522,18 @@ void GameObject::Use(Unit* user)
Player* player = user->ToPlayer();
if (player->CanUseBattlegroundObject())
if (player->CanUseBattlegroundObject(this))
{
// in battleground check
Battleground* bg = player->GetBattleground();
if (!bg)
return;
if (player->GetVehicle())
return;
player->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
player->RemoveAurasByType(SPELL_AURA_MOD_INVISIBILITY);
// BG flag click
// AB:
// 15001
@@ -1562,14 +1566,18 @@ void GameObject::Use(Unit* user)
Player* player = user->ToPlayer();
if (player->CanUseBattlegroundObject())
if (player->CanUseBattlegroundObject(this))
{
// in battleground check
Battleground* bg = player->GetBattleground();
if (!bg)
return;
if (player->GetVehicle())
return;
player->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
player->RemoveAurasByType(SPELL_AURA_MOD_INVISIBILITY);
// BG flag dropped
// WS:
// 179785 - Silverwing Flag
+76 -144
View File
@@ -598,9 +598,16 @@ void KillRewarder::_RewardGroup()
// 3.1.3. Reward each group member (even dead or corpse) within reward distance.
for (GroupReference* itr = _group->GetFirstMember(); itr != NULL; itr = itr->next())
{
if (Player* member = itr->getSource())
{
if (member->IsAtGroupRewardDistance(_victim))
{
_RewardPlayer(member, isDungeon);
member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, _victim);
}
}
}
}
}
}
@@ -1573,6 +1580,16 @@ void Player::Update(uint32 p_time)
if (now > m_Last_tick + 1)
UpdateSoulboundTradeItems();
// If mute expired, remove it from the DB
if (GetSession()->m_muteTime && GetSession()->m_muteTime < now)
{
GetSession()->m_muteTime = 0;
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_MUTE_TIME);
stmt->setInt64(0, 0); // Set the mute time to 0
stmt->setUInt32(1, GetSession()->GetAccountId());
LoginDatabase.Execute(stmt);
}
if (!m_timedquests.empty())
{
QuestSet::iterator iter = m_timedquests.begin();
@@ -9036,7 +9053,6 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
{
// data depends on zoneid/mapid...
Battleground* bg = GetBattleground();
uint16 NumberOfFields = 0;
uint32 mapid = GetMapId();
OutdoorPvP* pvp = sOutdoorPvPMgr->GetOutdoorPvPToZoneId(zoneid);
InstanceScript* instance = GetInstanceScript();
@@ -9044,94 +9060,12 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
sLog->outDebug(LOG_FILTER_NETWORKIO, "Sending SMSG_INIT_WORLD_STATES to Map: %u, Zone: %u", mapid, zoneid);
// may be exist better way to do this...
switch (zoneid)
{
case 0:
case 1:
case 4:
case 8:
case 10:
case 11:
case 12:
case 36:
case 38:
case 40:
case 41:
case 51:
case 267:
case 1519:
case 1537:
case 2257:
case 2918:
NumberOfFields = 8;
break;
case 139:
NumberOfFields = 41;
break;
case 1377:
NumberOfFields = 15;
break;
case 2597:
NumberOfFields = 83;
break;
case 3277:
NumberOfFields = 18;
break;
case 3358:
case 3820:
NumberOfFields = 40;
break;
case 3483:
NumberOfFields = 27;
break;
case 3518:
NumberOfFields = 39;
break;
case 3519:
NumberOfFields = 38;
break;
case 3521:
NumberOfFields = 37;
break;
case 3698:
case 3702:
case 3968:
case 4378:
case 3703:
NumberOfFields = 11;
break;
case 4384:
NumberOfFields = 30;
break;
case 4710:
NumberOfFields = 28;
break;
case 4812: // Icecrown Citadel
case 4100: // The Culling of Stratholme
NumberOfFields = 13;
break;
case 4987: // The Ruby Sanctum
NumberOfFields = 3;
break;
case 4273: // Ulduar
NumberOfFields = 10;
break;
case 4197: // Wintergrasp
/// Use the max here, and fill with zeros if missing.
NumberOfFields = 10 + WG_MAX_OBJ + WG_MAX_WORKSHOP;
break;
default:
NumberOfFields = 12;
break;
}
WorldPacket data(SMSG_INIT_WORLD_STATES, (4+4+4+2+(NumberOfFields*8)));
WorldPacket data(SMSG_INIT_WORLD_STATES, (4+4+4+2+(12*8)));
data << uint32(mapid); // mapid
data << uint32(zoneid); // zone id
data << uint32(areaid); // area id, new 2.1.0
size_t countPos = data.wpos();
data << uint16(NumberOfFields); // count of uint64 blocks
data << uint16(0); // count of uint64 blocks
data << uint32(0x8d8) << uint32(0x0); // 1
data << uint32(0x8d7) << uint32(0x0); // 2
data << uint32(0x8d6) << uint32(0x0); // 3
@@ -9694,8 +9628,6 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
bf->FillInitialWorldStates(data);
break;
}
else
data.put<uint16>(countPos, 12);
// No break here, intended.
default:
data << uint32(0x914) << uint32(0x0); // 7
@@ -9704,6 +9636,10 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(0x915) << uint32(0x0); // 10
break;
}
uint16 length = (data.wpos() - countPos) / 8;
data.put<uint16>(countPos, length);
GetSession()->SendPacket(&data);
SendBGWeekendWorldStates();
SendBattlefieldWorldStates();
@@ -11965,7 +11901,7 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
bool lootedObjectInDungeon = false;
Map const* map = lootedObject->GetMap();
if (uint32 dungeonId = sLFGMgr->GetDungeon(GetGroup()->GetGUID(), true))
if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId))
if (LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId))
if (uint32(dungeon->map) == map->GetId() && dungeon->difficulty == uint32(map->GetDifficulty()))
lootedObjectInDungeon = true;
@@ -15044,19 +14980,6 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
if (questGiver && quest->GetQuestStartScript() != 0)
GetMap()->ScriptsStart(sQuestStartScripts, quest->GetQuestStartScript(), questGiver, this);
// Some spells applied at quest activation
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id, true);
if (saBounds.first != saBounds.second)
{
uint32 zone, area;
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
}
UpdateForQuestWorldObjects();
}
@@ -15245,33 +15168,6 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId());
uint32 zone = 0;
uint32 area = 0;
// remove auras from spells with quest reward state limitations
SpellAreaForQuestMapBounds saEndBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id);
if (saEndBounds.first != saEndBounds.second)
{
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saEndBounds.first; itr != saEndBounds.second; ++itr)
if (!itr->second->IsFitToRequirements(this, zone, area))
RemoveAurasDueToSpell(itr->second->spellId);
}
// Some spells applied at quest reward
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id, false);
if (saBounds.first != saBounds.second)
{
if (!zone || !area)
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
}
//lets remove flag for delayed teleports
SetCanDelayTeleport(false);
}
@@ -15814,6 +15710,30 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
m_QuestStatusSave[quest_id] = true;
}
uint32 zone = 0, area = 0;
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id);
if (saBounds.first != saBounds.second)
{
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
}
saBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id);
if (saBounds.first != saBounds.second)
{
if (!zone || !area)
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (!itr->second->IsFitToRequirements(this, zone, area))
RemoveAurasDueToSpell(itr->second->spellId);
}
UpdateForQuestWorldObjects();
}
@@ -23341,7 +23261,7 @@ PartyResult Player::CanUninviteFromGroup() const
if (state == LFG_STATE_BOOT)
return ERR_PARTY_LFG_BOOT_IN_PROGRESS;
if (grp->GetMembersCount() <= sLFGMgr->GetVotesNeeded(gguid))
if (grp->GetMembersCount() <= LFG_GROUP_KICK_VOTES_NEEDED)
return ERR_PARTY_LFG_BOOT_TOO_FEW_PLAYERS;
if (state == LFG_STATE_FINISHED_DUNGEON)
@@ -23374,8 +23294,22 @@ PartyResult Player::CanUninviteFromGroup() const
bool Player::isUsingLfg()
{
uint64 guid = GetGUID();
return sLFGMgr->GetState(guid) != LFG_STATE_NONE;
return sLFGMgr->GetState(GetGUID()) != LFG_STATE_NONE;
}
bool Player::inRandomLfgDungeon()
{
if (isUsingLfg())
{
const LfgDungeonSet& dungeons = sLFGMgr->GetSelectedDungeons(GetGUID());
if (!dungeons.empty())
{
LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(*dungeons.begin());
if (dungeon && (dungeon->type == LFG_TYPE_RANDOM || dungeon->seasonal))
return true;
}
}
return false;
}
void Player::SetBattlegroundOrBattlefieldRaid(Group* group, int8 subgroup)
@@ -23568,21 +23502,19 @@ WorldObject* Player::GetViewpoint() const
return NULL;
}
bool Player::CanUseBattlegroundObject()
bool Player::CanUseBattlegroundObject(GameObject* gameobject)
{
// TODO : some spells gives player ForceReaction to one faction (ReputationMgr::ApplyForceReaction)
// maybe gameobject code should handle that ForceReaction usage
FactionTemplateEntry const* playerFaction = getFactionTemplateEntry();
FactionTemplateEntry const* faction = sFactionTemplateStore.LookupEntry(gameobject->GetUInt32Value(GAMEOBJECT_FACTION));
if (playerFaction && faction && !playerFaction->IsFriendlyTo(*faction))
return false;
// BUG: sometimes when player clicks on flag in AB - client won't send gameobject_use, only gameobject_report_use packet
return (//InBattleground() && // in battleground - not need, check in other cases
//!IsMounted() && - not correct, player is dismounted when he clicks on flag
//player cannot use object when he is invulnerable (immune)
!isTotalImmune() && // not totally immune
//i'm not sure if these two are correct, because invisible players should get visible when they click on flag
!HasStealthAura() && // not stealthed
!HasInvisibilityAura() && // not invisible
!HasAura(SPELL_RECENTLY_DROPPED_FLAG) && // can't pickup
isAlive() // live player
);
// Note: Mount, stealth and invisibility will be removed when used
return (!isTotalImmune() && // Damage immune
!HasAura(SPELL_RECENTLY_DROPPED_FLAG) && // Still has recently held flag debuff
isAlive()); // Alive
}
bool Player::CanCaptureTowerPoint()
+2 -1
View File
@@ -2237,7 +2237,7 @@ class Player : public Unit, public GridObject<Player>
bool GetBGAccessByLevel(BattlegroundTypeId bgTypeId) const;
bool isTotalImmunity();
bool CanUseBattlegroundObject();
bool CanUseBattlegroundObject(GameObject* gameobject);
bool isTotalImmune();
bool CanCaptureTowerPoint();
@@ -2356,6 +2356,7 @@ class Player : public Unit, public GridObject<Player>
void RemoveAtLoginFlag(AtLoginFlags flags, bool persist = false);
bool isUsingLfg();
bool inRandomLfgDungeon();
typedef std::set<uint32> DFQuestsDoneList;
DFQuestsDoneList m_DFQuests;
+17 -16
View File
@@ -703,14 +703,8 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
sLog->outDebug(LOG_FILTER_UNITS, "DealDamage: victim just died");
if (victim->GetTypeId() == TYPEID_PLAYER && victim != this)
{
victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health);
// call before auras are removed
if (Player* killer = GetCharmerOrOwnerPlayerOrPlayerItself())
killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, victim);
}
Kill(victim, durabilityLoss);
}
else
@@ -2302,6 +2296,9 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell)
// Ranged attacks can only miss, resist and deflect
if (attType == RANGED_ATTACK)
{
canParry = false;
canDodge = false;
// only if in front
if (victim->HasInArc(M_PI, this) || victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION))
{
@@ -6637,30 +6634,30 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return false;
triggered_spell_id = 0;
Unit* beaconTarget = NULL;
if (this->GetTypeId() != TYPEID_PLAYER)
if (GetTypeId() != TYPEID_PLAYER)
{
beaconTarget = triggeredByAura->GetBase()->GetCaster();
if (beaconTarget == this || !(beaconTarget->GetAura(53563, victim->GetGUID())))
if (!beaconTarget || beaconTarget == this || !(beaconTarget->GetAura(53563, victim->GetGUID())))
return false;
basepoints0 = int32(damage);
triggered_spell_id = procSpell->IsRankOf(sSpellMgr->GetSpellInfo(635)) ? 53652 : 53654;
}
else
{ // Check Party/Raid Group
if (Group *group = this->ToPlayer()->GetGroup())
if (Group* group = ToPlayer()->GetGroup())
{
for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
{
if (Player* member = itr->getSource())
{
Player* Member = itr->getSource();
// check if it was heal by paladin which casted this beacon of light
if (Member->GetAura(53563, victim->GetGUID()))
if (member->GetAura(53563, victim->GetGUID()))
{
// do not proc when target of beacon of light is healed
if (Member == this)
if (member == this)
return false;
beaconTarget = Member;
beaconTarget = member;
basepoints0 = int32(damage);
triggered_spell_id = procSpell->IsRankOf(sSpellMgr->GetSpellInfo(635)) ? 53652 : 53654;
break;
@@ -6668,13 +6665,14 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
}
}
}
if (triggered_spell_id && beaconTarget)
{
victim->CastCustomSpell(beaconTarget, triggered_spell_id, &basepoints0, NULL, NULL, true, 0, triggeredByAura);
return true;
}
else
return false;
}
// Judgements of the Wise
@@ -13661,6 +13659,9 @@ void Unit::SetLevel(uint8 lvl)
// group update
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetGroup())
ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_LEVEL);
if (GetTypeId() == TYPEID_PLAYER)
sWorld->UpdateCharacterNameDataLevel(ToPlayer()->GetGUIDLow(), lvl);
}
void Unit::SetHealth(uint32 val)
+23 -1
View File
@@ -45,6 +45,7 @@
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "PoolMgr.h"
#include "LFGMgr.h"
ScriptMapMap sQuestEndScripts;
ScriptMapMap sQuestStartScripts;
@@ -5028,7 +5029,7 @@ void ObjectMgr::LoadInstanceEncounters()
continue;
}
if (lastEncounterDungeon && !sLFGDungeonStore.LookupEntry(lastEncounterDungeon))
if (lastEncounterDungeon && !sLFGMgr->GetLFGDungeon(lastEncounterDungeon))
{
sLog->outError(LOG_FILTER_SQL, "Table `instance_encounters` has an encounter %u (%s) marked as final for invalid dungeon id %u, skipped!", entry, dungeonEncounter->encounterName[0], lastEncounterDungeon);
continue;
@@ -7590,6 +7591,27 @@ SpellScriptsBounds ObjectMgr::GetSpellScriptsBounds(uint32 spell_id)
return SpellScriptsBounds(_spellScriptsStore.lower_bound(spell_id), _spellScriptsStore.upper_bound(spell_id));
}
// this allows calculating base reputations to offline players, just by race and class
int32 ObjectMgr::GetBaseReputationOff(FactionEntry const* factionEntry, uint8 race, uint8 playerClass)
{
if (!factionEntry)
return 0;
uint32 raceMask = (1 << (race - 1));
uint32 classMask = (1 << (playerClass-1));
for (int i = 0; i < 4; i++)
{
if ((!factionEntry->BaseRepClassMask[i] ||
factionEntry->BaseRepClassMask[i] & classMask) &&
(!factionEntry->BaseRepRaceMask[i] ||
factionEntry->BaseRepRaceMask[i] & raceMask))
return factionEntry->BaseRepValue[i];
}
return 0;
}
SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial)
{
switch (pSkill->categoryId)
+2
View File
@@ -749,6 +749,8 @@ class ObjectMgr
return NULL;
}
int32 GetBaseReputationOff(FactionEntry const* factionEntry, uint8 race, uint8 playerClass);
RepSpilloverTemplate const* GetRepSpilloverTemplate(uint32 factionId) const
{
RepSpilloverTemplateContainer::const_iterator itr = _repSpilloverTemplateStore.find(factionId);
+2 -2
View File
@@ -523,7 +523,7 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV
WorldPacket data;
if (method == GROUP_REMOVEMETHOD_KICK)
if (method == GROUP_REMOVEMETHOD_KICK || method == GROUP_REMOVEMETHOD_KICK_LFG)
{
data.Initialize(SMSG_GROUP_UNINVITE, 0);
player->GetSession()->SendPacket(&data);
@@ -600,7 +600,7 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV
if (isLFGGroup() && GetMembersCount() == 1)
{
Player* Leader = ObjectAccessor::FindPlayer(GetLeaderGUID());
LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(sLFGMgr->GetDungeon(GetGUID()));
LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(sLFGMgr->GetDungeon(GetGUID()));
if ((Leader && dungeon && Leader->isAlive() && Leader->GetMapId() != uint32(dungeon->map)) || !dungeon)
{
Disband();
+45 -12
View File
@@ -660,7 +660,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
std::string IP_str = GetRemoteAddress();
sLog->outInfo(LOG_FILTER_CHARACTER, "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow());
sScriptMgr->OnPlayerCreate(&newChar);
sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass());
sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass(), newChar.getLevel());
newChar.CleanupsBeforeDelete();
delete createInfo;
@@ -1625,10 +1625,14 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data)
uint32 lowGuid = GUID_LOPART(guid);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN);
// get the players old (at this moment current) race
CharacterNameData const* nameData = sWorld->GetCharacterNameData(lowGuid);
uint8 oldRace = nameData->m_race;
uint8 playerClass = nameData->m_class;
uint8 level = nameData->m_level;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_AT_LOGIN_TITLES);
stmt->setUInt32(0, lowGuid);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
@@ -1640,11 +1644,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data)
}
Field* fields = result->Fetch();
uint32 playerClass = uint32(fields[0].GetUInt8());
uint32 level = uint32(fields[1].GetUInt8());
uint32 at_loginFlags = fields[2].GetUInt16();
uint32 at_loginFlags = fields[0].GetUInt16();
char const* knownTitlesStr = fields[1].GetCString();
uint32 used_loginFlag = ((recv_data.GetOpcode() == CMSG_CHAR_RACE_CHANGE) ? AT_LOGIN_CHANGE_RACE : AT_LOGIN_CHANGE_FACTION);
char const* knownTitlesStr = fields[3].GetCString();
if (!sObjectMgr->GetPlayerInfo(race, playerClass))
{
@@ -2003,16 +2005,47 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data)
{
uint32 reputation_alliance = it->first;
uint32 reputation_horde = it->second;
uint32 newReputation = (team == TEAM_ALLIANCE) ? reputation_alliance : reputation_horde;
uint32 oldReputation = (team == TEAM_ALLIANCE) ? reputation_horde : reputation_alliance;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION);
stmt->setUInt32(0, uint16(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde));
// select old standing set in db
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
stmt->setUInt32(0, oldReputation);
stmt->setUInt32(1, lowGuid);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
{
WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1);
data << uint8(CHAR_CREATE_ERROR);
SendPacket(&data);
return;
}
Field* fields = result->Fetch();
int32 oldDBRep = fields[0].GetInt32();
FactionEntry const* factionEntry = sFactionStore.LookupEntry(oldReputation);
// old base reputation
int32 oldBaseRep = sObjectMgr->GetBaseReputationOff(factionEntry, oldRace, playerClass);
// new base reputation
int32 newBaseRep = sObjectMgr->GetBaseReputationOff(sFactionStore.LookupEntry(newReputation), race, playerClass);
// final reputation shouldnt change
int32 FinalRep = oldDBRep + oldBaseRep;
int32 newDBRep = FinalRep - newBaseRep;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION);
stmt->setUInt32(0, newReputation);
stmt->setUInt32(1, lowGuid);
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
stmt->setUInt16(0, uint16(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde));
stmt->setUInt16(1, uint16(team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance));
stmt->setUInt32(2, lowGuid);
stmt->setUInt16(0, uint16(newReputation));
stmt->setInt32(1, newDBRep);
stmt->setUInt16(2, uint16(oldReputation));
stmt->setUInt32(3, lowGuid);
trans->Append(stmt);
}
+122 -172
View File
@@ -23,8 +23,6 @@
#include "LFGMgr.h"
#include "ObjectMgr.h"
#include "GroupMgr.h"
#include "GameEventMgr.h"
#include "InstanceScript.h"
void BuildPlayerLockDungeonBlock(WorldPacket& data, const LfgLockMap& lock)
{
@@ -82,18 +80,20 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recv_data)
std::string comment;
recv_data >> comment;
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_JOIN [" UI64FMTD "] roles: %u, Dungeons: %u, Comment: %s", GetPlayer()->GetGUID(), roles, uint8(newDungeons.size()), comment.c_str());
sLFGMgr->Join(GetPlayer(), uint8(roles), newDungeons, comment);
sLFGMgr->JoinLfg(GetPlayer(), uint8(roles), newDungeons, comment);
}
void WorldSession::HandleLfgLeaveOpcode(WorldPacket& /*recv_data*/)
{
Group* grp = GetPlayer()->GetGroup();
uint64 guid = GetPlayer()->GetGUID();
uint64 gguid = grp ? grp->GetGUID() : guid;
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LEAVE [" UI64FMTD "] in group: %u", GetPlayer()->GetGUID(), grp ? 1 : 0);
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LEAVE [" UI64FMTD "] in group: %u", guid, grp ? 1 : 0);
// Check cheating - only leader can leave the queue
if (!grp || grp->GetLeaderGUID() == GetPlayer()->GetGUID())
sLFGMgr->Leave(GetPlayer(), grp);
sLFGMgr->LeaveLfg(gguid);
}
void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recv_data)
@@ -128,7 +128,7 @@ void WorldSession::HandleLfgSetCommentOpcode(WorldPacket& recv_data)
std::string comment;
recv_data >> comment;
uint64 guid = GetPlayer()->GetGUID();
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SET_LFG_COMMENT [" UI64FMTD "] comment: %s", guid, comment.c_str());
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_COMMENT [" UI64FMTD "] comment: %s", guid, comment.c_str());
sLFGMgr->SetComment(guid, comment);
}
@@ -138,8 +138,9 @@ void WorldSession::HandleLfgSetBootVoteOpcode(WorldPacket& recv_data)
bool agree; // Agree to kick player
recv_data >> agree;
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_BOOT_VOTE [" UI64FMTD "] agree: %u", GetPlayer()->GetGUID(), agree ? 1 : 0);
sLFGMgr->UpdateBoot(GetPlayer(), agree);
uint64 guid = GetPlayer()->GetGUID();
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_BOOT_VOTE [" UI64FMTD "] agree: %u", guid, agree ? 1 : 0);
sLFGMgr->UpdateBoot(guid, agree);
}
void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recv_data)
@@ -154,32 +155,24 @@ void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recv_data)
void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data*/)
{
uint64 guid = GetPlayer()->GetGUID();
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST [" UI64FMTD "]", guid);
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_PLAYER_LOCK_INFO_REQUEST [" UI64FMTD "]", guid);
// Get Random dungeons that can be done at a certain level and expansion
LfgDungeonSet randomDungeons;
uint8 level = GetPlayer()->getLevel();
uint8 expansion = GetPlayer()->GetSession()->Expansion();
for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i)
{
LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i);
if (dungeon && dungeon->expansion <= expansion && dungeon->minlevel <= level && level <= dungeon->maxlevel)
{
if (dungeon->flags & LFG_FLAG_SEASONAL)
{
if (HolidayIds holiday = sLFGMgr->GetDungeonSeason(dungeon->ID))
if (!IsHolidayActive(holiday))
continue;
}
else if (dungeon->type != LFG_TYPE_RANDOM)
continue;
randomDungeons.insert(dungeon->Entry());
}
LFGDungeonMap& LfgDungeons = sLFGMgr->GetLFGDungeonMap();
for (LFGDungeonMap::const_iterator itr = LfgDungeons.begin(); itr != LfgDungeons.end(); ++itr)
{
LFGDungeonData const& dungeon = itr->second;
if ((dungeon.type == LFG_TYPE_RANDOM || (dungeon.seasonal && sLFGMgr->IsSeasonActive(dungeon.id)))
&& dungeon.expansion <= expansion && dungeon.minlevel <= level && level <= dungeon.maxlevel)
randomDungeons.insert(dungeon.Entry());
}
// Get player locked Dungeons
LfgLockMap lock = sLFGMgr->GetLockedDungeons(guid);
LfgLockMap const& lock = sLFGMgr->GetLockedDungeons(guid);
uint32 rsize = uint32(randomDungeons.size());
uint32 lsize = uint32(lock.size());
@@ -191,39 +184,36 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data
{
data << uint32(*it); // Dungeon Entry (id + type)
LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(*it, level);
Quest const* qRew = NULL;
Quest const* quest = NULL;
uint8 done = 0;
if (reward)
{
qRew = sObjectMgr->GetQuestTemplate(reward->reward[0].questId);
if (qRew)
quest = sObjectMgr->GetQuestTemplate(reward->reward[0].questId);
if (quest)
{
done = !GetPlayer()->CanRewardQuest(qRew, false);
done = !GetPlayer()->CanRewardQuest(quest, false);
if (done)
qRew = sObjectMgr->GetQuestTemplate(reward->reward[1].questId);
quest = sObjectMgr->GetQuestTemplate(reward->reward[1].questId);
}
}
if (qRew)
if (quest)
{
data << uint8(done);
data << uint32(qRew->GetRewOrReqMoney());
data << uint32(qRew->XPValue(GetPlayer()));
data << uint32(quest->GetRewOrReqMoney());
data << uint32(quest->XPValue(GetPlayer()));
data << uint32(reward->reward[done].variableMoney);
data << uint32(reward->reward[done].variableXP);
data << uint8(qRew->GetRewItemsCount());
if (qRew->GetRewItemsCount())
data << uint8(quest->GetRewItemsCount());
if (quest->GetRewItemsCount())
{
ItemTemplate const* iProto = NULL;
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
if (uint32 itemId = quest->RewardItemId[i])
{
if (!qRew->RewardItemId[i])
continue;
iProto = sObjectMgr->GetItemTemplate(qRew->RewardItemId[i]);
data << uint32(qRew->RewardItemId[i]);
data << uint32(iProto ? iProto->DisplayInfoID : 0);
data << uint32(qRew->RewardItemIdCount[i]);
ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId);
data << uint32(itemId);
data << uint32(item ? item->DisplayInfoID : 0);
data << uint32(quest->RewardItemIdCount[i]);
}
}
}
@@ -244,7 +234,7 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data
void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recv_data*/)
{
uint64 guid = GetPlayer()->GetGUID();
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFD_PARTY_LOCK_INFO_REQUEST [" UI64FMTD "]", guid);
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_PARTY_LOCK_INFO_REQUEST [" UI64FMTD "]", guid);
Group* grp = GetPlayer()->GetGroup();
if (!grp)
@@ -275,11 +265,11 @@ void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recv_data
SendPacket(&data);
}
void WorldSession::HandleLfrSearchOpcode(WorldPacket& recv_data)
void WorldSession::HandleLfrJoinOpcode(WorldPacket& recv_data)
{
uint32 entry; // Raid id to search
recv_data >> entry;
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SEARCH_LFG_JOIN [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), entry);
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LFR_JOIN [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), entry);
//SendLfrUpdateListOpcode(entry);
}
@@ -287,7 +277,7 @@ void WorldSession::HandleLfrLeaveOpcode(WorldPacket& recv_data)
{
uint32 dungeonId; // Raid id queue to leave
recv_data >> dungeonId;
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SEARCH_LFG_LEAVE [" UI64FMTD "] dungeonId: %u", GetPlayer()->GetGUID(), dungeonId);
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LFR_LEAVE [" UI64FMTD "] dungeonId: %u", GetPlayer()->GetGUID(), dungeonId);
//sLFGMgr->LeaveLfr(GetPlayer(), dungeonId);
}
@@ -295,6 +285,8 @@ void WorldSession::SendLfgUpdatePlayer(const LfgUpdateData& updateData)
{
bool queued = false;
bool extrainfo = false;
uint64 guid = GetPlayer()->GetGUID();
uint8 size = uint8(updateData.dungeons.size());
switch (updateData.updateType)
{
@@ -311,9 +303,6 @@ void WorldSession::SendLfgUpdatePlayer(const LfgUpdateData& updateData)
break;
}
uint64 guid = GetPlayer()->GetGUID();
uint8 size = uint8(updateData.dungeons.size());
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_PLAYER [" UI64FMTD "] updatetype: %u", guid, updateData.updateType);
WorldPacket data(SMSG_LFG_UPDATE_PLAYER, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + size * 4 + updateData.comment.length()));
data << uint8(updateData.updateType); // Lfg Update type
@@ -338,6 +327,8 @@ void WorldSession::SendLfgUpdateParty(const LfgUpdateData& updateData)
bool join = false;
bool extrainfo = false;
bool queued = false;
uint64 guid = GetPlayer()->GetGUID();
uint8 size = uint8(updateData.dungeons.size());
switch (updateData.updateType)
{
@@ -361,9 +352,6 @@ void WorldSession::SendLfgUpdateParty(const LfgUpdateData& updateData)
break;
}
uint64 guid = GetPlayer()->GetGUID();
uint8 size = uint8(updateData.dungeons.size());
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_PARTY [" UI64FMTD "] updatetype: %u", guid, updateData.updateType);
WorldPacket data(SMSG_LFG_UPDATE_PARTY, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + 1 + size * 4 + updateData.comment.length()));
data << uint8(updateData.updateType); // Lfg Update type
@@ -397,45 +385,44 @@ void WorldSession::SendLfgRoleChosen(uint64 guid, uint8 roles)
SendPacket(&data);
}
void WorldSession::SendLfgRoleCheckUpdate(const LfgRoleCheck* pRoleCheck)
void WorldSession::SendLfgRoleCheckUpdate(const LfgRoleCheck& roleCheck)
{
ASSERT(pRoleCheck);
LfgDungeonSet dungeons;
if (pRoleCheck->rDungeonId)
dungeons.insert(pRoleCheck->rDungeonId);
if (roleCheck.rDungeonId)
dungeons.insert(roleCheck.rDungeonId);
else
dungeons = pRoleCheck->dungeons;
dungeons = roleCheck.dungeons;
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_ROLE_CHECK_UPDATE [" UI64FMTD "]", GetPlayer()->GetGUID());
WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + dungeons.size() * 4 + 1 + pRoleCheck->roles.size() * (8 + 1 + 4 + 1));
WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + dungeons.size() * 4 + 1 + roleCheck.roles.size() * (8 + 1 + 4 + 1));
data << uint32(pRoleCheck->state); // Check result
data << uint8(pRoleCheck->state == LFG_ROLECHECK_INITIALITING);
data << uint32(roleCheck.state); // Check result
data << uint8(roleCheck.state == LFG_ROLECHECK_INITIALITING);
data << uint8(dungeons.size()); // Number of dungeons
if (!dungeons.empty())
{
for (LfgDungeonSet::iterator it = dungeons.begin(); it != dungeons.end(); ++it)
{
LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(*it);
LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(*it);
data << uint32(dungeon ? dungeon->Entry() : 0); // Dungeon
}
}
data << uint8(pRoleCheck->roles.size()); // Players in group
if (!pRoleCheck->roles.empty())
data << uint8(roleCheck.roles.size()); // Players in group
if (!roleCheck.roles.empty())
{
// Leader info MUST be sent 1st :S
uint64 guid = pRoleCheck->leader;
uint8 roles = pRoleCheck->roles.find(guid)->second;
uint64 guid = roleCheck.leader;
uint8 roles = roleCheck.roles.find(guid)->second;
data << uint64(guid); // Guid
data << uint8(roles > 0); // Ready
data << uint32(roles); // Roles
Player* player = ObjectAccessor::FindPlayer(guid);
data << uint8(player ? player->getLevel() : 0); // Level
for (LfgRolesMap::const_iterator it = pRoleCheck->roles.begin(); it != pRoleCheck->roles.end(); ++it)
for (LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it)
{
if (it->first == pRoleCheck->leader)
if (it->first == roleCheck.leader)
continue;
guid = it->first;
@@ -465,30 +452,31 @@ void WorldSession::SendLfgJoinResult(const LfgJoinResultData& joinData)
SendPacket(&data);
}
void WorldSession::SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps)
void WorldSession::SendLfgQueueStatus(const LfgQueueStatusData& queueData)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_QUEUE_STATUS [" UI64FMTD "] dungeon: %u - waitTime: %d - avgWaitTime: %d - waitTimeTanks: %d - waitTimeHealer: %d - waitTimeDps: %d - queuedTime: %u - tanks: %u - healers: %u - dps: %u", GetPlayer()->GetGUID(), dungeon, waitTime, avgWaitTime, waitTimeTanks, waitTimeHealer, waitTimeDps, queuedTime, tanks, healers, dps);
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_QUEUE_STATUS [" UI64FMTD "] dungeon: %u - waitTime: %d - avgWaitTime: %d - waitTimeTanks: %d - waitTimeHealer: %d - waitTimeDps: %d - queuedTime: %u - tanks: %u - healers: %u - dps: %u",
GetPlayer()->GetGUID(), queueData.dungeonId, queueData.waitTime, queueData.waitTimeAvg, queueData.waitTimeTank, queueData.waitTimeHealer, queueData.waitTimeDps, queueData.queuedTime, queueData.tanks, queueData.healers, queueData.dps);
WorldPacket data(SMSG_LFG_QUEUE_STATUS, 4 + 4 + 4 + 4 + 4 +4 + 1 + 1 + 1 + 4);
data << uint32(dungeon); // Dungeon
data << int32(avgWaitTime); // Average Wait time
data << int32(waitTime); // Wait Time
data << int32(waitTimeTanks); // Wait Tanks
data << int32(waitTimeHealer); // Wait Healers
data << int32(waitTimeDps); // Wait Dps
data << uint8(tanks); // Tanks needed
data << uint8(healers); // Healers needed
data << uint8(dps); // Dps needed
data << uint32(queuedTime); // Player wait time in queue
data << uint32(queueData.dungeonId); // Dungeon
data << int32(queueData.waitTimeAvg); // Average Wait time
data << int32(queueData.waitTime); // Wait Time
data << int32(queueData.waitTimeTank); // Wait Tanks
data << int32(queueData.waitTimeHealer); // Wait Healers
data << int32(queueData.waitTimeDps); // Wait Dps
data << uint8(queueData.tanks); // Tanks needed
data << uint8(queueData.healers); // Healers needed
data << uint8(queueData.dps); // Dps needed
data << uint32(queueData.queuedTime); // Player wait time in queue
SendPacket(&data);
}
void WorldSession::SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntry, uint8 done, const LfgReward* reward, const Quest* qRew)
void WorldSession::SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntry, uint8 done, const LfgReward* reward, const Quest* quest)
{
if (!rdungeonEntry || !sdungeonEntry || !qRew)
if (!rdungeonEntry || !sdungeonEntry || !quest)
return;
uint8 itemNum = uint8(qRew ? qRew->GetRewItemsCount() : 0);
uint8 itemNum = uint8(quest ? quest->GetRewItemsCount() : 0);
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PLAYER_REWARD [" UI64FMTD "] rdungeonEntry: %u - sdungeonEntry: %u - done: %u", GetPlayer()->GetGUID(), rdungeonEntry, sdungeonEntry, done);
WorldPacket data(SMSG_LFG_PLAYER_REWARD, 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + itemNum * (4 + 4 + 4));
@@ -496,37 +484,33 @@ void WorldSession::SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntr
data << uint32(sdungeonEntry); // Dungeon Finished
data << uint8(done);
data << uint32(1);
data << uint32(qRew->GetRewOrReqMoney());
data << uint32(qRew->XPValue(GetPlayer()));
data << uint32(quest->GetRewOrReqMoney());
data << uint32(quest->XPValue(GetPlayer()));
data << uint32(reward->reward[done].variableMoney);
data << uint32(reward->reward[done].variableXP);
data << uint8(itemNum);
if (itemNum)
{
ItemTemplate const* iProto = NULL;
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
if (uint32 itemId = quest->RewardItemId[i])
{
if (!qRew->RewardItemId[i])
continue;
iProto = sObjectMgr->GetItemTemplate(qRew->RewardItemId[i]);
data << uint32(qRew->RewardItemId[i]);
data << uint32(iProto ? iProto->DisplayInfoID : 0);
data << uint32(qRew->RewardItemIdCount[i]);
ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId);
data << uint32(itemId);
data << uint32(item ? item->DisplayInfoID : 0);
data << uint32(quest->RewardItemIdCount[i]);
}
}
SendPacket(&data);
}
void WorldSession::SendLfgBootPlayer(const LfgPlayerBoot* pBoot)
void WorldSession::SendLfgBootProposalUpdate(const LfgPlayerBoot& boot)
{
uint64 guid = GetPlayer()->GetGUID();
LfgAnswer playerVote = pBoot->votes.find(guid)->second;
LfgAnswer playerVote = boot.votes.find(guid)->second;
uint8 votesNum = 0;
uint8 agreeNum = 0;
uint32 secsleft = uint8((pBoot->cancelTime - time(NULL)) / 1000);
for (LfgAnswerMap::const_iterator it = pBoot->votes.begin(); it != pBoot->votes.end(); ++it)
uint32 secsleft = uint8((boot.cancelTime - time(NULL)) / 1000);
for (LfgAnswerMap::const_iterator it = boot.votes.begin(); it != boot.votes.end(); ++it)
{
if (it->second != LFG_ANSWER_PENDING)
{
@@ -536,106 +520,72 @@ void WorldSession::SendLfgBootPlayer(const LfgPlayerBoot* pBoot)
}
}
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PROPOSAL_UPDATE [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s",
guid, uint8(pBoot->inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), pBoot->victim, votesNum, agreeNum, secsleft, pBoot->votedNeeded, pBoot->reason.c_str());
WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length());
data << uint8(pBoot->inProgress); // Vote in progress
guid, uint8(boot.inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), boot.victim, votesNum, agreeNum, secsleft, LFG_GROUP_KICK_VOTES_NEEDED, boot.reason.c_str());
WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length());
data << uint8(boot.inProgress); // Vote in progress
data << uint8(playerVote != LFG_ANSWER_PENDING); // Did Vote
data << uint8(playerVote == LFG_ANSWER_AGREE); // Agree
data << uint64(pBoot->victim); // Victim GUID
data << uint64(boot.victim); // Victim GUID
data << uint32(votesNum); // Total Votes
data << uint32(agreeNum); // Agree Count
data << uint32(secsleft); // Time Left
data << uint32(pBoot->votedNeeded); // Needed Votes
data << pBoot->reason.c_str(); // Kick reason
data << uint32(LFG_GROUP_KICK_VOTES_NEEDED); // Needed Votes
data << boot.reason.c_str(); // Kick reason
SendPacket(&data);
}
void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* pProp)
void WorldSession::SendLfgUpdateProposal(uint32 proposalId, LfgProposal const& proposal)
{
if (!pProp)
return;
uint64 guid = GetPlayer()->GetGUID();
LfgProposalPlayerMap::const_iterator itPlayer = pProp->players.find(guid);
if (itPlayer == pProp->players.end()) // Player MUST be in the proposal
return;
uint64 gguid = proposal.players.find(guid)->second.group;
bool silent = !proposal.isNew && gguid == proposal.group;
uint32 dungeonEntry = proposal.dungeonId;
LfgProposalPlayer* ppPlayer = itPlayer->second;
uint32 pLowGroupGuid = ppPlayer->groupLowGuid;
uint32 dLowGuid = pProp->groupLowGuid;
uint32 dungeonId = pProp->dungeonId;
bool isSameDungeon = false;
bool isContinue = false;
Group* grp = dLowGuid ? sGroupMgr->GetGroupByGUID(dLowGuid) : NULL;
uint32 completedEncounters = 0;
if (grp)
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", guid, proposal.state);
WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + proposal.players.size() * (4 + 1 + 1 + 1 + 1 +1));
// show random dungeon if player selected random dungeon and it's not lfg group
if (!silent)
{
uint64 gguid = grp->GetGUID();
isContinue = grp->isLFGGroup() && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON;
isSameDungeon = GetPlayer()->GetGroup() == grp && isContinue;
LfgDungeonSet const& playerDungeons = sLFGMgr->GetSelectedDungeons(guid);
if (playerDungeons.find(proposal.dungeonId) == playerDungeons.end())
dungeonEntry = (*playerDungeons.begin());
}
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", GetPlayer()->GetGUID(), pProp->state);
WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + pProp->players.size() * (4 + 1 + 1 + 1 + 1 +1));
if (LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(dungeonEntry))
dungeonEntry = dungeon->Entry();
if (!isContinue) // Only show proposal dungeon if it's continue
{
LfgDungeonSet playerDungeons = sLFGMgr->GetSelectedDungeons(guid);
if (playerDungeons.size() == 1)
dungeonId = (*playerDungeons.begin());
}
data << uint32(dungeonEntry); // Dungeon
data << uint8(proposal.state); // Proposal state
data << uint32(proposalId); // Proposal ID
data << uint32(proposal.encounters); // encounters done
data << uint8(silent); // Show proposal window
data << uint8(proposal.players.size()); // Group size
if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId))
for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
{
dungeonId = dungeon->Entry();
// Select a player inside to be get completed encounters from
if (grp)
{
for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* groupMember = itr->getSource();
if (groupMember && groupMember->GetMapId() == uint32(dungeon->map))
{
if (InstanceScript* instance = groupMember->GetInstanceScript())
completedEncounters = instance->GetCompletedEncounterMask();
break;
}
}
}
}
data << uint32(dungeonId); // Dungeon
data << uint8(pProp->state); // Result state
data << uint32(proposalId); // Internal Proposal ID
data << uint32(completedEncounters); // Bosses killed
data << uint8(isSameDungeon); // Silent (show client window)
data << uint8(pProp->players.size()); // Group size
for (itPlayer = pProp->players.begin(); itPlayer != pProp->players.end(); ++itPlayer)
{
ppPlayer = itPlayer->second;
data << uint32(ppPlayer->role); // Role
data << uint8(itPlayer->first == guid); // Self player
if (!ppPlayer->groupLowGuid) // Player not it a group
LfgProposalPlayer const& player = it->second;
data << uint32(player.role); // Role
data << uint8(it->first == guid); // Self player
if (!player.group) // Player not it a group
{
data << uint8(0); // Not in dungeon
data << uint8(0); // Not same group
}
else
{
data << uint8(ppPlayer->groupLowGuid == dLowGuid); // In dungeon (silent)
data << uint8(ppPlayer->groupLowGuid == pLowGroupGuid); // Same Group than player
data << uint8(player.group == proposal.group); // In dungeon (silent)
data << uint8(player.group == gguid); // Same Group than player
}
data << uint8(ppPlayer->accept != LFG_ANSWER_PENDING); // Answered
data << uint8(ppPlayer->accept == LFG_ANSWER_AGREE); // Accepted
data << uint8(player.accept != LFG_ANSWER_PENDING); // Answered
data << uint8(player.accept == LFG_ANSWER_AGREE); // Accepted
}
SendPacket(&data);
}
void WorldSession::SendLfgUpdateSearch(bool update)
void WorldSession::SendLfgLfrList(bool update)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_SEARCH [" UI64FMTD "] update: %u", GetPlayer()->GetGUID(), update ? 1 : 0);
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_LFR_LIST [" UI64FMTD "] update: %u", GetPlayer()->GetGUID(), update ? 1 : 0);
WorldPacket data(SMSG_LFG_UPDATE_SEARCH, 1);
data << uint8(update); // In Lfg Queue?
SendPacket(&data);
@@ -667,8 +617,8 @@ void WorldSession::SendLfgTeleportError(uint8 err)
/*
void WorldSession::SendLfrUpdateListOpcode(uint32 dungeonEntry)
{
sLog->outDebug(LOG_FILTER_PACKETIO, "SMSG_UPDATE_LFG_LIST [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), dungeonEntry);
WorldPacket data(SMSG_UPDATE_LFG_LIST);
sLog->outDebug(LOG_FILTER_PACKETIO, "SMSG_LFG_UPDATE_LIST [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), dungeonEntry);
WorldPacket data(SMSG_LFG_UPDATE_LIST);
SendPacket(&data);
}
*/
+42 -2
View File
@@ -16,6 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "zlib.h"
#include "Language.h"
#include "WorldPacket.h"
#include "Common.h"
@@ -26,7 +27,7 @@
#include "WorldSession.h"
#include "Util.h"
void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data)
void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData)
{
// Don't accept tickets if the ticket queue is disabled. (Ticket UI is greyed out but not fully dependable)
if (sTicketMgr->GetStatus() == GMTICKET_QUEUE_STATUS_DISABLED)
@@ -42,7 +43,46 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data)
// Player must not have ticket
if (!sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
{
GmTicket* ticket = new GmTicket(GetPlayer(), recv_data);
GmTicket* ticket = new GmTicket(GetPlayer(), recvData);
uint32 count;
std::list<uint32> times;
uint32 decompressedSize;
std::string chatLog;
recvData >> count;
for (uint32 i = 0; i < count; i++)
{
uint32 time;
recvData >> time;
times.push_back(time);
}
recvData >> decompressedSize;
if (count && decompressedSize && decompressedSize < 0xFFFF)
{
uint32 pos = recvData.rpos();
ByteBuffer dest;
dest.resize(decompressedSize);
uLongf realSize = decompressedSize;
if (uncompress(const_cast<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(recvData.contents() + pos), recvData.size() - pos) == Z_OK)
{
dest >> chatLog;
ticket->SetChatLog(times, chatLog);
}
else
{
sLog->outError(LOG_FILTER_NETWORKIO, "CMSG_GMTICKET_CREATE possibly corrupt. Uncompression failed.");
recvData.rfinish();
return;
}
recvData.rfinish(); // Will still have compressed data in buffer.
}
sTicketMgr->AddTicket(ticket);
sTicketMgr->UpdateLastChange();
+2 -2
View File
@@ -2483,8 +2483,8 @@ bool InstanceMap::AddPlayerToMap(Player* player)
if (group && group->isLFGGroup())
if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true))
if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId))
if (LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*(sLFGMgr->GetSelectedDungeons(player->GetGUID()).begin())))
if (LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId))
if (LFGDungeonData const* randomDungeon = sLFGMgr->GetLFGDungeon(*(sLFGMgr->GetSelectedDungeons(player->GetGUID()).begin())))
if (uint32(dungeon->map) == GetId() && dungeon->difficulty == uint32(GetDifficulty()) && randomDungeon->type == uint32(LFG_TYPE_RANDOM))
player->CastSpell(player, LFG_SPELL_LUCK_OF_THE_DRAW, true);
}
+16 -1
View File
@@ -990,6 +990,21 @@ enum TrinityStrings
LANG_WORLD_CLOSED = 7523,
LANG_WORLD_OPENED = 7524,
LANG_LFG_STATE_NONE = 9986,
LANG_LFG_STATE_ROLECHECK = 9987,
LANG_LFG_STATE_QUEUED = 9988,
LANG_LFG_STATE_PROPOSAL = 9989,
LANG_LFG_STATE_BOOT = 9990,
LANG_LFG_STATE_DUNGEON = 9991,
LANG_LFG_STATE_FINISHED_DUNGEON = 9992,
LANG_LFG_STATE_RAIDBROWSER = 9993,
LANG_LFG_ROLE_TANK = 9994,
LANG_LFG_ROLE_HEALER = 9995,
LANG_LFG_ROLE_DAMAGE = 9996,
LANG_LFG_ROLE_LEADER = 9997,
LANG_LFG_ROLE_NONE = 9998,
LANG_LFG_ERROR = 9999,
// Use for not-in-offcial-sources patches
// 10000-10999
// opvp hp
@@ -1076,7 +1091,7 @@ enum TrinityStrings
// Use for custom patches 11000-11999
LANG_AUTO_BROADCAST = 11000,
LANG_INVALID_REALMID = 11001
LANG_INVALID_REALMID = 11001,
// NOT RESERVED IDS 12000-1999999999
// `db_script_string` table index 2000000000-2000009999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID)
@@ -3402,7 +3402,8 @@ enum RemoveMethod
{
GROUP_REMOVEMETHOD_DEFAULT = 0,
GROUP_REMOVEMETHOD_KICK = 1,
GROUP_REMOVEMETHOD_LEAVE = 2
GROUP_REMOVEMETHOD_LEAVE = 2,
GROUP_REMOVEMETHOD_KICK_LFG = 3
};
enum ActivateTaxiReply
+1 -1
View File
@@ -888,7 +888,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x35C*/ { "CMSG_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode },
/*0x35D*/ { "CMSG_LFG_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgLeaveOpcode },
/*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrSearchOpcode },
/*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrJoinOpcode },
/*0x35F*/ { "CMSG_SEARCH_LFG_LEAVE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfrLeaveOpcode },
/*0x360*/ { "SMSG_UPDATE_LFG_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x361*/ { "SMSG_LFG_PROPOSAL_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
+7 -6
View File
@@ -54,6 +54,7 @@ struct LfgJoinResultData;
struct LfgLockStatus;
struct LfgPlayerBoot;
struct LfgProposal;
struct LfgQueueStatusData;
struct LfgReward;
struct LfgRoleCheck;
struct LfgUpdateData;
@@ -815,19 +816,19 @@ class WorldSession
void HandleLfgProposalResultOpcode(WorldPacket& recv_data);
void HandleLfgSetBootVoteOpcode(WorldPacket& recv_data);
void HandleLfgTeleportOpcode(WorldPacket& recv_data);
void HandleLfrSearchOpcode(WorldPacket& recv_data);
void HandleLfrJoinOpcode(WorldPacket& recv_data);
void HandleLfrLeaveOpcode(WorldPacket& recv_data);
void SendLfgUpdatePlayer(const LfgUpdateData& updateData);
void SendLfgUpdateParty(const LfgUpdateData& updateData);
void SendLfgRoleChosen(uint64 guid, uint8 roles);
void SendLfgRoleCheckUpdate(const LfgRoleCheck* pRoleCheck);
void SendLfgUpdateSearch(bool update);
void SendLfgRoleCheckUpdate(const LfgRoleCheck& pRoleCheck);
void SendLfgLfrList(bool update);
void SendLfgJoinResult(const LfgJoinResultData& joinData);
void SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps);
void SendLfgQueueStatus(const LfgQueueStatusData& queueData);
void SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntry, uint8 done, const LfgReward* reward, const Quest *qRew);
void SendLfgBootPlayer(const LfgPlayerBoot* pBoot);
void SendLfgUpdateProposal(uint32 proposalId, const LfgProposal *pProp);
void SendLfgBootProposalUpdate(const LfgPlayerBoot& boot);
void SendLfgUpdateProposal(uint32 proposalId, const LfgProposal& proposal);
void SendLfgDisabled();
void SendLfgOfferContinue(uint32 dungeonEntry);
void SendLfgTeleportError(uint8 err);
@@ -2863,6 +2863,7 @@ void AuraEffect::HandleAuraAllowFlight(AuraApplication const* aurApp, uint8 mode
{
target->RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY);
target->GetMotionMaster()->MoveFall();
target->m_movementInfo.SetFallTime(0);
}
Player* player = target->ToPlayer();
@@ -3254,9 +3255,8 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp,
target->SetCanFly(apply);
if (!apply)
{
target->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
target->m_movementInfo.SetFallTime(0);
target->RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY);
}
Player* player = target->ToPlayer();
+2 -2
View File
@@ -5229,7 +5229,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (m_spellInfo->Id != 1842 || (m_targets.GetGOTarget() &&
m_targets.GetGOTarget()->GetGOInfo()->type != GAMEOBJECT_TYPE_TRAP))
if (m_caster->ToPlayer()->InBattleground() && // In Battleground players can use only flags and banners
!m_caster->ToPlayer()->CanUseBattlegroundObject())
!m_caster->ToPlayer()->CanUseBattlegroundObject(m_targets.GetGOTarget()))
return SPELL_FAILED_TRY_AGAIN;
// get the lock entry
@@ -5640,7 +5640,7 @@ SpellCastResult Spell::CheckCasterAuras() const
break;
}
}
if (foundNotStun)
if (foundNotStun && m_spellInfo->Id != 22812)
prevented_reason = SPELL_FAILED_STUNNED;
}
else
+17 -27
View File
@@ -1061,11 +1061,8 @@ SpellAreaMapBounds SpellMgr::GetSpellAreaMapBounds(uint32 spell_id) const
return SpellAreaMapBounds(mSpellAreaMap.lower_bound(spell_id), mSpellAreaMap.upper_bound(spell_id));
}
SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestMapBounds(uint32 quest_id, bool active) const
SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestMapBounds(uint32 quest_id) const
{
if (active)
return SpellAreaForQuestMapBounds(mSpellAreaForActiveQuestMap.lower_bound(quest_id), mSpellAreaForActiveQuestMap.upper_bound(quest_id));
else
return SpellAreaForQuestMapBounds(mSpellAreaForQuestMap.lower_bound(quest_id), mSpellAreaForQuestMap.upper_bound(quest_id));
}
@@ -1099,11 +1096,11 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
return false;
if (questStart) // not in expected required quest state
if (!player || ((!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart)))
if (!player || (((1 << player->GetQuestStatus(questStart)) & questStartStatus) == 0))
return false;
if (questEnd) // not in expected forbidden quest state
if (!player || player->GetQuestRewardStatus(questEnd))
if (!player || (((1 << player->GetQuestStatus(questEnd)) & questEndStatus) == 0))
return false;
if (auraSpell) // not have expected aura
@@ -2433,12 +2430,11 @@ void SpellMgr::LoadSpellAreas()
mSpellAreaMap.clear(); // need for reload case
mSpellAreaForQuestMap.clear();
mSpellAreaForActiveQuestMap.clear();
mSpellAreaForQuestEndMap.clear();
mSpellAreaForAuraMap.clear();
// 0 1 2 3 4 5 6 7 8
QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_active, quest_end, aura_spell, racemask, gender, autocast FROM spell_area");
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_status, quest_end_status, quest_end, aura_spell, racemask, gender, autocast FROM spell_area");
if (!result)
{
@@ -2457,12 +2453,13 @@ void SpellMgr::LoadSpellAreas()
spellArea.spellId = spell;
spellArea.areaId = fields[1].GetUInt32();
spellArea.questStart = fields[2].GetUInt32();
spellArea.questStartCanActive = fields[3].GetBool();
spellArea.questEnd = fields[4].GetUInt32();
spellArea.auraSpell = fields[5].GetInt32();
spellArea.raceMask = fields[6].GetUInt32();
spellArea.gender = Gender(fields[7].GetUInt8());
spellArea.autocast = fields[8].GetBool();
spellArea.questStartStatus = fields[3].GetUInt32();
spellArea.questEndStatus = fields[4].GetUInt32();
spellArea.questEnd = fields[5].GetUInt32();
spellArea.auraSpell = fields[6].GetInt32();
spellArea.raceMask = fields[7].GetUInt32();
spellArea.gender = Gender(fields[8].GetUInt8());
spellArea.autocast = fields[9].GetBool();
if (SpellInfo const* spellInfo = GetSpellInfo(spell))
{
@@ -2494,7 +2491,7 @@ void SpellMgr::LoadSpellAreas()
continue;
// duplicate by requirements
ok =false;
ok = false;
break;
}
@@ -2524,12 +2521,6 @@ void SpellMgr::LoadSpellAreas()
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_area` have wrong end quest (%u) requirement", spell, spellArea.questEnd);
continue;
}
if (spellArea.questEnd == spellArea.questStart && !spellArea.questStartCanActive)
{
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_area` have quest (%u) requirement for start and end in same time", spell, spellArea.questEnd);
continue;
}
}
if (spellArea.auraSpell)
@@ -2605,12 +2596,7 @@ void SpellMgr::LoadSpellAreas()
// for search at quest start/reward
if (spellArea.questStart)
{
if (spellArea.questStartCanActive)
mSpellAreaForActiveQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
else
mSpellAreaForQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
}
// for search at quest start/reward
if (spellArea.questEnd)
@@ -3486,6 +3472,10 @@ void SpellMgr::LoadDbcDataCorrections()
case 71085: // Mana Void (periodic aura)
spellInfo->DurationIndex = 9; // 30 seconds (missing)
break;
case 72015: // Frostbolt Volley (only heroic)
case 72016: // Frostbolt Volley (only heroic)
spellInfo->EffectRadiusIndex[2] = EFFECT_RADIUS_40_YARDS;
break;
case 70936: // Summon Suppressor (needs target selection script)
spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ANY;
spellInfo->EffectImplicitTargetB[0] = 0;
+3 -3
View File
@@ -495,7 +495,8 @@ struct SpellArea
int32 auraSpell; // spell aura must be applied for spell apply)if possitive) and it must not be applied in other case
uint32 raceMask; // can be applied only to races
Gender gender; // can be applied only to gender
bool questStartCanActive; // if true then quest start can be active (not only rewarded)
uint32 questStartStatus; // QuestStatus that quest_start must have in order to keep the spell
uint32 questEndStatus; // QuestStatus that the quest_end must have in order to keep the spell (if the quest_end's status is different than this, the spell will be dropped)
bool autocast; // if true then auto applied at area enter, in other case just allowed to cast
// helpers
@@ -681,7 +682,7 @@ class SpellMgr
// Spell area
SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const;
SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id, bool active) const;
SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id) const;
SpellAreaForQuestMapBounds GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const;
SpellAreaForAuraMapBounds GetSpellAreaForAuraMapBounds(uint32 spell_id) const;
SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const;
@@ -740,7 +741,6 @@ class SpellMgr
EnchantCustomAttribute mEnchantCustomAttr;
SpellAreaMap mSpellAreaMap;
SpellAreaForQuestMap mSpellAreaForQuestMap;
SpellAreaForQuestMap mSpellAreaForActiveQuestMap;
SpellAreaForQuestMap mSpellAreaForQuestEndMap;
SpellAreaForAuraMap mSpellAreaForAuraMap;
SpellAreaForAreaMap mSpellAreaForAreaMap;
+1 -1
View File
@@ -586,7 +586,7 @@ class AuraScript : public _SpellScript
uint8 _currentScriptState;
bool _defaultActionPrevented;
ScriptStateStore(uint8 currentScriptState, AuraApplication const* auraApplication, bool defaultActionPrevented)
: _currentScriptState(currentScriptState), _auraApplication(auraApplication), _defaultActionPrevented(defaultActionPrevented)
: _auraApplication(auraApplication), _currentScriptState(currentScriptState), _defaultActionPrevented(defaultActionPrevented)
{}
};
typedef std::stack<ScriptStateStore> ScriptStateStack;
+36 -41
View File
@@ -31,45 +31,32 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; }
// GM ticket
GmTicket::GmTicket() { }
GmTicket::GmTicket(Player* player, WorldPacket& recv_data) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED)
GmTicket::GmTicket(Player* player, WorldPacket& recvData) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _haveTicket(false)
{
_id = sTicketMgr->GenerateTicketId();
_playerName = player->GetName();
_playerGuid = player->GetGUID();
uint32 mapId;
recv_data >> mapId; // Map is sent as UInt32!
recvData >> mapId; // Map is sent as UInt32!
_mapId = mapId;
recv_data >> _posX;
recv_data >> _posY;
recv_data >> _posZ;
recv_data >> _message;
recvData >> _posX;
recvData >> _posY;
recvData >> _posZ;
recvData >> _message;
uint32 needResponse;
recv_data >> needResponse;
recvData >> needResponse;
_needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default)
uint8 unk1;
recv_data >> unk1; // Requests further GM interaction on a ticket to which a GM has already responded
recv_data.rfinish();
/*
recv_data >> uint32(count); // text lines
for (int i = 0; i < count; i++)
recv_data >> uint32();
if (something)
recv_data >> uint32();
else
compressed uint32 + string;
*/
recvData >> _haveTicket; // Requests further GM interaction on a ticket to which a GM has already responded. Basically means "has a new ticket"
}
GmTicket::~GmTicket() { }
bool GmTicket::LoadFromDB(Field* fields)
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket
uint8 index = 0;
_id = fields[ index].GetUInt32();
_playerGuid = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER);
@@ -84,9 +71,11 @@ bool GmTicket::LoadFromDB(Field* fields)
_closedBy = fields[++index].GetInt32();
_assignedTo = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER);
_comment = fields[++index].GetString();
_response = fields[++index].GetString();
_completed = fields[++index].GetBool();
_escalatedStatus = GMTicketEscalationStatus(fields[++index].GetUInt8());
_viewed = fields[++index].GetBool();
_haveTicket = fields[++index].GetBool();
return true;
}
@@ -109,9 +98,11 @@ void GmTicket::SaveToDB(SQLTransaction& trans) const
stmt->setInt32 (++index, GUID_LOPART(_closedBy));
stmt->setUInt32(++index, GUID_LOPART(_assignedTo));
stmt->setString(++index, _comment);
stmt->setString(++index, _response);
stmt->setBool (++index, _completed);
stmt->setUInt8 (++index, uint8(_escalatedStatus));
stmt->setBool (++index, _viewed);
stmt->setBool (++index, _haveTicket);
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
@@ -125,6 +116,10 @@ void GmTicket::DeleteFromDB()
void GmTicket::WritePacket(WorldPacket& data) const
{
data << uint32(GMTICKET_STATUS_HASTEXT);
data << uint32(_id);
data << _message;
data << uint8(_haveTicket);
data << GetAge(_lastModifiedTime);
if (GmTicket* ticket = sTicketMgr->GetOldestOpenTicket())
data << GetAge(ticket->GetLastModifiedTime());
@@ -223,6 +218,20 @@ void GmTicket::TeleportTo(Player* player) const
player->TeleportTo(_mapId, _posX, _posY, _posZ, 0.0f, 0);
}
void GmTicket::SetChatLog(std::list<uint32> time, std::string const& log)
{
std::stringstream ss(log);
std::stringstream newss;
std::string line;
while (std::getline(ss, line))
{
newss << secsToTimeString(time.front()) << ": " << line << "\n";
time.pop_front();
}
_chatLog = newss.str();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Ticket manager
TicketMgr::TicketMgr() : _status(true), _lastTicketId(0), _lastSurveyId(0), _openTicketCount(0), _lastChange(time(NULL)) { }
@@ -365,26 +374,12 @@ void TicketMgr::ShowEscalatedList(ChatHandler& handler) const
void TicketMgr::SendTicket(WorldSession* session, GmTicket* ticket) const
{
uint32 status = GMTICKET_STATUS_DEFAULT;
std::string message;
if (ticket)
{
message = ticket->GetMessage();
status = GMTICKET_STATUS_HASTEXT;
}
WorldPacket data(SMSG_GMTICKET_GETTICKET, (4 + 4 + (ticket ? message.length() + 1 + 4 + 4 + 4 + 1 + 1 : 0)));
data << uint32(status); // standard 0x0A, 0x06 if text present
data << uint32(ticket ? ticket->GetId() : 0); // ticketID
WorldPacket data(SMSG_GMTICKET_GETTICKET, (ticket ? (4 + 4 + 1 + 4 + 4 + 4 + 1 + 1) : 4));
if (ticket)
{
data << message.c_str(); // ticket text
data << uint8(0x7); // ticket category; why is this hardcoded? does it make a diff re: client?
// we've got the easy stuff done by now.
// Now we need to go through the client logic for displaying various levels of ticket load
ticket->WritePacket(data);
}
else
data << uint32(GMTICKET_STATUS_DEFAULT);
session->SendPacket(&data);
}
+6 -1
View File
@@ -82,7 +82,7 @@ class GmTicket
{
public:
GmTicket();
explicit GmTicket(Player* player, WorldPacket& recv_data);
explicit GmTicket(Player* player, WorldPacket& recvData);
~GmTicket();
bool IsClosed() const { return _closedBy; }
@@ -142,6 +142,9 @@ public:
std::string FormatMessageString(ChatHandler& handler, bool detailed = false) const;
std::string FormatMessageString(ChatHandler& handler, const char* szClosedName, const char* szAssignedToName, const char* szUnassignedName, const char* szDeletedName) const;
void SetChatLog(std::list<uint32> time, std::string const& log);
std::string GetChatLog() const { return _chatLog; }
private:
uint32 _id;
uint64 _playerGuid;
@@ -160,7 +163,9 @@ private:
GMTicketEscalationStatus _escalatedStatus;
bool _viewed;
bool _needResponse; // TODO: find out the use of this, and then store it in DB
bool _haveTicket;
std::string _response;
std::string _chatLog; // No need to store in db, will be refreshed every session client side
};
typedef std::map<uint32, GmTicket*> GmTicketList;
+3 -1
View File
@@ -457,6 +457,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
uint8 gender = GENDER_NONE;
uint8 race = RACE_NONE;
uint8 playerClass = 0;
uint8 level = 1;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
while (!feof(fin))
@@ -531,6 +532,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
race = uint8(atol(getnth(line, 4).c_str()));
playerClass = uint8(atol(getnth(line, 5).c_str()));
gender = uint8(atol(getnth(line, 6).c_str()));
level = uint8(atol(getnth(line, 7).c_str()));
if (name == "")
{
// check if the original name already exists
@@ -674,7 +676,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
CharacterDatabase.CommitTransaction(trans);
// in case of name conflict player has to rename at login anyway
sWorld->AddCharacterNameData(guid, name, gender, race, playerClass);
sWorld->AddCharacterNameData(guid, name, gender, race, playerClass, level);
sObjectMgr->_hiItemGuid += items.size();
sObjectMgr->_mailId += mails.size();
+16 -5
View File
@@ -1469,14 +1469,15 @@ void World::SetInitialWorldSettings()
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Vehicle Accessories...");
sObjectMgr->LoadVehicleAccessories(); // must be after LoadCreatureTemplates() and LoadNPCSpellClickSpells()
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading LFG entrance positions...");
sLFGMgr->LoadLFGDungeons();
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Dungeon boss data...");
sObjectMgr->LoadInstanceEncounters();
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading LFG rewards...");
sLFGMgr->LoadRewards();
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading LFG entrance positions...");
sLFGMgr->LoadEntrancePositions();
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading SpellArea Data..."); // must be after quest load
sSpellMgr->LoadSpellAreas();
@@ -2945,7 +2946,7 @@ void World::LoadCharacterNameData()
{
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading character name data");
QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class FROM characters WHERE deleteDate IS NULL");
QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class, level FROM characters WHERE deleteDate IS NULL");
if (!result)
{
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "No character name data loaded, empty query");
@@ -2958,20 +2959,21 @@ void World::LoadCharacterNameData()
{
Field* fields = result->Fetch();
AddCharacterNameData(fields[0].GetUInt32(), fields[1].GetString(),
fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/);
fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/, fields[5].GetUInt8() /*level*/);
++count;
} while (result->NextRow());
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loaded name data for %u characters", count);
}
void World::AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass)
void World::AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level)
{
CharacterNameData& data = _characterNameDataMap[guid];
data.m_name = name;
data.m_race = race;
data.m_gender = gender;
data.m_class = playerClass;
data.m_level = level;
}
void World::UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender /*= GENDER_NONE*/, uint8 race /*= RACE_NONE*/)
@@ -2989,6 +2991,15 @@ void World::UpdateCharacterNameData(uint32 guid, std::string const& name, uint8
itr->second.m_race = race;
}
void World::UpdateCharacterNameDataLevel(uint32 guid, uint8 level)
{
std::map<uint32, CharacterNameData>::iterator itr = _characterNameDataMap.find(guid);
if (itr == _characterNameDataMap.end())
return;
itr->second.m_level = level;
}
CharacterNameData const* World::GetCharacterNameData(uint32 guid) const
{
std::map<uint32, CharacterNameData>::const_iterator itr = _characterNameDataMap.find(guid);
+3 -1
View File
@@ -538,6 +538,7 @@ struct CharacterNameData
uint8 m_class;
uint8 m_race;
uint8 m_gender;
uint8 m_level;
};
/// The World
@@ -759,8 +760,9 @@ class World
bool isEventKillStart;
CharacterNameData const* GetCharacterNameData(uint32 guid) const;
void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass);
void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level);
void UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE);
void UpdateCharacterNameDataLevel(uint32 guid, uint8 level);
void DeleteCharaceterNameData(uint32 guid) { _characterNameDataMap.erase(guid); }
uint32 GetCleaningFlags() const { return m_CleaningFlags; }
+1 -1
View File
@@ -224,7 +224,7 @@ public:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA);
stmt->setUInt32(0, delInfo.lowGuid);
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
sWorld->AddCharacterNameData(delInfo.lowGuid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8());
sWorld->AddCharacterNameData(delInfo.lowGuid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8(), (*result)[3].GetUInt8());
}
static void HandleCharacterLevel(Player* player, uint64 playerGuid, uint32 oldLevel, uint32 newLevel, ChatHandler* handler)
+16 -12
View File
@@ -1002,15 +1002,19 @@ public:
if (handler->HasLowerSecurity(target, 0))
return false;
int32 addmoney = atoi((char*)args);
int32 moneyToAdd = 0;
if (strchr(args, 'g') || strchr(args, 's') || strchr(args, 'c'))
moneyToAdd = MoneyStringToMoney(std::string(args));
else
moneyToAdd = atoi(args);
uint32 moneyuser = target->GetMoney();
uint32 targetMoney = target->GetMoney();
if (addmoney < 0)
if (moneyToAdd < 0)
{
int32 newmoney = int32(moneyuser) + addmoney;
int32 newmoney = int32(targetMoney) + moneyToAdd;
sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney);
sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_CURRENT_MONEY), targetMoney, moneyToAdd, newmoney);
if (newmoney <= 0)
{
handler->PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, handler->GetNameLink(target).c_str());
@@ -1024,25 +1028,25 @@ public:
if (newmoney > MAX_MONEY_AMOUNT)
newmoney = MAX_MONEY_AMOUNT;
handler->PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), handler->GetNameLink(target).c_str());
handler->PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(moneyToAdd), handler->GetNameLink(target).c_str());
if (handler->needReportToTarget(target))
(ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, handler->GetNameLink().c_str(), abs(addmoney));
(ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, handler->GetNameLink().c_str(), abs(moneyToAdd));
target->SetMoney(newmoney);
}
}
else
{
handler->PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, handler->GetNameLink(target).c_str());
handler->PSendSysMessage(LANG_YOU_GIVE_MONEY, moneyToAdd, handler->GetNameLink(target).c_str());
if (handler->needReportToTarget(target))
(ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, handler->GetNameLink().c_str(), addmoney);
(ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, handler->GetNameLink().c_str(), moneyToAdd);
if (addmoney >=MAX_MONEY_AMOUNT)
if (moneyToAdd >= MAX_MONEY_AMOUNT)
target->SetMoney(MAX_MONEY_AMOUNT);
else
target->ModifyMoney(addmoney);
target->ModifyMoney(moneyToAdd);
}
sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_NEW_MONEY), moneyuser, addmoney, target->GetMoney());
sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_NEW_MONEY), targetMoney, moneyToAdd, target->GetMoney());
return true;
}
@@ -30,40 +30,41 @@ Script Data End */
#define GOSSIP_START_EVENT "I am ready to being"
enum eBlastmasterEmiShortfuse
enum BlastmasterEmi
{
GOSSIP_TEXT_EMI = 1693,
SAY_BLASTMASTER_0 = -1090000,
SAY_BLASTMASTER_1 = -1090001,
SAY_BLASTMASTER_2 = -1090002,
SAY_BLASTMASTER_3 = -1090003,
SAY_BLASTMASTER_4 = -1090004,
SAY_BLASTMASTER_5 = -1090005,
SAY_BLASTMASTER_6 = -1090006,
SAY_BLASTMASTER_7 = -1090007,
SAY_BLASTMASTER_8 = -1090008,
SAY_BLASTMASTER_9 = -1090009,
SAY_BLASTMASTER_10 = -1090010,
SAY_BLASTMASTER_11 = -1090011,
SAY_BLASTMASTER_12 = -1090012,
SAY_BLASTMASTER_13 = -1090013,
SAY_BLASTMASTER_14 = -1090014,
SAY_BLASTMASTER_15 = -1090015,
SAY_BLASTMASTER_16 = -1090016,
SAY_BLASTMASTER_17 = -1090017,
SAY_BLASTMASTER_18 = -1090018,
SAY_BLASTMASTER_19 = -1090019,
SAY_BLASTMASTER_20 = -1090020,
SAY_BLASTMASTER_21 = -1090021,
SAY_BLASTMASTER_22 = -1090022,
SAY_BLASTMASTER_23 = -1090023,
SAY_BLASTMASTER_24 = -1090024,
SAY_BLASTMASTER_25 = -1090025,
SAY_BLASTMASTER_26 = -1090026,
SAY_BLASTMASTER_27 = -1090027,
SAY_BLASTMASTER_0 = 0,
SAY_BLASTMASTER_1 = 1,
SAY_BLASTMASTER_2 = 2,
SAY_BLASTMASTER_3 = 3,
SAY_BLASTMASTER_4 = 4,
SAY_BLASTMASTER_5 = 5,
SAY_BLASTMASTER_6 = 6,
SAY_BLASTMASTER_7 = 7,
SAY_BLASTMASTER_8 = 8,
SAY_BLASTMASTER_9 = 9,
SAY_BLASTMASTER_10 = 10,
SAY_BLASTMASTER_11 = 11,
SAY_BLASTMASTER_12 = 12,
SAY_BLASTMASTER_13 = 13,
SAY_BLASTMASTER_14 = 14,
SAY_BLASTMASTER_15 = 15,
SAY_BLASTMASTER_16 = 16,
SAY_BLASTMASTER_17 = 17,
SAY_BLASTMASTER_18 = 18,
SAY_BLASTMASTER_19 = 19,
SAY_BLASTMASTER_20 = 20,
SAY_BLASTMASTER_21 = 21,
SAY_BLASTMASTER_22 = 22,
SAY_BLASTMASTER_23 = 23,
SAY_BLASTMASTER_24 = 24,
SAY_BLASTMASTER_25 = 25,
SAY_BLASTMASTER_26 = 26,
SAY_BLASTMASTER_27 = 27,
SAY_BLASTMASTER_28 = 28,
SAY_GRUBBIS = -1090028
SAY_GRUBBIS = 0
};
const Position SpawnPosition[] =
@@ -78,13 +79,16 @@ const Position SpawnPosition[] =
{-552.534f, -110.012f, -153.577f, 0.747f},
{-550.708f, -116.436f, -153.103f, 0.679f},
{-554.030f, -115.983f, -152.635f, 0.695f},
{-494.595f, -87.516f, 149.116f, 3.344f},
{-494.595f, -87.516f, -149.116f, 3.344f},
{-493.349f, -90.845f, -148.882f, 3.717f},
{-491.995f, -87.619f, -148.197f, 3.230f},
{-490.732f, -90.739f, -148.091f, 3.230f},
{-490.554f, -89.114f, -148.055f, 3.230f},
{-495.240f, -90.808f, -149.493f, 3.238f},
{-494.195f, -89.553f, -149.131f, 3.254f}
{-494.195f, -89.553f, -149.131f, 3.254f},
{-511.3304f, -139.9622f, -152.4761f, 0.7504908f},
{-510.6754f, -139.4371f, -152.6167f, 3.33359f},
{-511.8976f, -139.3562f, -152.4785f, 3.961899f}
};
class npc_blastmaster_emi_shortfuse : public CreatureScript
@@ -305,7 +309,7 @@ public:
break;
case 14:
SetInFace(false);
DoScriptText(SAY_BLASTMASTER_26, me);
Talk(SAY_BLASTMASTER_26);
SetEscortPaused(true);
NextStep(5000, false, 20);
break;
@@ -318,8 +322,8 @@ public:
{
case 1:
SetEscortPaused(true);
DoScriptText(SAY_BLASTMASTER_0, me);
NextStep(1500, true);
Talk(SAY_BLASTMASTER_0);
NextStep(2000, true);
break;
case 2:
if (!instance)
@@ -368,7 +372,7 @@ public:
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
DoScriptText(SAY_BLASTMASTER_19, me);
Talk(SAY_BLASTMASTER_19);
break;
case 4:
if (GameObject* go = me->SummonGameObject(183410, -542.199f, -96.854f, -155.790f, 0, 0, 0, 0, 0, 1000))
@@ -381,7 +385,7 @@ public:
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
DoScriptText(SAY_BLASTMASTER_15, me);
Talk(SAY_BLASTMASTER_15);
break;
case 6:
me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[10], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
@@ -406,10 +410,15 @@ public:
}
break;
case 9:
if (Creature* pGrubbis = me->SummonCreature(NPC_GRUBBIS, SpawnPosition[15], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000))
DoScriptText(SAY_GRUBBIS, pGrubbis);
if (Creature* grubbis = me->SummonCreature(NPC_GRUBBIS, SpawnPosition[15], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000))
grubbis->AI()->Talk(SAY_GRUBBIS);
me->SummonCreature(NPC_CHOMPER, SpawnPosition[16], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000);
break;
case 10:
me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[17].GetPositionX(), SpawnPosition[17].GetPositionY(), SpawnPosition[17].GetPositionZ(), SpawnPosition[17].GetOrientation(), 0, 0, 0, 0, 7200);
me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[18].GetPositionX(), SpawnPosition[18].GetPositionY(), SpawnPosition[18].GetPositionZ(), SpawnPosition[18].GetOrientation(), 0, 0, 0, 0, 7200);
me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[19].GetPositionX(), SpawnPosition[19].GetPositionY(), SpawnPosition[19].GetPositionZ(), SpawnPosition[19].GetOrientation(), 0, 0, 0, 0, 7200);
break;
}
}
@@ -422,29 +431,29 @@ public:
switch (uiPhase)
{
case 1:
DoScriptText(SAY_BLASTMASTER_1, me);
NextStep(1500, true);
Talk(SAY_BLASTMASTER_1);
NextStep(2000, true);
break;
case 2:
SetEscortPaused(false);
NextStep(0, false, 0);
break;
case 3:
DoScriptText(SAY_BLASTMASTER_2, me);
Talk(SAY_BLASTMASTER_2);
SetEscortPaused(false);
NextStep(0, false, 0);
break;
case 4:
DoScriptText(SAY_BLASTMASTER_3, me);
Talk(SAY_BLASTMASTER_3);
NextStep(3000, true);
break;
case 5:
DoScriptText(SAY_BLASTMASTER_4, me);
Talk(SAY_BLASTMASTER_4);
NextStep(3000, true);
break;
case 6:
SetInFace(true);
DoScriptText(SAY_BLASTMASTER_5, me);
Talk(SAY_BLASTMASTER_5);
Summon(1);
if (instance)
if (GameObject* go = GameObject::GetGameObject(*me, instance->GetData64(DATA_GO_CAVE_IN_RIGHT)))
@@ -452,12 +461,12 @@ public:
NextStep(3000, true);
break;
case 7:
DoScriptText(SAY_BLASTMASTER_6, me);
Talk(SAY_BLASTMASTER_6);
SetEscortPaused(false);
NextStep(0, false, 0);
break;
case 8:
me->HandleEmoteCommand(EMOTE_STATE_WORK);
me->HandleEmoteCommand(EMOTE_STATE_USE_STANDING);
NextStep(25000, true);
break;
case 9:
@@ -469,28 +478,28 @@ public:
NextStep(0, false);
break;
case 11:
DoScriptText(SAY_BLASTMASTER_17, me);
Talk(SAY_BLASTMASTER_17);
NextStep(5000, true);
break;
case 12:
DoScriptText(SAY_BLASTMASTER_18, me);
Talk(SAY_BLASTMASTER_18);
NextStep(5000, true);
break;
case 13:
DoScriptText(SAY_BLASTMASTER_20, me);
Talk(SAY_BLASTMASTER_20);
CaveDestruction(true);
NextStep(8000, true);
break;
case 14:
DoScriptText(SAY_BLASTMASTER_21, me);
Talk(SAY_BLASTMASTER_21);
NextStep(8500, true);
break;
case 15:
DoScriptText(SAY_BLASTMASTER_22, me);
Talk(SAY_BLASTMASTER_22);
NextStep(2000, true);
break;
case 16:
DoScriptText(SAY_BLASTMASTER_23, me);
Talk(SAY_BLASTMASTER_23);
SetInFace(false);
if (instance)
if (GameObject* go = GameObject::GetGameObject(*me, instance->GetData64(DATA_GO_CAVE_IN_LEFT)))
@@ -499,7 +508,7 @@ public:
break;
case 17:
SetEscortPaused(false);
DoScriptText(SAY_BLASTMASTER_24, me);
Talk(SAY_BLASTMASTER_24);
Summon(6);
NextStep(0, false);
break;
@@ -510,11 +519,11 @@ public:
case 19:
SetInFace(false);
Summon(8);
DoScriptText(SAY_BLASTMASTER_25, me);
Talk(SAY_BLASTMASTER_25);
NextStep(0, false);
break;
case 20:
DoScriptText(SAY_BLASTMASTER_27, me);
Talk(SAY_BLASTMASTER_27);
NextStep(2000, true);
break;
case 21:
@@ -523,7 +532,12 @@ public:
break;
case 22:
CaveDestruction(false);
DoScriptText(SAY_BLASTMASTER_20, me);
Talk(SAY_BLASTMASTER_20);
NextStep(2000, true);
break;
case 23:
Summon(10);
Talk(SAY_BLASTMASTER_28);
NextStep(0, false);
break;
}
@@ -21,7 +21,8 @@
enum eGameObjects
{
GO_CAVE_IN_LEFT = 146085,
GO_CAVE_IN_RIGHT = 146086
GO_CAVE_IN_RIGHT = 146086,
GO_RED_ROCKET = 103820
};
enum eCreatures
@@ -168,7 +168,7 @@ public:
void Reset()
{
uiDarkOffering = urand(290, 10);
uiDarkOffering = urand(200, 1000);
}
void UpdateAI(uint32 const uiDiff)
@@ -696,7 +696,7 @@ class npc_halion_controller : public CreatureScript
halion->AI()->Talk(SAY_INTRO);
break;
case EVENT_TWILIGHT_MENDING:
if (Creature* halion = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_HALION)))
if (ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_HALION))) // Just check if physical Halion is spawned
if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_TWILIGHT_HALION)))
twilightHalion->CastSpell((Unit*)NULL, SPELL_TWILIGHT_MENDING, true);
break;
@@ -1115,7 +1115,7 @@ class npc_combustion_consumption : public CreatureScript
struct npc_combustion_consumptionAI : public Scripted_NoMovementAI
{
npc_combustion_consumptionAI(Creature* creature) : Scripted_NoMovementAI(creature),
_summonerGuid(0), _instance(creature->GetInstanceScript())
_instance(creature->GetInstanceScript()), _summonerGuid(0)
{
switch (me->GetEntry())
{
@@ -86,7 +86,7 @@ public:
uiConsumeTimer = 15*IN_MILLISECONDS;
uiAuraCountTimer = 15500;
uiCrushTimer = urand(1*IN_MILLISECONDS, 5*IN_MILLISECONDS);
uiInfectedWoundTimer = urand(60*IN_MILLISECONDS, 10*IN_MILLISECONDS);
uiInfectedWoundTimer = urand(10*IN_MILLISECONDS, 60*IN_MILLISECONDS);
uiExplodeCorpseTimer = 3*IN_MILLISECONDS;
uiSpawnTimer = urand(30*IN_MILLISECONDS, 40*IN_MILLISECONDS);
@@ -232,7 +232,7 @@ public:
{
npc_verdisa_beglaristrasz_eternosAI(Creature* creature) : ScriptedAI(creature) { }
void MovementInform(uint32 type, uint32 id)
void MovementInform(uint32 /*type*/, uint32 id)
{
// When Belgaristraz finish his moving say grateful text
if (me->GetEntry() == NPC_BELGARISTRASZ)
+2 -2
View File
@@ -1581,12 +1581,12 @@ class spell_gen_luck_of_the_draw : public SpellScriptLoader
}
LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*itr);
LFGDungeonData const* randomDungeon = sLFGMgr->GetLFGDungeon(*itr);
if (Group* group = owner->GetGroup())
if (Map const* map = owner->GetMap())
if (group->isLFGGroup())
if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true))
if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId))
if (LFGDungeonData const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId))
if (uint32(dungeon->map) == map->GetId() && dungeon->difficulty == uint32(map->GetDifficulty()))
if (randomDungeon && randomDungeon->type == LFG_TYPE_RANDOM)
return; // in correct dungeon
@@ -32,6 +32,7 @@
enum HunterSpells
{
HUNTER_SPELL_READINESS = 23989,
DRAENEI_SPELL_GIFT_OF_THE_NAARU = 59543,
HUNTER_SPELL_BESTIAL_WRATH = 19574,
HUNTER_PET_SPELL_LAST_STAND_TRIGGERED = 53479,
HUNTER_PET_HEART_OF_THE_PHOENIX = 55709,
@@ -340,6 +341,7 @@ class spell_hun_readiness : public SpellScriptLoader
spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER &&
spellInfo->Id != HUNTER_SPELL_READINESS &&
spellInfo->Id != HUNTER_SPELL_BESTIAL_WRATH &&
spellInfo->Id != DRAENEI_SPELL_GIFT_OF_THE_NAARU &&
spellInfo->GetRecoveryTime() > 0)
caster->RemoveSpellCooldown((itr++)->first, true);
else
+1 -1
View File
@@ -1844,7 +1844,7 @@ class spell_item_unusual_compass : public SpellScriptLoader
{
Unit* caster = GetCaster();
caster->SetOrientation(frand(0.0f, 62832.0f) / 10000.0f);
caster->SendMovementFlagUpdate();
caster->SendMovementFlagUpdate(true);
}
void Register()
+1 -3
View File
@@ -2115,14 +2115,12 @@ class npc_shadowfiend : public CreatureScript
{
npc_shadowfiendAI(Creature* creature) : PetAI(creature) {}
void JustDied(Unit* killer)
void JustDied(Unit* /*killer*/)
{
if (me->isSummon())
if (Unit* owner = me->ToTempSummon()->GetSummoner())
if (owner->HasAura(GLYPH_OF_SHADOWFIEND))
owner->CastSpell(owner, GLYPH_OF_SHADOWFIEND_MANA, true);
PetAI::JustDied(killer);
}
};
@@ -49,7 +49,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_SEL_CHAR_RACE, "SELECT race FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_LEVEL, "SELECT level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_ZONE, "SELECT zone FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender, level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_DEL_QUEST_STATUS_DAILY, "DELETE FROM character_queststatus_daily", CONNECTION_ASYNC);
@@ -327,8 +327,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC)
// GM Tickets
PREPARE_STATEMENT(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed FROM gm_tickets", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_REP_GM_TICKET, "REPLACE INTO gm_tickets (ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket FROM gm_tickets", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_REP_GM_TICKET, "REPLACE INTO gm_tickets (ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_GM_TICKET, "DELETE FROM gm_tickets WHERE ticketId = ?", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_PLAYER_GM_TICKETS, "DELETE FROM gm_tickets WHERE guid = ?", CONNECTION_ASYNC)
@@ -421,6 +421,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHARACTER_AT_LOGIN, "SELECT at_login FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN, "SELECT class, level, at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_AT_LOGIN_TITLES, "SELECT at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_INSTANCE, "SELECT data, completedEncounters FROM instance WHERE map = ? AND id = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_PET_SPELL_LIST, "SELECT DISTINCT pet_spell.spell FROM pet_spell, character_pet WHERE character_pet.owner = ? AND character_pet.id = pet_spell.guid AND character_pet.id <> ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_PET, "SELECT id FROM character_pet WHERE owner = ? AND id <> ?", CONNECTION_SYNCH);
@@ -497,8 +498,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE, "UPDATE item_instance ii, character_inventory ci SET ii.itemEntry = ? WHERE ii.itemEntry = ? AND ci.guid = ? AND ci.item = ii.guid", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_DEL_CHAR_SPELL_BY_SPELL, "DELETE FROM character_spell WHERE spell = ? AND guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_UPD_CHAR_SPELL_FACTION_CHANGE, "UPDATE character_spell SET spell = ? where spell = ? AND guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_SEL_CHAR_REP_BY_FACTION, "SELECT standing FROM character_reputation WHERE faction = ? AND guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_DEL_CHAR_REP_BY_FACTION, "DELETE FROM character_reputation WHERE faction = ? AND guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_UPD_CHAR_REP_FACTION_CHANGE, "UPDATE character_reputation SET faction = ? where faction = ? AND guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_UPD_CHAR_REP_FACTION_CHANGE, "UPDATE character_reputation SET faction = ?, standing = ? WHERE faction = ? AND guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_UPD_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET knownTitles = ? WHERE guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_RES_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET chosenTitle = 0 WHERE guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_DEL_CHAR_SPELL_COOLDOWN, "DELETE FROM character_spell_cooldown WHERE guid = ?", CONNECTION_ASYNC);
@@ -384,6 +384,7 @@ enum CharacterDatabaseStatements
CHAR_SEL_POOL_QUEST_SAVE,
CHAR_SEL_CHARACTER_AT_LOGIN,
CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN,
CHAR_SEL_CHAR_AT_LOGIN_TITLES,
CHAR_SEL_INSTANCE,
CHAR_SEL_PET_SPELL_LIST,
CHAR_SEL_CHAR_PET,
@@ -460,6 +461,7 @@ enum CharacterDatabaseStatements
CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE,
CHAR_DEL_CHAR_SPELL_BY_SPELL,
CHAR_UPD_CHAR_SPELL_FACTION_CHANGE,
CHAR_SEL_CHAR_REP_BY_FACTION,
CHAR_DEL_CHAR_REP_BY_FACTION,
CHAR_UPD_CHAR_REP_FACTION_CHANGE,
CHAR_UPD_CHAR_TITLES_FACTION_CHANGE,
+31
View File
@@ -150,6 +150,37 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText, bool hoursOnly)
return ss.str();
}
int32 MoneyStringToMoney(const std::string& moneyString)
{
int32 money = 0;
if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
std::count(moneyString.begin(), moneyString.end(), 'c') == 1))
return 0; // Bad format
Tokenizer tokens(moneyString, ' ');
for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
{
std::string tokenString(*itr);
uint32 gCount = std::count(tokenString.begin(), tokenString.end(), 'g');
uint32 sCount = std::count(tokenString.begin(), tokenString.end(), 's');
uint32 cCount = std::count(tokenString.begin(), tokenString.end(), 'c');
if (gCount + sCount + cCount != 1)
return 0;
uint32 amount = atoi(*itr);
if (gCount == 1)
money += amount * 100 * 100;
else if (sCount == 1)
money += amount * 100;
else if (cCount == 1)
money += amount;
}
return money;
}
uint32 TimeStringToSecs(const std::string& timestring)
{
uint32 secs = 0;
+2
View File
@@ -66,6 +66,8 @@ private:
void stripLineInvisibleChars(std::string &src);
int32 MoneyStringToMoney(const std::string& moneyString);
std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false);
uint32 TimeStringToSecs(const std::string& timestring);
std::string TimeToTimestampStr(time_t t);