diff --git a/common/bodytypes.h b/common/bodytypes.h index fd64b1825..0528e14f6 100644 --- a/common/bodytypes.h +++ b/common/bodytypes.h @@ -27,16 +27,17 @@ typedef enum { BT_Extraplanar = 6, BT_Magical = 7, //this name might be a bit off, BT_SummonedUndead = 8, - BT_RaidGiant = 9, - // ... + BT_RaidGiant = 9, //Velious era Raid Giant + BT_RaidColdain = 10, //Velious era Raid Coldain BT_NoTarget = 11, //no name, can't target this bodytype BT_Vampire = 12, BT_Atenha_Ra = 13, BT_Greater_Akheva = 14, BT_Khati_Sha = 15, - BT_Seru = 16, //not confirmed.... + BT_Seru = 16, + BT_Grieg_Veneficus = 17, BT_Draz_Nurakk = 18, - BT_Zek = 19, + BT_Zek = 19, //"creatures from the Plane of War." BT_Luggald = 20, BT_Animal = 21, BT_Insect = 22, @@ -46,17 +47,18 @@ typedef enum { BT_Dragon = 26, BT_Summoned2 = 27, BT_Summoned3 = 28, - //29 + BT_Dragon2 = 29, //database data indicates this is a dragon type (kunark and DoN?) BT_VeliousDragon = 30, //might not be a tight set - // ... + BT_Familiar = 31, BT_Dragon3 = 32, BT_Boxes = 33, BT_Muramite = 34, //tribal dudes // ... BT_NoTarget2 = 60, // ... - BT_SwarmPet = 63, //is this valid, or made up? - // ... + BT_SwarmPet = 63, //Looks like weapon proc related temp pets and few misc pets, should not be used for checking swarm pets in general. + BT_MonsterSummon = 64, + // 65, trap or effect related? BT_InvisMan = 66, //no name, seen on 'InvisMan', can be /targeted BT_Special = 67 } bodyType; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 258450200..042f0cf6a 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1883,6 +1883,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].override_crit_chance = atoi(row[217]); sp[tempid].aemaxtargets = atoi(row[218]); sp[tempid].no_heal_damage_item_mod = atoi(row[219]); + sp[tempid].caster_requirement_id = atoi(row[220]); sp[tempid].spell_class = atoi(row[221]); sp[tempid].spell_subclass = atoi(row[222]); sp[tempid].persistdeath = atoi(row[224]) != 0; diff --git a/common/spdat.h b/common/spdat.h index b39ee4904..a63df94cc 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -155,6 +155,17 @@ #define SPELL_RESURRECTION_SICKNESS 756 #define SPELL_RESURRECTION_SICKNESS2 5249 #define SPELL_REVIVAL_SICKNESS 13087 +#define SPELL_PACT_OF_HATE_RECOURSE 40375 +#define SPELL_INCENDIARY_OOZE_BUFF 32513 + +//spellgroup ids +#define SPELLGROUP_FRENZIED_BURNOUT 2754 +#define SPELLGROUP_ILLUSION_OF_GRANDEUR 38603 +#define SPELLGROUP_ROGUES_FURY 16861 +#define SPELLGROUP_HARMONIOUS_PRECISION 15634 +#define SPELLGROUP_HARMONIOUS_EXPANSE 15633 +#define SPELLGROUP_FURIOUS_RAMPAGE 38106 +#define SPELLGROUP_SHROUD_OF_PRAYER 41050 @@ -189,6 +200,306 @@ enum FocusLimitIncludes { IncludeExistsSELimitSpellSubclass = 14, IncludeFoundSELimitSpellSubclass = 15 }; +/* + The id's correspond to 'type' 39 in live(2021) dbstr_us gives the message for target and caster restricted effects. These are not present in the ROF2 dbstr_us. + If from CasterRestriction spell field. "Your target does not meet the spell requirements. ." Msg in combat window, color red. + If set as limit in a direct damage or heal spell (SPA 0) do not give message. +*/ +enum SpellRestriction +{ + UNKNOWN_3 = 3, // | caster restriction | seen in spell 30183 Mind Spiral + IS_NOT_ON_HORSE = 5, // | caster restriction | + IS_ANIMAL_OR_HUMANOID = 100, // This spell will only work on animals or humanoid creatures. + IS_DRAGON = 101, // This spell will only work on dragons. + IS_ANIMAL_OR_INSECT = 102, // This spell will only work on animals or insects. + IS_BODY_TYPE_MISC = 103, // This spell will only work on humanoids, lycanthropes, giants, Kael Drakkel giants, Coldain, animals, insects, constructs, dragons, Skyshrine dragons, Muramites, or creatures constructed from magic. + IS_BODY_TYPE_MISC2 = 104, // This spell will only work on humanoids, lycanthropes, giants, Kael Drakkel giants, Coldain, animals, or insects. + IS_PLANT = 105, // This spell will only work on plants. + IS_GIANT = 106, // This spell will only work on animals. | Live used to have this on spells restricted to Giants, but those spells were removed... We still have them + IS_NOT_ANIMAL_OR_HUMANOID = 108, // This spell will only work on targets that are neither animals or humanoid. + IS_BIXIE = 109, // This spell will only work on bixies. + IS_HARPY = 110, // This spell will only work on harpies. + IS_GNOLL = 111, // This spell will only work on gnolls. + IS_SPORALI = 112, // This spell will only work on fungusoids. + IS_KOBOLD = 113, // This spell will only work on kobolds. + IS_FROSTCRYPT_SHADE = 114, // This spell will only work on undead creatures or the Shades of Frostcrypt. + IS_DRAKKIN = 115, // This spell will only work on Drakkin. + IS_UNDEAD_OR_VALDEHOLM_GIANT = 116, // This spell will only work on undead creatures or the inhabitants of Valdeholm. + IS_ANIMAL_OR_PLANT = 117, // This spell will only work on plants or animals. + IS_SUMMONED = 118, // This spell will only work on constructs, elementals, or summoned elemental minions. + IS_WIZARD_USED_ON_MAGE_FIRE_PET = 119, // This spell will only work on wizards. | Live uses this on high level mage fire pets, which are wizard class + IS_UNDEAD = 120, // + IS_NOT_UNDEAD_OR_SUMMONED_OR_VAMPIRE = 121, // This spell will only work on creatures that are not undead, constructs, elementals, or vampires. + IS_FAE_OR_PIXIE = 122, // This spell will only work on Fae or pixies. + IS_HUMANOID = 123, // + IS_UNDEAD_AND_HP_LESS_THAN_10_PCT = 124, // The Essence Extractor whirrs but does not light up. + IS_CLOCKWORK_AND_HP_LESS_THAN_45_PCT = 125, // This spell will only work on clockwork gnomes. + IS_WISP_AND_HP_LESS_THAN_10_PCT = 126, // This spell will only work on wisps at or below 10% of their maximum HP. + IS_CLASS_MELEE_THAT_CAN_BASH_OR_KICK_EXCEPT_BARD = 127, // This spell will only work on non-bard targets that can bash or kick. + IS_CLASS_PURE_MELEE = 128, // This spell will only affect melee classes (warriors, monks, rogues, and berserkers). + IS_CLASS_PURE_CASTER = 129, // This spell will only affect pure caster classes (necromancers, wizards, magicians, and enchanters). + IS_CLASS_HYBRID_CLASS = 130, // This spell will only affect hybrid classes (paladins, rangers, shadow knights, bards, and beastlords). + IS_CLASS_WARRIOR = 131, // This spell will only affect Warriors. + IS_CLASS_CLERIC = 132, // This spell will only affect Clerics. + IS_CLASS_PALADIN = 133, // This spell will only affect Paladins. + IS_CLASS_RANGER = 134, // This spell will only affect Rangers. + IS_CLASS_SHADOWKNIGHT = 135, // This spell will only affect Shadow Knights. + IS_CLASS_DRUID = 136, // This spell will only affect Druids. + IS_CLASS_MONK = 137, // This spell will only affect Monks. + IS_CLASS_BARD = 138, // This spell will only affect Bards. + IS_CLASS_ROGUE = 139, // This spell will only affect Rogues. + IS_CLASS_SHAMAN = 140, // This spell will only affect Shamans. + IS_CLASS_NECRO = 141, // This spell will only affect Necromancers. + IS_CLASS_WIZARD = 142, // This spell will only affect Wizards. + IS_CLASS_MAGE = 143, // This spell will only affect Magicians. + IS_CLASS_ENCHANTER = 144, // This spell will only affect Enchanters. + IS_CLASS_BEASTLORD = 145, // This spell will only affect Beastlords. + IS_CLASS_BERSERKER = 146, // This spell will only affect Berserkers. + IS_CLASS_CLR_SHM_DRU = 147, // This spell will only affect priest classes (clerics, druids, and shaman). + IS_CLASS_NOT_WAR_PAL_SK = 148, // This spell will not affect Warriors, Paladins, or Shadow Knights. + IS_LEVEL_UNDER_100 = 150, // This spell will not affect any target over level 100. + IS_NOT_RAID_BOSS = 190, // This spell will not affect raid bosses. + IS_RAID_BOSS = 191, // This spell will only affect raid bosses. + FRENZIED_BURNOUT_ACTIVE = 192, // This spell will only cast if you have Frenzied Burnout active. + FRENZIED_BURNOUT_NOT_ACTIVE = 193, // This spell will only cast if you do not have Frenzied Burnout active. + UNKNOWN_199 = 199, // + IS_HP_ABOVE_75_PCT = 201, // + IS_HP_LESS_THAN_20_PCT = 203, // Your target's HP must be at 20% of its maximum or below. | caster restriction | + IS_HP_LESS_THAN_50_PCT = 204, // Your target's HP must be at 50% of its maximum or below. | caster restriction | + IS_HP_LESS_THAN_75_PCT = 205, // Your target's HP must be at 75% of its maximum or below. + IS_NOT_IN_COMBAT = 216, // This spell will only affect creatures that are not in combat. + HAS_AT_LEAST_1_PET_ON_HATELIST = 221, // + HAS_AT_LEAST_2_PETS_ON_HATELIST = 222, // + HAS_AT_LEAST_3_PETS_ON_HATELIST = 223, // + HAS_AT_LEAST_4_PETS_ON_HATELIST = 224, // + HAS_AT_LEAST_5_PETS_ON_HATELIST = 225, // + HAS_AT_LEAST_6_PETS_ON_HATELIST = 226, // + HAS_AT_LEAST_7_PETS_ON_HATELIST = 227, // + HAS_AT_LEAST_8_PETS_ON_HATELIST = 228, // + HAS_AT_LEAST_9_PETS_ON_HATELIST = 229, // + HAS_AT_LEAST_10_PETS_ON_HATELIST = 230, // + HAS_AT_LEAST_11_PETS_ON_HATELIST = 231, // + HAS_AT_LEAST_12_PETS_ON_HATELIST = 232, // + HAS_AT_LEAST_13_PETS_ON_HATELIST = 233, // + HAS_AT_LEAST_14_PETS_ON_HATELIST = 234, // + HAS_AT_LEAST_15_PETS_ON_HATELIST = 235, // + HAS_AT_LEAST_16_PETS_ON_HATELIST = 236, // + HAS_AT_LEAST_17_PETS_ON_HATELIST = 237, // + HAS_AT_LEAST_18_PETS_ON_HATELIST = 238, // + HAS_AT_LEAST_19_PETS_ON_HATELIST = 239, // + HAS_AT_LEAST_20_PETS_ON_HATELIST = 240, // + IS_HP_LESS_THAN_35_PCT = 250, // Your target's HP must be at 35% of its maximum or below. + HAS_BETWEEN_1_TO_2_PETS_ON_HATELIST = 260, // between 1 and 2 pets + HAS_BETWEEN_3_TO_5_PETS_ON_HATELIST = 261, // between 3 and 5 pets + HAS_BETWEEN_6_TO_9_PETS_ON_HATELIST = 262, // between 6 and 9 pets + HAS_BETWEEN_10_TO_14_PETS_ON_HATELIST = 263, // between 10 and 14 pets + HAS_MORE_THAN_14_PETS_ON_HATELIST = 264, // 15 or more pets + IS_CLASS_CHAIN_OR_PLATE = 304, // This spell will only affect plate or chain wearing classes. + IS_HP_BETWEEN_5_AND_9_PCT = 350, // Your target's HP must be between 5% and 9% of its maximum. + IS_HP_BETWEEN_10_AND_14_PCT = 351, // Your target's HP must be between 10% and 14% of its maximum. + IS_HP_BETWEEN_15_AND_19_PCT = 352, // Your target's HP must be between 15% and 19% of its maximum. + IS_HP_BETWEEN_20_AND_24_PCT = 353, // Your target's HP must be between 20% and 24% of its maximum. + IS_HP_BETWEEN_25_AND_29_PCT = 354, // Your target's HP must be between 25% and 29% of its maximum. + IS_HP_BETWEEN_30_AND_34_PCT = 355, // Your target's HP must be between 30% and 34% of its maximum. + IS_HP_BETWEEN_35_AND_39_PCT = 356, // Your target's HP must be between 35% and 39% of its maximum. + IS_HP_BETWEEN_40_AND_44_PCT = 357, // Your target's HP must be between 40% and 44% of its maximum. + IS_HP_BETWEEN_45_AND_49_PCT = 358, // Your target's HP must be between 45% and 49% of its maximum. + IS_HP_BETWEEN_50_AND_54_PCT = 359, // Your target's HP must be between 50% and 54% of its maximum. + IS_HP_BETWEEN_55_AND_59_PCT = 360, // Your target's HP must be between 55% and 59% of its maximum. + IS_HP_BETWEEN_5_AND_15_PCT = 398, // Your target's HP must be between 5% and 15% of its maximum. + IS_HP_BETWEEN_15_AND_25_PCT = 399, // Your target's HP must be between 15% and 25% of its maximum. + IS_HP_BETWEEN_1_AND_25_PCT = 400, // Your target's HP must be at 25% of its maximum or below. + IS_HP_BETWEEN_25_AND_35_PCT = 401, // Your target's HP must be between 25% and 35% of its maximum. + IS_HP_BETWEEN_35_AND_45_PCT = 402, // Your target's HP must be between 35% and 45% of its maximum. + IS_HP_BETWEEN_45_AND_55_PCT = 403, // Your target's HP must be between 45% and 55% of its maximum. + IS_HP_BETWEEN_55_AND_65_PCT = 404, // Your target's HP must be between 55% and 65% of its maximum. + IS_HP_BETWEEN_65_AND_75_PCT = 405, // Your target's HP must be between 65% and 75% of its maximum. + IS_HP_BETWEEN_75_AND_85_PCT = 406, // Your target's HP must be between 75% and 85% of its maximum. + IS_HP_BETWEEN_85_AND_95_PCT = 407, // Your target's HP must be between 85% and 95% of its maximum. + IS_HP_ABOVE_45_PCT = 408, // Your target's HP must be at least 45% of its maximum. + IS_HP_ABOVE_55_PCT = 409, // Your target's HP must be at least 55% of its maximum. + UNKNOWN_TOO_MUCH_HP_410 = 410, // Your target has too much HP to be affected by this spell. + UNKNOWN_TOO_MUCH_HP_411 = 411, // Your target has too much HP to be affected by this spell. + IS_HP_ABOVE_99_PCT = 412, // + IS_MANA_ABOVE_10_PCT = 429, // You must have at least 10% of your maximum mana available to cast this spell. | caster restriction | + IS_HP_BELOW_5_PCT = 501, // + IS_HP_BELOW_10_PCT = 502, // + IS_HP_BELOW_15_PCT = 503, // + IS_HP_BELOW_20_PCT = 504, // Your target's HP must be at 20% of its maximum or below. + IS_HP_BELOW_25_PCT = 505, // + IS_HP_BELOW_30_PCT = 506, // + IS_HP_BELOW_35_PCT = 507, // + IS_HP_BELOW_40_PCT = 508, // + IS_HP_BELOW_45_PCT = 509, // Your target's HP must be at 45% of its maximum or below. + IS_HP_BELOW_50_PCT = 510, // + IS_HP_BELOW_55_PCT = 511, // + IS_HP_BELOW_60_PCT = 512, // + IS_HP_BELOW_65_PCT = 513, // + IS_HP_BELOW_70_PCT = 514, // + IS_HP_BELOW_75_PCT = 515, // + IS_HP_BELOW_80_PCT = 516, // + IS_HP_BELOW_85_PCT = 517, // + IS_HP_BELOW_90_PCT = 518, // This ability requires you to be at or below 90% of your maximum HP. | caster restriction | + IS_HP_BELOW_95_PCT = 519, // + IS_MANA_BELOW_UNKNOWN_PCT = 521, // + IS_ENDURANCE_BELOW_40_PCT = 522, // + IS_MANA_BELOW_40_PCT = 523, // + IS_HP_ABOVE_20_PCT = 524, // Your target's HP must be at least 21% of its maximum. + IS_BODY_TYPE_UNDEFINED = 600, // This spell will only work on creatures with an undefined body type. + IS_BODY_TYPE_HUMANOID = 601, // This spell will only work on humanoid creatures. + IS_BODY_TYPE_WEREWOLF = 602, // This spell will only work on lycanthrope creatures. + IS_BODY_TYPE_UNDEAD = 603, // This spell will only work on undead creatures. + IS_BODY_TYPE_GIANTS = 604, // This spell will only work on giants. + IS_BODY_TYPE_CONSTRUCTS = 605, // This spell will only work on constructs. + IS_BODY_TYPE_EXTRAPLANAR = 606, // This spell will only work on extraplanar creatures. + IS_BODY_TYPE_MAGICAL_CREATURE = 607, // This spell will only work on creatures constructed from magic. + IS_BODY_TYPE_UNDEADPET = 608, // This spell will only work on animated undead servants. + IS_BODY_TYPE_KAELGIANT = 609, // This spell will only work on the Giants of Kael Drakkal. + IS_BODY_TYPE_COLDAIN = 610, // This spell will only work on Coldain Dwarves. + IS_BODY_TYPE_VAMPIRE = 612, // This spell will only work on vampires. + IS_BODY_TYPE_ATEN_HA_RA = 613, // This spell will only work on Aten Ha Ra. + IS_BODY_TYPE_GREATER_AHKEVANS = 614, // This spell will only work on Greater Ahkevans. + IS_BODY_TYPE_KHATI_SHA = 615, // This spell will only work on Khati Sha. + IS_BODY_TYPE_LORD_INQUISITOR_SERU = 616, // This spell will only work on Lord Inquisitor Seru. + IS_BODY_TYPE_GRIEG_VENEFICUS = 617, // This spell will only work on Grieg Veneficus. + IS_BODY_TYPE_FROM_PLANE_OF_WAR = 619, // This spell will only work on creatures from the Plane of War. + IS_BODY_TYPE_LUGGALD = 620, // This spell will only work on Luggalds. + IS_BODY_TYPE_ANIMAL = 621, // This spell will only work on animals. + IS_BODY_TYPE_INSECT = 622, // This spell will only work on insects. + IS_BODY_TYPE_MONSTER = 623, // This spell will only work on monsters. + IS_BODY_TYPE_ELEMENTAL = 624, // This spell will only work on elemental creatures. + IS_BODY_TYPE_PLANT = 625, // This spell will only work on plants. + IS_BODY_TYPE_DRAGON2 = 626, // This spell will only work on dragons. + IS_BODY_TYPE_SUMMONED_ELEMENTAL = 627, // This spell will only work on summoned elementals. + IS_BODY_TYPE_WARDER = 628, // + IS_BODY_TYPE_DRAGON_OF_TOV = 630, // This spell will only work on Dragons of Veeshan's Temple. + IS_BODY_TYPE_FAMILIAR = 631, // This spell will only work on familiars. + IS_BODY_TYPE_MURAMITE = 634, // This spell will only work on Muramites. + IS_NOT_UNDEAD_OR_SUMMONED = 635, // + IS_NOT_PLANT = 636, // This spell will not affect plants. + IS_NOT_CLIENT = 700, // This spell will not work on adventurers. + IS_CLIENT = 701, // This spell will only work on adventurers. + IS_LEVEL_ABOVE_42_AND_IS_CLIENT = 800, // This spell will only work on level 43 or higher adventurers. + UNKNOWN_812 = 812, // | seen in spell 22616 Thaumatize Pet Mana Regen Base | + UNKNOWN_814 = 814, // | seen in spell 22704 Vegetentacles I | + IS_TREANT = 815, // This spell will only work on treants. + IS_BIXIE2 = 816, // This spell will only work on bixies. + IS_SCARECROW = 817, // This spell will only work on scarecrows. + IS_VAMPIRE_OR_UNDEAD_OR_UNDEADPET = 818, // This spell will only work on vampires, undead, or animated undead creatures. + IS_NOT_VAMPIRE_OR_UNDEAD = 819, // This spell will not work on vampires or undead creatures. + IS_CLASS_KNIGHT_HYBRID_MELEE = 820, // This spell will only work on knights, hybrids, or melee classes. + IS_CLASS_WARRIOR_CASTER_PRIEST = 821, // This spell will only work on warriors, casters, or priests. + UNKNOWN_822 = 822, // | seen in spell 22870 Morell's Distraction 822 | + IS_END_BELOW_21_PCT = 825, // This ability requires you to be at or below 21% of your maximum endurance. + IS_END_BELOW_25_PCT = 826, // This ability requires you to be at or below 25% of your maximum endurance. + IS_END_BELOW_29_PCT = 827, // This ability requires you to be at or below 29% of your maximum endurance. + IS_REGULAR_SERVER = 836, // + IS_PROGRESSION_SERVER = 837, // + IS_GOD_EXPANSION_UNLOCKED = 839, // + UNKNOWN_840 = 840, // | caster restriction | seen in spell 6883 Expedient Recovery + UNKNOWN_841 = 841, // | caster restriction | seen in spell 32192 Merciless Blow + IS_HUMANOID_LEVEL_84_MAX = 842, // + IS_HUMANOID_LEVEL_86_MAX = 843, // + IS_HUMANOID_LEVEL_88_MAX = 844, // + HAS_CRYSTALLIZED_FLAME_BUFF = 845, // This spell will only work on targets afflicted by Crystallized Flame. | On live spell does not appear to be a buff + HAS_INCENDIARY_OOZE_BUFF = 847, // This spell will only work on targets afflicted by Incendiary Ooze. + IS_LEVEL_90_MAX = 860, // + IS_LEVEL_92_MAX = 861, // + IS_LEVEL_94_MAX = 862, // + IS_LEVEL_95_MAX = 863, // + IS_LEVEL_97_MAX = 864, // + IS_LEVEL_99_MAX = 865, // + HAS_WEAPONSTANCE_DEFENSIVE_PROFICIENCY = 866, // | caster restriction | + HAS_WEAPONSTANCE_TWO_HAND_PROFICIENCY = 867, // | caster restriction | + HAS_WEAPONSTANCE_DUAL_WEILD_PROFICIENCY = 868, // | caster restriction | + IS_LEVEL_100_MAX = 869, // + IS_LEVEL_102_MAX = 870, // + IS_LEVEL_104_MAX = 871, // + IS_LEVEL_105_MAX = 872, // + IS_LEVEL_107_MAX = 873, // + IS_LEVEL_109_MAX = 874, // + IS_LEVEL_110_MAX = 875, // + IS_LEVEL_112_MAX = 876, // + IS_LEVEL_114_MAX = 877, // + HAS_TBL_ESIANTI_ACCESS = 997, // This spell will only transport adventurers who have gained access to Esianti: Palace of the Winds. | not implemented + HAS_ITEM_CLOCKWORK_SCRAPS = 999, // + IS_BETWEEN_LEVEL_1_AND_75 = 1000, // + IS_BETWEEN_LEVEL_76_AND_85 = 1001, // + IS_BETWEEN_LEVEL_86_AND_95 = 1002, // + IS_BETWEEN_LEVEL_96_AND_105 = 1003, // + IS_HP_LESS_THAN_80_PCT = 1004, // + IS_LEVEL_ABOVE_34 = 1474, // Your target must be level 35 or higher. + IN_TWO_HANDED_STANCE = 2000, // You must be in your two-handed stance to use this ability. + IN_DUAL_WIELD_HANDED_STANCE = 2001, // You must be in your dual-wielding stance to use this ability. + IN_SHIELD_STANCE = 2002, // You must be in your shield stance to use this ability. + NOT_IN_TWO_HANDED_STANCE = 2010, // You may not use this ability if you are in your two-handed stance. + NOT_IN_DUAL_WIELD_HANDED_STANCE = 2011, // You may not use this ability if you are in your dual-wielding stance. + NOT_IN_SHIELD_STANCE = 2012, // You may not use this ability if you are in your shield stance. + LEVEL_46_MAX = 2761, // + DISABLED_UNTIL_EXPANSION_ROK = 7000, // This ability is disabled until Ruins of Kunark. + DISABLED_UNTIL_EXPANSION_SOV = 7001, // This ability is disabled until Scars of Velious. + DISABLED_UNTIL_EXPANSION_SOL = 7002, // This ability is disabled until Shadows of Luclin. + DISABLED_UNTIL_EXPANSION_POP = 7003, // This ability is disabled until Planes of Power. + DISABLED_UNTIL_EXPANSION_LOY = 7004, // This ability is disabled until Legacy of Ykesha. + DISABLED_UNTIL_EXPANSION_LDON = 7005, // This ability is disabled until Lost Dungeons of Norrath. + DISABLED_UNTIL_EXPANSION_GOD = 7006, // This ability is disabled until Gates of Discord. + DISABLED_UNTIL_EXPANSION_OOW = 7007, // This ability is disabled until Omens of War. + DISABLED_UNTIL_EXPANSION_DON = 7008, // This ability is disabled until Dragons of Norrath. + DISABLED_UNTIL_EXPANSION_DOD = 7009, // This ability is disabled until Depths of Darkhollow. + DISABLED_UNTIL_EXPANSION_POR = 7010, // This ability is disabled until Prophecy of Ro. + DISABLED_UNTIL_EXPANSION_TSS = 7011, // This ability is disabled until Serpent's Spine. + DISABLED_UNTIL_EXPANSION_TBS = 7012, // This ability is disabled until Buried Sea. + DISABLED_UNTIL_EXPANSION_SOF = 7013, // This ability is disabled until Secrets of Faydwer. + DISABLED_UNTIL_EXPANSION_SOD = 7014, // This ability is disabled until Seeds of Destruction. + DISABLED_UNTIL_EXPANSION_UF = 7015, // This ability is disabled until Underfoot. + DISABLED_UNTIL_EXPANSION_HOT = 7016, // This ability is disabled until House of Thule. + DISABLED_UNTIL_EXPANSION_VOA = 7017, // This ability is disabled until Veil of Alaris. + DISABLED_UNTIL_EXPANSION_ROF = 7018, // This ability is disabled until Rain of Fear. + DISABLED_UNTIL_EXPANSION_COF = 7019, // This ability is disabled until Call of the Forsaken. + DISABLED_UNTIL_EXPANSION_TDS = 7020, // This ability is disabled until Darkened Sea. + DISABLED_UNTIL_EXPANSION_TBM = 7021, // This ability is disabled until Broken Mirror. + DISABLED_UNTIL_EXPANSION_EOK = 7022, // This ability is disabled until Empires of Kunark. + DISABLED_UNTIL_EXPANSION_ROS = 7023, // This ability is disabled until Ring of Scale. + DISABLED_UNTIL_EXPANSION_TBL = 7024, // This ability is disabled until The Burning Lands. + DISABLED_UNTIL_EXPANSION_TOV = 7025, // This ability is disabled until Torment of Velious. + DISABLED_UNTIL_EXPANSION_COV = 7026, // This ability is disabled until Claws of Veeshan. + HAS_NO_MANA_BURN_BUFF = 8450, // This spell will not take hold until the effects of the previous Mana Burn have expired. + IS_RACE_FIRST_CUSTOM = 10000, // | custom range to restrict targets or casters by race *not on live* | + IS_RACE_LAST_CUSTOM = 11000, // | custom range to restrict targets or casters by race *not on live* | + IS_CLIENT_AND_MALE_PLATE_USER = 11044, // Your target wouldn't look right as that Jann. + IS_CLEINT_AND_MALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD = 11090, // Your target wouldn't look right as that Jann. + IS_CLIENT_AND_MALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE = 11209, // Your target wouldn't look right as that Jann. + IS_CLIENT_AND_FEMALE_PLATE_USER = 11210, // Your target wouldn't look right as that Jann. + IS_CLIENT_AND_FEMALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD = 11211, // Your target wouldn't look right as that Jann. + IS_CLIENT_AND_FEMALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE = 11248, // Your target wouldn't look right as that Jann. + HAS_TRAVELED_TO_STRATOS = 11260, // You must travel to Stratos at least once before wishing to go there. + HAS_TRAVELED_TO_AALISHAI = 11261, // You must travel to Aalishai at least once before wishing to go there. + HAS_TRAVELED_TO_MEARATS = 11268, // You must travel to Mearatas at least once before wishing to go there. + HAS_NO_ILLUSIONS_OF_GRANDEUR_BUFF = 12519, // + IS_HP_ABOVE_50_PCT = 16010, // + IS_HP_UNDER_50_PCT = 16031, // + IS_OFF_HAND_EQUIPED = 27672, // You must be wielding a weapon or shield in your offhand to use this ability. + HAS_NO_PACT_OF_FATE_RECOURSE_BUFF = 29556, // This spell will not work while Pact of Fate Recourse is active. | caster restriction | + HAS_NO_SHROUD_OF_PRAYER_BUFF = 32339, // Your target cannot receive another Quiet Prayer this soon. + IS_MANA_BELOW_20_PCT = 38311, // This ability requires you to be at or below 20% of your maximum mana. + IS_MANA_ABOVE_50_PCT = 38312, // This ability requires you to be at or above 50% of your maximum mana. + COMPLETED_ACHIEVEMENT_LEGENDARY_ANSWERER = 39281, // You have completed Legendary Answerer. + HAS_NO_ROGUES_FURY_BUFF = 40297, // This spell will not affect anyone that currently has Rogue's Fury active. | caster restriction | + NOT_COMPLETED_ACHIEVEMENT_LEGENDARY_ANSWERER = 42280, // You must complete Legendary Answerer. + IS_SUMMONED_OR_UNDEAD = 49326, // + IS_CLASS_CASTER_PRIEST = 49529, // + IS_END_OR_MANA_ABOVE_20_PCT = 49543, // You must have at least 20% of your maximum mana and endurance to use this ability. //pure melee class check end, other check mana + IS_END_OR_MANA_BELOW_30_PCT = 49573, // Your target already has 30% or more of their maximum mana or endurance. //pure melee class check the, other check more + IS_CLASS_BARD2 = 49574, // + IS_NOT_CLASS_BARD = 49575, // + HAS_NO_FURIOUS_RAMPAGE_BUFF = 49612, // This ability cannot be activated while Furious Rampage is active. + IS_END_OR_MANA_BELOW_30_PCT2 = 49809, // You can only perform this solo if you have less than 30% mana or endurance. + HAS_NO_HARMONIOUS_PRECISION_BUFF = 50003, // This spell will not work if you have the Harmonious Precision line active. + HAS_NO_HARMONIOUS_EXPANSE_BUFF = 50009, // This spell will not work if you have the Harmonious Expanse line active. + UNKNOWN_99999 = 99999, // | caster restriction | works will spell 27672 Strike of Ire +}; + + enum SpellTypes : uint32 { @@ -1037,7 +1348,7 @@ struct SPDat_Spell_Struct /* 217 */ int override_crit_chance; //Places a cap on the max chance to critical -- OVERRIDE_CRIT_CHANCE /* 218 */ int aemaxtargets; //Is used for various AE effects -- MAX_TARGETS /* 219 */ int no_heal_damage_item_mod; // -- NO_HEAL_DAMAGE_ITEM_MOD -/* 220 */ //int caster_requirement_id; // -- CASTER_REQUIREMENT_ID +/* 220 */ int caster_requirement_id; // -- CASTER_REQUIREMENT_ID /* 221 */ int spell_class; // -- SPELL_CLASS /* 222 */ int spell_subclass; // -- SPELL_SUBCLASS /* 223 */ //int ai_valid_targets; // -- AI_VALID_TARGETS diff --git a/zone/mob.cpp b/zone/mob.cpp index 6d4dfc0e9..2bbb15c30 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5903,6 +5903,7 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot) else if (id == "rank") {return spells[spell_id].rank; } else if (id == "no_resist") {return spells[spell_id].no_resist; } else if (id == "CastRestriction") {return spells[spell_id].CastRestriction; } + else if (id == "caster_requirement_id") { return spells[spell_id].caster_requirement_id; } else if (id == "AllowRest") {return spells[spell_id].AllowRest; } else if (id == "InCombat") {return spells[spell_id].InCombat; } else if (id == "OutofCombat") {return spells[spell_id].OutofCombat; } diff --git a/zone/mob.h b/zone/mob.h index a951d7cb3..1a3bffc4f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -420,6 +420,7 @@ public: inline float GetTargetRingZ() const { return m_TargetRing.z; } inline bool HasEndurUpkeep() const { return endur_upkeep; } inline void SetEndurUpkeep(bool val) { endur_upkeep = val; } + bool HasBuffWithSpellGroup(int spellgroup); //Basic Stats/Inventory virtual void SetLevel(uint8 in_level, bool command = false) { level = in_level; } @@ -832,7 +833,7 @@ public: int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect); int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg); void MeleeLifeTap(int32 damage); - bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true); + bool PassCastRestriction(int value); bool ImprovedTaunt(); bool TryRootFadeByDamage(int buffslot, Mob* attacker); float GetSlowMitigation() const { return slow_mitigation; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 0284fd4c6..848edd656 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -231,12 +231,14 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (buffslot >= 0) break; + if (spells[spell_id].base2[i] && !PassCastRestriction(spells[spell_id].base2[i])) { + break; //no messages are given on live if this fails. + } + // for offensive spells check if we have a spell rune on int32 dmg = effect_value; if(dmg < 0) { - if (!PassCastRestriction(false, spells[spell_id].base2[i], true)) - break; // take partial damage into account dmg = (int32) (dmg * partial / 100); @@ -253,9 +255,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove else if(dmg > 0) { //healing spell... - if (!PassCastRestriction(false, spells[spell_id].base2[i], false)) - break; - if(caster) dmg = caster->GetActSpellHealing(spell_id, dmg, this); @@ -289,15 +288,15 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove // hack fix for client health not reflecting server value last_hp = 0; + if (spells[spell_id].base2[i] && !PassCastRestriction(spells[spell_id].base2[i])) { + break; + } + //do any AAs apply to these spells? if(dmg < 0) { - if (!PassCastRestriction(false, spells[spell_id].base2[i], true)) - break; dmg = -dmg; Damage(caster, dmg, spell_id, spell.skill, false, buffslot, false); } else { - if (!PassCastRestriction(false, spells[spell_id].base2[i], false)) - break; HealDamage(dmg, caster); } break; @@ -3750,8 +3749,11 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) switch (effect) { case SE_CurrentHP: { - if (!PassCastRestriction(false, spells[buff.spellid].base2[i], true)) + + if (spells[buff.spellid].base2[i] && !PassCastRestriction(spells[buff.spellid].base2[i])) { break; + } + effect_value = CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod, caster, buff.ticsremaining); // Handle client cast DOTs here. @@ -7108,331 +7110,948 @@ bool Mob::ImprovedTaunt(){ } -bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDamage) +bool Mob::PassCastRestriction(int value) { - /*If return TRUE spell met all restrictions and can continue (this = target). - This check is used when the spell_new field CastRestriction is defined OR spell effect '0'(DD/Heal) has a defined limit - Range 1 : UNKNOWN -- the spells with this seem to not have a restiction, true for now - Range 100 : *Animal OR Humanoid - Range 101 : *Dragon - Range 102 : *Animal OR Insect - Range 103 : NOT USED - Range 104 : *Animal - Range 105 : Plant - Range 106 : *Giant - Range 107 : NOT USED - Range 108 : NOT Animal or Humaniod - Range 109 : *Bixie - Range 111 : *Harpy - Range 112 : *Sporali - Range 113 : *Kobold - Range 114 : *Shade Giant - Range 115 : *Drakkin - Range 116 : NOT USED - Range 117 : *Animal OR Plant - Range 118 : *Summoned - Range 119 : *Firepet - Range 120 : Undead - Range 121 : *Living (NOT Undead) - Range 122 : *Fairy - Range 123 : Humanoid - Range 124 : *Undead HP < 10% - Range 125 : *Clockwork HP < 10% - Range 126 : *Wisp HP < 10% - Range 127 : UNKNOWN - Range 128 : pure melee -- guess - Range 129 : pure caster -- guess - Range 130 : hybrid -- guess - Range 150 : UNKNOWN - Range 190 : No Raid boss flag *not implemented - Range 191 : This spell will deal less damage to 'exceptionally strong targets' - Raid boss flag *not implemented - Range 201 : Damage if HP > 75% - Range 203 : Damage if HP < 20% - Range 216 : TARGET NOT IN COMBAT - Range 221 - 249 : Causing damage dependent on how many pets/swarmpets are attacking your target. - Range 250 : Damage if HP < 35% - Range 300 - 303 : UNKOWN *not implemented - Range 304 : Chain + Plate class (buffs) - Range 399 - 409 : Heal if HP within a specified range (400 = 0-25% 401 = 25 - 35% 402 = 35-45% ect) - Range 410 - 411 : UNKOWN -- examples are auras that cast on NPCs maybe in combat/out of combat? - Range 500 - 599 : Heal if HP less than a specified value - Range 600 - 699 : Limit to Body Type [base2 - 600 = Body] - Range 700 : NPC only -- from patch notes "Wizard - Arcane Fusion no longer deals damage to non-NPC targets. This should ensure that wizards who fail their Bucolic Gambit are slightly less likely to annihilate themselves." - Range 701 : NOT PET - Range 800 : UKNOWN -- Target's Target Test (16598) - Range 812 : UNKNOWN -- triggered by Thaumatize Owner - Range 814 : UNKNOWN -- Vegetentacles - Range 815 : UNKNOWN -- Pumpkin Pulp Splash - Range 816 : UNKNOWN -- Rotten Fruit Splash - Range 817 : UNKNOWN -- Tainted Bixie Pollen Splash - Range 818 - 819 : If Undead/If Not Undead - Range 820 - 822 : UKNOWN - Range 835 : Unknown *not implemented - Range 836 - 837 : Progression Server / Live Server *not fully implemented - Range 839 : Progression Server and GoD released -- broken until Oct 21 2015 on live *not fully implemented - Range 842 - 844 : Humaniod lv MAX ((842 - 800) * 2) - Range 845 - 847 : UNKNOWN - Range 860 - 871 : Humanoid lv MAX 860 = 90, 871 = 104 *not implemented - Range 10000 - 11000 : Limit to Race [base2 - 10000 = Race] (*Not on live: Too useful a function to not implement) - THIS IS A WORK IN PROGRESS + /* + Restriction ID corresponds to the type 39 value in dstr_us on live clients (2021). See enum SpellRestriction for full list. + Modern client will give a message corresponding the type 39 field in the dstr_us for many of these effects upon failure. + + Use with spell_news table field 'CastRestriction' which limits targets by restrictions below and 'caster_requirement' (field220) + which limits caster by restrictions below. + These restrictions also apply to direct damage,dot, heal spells using SPA 0 or SPA 79 by placing a restriction id in the LIMIT field. + + Note: (ID 221 - 249) For effect seen in mage spell 'Shock of Many' which increases damage based on number of pets on targets hatelist. The way it is implemented + works for how our ROF2 spell file handles the effect where each slot fires individually, while on live it only takes the highest + value. In the future the way check is done will need to be adjusted to check a defined range instead of just great than. */ - if (value <= 0) + if (value <= 0) { return true; + } - if (IsDamage || UseCastRestriction) { + switch(value) + { + case 1: + return true; + break; - switch(value) - { - case 1: + case IS_NOT_ON_HORSE: + if (IsClient() && !CastToClient()->GetHorseId()) return true; + break; - case 100: - if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Humanoid)) - return true; - break; + case IS_ANIMAL_OR_HUMANOID: + if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Humanoid)) + return true; + break; - case 101: - if (GetBodyType() == BT_Dragon || GetBodyType() == BT_VeliousDragon || GetBodyType() == BT_Dragon3) - return true; - break; + case IS_DRAGON: + if (GetBodyType() == BT_Dragon || GetBodyType() == BT_VeliousDragon || GetBodyType() == BT_Dragon3) + return true; + break; - case 102: - if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Insect)) - return true; - break; + case IS_ANIMAL_OR_INSECT: + if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Insect)) + return true; + break; - case 104: - if (GetBodyType() == BT_Animal) - return true; - break; + case IS_BODY_TYPE_MISC: + if ((GetBodyType() == BT_Humanoid) || (GetBodyType() == BT_Lycanthrope) || (GetBodyType() == BT_Giant) || + (GetBodyType() == BT_RaidGiant) || (GetBodyType() == BT_RaidColdain) || (GetBodyType() == BT_Animal)|| + (GetBodyType() == BT_Construct) || (GetBodyType() == BT_Dragon) || (GetBodyType() == BT_Insect)|| + (GetBodyType() == BT_VeliousDragon) || (GetBodyType() == BT_Muramite) || (GetBodyType() == BT_Magical)) + return true; + break; - case 105: - if (GetBodyType() == BT_Plant) - return true; - break; + case IS_BODY_TYPE_MISC2: + if ((GetBodyType() == BT_Humanoid) || (GetBodyType() == BT_Lycanthrope) || (GetBodyType() == BT_Giant) || + (GetBodyType() == BT_RaidGiant) || (GetBodyType() == BT_RaidColdain) || (GetBodyType() == BT_Animal) || + (GetBodyType() == BT_Insect)) + return true; + break; - case 106: - if (GetBodyType() == BT_Giant) - return true; - break; + case IS_PLANT: + if (GetBodyType() == BT_Plant) + return true; + break; - case 108: - if ((GetBodyType() != BT_Animal) || (GetBodyType() != BT_Humanoid)) - return true; - break; + case IS_GIANT: + if (GetBodyType() == BT_Giant) + return true; + break; - case 109: - if ((GetRace() == 520) ||(GetRace() == 79)) - return true; - break; + case IS_NOT_ANIMAL_OR_HUMANOID: + if ((GetBodyType() != BT_Animal) || (GetBodyType() != BT_Humanoid)) + return true; + break; - case 111: - if ((GetRace() == 527) ||(GetRace() == 11)) - return true; - break; + case IS_BIXIE: + case IS_BIXIE2: + if ((GetRace() == RT_BIXIE) ||(GetRace() == RT_BIXIE_2)) + return true; + break; - case 112: - if ((GetRace() == 456) ||(GetRace() == 28)) - return true; - break; + case IS_HARPY: + if ((GetRace() == RT_HARPY) ||(GetRace() == RT_HARPY_2)) + return true; + break; - case 113: - if ((GetRace() == 456) ||(GetRace() == 48)) - return true; - break; + case IS_GNOLL: + if ((GetRace() == RT_GNOLL) || (GetRace() == RT_GNOLL_2) || (GetRace() == RT_GNOLL_3)) + return true; + break; - case 114: - if (GetRace() == 526) - return true; - break; + case IS_SPORALI: + if ((GetRace() == RT_SPORALI) ||(GetRace() == RT_FUNGUSMAN)) + return true; + break; - case 115: - if (GetRace() == 522) - return true; - break; + case IS_KOBOLD: + if ((GetRace() == RT_KOBOLD) ||(GetRace() == RT_KOBOLD_2)) + return true; + break; - case 117: - if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Plant)) - return true; - break; + case IS_FROSTCRYPT_SHADE: + if (GetRace() == RT_GIANT_SHADE) + return true; + break; - case 118: - if (GetBodyType() == BT_Summoned) - return true; - break; + case IS_DRAKKIN: + if (GetRace() == RT_DRAKKIN) + return true; + break; - case 119: - if (IsPet() && ((GetRace() == 212) || ((GetRace() == 75) && GetTexture() == 1))) - return true; - break; + case IS_UNDEAD_OR_VALDEHOLM_GIANT: + if (GetBodyType() == BT_Undead || GetRace() == RT_GIANT_12 || GetRace() == RT_GIANT_13) + return true; + break; - case 120: - if (GetBodyType() == BT_Undead) - return true; - break; + case IS_ANIMAL_OR_PLANT: + if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Plant)) + return true; + break; - case 121: - if (GetBodyType() != BT_Undead) - return true; - break; + case IS_SUMMONED: + if (GetBodyType() == BT_Summoned) + return true; + break; - case 122: - if ((GetRace() == 473) || (GetRace() == 425)) - return true; - break; + case IS_CLASS_WIZARD: + case IS_WIZARD_USED_ON_MAGE_FIRE_PET: + if (GetClass() == WIZARD) + return true; + break; - case 123: - if (GetBodyType() == BT_Humanoid) - return true; - break; + case IS_UNDEAD: + if (GetBodyType() == BT_Undead) + return true; + break; - case 124: - if ((GetBodyType() == BT_Undead) && (GetHPRatio() < 10)) - return true; - break; + case IS_NOT_UNDEAD_OR_SUMMONED_OR_VAMPIRE: + if ((GetBodyType() != BT_Undead) && (GetBodyType() != BT_Summoned) && (GetBodyType() != BT_Vampire)) + return true; + break; - case 125: - if ((GetRace() == 457 || GetRace() == 88) && (GetHPRatio() < 10)) - return true; - break; + case IS_FAE_OR_PIXIE: + if ((GetRace() == RT_PIXIE) || (GetRace() == RT_FAY_DRAKE)) + return true; + break; - case 126: - if ((GetRace() == 581 || GetRace() == 69) && (GetHPRatio() < 10)) - return true; - break; + case IS_HUMANOID: + if (GetBodyType() == BT_Humanoid) + return true; + break; - case 201: - if (GetHPRatio() > 75) - return true; - break; + case IS_UNDEAD_AND_HP_LESS_THAN_10_PCT: + if ((GetBodyType() == BT_Undead) && (GetHPRatio() < 10)) + return true; + break; - case 204: - if (GetHPRatio() < 20) - return true; - break; + case IS_CLOCKWORK_AND_HP_LESS_THAN_45_PCT: + if ((GetRace() == RT_GNOMEWORK || GetRace() == RACE_CLOCKWORK_GNOME_88) && (GetHPRatio() < 45)) + return true; + break; - case 216: - if (!IsEngaged()) - return true; - break; + case IS_WISP_AND_HP_LESS_THAN_10_PCT: + if ((GetRace() == RT_WILL_O_WISP) && (GetHPRatio() < 10)) + return true; + break; - case 250: - if (GetHPRatio() < 35) - return true; - break; + case IS_CLASS_MELEE_THAT_CAN_BASH_OR_KICK_EXCEPT_BARD: + if ((GetClass() != BARD) && (GetClass() != ROGUE) && IsFighterClass(GetClass())) + return true; + break; - case 304: - if (IsClient() && - ((GetClass() == WARRIOR) || (GetClass() == BARD) || (GetClass() == SHADOWKNIGHT) || (GetClass() == PALADIN) || (GetClass() == CLERIC) - || (GetClass() == RANGER) || (GetClass() == SHAMAN) || (GetClass() == ROGUE) || (GetClass() == BERSERKER))) - return true; - break; + case IS_CLASS_PURE_MELEE: + if (GetClass() == ROGUE || GetClass() == WARRIOR || GetClass() == BERSERKER || GetClass() == MONK) + return true; + break; - case 700: - if (IsNPC()) - return true; - break; + case IS_CLASS_PURE_CASTER: + if (IsINTCasterClass(GetClass())) + return true; + break; - case 701: - if (!IsPet()) - return true; - break; + case IS_CLASS_HYBRID_CLASS: + if (IsHybridClass(GetClass())) + return true; + break; + + case IS_CLASS_WARRIOR: + if (GetClass() == WARRIOR) + return true; + break; - case 818: - if (GetBodyType() == BT_Undead) - return true; - break; + case IS_CLASS_CLERIC: + if (GetClass() == CLERIC) + return true; + break; - case 819: - if (GetBodyType() != BT_Undead) - return true; - break; + case IS_CLASS_PALADIN: + if (GetClass() == PALADIN) + return true; + break; - case 836: - return true; // todo implement progression flag assume not progression for now + case IS_CLASS_RANGER: + if (GetClass() == RANGER) + return true; + break; - case 837: - return false; // todo implement progression flag assume not progression for now + case IS_CLASS_SHADOWKNIGHT: + if (GetClass() == SHADOWKNIGHT) + return true; + break; - case 839: - return true; // todo implement progression flag assume not progression for now, this one is a check if GoD is live + case IS_CLASS_DRUID: + if (GetClass() == DRUID) + return true; + break; - case 842: - if (GetBodyType() == BT_Humanoid && GetLevel() <= 84) - return true; - break; + case IS_CLASS_MONK: + if (GetClass() == MONK) + return true; + break; - case 843: - if (GetBodyType() == BT_Humanoid && GetLevel() <= 86) - return true; - break; + case IS_CLASS_BARD2: + case IS_CLASS_BARD: + if (GetClass() == BARD) + return true; + break; - case 844: - if (GetBodyType() == BT_Humanoid && GetLevel() <= 88) - return true; - break; - } + case IS_CLASS_ROGUE: + if (GetClass() == ROGUE) + return true; + break; - //Limit to amount of pets - if (value >= 221 && value <= 249){ + case IS_CLASS_SHAMAN: + if (GetClass() == SHAMAN) + return true; + break; + + case IS_CLASS_NECRO: + if (GetClass() == NECROMANCER) + return true; + break; + + case IS_CLASS_MAGE: + if (GetClass() == MAGICIAN) + return true; + break; + + case IS_CLASS_ENCHANTER: + if (GetClass() == ENCHANTER) + return true; + break; + + case IS_CLASS_BEASTLORD: + if (GetClass() == BEASTLORD) + return true; + break; + + case IS_CLASS_BERSERKER: + if (GetClass() == BERSERKER) + return true; + break; + + case IS_CLASS_CLR_SHM_DRU: + if (IsWISCasterClass(GetClass())) + return true; + break; + + case IS_CLASS_NOT_WAR_PAL_SK: + if ((GetClass() != WARRIOR) && (GetClass() != PALADIN) && (GetClass() != SHADOWKNIGHT)) + return true; + break; + + case IS_LEVEL_UNDER_100: + if (GetLevel() < 100) + return true; + break; + + case IS_NOT_RAID_BOSS: + if (!IsRaidTarget()) + return true; + break; + + case IS_RAID_BOSS: + if (IsRaidTarget()) + return true; + break; + + case FRENZIED_BURNOUT_ACTIVE: + if (HasBuffWithSpellGroup(SPELLGROUP_FRENZIED_BURNOUT)) + return true; + break; + + case FRENZIED_BURNOUT_NOT_ACTIVE: + if (!HasBuffWithSpellGroup(SPELLGROUP_FRENZIED_BURNOUT)) + return true; + break; + + case IS_HP_ABOVE_75_PCT: + if (GetHPRatio() > 75) + return true; + break; + + case IS_HP_LESS_THAN_20_PCT: + if (GetHPRatio() <= 20) + return true; + break; + + case IS_HP_LESS_THAN_50_PCT: + if (GetHPRatio() <= 50) + return true; + break; + + case IS_HP_LESS_THAN_75_PCT: + if (GetHPRatio() <= 75) + return true; + break; + + case IS_NOT_IN_COMBAT: + if (!IsEngaged()) + return true; + break; + + case IS_HP_LESS_THAN_35_PCT: + if (GetHPRatio() <= 35) + return true; + break; + + case HAS_BETWEEN_1_TO_2_PETS_ON_HATELIST: { int count = hate_list.GetSummonedPetCountOnHateList(this); + if (count >= 1 && count <= 2) { + return true; + } + break; + } - for (int base2_value = 221; base2_value <= 249; ++base2_value){ - if (value == base2_value){ - if (count >= (base2_value - 220)){ - return true; - } + case HAS_BETWEEN_3_TO_5_PETS_ON_HATELIST: { + int count = hate_list.GetSummonedPetCountOnHateList(this); + if (count >= 3 && count <= 5) { + return true; + } + break; + } + + case HAS_BETWEEN_6_TO_9_PETS_ON_HATELIST: { + int count = hate_list.GetSummonedPetCountOnHateList(this); + if (count >= 6 && count <= 9) { + return true; + } + break; + } + + case HAS_BETWEEN_10_TO_14_PETS_ON_HATELIST: { + int count = hate_list.GetSummonedPetCountOnHateList(this); + if (count >= 10 && count <= 14) { + return true; + } + break; + } + + case HAS_MORE_THAN_14_PETS_ON_HATELIST: { + int count = hate_list.GetSummonedPetCountOnHateList(this); + if (count > 14) { + return true; + } + break; + } + + case IS_CLASS_CHAIN_OR_PLATE: + if (IsClient() && + ((GetClass() == WARRIOR) || (GetClass() == BARD) || (GetClass() == SHADOWKNIGHT) || (GetClass() == PALADIN) || (GetClass() == CLERIC) + || (GetClass() == RANGER) || (GetClass() == SHAMAN) || (GetClass() == ROGUE) || (GetClass() == BERSERKER))) + return true; + break; + + case IS_HP_BETWEEN_5_AND_9_PCT: + if (GetHPRatio() >= 5 && GetHPRatio() <= 9) + return true; + break; + + case IS_HP_BETWEEN_10_AND_14_PCT: + if (GetHPRatio() >= 10 && GetHPRatio() <= 14) + return true; + break; + + case IS_HP_BETWEEN_15_AND_19_PCT: + if (GetHPRatio() >= 15 && GetHPRatio() <= 19) + return true; + break; + + case IS_HP_BETWEEN_20_AND_24_PCT: + if (GetHPRatio() >= 20 && GetHPRatio() <= 24) + return true; + break; + + case IS_HP_BETWEEN_25_AND_29_PCT: + if (GetHPRatio() >= 25 && GetHPRatio() <= 29) + return true; + break; + + case IS_HP_BETWEEN_30_AND_34_PCT: + if (GetHPRatio() >= 30 && GetHPRatio() <= 34) + return true; + break; + + case IS_HP_BETWEEN_35_AND_39_PCT: + if (GetHPRatio() >= 35 && GetHPRatio() <= 39) + return true; + break; + + case IS_HP_BETWEEN_40_AND_44_PCT: + if (GetHPRatio() >= 40 && GetHPRatio() <= 44) + return true; + break; + + case IS_HP_BETWEEN_45_AND_49_PCT: + if (GetHPRatio() >= 45 && GetHPRatio() <= 49) + return true; + break; + + case IS_HP_BETWEEN_50_AND_54_PCT: + if (GetHPRatio() >= 50 && GetHPRatio() <= 54) + return true; + break; + + case IS_HP_BETWEEN_55_AND_59_PCT: + if (GetHPRatio() >= 55 && GetHPRatio() <= 59) + return true; + break; + + case IS_HP_BETWEEN_5_AND_15_PCT: + if (GetHPRatio() >= 5 && GetHPRatio() <= 15) + return true; + break; + + case IS_HP_BETWEEN_15_AND_25_PCT: + if (GetHPRatio() >= 15 && GetHPRatio() <= 25) + return true; + break; + + case IS_HP_BETWEEN_1_AND_25_PCT: + if (GetHPRatio() <= 25) + return true; + break; + + case IS_HP_BETWEEN_25_AND_35_PCT: + if (GetHPRatio() > 25 && GetHPRatio() <= 35) + return true; + break; + + case IS_HP_BETWEEN_35_AND_45_PCT: + if (GetHPRatio() > 35 && GetHPRatio() <= 45) + return true; + break; + + case IS_HP_BETWEEN_45_AND_55_PCT: + if (GetHPRatio() > 45 && GetHPRatio() <= 55) + return true; + break; + + case IS_HP_BETWEEN_55_AND_65_PCT: + if (GetHPRatio() > 55 && GetHPRatio() <= 65) + return true; + break; + + case IS_HP_BETWEEN_65_AND_75_PCT: + if (GetHPRatio() > 65 && GetHPRatio() <= 75) + return true; + break; + + case IS_HP_BETWEEN_75_AND_85_PCT: + if (GetHPRatio() > 75 && GetHPRatio() <= 85) + return true; + break; + + case IS_HP_BETWEEN_85_AND_95_PCT: + if (GetHPRatio() > 85 && GetHPRatio() <= 95) + return true; + break; + + case IS_HP_ABOVE_45_PCT: + if (GetHPRatio() > 45) + return true; + break; + + case IS_HP_ABOVE_55_PCT: + if (GetHPRatio() > 55) + return true; + break; + + case IS_MANA_ABOVE_10_PCT: + if (GetManaRatio() > 10) + return true; + break; + + case IS_ENDURANCE_BELOW_40_PCT: + if (IsClient() && CastToClient()->GetEndurancePercent() <= 40) + return true; + break; + + case IS_MANA_BELOW_40_PCT: + if (GetManaRatio() <= 40) + return true; + break; + + case IS_HP_ABOVE_20_PCT: + if (GetHPRatio() > 20) + return true; + break; + + case IS_NOT_UNDEAD_OR_SUMMONED: + if ((GetBodyType() != BT_Undead) && (GetBodyType() != BT_Summoned)) + return true; + break; + + case IS_NOT_PLANT: + if (GetBodyType() != BT_Plant) + return true; + break; + + case IS_NOT_CLIENT: + if (!IsClient()) + return true; + break; + + case IS_CLIENT: + if (IsClient()) + return true; + break; + + case IS_LEVEL_ABOVE_42_AND_IS_CLIENT: + if (IsClient() && GetLevel() > 42) + return true; + break; + + case IS_TREANT: + if (GetRace() == RT_TREANT || GetRace() == RT_TREANT_2 || GetRace() == RT_TREANT_3) + return true; + break; + + case IS_SCARECROW: + if (GetRace() == RT_SCARECROW || GetRace() == RT_SCARECROW_2) + return true; + break; + + case IS_VAMPIRE_OR_UNDEAD_OR_UNDEADPET: + if (GetBodyType() == BT_Vampire || GetBodyType() == BT_Undead || GetBodyType() == BT_SummonedUndead) + return true; + break; + + case IS_NOT_VAMPIRE_OR_UNDEAD: + if (GetBodyType() != BT_Vampire && GetBodyType() != BT_Undead && GetBodyType() != BT_SummonedUndead) + return true; + break; + + case IS_CLASS_KNIGHT_HYBRID_MELEE: + if (IsHybridClass(GetClass()) || IsNonSpellFighterClass(GetClass())) + return true; + break; + + case IS_CLASS_WARRIOR_CASTER_PRIEST: + if (IsCasterClass(GetClass()) || GetClass() == WARRIOR) + return true; + break; + + case IS_END_BELOW_21_PCT: + if (IsClient() && CastToClient()->GetEndurancePercent() <= 21) + return true; + break; + + case IS_END_BELOW_25_PCT: + if (IsClient() && CastToClient()->GetEndurancePercent() <= 25) + return true; + break; + + case IS_END_BELOW_29_PCT: + if (IsClient() && CastToClient()->GetEndurancePercent() <= 29) + return true; + break; + + case IS_REGULAR_SERVER: + return true; // todo implement progression flag assume not progression for now + break; + + case IS_PROGRESSION_SERVER: + return false; // todo implement progression flag assume not progression for now + break; + + case IS_GOD_EXPANSION_UNLOCKED: + return true; // todo implement progression flag assume not progression for now, this one is a check if GoD is live + break; + + case IS_HUMANOID_LEVEL_84_MAX: + if (GetBodyType() == BT_Humanoid && GetLevel() <= 84) + return true; + break; + + case IS_HUMANOID_LEVEL_86_MAX: + if (GetBodyType() == BT_Humanoid && GetLevel() <= 86) + return true; + break; + + case IS_HUMANOID_LEVEL_88_MAX: + if (GetBodyType() == BT_Humanoid && GetLevel() <= 88) + return true; + break; + + case IS_LEVEL_90_MAX: + if (GetLevel() <= 90) + return true; + break; + + case IS_LEVEL_92_MAX: + if (GetLevel() <= 92) + return true; + break; + + case IS_LEVEL_94_MAX: + if (GetLevel() <= 94) + return true; + break; + + case IS_LEVEL_95_MAX: + if (GetLevel() <= 95) + return true; + break; + + case IS_LEVEL_97_MAX: + if (GetLevel() <= 97) + return true; + break; + + case IS_LEVEL_99_MAX: + if (GetLevel() <= 99) + return true; + break; + + case IS_LEVEL_100_MAX: + if (GetLevel() <= 100) + return true; + break; + + case IS_LEVEL_102_MAX: + if (GetLevel() <= 102) + return true; + break; + + case IS_LEVEL_104_MAX: + if (GetLevel() <= 104) + return true; + break; + case IS_LEVEL_105_MAX: + if (GetLevel() <= 105) + return true; + break; + + case IS_LEVEL_107_MAX: + if (GetLevel() <= 107) + return true; + break; + + case IS_LEVEL_109_MAX: + if (GetLevel() <= 109) + return true; + break; + case IS_LEVEL_110_MAX: + if (GetLevel() <= 110) + return true; + break; + + case IS_LEVEL_112_MAX: + if (GetLevel() <= 112) + return true; + break; + + case IS_LEVEL_114_MAX: + if (GetLevel() <= 114) + return true; + break; + + case IS_BETWEEN_LEVEL_1_AND_75: + if (GetLevel() >= 1 && GetLevel() <= 75) + return true; + break; + + case IS_BETWEEN_LEVEL_76_AND_85: + if (GetLevel() >= 76 && GetLevel() <= 85) + return true; + break; + + case IS_BETWEEN_LEVEL_86_AND_95: + if (GetLevel() >= 86 && GetLevel() <= 95) + return true; + break; + + case IS_BETWEEN_LEVEL_96_AND_105: + if (GetLevel() >= 96 && GetLevel() <= 105) + return true; + break; + + case IS_HP_LESS_THAN_80_PCT: + if (GetHPRatio() < 80) + return true; + break; + + case IS_LEVEL_ABOVE_34: + if (GetLevel() < 34) + return true; + break; + + case HAS_NO_MANA_BURN_BUFF: { + bool has_effect = false; + for (int i = 0; i < GetMaxTotalSlots(); i++) { + if (IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SE_ManaBurn)) { + has_effect = true; } } - } - - //Limit to Body Type - if (value >= 600 && value <= 699){ - if (GetBodyType() == (value - 600)) + if (!has_effect) { return true; - } - - //Limit to Race. *Not implemented on live - if (value >= 10000 && value <= 11000){ - if (GetRace() == (value - 10000)) - return true; - } - } //End Damage - - if (!IsDamage || UseCastRestriction) { - - //Heal only if HP within specified range. [Doesn't follow a set forumla for all values...] - if (value >= 400 && value <= 408){ - for (int base2_value = 400; base2_value <= 408; ++base2_value){ - if (value == base2_value){ - - if (value == 400 && GetHPRatio() <= 25) - return true; - - else if (value == base2_value){ - if (GetHPRatio() > 25+((base2_value - 401)*10) && GetHPRatio() <= 35+((base2_value - 401)*10)) - return true; - } - } } + break; } - - else if (value >= 500 && value <= 549){ - for (int base2_value = 500; base2_value <= 520; ++base2_value){ - if (value == base2_value){ - if (GetHPRatio() < (base2_value - 500)*5) - return true; - } - } - } - - else if (value == 399) { - if (GetHPRatio() > 15 && GetHPRatio() <= 25) + + case IS_CLIENT_AND_MALE_PLATE_USER: + if (IsClient() && GetGender() == MALE && IsPlateClass(GetClass())) return true; - } - } // End Heal + break; + case IS_CLEINT_AND_MALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD: + if (IsClient() && GetGender() == MALE && (IsCasterClass(GetClass()) && GetClass() != CLERIC)) + return true; + break; + + case IS_CLIENT_AND_MALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE: + if (IsClient() && GetGender() == MALE && + (GetClass() == BEASTLORD || GetClass() == BERSERKER || GetClass() == MONK || GetClass() == RANGER || GetClass() == ROGUE)) + return true; + break; + + case IS_CLIENT_AND_FEMALE_PLATE_USER: + if (IsClient() && GetGender() == FEMALE && IsPlateClass(GetClass())) + return true; + break; + + case IS_CLIENT_AND_FEMALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD: + if (IsClient() && GetGender() == FEMALE && (IsCasterClass(GetClass()) && GetClass() != CLERIC)) + return true; + break; + + case IS_CLIENT_AND_FEMALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE: + if (IsClient() && GetGender() == FEMALE && + (GetClass() == BEASTLORD || GetClass() == BERSERKER || GetClass() == MONK || GetClass() == RANGER || GetClass() == ROGUE)) + return true; + break; + + case IS_HP_ABOVE_50_PCT: + if (GetHPRatio() > 50) + return true; + break; + + case IS_HP_BELOW_50_PCT: + if (GetHPRatio() <= 50) + return true; + break; + + case IS_OFF_HAND_EQUIPED: + if (HasShieldEquiped() || CanThisClassDualWield()) + return true; + break; + + case IS_MANA_BELOW_20_PCT: + if (GetManaRatio() <= 20) + return true; + break; + + case IS_MANA_ABOVE_50_PCT: + if (GetManaRatio() >= 50) + return true; + break; + + case IS_SUMMONED_OR_UNDEAD: + if (GetBodyType() == BT_Summoned || GetBodyType() == BT_Undead) + return true; + break; + + + case IS_CLASS_CASTER_PRIEST: + if (IsCasterClass(GetClass())) + return true; + break; + + case IS_END_OR_MANA_ABOVE_20_PCT: { + if (IsNonSpellFighterClass(GetClass()) && CastToClient()->GetEndurancePercent() >= 20) { + return true; + } + else if (!IsNonSpellFighterClass(GetClass()) && GetManaRatio() >= 20) { + return true; + } + break; + } + + case IS_END_OR_MANA_BELOW_30_PCT: + case IS_END_OR_MANA_BELOW_30_PCT2: { + if (IsNonSpellFighterClass(GetClass()) && CastToClient()->GetEndurancePercent() <= 30) { + return true; + } + else if (!IsNonSpellFighterClass(GetClass()) && GetManaRatio() <= 30) { + return true; + } + break; + } + + case IS_NOT_CLASS_BARD: + if (GetClass() != BARD) + return true; + break; + + case HAS_NO_PACT_OF_FATE_RECOURSE_BUFF: + if (!FindBuff(SPELL_PACT_OF_HATE_RECOURSE)) + return true; + break; + + case HAS_NO_ROGUES_FURY_BUFF: + if (!HasBuffWithSpellGroup(SPELLGROUP_ROGUES_FURY)) + return true; + break; + + case HAS_NO_ILLUSIONS_OF_GRANDEUR_BUFF: + if (!HasBuffWithSpellGroup(SPELLGROUP_ILLUSION_OF_GRANDEUR)) + return true; + break; + + case HAS_NO_HARMONIOUS_PRECISION_BUFF: + if (!HasBuffWithSpellGroup(SPELLGROUP_HARMONIOUS_PRECISION)) + return true; + break; + + case HAS_NO_HARMONIOUS_EXPANSE_BUFF: + if (!HasBuffWithSpellGroup(SPELLGROUP_HARMONIOUS_EXPANSE)) + return true; + break; + + case HAS_NO_FURIOUS_RAMPAGE_BUFF: + if (!HasBuffWithSpellGroup(SPELLGROUP_FURIOUS_RAMPAGE)) + return true; + break; + + case HAS_NO_SHROUD_OF_PRAYER_BUFF: + if (!HasBuffWithSpellGroup(SPELLGROUP_SHROUD_OF_PRAYER)) + return true; + break; + + case HAS_INCENDIARY_OOZE_BUFF: + if (FindBuff(SPELL_INCENDIARY_OOZE_BUFF)) + return true; + break; + + //Not handled, just allow them to pass for now. + case UNKNOWN_3: + case HAS_CRYSTALLIZED_FLAME_BUFF: + case UNKNOWN_199: + case UNKNOWN_TOO_MUCH_HP_410: + case UNKNOWN_TOO_MUCH_HP_411: + case HAS_TBL_ESIANTI_ACCESS: + case HAS_ITEM_CLOCKWORK_SCRAPS: + case IN_TWO_HANDED_STANCE: + case IN_DUAL_WIELD_HANDED_STANCE: + case IN_SHIELD_STANCE: + case NOT_IN_TWO_HANDED_STANCE: + case NOT_IN_DUAL_WIELD_HANDED_STANCE: + case NOT_IN_SHIELD_STANCE: + case DISABLED_UNTIL_EXPANSION_ROK: + case DISABLED_UNTIL_EXPANSION_SOV: + case DISABLED_UNTIL_EXPANSION_SOL: + case DISABLED_UNTIL_EXPANSION_POP: + case DISABLED_UNTIL_EXPANSION_LOY: + case DISABLED_UNTIL_EXPANSION_LDON: + case DISABLED_UNTIL_EXPANSION_GOD: + case DISABLED_UNTIL_EXPANSION_OOW: + case DISABLED_UNTIL_EXPANSION_DON: + case DISABLED_UNTIL_EXPANSION_DOD: + case DISABLED_UNTIL_EXPANSION_POR: + case DISABLED_UNTIL_EXPANSION_TSS: + case DISABLED_UNTIL_EXPANSION_TBS: + case DISABLED_UNTIL_EXPANSION_SOF: + case DISABLED_UNTIL_EXPANSION_SOD: + case DISABLED_UNTIL_EXPANSION_UF: + case DISABLED_UNTIL_EXPANSION_HOT: + case DISABLED_UNTIL_EXPANSION_VOA: + case DISABLED_UNTIL_EXPANSION_ROF: + case DISABLED_UNTIL_EXPANSION_COF: + case DISABLED_UNTIL_EXPANSION_TDS: + case DISABLED_UNTIL_EXPANSION_TBM: + case DISABLED_UNTIL_EXPANSION_EOK: + case DISABLED_UNTIL_EXPANSION_ROS: + case DISABLED_UNTIL_EXPANSION_TBL: + case DISABLED_UNTIL_EXPANSION_TOV: + case DISABLED_UNTIL_EXPANSION_COV: + case HAS_TRAVELED_TO_STRATOS: + case HAS_TRAVELED_TO_AALISHAI: + case HAS_TRAVELED_TO_MEARATS: + case COMPLETED_ACHIEVEMENT_LEGENDARY_ANSWERER: + case NOT_COMPLETED_ACHIEVEMENT_LEGENDARY_ANSWERER: + case HAS_WEAPONSTANCE_DEFENSIVE_PROFICIENCY: + case HAS_WEAPONSTANCE_TWO_HAND_PROFICIENCY: + case HAS_WEAPONSTANCE_DUAL_WEILD_PROFICIENCY: + case UNKNOWN_812: + case UNKNOWN_814: + case UNKNOWN_822: + case UNKNOWN_840: + case UNKNOWN_841: + case UNKNOWN_99999: + return true; + break; + } + + if (value >= HAS_AT_LEAST_1_PET_ON_HATELIST && value <= HAS_AT_LEAST_20_PETS_ON_HATELIST) { + int count = hate_list.GetSummonedPetCountOnHateList(this); + int minium_amount_of_pets_needed = (1 + value) - HAS_AT_LEAST_1_PET_ON_HATELIST; + + if (count >= minium_amount_of_pets_needed) { + return true; + } + } + + if (value >= IS_HP_BELOW_5_PCT && value <= IS_HP_BELOW_95_PCT) { + int hp_below_amt = 5 * ((1 + value) - IS_HP_BELOW_5_PCT); + if (GetHPRatio() <= hp_below_amt) { + return true; + } + } + + if (value >= IS_BODY_TYPE_UNDEFINED && value <= IS_BODY_TYPE_MURAMITE){ + if (GetBodyType() == (value - IS_BODY_TYPE_UNDEFINED)) + return true; + } + + //Limit to Race. *Not implemented on live, too much potential not to give an option here. + if (value >= IS_RACE_FIRST_CUSTOM && value <= IS_RACE_LAST_CUSTOM){ + if (GetRace() == (value - IS_RACE_FIRST_CUSTOM)) + return true; + } return false; } diff --git a/zone/spells.cpp b/zone/spells.cpp index 12bc97493..f5a756f79 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1535,8 +1535,13 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce if (isproc && IsNPC() && CastToNPC()->GetInnateProcSpellID() == spell_id) targetType = ST_Target; - if (spell_target && !spell_target->PassCastRestriction(true, spells[spell_id].CastRestriction)){ - MessageString(Chat::Red,SPELL_NEED_TAR); + if (spell_target && spells[spell_id].CastRestriction && !spell_target->PassCastRestriction(spells[spell_id].CastRestriction)){ + Message(Chat::Red, "Your target does not meet the spell requirements."); //Current live also adds description after this from dbstr_us type 39 + return false; + } + + if (spells[spell_id].caster_requirement_id && !PassCastRestriction(spells[spell_id].caster_requirement_id)) { + MessageString(Chat::Red, SPELL_WOULDNT_HOLD); return false; } @@ -4146,6 +4151,16 @@ uint32 Mob::BuffCount() { return active_buff_count; } +bool Mob::HasBuffWithSpellGroup(int spellgroup) +{ + for (int i = 0; i < GetMaxTotalSlots(); i++) { + if (IsValidSpell(buffs[i].spellid) && spells[buffs[i].spellid].spellgroup == spellgroup) { + return true; + } + } + return false; +} + // removes all buffs void Mob::BuffFadeAll() {