aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/2012_02_21_00_world_conditions.sql3592
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.cpp420
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.h29
-rwxr-xr-xsrc/server/game/Entities/Object/Object.cpp12
-rwxr-xr-xsrc/server/game/Entities/Object/Object.h6
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp21
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Grids/GridDefines.h10
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiers.cpp13
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiers.h117
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiersImpl.h111
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp2490
-rwxr-xr-xsrc/server/game/Spells/Spell.h192
-rw-r--r--src/server/game/Spells/SpellInfo.cpp414
-rw-r--r--src/server/game/Spells/SpellInfo.h31
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp11
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.h12
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp5
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h1
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp34
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp2
-rw-r--r--src/server/scripts/Spells/spell_hunter.cpp2
23 files changed, 5713 insertions, 1815 deletions
diff --git a/sql/updates/world/2012_02_21_00_world_conditions.sql b/sql/updates/world/2012_02_21_00_world_conditions.sql
new file mode 100644
index 00000000000..54685868186
--- /dev/null
+++ b/sql/updates/world/2012_02_21_00_world_conditions.sql
@@ -0,0 +1,3592 @@
+CREATE TABLE `temp_convert_spells`
+(
+ `id` INT(11),
+ `effMask` INT(11),
+ `onlyPlayers` TINYINT(3),
+ PRIMARY KEY (`id`)
+);
+
+INSERT INTO `temp_convert_spells` VALUES
+(46174,1,0),
+(78002,1,1),
+(78001,1,1),
+(78000,1,1),
+(77999,1,1),
+(77984,1,1),
+(76379,1,0),
+(76098,1,0),
+(76092,1,0),
+(75920,1,1),
+(75767,1,1),
+(75765,1,1),
+(75396,1,0),
+(75389,1,1),
+(75364,1,0),
+(75319,1,0),
+(75313,1,0),
+(75244,1,0),
+(75197,1,0),
+(75195,1,0),
+(75181,1,0),
+(75107,1,0),
+(75100,1,0),
+(75078,1,0),
+(75053,1,0),
+(75018,1,0),
+(74977,1,0),
+(74903,1,0),
+(74801,1,1),
+(74758,1,0),
+(74735,1,0),
+(74549,1,0),
+(74548,1,0),
+(74486,1,0),
+(74455,1,0),
+(74444,1,0),
+(74313,1,0),
+(74285,1,0),
+(74219,1,0),
+(74182,1,0),
+(74148,1,0),
+(74098,1,0),
+(74090,1,1),
+(74086,1,1),
+(74074,1,0),
+(74033,1,0),
+(73980,1,0),
+(73955,1,0),
+(73953,1,0),
+(73886,1,0),
+(73846,1,1),
+(73845,1,1),
+(73844,1,1),
+(73843,1,1),
+(73837,1,0),
+(73836,1,0),
+(73835,1,0),
+(73787,1,0),
+(73786,1,0),
+(73785,1,0),
+(73725,1,0),
+(73659,1,0),
+(73650,1,1),
+(73582,1,0),
+(73556,1,0),
+(73555,1,0),
+(73548,1,0),
+(73331,1,1),
+(73288,1,0),
+(73165,1,0),
+(73164,1,1),
+(73159,1,1),
+(73129,1,0),
+(73128,1,0),
+(73082,1,0),
+(73071,1,0),
+(73035,1,0),
+(72959,1,1),
+(72934,1,1),
+(72928,1,1),
+(72900,1,1),
+(72830,1,1),
+(72748,1,0),
+(72747,1,0),
+(72746,1,0),
+(72745,1,0),
+(72728,1,0),
+(72706,1,1),
+(72618,1,0),
+(72595,1,1),
+(72527,1,0),
+(72479,1,1),
+(72431,1,1),
+(72429,1,1),
+(72401,1,0),
+(72347,1,0),
+(72346,1,1),
+(72280,1,0),
+(72279,1,0),
+(72278,1,0),
+(72262,1,0),
+(72260,1,0),
+(72257,1,1),
+(72209,1,0),
+(72202,1,0),
+(72099,1,0),
+(72033,1,0),
+(72032,1,0),
+(72031,1,0),
+(71952,1,0),
+(71949,1,1),
+(71948,1,0),
+(71946,1,0),
+(71848,1,0),
+(71811,1,0),
+(71809,1,0),
+(71753,1,1),
+(71693,1,0),
+(71620,1,0),
+(71617,1,0),
+(71599,1,0),
+(71538,1,1),
+(71536,1,1),
+(71520,1,0),
+(71440,1,0),
+(71415,1,0),
+(71412,1,0),
+(71365,1,0),
+(71352,1,1),
+(71322,1,0),
+(71310,1,0),
+(71308,1,0),
+(71306,1,0),
+(71281,1,0),
+(71272,1,0),
+(71189,1,0),
+(71082,1,0),
+(71081,1,0),
+(71080,1,0),
+(71079,1,0),
+(71078,1,0),
+(71075,1,0),
+(71070,1,0),
+(71032,1,0),
+(71024,1,0),
+(70995,1,0),
+(70983,1,0),
+(70966,1,1),
+(70939,1,0),
+(70936,1,0),
+(70933,1,0),
+(70931,1,0),
+(70921,1,0),
+(70881,1,0),
+(70861,1,0),
+(70860,1,0),
+(70859,1,0),
+(70858,1,0),
+(70857,1,0),
+(70856,1,0),
+(70792,1,0),
+(70790,1,0),
+(70784,1,0),
+(70781,1,0),
+(70743,1,0),
+(70713,1,1),
+(70643,1,0),
+(70639,1,0),
+(70638,1,1),
+(70636,1,1),
+(70635,1,0),
+(70623,1,1),
+(70614,1,0),
+(70611,1,0),
+(70602,1,0),
+(70595,1,0),
+(70588,1,0),
+(70586,1,0),
+(70572,1,0),
+(70569,1,0),
+(70527,1,1),
+(70525,1,0),
+(70488,1,0),
+(70485,1,0),
+(70471,1,0),
+(70466,1,0),
+(70464,1,0),
+(70444,1,0),
+(70443,1,1),
+(70403,1,0),
+(70397,1,0),
+(70383,1,0),
+(70374,1,0),
+(70366,1,0),
+(70360,1,0),
+(70338,1,0),
+(70331,1,1),
+(70299,1,0),
+(70293,1,0),
+(70290,1,0),
+(70267,1,0),
+(70266,1,0),
+(70265,1,0),
+(70246,1,0),
+(70225,1,0),
+(70224,1,0),
+(70143,1,0),
+(70130,1,0),
+(70104,1,0),
+(70100,1,0),
+(70098,1,0),
+(70079,1,0),
+(70078,1,0),
+(70053,1,0),
+(70041,1,0),
+(70040,1,0),
+(70021,1,0),
+(69960,1,0),
+(69959,1,0),
+(69922,1,0),
+(69907,1,0),
+(69886,1,0),
+(69857,1,0),
+(69843,1,0),
+(69801,1,0),
+(69798,1,0),
+(69796,1,0),
+(69784,1,0),
+(69782,1,0),
+(69768,1,0),
+(69753,1,0),
+(69705,1,0),
+(69682,1,0),
+(69614,1,0),
+(69610,1,0),
+(69601,1,0),
+(69600,1,0),
+(69593,1,0),
+(69553,1,0),
+(69538,1,0),
+(69508,1,0),
+(69431,1,0),
+(69372,1,0),
+(69347,1,0),
+(69298,1,1),
+(69171,1,0),
+(69125,1,0),
+(69101,1,0),
+(69098,1,0),
+(69097,1,0),
+(69048,1,1),
+(69039,1,0),
+(69016,1,0),
+(68957,1,0),
+(68922,1,0),
+(68919,1,0),
+(68901,1,0),
+(68881,1,0),
+(68880,1,0),
+(68861,1,0),
+(68847,1,0),
+(68842,1,0),
+(68798,1,0),
+(68663,1,0),
+(68644,1,0),
+(68617,1,0),
+(68616,1,0),
+(68614,1,0),
+(68515,1,1),
+(68471,1,1),
+(68470,1,1),
+(68401,1,0),
+(68400,1,0),
+(68360,1,0),
+(68359,1,0),
+(68358,1,0),
+(68206,1,1),
+(68198,1,1),
+(68197,1,1),
+(68193,1,1),
+(68186,1,1),
+(67888,1,0),
+(67864,1,0),
+(67857,1,0),
+(67856,1,0),
+(67855,1,0),
+(67804,1,0),
+(67757,1,0),
+(67756,1,0),
+(67755,1,0),
+(67748,1,0),
+(67732,1,0),
+(67715,1,0),
+(67705,1,0),
+(67551,1,1),
+(67547,1,0),
+(67482,1,0),
+(67400,1,0),
+(67397,1,0),
+(67369,1,0),
+(67335,1,0),
+(67328,1,0),
+(67163,1,0),
+(67162,1,0),
+(67161,1,0),
+(67160,1,0),
+(67159,1,0),
+(67158,1,0),
+(66986,1,1),
+(66810,1,1),
+(66798,1,0),
+(66785,1,0),
+(66774,1,0),
+(66718,1,1),
+(66665,1,0),
+(66637,1,0),
+(66636,1,0),
+(66630,1,0),
+(66551,1,0),
+(66550,1,0),
+(66513,1,0),
+(66512,1,0),
+(66508,1,0),
+(66401,1,0),
+(66391,1,0),
+(66390,1,0),
+(66387,1,0),
+(66386,1,0),
+(66385,1,0),
+(66384,1,0),
+(66383,1,0),
+(66382,1,0),
+(66379,1,0),
+(66357,1,0),
+(66356,1,0),
+(66355,1,0),
+(66354,1,0),
+(66353,1,0),
+(66352,1,0),
+(66350,1,0),
+(66349,1,0),
+(66348,1,0),
+(66345,1,0),
+(66339,1,0),
+(66332,1,0),
+(66314,1,1),
+(66312,1,1),
+(66287,1,0),
+(66256,1,0),
+(66193,1,0),
+(66181,1,0),
+(66153,1,0),
+(66152,1,0),
+(66141,1,0),
+(66140,1,0),
+(66135,1,1),
+(66133,1,0),
+(66132,1,0),
+(65872,1,0),
+(65861,1,0),
+(65719,1,0),
+(65718,1,0),
+(65699,1,0),
+(65685,1,0),
+(65652,1,0),
+(65614,1,0),
+(65613,1,0),
+(65611,1,0),
+(65594,1,1),
+(65589,1,0),
+(65588,1,0),
+(65587,1,0),
+(65509,1,0),
+(65357,1,0),
+(65354,1,0),
+(65350,1,0),
+(65349,1,0),
+(65346,1,1),
+(65312,1,1),
+(65311,1,1),
+(65265,1,0),
+(65258,1,0),
+(65238,1,0),
+(65224,1,0),
+(65206,1,0),
+(65200,1,0),
+(65192,1,0),
+(65184,1,1),
+(65140,1,0),
+(65109,1,0),
+(65061,1,0),
+(65042,1,0),
+(65040,1,1),
+(65034,1,0),
+(65016,1,0),
+(65015,1,0),
+(64996,1,0),
+(64995,1,0),
+(64898,1,0),
+(64887,1,0),
+(64886,1,0),
+(64880,1,0),
+(64828,1,0),
+(64799,1,0),
+(64767,1,0),
+(64623,1,0),
+(64620,1,0),
+(64619,1,0),
+(64618,1,0),
+(64597,1,0),
+(64543,1,0),
+(64539,1,0),
+(64503,1,0),
+(64499,1,0),
+(64480,1,0),
+(64475,1,0),
+(64474,1,0),
+(64466,1,0),
+(64465,1,0),
+(64463,1,0),
+(64449,1,0),
+(64444,1,0),
+(64425,1,0),
+(64414,1,0),
+(64402,1,0),
+(64397,1,0),
+(64320,1,0),
+(64229,1,0),
+(64225,1,0),
+(64224,1,0),
+(64201,1,0),
+(64185,1,0),
+(64184,1,0),
+(64183,1,0),
+(64173,1,0),
+(64172,1,0),
+(64098,1,0),
+(64069,1,0),
+(64063,1,0),
+(64061,1,0),
+(64059,1,1),
+(64032,1,0),
+(64031,1,0),
+(64030,1,0),
+(64029,1,0),
+(64028,1,0),
+(64027,1,0),
+(64026,1,0),
+(64025,1,0),
+(64024,1,0),
+(64014,1,0),
+(63984,1,0),
+(63979,1,0),
+(63947,1,0),
+(63886,1,0),
+(63882,1,0),
+(63820,1,0),
+(63813,1,0),
+(63812,1,0),
+(63764,1,0),
+(63763,1,0),
+(63762,1,0),
+(63761,1,0),
+(63749,1,0),
+(63747,1,1),
+(63745,1,1),
+(63744,1,0),
+(63702,1,0),
+(63676,1,0),
+(63659,1,0),
+(63658,1,0),
+(63657,1,0),
+(63629,1,0),
+(63628,1,0),
+(63576,1,0),
+(63524,1,0),
+(63499,1,0),
+(63446,1,0),
+(63445,1,0),
+(63444,1,0),
+(63443,1,0),
+(63442,1,0),
+(63441,1,0),
+(63440,1,0),
+(63439,1,0),
+(63438,1,0),
+(63352,1,0),
+(63348,1,0),
+(63322,1,1),
+(63274,1,0),
+(63255,1,0),
+(63238,1,0),
+(63109,1,0),
+(63037,1,0),
+(63013,1,0),
+(63001,1,0),
+(62990,1,0),
+(62978,1,0),
+(62976,1,0),
+(62943,1,0),
+(62911,1,0),
+(62909,1,0),
+(62906,1,0),
+(62888,1,0),
+(62883,1,0),
+(62882,1,0),
+(62834,1,0),
+(62809,1,0),
+(62797,1,1),
+(62778,1,0),
+(62731,1,0),
+(62727,1,0),
+(62711,1,0),
+(62708,1,0),
+(62706,1,0),
+(62701,1,0),
+(62669,1,0),
+(62646,1,0),
+(62603,1,0),
+(62584,1,0),
+(62577,1,0),
+(62567,1,0),
+(62533,1,0),
+(62525,1,0),
+(62524,1,0),
+(62521,1,0),
+(62509,1,0),
+(62505,1,0),
+(62496,1,0),
+(62488,1,0),
+(62485,1,0),
+(62484,1,0),
+(62483,1,0),
+(62480,1,0),
+(62464,1,0),
+(62378,1,0),
+(124,1,0),
+(2222,1,0),
+(3730,1,0),
+(4020,1,0),
+(4338,1,0),
+(5249,1,0),
+(5251,1,0),
+(5432,1,0),
+(5555,1,0),
+(6636,1,0),
+(6672,1,0),
+(6755,1,0),
+(6955,1,0),
+(6967,1,0),
+(7022,1,0),
+(7035,1,0),
+(7036,1,0),
+(7277,1,0),
+(7393,1,0),
+(7670,1,0),
+(7769,1,0),
+(8283,1,0),
+(8593,1,0),
+(8596,1,0),
+(9002,1,0),
+(9003,1,0),
+(9004,1,0),
+(9012,1,0),
+(9082,1,0),
+(9095,1,0),
+(9455,1,0),
+(9457,1,0),
+(9712,1,0),
+(9976,1,0),
+(10113,1,0),
+(10137,1,0),
+(10252,1,0),
+(10258,1,0),
+(10259,1,0),
+(10260,1,0),
+(10345,1,0),
+(10604,1,0),
+(10727,1,0),
+(10747,1,0),
+(11195,1,0),
+(11402,1,0),
+(11440,1,0),
+(11513,1,0),
+(11637,1,0),
+(11757,1,0),
+(11893,1,0),
+(12134,1,0),
+(12158,1,0),
+(12159,1,0),
+(12347,1,0),
+(12512,1,0),
+(12564,1,0),
+(12613,1,0),
+(12623,1,0),
+(12699,1,0),
+(12709,1,0),
+(12774,1,0),
+(12938,1,0),
+(13461,1,0),
+(13727,1,0),
+(13821,1,0),
+(13951,1,0),
+(13982,1,0),
+(14250,1,0),
+(14292,1,0),
+(14806,1,0),
+(14813,1,0),
+(14928,1,0),
+(15252,1,0),
+(15281,1,0),
+(15591,1,0),
+(15658,1,0),
+(15746,1,0),
+(15958,1,0),
+(16007,1,0),
+(16032,1,0),
+(16037,1,0),
+(16053,1,0),
+(16068,1,0),
+(16069,1,0),
+(16070,1,0),
+(16074,1,0),
+(16378,1,0),
+(16381,1,0),
+(16404,1,0),
+(16556,1,0),
+(16558,1,0),
+(16637,1,0),
+(16786,1,0),
+(16807,1,0),
+(17048,1,0),
+(17166,1,0),
+(17190,1,0),
+(17202,1,0),
+(17272,1,0),
+(17278,1,0),
+(17279,1,0),
+(17471,1,0),
+(17536,1,0),
+(17616,1,0),
+(17618,1,0),
+(17652,1,0),
+(17671,1,0),
+(17675,1,0),
+(17676,1,0),
+(17677,1,0),
+(17678,1,0),
+(17698,1,0),
+(17748,1,0),
+(18110,1,0),
+(18655,1,0),
+(18666,1,0),
+(18811,1,0),
+(18969,1,0),
+(19032,1,0),
+(19096,1,0),
+(19571,1,0),
+(19593,1,0),
+(19721,1,0),
+(19749,1,0),
+(19770,1,0),
+(19773,1,0),
+(19952,1,0),
+(20358,1,0),
+(20465,1,0),
+(20619,1,0),
+(21052,1,0),
+(21075,1,0),
+(21076,1,0),
+(21391,1,0),
+(21556,1,0),
+(21566,1,0),
+(21885,1,0),
+(21950,1,0),
+(22096,1,0),
+(22203,1,0),
+(22205,1,0),
+(22393,1,0),
+(22458,1,0),
+(22860,1,0),
+(22906,1,0),
+(22966,1,0),
+(23014,1,0),
+(23016,1,0),
+(23018,1,0),
+(23019,1,0),
+(23168,1,0),
+(23328,1,0),
+(23360,1,0),
+(23389,1,0),
+(23394,1,0),
+(23415,1,0),
+(23642,1,0),
+(23951,1,0),
+(23974,1,0),
+(24062,1,0),
+(24083,1,0),
+(24172,1,0),
+(24207,1,0),
+(24217,1,0),
+(24311,1,0),
+(24322,1,0),
+(24323,1,0),
+(24391,1,0),
+(24734,1,0),
+(24744,1,0),
+(24756,1,0),
+(24758,1,0),
+(24760,1,0),
+(24763,1,0),
+(24765,1,0),
+(24768,1,0),
+(24770,1,0),
+(24772,1,0),
+(24784,1,0),
+(24786,1,0),
+(24788,1,0),
+(24789,1,0),
+(24790,1,0),
+(24804,1,0),
+(24933,1,0),
+(25030,1,0),
+(25031,1,0),
+(25032,1,0),
+(25099,1,0),
+(25145,1,0),
+(25149,1,0),
+(25150,1,0),
+(25158,1,0),
+(25201,1,0),
+(25715,1,0),
+(25727,1,0),
+(25745,1,0),
+(25822,1,0),
+(25823,1,0),
+(25896,1,0),
+(26235,1,0),
+(26344,1,0),
+(26345,1,0),
+(26346,1,0),
+(26347,1,0),
+(26348,1,0),
+(26349,1,0),
+(26351,1,0),
+(26352,1,0),
+(26353,1,0),
+(26354,1,0),
+(26355,1,0),
+(26356,1,0),
+(26462,1,0),
+(26522,1,1),
+(26608,1,0),
+(26687,1,1),
+(26879,1,0),
+(27583,1,0),
+(27651,1,0),
+(27663,1,0),
+(27745,1,0),
+(27885,1,0),
+(27886,1,0),
+(27892,1,0),
+(27893,1,0),
+(27894,1,0),
+(27928,1,0),
+(27929,1,0),
+(27935,1,0),
+(27936,1,0),
+(28018,1,0),
+(28032,1,0),
+(28056,1,0),
+(28078,1,0),
+(28087,1,0),
+(28096,1,0),
+(28111,1,0),
+(28159,1,0),
+(28278,1,0),
+(28281,1,0),
+(28309,1,0),
+(28326,1,0),
+(28338,1,0),
+(28339,1,0),
+(28365,1,0),
+(28366,1,0),
+(28367,1,0),
+(28374,1,0),
+(28392,1,0),
+(28404,1,0),
+(28441,1,0),
+(28605,1,0),
+(28697,1,0),
+(28731,1,0),
+(28732,1,0),
+(28861,1,0),
+(29070,1,0),
+(29072,1,0),
+(29120,1,0),
+(29121,1,0),
+(29122,1,0),
+(29172,1,0),
+(29173,1,0),
+(29176,1,0),
+(29328,1,1),
+(29339,1,0),
+(29340,1,0),
+(29428,1,0),
+(29437,1,0),
+(29456,1,0),
+(29457,1,0),
+(29458,1,0),
+(29459,1,0),
+(29461,1,0),
+(29531,1,0),
+(29534,1,0),
+(29612,1,0),
+(29705,1,0),
+(29726,1,0),
+(29727,1,0),
+(29769,1,0),
+(29770,1,0),
+(29846,1,1),
+(29962,1,0),
+(29966,1,0),
+(29967,1,0),
+(29969,1,0),
+(29970,1,0),
+(29972,1,0),
+(29989,1,0),
+(30012,1,0),
+(30065,1,0),
+(30107,1,0),
+(30166,1,0),
+(30207,1,0),
+(30221,1,0),
+(30232,1,0),
+(30273,1,0),
+(30410,1,0),
+(30417,1,0),
+(30418,1,0),
+(30425,1,0),
+(30427,1,0),
+(30460,1,0),
+(30462,1,0),
+(30469,1,0),
+(30477,1,0),
+(30541,1,0),
+(30544,1,0),
+(30571,1,1),
+(30572,1,0),
+(30625,1,0),
+(30631,1,1),
+(30656,1,0),
+(30662,1,0),
+(30676,1,0),
+(30690,1,0),
+(30735,1,0),
+(30738,1,0),
+(30745,1,0),
+(30751,1,0),
+(30762,1,0),
+(30763,1,0),
+(30764,1,0),
+(30765,1,0),
+(30766,1,0),
+(30834,1,0),
+(30835,1,0),
+(30875,1,0),
+(30876,1,0),
+(30951,1,0),
+(30952,1,0),
+(30964,1,0),
+(30968,1,0),
+(30970,1,0),
+(30974,1,0),
+(30985,1,0),
+(30988,1,0),
+(31115,1,0),
+(31225,1,0),
+(31315,1,0),
+(31324,1,0),
+(31326,1,0),
+(31329,1,0),
+(31336,1,0),
+(31346,1,0),
+(31411,1,0),
+(31412,1,0),
+(31413,1,0),
+(31414,1,0),
+(31474,1,0),
+(31515,1,0),
+(31532,1,0),
+(31537,1,0),
+(31550,1,0),
+(31611,1,0),
+(31628,1,0),
+(31630,1,0),
+(31631,1,0),
+(31702,1,0),
+(31727,1,0),
+(31736,1,0),
+(31749,1,0),
+(31781,1,0),
+(31793,1,0),
+(31799,1,0),
+(31806,1,0),
+(31889,1,0),
+(31902,1,0),
+(31936,1,0),
+(31979,1,0),
+(31993,1,0),
+(32040,1,0),
+(32042,1,0),
+(32045,1,0),
+(32051,1,0),
+(32052,1,0),
+(32087,1,0),
+(32111,1,0),
+(32127,1,0),
+(32146,1,0),
+(32163,1,0),
+(32164,1,0),
+(32227,1,0),
+(32228,1,0),
+(32251,1,0),
+(32260,1,0),
+(32286,1,0),
+(32301,1,0),
+(32303,1,0),
+(32312,1,0),
+(32373,1,0),
+(32396,1,0),
+(32560,1,0),
+(32573,1,0),
+(32589,1,0),
+(32622,1,0),
+(32623,1,0),
+(32638,1,0),
+(32668,1,0),
+(32708,1,1),
+(32760,1,0),
+(32838,1,0),
+(32890,1,0),
+(32928,1,0),
+(32929,1,0),
+(32930,1,0),
+(32953,1,0),
+(32958,1,0),
+(32974,1,0),
+(32976,1,0),
+(32979,1,0),
+(33067,1,0),
+(33270,1,1),
+(33329,1,0),
+(33332,1,0),
+(33336,1,0),
+(33337,1,0),
+(33423,1,0),
+(33424,1,0),
+(33425,1,0),
+(33531,1,0),
+(33532,1,0),
+(33618,1,0),
+(33644,1,0),
+(33655,1,0),
+(33669,1,0),
+(33710,1,0),
+(33716,1,1),
+(33742,1,0),
+(33744,1,0),
+(33796,1,0),
+(33805,1,0),
+(33806,1,0),
+(33809,1,0),
+(33822,1,0),
+(33831,1,0),
+(33838,1,0),
+(33861,1,0),
+(33862,1,0),
+(33918,1,0),
+(33924,1,0),
+(33937,1,0),
+(33981,1,0),
+(34011,1,0),
+(34013,1,0),
+(34016,1,0),
+(34019,1,0),
+(34023,1,0),
+(34024,1,0),
+(34062,1,0),
+(34063,1,0),
+(34076,1,0),
+(34119,1,0),
+(34154,1,0),
+(34156,1,0),
+(34209,1,0),
+(34211,1,0),
+(34212,1,0),
+(34221,1,0),
+(34239,1,0),
+(34254,1,0),
+(34330,1,0),
+(34332,1,0),
+(34367,1,0),
+(34378,1,0),
+(34393,1,0),
+(34397,1,0),
+(34430,1,0),
+(34516,1,0),
+(34526,1,0),
+(34536,1,0),
+(34581,1,0),
+(34583,1,0),
+(34613,1,0),
+(34627,1,0),
+(34646,1,0),
+(34662,1,0),
+(34742,1,0),
+(34806,1,0),
+(34874,1,0),
+(34893,1,0),
+(34946,1,0),
+(35016,1,0),
+(35040,1,0),
+(35063,1,0),
+(35097,1,0),
+(35113,1,0),
+(35137,1,0),
+(35140,1,0),
+(35141,1,0),
+(35155,1,0),
+(35160,1,0),
+(35162,1,0),
+(35170,1,0),
+(35176,1,0),
+(35190,1,0),
+(35245,1,0),
+(35262,1,0),
+(35282,1,0),
+(35301,1,0),
+(35372,1,0),
+(35413,1,0),
+(35427,1,0),
+(35515,1,0),
+(35516,1,0),
+(35598,1,0),
+(35600,1,0),
+(35673,1,0),
+(35682,1,0),
+(35724,1,0),
+(35746,1,0),
+(35756,1,0),
+(35770,1,0),
+(35771,1,0),
+(35772,1,0),
+(35782,1,0),
+(35930,1,0),
+(35941,1,1),
+(35956,1,1),
+(35960,1,0),
+(35961,1,0),
+(35962,1,0),
+(36000,1,0),
+(36035,1,0),
+(36089,1,0),
+(36090,1,0),
+(36103,1,0),
+(36167,1,0),
+(36174,1,0),
+(36196,1,0),
+(36197,1,0),
+(36198,1,0),
+(36201,1,0),
+(36220,1,0),
+(36239,1,0),
+(36241,1,0),
+(36243,1,0),
+(36290,1,0),
+(36291,1,0),
+(36293,1,0),
+(36327,1,0),
+(36330,1,0),
+(36378,1,0),
+(36384,1,0),
+(36431,1,0),
+(36452,1,0),
+(36455,1,1),
+(36456,1,0),
+(36514,1,0),
+(36544,1,0),
+(36639,1,0),
+(36651,1,0),
+(36652,1,0),
+(36692,1,0),
+(36709,1,0),
+(36717,1,1),
+(36779,1,0),
+(36795,1,0),
+(36802,1,0),
+(36803,1,0),
+(36804,1,0),
+(36823,1,0),
+(36852,1,0),
+(36854,1,0),
+(36856,1,0),
+(36857,1,0),
+(36858,1,0),
+(36859,1,0),
+(36871,1,0),
+(36878,1,0),
+(36884,1,0),
+(36896,1,0),
+(36951,1,0),
+(36953,1,0),
+(36969,1,0),
+(36995,1,0),
+(37013,1,0),
+(37017,1,0),
+(37032,1,0),
+(37033,1,0),
+(37034,1,0),
+(37035,1,0),
+(37051,1,0),
+(37052,1,0),
+(37053,1,0),
+(37055,1,0),
+(37056,1,0),
+(37071,1,0),
+(37072,1,0),
+(37103,1,0),
+(37142,1,0),
+(37143,1,0),
+(37144,1,0),
+(37146,1,0),
+(37147,1,0),
+(37148,1,0),
+(37149,1,0),
+(37150,1,0),
+(37151,1,0),
+(37152,1,0),
+(37153,1,0),
+(37199,1,0),
+(37220,1,0),
+(37226,1,0),
+(37229,1,0),
+(37235,1,0),
+(37281,1,0),
+(37285,1,0),
+(37337,1,0),
+(37339,1,0),
+(37345,1,0),
+(37348,1,0),
+(37388,1,0),
+(37406,1,0),
+(37408,1,1),
+(37413,1,0),
+(37422,1,0),
+(37427,1,0),
+(37428,1,0),
+(37448,1,1),
+(37449,1,1),
+(37453,1,0),
+(37454,1,0),
+(37459,1,0),
+(37461,1,0),
+(37465,1,0),
+(37469,1,0),
+(37471,1,0),
+(37472,1,0),
+(37474,1,0),
+(37476,1,0),
+(37498,1,0),
+(37502,1,0),
+(37573,1,0),
+(37626,1,0),
+(37645,1,0),
+(37689,1,0),
+(37697,1,0),
+(37712,1,0),
+(37720,1,0),
+(37748,1,0),
+(37755,1,0),
+(37775,1,0),
+(37784,1,0),
+(37824,1,0),
+(37842,1,0),
+(37843,1,0),
+(37848,1,0),
+(37849,1,1),
+(37853,1,0),
+(37868,1,0),
+(37893,1,0),
+(37895,1,0),
+(37918,1,0),
+(37934,1,0),
+(37936,1,0),
+(37964,1,0),
+(37984,1,0),
+(38003,1,0),
+(38014,1,0),
+(38015,1,0),
+(38017,1,0),
+(38020,1,0),
+(38053,1,0),
+(38054,1,0),
+(38072,1,0),
+(38073,1,0),
+(38112,1,0),
+(38121,1,0),
+(38123,1,0),
+(38126,1,0),
+(38128,1,0),
+(38130,1,0),
+(38202,1,0),
+(38250,1,0),
+(38269,1,0),
+(38360,1,0),
+(38444,1,0),
+(38451,1,0),
+(38452,1,0),
+(38455,1,0),
+(38469,1,0),
+(38482,1,0),
+(38508,1,0),
+(38530,1,0),
+(38629,1,0),
+(38632,1,0),
+(38691,1,0),
+(38711,1,0),
+(38722,1,0),
+(38736,1,0),
+(38738,1,0),
+(38762,1,0),
+(38802,1,0),
+(38829,1,1),
+(38966,1,0),
+(38968,1,0),
+(39010,1,0),
+(39011,1,0),
+(39043,1,0),
+(39073,1,0),
+(39094,1,0),
+(39124,1,0),
+(39126,1,0),
+(39140,1,0),
+(39141,1,0),
+(39184,1,0),
+(39185,1,0),
+(39189,1,0),
+(39190,1,0),
+(39206,1,0),
+(39211,1,0),
+(39216,1,0),
+(39219,1,0),
+(39221,1,0),
+(39248,1,0),
+(39334,1,0),
+(39335,1,0),
+(39338,1,0),
+(39341,1,0),
+(39342,1,0),
+(39344,1,0),
+(39350,1,0),
+(39352,1,0),
+(39353,1,0),
+(39354,1,0),
+(39355,1,0),
+(39356,1,0),
+(39357,1,0),
+(39358,1,0),
+(39359,1,0),
+(39360,1,0),
+(39361,1,0),
+(39362,1,0),
+(39395,1,0),
+(39495,1,0),
+(39497,1,1),
+(39552,1,0),
+(39559,1,0),
+(39583,1,0),
+(39601,1,0),
+(39635,1,0),
+(39678,1,0),
+(39687,1,0),
+(39690,1,0),
+(39691,1,0),
+(39692,1,0),
+(39696,1,0),
+(39758,1,0),
+(39834,1,1),
+(39849,1,0),
+(39851,1,1),
+(39852,1,1),
+(39853,1,1),
+(39854,1,1),
+(39873,1,0),
+(39899,1,0),
+(39914,1,0),
+(39915,1,0),
+(39919,1,0),
+(39921,1,0),
+(39923,1,1),
+(39930,1,0),
+(39938,1,0),
+(39939,1,0),
+(39940,1,0),
+(39974,1,0),
+(39977,1,0),
+(39978,1,0),
+(39985,1,0),
+(39989,1,0),
+(39993,1,0),
+(39999,1,0),
+(40085,1,0),
+(40094,1,0),
+(40106,1,0),
+(40110,1,0),
+(40112,1,1),
+(40136,1,0),
+(40147,1,0),
+(40153,1,0),
+(40156,1,0),
+(40160,1,0),
+(40187,1,0),
+(40189,1,0),
+(40190,1,0),
+(40224,1,0),
+(40281,1,0),
+(40287,1,0),
+(40288,1,0),
+(40289,1,0),
+(40309,1,0),
+(40350,1,0),
+(40359,1,0),
+(40382,1,0),
+(40383,1,0),
+(40397,1,0),
+(40437,1,0),
+(40439,1,0),
+(40454,1,0),
+(40490,1,0),
+(40494,1,0),
+(40498,1,0),
+(40499,1,0),
+(40512,1,0),
+(40520,1,0),
+(40521,1,0),
+(40523,1,0),
+(40532,1,0),
+(40547,1,0),
+(40607,1,0),
+(40638,1,0),
+(40693,1,0),
+(40704,1,0),
+(40707,1,0),
+(40708,1,0),
+(40709,1,0),
+(40710,1,0),
+(40711,1,0),
+(40712,1,0),
+(40713,1,0),
+(40715,1,0),
+(40730,1,1),
+(40738,1,0),
+(40750,1,0),
+(40761,1,0),
+(40788,1,0),
+(40821,1,0),
+(40824,1,0),
+(40825,1,0),
+(40828,1,0),
+(40830,1,0),
+(40848,1,1),
+(40874,1,0),
+(40887,1,0),
+(40978,1,0),
+(40985,1,1),
+(40989,1,0),
+(40993,1,1),
+(41007,1,1),
+(41015,1,1),
+(41022,1,1),
+(41073,1,0),
+(41077,1,0),
+(41122,1,0),
+(41124,1,0),
+(41125,1,0),
+(41128,1,0),
+(41129,1,0),
+(41154,1,0),
+(41257,1,0),
+(41268,1,0),
+(41269,1,0),
+(41271,1,0),
+(41285,1,1),
+(41295,1,0),
+(41333,1,0),
+(41342,1,0),
+(41343,1,0),
+(41344,1,0),
+(41362,1,0),
+(41455,1,0),
+(41457,1,0),
+(41477,1,0),
+(41499,1,0),
+(41522,1,0),
+(41525,1,0),
+(41537,1,0),
+(41557,1,0),
+(41560,1,0),
+(41575,1,0),
+(41602,1,0),
+(41614,1,0),
+(41624,1,1),
+(41975,1,0),
+(41976,1,0),
+(41993,1,0),
+(42008,1,0),
+(42014,1,0),
+(42138,1,1),
+(42143,1,0),
+(42151,1,0),
+(42166,1,0),
+(42167,1,0),
+(42168,1,0),
+(42178,1,0),
+(42219,1,0),
+(42222,1,0),
+(42247,1,0),
+(42269,1,0),
+(42271,1,0),
+(42272,1,0),
+(42289,1,0),
+(42317,1,0),
+(42318,1,0),
+(42321,1,0),
+(42339,1,0),
+(42341,1,0),
+(42352,1,0),
+(42356,1,0),
+(42391,1,0),
+(42393,1,0),
+(42405,1,0),
+(42410,1,0),
+(42415,1,0),
+(42428,1,0),
+(42442,1,0),
+(42447,1,0),
+(42454,1,0),
+(42471,1,0),
+(42473,1,0),
+(42482,1,0),
+(42484,1,0),
+(42515,1,0),
+(42517,1,0),
+(42530,1,0),
+(42534,1,0),
+(42536,1,0),
+(42542,1,0),
+(42550,1,0),
+(42564,1,0),
+(42567,1,0),
+(42570,1,0),
+(42577,1,0),
+(42585,1,0),
+(42604,1,0),
+(42605,1,0),
+(42616,1,0),
+(42631,1,0),
+(42638,1,1),
+(42647,1,0),
+(42654,1,0),
+(42655,1,0),
+(42659,1,0),
+(42661,1,0),
+(42664,1,0),
+(42674,1,1),
+(42685,1,0),
+(42695,1,0),
+(42697,1,0),
+(42703,1,0),
+(42707,1,0),
+(42713,1,0),
+(42720,1,0),
+(42734,1,0),
+(42757,1,1),
+(42768,1,0),
+(42793,1,0),
+(42797,1,0),
+(42808,1,0),
+(42809,1,0),
+(42813,1,0),
+(42815,1,0),
+(42816,1,0),
+(42818,1,0),
+(42821,1,0),
+(42839,1,0),
+(42857,1,0),
+(42881,1,0),
+(42882,1,0),
+(42883,1,0),
+(42884,1,0),
+(42888,1,0),
+(42905,1,0),
+(42968,1,0),
+(42982,1,0),
+(43033,1,0),
+(43035,1,0),
+(43057,1,0),
+(43066,1,0),
+(43068,1,0),
+(43069,1,0),
+(43072,1,0),
+(43076,1,0),
+(43078,1,0),
+(43079,1,0),
+(43092,1,0),
+(43101,1,0),
+(43106,1,0),
+(43109,1,0),
+(43144,1,0),
+(43171,1,0),
+(43209,1,0),
+(43210,1,0),
+(43234,1,0),
+(43239,1,0),
+(43244,1,0),
+(43255,1,0),
+(43291,1,0),
+(43306,1,0),
+(43307,1,0),
+(43333,1,0),
+(43371,1,0),
+(43385,1,0),
+(43386,1,0),
+(43403,1,0),
+(43404,1,0),
+(43407,1,0),
+(43450,1,0),
+(43458,1,0),
+(43468,1,0),
+(43486,1,0),
+(43487,1,0),
+(43515,1,0),
+(43520,1,0),
+(43525,1,0),
+(43546,1,0),
+(43559,1,0),
+(43563,1,0),
+(43568,1,0),
+(43615,1,0),
+(43647,1,0),
+(43662,1,0),
+(43685,1,0),
+(43691,1,0),
+(43711,1,0),
+(43734,1,0),
+(43754,1,0),
+(43770,1,0),
+(43791,1,0),
+(43805,1,0),
+(43863,1,0),
+(43865,1,0),
+(43867,1,0),
+(43871,1,0),
+(43872,1,0),
+(43878,1,0),
+(43882,1,0),
+(43892,1,0),
+(43942,1,0),
+(43943,1,0),
+(43949,1,0),
+(43962,1,0),
+(43990,1,0),
+(43994,1,0),
+(44014,1,0),
+(44022,1,0),
+(44023,1,0),
+(44024,1,0),
+(44026,1,0),
+(44027,1,0),
+(44028,1,0),
+(44037,1,0),
+(44145,1,0),
+(44161,1,0),
+(44193,1,0),
+(44214,1,0),
+(44224,1,1),
+(44229,1,0),
+(44232,1,1),
+(44250,1,0),
+(44255,1,0),
+(44260,1,0),
+(44266,1,0),
+(44270,1,0),
+(44283,1,0),
+(44284,1,0),
+(44309,1,0),
+(44313,1,0),
+(44329,1,0),
+(44330,1,0),
+(44355,1,0),
+(44362,1,0),
+(44365,1,0),
+(44367,1,0),
+(44374,1,0),
+(44392,1,0),
+(44411,1,0),
+(44420,1,0),
+(44422,1,0),
+(44458,1,0),
+(44550,1,0),
+(44562,1,0),
+(44574,1,0),
+(44609,1,0),
+(44610,1,0),
+(44653,1,0),
+(44681,1,0),
+(44682,1,1),
+(44749,1,0),
+(44804,1,0),
+(44807,1,0),
+(44826,1,0),
+(44837,1,0),
+(44838,1,0),
+(44839,1,0),
+(44840,1,0),
+(44841,1,0),
+(44842,1,0),
+(44845,1,0),
+(44846,1,0),
+(44849,1,1),
+(44864,1,0),
+(44865,1,0),
+(44872,1,0),
+(44877,1,0),
+(44883,1,0),
+(44886,1,0),
+(44938,1,0),
+(44939,1,0),
+(44941,1,0),
+(44946,1,0),
+(44948,1,0),
+(44963,1,0),
+(44965,1,0),
+(44981,1,0),
+(45005,1,0),
+(45008,1,0),
+(45012,1,0),
+(45013,1,0),
+(45076,1,0),
+(45086,1,0),
+(45103,1,0),
+(45109,1,0),
+(45114,1,0),
+(45115,1,0),
+(45119,1,0),
+(45172,1,0),
+(45188,1,0),
+(45191,1,0),
+(45219,1,0),
+(45223,1,0),
+(45224,1,0),
+(45229,1,0),
+(45233,1,0),
+(45259,1,0),
+(45260,1,1),
+(45264,1,0),
+(45267,1,0),
+(45277,1,0),
+(45279,1,0),
+(45307,1,0),
+(45323,1,0),
+(45339,1,0),
+(45340,1,0),
+(45351,1,0),
+(45368,1,0),
+(45371,1,0),
+(45388,1,0),
+(45389,1,0),
+(45405,1,0),
+(45407,1,0),
+(45414,1,0),
+(45437,1,0),
+(45446,1,0),
+(45448,1,0),
+(45449,1,0),
+(45465,1,0),
+(45474,1,0),
+(45536,1,0),
+(45581,1,0),
+(45583,1,0),
+(45586,1,0),
+(45594,1,0),
+(45595,1,0),
+(45596,1,0),
+(45597,1,0),
+(45602,1,0),
+(45605,1,0),
+(45606,1,0),
+(45607,1,0),
+(45608,1,0),
+(45609,1,0),
+(45622,1,0),
+(45623,1,0),
+(45630,1,0),
+(45634,1,0),
+(45644,1,1),
+(45651,1,0),
+(45655,1,0),
+(45656,1,0),
+(45666,1,0),
+(45667,1,0),
+(45671,1,1),
+(45680,1,1),
+(45692,1,0),
+(45700,1,0),
+(45714,1,0),
+(45732,1,0),
+(45735,1,0),
+(45761,1,0),
+(45774,1,0),
+(45780,1,0),
+(45788,1,0),
+(45805,1,0),
+(45808,1,0),
+(45834,1,0),
+(45835,1,0),
+(45841,1,0),
+(45853,1,0),
+(45859,1,0),
+(45863,1,0),
+(45864,1,0),
+(45867,1,0),
+(45872,1,0),
+(45888,1,0),
+(45907,1,0),
+(45911,1,0),
+(45912,1,0),
+(45914,1,0),
+(45918,1,1),
+(45923,1,0),
+(45929,1,0),
+(45930,1,0),
+(45941,1,0),
+(45949,1,0),
+(45961,1,0),
+(45968,1,0),
+(45969,1,0),
+(45970,1,0),
+(45976,1,0),
+(45979,1,0),
+(45990,1,0),
+(45993,1,0),
+(46013,1,0),
+(46018,1,1),
+(46022,1,0),
+(46034,1,0),
+(46054,1,0),
+(46058,1,0),
+(46063,1,0),
+(46066,1,0),
+(46068,1,0),
+(46085,1,0),
+(46143,1,0),
+(46171,1,0),
+(46173,1,0),
+(62377,1,0),
+(46175,1,0),
+(46176,1,0),
+(46177,1,0),
+(46178,1,0),
+(46201,1,0),
+(46208,1,0),
+(46219,1,0),
+(46222,1,0),
+(46236,1,0),
+(46237,1,0),
+(46245,1,0),
+(46246,1,0),
+(46281,1,0),
+(46307,1,1),
+(46318,1,0),
+(46319,1,0),
+(46320,1,1),
+(46330,1,0),
+(46363,1,0),
+(46372,1,1),
+(46374,1,0),
+(46376,1,0),
+(46382,1,0),
+(46385,1,0),
+(46396,1,1),
+(46398,1,0),
+(46399,1,0),
+(46400,1,0),
+(46474,1,0),
+(46475,1,0),
+(46477,1,0),
+(46482,1,0),
+(46488,1,0),
+(46521,1,0),
+(46588,1,1),
+(46592,1,0),
+(46593,1,0),
+(46603,1,0),
+(46609,1,0),
+(46610,1,0),
+(46623,1,0),
+(46631,1,0),
+(46637,1,0),
+(46650,1,0),
+(46652,1,0),
+(46656,1,0),
+(46685,1,0),
+(46692,1,0),
+(46694,1,0),
+(46704,1,0),
+(46707,1,0),
+(46732,1,1),
+(46733,1,0),
+(46735,1,0),
+(46747,1,0),
+(46793,1,0),
+(46797,1,0),
+(46809,1,0),
+(46815,1,0),
+(46818,1,0),
+(46820,1,0),
+(46843,1,0),
+(46886,1,0),
+(46895,1,0),
+(46900,1,0),
+(46902,1,0),
+(46903,1,0),
+(46904,1,0),
+(46936,1,0),
+(46937,1,0),
+(46963,1,0),
+(46964,1,0),
+(46965,1,1),
+(46974,1,0),
+(47016,1,0),
+(47026,1,0),
+(47035,1,0),
+(47060,1,0),
+(47065,1,0),
+(47104,1,0),
+(47110,1,0),
+(47137,1,0),
+(47170,1,0),
+(47176,1,0),
+(47184,1,0),
+(47214,1,0),
+(47253,1,0),
+(47254,1,0),
+(47336,1,0),
+(47344,1,0),
+(47370,1,1),
+(47374,1,0),
+(47378,1,0),
+(47421,1,0),
+(47452,1,0),
+(47460,1,0),
+(47463,1,0),
+(47469,1,0),
+(47542,1,0),
+(47547,1,0),
+(47563,1,0),
+(47574,1,0),
+(47593,1,0),
+(47594,1,0),
+(47596,1,0),
+(47597,1,0),
+(47598,1,0),
+(47599,1,0),
+(47616,1,0),
+(47617,1,0),
+(47618,1,0),
+(47619,1,0),
+(47634,1,0),
+(47669,1,0),
+(47670,1,0),
+(47681,1,0),
+(47682,1,0),
+(47683,1,0),
+(47684,1,0),
+(47685,1,0),
+(47691,1,1),
+(47711,1,0),
+(47712,1,0),
+(47713,1,0),
+(47747,1,0),
+(47771,1,0),
+(47787,1,0),
+(47799,1,0),
+(47911,1,0),
+(47913,1,0),
+(47916,1,0),
+(47933,1,0),
+(47935,1,0),
+(47939,1,0),
+(47959,1,0),
+(48009,1,0),
+(48021,1,0),
+(48028,1,1),
+(48035,1,0),
+(48115,1,0),
+(48117,1,0),
+(48183,1,0),
+(48185,1,0),
+(48188,1,0),
+(48194,1,1),
+(48199,1,0),
+(48201,1,0),
+(48202,1,0),
+(48213,1,0),
+(48218,1,0),
+(48222,1,0),
+(48223,1,0),
+(48227,1,0),
+(48246,1,1),
+(48252,1,0),
+(48293,1,0),
+(48306,1,0),
+(48315,1,0),
+(48329,1,0),
+(48344,1,0),
+(48345,1,0),
+(48362,1,0),
+(48363,1,0),
+(48375,1,0),
+(48385,1,0),
+(48398,1,0),
+(48399,1,0),
+(48425,1,0),
+(48426,1,0),
+(48455,1,0),
+(48490,1,0),
+(48497,1,0),
+(48508,1,0),
+(48530,1,0),
+(48551,1,0),
+(48597,1,0),
+(48600,1,0),
+(48605,1,0),
+(48620,1,0),
+(48623,1,0),
+(48627,1,0),
+(48641,1,0),
+(48642,1,0),
+(48646,1,0),
+(48649,1,0),
+(48685,1,0),
+(48724,1,0),
+(48726,1,0),
+(48728,1,0),
+(48730,1,0),
+(48732,1,0),
+(48748,1,0),
+(48764,1,0),
+(48771,1,0),
+(48773,1,0),
+(48790,1,0),
+(48793,1,0),
+(48799,1,0),
+(48808,1,0),
+(48811,1,0),
+(48896,1,0),
+(48901,1,0),
+(48904,1,0),
+(48929,1,0),
+(48974,1,0),
+(48975,1,0),
+(49022,1,0),
+(49030,1,0),
+(49058,1,0),
+(49062,1,0),
+(49075,1,0),
+(49080,1,0),
+(49083,1,0),
+(49118,1,0),
+(49125,1,0),
+(49128,1,0),
+(49129,1,0),
+(49131,1,0),
+(49134,1,0),
+(49135,1,0),
+(49159,1,0),
+(49166,1,0),
+(49210,1,0),
+(49211,1,0),
+(49262,1,0),
+(49291,1,0),
+(49292,1,0),
+(49313,1,0),
+(49319,1,0),
+(49325,1,0),
+(49330,1,0),
+(49332,1,0),
+(49333,1,0),
+(49334,1,0),
+(49367,1,0),
+(49370,1,0),
+(49404,1,0),
+(49405,1,0),
+(49428,1,0),
+(49434,1,0),
+(49515,1,0),
+(49517,1,0),
+(49519,1,0),
+(49524,1,0),
+(49525,1,0),
+(49552,1,0),
+(49554,1,0),
+(49555,1,0),
+(49557,1,0),
+(49590,1,0),
+(49625,1,0),
+(49634,1,0),
+(49679,1,0),
+(49682,1,0),
+(49683,1,0),
+(49684,1,0),
+(49731,1,0),
+(49751,1,0),
+(49762,1,0),
+(49825,1,0),
+(49826,1,0),
+(49829,1,0),
+(49858,1,0),
+(49862,1,0),
+(49870,1,0),
+(49899,1,0),
+(49947,1,0),
+(50036,1,0),
+(50087,1,0),
+(50133,1,0),
+(50173,1,0),
+(50174,1,0),
+(50176,1,0),
+(50177,1,0),
+(50178,1,0),
+(50179,1,0),
+(50312,1,0),
+(50315,1,1),
+(50331,1,0),
+(50350,1,0),
+(50382,1,0),
+(50383,1,0),
+(50398,1,1),
+(50430,1,0),
+(50440,1,0),
+(50492,1,0),
+(50515,1,0),
+(50524,1,0),
+(50546,1,0),
+(50547,1,0),
+(50548,1,0),
+(50554,1,0),
+(50556,1,0),
+(50562,1,0),
+(50563,1,0),
+(50568,1,0),
+(50569,1,0),
+(50592,1,0),
+(50628,1,0),
+(50669,1,0),
+(50674,1,0),
+(50682,1,1),
+(50742,1,0),
+(50775,1,0),
+(50793,1,0),
+(50794,1,0),
+(50817,1,0),
+(50835,1,0),
+(50878,1,0),
+(50883,1,1),
+(50892,1,0),
+(51001,1,0),
+(51022,1,0),
+(51023,1,0),
+(51024,1,0),
+(51025,1,0),
+(51039,1,0),
+(51049,1,0),
+(51122,1,0),
+(51136,1,0),
+(51139,1,0),
+(51152,1,0),
+(51171,1,0),
+(51172,1,0),
+(51202,1,0),
+(51213,1,0),
+(51215,1,0),
+(51234,1,0),
+(51239,1,0),
+(51247,1,0),
+(51256,1,0),
+(51276,1,0),
+(51288,1,0),
+(51318,1,0),
+(51331,1,0),
+(51332,1,0),
+(51333,1,0),
+(51343,1,0),
+(51366,1,0),
+(51368,1,0),
+(51381,1,0),
+(51384,1,0),
+(51393,1,0),
+(51396,1,0),
+(51403,1,0),
+(51420,1,0),
+(51448,1,1),
+(51516,1,0),
+(51518,1,0),
+(51577,1,0),
+(51579,1,0),
+(51590,1,0),
+(51603,1,0),
+(51606,1,0),
+(51607,1,0),
+(51616,1,0),
+(51639,1,0),
+(51641,1,0),
+(51642,1,0),
+(51643,1,0),
+(51644,1,0),
+(51645,1,0),
+(51649,1,0),
+(51650,1,0),
+(51651,1,0),
+(51652,1,0),
+(51670,1,0),
+(51694,1,0),
+(51697,1,0),
+(51727,1,0),
+(51737,1,0),
+(51739,1,0),
+(51743,1,0),
+(51754,1,0),
+(51767,1,0),
+(51769,1,0),
+(51773,1,0),
+(51774,1,0),
+(51791,1,0),
+(51794,1,0),
+(51825,1,0),
+(51840,1,0),
+(51843,1,0),
+(51858,1,0),
+(51859,1,0),
+(51861,1,0),
+(51866,1,0),
+(51870,1,0),
+(51902,1,0),
+(51904,1,0),
+(51907,1,0),
+(51910,1,0),
+(51925,1,0),
+(51927,1,0),
+(51931,1,0),
+(51932,1,0),
+(51933,1,0),
+(51942,1,0),
+(51959,1,0),
+(51964,1,0),
+(51965,1,0),
+(52011,1,0),
+(52037,1,0),
+(52059,1,0),
+(52064,1,0),
+(52089,1,0),
+(52106,1,0),
+(52122,1,0),
+(52124,1,0),
+(52140,1,0),
+(52151,1,0),
+(52164,1,0),
+(52170,1,0),
+(52173,1,0),
+(52185,1,0),
+(52227,1,0),
+(52229,1,0),
+(52238,1,0),
+(52239,1,0),
+(52242,1,0),
+(52247,1,0),
+(52254,1,0),
+(52257,1,0),
+(52259,1,0),
+(52264,1,0),
+(52294,1,0),
+(52313,1,0),
+(52322,1,0),
+(52335,1,0),
+(52336,1,0),
+(52337,1,1),
+(52340,1,0),
+(52343,1,0),
+(52349,1,0),
+(52365,1,1),
+(52369,1,0),
+(52371,1,0),
+(52381,1,0),
+(52387,1,0),
+(52388,1,0),
+(52407,1,0),
+(52412,1,0),
+(52414,1,0),
+(52427,1,0),
+(52438,1,0),
+(52446,1,0),
+(52449,1,0),
+(52452,1,0),
+(52453,1,0),
+(52454,1,0),
+(52457,1,0),
+(52458,1,0),
+(52512,1,0),
+(52514,1,0),
+(52528,1,0),
+(52576,1,0),
+(52577,1,0),
+(52585,1,0),
+(52607,1,0),
+(52632,1,0),
+(52638,1,0),
+(52654,1,0),
+(52661,1,0),
+(52676,1,0),
+(52681,1,0),
+(52686,1,0),
+(52687,1,0),
+(52688,1,0),
+(52725,1,0),
+(52726,1,0),
+(52727,1,0),
+(52728,1,0),
+(52729,1,0),
+(52730,1,0),
+(52731,1,0),
+(52732,1,0),
+(52774,1,0),
+(52791,1,0),
+(52793,1,0),
+(52805,1,0),
+(52811,1,0),
+(52816,1,0),
+(52833,1,0),
+(52834,1,0),
+(52837,1,0),
+(52838,1,0),
+(52844,1,0),
+(52850,1,0),
+(52884,1,0),
+(52908,1,0),
+(52920,1,0),
+(52930,1,0),
+(52934,1,0),
+(52935,1,0),
+(52936,1,0),
+(52937,1,0),
+(52953,1,0),
+(52955,1,0),
+(52956,1,0),
+(52981,1,0),
+(52989,1,0),
+(52990,1,0),
+(53010,1,0),
+(53020,1,0),
+(53024,1,0),
+(53029,1,0),
+(53038,1,0),
+(53083,1,0),
+(53093,1,0),
+(53096,1,0),
+(53106,1,0),
+(53110,1,0),
+(53163,1,0),
+(53170,1,0),
+(53177,1,0),
+(53185,1,0),
+(53206,1,0),
+(53210,1,0),
+(53242,1,1),
+(53272,1,0),
+(53441,1,0),
+(53464,1,0),
+(53465,1,0),
+(53466,1,0),
+(53570,1,0),
+(53609,1,0),
+(53613,1,0),
+(53626,1,0),
+(53644,1,0),
+(53680,1,0),
+(53683,1,0),
+(53684,1,0),
+(53685,1,0),
+(53701,1,0),
+(53714,1,1),
+(53717,1,0),
+(53730,1,0),
+(53745,1,0),
+(53757,1,1),
+(53778,1,0),
+(53798,1,0),
+(53826,1,0),
+(53827,1,0),
+(53828,1,0),
+(53829,1,0),
+(54040,1,0),
+(54047,1,0),
+(54089,1,0),
+(54090,1,0),
+(54097,1,0),
+(54108,1,0),
+(54112,1,0),
+(54128,1,0),
+(54142,1,0),
+(54209,1,0),
+(54236,1,0),
+(54245,1,0),
+(54250,1,0),
+(54258,1,0),
+(54264,1,0),
+(54265,1,0),
+(54266,1,0),
+(54267,1,0),
+(54269,1,0),
+(54323,1,0),
+(54325,1,0),
+(54327,1,0),
+(54328,1,0),
+(54377,1,0),
+(54423,1,0),
+(54426,1,0),
+(54430,1,0),
+(54464,1,0),
+(54510,1,0),
+(54522,1,0),
+(54539,1,0),
+(54548,1,0),
+(54643,1,0),
+(54656,1,0),
+(54664,1,0),
+(54685,1,0),
+(54699,1,1),
+(54725,1,1),
+(54728,1,0),
+(54744,1,1),
+(54746,1,1),
+(54773,1,0),
+(54796,1,0),
+(54798,1,0),
+(54806,1,0),
+(54878,1,0),
+(54899,1,0),
+(54984,1,0),
+(54985,1,0),
+(54988,1,0),
+(54991,1,0),
+(55063,1,0),
+(55089,1,0),
+(55127,1,0),
+(55134,1,0),
+(55137,1,0),
+(55138,1,0),
+(55141,1,0),
+(55145,1,0),
+(55161,1,0),
+(55223,1,0),
+(55227,1,0),
+(55229,1,0),
+(55231,1,0),
+(55244,1,0),
+(55257,1,0),
+(55287,1,0),
+(55288,1,0),
+(55290,1,0),
+(55406,1,0),
+(55418,1,0),
+(55419,1,0),
+(55423,1,1),
+(55432,1,0),
+(55465,1,0),
+(55468,1,0),
+(55510,1,0),
+(55516,1,0),
+(55519,1,0),
+(55524,1,0),
+(55526,1,0),
+(55527,1,0),
+(55571,1,0),
+(55578,1,0),
+(55616,1,1),
+(55647,1,0),
+(55660,1,0),
+(55661,1,0),
+(55662,1,0),
+(55693,1,0),
+(55720,1,0),
+(55721,1,0),
+(55722,1,0),
+(55723,1,0),
+(55724,1,0),
+(55725,1,0),
+(55726,1,0),
+(55727,1,0),
+(55785,1,0),
+(55796,1,0),
+(55801,1,0),
+(55803,1,0),
+(55805,1,0),
+(55811,1,0),
+(55844,1,0),
+(55853,1,0),
+(55868,1,0),
+(55872,1,0),
+(55875,1,0),
+(55878,1,1),
+(55881,1,1),
+(55882,1,0),
+(55885,1,1),
+(55886,1,0),
+(55887,1,1),
+(55888,1,0),
+(55954,1,0),
+(56047,1,0),
+(56066,1,0),
+(56099,1,0),
+(56103,1,0),
+(56114,1,0),
+(56117,1,0),
+(56150,1,0),
+(56152,1,0),
+(56189,1,0),
+(56227,1,0),
+(56253,1,0),
+(56263,1,0),
+(56264,1,0),
+(56265,1,0),
+(56266,1,0),
+(56275,1,0),
+(56312,1,0),
+(56387,1,0),
+(56388,1,0),
+(56393,1,0),
+(56429,1,0),
+(56458,1,0),
+(56505,1,0),
+(56523,1,0),
+(56560,1,0),
+(56563,1,0),
+(56567,1,0),
+(56575,1,0),
+(56621,1,0),
+(56622,1,0),
+(56652,1,0),
+(56661,1,0),
+(56663,1,0),
+(56665,1,0),
+(56667,1,0),
+(56669,1,0),
+(56673,1,0),
+(56677,1,0),
+(56680,1,0),
+(56683,1,0),
+(56688,1,0),
+(56691,1,0),
+(56693,1,0),
+(56695,1,0),
+(56696,1,0),
+(56711,1,0),
+(56713,1,0),
+(56722,1,0),
+(56723,1,0),
+(56724,1,0),
+(56725,1,0),
+(56738,1,0),
+(56763,1,0),
+(56764,1,0),
+(56865,1,0),
+(56905,1,0),
+(56917,1,0),
+(56941,1,1),
+(57042,1,0),
+(57068,1,0),
+(57071,1,0),
+(57072,1,0),
+(57410,1,0),
+(57417,1,0),
+(57420,1,0),
+(57422,1,0),
+(57469,1,0),
+(57471,1,0),
+(57495,1,0),
+(57523,1,0),
+(57534,1,0),
+(57632,1,0),
+(57637,1,0),
+(57638,1,0),
+(57639,1,0),
+(57642,1,0),
+(57650,1,0),
+(57659,1,0),
+(57666,1,0),
+(57667,1,0),
+(57682,1,0),
+(57732,1,0),
+(57734,1,0),
+(57735,1,0),
+(57736,1,0),
+(57737,1,0),
+(57738,1,0),
+(57797,1,0),
+(57806,1,0),
+(57809,1,0),
+(57828,1,0),
+(57852,1,0),
+(57853,1,0),
+(57885,1,0),
+(57891,1,0),
+(57912,1,0),
+(57930,1,0),
+(57962,1,0),
+(57963,1,0),
+(57980,1,0),
+(57983,1,0),
+(58036,1,0),
+(58040,1,0),
+(58064,1,0),
+(58084,1,0),
+(58103,1,0),
+(58108,1,0),
+(58109,1,0),
+(58112,1,0),
+(58114,1,0),
+(58121,1,0),
+(58123,1,0),
+(58124,1,0),
+(58131,1,0),
+(58152,1,0),
+(58178,1,0),
+(58195,1,1),
+(58196,1,1),
+(58197,1,1),
+(58198,1,1),
+(58225,1,0),
+(58350,1,0),
+(58416,1,0),
+(58493,1,1),
+(58515,1,0),
+(58533,1,0),
+(58542,1,0),
+(58552,1,0),
+(58593,1,0),
+(58641,1,0),
+(58658,1,0),
+(58672,1,0),
+(58685,1,0),
+(58793,1,0),
+(58836,1,0),
+(58838,1,0),
+(58846,1,1),
+(58858,1,0),
+(58873,1,0),
+(58916,1,0),
+(58917,1,0),
+(58945,1,0),
+(58949,1,0),
+(59078,1,0),
+(59091,1,0),
+(59098,1,0),
+(59115,1,0),
+(59125,1,0),
+(59189,1,0),
+(59190,1,0),
+(59284,1,0),
+(59335,1,0),
+(59363,1,0),
+(59375,1,0),
+(59383,1,0),
+(59386,1,0),
+(59396,1,0),
+(59449,1,0),
+(59456,1,0),
+(59461,1,1),
+(59528,1,0),
+(59534,1,0),
+(59552,1,0),
+(59554,1,0),
+(59556,1,1),
+(59579,1,0),
+(59595,1,0),
+(59643,1,0),
+(59655,1,0),
+(59668,1,0),
+(59677,1,0),
+(59678,1,0),
+(59704,1,0),
+(59729,1,0),
+(59730,1,0),
+(59764,1,0),
+(59780,1,0),
+(59781,1,0),
+(59807,1,0),
+(59847,1,0),
+(59867,1,0),
+(59871,1,0),
+(59897,1,0),
+(59925,1,0),
+(59930,1,0),
+(59951,1,0),
+(59952,1,0),
+(59977,1,0),
+(60038,1,0),
+(60045,1,0),
+(60046,1,0),
+(60088,1,0),
+(60104,1,0),
+(60178,1,1),
+(60207,1,0),
+(60208,1,0),
+(60224,1,0),
+(60243,1,0),
+(60256,1,0),
+(60285,1,0),
+(60288,1,0),
+(60291,1,1),
+(60292,1,1),
+(60293,1,1),
+(60294,1,1),
+(60295,1,1),
+(60296,1,1),
+(60297,1,1),
+(60298,1,0),
+(60310,1,0),
+(60315,1,0),
+(60316,1,0),
+(60342,1,0),
+(60422,1,0),
+(60456,1,0),
+(60476,1,1),
+(60496,1,0),
+(60499,1,1),
+(60507,1,1),
+(60508,1,1),
+(60511,1,0),
+(60516,1,0),
+(60522,1,1),
+(60528,1,0),
+(60535,1,0),
+(60536,1,0),
+(60561,1,0),
+(60612,1,0),
+(60614,1,0),
+(60713,1,0),
+(60810,1,0),
+(60829,1,0),
+(60831,1,0),
+(60834,1,0),
+(60836,1,0),
+(60863,1,0),
+(60909,1,0),
+(60912,1,1),
+(60967,1,0),
+(61007,1,0),
+(61026,1,0),
+(61028,1,0),
+(61071,1,0),
+(61072,1,0),
+(61073,1,0),
+(61074,1,0),
+(61075,1,0),
+(61114,1,0),
+(61121,1,0),
+(61151,1,0),
+(61152,1,0),
+(61180,1,0),
+(61210,1,0),
+(61219,1,0),
+(61245,1,0),
+(61254,1,0),
+(61353,1,0),
+(61355,1,0),
+(61397,1,0),
+(61408,1,0),
+(61416,1,0),
+(61487,1,0),
+(61488,1,0),
+(61492,1,0),
+(61524,1,0),
+(61537,1,0),
+(61588,1,0),
+(61602,1,0),
+(61647,1,0),
+(61652,1,0),
+(61665,1,0),
+(61710,1,0),
+(61738,1,0),
+(61764,1,0),
+(61765,1,0),
+(61766,1,0),
+(61771,1,0),
+(61816,1,1),
+(61863,1,1),
+(61901,1,0),
+(61934,1,0),
+(61942,1,0),
+(61964,1,0),
+(61975,1,0),
+(62002,1,0),
+(62016,1,0),
+(62034,1,0),
+(62037,1,1),
+(62072,1,0),
+(62082,1,0),
+(62083,1,0),
+(62084,1,0),
+(62091,1,0),
+(62102,1,0),
+(62195,1,0),
+(62223,1,0),
+(62266,1,0),
+(62272,1,0),
+(62278,1,0),
+(62284,1,0),
+(62304,1,0),
+(62323,1,0),
+(62343,1,0),
+(47129,2,0),
+(34395,2,0),
+(34387,2,0),
+(32440,2,0),
+(32439,2,0),
+(32205,2,0),
+(31538,2,0),
+(30740,2,0),
+(29831,2,0),
+(28806,2,0),
+(28353,2,0),
+(27517,2,0),
+(27203,2,0),
+(27202,2,0),
+(27201,2,0),
+(27191,2,0),
+(27190,2,0),
+(27184,2,0),
+(26560,2,0),
+(26063,2,0),
+(25005,2,0),
+(24934,2,0),
+(24871,2,0),
+(24721,2,0),
+(24390,2,0),
+(23208,2,0),
+(21127,2,0),
+(18431,2,0),
+(17731,2,0),
+(17016,2,0),
+(16613,2,0),
+(16447,2,0),
+(13489,2,0),
+(12139,2,0),
+(11792,2,0),
+(9224,2,0),
+(9223,2,0),
+(9222,2,0),
+(9221,2,0),
+(8674,2,0),
+(7729,2,0),
+(7728,2,0),
+(3921,2,0),
+(35683,2,0),
+(36066,2,0),
+(36546,2,0),
+(36851,2,0),
+(37754,2,0),
+(38439,2,0),
+(38782,2,0),
+(39050,2,0),
+(40055,2,0),
+(40165,2,0),
+(40166,2,0),
+(40167,2,0),
+(40328,2,0),
+(40447,2,0),
+(40468,2,0),
+(40632,2,0),
+(40640,2,0),
+(40642,2,0),
+(40644,2,0),
+(40675,2,0),
+(40774,2,0),
+(40785,2,0),
+(40964,2,0),
+(40965,2,0),
+(40968,2,0),
+(40970,2,0),
+(41004,2,0),
+(41145,2,0),
+(41146,2,0),
+(42020,2,0),
+(42022,2,0),
+(42323,2,0),
+(42788,2,0),
+(43418,2,0),
+(43552,2,0),
+(43723,2,0),
+(43753,2,0),
+(43768,2,0),
+(43950,2,0),
+(44307,2,0),
+(44498,2,0),
+(44499,2,0),
+(44611,2,0),
+(44686,2,0),
+(44874,2,0),
+(44885,2,0),
+(45149,2,0),
+(45222,2,0),
+(45226,2,0),
+(45795,2,0),
+(45877,2,0),
+(45971,2,0),
+(46072,2,0),
+(46350,2,0),
+(46360,2,1),
+(46584,2,0),
+(76006,2,0),
+(74179,2,0),
+(72869,2,0),
+(72868,2,0),
+(72608,2,0),
+(72456,2,0),
+(72405,2,0),
+(72340,2,1),
+(71284,2,1),
+(70598,2,1),
+(70446,2,1),
+(70346,2,0),
+(70227,2,0),
+(70199,2,0),
+(70175,2,0),
+(70173,2,0),
+(69402,2,0),
+(69400,2,0),
+(69294,2,0),
+(69157,2,0),
+(67815,2,0),
+(67814,2,0),
+(67813,2,0),
+(67812,2,0),
+(67798,2,0),
+(67459,2,0),
+(67458,2,0),
+(67448,2,0),
+(67439,2,0),
+(67436,2,0),
+(66676,2,0),
+(66672,2,0),
+(66655,2,0),
+(66531,2,0),
+(66289,2,0),
+(65209,2,0),
+(64871,2,0),
+(64570,2,0),
+(64436,2,0),
+(63618,2,0),
+(63381,2,0),
+(62776,2,0),
+(62714,2,0),
+(62635,2,0),
+(62397,2,0),
+(62363,2,0),
+(62357,2,0),
+(62355,2,0),
+(62307,2,0),
+(62086,2,0),
+(61999,2,1),
+(60289,2,0),
+(60101,2,0),
+(59790,2,0),
+(59732,2,0),
+(59576,2,0),
+(58596,2,0),
+(58231,2,0),
+(57945,2,0),
+(57619,2,0),
+(57610,2,0),
+(57607,2,0),
+(57583,2,0),
+(57575,2,0),
+(57544,2,0),
+(57517,2,0),
+(57415,2,0),
+(56790,2,0),
+(56570,2,0),
+(56385,2,0),
+(56350,2,0),
+(55934,2,0),
+(55820,2,0),
+(55367,2,0),
+(55197,2,0),
+(54712,2,0),
+(54666,2,0),
+(54530,2,0),
+(52510,2,0),
+(52408,2,0),
+(52339,2,0),
+(52277,2,0),
+(52274,2,0),
+(52115,2,0),
+(51383,2,0),
+(51328,2,0),
+(51327,2,0),
+(51326,2,0),
+(51325,2,0),
+(51241,2,0),
+(50999,2,0),
+(50319,2,0),
+(50026,2,0),
+(50003,2,0),
+(49867,2,0),
+(49860,2,0),
+(49765,2,0),
+(49728,2,0),
+(49693,2,0),
+(49689,2,0),
+(49158,2,0),
+(49123,2,0),
+(49109,2,0),
+(48794,2,0),
+(48738,2,0),
+(48347,2,0),
+(47978,2,0),
+(35246,2,0),
+(42576,3,0),
+(42492,3,0),
+(42475,3,0),
+(42433,3,0),
+(42350,3,0),
+(42348,3,0),
+(42242,3,1),
+(42228,3,0),
+(42220,3,0),
+(42114,3,0),
+(41221,3,0),
+(40961,3,0),
+(40960,3,0),
+(40959,3,0),
+(40957,3,0),
+(40885,3,0),
+(40603,3,0),
+(40495,3,0),
+(40401,3,0),
+(40380,3,0),
+(40341,3,0),
+(40307,3,0),
+(40286,3,0),
+(40285,3,0),
+(40284,3,0),
+(40283,3,0),
+(40268,3,0),
+(40247,3,0),
+(40246,3,0),
+(40245,3,0),
+(40244,3,0),
+(40240,3,0),
+(40222,3,0),
+(40179,3,0),
+(40178,3,0),
+(40177,3,0),
+(40176,3,0),
+(40105,3,0),
+(40076,3,0),
+(39932,3,0),
+(39887,3,0),
+(39844,3,0),
+(39832,3,1),
+(39831,3,0),
+(39558,3,0),
+(39401,3,0),
+(39399,3,0),
+(39398,3,0),
+(39393,3,0),
+(39384,3,0),
+(39364,3,0),
+(38866,3,0),
+(38680,3,0),
+(38173,3,0),
+(38046,3,0),
+(38044,3,0),
+(37970,3,0),
+(37954,3,0),
+(37942,3,0),
+(37919,3,0),
+(37913,3,0),
+(37793,3,1),
+(37789,3,0),
+(37750,3,1),
+(37504,3,0),
+(37489,3,0),
+(37473,3,1),
+(37366,3,0),
+(37134,3,0),
+(36821,3,0),
+(36811,3,0),
+(36450,3,0),
+(36449,3,1),
+(36325,3,0),
+(35958,3,0),
+(35776,3,0),
+(35734,3,0),
+(35599,3,0),
+(35596,3,0),
+(34303,3,0),
+(34200,3,0),
+(34186,3,0),
+(42578,3,0),
+(33814,3,0),
+(33783,3,0),
+(33670,3,0),
+(33664,3,0),
+(33365,3,0),
+(33240,3,0),
+(33111,3,0),
+(32785,3,0),
+(32314,3,0),
+(32307,3,0),
+(32241,3,0),
+(32148,3,0),
+(32067,3,0),
+(31927,3,0),
+(31543,3,0),
+(31364,3,0),
+(31363,3,0),
+(31333,3,0),
+(30758,3,0),
+(30741,3,0),
+(30284,3,0),
+(29945,3,0),
+(29866,3,0),
+(29820,3,1),
+(29460,3,0),
+(28373,3,0),
+(28250,3,0),
+(28054,3,0),
+(26521,3,0),
+(26519,3,0),
+(26518,3,0),
+(26517,3,0),
+(26516,3,0),
+(26490,3,0),
+(26488,3,0),
+(26393,3,1),
+(26373,3,0),
+(26338,3,0),
+(26337,3,0),
+(26336,3,0),
+(26335,3,0),
+(26334,3,0),
+(26333,3,0),
+(26329,3,0),
+(26328,3,0),
+(26327,3,0),
+(26326,3,0),
+(26325,3,0),
+(26304,3,0),
+(26295,3,0),
+(26294,3,0),
+(26293,3,0),
+(26292,3,0),
+(26291,3,0),
+(26286,3,0),
+(25687,3,0),
+(25183,3,0),
+(25181,3,0),
+(25180,3,0),
+(25178,3,0),
+(25177,3,0),
+(24973,3,0),
+(24731,3,0),
+(23024,3,0),
+(21086,3,0),
+(21014,3,0),
+(20038,3,0),
+(20037,3,0),
+(19873,3,0),
+(17179,3,0),
+(16629,3,0),
+(16452,3,0),
+(16337,3,0),
+(15998,3,0),
+(13488,3,0),
+(12151,3,0),
+(10860,3,0),
+(10836,3,0),
+(10835,3,0),
+(10834,3,0),
+(10805,3,0),
+(9257,3,0),
+(9232,3,0),
+(42868,3,0),
+(43233,3,0),
+(43539,3,0),
+(43664,3,0),
+(43898,3,0),
+(43954,3,0),
+(43963,3,0),
+(43986,3,0),
+(44013,3,0),
+(44132,3,0),
+(44213,3,0),
+(44249,3,0),
+(44320,3,0),
+(44321,3,0),
+(44375,3,0),
+(44465,3,0),
+(44554,3,0),
+(44565,3,0),
+(44603,3,0),
+(44678,3,0),
+(44844,3,0),
+(44884,3,0),
+(45030,3,0),
+(45050,3,1),
+(45201,3,0),
+(45203,3,0),
+(45404,3,0),
+(45502,3,0),
+(45585,3,0),
+(45633,3,0),
+(45635,3,0),
+(45653,3,0),
+(45839,3,0),
+(45885,3,1),
+(46417,3,0),
+(46574,3,0),
+(46638,3,1),
+(46852,3,0),
+(46896,3,0),
+(47030,3,1),
+(47328,3,0),
+(47510,3,0),
+(47628,3,0),
+(47745,3,0),
+(47775,3,1),
+(47800,3,0),
+(48198,3,0),
+(48212,3,0),
+(48331,3,0),
+(48431,3,0),
+(48882,3,0),
+(48972,3,0),
+(49197,3,0),
+(49300,3,0),
+(49308,3,0),
+(49453,3,0),
+(49735,3,0),
+(50313,3,1),
+(50348,3,0),
+(50443,3,0),
+(50501,3,0),
+(50626,3,0),
+(50639,3,0),
+(50640,3,0),
+(50716,3,0),
+(50790,3,0),
+(50791,3,0),
+(50802,3,0),
+(50803,3,0),
+(50825,3,0),
+(50826,3,0),
+(51212,3,0),
+(51246,3,0),
+(51395,3,0),
+(51511,3,0),
+(51742,3,0),
+(51748,3,0),
+(51805,3,0),
+(51846,3,0),
+(52067,3,1),
+(52271,3,0),
+(52305,3,0),
+(52479,3,0),
+(52480,3,0),
+(52497,3,0),
+(52603,3,0),
+(52683,3,0),
+(52685,3,0),
+(52812,3,0),
+(53677,3,0),
+(53679,3,0),
+(53694,3,0),
+(53705,3,0),
+(53706,3,0),
+(54272,3,0),
+(54517,3,0),
+(54914,3,0),
+(54961,3,0),
+(54990,3,0),
+(55037,3,0),
+(55083,3,0),
+(55365,3,0),
+(55479,3,0),
+(55715,3,0),
+(55800,3,0),
+(55889,3,1),
+(56095,3,0),
+(56140,3,0),
+(56386,3,0),
+(56389,3,0),
+(56578,3,0),
+(56747,3,0),
+(56765,3,0),
+(57586,3,0),
+(57800,3,0),
+(57824,3,0),
+(57835,3,0),
+(58766,3,0),
+(58825,3,0),
+(59008,3,0),
+(59462,3,0),
+(59464,3,0),
+(59564,3,0),
+(59629,3,0),
+(59694,3,0),
+(60639,3,0),
+(61126,3,0),
+(61224,3,0),
+(61699,3,0),
+(62000,3,0),
+(62056,3,0),
+(62385,3,0),
+(62387,3,0),
+(62399,3,0),
+(62565,3,0),
+(62709,3,0),
+(62973,3,0),
+(62991,3,0),
+(63019,3,0),
+(63122,3,1),
+(63292,3,0),
+(63294,3,0),
+(63295,3,0),
+(63317,3,0),
+(63414,3,0),
+(63528,3,0),
+(63766,3,0),
+(63983,3,0),
+(63985,3,0),
+(64021,3,0),
+(65044,3,0),
+(65045,3,0),
+(65101,3,0),
+(65585,3,0),
+(65586,3,0),
+(65690,3,0),
+(66129,3,0),
+(66170,3,0),
+(66598,3,0),
+(67398,3,0),
+(68378,3,0),
+(68902,3,0),
+(69007,3,0),
+(69095,3,0),
+(69096,3,0),
+(69708,3,0),
+(69783,3,0),
+(69797,3,0),
+(69799,3,0),
+(69802,3,0),
+(69985,3,0),
+(70028,3,0),
+(70037,3,0),
+(70194,3,0),
+(70521,3,0),
+(70564,3,0),
+(70590,3,0),
+(70997,3,0),
+(70998,3,0),
+(70999,3,0),
+(71278,3,1),
+(71621,3,0),
+(71704,3,0),
+(72155,3,1),
+(72162,3,1),
+(72274,3,1),
+(72297,3,1),
+(72460,3,1),
+(72548,3,1),
+(72549,3,1),
+(72550,3,1),
+(72619,3,1),
+(72620,3,1),
+(72679,3,0),
+(72771,3,0),
+(72850,3,0),
+(72851,3,0),
+(72852,3,0),
+(74318,3,0),
+(74319,3,0),
+(74320,3,0),
+(74472,3,0),
+(75509,3,0),
+(75553,3,1),
+(75766,3,1),
+(34012,3,0),
+(74271,4,0),
+(74270,4,0),
+(72096,4,1),
+(72034,4,1),
+(71615,4,0),
+(70827,4,0),
+(69425,4,0),
+(69164,4,0),
+(69162,4,0),
+(68981,4,0),
+(68788,4,1),
+(67816,4,0),
+(67796,4,0),
+(65370,4,0),
+(65333,4,0),
+(64626,4,0),
+(62826,4,0),
+(62489,4,0),
+(62466,4,0),
+(62457,4,0),
+(62345,4,0),
+(62308,4,0),
+(60206,4,0),
+(58185,4,0),
+(55896,4,0),
+(55349,4,0),
+(54109,4,0),
+(54107,4,0),
+(51678,4,0),
+(50652,4,0),
+(49556,4,0),
+(48610,4,0),
+(48277,4,0),
+(48224,4,0),
+(47674,4,0),
+(47109,4,0),
+(45922,4,0),
+(44969,4,0),
+(44737,4,0),
+(44687,4,0),
+(44626,4,0),
+(44233,4,0),
+(40647,4,0),
+(40259,4,0),
+(39246,4,0),
+(36904,4,0),
+(36460,4,0),
+(36374,4,0),
+(30532,4,0),
+(28995,4,0),
+(10451,4,0),
+(9735,4,0),
+(8900,4,0),
+(8899,4,0),
+(8898,4,0),
+(8202,4,0),
+(74272,4,0),
+(69767,5,0),
+(65590,5,0),
+(62386,5,0),
+(55588,5,0),
+(54713,5,0),
+(49464,5,0),
+(49460,5,0),
+(49346,5,0),
+(47310,5,1),
+(45676,5,0),
+(44217,5,0),
+(43977,5,0),
+(41962,5,0),
+(40789,5,0),
+(40503,5,0),
+(38729,5,0),
+(38312,5,0),
+(38106,5,0),
+(38105,5,0),
+(38104,5,0),
+(38103,5,0),
+(38102,5,0),
+(38101,5,0),
+(38100,5,0),
+(38099,5,0),
+(37206,5,0),
+(37205,5,0),
+(37204,5,0),
+(36817,5,0),
+(34630,5,0),
+(21866,5,0),
+(21794,5,0),
+(19832,5,0),
+(19250,5,0),
+(8913,5,0),
+(67308,6,0),
+(67307,6,0),
+(67306,6,0),
+(67305,6,0),
+(67304,6,0),
+(67303,6,0),
+(65876,6,0),
+(65875,6,0),
+(63041,6,0),
+(62560,6,0),
+(59099,6,1),
+(44608,6,0),
+(43702,6,0),
+(43080,6,0),
+(43056,6,0),
+(40902,6,0),
+(40657,6,0),
+(28803,6,1),
+(16054,6,0),
+(8712,6,0),
+(75863,7,1),
+(75448,7,1),
+(74412,7,1),
+(74323,7,0),
+(74322,7,0),
+(74321,7,0),
+(73028,7,0),
+(72622,7,1),
+(72621,7,1),
+(72459,7,1),
+(72273,7,0),
+(72272,7,0),
+(71618,7,0),
+(71614,7,0),
+(71279,7,1),
+(70982,7,0),
+(70981,7,0),
+(70952,7,0),
+(69540,7,0),
+(67751,7,0),
+(66905,7,0),
+(66667,7,0),
+(65126,7,0),
+(64218,7,0),
+(63059,7,0),
+(62942,7,0),
+(62705,7,0),
+(61920,7,0),
+(61715,7,0),
+(61714,7,0),
+(61632,7,0),
+(60532,7,0),
+(60430,7,0),
+(59474,7,0),
+(59465,7,0),
+(57409,7,0),
+(57405,7,0),
+(57056,7,1),
+(56694,7,0),
+(56454,7,0),
+(54160,7,0),
+(53605,7,0),
+(52319,7,0),
+(51719,7,0),
+(50747,7,0),
+(50646,7,0),
+(50645,7,0),
+(50627,7,0),
+(50218,7,0),
+(49889,7,0),
+(48742,7,0),
+(48552,7,0),
+(46158,7,0),
+(42287,7,0),
+(42265,7,1),
+(42079,7,0),
+(42004,7,1),
+(41284,7,0),
+(41113,7,0),
+(41112,7,0),
+(41111,7,0),
+(41110,7,0),
+(41071,7,0),
+(41064,7,1),
+(40931,7,0),
+(40929,7,0),
+(40905,7,0),
+(40900,7,0),
+(40851,7,0),
+(40370,7,0),
+(40172,7,0),
+(40171,7,0),
+(40170,7,0),
+(40169,7,0),
+(40075,7,1),
+(39698,7,0),
+(39686,7,0),
+(39218,7,0),
+(38920,7,0),
+(38774,7,0),
+(38484,7,0),
+(38449,7,0),
+(38371,7,0),
+(37076,7,0),
+(35957,7,1),
+(35754,7,0),
+(35289,7,0),
+(34350,7,0),
+(34187,7,0),
+(31625,7,0),
+(31624,7,0),
+(31617,7,0),
+(30939,7,1),
+(30659,7,0),
+(30657,7,0),
+(30531,7,0),
+(30098,7,0),
+(28681,7,1),
+(25790,7,0),
+(25029,7,0),
+(23015,7,0),
+(22710,7,0),
+(20553,7,0),
+(10732,7,0),
+(10348,7,0),
+(7082,7,0),
+(5628,7,0),
+(804,7,0),
+(802,7,0),
+(54069,1,0),
+(56251,1,0),
+(58630,1,0);
+
+-- remove redundant entries
+DELETE FROM `conditions` WHERE `ConditionTypeOrReference` = 18 AND `ConditionValue1` = 1 AND `ConditionValue2` = 0 AND `SourceEntry` IN (SELECT `id` FROM `temp_convert_spells` WHERE onlyPlayers);
+
+-- set source group if available in db
+UPDATE `conditions` SET `SourceGroup` = `ConditionValue3`, `ConditionValue3` = 0 WHERE `ConditionTypeOrReference` = 18;
+
+-- set source group in case of old default (not set) source group
+UPDATE `conditions` SET `SourceGroup` = (SELECT `effMask` FROM `temp_convert_spells` WHERE `id` = `SourceEntry`) WHERE `SourceGroup` = 0 AND `ConditionTypeOrReference` = 18;
+
+CREATE TABLE `temp_cond_vals`
+(
+ `sourceGroup` INT(11),
+ `sourceEntry` INT(11),
+ `conditionValue1` INT(11),
+ `conditionValue2` INT(11),
+ `elseGroup` INT(11) AUTO_INCREMENT,
+ PRIMARY KEY (`sourceGroup`, `sourceEntry`, `elseGroup`)
+) ENGINE=MYISAM;
+
+INSERT INTO `temp_cond_vals` (`sourceGroup`, `sourceEntry`, `conditionValue1`, `conditionValue2`) SELECT `SourceGroup`, `SourceEntry`, `ConditionValue1`, `ConditionValue2` FROM `conditions` WHERE `ConditionTypeOrReference` = 18;
+
+-- set correct else group
+UPDATE `conditions` SET `ElseGroup` = (SELECT `elseGroup` FROM `temp_cond_vals` WHERE `sourceGroup` = `conditions`.`SourceGroup` AND `sourceEntry` = `conditions`.`SourceEntry` AND `conditionValue1` = `conditions`.`ConditionValue1` AND `conditionValue2` = `conditions`.`ConditionValue2`)-1 WHERE `ConditionTypeOrReference` = 18;
+
+-- old condition type 3 (caster's minion)
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`)
+SELECT `SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `ElseGroup`, 33, 0, 1, 3 FROM `conditions` WHERE `ConditionTypeOrReference` = 18 AND `ConditionValue1` = 3;
+
+UPDATE `conditions` SET `ConditionTypeOrReference` = 31 WHERE `ConditionTypeOrReference` = 18 AND `ConditionValue1` = 3;
+
+-- old condition type 2 (dead creature)
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `NegativeCondition`)
+SELECT `SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `ElseGroup`, 36, 0, 0, 0, 1 FROM `conditions` WHERE `ConditionTypeOrReference` = 18 AND `ConditionValue1` = 2;
+
+UPDATE `conditions` SET `ConditionTypeOrReference` = 31, `ConditionValue1` = 3 WHERE `ConditionTypeOrReference` = 18 AND `ConditionValue1` = 2;
+
+-- old condition type 1 (creature)
+UPDATE `conditions` SET `ConditionTypeOrReference` = 31, `ConditionValue1` = 3 WHERE `ConditionTypeOrReference` = 18 AND `ConditionValue1` = 1 AND `ConditionValue2`;
+
+-- old condition type 1 (player)
+UPDATE `conditions` SET `ConditionTypeOrReference` = 32, `ConditionValue1` = 0x90 WHERE `ConditionTypeOrReference` = 18 AND `ConditionValue1` = 1 AND NOT `ConditionValue2`;
+
+-- old condition type 0 (gameobject)
+UPDATE `conditions` SET `ConditionTypeOrReference` = 31, `ConditionValue1` = 5 WHERE `ConditionTypeOrReference` = 18 AND `ConditionValue1` = 0;
+
+DROP TABLE `temp_convert_spells`;
+DROP TABLE `temp_cond_vals`; \ No newline at end of file
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 550814ccf3f..af0c1a07c2b 100755
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -26,6 +26,7 @@
#include "ConditionMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
// Checks if object meets the condition
// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI)
@@ -94,14 +95,14 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
}
case CONDITION_CLASS:
{
- if (Player* player = object->ToPlayer())
- condMeets = player->getClassMask() & ConditionValue1;
+ if (Unit* unit = object->ToUnit())
+ condMeets = unit->getClassMask() & ConditionValue1;
break;
}
case CONDITION_RACE:
{
- if (Player* player = object->ToPlayer())
- condMeets = player->getRaceMask() & ConditionValue1;
+ if (Unit* unit = object->ToUnit())
+ condMeets = unit->getRaceMask() & ConditionValue1;
break;
}
case CONDITION_SKILL:
@@ -153,9 +154,6 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
condMeets = ((InstanceMap*)map)->GetInstanceScript()->GetData(ConditionValue1) == ConditionValue2;
break;
}
- case CONDITION_SPELL_SCRIPT_TARGET:
- condMeets = true;//spell target condition is handled in spellsystem, here it is always true
- break;
case CONDITION_MAPID:
condMeets = object->GetMapId() == ConditionValue1;
break;
@@ -291,12 +289,153 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
return condMeets && script;
}
+uint32 Condition::GetSearcherTypeMaskForCondition()
+{
+ // build mask of types for which condition can return true
+ // this is used for speeding up gridsearches
+ if (NegativeCondition)
+ return (GRID_MAP_TYPE_MASK_ALL);
+ uint32 mask = 0;
+ switch (ConditionType)
+ {
+ case CONDITION_NONE:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_AURA:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ITEM:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ITEM_EQUIPPED:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ZONEID:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_REPUTATION_RANK:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ACHIEVEMENT:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_TEAM:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_CLASS:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_RACE:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_SKILL:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUESTREWARDED:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUESTTAKEN:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUEST_COMPLETE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUEST_NONE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ACTIVE_EVENT:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_INSTANCE_DATA:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_MAPID:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_AREAID:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_SPELL:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_LEVEL:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_DRUNKENSTATE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_NEAR_CREATURE:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_NEAR_GAMEOBJECT:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_OBJECT_ENTRY:
+ switch (ConditionValue1)
+ {
+ case TYPEID_UNIT:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE;
+ break;
+ case TYPEID_PLAYER:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case TYPEID_GAMEOBJECT:
+ mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT;
+ break;
+ case TYPEID_CORPSE:
+ mask |= GRID_MAP_TYPE_MASK_CORPSE;
+ break;
+ default:
+ break;
+ }
+ case CONDITION_TYPE_MASK:
+ if (ConditionValue1 & TYPEMASK_UNIT)
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ if (ConditionValue1 & TYPEMASK_PLAYER)
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ if (ConditionValue1 & TYPEMASK_GAMEOBJECT)
+ mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT;
+ if (ConditionValue1 & TYPEMASK_CORPSE)
+ mask |= GRID_MAP_TYPE_MASK_CORPSE;
+ break;
+ case CONDITION_RELATION_TO:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_REACTION_TO:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_DISTANCE_TO:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_ALIVE:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_HP_VAL:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_HP_PCT:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_WORLD_STATE:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_PHASEMASK:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ default:
+ ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
+ break;
+ }
+ return mask;
+}
+
uint32 Condition::GetMaxAvailableConditionTargets()
{
// returns number of targets which are available for given source type
switch(SourceType)
{
case CONDITION_SOURCE_TYPE_SPELL:
+ case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
@@ -327,8 +466,49 @@ ConditionList ConditionMgr::GetConditionReferences(uint32 refId)
return conditions;
}
+uint32 ConditionMgr::GetSearcherTypeMaskForConditionList(ConditionList const& conditions)
+{
+ if (conditions.empty())
+ return GRID_MAP_TYPE_MASK_ALL;
+ // groupId, typeMask
+ std::map<uint32, uint32> ElseGroupStore;
+ for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
+ {
+ // no point of having not loaded conditions in list
+ ASSERT((*i)->isLoaded() && "ConditionMgr::GetSearcherTypeMaskForConditionList - not yet loaded condition found in list");
+ std::map<uint32, uint32>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup);
+ // group not filled yet, fill with widest mask possible
+ if (itr == ElseGroupStore.end())
+ ElseGroupStore[(*i)->ElseGroup] = GRID_MAP_TYPE_MASK_ALL;
+ // no point of checking anymore, empty mask
+ else if (!(*itr).second)
+ continue;
+
+ if ((*i)->ReferenceId) // handle reference
+ {
+ ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId);
+ ASSERT(ref != ConditionReferenceStore.end() && "ConditionMgr::GetSearcherTypeMaskForConditionList - incorrect reference");
+ ElseGroupStore[(*i)->ElseGroup] &= GetSearcherTypeMaskForConditionList((*ref).second);
+ }
+ else // handle normal condition
+ {
+ // object will match conditions in one ElseGroupStore only when it matches all of them
+ // so, let's find a smallest possible mask which satisfies all conditions
+ ElseGroupStore[(*i)->ElseGroup] &= (*i)->GetSearcherTypeMaskForCondition();
+ }
+ }
+ // object will match condition when one of the checks in ElseGroupStore is matching
+ // so, let's include all possible masks
+ uint32 mask = 0;
+ for (std::map<uint32, uint32>::const_iterator i = ElseGroupStore.begin(); i != ElseGroupStore.end(); ++i)
+ mask |= i->second;
+
+ return mask;
+}
+
bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions)
{
+ // groupId, groupCheckPassed
std::map<uint32, bool> ElseGroupStore;
for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
{
@@ -391,6 +571,32 @@ bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, Con
return IsObjectMeetToConditionList(sourceInfo, conditions);
}
+bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const
+{
+ return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
+ sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION ||
+ sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL ||
+ sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET ||
+ sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
+}
+
+bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType) const
+{
+ return (sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
+}
+
ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry)
{
ConditionList spellCond;
@@ -487,6 +693,7 @@ void ConditionMgr::LoadConditions(bool isReload)
sLog->outString("Re-Loading `gossip_menu_option` Table for Conditions!");
sObjectMgr->LoadGossipMenuItems();
+ sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists();
}
QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, "
@@ -583,16 +790,23 @@ void ConditionMgr::LoadConditions(bool isReload)
}
//Grouping is only allowed for some types (loot templates, gossip menus, gossip items)
- if (cond->SourceGroup && !isGroupable(cond->SourceType))
+ if (cond->SourceGroup && !CanHaveSourceGroupSet(cond->SourceType))
+ {
+ sLog->outErrorDb("Condition type %u has not allowed value of SourceGroup = %u!", uint32(cond->SourceType), cond->SourceGroup);
+ delete cond;
+ continue;
+ }
+ if (cond->SourceId && !CanHaveSourceIdSet(cond->SourceType))
{
- sLog->outErrorDb("Condition type %u has not allowed grouping %u!", uint32(cond->SourceType), cond->SourceGroup);
+ sLog->outErrorDb("Condition type %u has not allowed value of SourceId = %u!", uint32(cond->SourceType), cond->SourceId);
delete cond;
continue;
}
- else if (cond->SourceGroup)
+
+ if (cond->SourceGroup)
{
bool valid = false;
- //handle grouped conditions
+ // handle grouped conditions
switch (cond->SourceType)
{
case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE:
@@ -637,6 +851,9 @@ void ConditionMgr::LoadConditions(bool isReload)
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
valid = addToGossipMenuItems(cond);
break;
+ case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
+ valid = addToSpellImplicitTargetConditions(cond);
+ break;
case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
{
//if no list for vehicle create one
@@ -771,6 +988,78 @@ bool ConditionMgr::addToGossipMenuItems(Condition* cond)
return false;
}
+bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond)
+{
+ uint32 conditionEffMask = cond->SourceGroup;
+ SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->GetSpellInfo(cond->SourceEntry));
+ ASSERT(spellInfo);
+ std::list<uint32> sharedMasks;
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ // check if effect is already a part of some shared mask
+ bool found = false;
+ for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
+ {
+ if ((1<<i) & *itr)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ // build new shared mask with found effect
+ uint32 sharedMask = (1<<i);
+ ConditionList* cmp = spellInfo->Effects[i].ImplicitTargetConditions;
+ for (uint8 effIndex = i+1; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
+ {
+ if (spellInfo->Effects[effIndex].ImplicitTargetConditions == cmp)
+ sharedMask |= 1<<effIndex;
+ }
+ sharedMasks.push_back(sharedMask);
+ }
+
+ for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
+ {
+ // some effect indexes should have same data
+ if (uint32 commonMask = *itr & conditionEffMask)
+ {
+ uint8 firstEffIndex = 0;
+ for (; firstEffIndex < MAX_SPELL_EFFECTS; ++firstEffIndex)
+ if ((1<<firstEffIndex) & *itr)
+ break;
+
+ // get shared data
+ ConditionList* sharedList = spellInfo->Effects[firstEffIndex].ImplicitTargetConditions;
+
+ // there's already data entry for that sharedMask
+ if (sharedList)
+ {
+ // we have overlapping masks in db
+ if (conditionEffMask != *itr)
+ {
+ sLog->outErrorDb("SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set - "
+ "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->SourceEntry, cond->SourceGroup);
+ return false;
+ }
+ }
+ // no data for shared mask, we can create new submask
+ else
+ {
+ // add new list, create new shared mask
+ sharedList = new ConditionList();
+ for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i)
+ if ((1<<i) & commonMask)
+ spellInfo->Effects[i].ImplicitTargetConditions = sharedList;
+ }
+ sharedList->push_back(cond);
+ break;
+ }
+ }
+ return true;
+}
+
bool ConditionMgr::isSourceTypeValid(Condition* cond)
{
if (cond->SourceType == CONDITION_SOURCE_TYPE_NONE || cond->SourceType >= CONDITION_SOURCE_TYPE_MAX)
@@ -985,64 +1274,48 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
}
break;
}
- case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET:
+ case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
{
- if (cond->ConditionType != CONDITION_SPELL_SCRIPT_TARGET)
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry);
+ if (!spellInfo)
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_SPELL_SCRIPT_TARGET(18) is valid for CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET(14), ignoring.", cond->SourceEntry, uint32(cond->ConditionType));
+ sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
return false;
}
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry);
- if (!spellProto)
+ if ((cond->SourceGroup > MAX_EFFECT_MASK) || !cond->SourceGroup)
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
+ sLog->outErrorDb("SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set , ignoring.", cond->SourceEntry, cond->SourceGroup);
return false;
}
- bool targetfound = false;
+ uint32 origGroup = cond->SourceGroup;
+
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- if (spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_SRC_AREA_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_SRC_AREA ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_SRC_AREA ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_DEST_AREA ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_DEST_AREA ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_DEST_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_DEST_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CONE_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_CONE_ENTRY)
+ if (!((1<<i) & cond->SourceGroup))
+ continue;
+
+ switch (spellInfo->Effects[i].TargetA.GetSelectionCategory())
{
- targetfound = true;
- //break;
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ case TARGET_SELECT_CATEGORY_CONE:
+ case TARGET_SELECT_CATEGORY_AREA:
+ continue;
}
- else if (cond->ConditionValue3 & (1 << i))
+ switch (spellInfo->Effects[i].TargetB.GetSelectionCategory())
{
- cond->ConditionValue3 &= ~(1 << i);
- sLog->outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DEST_NEARBY_ENTRY (46)"
- ", TARGET_UNIT_SRC_AREA_ENTRY(7), TARGET_UNIT_DEST_AREA_ENTRY(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)"
- "TARGET_GAMEOBJECT_SRC_AREA(51), TARGET_GAMEOBJECT_DEST_AREA(52) in effect %u", cond->SourceEntry, uint32(i));
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ case TARGET_SELECT_CATEGORY_CONE:
+ case TARGET_SELECT_CATEGORY_AREA:
+ continue;
}
+ sLog->outErrorDb("SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i));
+ cond->SourceGroup &= ~(1<<i);
}
- if (!targetfound && !cond->ConditionValue3) // cond->mConditionValue3 already errored up there
- {
- sLog->outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DEST_NEARBY_ENTRY (46)"
- ", TARGET_UNIT_SRC_AREA_ENTRY(7), TARGET_UNIT_DEST_AREA_ENTRY(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)"
- "TARGET_GAMEOBJECT_SRC_AREA(51), TARGET_GAMEOBJECT_DEST_AREA(52)", cond->SourceEntry);
- return false;
- }
- if ((cond->ConditionValue1 == SPELL_TARGET_TYPE_DEAD) && !spellProto->IsAllowingDeadTarget())
- {
- sLog->outErrorDb("SourceEntry %u in `condition` table does have SPELL_TARGET_TYPE_DEAD specified but spell does not have SPELL_ATTR2_CAN_TARGET_DEAD", cond->SourceEntry);
+ // all effects were removed, no need to add the condition at all
+ if (!cond->SourceGroup)
return false;
- }
break;
}
case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
@@ -1318,46 +1591,6 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
sLog->outErrorDb("Race condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_SPELL_SCRIPT_TARGET:
- {
- if (cond->ConditionValue1 >= MAX_SPELL_TARGET_TYPE)
- {
- sLog->outErrorDb("SpellTarget condition has non existing spell target type (%u), skipped", cond->ConditionValue1);
- return false;
- }
-
- switch (cond->ConditionValue1)
- {
- case SPELL_TARGET_TYPE_GAMEOBJECT:
- {
- if (cond->ConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->ConditionValue2))
- {
- sLog->outErrorDb("SpellTarget condition has non existing gameobject (%u) as target, skipped", cond->ConditionValue2);
- return false;
- }
- break;
- }
- case SPELL_TARGET_TYPE_CONTROLLED:
- case SPELL_TARGET_TYPE_CREATURE:
- case SPELL_TARGET_TYPE_DEAD:
- {
- if (cond->ConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->ConditionValue2))
- {
- sLog->outErrorDb("SpellTarget condition has non existing creature template entry (%u) as target, skipped", cond->ConditionValue2);
- return false;
- }
-
- const CreatureTemplate* cInfo = sObjectMgr->GetCreatureTemplate(cond->ConditionValue2);
- if (cond->SourceEntry == 30427 && !cInfo->SkinLootId)
- {
- sLog->outErrorDb("SpellTarget condition has creature entry %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!, skipped", cond->ConditionValue2);
- return false;
- }
- break;
- }
- }
- break;
- }
case CONDITION_MAPID:
{
MapEntry const* me = sMapStore.LookupEntry(cond->ConditionValue1);
@@ -1598,6 +1831,9 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
sLog->outErrorDb("Phasemask condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
+ case CONDITION_UNUSED_18:
+ sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_18 in `conditions` table - ignoring");
+ return false;
case CONDITION_UNUSED_19:
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring");
return false;
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 9911aa2a98a..a1c6146d0cf 100755
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -48,7 +48,7 @@ enum ConditionTypes
CONDITION_CLASS = 15, // class 0 0 true if player's class is equal to class
CONDITION_RACE = 16, // race 0 0 true if player's race is equal to race
CONDITION_ACHIEVEMENT = 17, // achievement_id 0 0 true if achievement is complete
- CONDITION_SPELL_SCRIPT_TARGET = 18, // SpellScriptTargetType, TargetEntry, 0
+ CONDITION_UNUSED_18 = 18, //
CONDITION_UNUSED_19 = 19, //
CONDITION_UNUSED_20 = 20, //
CONDITION_UNUSED_21 = 21, //
@@ -87,7 +87,7 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE = 10,
CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE = 11,
CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE = 12,
- CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET = 13,
+ CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET = 13,
CONDITION_SOURCE_TYPE_GOSSIP_MENU = 14,
CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15,
CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16,
@@ -173,6 +173,7 @@ struct Condition
}
bool Meets(ConditionSourceInfo& sourceInfo);
+ uint32 GetSearcherTypeMaskForCondition();
bool isLoaded() const { return ConditionType > CONDITION_NONE || ReferenceId; }
uint32 GetMaxAvailableConditionTargets();
};
@@ -198,9 +199,12 @@ class ConditionMgr
bool isConditionTypeValid(Condition* cond);
ConditionList GetConditionReferences(uint32 refId);
+ uint32 GetSearcherTypeMaskForConditionList(ConditionList const& conditions);
bool IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions);
bool IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions);
bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions);
+ bool CanHaveSourceGroupSet(ConditionSourceType sourceType) const;
+ bool CanHaveSourceIdSet(ConditionSourceType sourceType) const;
ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry);
ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId);
ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType);
@@ -211,29 +215,10 @@ class ConditionMgr
bool addToLootTemplate(Condition* cond, LootTemplate* loot);
bool addToGossipMenus(Condition* cond);
bool addToGossipMenuItems(Condition* cond);
+ bool addToSpellImplicitTargetConditions(Condition* cond);
bool IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions);
- bool isGroupable(ConditionSourceType sourceType) const
- {
- return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
- sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION ||
sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT ||
- sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL ||
- sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
- }
-
void Clean(); // free up resources
std::list<Condition*> AllocatedMemoryStore; // some garbage collection :)
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index aadf9f44b0b..c98364ecb2d 100755
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1085,9 +1085,9 @@ bool Object::PrintIndexError(uint32 index, bool set) const
return false;
}
-bool Position::HasInLine(Unit const* target, float distance, float width) const
+bool Position::HasInLine(WorldObject const* target, float width) const
{
- if (!HasInArc(M_PI, target) || !target->IsWithinDist3d(m_positionX, m_positionY, m_positionZ, distance))
+ if (!HasInArc(M_PI, target))
return false;
width += target->GetObjectSize();
float angle = GetRelativeAngle(target);
@@ -1502,14 +1502,14 @@ bool WorldObject::IsInBetween(const WorldObject* obj1, const WorldObject* obj2,
return (size * size) >= GetExactDist2dSq(obj1->GetPositionX() + cos(angle) * dist, obj1->GetPositionY() + sin(angle) * dist);
}
-bool WorldObject::isInFront(WorldObject const* target, float distance, float arc) const
+bool WorldObject::isInFront(WorldObject const* target, float arc) const
{
- return IsWithinDist(target, distance) && HasInArc(arc, target);
+ return HasInArc(arc, target);
}
-bool WorldObject::isInBack(WorldObject const* target, float distance, float arc) const
+bool WorldObject::isInBack(WorldObject const* target, float arc) const
{
- return IsWithinDist(target, distance) && !HasInArc(2 * M_PI - arc, target);
+ return !HasInArc(2 * M_PI - arc, target);
}
void WorldObject::GetRandomPoint(const Position &pos, float distance, float &rand_x, float &rand_y, float &rand_z) const
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index c14b7599d5f..7b3fcc4a337 100755
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -451,7 +451,7 @@ struct Position
bool IsInDist(const Position* pos, float dist) const
{ return GetExactDistSq(pos) < dist * dist; }
bool HasInArc(float arcangle, const Position* pos) const;
- bool HasInLine(Unit const* target, float distance, float width) const;
+ bool HasInLine(WorldObject const* target, float width) const;
std::string ToString() const;
};
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
@@ -707,8 +707,8 @@ class WorldObject : public Object, public WorldLocation
bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const;
bool IsInRange2d(float x, float y, float minRange, float maxRange) const;
bool IsInRange3d(float x, float y, float z, float minRange, float maxRange) const;
- bool isInFront(WorldObject const* target, float distance, float arc = M_PI) const;
- bool isInBack(WorldObject const* target, float distance, float arc = M_PI) const;
+ bool isInFront(WorldObject const* target, float arc = M_PI) const;
+ bool isInBack(WorldObject const* target, float arc = M_PI) const;
bool IsInBetween(const WorldObject* obj1, const WorldObject* obj2, float size = 0) const;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 47c3c1a9395..0e3e2f593fa 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -10004,6 +10004,7 @@ Unit* Unit::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo)
&& _IsValidAttackTarget(magnet, spellInfo)
&& IsWithinLOSInMap(magnet))
{
+ // TODO: handle this charge drop by proc in cast phase on explicit target
(*itr)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
return magnet;
}
@@ -16178,26 +16179,6 @@ bool Unit::IsInRaidWith(Unit const* unit) const
return false;
}
-bool Unit::IsTargetMatchingCheck(Unit const* target, SpellTargetSelectionCheckTypes check) const
-{
- switch (check)
- {
- case TARGET_SELECT_CHECK_ENEMY:
- if (IsControlledByPlayer())
- return !IsFriendlyTo(target);
- else
- return IsHostileTo(target);
- case TARGET_SELECT_CHECK_ALLY:
- return IsFriendlyTo(target);
- case TARGET_SELECT_CHECK_PARTY:
- return IsInPartyWith(target);
- case TARGET_SELECT_CHECK_RAID:
- return IsInRaidWith(target);
- default:
- return true;
- }
-}
-
void Unit::GetRaidMember(std::list<Unit*> &nearMembers, float radius)
{
Player* owner = GetCharmerOrOwnerPlayerOrPlayerItself();
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 66b0bcbeb54..e55141a3bae 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1394,7 +1394,6 @@ class Unit : public WorldObject
bool IsNeutralToAll() const;
bool IsInPartyWith(Unit const* unit) const;
bool IsInRaidWith(Unit const* unit) const;
- bool IsTargetMatchingCheck(Unit const* target, SpellTargetSelectionCheckTypes check) const;
void GetPartyMemberInDist(std::list<Unit*> &units, float dist);
void GetPartyMembers(std::list<Unit*> &units);
void GetRaidMember(std::list<Unit*> &units, float dist);
diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h
index 8651680cb49..d096bb7ab63 100644
--- a/src/server/game/Grids/GridDefines.h
+++ b/src/server/game/Grids/GridDefines.h
@@ -65,6 +65,16 @@ typedef GridRefManager<DynamicObject> DynamicObjectMapType;
typedef GridRefManager<GameObject> GameObjectMapType;
typedef GridRefManager<Player> PlayerMapType;
+enum GridMapTypeMask
+{
+ GRID_MAP_TYPE_MASK_CORPSE = 0x01,
+ GRID_MAP_TYPE_MASK_CREATURE = 0x02,
+ GRID_MAP_TYPE_MASK_DYNAMICOBJECT = 0x04,
+ GRID_MAP_TYPE_MASK_GAMEOBJECT = 0x08,
+ GRID_MAP_TYPE_MASK_PLAYER = 0x10,
+ GRID_MAP_TYPE_MASK_ALL = 0x1F
+};
+
typedef Grid<Player, AllWorldObjectTypes, AllGridObjectTypes> GridType;
typedef NGrid<MAX_NUMBER_OF_CELLS, Player, AllWorldObjectTypes, AllGridObjectTypes> NGridType;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index 2446e9d4276..17d3066e64d 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -343,24 +343,17 @@ bool AnyDeadUnitObjectInRangeCheck::operator()(Creature* u)
bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Player* u)
{
- return AnyDeadUnitObjectInRangeCheck::operator()(u)
- && (i_spellInfo->CheckTarget(i_searchObj, u, true) == SPELL_CAST_OK)
- && i_searchObj->IsTargetMatchingCheck(u, i_check);
+ return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u);
}
bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Corpse* u)
{
- Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID());
- return owner && AnyDeadUnitObjectInRangeCheck::operator()(u)
- && (i_spellInfo->CheckTarget(i_searchObj, owner, true) == SPELL_CAST_OK)
- && i_searchObj->IsTargetMatchingCheck(owner, i_check);
+ return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u);
}
bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Creature* u)
{
- return AnyDeadUnitObjectInRangeCheck::operator()(u)
- && (i_spellInfo->CheckTarget(i_searchObj, u, true) == SPELL_CAST_OK)
- && i_searchObj->IsTargetMatchingCheck(u, i_check);
+ return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u);
}
template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &);
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 12e3fda0484..21f27d6a453 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -30,6 +30,7 @@
#include "Player.h"
#include "Unit.h"
#include "CreatureAI.h"
+#include "Spell.h"
class Player;
//class Map;
@@ -168,12 +169,33 @@ namespace Trinity
template<class Check>
struct WorldObjectSearcher
{
+ uint32 i_mapTypeMask;
uint32 i_phaseMask;
WorldObject* &i_object;
Check &i_check;
- WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check)
- : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
+ WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check), i_mapTypeMask(mapTypeMask) {}
+
+ void Visit(GameObjectMapType &m);
+ void Visit(PlayerMapType &m);
+ void Visit(CreatureMapType &m);
+ void Visit(CorpseMapType &m);
+ void Visit(DynamicObjectMapType &m);
+
+ template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
+ };
+
+ template<class Check>
+ struct WorldObjectLastSearcher
+ {
+ uint32 i_mapTypeMask;
+ uint32 i_phaseMask;
+ WorldObject* &i_object;
+ Check &i_check;
+
+ WorldObjectLastSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
+ : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check), i_mapTypeMask(mapTypeMask) {}
void Visit(GameObjectMapType &m);
void Visit(PlayerMapType &m);
@@ -187,12 +209,13 @@ namespace Trinity
template<class Check>
struct WorldObjectListSearcher
{
+ uint32 i_mapTypeMask;
uint32 i_phaseMask;
std::list<WorldObject*> &i_objects;
Check& i_check;
- WorldObjectListSearcher(WorldObject const* searcher, std::list<WorldObject*> &objects, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {}
+ WorldObjectListSearcher(WorldObject const* searcher, std::list<WorldObject*> &objects, Check & check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
+ : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check), i_mapTypeMask(mapTypeMask) {}
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
@@ -206,14 +229,17 @@ namespace Trinity
template<class Do>
struct WorldObjectWorker
{
+ uint32 i_mapTypeMask;
uint32 i_phaseMask;
Do const& i_do;
- WorldObjectWorker(WorldObject const* searcher, Do const& _do)
- : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {}
+ WorldObjectWorker(WorldObject const* searcher, Do const& _do, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
+ : i_phaseMask(searcher->GetPhaseMask()), i_do(_do), i_mapTypeMask(mapTypeMask) {}
void Visit(GameObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
+ return;
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
@@ -221,12 +247,16 @@ namespace Trinity
void Visit(PlayerMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
+ return;
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
}
void Visit(CreatureMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
+ return;
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
@@ -234,6 +264,8 @@ namespace Trinity
void Visit(CorpseMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
+ return;
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
@@ -241,6 +273,8 @@ namespace Trinity
void Visit(DynamicObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
+ return;
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
@@ -527,73 +561,11 @@ namespace Trinity
// CHECKS && DO classes
// WorldObject check classes
- class RaiseDeadObjectCheck
- {
- public:
- RaiseDeadObjectCheck(Unit* source, float range) : _source(source), _range(range) {}
- bool operator()(Creature* u)
- {
- if (_source->GetTypeId() != TYPEID_PLAYER || !((Player*)_source)->isHonorOrXPTarget(u) ||
- u->getDeathState() != CORPSE ||
- (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 ||
- (u->GetDisplayId() != u->GetNativeDisplayId()))
- return false;
-
- return _source->IsWithinDistInMap(u, _range);
- }
- bool operator()(Player* u)
- {
- if (_source == u || _source->GetTypeId() != TYPEID_PLAYER || !((Player*)_source)->isHonorOrXPTarget(u) ||
- u->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) || u->isInFlight() || !u->isDead() ||
- (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0)
- return false;
- return _source->IsWithinDistInMap(u, _range);
- }
-
- bool operator()(Corpse* u)
- {
- if (_source->GetTypeId() != TYPEID_PLAYER || u->GetType() == CORPSE_BONES)
- return false;
-
- return _source->IsWithinDistInMap(u, _range);
- }
- template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
- private:
- Unit* const _source;
- float _range;
- };
-
- class ExplodeCorpseObjectCheck
- {
- public:
- ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {}
- bool operator()(Player* u)
- {
- if (u->getDeathState() != CORPSE || u->isInFlight() ||
- u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId()))
- return false;
-
- return i_funit->IsWithinDistInMap(u, i_range);
- }
- bool operator()(Creature* u)
- {
- if (u->getDeathState() != CORPSE || u->isInFlight() ||
- (u->GetDisplayId() != u->GetNativeDisplayId()) ||
- (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0)
- return false;
-
- return i_funit->IsWithinDistInMap(u, i_range);
- }
- template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
- private:
- Unit* const i_funit;
- float i_range;
- };
class AnyDeadUnitObjectInRangeCheck
{
public:
- AnyDeadUnitObjectInRangeCheck(Unit const* searchObj, float range) : i_searchObj(searchObj), i_range(range) {}
+ AnyDeadUnitObjectInRangeCheck(Unit* searchObj, float range) : i_searchObj(searchObj), i_range(range) {}
bool operator()(Player* u);
bool operator()(Corpse* u);
bool operator()(Creature* u);
@@ -606,15 +578,16 @@ namespace Trinity
class AnyDeadUnitSpellTargetInRangeCheck : public AnyDeadUnitObjectInRangeCheck
{
public:
- AnyDeadUnitSpellTargetInRangeCheck(Unit const* searchObj, float range, SpellInfo const* spellInfo, SpellTargetSelectionCheckTypes check)
- : AnyDeadUnitObjectInRangeCheck(searchObj, range), i_spellInfo(spellInfo), i_check(check) {}
+ AnyDeadUnitSpellTargetInRangeCheck(Unit* searchObj, float range, SpellInfo const* spellInfo, SpellTargetCheckTypes check)
+ : AnyDeadUnitObjectInRangeCheck(searchObj, range), i_spellInfo(spellInfo), i_check(searchObj, searchObj, spellInfo, check, NULL)
+ {}
bool operator()(Player* u);
bool operator()(Corpse* u);
bool operator()(Creature* u);
template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
protected:
SpellInfo const* i_spellInfo;
- SpellTargetSelectionCheckTypes i_check;
+ WorldObjectSpellTargetCheck i_check;
};
// WorldObject do classes
diff --git a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
index 34fe7757c5f..40b3863679b 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
@@ -51,6 +51,9 @@ inline void Trinity::ObjectUpdater::Visit(CreatureMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
+ return;
+
// already found
if (i_object)
return;
@@ -71,6 +74,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
+ return;
+
// already found
if (i_object)
return;
@@ -91,6 +97,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
+ return;
+
// already found
if (i_object)
return;
@@ -111,6 +120,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
+ return;
+
// already found
if (i_object)
return;
@@ -131,6 +143,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
+ return;
+
// already found
if (i_object)
return;
@@ -148,9 +163,93 @@ void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
}
}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(GameObjectMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
+ return;
+
+ for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(PlayerMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
+ return;
+
+ for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(CreatureMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
+ return;
+
+ for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(CorpseMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
+ return;
+
+ for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(DynamicObjectMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
+ return;
+
+ for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
+ return;
+
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
@@ -160,6 +259,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m)
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
+ return;
+
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
@@ -169,6 +271,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m)
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
+ return;
+
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
@@ -178,6 +283,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m)
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
+ return;
+
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
@@ -187,6 +295,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m)
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
+ return;
+
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 53356772ff6..207ab2b663d 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -592,19 +592,6 @@ Spell::~Spell()
CheckEffectExecuteData();
}
-template<typename T>
-WorldObject* Spell::FindCorpseUsing()
-{
- // non-standard target selection
- float max_range = m_spellInfo->GetMaxRange(false);
-
- WorldObject* result = NULL;
- T u_check(m_caster, max_range);
- Trinity::WorldObjectSearcher<T> searcher(m_caster, result, u_check);
- m_caster->GetMap()->VisitFirstFound(m_caster->GetPositionX(), m_caster->GetPositionY(), max_range, searcher);
- return result;
-}
-
void Spell::InitExplicitTargets(SpellCastTargets const& targets)
{
m_targets = targets;
@@ -707,7 +694,8 @@ void Spell::SelectSpellTargets()
{
// select targets for cast phase
SelectExplicitTargets();
- uint32 processedTargets = 0;
+
+ uint32 processedAreaEffectsMask = 0;
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
// not call for empty effect.
@@ -715,9 +703,6 @@ void Spell::SelectSpellTargets()
if (!m_spellInfo->Effects[i].IsEffect())
continue;
- if (processedTargets & (1 << i))
- continue;
-
// set expected type of implicit targets to be sent to client
uint32 implicitTargetMask = GetTargetFlagMask(m_spellInfo->Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(m_spellInfo->Effects[i].TargetB.GetObjectType());
if (implicitTargetMask & TARGET_FLAG_UNIT)
@@ -725,13 +710,8 @@ void Spell::SelectSpellTargets()
if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM))
m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT);
- uint32 targetA = m_spellInfo->Effects[i].TargetA.GetTarget();
- uint32 targetB = m_spellInfo->Effects[i].TargetB.GetTarget();
-
- if (targetA)
- processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetA);
- if (targetB)
- processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetB);
+ SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetA, processedAreaEffectsMask);
+ SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetB, processedAreaEffectsMask);
// Select targets of effect based on effect type
// those are used when no valid target could be added for spell effect based on spell target type
@@ -793,6 +773,920 @@ void Spell::SelectSpellTargets()
}
}
+void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask)
+{
+ if (!targetType.GetTarget())
+ return;
+
+ uint32 effectMask = 1 << effIndex;
+ // set the same target list for all effects
+ // some spells appear to need this, however this requires more research
+ switch (targetType.GetSelectionCategory())
+ {
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ case TARGET_SELECT_CATEGORY_CONE:
+ case TARGET_SELECT_CATEGORY_AREA:
+ // targets for effect already selected
+ if (effectMask & processedEffectMask)
+ return;
+ // choose which targets we can select at once
+ for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j)
+ if (GetSpellInfo()->Effects[effIndex].TargetA.GetTarget() == GetSpellInfo()->Effects[j].TargetA.GetTarget() &&
+ GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == GetSpellInfo()->Effects[j].TargetB.GetTarget() &&
+ GetSpellInfo()->Effects[effIndex].ImplicitTargetConditions == GetSpellInfo()->Effects[j].ImplicitTargetConditions &&
+ GetSpellInfo()->Effects[effIndex].CalcRadius(m_caster) == GetSpellInfo()->Effects[j].CalcRadius(m_caster))
+ effectMask |= 1 << j;
+ processedEffectMask |= effectMask;
+ }
+
+ switch(targetType.GetSelectionCategory())
+ {
+ case TARGET_SELECT_CATEGORY_CHANNEL:
+ SelectImplicitChannelTargets(effIndex, targetType);
+ break;
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ SelectImplicitNearbyTargets(effIndex, targetType, effectMask);
+ break;
+ case TARGET_SELECT_CATEGORY_CONE:
+ SelectImplicitConeTargets(effIndex, targetType, effectMask);
+ break;
+ case TARGET_SELECT_CATEGORY_AREA:
+ SelectImplicitAreaTargets(effIndex, targetType, effectMask);
+ break;
+ case TARGET_SELECT_CATEGORY_DEFAULT:
+ switch (targetType.GetObjectType())
+ {
+ case TARGET_OBJECT_TYPE_SRC:
+ switch(targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_CASTER:
+ m_targets.SetSrc(*m_caster);
+ break;
+ default:
+ ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_SRC");
+ break;
+ }
+ break;
+ case TARGET_OBJECT_TYPE_DEST:
+ switch(targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_CASTER:
+ SelectImplicitCasterDestTargets(effIndex, targetType);
+ break;
+ case TARGET_REFERENCE_TYPE_TARGET:
+ SelectImplicitCasterDestTargets(effIndex, targetType);
+ break;
+ case TARGET_REFERENCE_TYPE_DEST:
+ SelectImplicitDestDestTargets(effIndex, targetType);
+ break;
+ default:
+ ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST");
+ break;
+ }
+ break;
+ default:
+ switch(targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_CASTER:
+ SelectImplicitCasterObjectTargets(effIndex, targetType);
+ break;
+ case TARGET_REFERENCE_TYPE_TARGET:
+ SelectImplicitTargetObjectTargets(effIndex, targetType);
+ break;
+ default:
+ ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT");
+ break;
+ }
+ break;
+ }
+ break;
+ case TARGET_SELECT_CATEGORY_NYI:
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: target type %u, found in spellID %u, effect %u is not implemented yet!", m_spellInfo->Id, effIndex, targetType.GetTarget());
+ break;
+ default:
+ ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target category");
+ break;
+ }
+}
+
+void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
+ {
+ ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target reference type");
+ return;
+ }
+
+ Spell* channeledSpell = m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
+ if (!channeledSpell)
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::SelectImplicitChannelTargets: cannot find channel spell for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
+ return;
+ }
+ switch (targetType.GetType())
+ {
+ case TARGET_UNIT_CHANNEL_TARGET:
+ // unit target may be no longer avalible - teleported out of map for example
+ if (Unit* target = Unit::GetUnit(*m_caster, channeledSpell->m_targets.GetUnitTargetGUID()))
+ AddUnitTarget(target, 1 << effIndex);
+ else
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
+ break;
+ case TARGET_DEST_CHANNEL_TARGET:
+ if (channeledSpell->m_targets.HasDst())
+ m_targets.SetDst(channeledSpell->m_targets);
+ else if (WorldObject* target = ObjectAccessor::GetWorldObject(*m_caster, channeledSpell->m_targets.GetObjectTargetGUID()))
+ m_targets.SetDst(*target);
+ else
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
+ break;
+ case TARGET_DEST_CHANNEL_CASTER:
+ m_targets.SetDst(*channeledSpell->GetCaster());
+ break;
+ default:
+ ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target type");
+ break;
+ }
+}
+
+void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask)
+{
+ if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
+ {
+ ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target reference type");
+ return;
+ }
+
+ float range;
+ switch (targetType.GetCheckType())
+ {
+ case TARGET_CHECK_ENEMY:
+ range = m_spellInfo->GetMaxRange(false, m_caster, this);
+ break;
+ case TARGET_CHECK_ALLY:
+ case TARGET_CHECK_PARTY:
+ case TARGET_CHECK_RAID:
+ case TARGET_CHECK_RAID_CLASS:
+ range = m_spellInfo->GetMaxRange(true, m_caster, this);
+ break;
+ case TARGET_CHECK_ENTRY:
+ case TARGET_CHECK_DEFAULT:
+ range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive(), m_caster, this);
+ break;
+ default:
+ ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented selection check type");
+ break;
+ }
+
+ ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
+
+ // handle emergency case - try to use other provided targets if no conditions provided
+ if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && !condList || condList->empty())
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID %u, effect %u - selecting default targets", m_spellInfo->Id, effIndex);
+ switch (targetType.GetObjectType())
+ {
+ case TARGET_OBJECT_TYPE_GOBJ:
+ if (m_spellInfo->RequiresSpellFocus)
+ {
+ if (focusObject)
+ AddGOTarget(focusObject, effMask);
+ return;
+ }
+ break;
+ case TARGET_OBJECT_TYPE_DEST:
+ if (m_spellInfo->RequiresSpellFocus)
+ {
+ if (focusObject)
+ m_targets.SetDst(*focusObject);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ WorldObject* target = SearchNearbyTarget(range, targetType.GetObjectType(), targetType.GetCheckType(), condList);
+ if (!target)
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::SelectImplicitNearbyTargets: cannot find nearby target for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
+ return;
+ }
+
+ switch (targetType.GetObjectType())
+ {
+ case TARGET_OBJECT_TYPE_UNIT:
+ if (Unit* unitTarget = target->ToUnit())
+ AddUnitTarget(unitTarget, effMask, false);
+ break;
+ case TARGET_OBJECT_TYPE_GOBJ:
+ if (GameObject* gobjTarget = target->ToGameObject())
+ AddGOTarget(gobjTarget, effMask);
+ break;
+ case TARGET_OBJECT_TYPE_DEST:
+ m_targets.SetDst(*target);
+ break;
+ default:
+ ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target object type");
+ break;
+ }
+
+ SelectImplicitChainTargets(effIndex, targetType, target, effMask);
+}
+
+void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask)
+{
+ if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
+ {
+ ASSERT(false && "Spell::SelectImplicitConeTargets: received not implemented target reference type");
+ return;
+ }
+ std::list<WorldObject*> targets;
+ SpellTargetObjectTypes objectType = targetType.GetObjectType();
+ SpellTargetCheckTypes selectionType = targetType.GetCheckType();
+ ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
+ float coneAngle = M_PI/2;
+ float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
+
+ if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList))
+ {
+ Trinity::WorldObjectSpellConeTargetCheck check(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList);
+ Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> searcher(m_caster, targets, check, containerTypeMask);
+ SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, radius);
+
+ if (!targets.empty())
+ {
+ // Other special target selection goes here
+ if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
+ {
+ Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
+ for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
+ if ((*j)->IsAffectedOnSpell(m_spellInfo))
+ maxTargets += (*j)->GetAmount();
+
+ Trinity::RandomResizeList(targets, maxTargets);
+ }
+
+ // for compability with older code - add only unit and go targets
+ // TODO: remove this
+ std::list<Unit*> unitTargets;
+ std::list<GameObject*> gObjTargets;
+
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ {
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ unitTargets.push_back(unitTarget);
+ else if (GameObject* gObjTarget = (*itr)->ToGameObject())
+ gObjTargets.push_back(gObjTarget);
+ }
+
+ CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex);
+
+ for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
+ AddUnitTarget(*itr, effMask, false);
+
+ for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr)
+ AddGOTarget(*itr, effMask);
+ }
+ }
+}
+
+void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask)
+{
+ Unit* referer = NULL;
+ switch (targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_SRC:
+ case TARGET_REFERENCE_TYPE_DEST:
+ case TARGET_REFERENCE_TYPE_CASTER:
+ referer = m_caster;
+ break;
+ case TARGET_REFERENCE_TYPE_TARGET:
+ referer = m_targets.GetUnitTarget();
+ break;
+ case TARGET_REFERENCE_TYPE_LAST:
+ {
+ // find last added target for this effect
+ for (std::list<TargetInfo>::reverse_iterator ihit = m_UniqueTargetInfo.rbegin(); ihit != m_UniqueTargetInfo.rend(); ++ihit)
+ {
+ if (ihit->effectMask & (1<<effIndex))
+ {
+ referer = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
+ return;
+ }
+ if (!referer)
+ return;
+
+ Position const* center = NULL;
+ switch (targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_SRC:
+ center = m_targets.GetSrc();
+ break;
+ case TARGET_REFERENCE_TYPE_DEST:
+ center = m_targets.GetDst();
+ break;
+ case TARGET_REFERENCE_TYPE_CASTER:
+ case TARGET_REFERENCE_TYPE_TARGET:
+ case TARGET_REFERENCE_TYPE_LAST:
+ center = referer;
+ break;
+ default:
+ ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
+ return;
+ }
+ std::list<WorldObject*> targets;
+ float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
+ SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
+
+ // Custom entries
+ // TODO: remove those
+ switch (m_spellInfo->Id)
+ {
+ case 46584: // Raise Dead
+ {
+ if (Player* playerCaster = m_caster->ToPlayer())
+ {
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ {
+ switch ((*itr)->GetTypeId())
+ {
+ case TYPEID_UNIT:
+ case TYPEID_PLAYER:
+ {
+ Unit* unitTarget = (*itr)->ToUnit();
+ if (unitTarget->isAlive() || !playerCaster->isHonorOrXPTarget(unitTarget)
+ || ((unitTarget->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0)
+ || (unitTarget->GetDisplayId() != unitTarget->GetNativeDisplayId()))
+ break;
+ AddUnitTarget(unitTarget, effMask, false);
+ // no break;
+ }
+ case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet
+ m_targets.SetDst(*(*itr));
+ return; // nothing more to do here
+ default:
+ break;
+ }
+ }
+ }
+ return; // don't add targets to target map
+ }
+ // Corpse Explosion
+ case 49158:
+ case 51325:
+ case 51326:
+ case 51327:
+ case 51328:
+ // check if our target is not valid (spell can target ghoul or dead unit)
+ if (!(m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId() &&
+ ((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID())
+ || m_targets.GetUnitTarget()->isDead())))
+ {
+ // remove existing targets
+ CleanupTargetList();
+
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ {
+ switch ((*itr)->GetTypeId())
+ {
+ case TYPEID_UNIT:
+ case TYPEID_PLAYER:
+ if (!(*itr)->ToUnit()->isDead())
+ break;
+ AddUnitTarget((*itr)->ToUnit(), 1 << effIndex, false);
+ return;
+ default:
+ break;
+ }
+ }
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
+ SendCastResult(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW);
+ finish(false);
+ }
+ return;
+ default:
+ break;
+ }
+ std::list<Unit*> unitTargets;
+ std::list<GameObject*> gObjTargets;
+ // for compability with older code - add only unit and go targets
+ // TODO: remove this
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ {
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ unitTargets.push_back(unitTarget);
+ else if (GameObject* gObjTarget = (*itr)->ToGameObject())
+ gObjTargets.push_back(gObjTarget);
+ }
+
+ if (!unitTargets.empty())
+ {
+ // Special target selection for smart heals and energizes
+ uint32 maxSize = 0;
+ int32 power = -1;
+ switch (m_spellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ switch (m_spellInfo->Id)
+ {
+ case 52759: // Ancestral Awakening
+ case 71610: // Echoes of Light (Althor's Abacus normal version)
+ case 71641: // Echoes of Light (Althor's Abacus heroic version)
+ maxSize = 1;
+ power = POWER_HEALTH;
+ break;
+ case 54968: // Glyph of Holy Light
+ maxSize = m_spellInfo->MaxAffectedTargets;
+ power = POWER_HEALTH;
+ break;
+ case 57669: // Replenishment
+ // In arenas Replenishment may only affect the caster
+ if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->InArena())
+ {
+ unitTargets.clear();
+ unitTargets.push_back(m_caster);
+ break;
+ }
+ maxSize = 10;
+ power = POWER_MANA;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SPELLFAMILY_PRIEST:
+ if (m_spellInfo->SpellFamilyFlags[0] == 0x10000000) // Circle of Healing
+ {
+ maxSize = m_caster->HasAura(55675) ? 6 : 5; // Glyph of Circle of Healing
+ power = POWER_HEALTH;
+ }
+ else if (m_spellInfo->Id == 64844) // Divine Hymn
+ {
+ maxSize = 3;
+ power = POWER_HEALTH;
+ }
+ else if (m_spellInfo->Id == 64904) // Hymn of Hope
+ {
+ maxSize = 3;
+ power = POWER_MANA;
+ }
+ else
+ break;
+
+ // Remove targets outside caster's raid
+ for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();)
+ {
+ if (!(*itr)->IsInRaidWith(m_caster))
+ itr = unitTargets.erase(itr);
+ else
+ ++itr;
+ }
+ break;
+ case SPELLFAMILY_DRUID:
+ if (m_spellInfo->SpellFamilyFlags[1] == 0x04000000) // Wild Growth
+ {
+ maxSize = m_caster->HasAura(62970) ? 6 : 5; // Glyph of Wild Growth
+ power = POWER_HEALTH;
+ }
+ else if (m_spellInfo->SpellFamilyFlags[2] == 0x0100) // Starfall
+ {
+ // Remove targets not in LoS or in stealth
+ for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();)
+ {
+ if ((*itr)->HasStealthAura() || (*itr)->HasInvisibilityAura() || !(*itr)->IsWithinLOSInMap(m_caster))
+ itr = unitTargets.erase(itr);
+ else
+ ++itr;
+ }
+ break;
+ }
+ else
+ break;
+
+ // Remove targets outside caster's raid
+ for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();)
+ if (!(*itr)->IsInRaidWith(m_caster))
+ itr = unitTargets.erase(itr);
+ else
+ ++itr;
+ break;
+ default:
+ break;
+ }
+
+ if (maxSize && power != -1)
+ {
+ if (Powers(power) == POWER_HEALTH)
+ {
+ if (unitTargets.size() > maxSize)
+ {
+ unitTargets.sort(Trinity::HealthPctOrderPred());
+ unitTargets.resize(maxSize);
+ }
+ }
+ else
+ {
+ for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();)
+ if ((*itr)->getPowerType() != (Powers)power)
+ itr = unitTargets.erase(itr);
+ else
+ ++itr;
+
+ if (unitTargets.size() > maxSize)
+ {
+ unitTargets.sort(Trinity::PowerPctOrderPred((Powers)power));
+ unitTargets.resize(maxSize);
+ }
+ }
+ }
+
+ // Other special target selection goes here
+ if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
+ {
+ Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
+ for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
+ if ((*j)->IsAffectedOnSpell(m_spellInfo))
+ maxTargets += (*j)->GetAmount();
+
+ if (m_spellInfo->Id == 5246) //Intimidating Shout
+ unitTargets.remove(m_targets.GetUnitTarget());
+ Trinity::RandomResizeList(unitTargets, maxTargets);
+ }
+
+ CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex);
+
+ for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
+ AddUnitTarget(*itr, effMask, false);
+ }
+
+ if (!gObjTargets.empty())
+ {
+ if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
+ {
+ Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
+ for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
+ if ((*j)->IsAffectedOnSpell(m_spellInfo))
+ maxTargets += (*j)->GetAmount();
+
+ Trinity::RandomResizeList(gObjTargets, maxTargets);
+ }
+ for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr)
+ AddGOTarget(*itr, effMask);
+ }
+}
+
+void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ switch(targetType.GetType())
+ {
+ case TARGET_DEST_CASTER:
+ m_targets.SetDst(*m_caster);
+ return;
+ case TARGET_DEST_HOME:
+ if (Player* playerCaster = m_caster->ToPlayer())
+ m_targets.SetDst(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId);
+ return;
+ case TARGET_DEST_DB:
+ if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id))
+ {
+ // TODO: fix this check
+ if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS))
+ m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId);
+ else if (st->target_mapId == m_caster->GetMapId())
+ m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
+ }
+ else
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id);
+ WorldObject* target = m_targets.GetObjectTarget();
+ m_targets.SetDst(target ? *target : *m_caster);
+ }
+ return;
+ case TARGET_DEST_CASTER_FISHING:
+ {
+ float min_dis = m_spellInfo->GetMinRange(true);
+ float max_dis = m_spellInfo->GetMaxRange(true);
+ float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis;
+ float x, y, z, angle;
+ angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
+ m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle);
+ m_targets.SetDst(x, y, z, m_caster->GetOrientation());
+ return;
+ }
+ }
+
+ float dist;
+ float angle = targetType.CalcDirectionAngle();
+ float objSize = m_caster->GetObjectSize();
+ if (targetType.GetType() == TARGET_DEST_CASTER_SUMMON)
+ dist = PET_FOLLOW_DIST;
+ else
+ dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
+
+ if (dist < objSize)
+ dist = objSize;
+ else if (targetType.GetType() == TARGET_DEST_CASTER_RANDOM)
+ dist = objSize + (dist - objSize) * (float)rand_norm();
+
+ Position pos;
+ if (targetType.GetType() == TARGET_DEST_CASTER_FRONT_LEAP)
+ m_caster->GetFirstCollisionPosition(pos, dist, angle);
+ else
+ m_caster->GetNearPosition(pos, dist, angle);
+ m_targets.SetDst(*m_caster);
+ m_targets.ModDst(pos);
+}
+
+void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ WorldObject* target = m_targets.GetObjectTarget();
+ switch(targetType.GetTarget())
+ {
+ case TARGET_DEST_TARGET_ENEMY:
+ case TARGET_DEST_TARGET_ANY:
+ m_targets.SetDst(*target);
+ return;
+ }
+
+ float angle = targetType.CalcDirectionAngle();
+ float objSize = target->GetObjectSize();
+ float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
+ if (dist < objSize)
+ dist = objSize;
+ else if (targetType.GetType() == TARGET_DEST_TARGET_RANDOM)
+ dist = objSize + (dist - objSize) * (float)rand_norm();
+
+ Position pos;
+ target->GetNearPosition(pos, dist, angle);
+ m_targets.SetDst(*target);
+ m_targets.ModDst(pos);
+}
+
+void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ switch(targetType.GetTarget())
+ {
+ case TARGET_DEST_DYNOBJ_ENEMY:
+ case TARGET_DEST_DYNOBJ_ALLY:
+ case TARGET_DEST_DYNOBJ_NONE:
+ case TARGET_DEST_DEST:
+ return;
+ case TARGET_DEST_TRAJ:
+ SelectImplicitTrajTargets();
+ return;
+ }
+
+ float angle = targetType.CalcDirectionAngle();
+ float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
+ if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM)
+ dist *= (float)rand_norm();
+
+ Position pos = *m_targets.GetDst();
+ m_caster->MovePosition(pos, dist, angle);
+ m_targets.ModDst(pos);
+}
+
+void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ switch(targetType.GetTarget())
+ {
+ case TARGET_UNIT_CASTER:
+ AddUnitTarget(m_caster, 1 << effIndex, false);
+ break;
+ case TARGET_UNIT_MASTER:
+ if (Unit* owner = m_caster->GetCharmerOrOwner())
+ AddUnitTarget(owner, 1 << effIndex);
+ break;
+ case TARGET_UNIT_PET:
+ if (Guardian* pet = m_caster->GetGuardianPet())
+ AddUnitTarget(pet, 1 << effIndex);
+ break;
+ case TARGET_UNIT_SUMMONER:
+ if (m_caster->isSummon())
+ if (Unit* unit = m_caster->ToTempSummon()->GetSummoner())
+ AddUnitTarget(unit, 1 << effIndex);
+ break;
+ case TARGET_UNIT_VEHICLE:
+ if (Unit *vehicle = m_caster->GetVehicleBase())
+ AddUnitTarget(vehicle, 1 << effIndex);
+ break;
+ case TARGET_UNIT_PASSENGER_0:
+ case TARGET_UNIT_PASSENGER_1:
+ case TARGET_UNIT_PASSENGER_2:
+ case TARGET_UNIT_PASSENGER_3:
+ case TARGET_UNIT_PASSENGER_4:
+ case TARGET_UNIT_PASSENGER_5:
+ case TARGET_UNIT_PASSENGER_6:
+ case TARGET_UNIT_PASSENGER_7:
+ if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle())
+ if (Unit *unit = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0))
+ AddUnitTarget(unit, 1 << effIndex);
+ break;
+ }
+}
+
+void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ ASSERT(m_targets.GetObjectTarget() && "Spell::SelectImplicitTargetObjectTargets - no explicit object target available!");
+ if (Unit* unit = m_targets.GetUnitTarget())
+ AddUnitTarget(unit, 1 << effIndex);
+ else if (GameObject* gobj = m_targets.GetGOTarget())
+ AddGOTarget(gobj, 1 << effIndex);
+ else
+ AddItemTarget(m_targets.GetItemTarget(), effIndex);
+
+ if (WorldObject* target = m_targets.GetObjectTarget())
+ SelectImplicitChainTargets(effIndex, targetType, target, 1 << effIndex);
+}
+
+void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask)
+{
+ uint32 maxTargets = m_spellInfo->Effects[effIndex].ChainTarget;
+ if (Player* modOwner = m_caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this);
+
+ if (maxTargets > 1)
+ {
+ // mark damage multipliers as used
+ for (uint32 k = effIndex; k < MAX_SPELL_EFFECTS; ++k)
+ if (effMask & (1 << k))
+ m_damageMultipliers[k] = 1.0f;
+ m_applyMultiplierMask |= effMask;
+
+ std::list<WorldObject*> targets;
+ SearchChainTargets(targets, maxTargets - 1, target, targetType.GetObjectType(), targetType.GetCheckType()
+ , m_spellInfo->Effects[effIndex].ImplicitTargetConditions, targetType.GetType() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY);
+
+ // for backward compability
+ std::list<Unit*> unitTargets;
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ unitTargets.push_back(unitTarget);
+
+ CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex);
+
+ for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
+ AddUnitTarget(*itr, effMask, false);
+ }
+}
+
+float tangent(float x)
+{
+ x = tan(x);
+ //if (x < std::numeric_limits<float>::max() && x > -std::numeric_limits<float>::max()) return x;
+ //if (x >= std::numeric_limits<float>::max()) return std::numeric_limits<float>::max();
+ //if (x <= -std::numeric_limits<float>::max()) return -std::numeric_limits<float>::max();
+ if (x < 100000.0f && x > -100000.0f) return x;
+ if (x >= 100000.0f) return 100000.0f;
+ if (x <= 100000.0f) return -100000.0f;
+ return 0.0f;
+}
+
+#define DEBUG_TRAJ(a) //a
+
+void Spell::SelectImplicitTrajTargets()
+{
+ if (!m_targets.HasTraj())
+ return;
+
+ float dist2d = m_targets.GetDist2d();
+ if (!dist2d)
+ return;
+
+ float srcToDestDelta = m_targets.GetDst()->m_positionZ - m_targets.GetSrc()->m_positionZ;
+
+ std::list<WorldObject*> targets;
+ Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, m_targets.GetSrc(), m_caster, m_spellInfo);
+ Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> searcher(m_caster, targets, check, GRID_MAP_TYPE_MASK_ALL);
+ SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, m_targets.GetSrc(), dist2d);
+ if (targets.empty())
+ return;
+
+ targets.sort(Trinity::ObjectDistanceOrderPred(m_caster));
+
+ float b = tangent(m_targets.GetElevation());
+ float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d);
+ if (a > -0.0001f)
+ a = 0;
+ DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: a %f b %f", a, b);)
+
+ float bestDist = m_spellInfo->GetMaxRange(false);
+
+ std::list<WorldObject*>::const_iterator itr = targets.begin();
+ for (; itr != targets.end(); ++itr)
+ {
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || (unitTarget)->GetVehicle())//(*itr)->IsOnVehicle(m_caster))
+ continue;
+
+ const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3)
+ // TODO: all calculation should be based on src instead of m_caster
+ const float objDist2d = m_targets.GetSrc()->GetExactDist2d(*itr) * cos(m_targets.GetSrc()->GetRelativeAngle(*itr));
+ const float dz = (*itr)->GetPositionZ() - m_targets.GetSrc()->m_positionZ;
+
+ DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);)
+
+ float dist = objDist2d - size;
+ float height = dist * (a * dist + b);
+ DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)
+ if (dist < bestDist && height < dz + size && height > dz - size)
+ {
+ bestDist = dist > 0 ? dist : 0;
+ break;
+ }
+
+#define CHECK_DIST {\
+ DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)\
+ if (dist > bestDist)\
+ continue;\
+ if (dist < objDist2d + size && dist > objDist2d - size)\
+ {\
+ bestDist = dist;\
+ break;\
+ }\
+ }
+
+ if (!a)
+ {
+ height = dz - size;
+ dist = height / b;
+ CHECK_DIST;
+
+ height = dz + size;
+ dist = height / b;
+ CHECK_DIST;
+
+ continue;
+ }
+
+ height = dz - size;
+ float sqrt1 = b * b + 4 * a * height;
+ if (sqrt1 > 0)
+ {
+ sqrt1 = sqrt(sqrt1);
+ dist = (sqrt1 - b) / (2 * a);
+ CHECK_DIST;
+ }
+
+ height = dz + size;
+ float sqrt2 = b * b + 4 * a * height;
+ if (sqrt2 > 0)
+ {
+ sqrt2 = sqrt(sqrt2);
+ dist = (sqrt2 - b) / (2 * a);
+ CHECK_DIST;
+
+ dist = (-sqrt2 - b) / (2 * a);
+ CHECK_DIST;
+ }
+
+ if (sqrt1 > 0)
+ {
+ dist = (-sqrt1 - b) / (2 * a);
+ CHECK_DIST;
+ }
+ }
+
+ if (m_targets.GetSrc()->GetExactDist2d(m_targets.GetDst()) > bestDist)
+ {
+ float x = m_targets.GetSrc()->m_positionX + cos(m_caster->GetOrientation()) * bestDist;
+ float y = m_targets.GetSrc()->m_positionY + sin(m_caster->GetOrientation()) * bestDist;
+ float z = m_targets.GetSrc()->m_positionZ + bestDist * (a * bestDist + b);
+
+ if (itr != targets.end())
+ {
+ float distSq = (*itr)->GetExactDistSq(x, y, z);
+ float sizeSq = (*itr)->GetObjectSize();
+ sizeSq *= sizeSq;
+ DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
+ if (distSq > sizeSq)
+ {
+ float factor = 1 - sqrt(sizeSq / distSq);
+ x += factor * ((*itr)->GetPositionX() - x);
+ y += factor * ((*itr)->GetPositionY() - y);
+ z += factor * ((*itr)->GetPositionZ() - z);
+
+ distSq = (*itr)->GetExactDistSq(x, y, z);
+ DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
+ }
+ }
+
+ Position trajDst;
+ trajDst.Relocate(x, y, z, m_caster->GetOrientation());
+ m_targets.ModDst(trajDst);
+ }
+}
+
void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
{
// special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER
@@ -865,6 +1759,190 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
}
}
+uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList)
+{
+ // this function selects which containers need to be searched for spell target
+ uint32 retMask = GRID_MAP_TYPE_MASK_ALL;
+
+ // filter searchers based on searched object type
+ switch (objType)
+ {
+ case TARGET_OBJECT_TYPE_UNIT:
+ case TARGET_OBJECT_TYPE_UNIT_AND_DEST:
+ case TARGET_OBJECT_TYPE_CORPSE:
+ case TARGET_OBJECT_TYPE_CORPSE_ENEMY:
+ case TARGET_OBJECT_TYPE_CORPSE_ALLY:
+ retMask &= GRID_MAP_TYPE_MASK_PLAYER | GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_CREATURE;
+ break;
+ case TARGET_OBJECT_TYPE_GOBJ:
+ case TARGET_OBJECT_TYPE_GOBJ_ITEM:
+ retMask &= GRID_MAP_TYPE_MASK_GAMEOBJECT;
+ break;
+ }
+ if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_DEAD))
+ retMask &= ~GRID_MAP_TYPE_MASK_CORPSE;
+ if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS)
+ retMask &= GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_PLAYER;
+ if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS)
+ retMask &= GRID_MAP_TYPE_MASK_PLAYER;
+
+ if (condList)
+ retMask &= sConditionMgr->GetSearcherTypeMaskForConditionList(*condList);
+ return retMask;
+}
+
+template<class SEARCHER>
+void Spell::SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* referer, Position const* pos, float radius)
+{
+ if (!containerMask)
+ return;
+
+ // search world and grid for possible targets
+ bool searchInGrid = containerMask & (GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_GAMEOBJECT);
+ bool searchInWorld = containerMask & (GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER | GRID_MAP_TYPE_MASK_CORPSE);
+ if (searchInGrid || searchInWorld)
+ {
+ float x,y;
+ x = pos->GetPositionX();
+ y = pos->GetPositionY();
+
+ CellCoord p(Trinity::ComputeCellCoord(x, y));
+ Cell cell(p);
+ cell.SetNoCreate();
+
+ Map& map = *(referer->GetMap());
+
+ if (searchInWorld)
+ {
+ TypeContainerVisitor<SEARCHER, WorldTypeMapContainer> world_object_notifier(searcher);
+ cell.Visit(p, world_object_notifier, map, radius, x, y);
+ }
+ if (searchInGrid)
+ {
+ TypeContainerVisitor<SEARCHER, GridTypeMapContainer > grid_object_notifier(searcher);
+ cell.Visit(p, grid_object_notifier, map, radius, x , y);
+ }
+ }
+}
+
+WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList)
+{
+ WorldObject* target = NULL;
+ uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList);
+ if (!containerTypeMask)
+ return NULL;
+ Trinity::WorldObjectSpellNearbyTargetCheck check(range, m_caster, m_spellInfo, selectionType, condList);
+ Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> searcher(m_caster, target, check, containerTypeMask);
+ SearchTargets<Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, range);
+ return target;
+}
+
+void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList)
+{
+ uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList);
+ if (!containerTypeMask)
+ return;
+ Trinity::WorldObjectSpellAreaTargetCheck check(range, position, m_caster, referer, m_spellInfo, selectionType, condList);
+ Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(m_caster, targets, check, containerTypeMask);
+ SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, range);
+}
+
+void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList* condList, bool isChainHeal)
+{
+ // max dist for jump target selection
+ float jumpRadius = 0.0f;
+ switch (m_spellInfo->DmgClass)
+ {
+ case SPELL_DAMAGE_CLASS_RANGED:
+ // 7.5y for multi shot
+ jumpRadius = 7.5f;
+ break;
+ case SPELL_DAMAGE_CLASS_MELEE:
+ // 5y for swipe, cleave and similar
+ jumpRadius = 5.0f;
+ break;
+ case SPELL_DAMAGE_CLASS_NONE:
+ case SPELL_DAMAGE_CLASS_MAGIC:
+ // 12.5y for chain heal spell since 3.2 patch
+ if (isChainHeal)
+ jumpRadius = 12.5f;
+ // 10y as default for magic chain spells
+ else
+ jumpRadius = 10.0f;
+ break;
+ }
+
+ // chain lightning/heal spells and similar - allow to jump at larger distance and go out of los
+ bool isBouncingFar = (m_spellInfo->AttributesEx4 & SPELL_ATTR4_AREA_TARGET_CHAIN
+ || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE
+ || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC);
+
+ // max dist which spell can reach
+ float searchRadius = jumpRadius;
+ if (isBouncingFar)
+ searchRadius *= chainTargets;
+
+ std::list<WorldObject*> tempTargets;
+ SearchAreaTargets(tempTargets, searchRadius, target, m_caster, objectType, selectType, condList);
+ tempTargets.remove(target);
+
+ // remove targets which are always invalid for chain spells
+ // for some spells allow only chain targets in front of caster (swipe for example)
+ if (!isBouncingFar)
+ {
+ for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end();)
+ {
+ std::list<WorldObject*>::iterator checkItr = itr++;
+ if (!m_caster->HasInArc(static_cast<float>(M_PI), *checkItr))
+ tempTargets.erase(checkItr);
+ }
+ }
+
+ while (chainTargets)
+ {
+ // try to get unit for next chain jump
+ std::list<WorldObject*>::iterator foundItr = tempTargets.end();
+ // get unit with highest hp deficit in dist
+ if (isChainHeal)
+ {
+ uint32 maxHPDeficit = 0;
+ for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
+ {
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ {
+ uint32 deficit = unitTarget->GetMaxHealth() - unitTarget->GetHealth();
+ if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unitTarget, jumpRadius) && target->IsWithinLOSInMap(unitTarget))
+ {
+ foundItr = itr;
+ maxHPDeficit = deficit;
+ }
+ }
+ }
+ }
+ // get closest object
+ else
+ {
+ for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
+ {
+ if (foundItr == tempTargets.end())
+ {
+ if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr))
+ foundItr = itr;
+ }
+ else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr))
+ foundItr = itr;
+ }
+ }
+ // not found any valid target - chain ends
+ if (foundItr == tempTargets.end())
+ break;
+ target = *foundItr;
+ tempTargets.erase(foundItr);
+ targets.push_back(target);
+ --chainTargets;
+ }
+}
+
void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
{
//==========================================================================================
@@ -1791,1077 +2869,6 @@ struct ChainHealingOrder : public std::binary_function<const Unit*, const Unit*,
}
};
-void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uint32 num, SpellTargets TargetType)
-{
- Unit* cur = m_targets.GetUnitTarget();
- if (!cur)
- return;
-
- //FIXME: This very like horrible hack and wrong for most spells
- if (m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE)
- max_range += num * CHAIN_SPELL_JUMP_RADIUS;
-
- std::list<Unit*> tempUnitMap;
- if (TargetType == SPELL_TARGETS_CHAINHEAL)
- {
- SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, SPELL_TARGETS_ALLY);
- tempUnitMap.sort(ChainHealingOrder(m_caster));
- }
- else
- SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, TargetType);
- tempUnitMap.remove(cur);
-
- while (num)
- {
- TagUnitMap.push_back(cur);
- --num;
-
- if (tempUnitMap.empty())
- break;
-
- std::list<Unit*>::iterator next;
-
- if (TargetType == SPELL_TARGETS_CHAINHEAL)
- {
- next = tempUnitMap.begin();
- while (cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS || !cur->IsWithinLOSInMap(*next))
- {
- ++next;
- if (next == tempUnitMap.end())
- return;
- }
- }
- else
- {
- tempUnitMap.sort(Trinity::ObjectDistanceOrderPred(cur));
- next = tempUnitMap.begin();
-
- if (cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) // Don't search beyond the max jump radius
- break;
-
- // Check if (*next) is a valid chain target. If not, don't add to TagUnitMap, and repeat loop.
- // If you want to add any conditions to exclude a target from TagUnitMap, add condition in this while () loop.
- while ((m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE
- && !m_caster->isInFrontInMap(*next, max_range))
- || !m_caster->canSeeOrDetect(*next)
- || !cur->IsWithinLOSInMap(*next)
- || (*next)->GetCreatureType() == CREATURE_TYPE_CRITTER
- || ((GetSpellInfo()->AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED) && !(*next)->CanFreeMove()))
- {
- ++next;
- if (next == tempUnitMap.end() || cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) // Don't search beyond the max jump radius
- return;
- }
- }
-
- cur = *next;
- tempUnitMap.erase(next);
- }
-}
-
-void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry)
-{
- if (TargetType == SPELL_TARGETS_GO)
- return;
-
- Position const* pos;
- switch (type)
- {
- case PUSH_DST_CENTER:
- CheckDst();
- pos = m_targets.GetDst();
- break;
- case PUSH_SRC_CENTER:
- CheckSrc();
- pos = m_targets.GetSrc();
- break;
- case PUSH_CHAIN:
- {
- Unit* target = m_targets.GetUnitTarget();
- if (!target)
- {
- sLog->outError("SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id);
- return;
- }
- pos = target;
- break;
- }
- default:
- pos = m_caster;
- break;
- }
-
- Trinity::SpellNotifierCreatureAndPlayer notifier(m_caster, TagUnitMap, radius, type, TargetType, pos, entry, m_spellInfo);
- if ((m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS) || (TargetType == SPELL_TARGETS_ENTRY && !entry))
- m_caster->GetMap()->VisitWorld(pos->m_positionX, pos->m_positionY, radius, notifier);
- else
- m_caster->GetMap()->VisitAll(pos->m_positionX, pos->m_positionY, radius, notifier);
-}
-
-void Spell::SearchGOAreaTarget(std::list<GameObject*> &TagGOMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry)
-{
- if (TargetType != SPELL_TARGETS_GO)
- return;
-
- Position const* pos;
- switch (type)
- {
- case PUSH_DST_CENTER:
- CheckDst();
- pos = m_targets.GetDst();
- break;
- case PUSH_SRC_CENTER:
- CheckSrc();
- pos = m_targets.GetSrc();
- break;
- default:
- pos = m_caster;
- break;
- }
-
- Trinity::GameObjectInRangeCheck check(pos->m_positionX, pos->m_positionY, pos->m_positionZ, radius, entry);
- Trinity::GameObjectListSearcher<Trinity::GameObjectInRangeCheck> searcher(m_caster, TagGOMap, check);
- m_caster->GetMap()->VisitGrid(pos->m_positionX, pos->m_positionY, radius, searcher);
-}
-
-WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex)
-{
- switch (TargetType)
- {
- case SPELL_TARGETS_ENTRY:
- {
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
- if (conditions.empty())
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) (caster Entry: %u) does not have record in `conditions` for spell script target (ConditionSourceType 13)", m_spellInfo->Id, m_caster->GetEntry());
- if (m_spellInfo->IsPositive())
- return SearchNearbyTarget(range, SPELL_TARGETS_ALLY, effIndex);
- else
- return SearchNearbyTarget(range, SPELL_TARGETS_ENEMY, effIndex);
- }
-
- Creature* creatureScriptTarget = NULL;
- GameObject* goScriptTarget = NULL;
-
- for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
- {
- if ((*i_spellST)->ConditionType != CONDITION_SPELL_SCRIPT_TARGET)
- continue;
- if ((*i_spellST)->ConditionValue3 && !((*i_spellST)->ConditionValue3 & (1 << uint32(effIndex))))
- continue;
- switch ((*i_spellST)->ConditionValue1)
- {
- case SPELL_TARGET_TYPE_CONTROLLED:
- for (Unit::ControlList::iterator itr = m_caster->m_Controlled.begin(); itr != m_caster->m_Controlled.end(); ++itr)
- if ((*itr)->GetEntry() == (*i_spellST)->ConditionValue2 && (*itr)->IsWithinDistInMap(m_caster, range))
- {
- goScriptTarget = NULL;
- creatureScriptTarget = (*itr)->ToCreature();
- range = m_caster->GetDistance(creatureScriptTarget);
- }
- break;
- case SPELL_TARGET_TYPE_GAMEOBJECT:
- if ((*i_spellST)->ConditionValue2)
- {
- if (GameObject* go = m_caster->FindNearestGameObject((*i_spellST)->ConditionValue2, range))
- {
- // remember found target and range, next attempt will find more near target with another entry
- goScriptTarget = go;
- creatureScriptTarget = NULL;
- range = m_caster->GetDistance(goScriptTarget);
- }
- }
- else if (focusObject) //Focus Object
- {
- float frange = m_caster->GetDistance(focusObject);
- if (range >= frange)
- {
- creatureScriptTarget = NULL;
- goScriptTarget = focusObject;
- range = frange;
- }
- }
- break;
- case SPELL_TARGET_TYPE_CREATURE:
- if (m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetEntry() == (*i_spellST)->ConditionValue2)
- return m_targets.GetUnitTarget();
- case SPELL_TARGET_TYPE_DEAD:
- default:
- if (Creature* cre = m_caster->FindNearestCreature((*i_spellST)->ConditionValue2, range, (*i_spellST)->ConditionValue1 != SPELL_TARGET_TYPE_DEAD))
- {
- creatureScriptTarget = cre;
- goScriptTarget = NULL;
- range = m_caster->GetDistance(creatureScriptTarget);
- }
- break;
- }
- }
-
- if (creatureScriptTarget)
- return creatureScriptTarget;
- else
- return goScriptTarget;
- }
- default:
- case SPELL_TARGETS_ENEMY:
- {
- Unit* target = NULL;
- Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range);
- Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check);
- m_caster->VisitNearbyObject(range, searcher);
- return target;
- }
- case SPELL_TARGETS_ALLY:
- {
- Unit* target = NULL;
- Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range);
- Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check);
- m_caster->VisitNearbyObject(range, searcher);
- return target;
- }
- }
-}
-
-uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur)
-{
- SpellNotifyPushType pushType = PUSH_NONE;
- Player* modOwner = NULL;
- if (m_originalCaster)
- modOwner = m_originalCaster->GetSpellModOwner();
-
- uint32 effectMask = 1 << i;
- // ENTRY targets may have different selection lists, skip those for now until we can compare lists easily and quickly
- if (GetSpellInfo()->Effects[i].TargetA.GetSelectionCheckType() != TARGET_SELECT_CHECK_ENTRY &&
- GetSpellInfo()->Effects[i].TargetB.GetSelectionCheckType() != TARGET_SELECT_CHECK_ENTRY)
- for (uint32 j = i + 1; j < MAX_SPELL_EFFECTS; ++j)
- if (GetSpellInfo()->Effects[i].TargetA.GetTarget() == GetSpellInfo()->Effects[j].TargetA.GetTarget() &&
- GetSpellInfo()->Effects[i].TargetB.GetTarget() == GetSpellInfo()->Effects[j].TargetB.GetTarget() &&
- GetSpellInfo()->Effects[i].CalcRadius(m_caster) == GetSpellInfo()->Effects[j].CalcRadius(m_caster))
- effectMask |= 1 << j;
-
- switch (cur.GetType())
- {
- case TARGET_TYPE_UNIT_CASTER:
- {
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_CASTER:
- AddUnitTarget(m_caster, effectMask, false);
- break;
- case TARGET_DEST_CASTER_FISHING:
- {
- float min_dis = m_spellInfo->GetMinRange(true);
- float max_dis = m_spellInfo->GetMaxRange(true);
- float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis;
- float x, y, z, angle;
- angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
- m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle);
- m_targets.SetDst(x, y, z, m_caster->GetOrientation());
- break;
- }
- case TARGET_UNIT_MASTER:
- if (Unit* owner = m_caster->GetCharmerOrOwner())
- AddUnitTarget(owner, effectMask);
- break;
- case TARGET_UNIT_PET:
- if (Guardian* pet = m_caster->GetGuardianPet())
- AddUnitTarget(pet, effectMask);
- break;
- case TARGET_UNIT_SUMMONER:
- if (m_caster->isSummon())
- if (Unit* unit = m_caster->ToTempSummon()->GetSummoner())
- AddUnitTarget(unit, effectMask);
- break;
- case TARGET_UNIT_CASTER_AREA_PARTY:
- case TARGET_UNIT_CASTER_AREA_RAID:
- pushType = PUSH_CASTER_CENTER;
- break;
- case TARGET_UNIT_VEHICLE:
- if (Unit* vehicle = m_caster->GetVehicleBase())
- AddUnitTarget(vehicle, effectMask);
- break;
- case TARGET_UNIT_PASSENGER_0:
- case TARGET_UNIT_PASSENGER_1:
- case TARGET_UNIT_PASSENGER_2:
- case TARGET_UNIT_PASSENGER_3:
- case TARGET_UNIT_PASSENGER_4:
- case TARGET_UNIT_PASSENGER_5:
- case TARGET_UNIT_PASSENGER_6:
- case TARGET_UNIT_PASSENGER_7:
- if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle())
- if (Unit* unit = m_caster->GetVehicleKit()->GetPassenger(cur.GetTarget() - TARGET_UNIT_PASSENGER_0))
- AddUnitTarget(unit, effectMask);
- break;
- default:
- break;
- }
- break;
- }
-
- case TARGET_TYPE_UNIT_TARGET:
- {
- Unit* target = m_targets.GetUnitTarget();
- if (!target)
- {
- sLog->outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id);
- break;
- }
-
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_TARGET_ENEMY:
- case TARGET_UNIT_TARGET_ANY:
- pushType = PUSH_CHAIN;
- break;
- case TARGET_UNIT_TARGET_CHAINHEAL_ALLY:
- pushType = PUSH_CHAIN;
- break;
- case TARGET_UNIT_TARGET_ALLY:
- AddUnitTarget(target, effectMask, false);
- break;
- case TARGET_UNIT_TARGET_RAID:
- case TARGET_UNIT_TARGET_PARTY:
- case TARGET_UNIT_TARGET_MINIPET:
- AddUnitTarget(target, effectMask, false);
- break;
- case TARGET_UNIT_TARGET_PASSENGER:
- AddUnitTarget(target, effectMask, false);
- break;
- case TARGET_UNIT_LASTTARGET_AREA_PARTY:
- case TARGET_UNIT_TARGET_AREA_RAID_CLASS:
- pushType = PUSH_CASTER_CENTER; // not real
- break;
- default:
- break;
- }
- break;
- }
-
- case TARGET_TYPE_UNIT_NEARBY:
- {
- WorldObject* target = NULL;
- float range;
-
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_NEARBY_ENEMY:
- range = m_spellInfo->GetMaxRange(false);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- target = SearchNearbyTarget(range, SPELL_TARGETS_ENEMY, SpellEffIndex(i));
- break;
- case TARGET_UNIT_NEARBY_ALLY:
- case TARGET_UNIT_NEARBY_PARTY: // TODO: fix party/raid targets
- case TARGET_UNIT_NEARBY_RAID:
- range = m_spellInfo->GetMaxRange(true);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- target = SearchNearbyTarget(range, SPELL_TARGETS_ALLY, SpellEffIndex(i));
- break;
- case TARGET_UNIT_NEARBY_ENTRY:
- case TARGET_GAMEOBJECT_NEARBY_ENTRY:
- range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive());
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY, SpellEffIndex(i));
- break;
- default:
- break;
- }
-
- if (!target)
- return 0;
- else if (target->GetTypeId() == TYPEID_GAMEOBJECT)
- AddGOTarget((GameObject*)target, effectMask);
- else
- {
- pushType = PUSH_CHAIN;
-
- if (m_targets.GetUnitTarget() != target)
- m_targets.SetUnitTarget((Unit*)target);
- }
-
- break;
- }
-
- case TARGET_TYPE_AREA_SRC:
- pushType = PUSH_SRC_CENTER;
- break;
-
- case TARGET_TYPE_AREA_DST:
- pushType = PUSH_DST_CENTER;
- break;
-
- case TARGET_TYPE_AREA_CONE:
- if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_BACK)
- pushType = PUSH_IN_BACK;
- else if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_LINE)
- pushType = PUSH_IN_LINE;
- else
- pushType = PUSH_IN_FRONT;
- break;
-
- case TARGET_TYPE_DEST_CASTER: //4+8+2
- {
- if (cur.GetTarget() == TARGET_SRC_CASTER)
- {
- m_targets.SetSrc(*m_caster);
- break;
- }
- else if (cur.GetTarget() == TARGET_DEST_CASTER)
- {
- m_targets.SetDst(*m_caster);
- break;
- }
-
- float angle, dist;
-
- float objSize = m_caster->GetObjectSize();
- if (cur.GetTarget() == TARGET_DEST_CASTER_SUMMON)
- dist = 0.0f;
- else
- dist = m_spellInfo->Effects[i].CalcRadius(m_caster);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, dist, this);
- if (dist < objSize)
- dist = objSize;
- else if (cur.GetTarget() == TARGET_DEST_CASTER_RANDOM)
- dist = objSize + (dist - objSize) * (float)rand_norm();
-
- switch (cur.GetTarget())
- {
- case TARGET_DEST_CASTER_FRONT_LEFT: angle = static_cast<float>(-M_PI/4); break;
- case TARGET_DEST_CASTER_BACK_LEFT: angle = static_cast<float>(-3*M_PI/4); break;
- case TARGET_DEST_CASTER_BACK_RIGHT: angle = static_cast<float>(3*M_PI/4); break;
- case TARGET_DEST_CASTER_FRONT_RIGHT:angle = static_cast<float>(M_PI/4); break;
- case TARGET_DEST_CASTER_SUMMON:
- case TARGET_DEST_CASTER_FRONT_LEAP:
- case TARGET_DEST_CASTER_FRONT: angle = 0.0f; break;
- case TARGET_DEST_CASTER_BACK: angle = static_cast<float>(M_PI); break;
- case TARGET_DEST_CASTER_RIGHT: angle = static_cast<float>(-M_PI/2); break;
- case TARGET_DEST_CASTER_LEFT: angle = static_cast<float>(M_PI/2); break;
- default: angle = (float)rand_norm()*static_cast<float>(2*M_PI); break;
- }
-
- Position pos;
- if (cur.GetTarget() == TARGET_DEST_CASTER_FRONT_LEAP)
- m_caster->GetFirstCollisionPosition(pos, dist, angle);
- else
- m_caster->GetNearPosition(pos, dist, angle);
- m_targets.SetDst(*m_caster);
- m_targets.ModDst(pos);
- break;
- }
-
- case TARGET_TYPE_DEST_TARGET: //2+8+2
- {
- Unit* target = m_targets.GetUnitTarget();
- if (!target)
- {
- sLog->outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id);
- break;
- }
-
- if (cur.GetTarget() == TARGET_DEST_TARGET_ENEMY || cur.GetTarget() == TARGET_DEST_TARGET_ANY)
- {
- m_targets.SetDst(*target);
- break;
- }
-
- float angle, dist;
-
- float objSize = target->GetObjectSize();
- dist = m_spellInfo->Effects[i].CalcRadius(m_caster);
- if (dist < objSize)
- dist = objSize;
- else if (cur.GetTarget() == TARGET_DEST_TARGET_RANDOM)
- dist = objSize + (dist - objSize) * (float)rand_norm();
-
- switch (cur.GetTarget())
- {
- case TARGET_DEST_TARGET_FRONT: angle = 0.0f; break;
- case TARGET_DEST_TARGET_BACK: angle = static_cast<float>(M_PI); break;
- case TARGET_DEST_TARGET_RIGHT: angle = static_cast<float>(M_PI/2); break;
- case TARGET_DEST_TARGET_LEFT: angle = static_cast<float>(-M_PI/2); break;
- case TARGET_DEST_TARGET_FRONT_LEFT: angle = static_cast<float>(-M_PI/4); break;
- case TARGET_DEST_TARGET_BACK_LEFT: angle = static_cast<float>(-3*M_PI/4); break;
- case TARGET_DEST_TARGET_BACK_RIGHT: angle = static_cast<float>(3*M_PI/4); break;
- case TARGET_DEST_TARGET_FRONT_RIGHT:angle = static_cast<float>(M_PI/4); break;
- default: angle = (float)rand_norm()*static_cast<float>(2*M_PI); break;
- }
-
- Position pos;
- target->GetNearPosition(pos, dist, angle);
- m_targets.SetDst(*target);
- m_targets.ModDst(pos);
- break;
- }
-
- case TARGET_TYPE_DEST_DEST: //5+8+1
- {
- if (!m_targets.HasDst())
- {
- sLog->outError("SPELL: no destination for spell ID %u", m_spellInfo->Id);
- break;
- }
-
- float angle;
- switch (cur.GetTarget())
- {
- case TARGET_DEST_DYNOBJ_ENEMY:
- case TARGET_DEST_DYNOBJ_ALLY:
- case TARGET_DEST_DYNOBJ_NONE:
- case TARGET_DEST_DEST:
- return effectMask;
- case TARGET_DEST_TRAJ:
- SelectTrajTargets();
- return effectMask;
- case TARGET_DEST_DEST_FRONT: angle = 0.0f; break;
- case TARGET_DEST_DEST_BACK: angle = static_cast<float>(M_PI); break;
- case TARGET_DEST_DEST_RIGHT: angle = static_cast<float>(M_PI/2); break;
- case TARGET_DEST_DEST_LEFT: angle = static_cast<float>(-M_PI/2); break;
- case TARGET_DEST_DEST_FRONT_LEFT: angle = static_cast<float>(-M_PI/4); break;
- case TARGET_DEST_DEST_BACK_LEFT: angle = static_cast<float>(-3*M_PI/4); break;
- case TARGET_DEST_DEST_BACK_RIGHT: angle = static_cast<float>(3*M_PI/4); break;
- case TARGET_DEST_DEST_FRONT_RIGHT:angle = static_cast<float>(M_PI/4); break;
- default: angle = (float)rand_norm()*static_cast<float>(2*M_PI); break;
- }
-
- float dist = m_spellInfo->Effects[i].CalcRadius(m_caster);
- if (cur.GetTarget() == TARGET_DEST_DEST_RANDOM || cur.GetTarget() == TARGET_DEST_DEST_RADIUS)
- dist *= (float)rand_norm();
-
- // must has dst, no need to set flag
- Position pos = *m_targets.GetDst();
- m_caster->MovePosition(pos, dist, angle);
- m_targets.ModDst(pos);
- break;
- }
-
- case TARGET_TYPE_DEST_SPECIAL:
- {
- switch (cur.GetTarget())
- {
- case TARGET_DEST_DB:
- if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id))
- {
- //TODO: fix this check
- if (m_spellInfo->Effects[0].Effect == SPELL_EFFECT_TELEPORT_UNITS || m_spellInfo->Effects[1].Effect == SPELL_EFFECT_TELEPORT_UNITS || m_spellInfo->Effects[2].Effect == SPELL_EFFECT_TELEPORT_UNITS)
- m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId);
- else if (st->target_mapId == m_caster->GetMapId())
- m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
- }
- else
- {
- sLog->outError("SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id);
- Unit* target = NULL;
- if (uint64 guid = m_caster->GetUInt64Value(UNIT_FIELD_TARGET))
- target = ObjectAccessor::GetUnit(*m_caster, guid);
- m_targets.SetDst(target ? *target : *m_caster);
- }
- break;
- case TARGET_DEST_HOME:
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- m_targets.SetDst(m_caster->ToPlayer()->m_homebindX, m_caster->ToPlayer()->m_homebindY, m_caster->ToPlayer()->m_homebindZ, m_caster->ToPlayer()->GetOrientation(), m_caster->ToPlayer()->m_homebindMapId);
- break;
- case TARGET_DEST_NEARBY_ENTRY:
- {
- float range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive());
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
-
- if (WorldObject* target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY, SpellEffIndex(i)))
- m_targets.SetDst(*target);
- break;
- }
- default:
- break;
- }
- break;
- }
-
- case TARGET_TYPE_CHANNEL:
- {
- if (!m_originalCaster || !m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: no current channeled spell for spell ID %u - spell triggering this spell was interrupted.", m_spellInfo->Id);
- break;
- }
-
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_CHANNEL_TARGET:
- // unit target may be no longer avalible - teleported out of map for example
- if (Unit* target = Unit::GetUnit(*m_caster, m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.GetUnitTargetGUID()))
- AddUnitTarget(target, effectMask);
- else
- sLog->outError("SPELL: cannot find channel spell target for spell ID %u", m_spellInfo->Id);
- break;
- case TARGET_DEST_CHANNEL_TARGET:
- if (m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.HasDst())
- m_targets.SetDst(m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets);
- else if (Unit* target = Unit::GetUnit(*m_caster, m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.GetUnitTargetGUID()))
- m_targets.SetDst(*target);
- else
- sLog->outError("SPELL: cannot find channel spell destination for spell ID %u", m_spellInfo->Id);
- break;
- case TARGET_DEST_CHANNEL_CASTER:
- m_targets.SetDst(*m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->GetCaster());
- break;
- default:
- break;
- }
- break;
- }
-
- default:
- {
- switch (cur.GetTarget())
- {
- case TARGET_GAMEOBJECT_TARGET:
- if (m_targets.GetGOTarget())
- AddGOTarget(m_targets.GetGOTarget(), effectMask);
- break;
- case TARGET_GAMEOBJECT_ITEM_TARGET:
- if (m_targets.GetGOTargetGUID())
- AddGOTarget(m_targets.GetGOTarget(), effectMask);
- else if (m_targets.GetItemTarget())
- AddItemTarget(m_targets.GetItemTarget(), effectMask);
- break;
- default:
- sLog->outError("SPELL (caster[type: %u; guidlow: %u], spell: %u): unhandled spell target (%u)",
- m_caster->GetTypeId(), m_caster->GetGUIDLow(), m_spellInfo->Id, cur.GetTarget());
- break;
- }
- break;
- }
- }
-
- if (pushType == PUSH_CHAIN) // Chain
- {
- Unit* target = m_targets.GetUnitTarget();
- if (!target)
- {
- sLog->outError("SPELL: no chain unit target for spell ID %u", m_spellInfo->Id);
- return 0;
- }
-
- //Chain: 2, 6, 22, 25, 45, 77
- uint32 maxTargets = m_spellInfo->Effects[i].ChainTarget;
- if (modOwner)
- modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this);
-
- if (maxTargets > 1)
- {
- //otherwise, this multiplier is used for something else
- for (uint32 k = i; k < MAX_SPELL_EFFECTS; ++k)
- if (effectMask & (1 << k))
- m_damageMultipliers[k] = 1.0f;
- m_applyMultiplierMask |= effectMask;
-
- float range;
- std::list<Unit*> unitList;
-
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_NEARBY_ENEMY:
- case TARGET_UNIT_TARGET_ENEMY:
- case TARGET_UNIT_NEARBY_ENTRY: // fix me
- range = m_spellInfo->GetMaxRange(false);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- SearchChainTarget(unitList, range, maxTargets, SPELL_TARGETS_ENEMY);
- break;
- case TARGET_UNIT_TARGET_CHAINHEAL_ALLY:
- case TARGET_UNIT_NEARBY_ALLY: // fix me
- case TARGET_UNIT_NEARBY_PARTY:
- case TARGET_UNIT_NEARBY_RAID:
- range = m_spellInfo->GetMaxRange(true);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- SearchChainTarget(unitList, range, maxTargets, SPELL_TARGETS_CHAINHEAL);
- break;
- default:
- break;
- }
-
- CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i));
-
- for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
- AddUnitTarget(*itr, effectMask, false);
- }
- else
- AddUnitTarget(target, effectMask, false);
- }
- else if (pushType)
- {
- float radius;
- SpellTargets targetType;
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_SRC_AREA_ENEMY:
- case TARGET_UNIT_DEST_AREA_ENEMY:
- case TARGET_UNIT_CONE_ENEMY_24:
- case TARGET_UNIT_CONE_ENEMY_54:
- case TARGET_UNIT_CONE_ENEMY_104:
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_ENEMY;
- break;
- case TARGET_UNIT_SRC_AREA_ALLY:
- case TARGET_UNIT_DEST_AREA_ALLY:
- case TARGET_UNIT_CONE_ALLY:
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_ALLY;
- break;
- case TARGET_UNIT_DEST_AREA_ENTRY:
- case TARGET_UNIT_SRC_AREA_ENTRY:
- case TARGET_UNIT_CONE_ENTRY: // fix me
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_ENTRY;
- break;
- case TARGET_GAMEOBJECT_SRC_AREA:
- case TARGET_GAMEOBJECT_DEST_AREA:
- case TARGET_GAMEOBJECT_CONE:
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_GO;
- break;
- default:
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_NONE;
- break;
- }
-
- if (modOwner)
- modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this);
- radius *= m_spellValue->RadiusMod;
-
- std::list<Unit*> unitList;
- std::list<GameObject*> gobjectList;
- switch (targetType)
- {
- case SPELL_TARGETS_ENTRY:
- {
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
- if (!conditions.empty())
- {
- for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
- {
- if ((*i_spellST)->ConditionType != CONDITION_SPELL_SCRIPT_TARGET)
- continue;
- if ((*i_spellST)->ConditionValue3 && !((*i_spellST)->ConditionValue3 & effectMask))
- continue;
- if ((*i_spellST)->ConditionValue1 == SPELL_TARGET_TYPE_CREATURE)
- SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, (*i_spellST)->ConditionValue2);
- else if ((*i_spellST)->ConditionValue1 == SPELL_TARGET_TYPE_CONTROLLED)
- {
- for (Unit::ControlList::iterator itr = m_caster->m_Controlled.begin(); itr != m_caster->m_Controlled.end(); ++itr)
- if ((*itr)->GetEntry() == (*i_spellST)->ConditionValue2 &&
- (*itr)->IsInMap(m_caster)) // For 60243 and 52173 need skip radius check or use range (no radius entry for effect)
- unitList.push_back(*itr);
- }
- }
- }
- else
- {
- // Custom entries
- // TODO: move these to sql
- switch (m_spellInfo->Id)
- {
- case 46584: // Raise Dead
- {
- if (WorldObject* result = FindCorpseUsing<Trinity::RaiseDeadObjectCheck>())
- {
- switch (result->GetTypeId())
- {
- case TYPEID_UNIT:
- case TYPEID_PLAYER:
- unitList.push_back(result->ToUnit());
- // no break;
- case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet
- m_targets.SetDst(*result);
- break;
- default:
- break;
- }
- }
- break;
- }
- // Corpse Explosion
- case 49158:
- case 51325:
- case 51326:
- case 51327:
- case 51328:
- // Search for ghoul if our ghoul or dead body not valid unit target
- if (!(m_targets.GetUnitTarget() && ((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID())
- || (m_targets.GetUnitTarget()->getDeathState() == CORPSE
- && m_targets.GetUnitTarget()->GetTypeId() == TYPEID_UNIT
- && !(m_targets.GetUnitTarget()->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL)
- && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId()))))
- {
- CleanupTargetList();
-
- WorldObject* result = FindCorpseUsing<Trinity::ExplodeCorpseObjectCheck>();
-
- if (result)
- {
- switch (result->GetTypeId())
- {
- case TYPEID_UNIT:
- case TYPEID_PLAYER:
- m_targets.SetUnitTarget((Unit*)result);
- break;
- default:
- break;
- }
- }
- else
- {
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
- SendCastResult(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW);
- finish(false);
- }
- }
- break;
-
- default:
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) (caster Entry: %u) does not have type CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET record in `conditions` table.", m_spellInfo->Id, m_caster->GetEntry());
-
- if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_TELEPORT_UNITS)
- SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, 0);
- else if (m_spellInfo->IsPositiveEffect(i))
- SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ALLY);
- else
- SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENEMY);
- }
- }
- break;
- }
- case SPELL_TARGETS_GO:
- {
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
- if (!conditions.empty())
- {
- for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
- {
- if ((*i_spellST)->ConditionType != CONDITION_SPELL_SCRIPT_TARGET)
- continue;
- if ((*i_spellST)->ConditionValue3 && !((*i_spellST)->ConditionValue3 & effectMask))
- continue;
- if ((*i_spellST)->ConditionValue1 == SPELL_TARGET_TYPE_GAMEOBJECT)
- SearchGOAreaTarget(gobjectList, radius, pushType, SPELL_TARGETS_GO, (*i_spellST)->ConditionValue2);
- }
- }
- else
- {
- if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_ACTIVATE_OBJECT)
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) (caster Entry: %u) with SPELL_EFFECT_ACTIVATE_OBJECT does not have type CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET record in `conditions` table.", m_spellInfo->Id, m_caster->GetEntry());
- SearchGOAreaTarget(gobjectList, radius, pushType, SPELL_TARGETS_GO);
- }
- break;
- }
- case SPELL_TARGETS_ALLY:
- case SPELL_TARGETS_ENEMY:
- case SPELL_TARGETS_CHAINHEAL:
- case SPELL_TARGETS_ANY:
- SearchAreaTarget(unitList, radius, pushType, targetType);
- break;
- default:
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_SRC_AREA_PARTY:
- case TARGET_UNIT_DEST_AREA_PARTY:
- m_caster->GetPartyMemberInDist(unitList, radius); //fix me
- break;
- case TARGET_UNIT_LASTTARGET_AREA_PARTY:
- m_targets.GetUnitTarget()->GetPartyMemberInDist(unitList, radius);
- break;
- case TARGET_UNIT_CASTER_AREA_PARTY:
- m_caster->GetPartyMemberInDist(unitList, radius);
- break;
- case TARGET_UNIT_CASTER_AREA_RAID:
- m_caster->GetRaidMember(unitList, radius);
- break;
- case TARGET_UNIT_TARGET_AREA_RAID_CLASS:
- {
- Player* targetPlayer = m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetTypeId() == TYPEID_PLAYER
- ? (Player*)m_targets.GetUnitTarget() : NULL;
-
- Group* group = targetPlayer ? targetPlayer->GetGroup() : NULL;
- if (group)
- {
- for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
- {
- Player* Target = itr->getSource();
-
- // IsHostileTo check duel and controlled by enemy
- if (Target && targetPlayer->IsWithinDistInMap(Target, radius) && targetPlayer->getClass() == Target->getClass() && !m_caster->IsHostileTo(Target))
- AddUnitTarget(Target, effectMask);
- }
- }
- else if (m_targets.GetUnitTarget())
- AddUnitTarget(m_targets.GetUnitTarget(), effectMask);
- break;
- }
- default:
- break;
- }
- break;
- }
-
- if (!unitList.empty())
- {
- // Special target selection for smart heals and energizes
- uint32 maxSize = 0;
- int32 power = -1;
- switch (m_spellInfo->SpellFamilyName)
- {
- case SPELLFAMILY_GENERIC:
- switch (m_spellInfo->Id)
- {
- case 52759: // Ancestral Awakening
- case 71610: // Echoes of Light (Althor's Abacus normal version)
- case 71641: // Echoes of Light (Althor's Abacus heroic version)
- maxSize = 1;
- power = POWER_HEALTH;
- break;
- case 54968: // Glyph of Holy Light
- maxSize = m_spellInfo->MaxAffectedTargets;
- power = POWER_HEALTH;
- break;
- case 57669: // Replenishment
- // In arenas Replenishment may only affect the caster
- if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->InArena())
- {
- unitList.clear();
- unitList.push_back(m_caster);
- break;
- }
- maxSize = 10;
- power = POWER_MANA;
- break;
- default:
- break;
- }
- break;
- case SPELLFAMILY_PRIEST:
- if (m_spellInfo->SpellFamilyFlags[0] == 0x10000000) // Circle of Healing
- {
- maxSize = m_caster->HasAura(55675) ? 6 : 5; // Glyph of Circle of Healing
- power = POWER_HEALTH;
- }
- else if (m_spellInfo->Id == 64844) // Divine Hymn
- {
- maxSize = 3;
- power = POWER_HEALTH;
- }
- else if (m_spellInfo->Id == 64904) // Hymn of Hope
- {
- maxSize = 3;
- power = POWER_MANA;
- }
- else
- break;
-
- // Remove targets outside caster's raid
- for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();)
- {
- if (!(*itr)->IsInRaidWith(m_caster))
- itr = unitList.erase(itr);
- else
- ++itr;
- }
- break;
- case SPELLFAMILY_DRUID:
- if (m_spellInfo->SpellFamilyFlags[1] == 0x04000000) // Wild Growth
- {
- maxSize = m_caster->HasAura(62970) ? 6 : 5; // Glyph of Wild Growth
- power = POWER_HEALTH;
- }
- else if (m_spellInfo->SpellFamilyFlags[2] == 0x0100) // Starfall
- {
- // Remove targets not in LoS or in stealth
- for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();)
- {
- if ((*itr)->HasStealthAura() || (*itr)->HasInvisibilityAura() || !(*itr)->IsWithinLOSInMap(m_caster))
- itr = unitList.erase(itr);
- else
- ++itr;
- }
- break;
- }
- else
- break;
-
- // Remove targets outside caster's raid
- for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();)
- if (!(*itr)->IsInRaidWith(m_caster))
- itr = unitList.erase(itr);
- else
- ++itr;
- break;
- default:
- break;
- }
-
- if (maxSize && power != -1)
- {
- if (Powers(power) == POWER_HEALTH)
- {
- if (unitList.size() > maxSize)
- {
- unitList.sort(Trinity::HealthPctOrderPred());
- unitList.resize(maxSize);
- }
- }
- else
- {
- for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();)
- if ((*itr)->getPowerType() != (Powers)power)
- itr = unitList.erase(itr);
- else
- ++itr;
-
- if (unitList.size() > maxSize)
- {
- unitList.sort(Trinity::PowerPctOrderPred((Powers)power));
- unitList.resize(maxSize);
- }
- }
- }
-
- // Other special target selection goes here
- if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
- {
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- maxTargets += (*j)->GetAmount();
-
- if (m_spellInfo->Id == 5246) //Intimidating Shout
- unitList.remove(m_targets.GetUnitTarget());
- Trinity::RandomResizeList(unitList, maxTargets);
- }
-
- CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i));
-
- for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
- AddUnitTarget(*itr, effectMask, false);
- }
-
- if (!gobjectList.empty())
- {
- if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
- {
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- maxTargets += (*j)->GetAmount();
-
- Trinity::RandomResizeList(gobjectList, maxTargets);
- }
- for (std::list<GameObject*>::iterator itr = gobjectList.begin(); itr != gobjectList.end(); ++itr)
- AddGOTarget(*itr, effectMask);
- }
- }
-
- return effectMask;
-}
-
void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura)
{
if (m_CastItem)
@@ -6847,150 +6854,6 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value)
}
}
-float tangent(float x)
-{
- x = tan(x);
- //if (x < std::numeric_limits<float>::max() && x > -std::numeric_limits<float>::max()) return x;
- //if (x >= std::numeric_limits<float>::max()) return std::numeric_limits<float>::max();
- //if (x <= -std::numeric_limits<float>::max()) return -std::numeric_limits<float>::max();
- if (x < 100000.0f && x > -100000.0f) return x;
- if (x >= 100000.0f) return 100000.0f;
- if (x <= 100000.0f) return -100000.0f;
- return 0.0f;
-}
-
-#define DEBUG_TRAJ(a) //a
-
-void Spell::SelectTrajTargets()
-{
- if (!m_targets.HasTraj())
- return;
-
- float dist2d = m_targets.GetDist2d();
- if (!dist2d)
- return;
-
- float srcToDestDelta = m_targets.GetDst()->m_positionZ - m_targets.GetSrc()->m_positionZ;
-
- UnitList unitList;
- SearchAreaTarget(unitList, dist2d, PUSH_IN_THIN_LINE, SPELL_TARGETS_ANY);
- if (unitList.empty())
- return;
-
- unitList.sort(Trinity::ObjectDistanceOrderPred(m_caster));
-
- float b = tangent(m_targets.GetElevation());
- float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d);
- if (a > -0.0001f)
- a = 0;
- DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: a %f b %f", a, b);)
-
- float bestDist = m_spellInfo->GetMaxRange(false);
-
- UnitList::const_iterator itr = unitList.begin();
- for (; itr != unitList.end(); ++itr)
- {
- if (m_caster == *itr || m_caster->IsOnVehicle(*itr) || (*itr)->GetVehicle())//(*itr)->IsOnVehicle(m_caster))
- continue;
-
- const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3)
- // TODO: all calculation should be based on src instead of m_caster
- const float objDist2d = m_targets.GetSrc()->GetExactDist2d(*itr) * cos(m_targets.GetSrc()->GetRelativeAngle(*itr));
- const float dz = (*itr)->GetPositionZ() - m_targets.GetSrc()->m_positionZ;
-
- DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);)
-
- float dist = objDist2d - size;
- float height = dist * (a * dist + b);
- DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)
- if (dist < bestDist && height < dz + size && height > dz - size)
- {
- bestDist = dist > 0 ? dist : 0;
- break;
- }
-
-#define CHECK_DIST {\
- DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)\
- if (dist > bestDist)\
- continue;\
- if (dist < objDist2d + size && dist > objDist2d - size)\
- {\
- bestDist = dist;\
- break;\
- }\
- }
-
- if (!a)
- {
- height = dz - size;
- dist = height / b;
- CHECK_DIST;
-
- height = dz + size;
- dist = height / b;
- CHECK_DIST;
-
- continue;
- }
-
- height = dz - size;
- float sqrt1 = b * b + 4 * a * height;
- if (sqrt1 > 0)
- {
- sqrt1 = sqrt(sqrt1);
- dist = (sqrt1 - b) / (2 * a);
- CHECK_DIST;
- }
-
- height = dz + size;
- float sqrt2 = b * b + 4 * a * height;
- if (sqrt2 > 0)
- {
- sqrt2 = sqrt(sqrt2);
- dist = (sqrt2 - b) / (2 * a);
- CHECK_DIST;
-
- dist = (-sqrt2 - b) / (2 * a);
- CHECK_DIST;
- }
-
- if (sqrt1 > 0)
- {
- dist = (-sqrt1 - b) / (2 * a);
- CHECK_DIST;
- }
- }
-
- if (m_targets.GetSrc()->GetExactDist2d(m_targets.GetDst()) > bestDist)
- {
- float x = m_targets.GetSrc()->m_positionX + cos(m_caster->GetOrientation()) * bestDist;
- float y = m_targets.GetSrc()->m_positionY + sin(m_caster->GetOrientation()) * bestDist;
- float z = m_targets.GetSrc()->m_positionZ + bestDist * (a * bestDist + b);
-
- if (itr != unitList.end())
- {
- float distSq = (*itr)->GetExactDistSq(x, y, z);
- float sizeSq = (*itr)->GetObjectSize();
- sizeSq *= sizeSq;
- DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
- if (distSq > sizeSq)
- {
- float factor = 1 - sqrt(sizeSq / distSq);
- x += factor * ((*itr)->GetPositionX() - x);
- y += factor * ((*itr)->GetPositionY() - y);
- z += factor * ((*itr)->GetPositionZ() - z);
-
- distSq = (*itr)->GetExactDistSq(x, y, z);
- DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
- }
- }
-
- Position trajDst;
- trajDst.Relocate(x, y, z, m_caster->GetOrientation());
- m_targets.ModDst(trajDst);
- }
-}
-
void Spell::PrepareTargetProcessing()
{
CheckEffectExecuteData();
@@ -7342,3 +7205,152 @@ void Spell::CancelGlobalCooldown()
else if (m_caster->GetTypeId() == TYPEID_PLAYER)
m_caster->ToPlayer()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
}
+
+namespace Trinity
+{
+
+WorldObjectSpellTargetCheck::WorldObjectSpellTargetCheck(Unit* caster, Unit* referer, SpellInfo const* spellInfo,
+ SpellTargetCheckTypes selectionType, ConditionList* condList) : _caster(caster), _referer(referer), _spellInfo(spellInfo),
+ _condList(condList), _targetSelectionType(selectionType)
+{
+ if (condList)
+ _condSrcInfo = new ConditionSourceInfo(NULL, caster);
+ else
+ _condSrcInfo = NULL;
+}
+
+WorldObjectSpellTargetCheck::~WorldObjectSpellTargetCheck()
+{
+ if (_condSrcInfo)
+ delete _condSrcInfo;
+}
+
+bool WorldObjectSpellTargetCheck::operator()(WorldObject* target)
+{
+ if (_spellInfo->CheckTarget(_caster, target, true) != SPELL_CAST_OK)
+ return false;
+ Unit* unitTarget = target->ToUnit();
+ if (Corpse* corpseTarget = target->ToCorpse())
+ {
+ // use ofter for party/assistance checks
+ if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
+ unitTarget = owner;
+ else
+ return false;
+ }
+ if (unitTarget)
+ {
+ switch (_targetSelectionType)
+ {
+ case TARGET_CHECK_ENEMY:
+ if (unitTarget->isTotem())
+ return false;
+ if (!_caster->_IsValidAttackTarget(unitTarget, _spellInfo))
+ return false;
+ break;
+ case TARGET_CHECK_ALLY:
+ if (unitTarget->isTotem())
+ return false;
+ if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
+ return false;
+ break;
+ case TARGET_CHECK_PARTY:
+ if (unitTarget->isTotem())
+ return false;
+ if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
+ return false;
+ if (!_referer->IsInPartyWith(unitTarget))
+ return false;
+ break;
+ case TARGET_CHECK_RAID_CLASS:
+ if (_referer->getClass() != unitTarget->getClass())
+ return false;
+ // nobreak;
+ case TARGET_CHECK_RAID:
+ if (unitTarget->isTotem())
+ return false;
+ if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
+ return false;
+ if (!_referer->IsInRaidWith(unitTarget))
+ return false;
+ break;
+ default:
+ break;
+ }
+ }
+ if (!_condSrcInfo)
+ return true;
+ _condSrcInfo->mConditionTargets[0] = target;
+ return sConditionMgr->IsObjectMeetToConditions(*_condSrcInfo, *_condList);
+}
+
+WorldObjectSpellNearbyTargetCheck::WorldObjectSpellNearbyTargetCheck(float range, Unit* caster, SpellInfo const* spellInfo,
+ SpellTargetCheckTypes selectionType, ConditionList* condList)
+ : WorldObjectSpellTargetCheck(caster, caster, spellInfo, selectionType, condList), _range(range), _position(caster)
+{
+}
+
+bool WorldObjectSpellNearbyTargetCheck::operator()(WorldObject* target)
+{
+ float dist = target->GetDistance(*_position);
+ if (dist < _range && WorldObjectSpellTargetCheck::operator ()(target))
+ {
+ _range = dist;
+ return true;
+ }
+ return false;
+}
+
+WorldObjectSpellAreaTargetCheck::WorldObjectSpellAreaTargetCheck(float range, Position const* position, Unit* caster,
+ Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList)
+ : WorldObjectSpellTargetCheck(caster, referer, spellInfo, selectionType, condList), _range(range), _position(position)
+{
+}
+
+bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target)
+{
+ if (!target->IsWithinDist3d(_position, _range))
+ return false;
+ return WorldObjectSpellTargetCheck::operator ()(target);
+}
+
+WorldObjectSpellConeTargetCheck::WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster,
+ SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList)
+ : WorldObjectSpellAreaTargetCheck(range, caster, caster, caster, spellInfo, selectionType, condList), _coneAngle(coneAngle)
+{
+}
+
+bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target)
+{
+ if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_BACK)
+ {
+ if (!_caster->isInBack(target, _coneAngle))
+ return false;
+ }
+ else if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_LINE)
+ {
+ if (!_caster->HasInLine(target, _caster->GetObjectSize()))
+ return false;
+ }
+ else
+ {
+ if (!_caster->isInFront(target, _coneAngle))
+ return false;
+ }
+ return WorldObjectSpellAreaTargetCheck::operator ()(target);
+}
+
+WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo)
+ : WorldObjectSpellAreaTargetCheck(range, position, caster, caster, spellInfo, TARGET_CHECK_DEFAULT, NULL)
+{
+}
+
+bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target)
+{
+ // return all targets on missile trajectory (0 - size of a missile)
+ if (!_caster->HasInLine(target, 0))
+ return false;
+ return WorldObjectSpellAreaTargetCheck::operator ()(target);
+}
+
+} //namespace Trinity
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 583123eb261..5e7c3a94737 100755
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -79,19 +79,6 @@ enum SpellRangeFlag
SPELL_RANGE_RANGED = 2, //hunter range and ranged weapon
};
-enum SpellNotifyPushType
-{
- PUSH_NONE = 0,
- PUSH_IN_FRONT,
- PUSH_IN_BACK,
- PUSH_IN_LINE,
- PUSH_IN_THIN_LINE,
- PUSH_SRC_CENTER,
- PUSH_DST_CENTER,
- PUSH_CASTER_CENTER, //this is never used in grid search
- PUSH_CHAIN,
-};
-
class SpellCastTargets
{
public:
@@ -210,17 +197,6 @@ enum SpellEffectHandleMode
SPELL_EFFECT_HANDLE_HIT_TARGET,
};
-enum SpellTargets
-{
- SPELL_TARGETS_NONE = 0,
- SPELL_TARGETS_ALLY,
- SPELL_TARGETS_ENEMY,
- SPELL_TARGETS_ENTRY,
- SPELL_TARGETS_CHAINHEAL,
- SPELL_TARGETS_ANY,
- SPELL_TARGETS_GO
-};
-
namespace Trinity
{
struct SpellNotifierCreatureAndPlayer;
@@ -228,7 +204,6 @@ namespace Trinity
class Spell
{
- friend struct Trinity::SpellNotifierCreatureAndPlayer;
friend void Unit::SetCurrentCastedSpell(Spell* pSpell);
friend class SpellScript;
public:
@@ -364,6 +339,32 @@ class Spell
Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, uint64 originalCasterGUID = 0, bool skipCheck = false);
~Spell();
+ void InitExplicitTargets(SpellCastTargets const& targets);
+ void SelectExplicitTargets();
+
+ void SelectSpellTargets();
+ void SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask);
+ void SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask);
+ void SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask);
+ void SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask);
+ void SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask);
+ void SelectImplicitTrajTargets();
+
+ void SelectEffectTypeImplicitTargets(uint8 effIndex);
+
+ uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList);
+ template<class SEARCHER> void SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* referer, Position const* pos, float radius);
+
+ WorldObject* SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList = NULL);
+ void SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList);
+ void SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList* condList, bool isChainHeal);
+
void prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura = NULL);
void cancel();
void update(uint32 difftime);
@@ -404,15 +405,6 @@ class Spell
void WriteSpellGoTargets(WorldPacket* data);
void WriteAmmoToPacket(WorldPacket* data);
- void InitExplicitTargets(SpellCastTargets const& targets);
- void SelectExplicitTargets();
- void SelectSpellTargets();
- void SelectEffectTypeImplicitTargets(uint8 effIndex);
- uint32 SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur);
- void SelectTrajTargets();
-
- template<typename T> WorldObject* FindCorpseUsing();
-
bool CheckEffectTarget(Unit const* target, uint32 eff) const;
bool CanAutoCast(Unit* target);
void CheckSrc() { if (!m_targets.HasSrc()) m_targets.SetSrc(*m_caster); }
@@ -607,10 +599,6 @@ class Spell
void DoAllEffectOnTarget(GOTargetInfo* target);
void DoAllEffectOnTarget(ItemTargetInfo* target);
bool UpdateChanneledTargetList();
- void SearchAreaTarget(std::list<Unit*> &unitList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0);
- void SearchGOAreaTarget(std::list<GameObject*> &gobjectList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0);
- void SearchChainTarget(std::list<Unit*> &unitList, float radius, uint32 unMaxTargets, SpellTargets TargetType);
- WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex);
bool IsValidDeadOrAliveTarget(Unit const* target) const;
void HandleLaunchPhase();
void DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier);
@@ -676,98 +664,52 @@ class Spell
namespace Trinity
{
- struct SpellNotifierCreatureAndPlayer
+ struct WorldObjectSpellTargetCheck
{
- std::list<Unit*> *i_data;
- SpellNotifyPushType i_push_type;
- float i_radius;
- SpellTargets i_TargetType;
- const Unit* const i_source;
- uint32 i_entry;
- const Position* const i_pos;
- SpellInfo const* i_spellProto;
-
- SpellNotifierCreatureAndPlayer(Unit* source, std::list<Unit*> &data, float radius, SpellNotifyPushType type,
- SpellTargets TargetType = SPELL_TARGETS_ENEMY, const Position* pos = NULL, uint32 entry = 0, SpellInfo const* spellProto = NULL)
- : i_data(&data), i_push_type(type), i_radius(radius), i_TargetType(TargetType),
- i_source(source), i_entry(entry), i_pos(pos), i_spellProto(spellProto)
- {
- ASSERT(i_source);
- }
+ Unit* _caster;
+ Unit* _referer;
+ SpellInfo const* _spellInfo;
+ SpellTargetCheckTypes _targetSelectionType;
+ ConditionSourceInfo* _condSrcInfo;
+ ConditionList* _condList;
+
+ WorldObjectSpellTargetCheck(Unit* caster, Unit* referer, SpellInfo const* spellInfo,
+ SpellTargetCheckTypes selectionType, ConditionList* condList);
+ WorldObjectSpellTargetCheck::~WorldObjectSpellTargetCheck();
+ bool operator()(WorldObject* target);
+ };
- template<class T> inline void Visit(GridRefManager<T>& m)
- {
- for (typename GridRefManager<T>::iterator itr = m.begin(); itr != m.end(); ++itr)
- {
- Unit* target = (Unit*)itr->getSource();
-
- if (i_spellProto->CheckTarget(i_source, target, true) != SPELL_CAST_OK)
- continue;
-
- switch (i_TargetType)
- {
- case SPELL_TARGETS_ENEMY:
- if (target->isTotem())
- continue;
- if (!i_source->_IsValidAttackTarget(target, i_spellProto))
- continue;
- break;
- case SPELL_TARGETS_ALLY:
- if (target->isTotem())
- continue;
- if (!i_source->_IsValidAssistTarget(target, i_spellProto))
- continue;
- break;
- case SPELL_TARGETS_ENTRY:
- if (target->GetEntry()!= i_entry)
- continue;
- break;
- case SPELL_TARGETS_ANY:
- default:
- break;
- }
-
- switch (i_push_type)
- {
- case PUSH_SRC_CENTER:
- case PUSH_DST_CENTER:
- case PUSH_CHAIN:
- default:
- if (target->IsWithinDist3d(i_pos, i_radius))
- i_data->push_back(target);
- break;
- case PUSH_IN_FRONT:
- if (i_source->isInFront(target, i_radius, static_cast<float>(M_PI/2)))
- i_data->push_back(target);
- break;
- case PUSH_IN_BACK:
- if (i_source->isInBack(target, i_radius, static_cast<float>(M_PI/2)))
- i_data->push_back(target);
- break;
- case PUSH_IN_LINE:
- if (i_source->HasInLine(target, i_radius, i_source->GetObjectSize()))
- i_data->push_back(target);
- break;
- case PUSH_IN_THIN_LINE: // only traj
- if (i_pos->HasInLine(target, i_radius, 0))
- i_data->push_back(target);
- break;
- }
- }
- }
+ struct WorldObjectSpellNearbyTargetCheck : public WorldObjectSpellTargetCheck
+ {
+ float _range;
+ Position const* _position;
+ WorldObjectSpellNearbyTargetCheck(float range, Unit* caster, SpellInfo const* spellInfo,
+ SpellTargetCheckTypes selectionType, ConditionList* condList);
+ bool operator()(WorldObject* target);
+ };
+
+ struct WorldObjectSpellAreaTargetCheck : public WorldObjectSpellTargetCheck
+ {
+ float _range;
+ Position const* _position;
+ WorldObjectSpellAreaTargetCheck(float range, Position const* position, Unit* caster,
+ Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList);
+ bool operator()(WorldObject* target);
+ };
- #ifdef _WIN32
- template<> inline void Visit(CorpseMapType &) {}
- template<> inline void Visit(GameObjectMapType &) {}
- template<> inline void Visit(DynamicObjectMapType &) {}
- #endif
+ struct WorldObjectSpellConeTargetCheck : public WorldObjectSpellAreaTargetCheck
+ {
+ float _coneAngle;
+ WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster,
+ SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList);
+ bool operator()(WorldObject* target);
};
- #ifndef _WIN32
- template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType&) {}
- template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType&) {}
- template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType&) {}
- #endif
+ struct WorldObjectSpellTrajTargetCheck : public WorldObjectSpellAreaTargetCheck
+ {
+ WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo);
+ bool operator()(WorldObject* target);
+ };
}
typedef void(Spell::*pEffect)(SpellEffIndex effIndex);
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index ad465767ab0..6d5c802e64f 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -20,6 +20,7 @@
#include "SpellMgr.h"
#include "Spell.h"
#include "DBCStores.h"
+#include "ConditionMgr.h"
uint32 GetTargetFlagMask(SpellTargetObjectTypes objType)
{
@@ -80,7 +81,7 @@ SpellTargetObjectTypes SpellImplicitTargetInfo::GetObjectType() const
return _data[_target].ObjectType;
}
-SpellTargetSelectionCheckTypes SpellImplicitTargetInfo::GetSelectionCheckType() const
+SpellTargetCheckTypes SpellImplicitTargetInfo::GetCheckType() const
{
return _data[_target].SelectionCheckType;
}
@@ -158,23 +159,25 @@ uint32 SpellImplicitTargetInfo::GetExplicitTargetMask(bool& srcSet, bool& dstSet
case TARGET_OBJECT_TYPE_UNIT_AND_DEST:
case TARGET_OBJECT_TYPE_UNIT:
case TARGET_OBJECT_TYPE_DEST:
- switch (GetSelectionCheckType())
+ switch (GetCheckType())
{
- case TARGET_SELECT_CHECK_ENEMY:
+ case TARGET_CHECK_ENEMY:
targetMask = TARGET_FLAG_UNIT_ENEMY;
break;
- case TARGET_SELECT_CHECK_ALLY:
+ case TARGET_CHECK_ALLY:
targetMask = TARGET_FLAG_UNIT_ALLY;
break;
- case TARGET_SELECT_CHECK_PARTY:
+ case TARGET_CHECK_PARTY:
targetMask = TARGET_FLAG_UNIT_PARTY;
break;
- case TARGET_SELECT_CHECK_RAID:
+ case TARGET_CHECK_RAID:
targetMask = TARGET_FLAG_UNIT_RAID;
break;
- case TARGET_SELECT_CHECK_PASSENGER:
+ case TARGET_CHECK_PASSENGER:
targetMask = TARGET_FLAG_UNIT_PASSENGER;
break;
+ case TARGET_CHECK_RAID_CLASS:
+ // nobreak;
default:
targetMask = TARGET_FLAG_UNIT;
break;
@@ -344,117 +347,117 @@ SpellSelectTargetTypes SpellImplicitTargetInfo::Type[TOTAL_SPELL_TARGETS];
SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_TARGETS] =
{
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, //
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 1 TARGET_UNIT_CASTER
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 2 TARGET_UNIT_NEARBY_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 3 TARGET_UNIT_NEARBY_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 4 TARGET_UNIT_NEARBY_ALLY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 5 TARGET_UNIT_PET
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 6 TARGET_UNIT_TARGET_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 7 TARGET_UNIT_SRC_AREA_ENTRY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 8 TARGET_UNIT_DEST_AREA_ENTRY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 9 TARGET_DEST_HOME
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 10
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 11 TARGET_UNIT_SRC_AREA_UNK_11
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 12
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 13
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 14
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 15 TARGET_UNIT_SRC_AREA_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 16 TARGET_UNIT_DEST_AREA_ENEMY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 17 TARGET_DEST_DB
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 18 TARGET_DEST_CASTER
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 19
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 20 TARGET_UNIT_CASTER_AREA_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 21 TARGET_UNIT_TARGET_ALLY
- {TARGET_OBJECT_TYPE_SRC, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 22 TARGET_SRC_CASTER
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 23 TARGET_GAMEOBJECT_TARGET
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_FRONT}, // 24 TARGET_UNIT_CONE_ENEMY_24
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 25 TARGET_UNIT_TARGET_ANY
- {TARGET_OBJECT_TYPE_GOBJ_ITEM, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 26 TARGET_GAMEOBJECT_ITEM_TARGET
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 27 TARGET_UNIT_MASTER
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 28 TARGET_DEST_DYNOBJ_ENEMY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 29 TARGET_DEST_DYNOBJ_ALLY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 30 TARGET_UNIT_SRC_AREA_ALLY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 31 TARGET_UNIT_DEST_AREA_ALLY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 32 TARGET_DEST_CASTER_SUMMON
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 33 TARGET_UNIT_SRC_AREA_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 34 TARGET_UNIT_DEST_AREA_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 35 TARGET_UNIT_TARGET_PARTY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 36 TARGET_DEST_CASTER_UNK_36
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_LAST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 37 TARGET_UNIT_LASTTARGET_AREA_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 38 TARGET_UNIT_NEARBY_ENTRY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 39 TARGET_DEST_CASTER_FISHING
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 40 TARGET_GAMEOBJECT_NEARBY_ENTRY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 41 TARGET_DEST_CASTER_FRONT_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 42 TARGET_DEST_CASTER_BACK_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 43 TARGET_DEST_CASTER_BACK_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 44 TARGET_DEST_CASTER_FRONT_LEFT
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 45 TARGET_UNIT_TARGET_CHAINHEAL_ALLY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 46 TARGET_DEST_NEARBY_ENTRY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 47 TARGET_DEST_CASTER_FRONT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK}, // 48 TARGET_DEST_CASTER_BACK
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 49 TARGET_DEST_CASTER_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 50 TARGET_DEST_CASTER_LEFT
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 51 TARGET_GAMEOBJECT_SRC_AREA
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 52 TARGET_GAMEOBJECT_DEST_AREA
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 53 TARGET_DEST_TARGET_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_FRONT}, // 54 TARGET_UNIT_CONE_ENEMY_54
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 55 TARGET_DEST_CASTER_FRONT_LEAP
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 56 TARGET_UNIT_CASTER_AREA_RAID
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 57 TARGET_UNIT_TARGET_RAID
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 58 TARGET_UNIT_NEARBY_RAID
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_FRONT}, // 59 TARGET_UNIT_CONE_ALLY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_FRONT}, // 60 TARGET_UNIT_CONE_ENTRY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 61 TARGET_UNIT_TARGET_AREA_RAID_CLASS
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 62 TARGET_UNK_62
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 63 TARGET_DEST_TARGET_ANY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 64 TARGET_DEST_TARGET_FRONT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK}, // 65 TARGET_DEST_TARGET_BACK
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 66 TARGET_DEST_TARGET_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 67 TARGET_DEST_TARGET_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 68 TARGET_DEST_TARGET_FRONT_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 69 TARGET_DEST_TARGET_BACK_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 70 TARGET_DEST_TARGET_BACK_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 71 TARGET_DEST_TARGET_FRONT_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 72 TARGET_DEST_CASTER_RANDOM
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 73 TARGET_DEST_CASTER_RADIUS
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 74 TARGET_DEST_TARGET_RANDOM
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 75 TARGET_DEST_TARGET_RADIUS
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 76 TARGET_DEST_CHANNEL_TARGET
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 77 TARGET_UNIT_CHANNEL_TARGET
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 78 TARGET_DEST_DEST_FRONT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK}, // 79 TARGET_DEST_DEST_BACK
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 80 TARGET_DEST_DEST_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 81 TARGET_DEST_DEST_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 82 TARGET_DEST_DEST_FRONT_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 83 TARGET_DEST_DEST_BACK_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 84 TARGET_DEST_DEST_BACK_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 85 TARGET_DEST_DEST_FRONT_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 86 TARGET_DEST_DEST_RANDOM
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 87 TARGET_DEST_DEST
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 88 TARGET_DEST_DYNOBJ_NONE
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 89 TARGET_DEST_TRAJ
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 90 TARGET_UNIT_TARGET_MINIPET
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 91 TARGET_DEST_DEST_RADIUS
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 92 TARGET_UNIT_SUMMONER
- {TARGET_OBJECT_TYPE_CORPSE, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 93 TARGET_CORPSE_SRC_AREA_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 94 TARGET_UNIT_VEHICLE
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_PASSENGER, TARGET_DIR_NONE}, // 95 TARGET_UNIT_TARGET_PASSENGER
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 96 TARGET_UNIT_PASSENGER_0
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 97 TARGET_UNIT_PASSENGER_1
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 98 TARGET_UNIT_PASSENGER_2
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 99 TARGET_UNIT_PASSENGER_3
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 100 TARGET_UNIT_PASSENGER_4
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 101 TARGET_UNIT_PASSENGER_5
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 102 TARGET_UNIT_PASSENGER_6
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 103 TARGET_UNIT_PASSENGER_7
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_FRONT}, // 104 TARGET_UNIT_CONE_ENEMY_104
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 105 TARGET_UNIT_UNK_105
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 106 TARGET_DEST_CHANNEL_CASTER
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 107 TARGET_UNK_DEST_AREA_UNK_107
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 110 TARGET_DEST_UNK_110
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, //
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 1 TARGET_UNIT_CASTER
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 2 TARGET_UNIT_NEARBY_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 3 TARGET_UNIT_NEARBY_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 4 TARGET_UNIT_NEARBY_ALLY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 5 TARGET_UNIT_PET
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 6 TARGET_UNIT_TARGET_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 7 TARGET_UNIT_SRC_AREA_ENTRY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 8 TARGET_UNIT_DEST_AREA_ENTRY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 9 TARGET_DEST_HOME
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 10
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 11 TARGET_UNIT_SRC_AREA_UNK_11
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 12
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 13
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 14
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 15 TARGET_UNIT_SRC_AREA_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 16 TARGET_UNIT_DEST_AREA_ENEMY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 17 TARGET_DEST_DB
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 18 TARGET_DEST_CASTER
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 19
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 20 TARGET_UNIT_CASTER_AREA_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 21 TARGET_UNIT_TARGET_ALLY
+ {TARGET_OBJECT_TYPE_SRC, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 22 TARGET_SRC_CASTER
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 23 TARGET_GAMEOBJECT_TARGET
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENEMY, TARGET_DIR_FRONT}, // 24 TARGET_UNIT_CONE_ENEMY_24
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 25 TARGET_UNIT_TARGET_ANY
+ {TARGET_OBJECT_TYPE_GOBJ_ITEM, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 26 TARGET_GAMEOBJECT_ITEM_TARGET
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 27 TARGET_UNIT_MASTER
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 28 TARGET_DEST_DYNOBJ_ENEMY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 29 TARGET_DEST_DYNOBJ_ALLY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 30 TARGET_UNIT_SRC_AREA_ALLY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 31 TARGET_UNIT_DEST_AREA_ALLY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 32 TARGET_DEST_CASTER_SUMMON
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 33 TARGET_UNIT_SRC_AREA_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 34 TARGET_UNIT_DEST_AREA_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 35 TARGET_UNIT_TARGET_PARTY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 36 TARGET_DEST_CASTER_UNK_36
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_LAST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 37 TARGET_UNIT_LASTTARGET_AREA_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 38 TARGET_UNIT_NEARBY_ENTRY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 39 TARGET_DEST_CASTER_FISHING
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 40 TARGET_GAMEOBJECT_NEARBY_ENTRY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 41 TARGET_DEST_CASTER_FRONT_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 42 TARGET_DEST_CASTER_BACK_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 43 TARGET_DEST_CASTER_BACK_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 44 TARGET_DEST_CASTER_FRONT_LEFT
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 45 TARGET_UNIT_TARGET_CHAINHEAL_ALLY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 46 TARGET_DEST_NEARBY_ENTRY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 47 TARGET_DEST_CASTER_FRONT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK}, // 48 TARGET_DEST_CASTER_BACK
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 49 TARGET_DEST_CASTER_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 50 TARGET_DEST_CASTER_LEFT
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 51 TARGET_GAMEOBJECT_SRC_AREA
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 52 TARGET_GAMEOBJECT_DEST_AREA
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 53 TARGET_DEST_TARGET_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENEMY, TARGET_DIR_FRONT}, // 54 TARGET_UNIT_CONE_ENEMY_54
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 55 TARGET_DEST_CASTER_FRONT_LEAP
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 56 TARGET_UNIT_CASTER_AREA_RAID
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 57 TARGET_UNIT_TARGET_RAID
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 58 TARGET_UNIT_NEARBY_RAID
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ALLY, TARGET_DIR_FRONT}, // 59 TARGET_UNIT_CONE_ALLY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENTRY, TARGET_DIR_FRONT}, // 60 TARGET_UNIT_CONE_ENTRY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_RAID_CLASS,TARGET_DIR_NONE}, // 61 TARGET_UNIT_TARGET_AREA_RAID_CLASS
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 62 TARGET_UNK_62
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 63 TARGET_DEST_TARGET_ANY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 64 TARGET_DEST_TARGET_FRONT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK}, // 65 TARGET_DEST_TARGET_BACK
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 66 TARGET_DEST_TARGET_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 67 TARGET_DEST_TARGET_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 68 TARGET_DEST_TARGET_FRONT_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 69 TARGET_DEST_TARGET_BACK_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 70 TARGET_DEST_TARGET_BACK_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 71 TARGET_DEST_TARGET_FRONT_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 72 TARGET_DEST_CASTER_RANDOM
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 73 TARGET_DEST_CASTER_RADIUS
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 74 TARGET_DEST_TARGET_RANDOM
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 75 TARGET_DEST_TARGET_RADIUS
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 76 TARGET_DEST_CHANNEL_TARGET
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 77 TARGET_UNIT_CHANNEL_TARGET
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 78 TARGET_DEST_DEST_FRONT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK}, // 79 TARGET_DEST_DEST_BACK
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 80 TARGET_DEST_DEST_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 81 TARGET_DEST_DEST_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 82 TARGET_DEST_DEST_FRONT_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 83 TARGET_DEST_DEST_BACK_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 84 TARGET_DEST_DEST_BACK_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 85 TARGET_DEST_DEST_FRONT_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 86 TARGET_DEST_DEST_RANDOM
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 87 TARGET_DEST_DEST
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 88 TARGET_DEST_DYNOBJ_NONE
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 89 TARGET_DEST_TRAJ
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 90 TARGET_UNIT_TARGET_MINIPET
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 91 TARGET_DEST_DEST_RADIUS
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 92 TARGET_UNIT_SUMMONER
+ {TARGET_OBJECT_TYPE_CORPSE, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 93 TARGET_CORPSE_SRC_AREA_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 94 TARGET_UNIT_VEHICLE
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_PASSENGER, TARGET_DIR_NONE}, // 95 TARGET_UNIT_TARGET_PASSENGER
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 96 TARGET_UNIT_PASSENGER_0
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 97 TARGET_UNIT_PASSENGER_1
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 98 TARGET_UNIT_PASSENGER_2
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 99 TARGET_UNIT_PASSENGER_3
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 100 TARGET_UNIT_PASSENGER_4
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 101 TARGET_UNIT_PASSENGER_5
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 102 TARGET_UNIT_PASSENGER_6
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 103 TARGET_UNIT_PASSENGER_7
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENEMY, TARGET_DIR_FRONT}, // 104 TARGET_UNIT_CONE_ENEMY_104
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 105 TARGET_UNIT_UNK_105
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 106 TARGET_DEST_CHANNEL_CASTER
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 107 TARGET_UNK_DEST_AREA_UNK_107
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 110 TARGET_DEST_UNK_110
};
SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex)
@@ -481,6 +484,7 @@ SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const*
ItemType = spellEntry->EffectItemType[effIndex];
TriggerSpell = spellEntry->EffectTriggerSpell[effIndex];
SpellClassMask = spellEntry->EffectSpellClassMask[effIndex];
+ ImplicitTargetConditions = NULL;
}
bool SpellEffectInfo::IsEffect() const
@@ -938,6 +942,11 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry)
ChainEntry = NULL;
}
+SpellInfo::~SpellInfo()
+{
+ _UnloadImplicitTargetConditionLists();
+}
+
bool SpellInfo::HasEffect(SpellEffects effect) const
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -1563,38 +1572,99 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
return SPELL_CAST_OK;
}
-SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, bool implicit) const
+SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* target, bool implicit) const
{
if (AttributesEx & SPELL_ATTR1_CANT_TARGET_SELF && caster == target)
return SPELL_FAILED_BAD_TARGETS;
- if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT && target->isInCombat())
- return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
+ // check visibility - ignore stealth for implicit (area) targets
+ if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE) && !caster->canSeeOrDetect(target, implicit))
+ return SPELL_FAILED_BAD_TARGETS;
+
+ Unit const* unitTarget;
+
+ // creature/player specific target checks
+ if (unitTarget = target->ToUnit())
+ {
+ if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT && unitTarget->isInCombat())
+ return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
+
+ // only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts
+ if (((AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS) != 0) != unitTarget->HasAuraType(SPELL_AURA_GHOST))
+ {
+ if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS)
+ return SPELL_FAILED_TARGET_NOT_GHOST;
+ else
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+
+ if (caster != unitTarget)
+ {
+ if (caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
+ if (AttributesEx2 & SPELL_ATTR2_CANT_TARGET_TAPPED)
+ if (Creature const* targetCreature = unitTarget->ToCreature())
+ if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer()))
+ return SPELL_FAILED_CANT_CAST_ON_TAPPED;
+
+ if (AttributesCu & SPELL_ATTR0_CU_PICKPOCKET)
+ {
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER)
+ return SPELL_FAILED_BAD_TARGETS;
+ else if ((unitTarget->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0)
+ return SPELL_FAILED_TARGET_NO_POCKETS;
+ }
+
+ // Not allow disarm unarmed player
+ if (Mechanic == MECHANIC_DISARM)
+ {
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER)
+ {
+ Player const* player = unitTarget->ToPlayer();
+ if (!player->GetWeaponForAttack(BASE_ATTACK) || !player->IsUseEquipedWeapon(true))
+ return SPELL_FAILED_TARGET_NO_WEAPONS;
+ }
+ else if (!unitTarget->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID))
+ return SPELL_FAILED_TARGET_NO_WEAPONS;
+ }
+ }
+ }
+ }
+ // corpse specific target checks
+ else if (Corpse const* corpseTarget = target->ToCorpse())
+ {
+ // cannot target bare bones
+ if (corpseTarget->GetType() == CORPSE_BONES)
+ return SPELL_FAILED_BAD_TARGETS;
+ // we have to use owner for some checks (aura preventing resurrection for example)
+ if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
+ unitTarget = owner;
+ // we're not interested in corpses without owner
+ else
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+ // other types of objects - always valid
+ else return SPELL_CAST_OK;
- if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS && !target->ToPlayer())
+ // corpseOwner and unit specific target checks
+ if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS && !unitTarget->ToPlayer())
return SPELL_FAILED_TARGET_NOT_PLAYER;
- if (!IsAllowingDeadTarget() && !target->isAlive())
+ if (!IsAllowingDeadTarget() && !unitTarget->isAlive())
return SPELL_FAILED_TARGETS_DEAD;
- if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS && !(!target->isAlive() && target->HasAuraType(SPELL_AURA_GHOST)))
- return SPELL_FAILED_TARGET_NOT_GHOST;
-
// check this flag only for implicit targets (chain and area), allow to explicitly target units for spells like Shield of Righteousness
- if (implicit && AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED && !target->CanFreeMove())
+ if (implicit && AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED && !unitTarget->CanFreeMove())
return SPELL_FAILED_BAD_TARGETS;
- // check visibility - ignore stealth for implicit (area) targets
- if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE) && !caster->canSeeOrDetect(target, implicit))
- return SPELL_FAILED_BAD_TARGETS;
-
// checked in Unit::IsValidAttack/AssistTarget, shouldn't be checked for ENTRY targets
//if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_UNTARGETABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
// return SPELL_FAILED_BAD_TARGETS;
//if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_POSSESSED_FRIENDS)
- if (!CheckTargetCreatureType(target))
+ if (!CheckTargetCreatureType(unitTarget))
{
if (target->GetTypeId() == TYPEID_PLAYER)
return SPELL_FAILED_TARGET_IS_PLAYER;
@@ -1603,65 +1673,32 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, b
}
// check GM mode and GM invisibility - only for player casts (npc casts are controlled by AI) and negative spells
- if (target != caster && (caster->IsControlledByPlayer() || !IsPositive()) && target->GetTypeId() == TYPEID_PLAYER)
+ if (unitTarget != caster && (caster->IsControlledByPlayer() || !IsPositive()) && unitTarget->GetTypeId() == TYPEID_PLAYER)
{
- if (!target->ToPlayer()->IsVisible())
+ if (!unitTarget->ToPlayer()->IsVisible())
return SPELL_FAILED_BM_OR_INVISGOD;
- if (target->ToPlayer()->isGameMaster())
+ if (unitTarget->ToPlayer()->isGameMaster())
return SPELL_FAILED_BM_OR_INVISGOD;
}
// not allow casting on flying player
- if (target->HasUnitState(UNIT_STATE_IN_FLIGHT))
+ if (unitTarget->HasUnitState(UNIT_STATE_IN_FLIGHT))
return SPELL_FAILED_BAD_TARGETS;
- if (TargetAuraState && !target->HasAuraState(AuraStateType(TargetAuraState), this, caster))
+ if (TargetAuraState && !unitTarget->HasAuraState(AuraStateType(TargetAuraState), this, caster))
return SPELL_FAILED_TARGET_AURASTATE;
- if (TargetAuraStateNot && target->HasAuraState(AuraStateType(TargetAuraStateNot), this, caster))
+ if (TargetAuraStateNot && unitTarget->HasAuraState(AuraStateType(TargetAuraStateNot), this, caster))
return SPELL_FAILED_TARGET_AURASTATE;
- if (TargetAuraSpell && !target->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster)))
+ if (TargetAuraSpell && !unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster)))
return SPELL_FAILED_TARGET_AURASTATE;
- if (ExcludeTargetAuraSpell && target->HasAura(sSpellMgr->GetSpellIdForDifficulty(ExcludeTargetAuraSpell, caster)))
+ if (ExcludeTargetAuraSpell && unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(ExcludeTargetAuraSpell, caster)))
return SPELL_FAILED_TARGET_AURASTATE;
- if (caster != target)
- {
- if (caster->GetTypeId() == TYPEID_PLAYER)
- {
- // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
- if (AttributesEx2 & SPELL_ATTR2_CANT_TARGET_TAPPED)
- if (Creature const* targetCreature = target->ToCreature())
- if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer()))
- return SPELL_FAILED_CANT_CAST_ON_TAPPED;
-
- if (AttributesCu & SPELL_ATTR0_CU_PICKPOCKET)
- {
- if (target->GetTypeId() == TYPEID_PLAYER)
- return SPELL_FAILED_BAD_TARGETS;
- else if ((target->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0)
- return SPELL_FAILED_TARGET_NO_POCKETS;
- }
-
- // Not allow disarm unarmed player
- if (Mechanic == MECHANIC_DISARM)
- {
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- Player const* player = target->ToPlayer();
- if (!player->GetWeaponForAttack(BASE_ATTACK) || !player->IsUseEquipedWeapon(true))
- return SPELL_FAILED_TARGET_NO_WEAPONS;
- }
- else if (!target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID))
- return SPELL_FAILED_TARGET_NO_WEAPONS;
- }
- }
- }
-
- if (target->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION))
+ if (unitTarget->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION))
if (HasEffect(SPELL_EFFECT_SELF_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT_NEW))
return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED;
@@ -2035,13 +2072,19 @@ float SpellInfo::GetMinRange(bool positive) const
return RangeEntry->minRangeHostile;
}
-float SpellInfo::GetMaxRange(bool positive) const
+float SpellInfo::GetMaxRange(bool positive, Unit* caster, Spell* spell) const
{
if (!RangeEntry)
return 0.0f;
+ float range;
if (positive)
- return RangeEntry->maxRangeFriend;
- return RangeEntry->maxRangeHostile;
+ range = RangeEntry->maxRangeFriend;
+ else
+ range = RangeEntry->maxRangeHostile;
+ if (caster)
+ if (Player* modOwner = caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(Id, SPELLMOD_RANGE, range, spell);
+ return range;
}
int32 SpellInfo::GetDuration() const
@@ -2552,3 +2595,20 @@ bool SpellInfo::_IsPositiveTarget(uint32 targetA, uint32 targetB)
return _IsPositiveTarget(targetB, 0);
return true;
}
+
+void SpellInfo::_UnloadImplicitTargetConditionLists()
+{
+ // find the same instances of ConditionList and delete them.
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ ConditionList* cur = Effects[i].ImplicitTargetConditions;
+ if (!cur)
+ continue;
+ for (uint8 j = i; j < MAX_SPELL_EFFECTS; ++j)
+ {
+ if (Effects[j].ImplicitTargetConditions == cur)
+ Effects[j].ImplicitTargetConditions = NULL;
+ }
+ delete cur;
+ }
+}
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 65be5981c64..69ea07f7563 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -36,6 +36,7 @@ struct SpellRangeEntry;
struct SpellRadiusEntry;
struct SpellEntry;
struct SpellCastTimesEntry;
+struct Condition;
enum SpellCastTargetFlags
{
@@ -105,15 +106,16 @@ enum SpellTargetObjectTypes
TARGET_OBJECT_TYPE_CORPSE_ALLY,
};
-enum SpellTargetSelectionCheckTypes
+enum SpellTargetCheckTypes
{
- TARGET_SELECT_CHECK_DEFAULT,
- TARGET_SELECT_CHECK_ENTRY,
- TARGET_SELECT_CHECK_ENEMY,
- TARGET_SELECT_CHECK_ALLY,
- TARGET_SELECT_CHECK_PARTY,
- TARGET_SELECT_CHECK_RAID,
- TARGET_SELECT_CHECK_PASSENGER,
+ TARGET_CHECK_DEFAULT,
+ TARGET_CHECK_ENTRY,
+ TARGET_CHECK_ENEMY,
+ TARGET_CHECK_ALLY,
+ TARGET_CHECK_PARTY,
+ TARGET_CHECK_RAID,
+ TARGET_CHECK_RAID_CLASS,
+ TARGET_CHECK_PASSENGER,
};
enum SpellTargetDirectionTypes
@@ -220,7 +222,7 @@ public:
SpellTargetSelectionCategories GetSelectionCategory() const;
SpellTargetReferenceTypes GetReferenceType() const;
SpellTargetObjectTypes GetObjectType() const;
- SpellTargetSelectionCheckTypes GetSelectionCheckType() const;
+ SpellTargetCheckTypes GetCheckType() const;
SpellTargetDirectionTypes GetDirectionType() const;
float CalcDirectionAngle() const;
@@ -240,7 +242,7 @@ private:
SpellTargetObjectTypes ObjectType; // type of object returned by target type
SpellTargetReferenceTypes ReferenceType; // defines which object is used as a reference when selecting target
SpellTargetSelectionCategories SelectionCategory;
- SpellTargetSelectionCheckTypes SelectionCheckType; // defines selection criteria
+ SpellTargetCheckTypes SelectionCheckType; // defines selection criteria
SpellTargetDirectionTypes DirectionType; // direction for cone and dest targets
};
static StaticData _data[TOTAL_SPELL_TARGETS];
@@ -271,6 +273,7 @@ public:
uint32 ItemType;
uint32 TriggerSpell;
flag96 SpellClassMask;
+ std::list<Condition*>* ImplicitTargetConditions;
SpellEffectInfo() {}
SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex);
@@ -388,6 +391,7 @@ public:
SpellChainNode const* ChainEntry;
SpellInfo(SpellEntry const* spellEntry);
+ ~SpellInfo();
bool HasEffect(SpellEffects effect) const;
bool HasAura(AuraType aura) const;
@@ -438,7 +442,7 @@ public:
SpellCastResult CheckShapeshift(uint32 form) const;
SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const;
- SpellCastResult CheckTarget(Unit const* caster, Unit const* target, bool implicit = true) const;
+ SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const;
SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const;
bool CheckTargetCreatureType(Unit const* target) const;
@@ -456,7 +460,7 @@ public:
SpellSpecificType GetSpellSpecific() const;
float GetMinRange(bool positive = false) const;
- float GetMaxRange(bool positive = false) const;
+ float GetMaxRange(bool positive = false, Unit* caster = NULL, Spell* spell = NULL) const;
int32 GetDuration() const;
int32 GetMaxDuration() const;
@@ -482,6 +486,9 @@ public:
bool _IsPositiveEffect(uint8 effIndex, bool deep) const;
bool _IsPositiveSpell() const;
static bool _IsPositiveTarget(uint32 targetA, uint32 targetB);
+
+ // unloading helpers
+ void _UnloadImplicitTargetConditionLists();
};
#endif // _SPELLINFO_H
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index ff4eaae42f2..c1b267d9fac 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -2644,11 +2644,20 @@ void SpellMgr::UnloadSpellInfoStore()
for (uint32 i = 0; i < mSpellInfoMap.size(); ++i)
{
if (mSpellInfoMap[i])
- delete mSpellInfoMap[i];
+ delete mSpellInfoMap[i];
}
mSpellInfoMap.clear();
}
+void SpellMgr::UnloadSpellInfoImplicitTargetConditionLists()
+{
+ for (uint32 i = 0; i < mSpellInfoMap.size(); ++i)
+ {
+ if (mSpellInfoMap[i])
+ mSpellInfoMap[i]->_UnloadImplicitTargetConditionLists();
+ }
+}
+
void SpellMgr::LoadSpellCustomAttr()
{
uint32 oldMSTime = getMSTime();
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 14137b6a91b..9fffd474651 100755
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -360,17 +360,6 @@ struct SpellThreatEntry
typedef std::map<uint32, SpellThreatEntry> SpellThreatMap;
-// Spell script target related declarations (accessed using SpellMgr functions)
-enum SpellScriptTargetType
-{
- SPELL_TARGET_TYPE_GAMEOBJECT = 0,
- SPELL_TARGET_TYPE_CREATURE = 1,
- SPELL_TARGET_TYPE_DEAD = 2,
- SPELL_TARGET_TYPE_CONTROLLED = 3,
-};
-
-#define MAX_SPELL_TARGET_TYPE 4
-
// coordinates for spells (accessed using SpellMgr functions)
struct SpellTargetPosition
{
@@ -726,6 +715,7 @@ class SpellMgr
void LoadSpellAreas();
void LoadSpellInfoStore();
void UnloadSpellInfoStore();
+ void UnloadSpellInfoImplicitTargetConditionLists();
void LoadSpellCustomAttr();
void LoadDbcDataCorrections();
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 14dd32a71b6..03fea614c0d 100755
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -473,11 +473,6 @@ void SpellScript::GetSummonPosition(uint32 i, Position &pos, float radius = 0.0f
m_spell->GetSummonPosition(i, pos, radius, count);
}
-void SpellScript::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry)
-{
- m_spell->SearchAreaTarget(TagUnitMap, radius, type, TargetType, entry);
-}
-
void SpellScript::PreventHitEffect(SpellEffIndex effIndex)
{
if (!IsInHitPhase() && !IsInEffectHook())
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 09b9eaebd62..1bf8d25adef 100755
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -336,7 +336,6 @@ class SpellScript : public _SpellScript
void PreventHitHeal() { SetHitHeal(0); }
Spell* GetSpell() { return m_spell; }
void GetSummonPosition(uint32 i, Position &pos, float radius, uint32 count);
- void SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry);
// returns current spell hit target aura
Aura* GetHitAura();
// prevents applying aura on current spell hit target
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
index d5695a0f39d..19ed96e8885 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp
@@ -62,7 +62,7 @@ class OrientationCheck : public std::unary_function<Unit*, bool>
explicit OrientationCheck(Unit* _caster) : caster(_caster) { }
bool operator() (Unit* unit)
{
- return !unit->isInFront(caster, 40.0f, 2.5f);
+ return !unit->isInFront(caster, 2.5f) || !unit->IsWithinDist(caster, 40.0f);
}
private:
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
index da46d016e91..c4f973726bc 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
@@ -1736,25 +1736,29 @@ class spell_vehicle_throw_passenger : public SpellScriptLoader
if (Vehicle* vehicle = GetCaster()->GetVehicleKit())
if (Unit* passenger = vehicle->GetPassenger(damage - 1))
{
- std::list<Unit*> unitList;
// use 99 because it is 3d search
- SearchAreaTarget(unitList, 99, PUSH_DST_CENTER, SPELL_TARGETS_ENTRY, NPC_SEAT);
+ std::list<WorldObject*> targetList;
+ Trinity::WorldObjectSpellAreaTargetCheck check(99, GetTargetDest(), GetCaster(), GetCaster(), GetSpellInfo(), TARGET_CHECK_DEFAULT, NULL);
+ Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(GetCaster(), targetList, check);
+ GetCaster()->GetMap()->VisitAll(GetCaster()->m_positionX, GetCaster()->m_positionY, 99, searcher);
float minDist = 99 * 99;
Unit* target = NULL;
- for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
+ for (std::list<WorldObject*>::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
{
- if (Vehicle* seat = (*itr)->GetVehicleKit())
- if (!seat->GetPassenger(0))
- if (Unit* device = seat->GetPassenger(2))
- if (!device->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
- {
- float dist = (*itr)->GetExactDistSq(targets.GetDst());
- if (dist < minDist)
- {
- minDist = dist;
- target = (*itr);
- }
- }
+ if (Unit* unit = (*itr)->ToUnit())
+ if (unit->GetEntry() == NPC_SEAT)
+ if (Vehicle* seat = unit->GetVehicleKit())
+ if (!seat->GetPassenger(0))
+ if (Unit* device = seat->GetPassenger(2))
+ if (!device->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
+ {
+ float dist = unit->GetExactDistSq(targets.GetDst());
+ if (dist < minDist)
+ {
+ minDist = dist;
+ target = unit;
+ }
+ }
}
if (target && target->IsWithinDist2d(targets.GetDst(), GetSpellInfo()->Effects[effIndex].CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct
passenger->EnterVehicle(target, 0);
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 638a17bc4f9..3835cb8ca0f 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -196,7 +196,7 @@ class spell_gen_cannibalize : public SpellScriptLoader
float max_range = GetSpellInfo()->GetMaxRange(false);
WorldObject* result = NULL;
// search for nearby enemy corpse in range
- Trinity::AnyDeadUnitSpellTargetInRangeCheck check(caster, max_range, GetSpellInfo(), TARGET_SELECT_CHECK_ENEMY);
+ Trinity::AnyDeadUnitSpellTargetInRangeCheck check(caster, max_range, GetSpellInfo(), TARGET_CHECK_ENEMY);
Trinity::WorldObjectSearcher<Trinity::AnyDeadUnitSpellTargetInRangeCheck> searcher(caster, result, check);
caster->GetMap()->VisitFirstFound(caster->m_positionX, caster->m_positionY, max_range, searcher);
if (!result)
diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp
index dd9bfd90a0b..855af75cd83 100644
--- a/src/server/scripts/Spells/spell_hunter.cpp
+++ b/src/server/scripts/Spells/spell_hunter.cpp
@@ -532,7 +532,7 @@ class spell_hun_pet_carrion_feeder : public SpellScriptLoader
float max_range = GetSpellInfo()->GetMaxRange(false);
WorldObject* result = NULL;
// search for nearby enemy corpse in range
- Trinity::AnyDeadUnitSpellTargetInRangeCheck check(caster, max_range, GetSpellInfo(), TARGET_SELECT_CHECK_ENEMY);
+ Trinity::AnyDeadUnitSpellTargetInRangeCheck check(caster, max_range, GetSpellInfo(), TARGET_CHECK_ENEMY);
Trinity::WorldObjectSearcher<Trinity::AnyDeadUnitSpellTargetInRangeCheck> searcher(caster, result, check);
caster->GetMap()->VisitFirstFound(caster->m_positionX, caster->m_positionY, max_range, searcher);
if (!result)