From d63fcded760dc82563baa78714120f4d0cf4da13 Mon Sep 17 00:00:00 2001 From: obligaron Date: Mon, 19 Jul 2021 05:55:31 +0200 Subject: [PATCH] Refactor PlaceGroup (#2425) * Rename MonstPlace -> CanPlaceMonster * Refactor custom hitpoints and armorclass out of mUnqAttr * Introduce enum UniqueMonsterPack --- Source/monstdat.cpp | 204 ++++++++++++++++++++++---------------------- Source/monstdat.h | 28 +++++- Source/monster.cpp | 40 ++++----- 3 files changed, 147 insertions(+), 125 deletions(-) diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index 26434ea13..4fd83bfdd 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -467,110 +467,110 @@ const char MonstAvailTbl[] = { /** Contains the data related to each unique monster ID. */ const UniqMonstStruct UniqMonst[] = { // clang-format off - // mtype, mName, mTrnName, mlevel, mmaxhp, mAi, mint, mMinDamage, mMaxDamage, mMagicRes, mUnqAttr, mUnqVar1, mUnqVar2, mtalkmsg + // mtype, mName, mTrnName, mlevel, mmaxhp, mAi, mint, mMinDamage, mMaxDamage, mMagicRes, monsterPack, customHitpoints, customArmorClass, mtalkmsg // TRANSLATORS: Unique Monster Block start - { MT_NGOATMC, N_("Gharbad the Weak"), "BSDB", 4, 120, AI_GARBUD, 3, 8, 16, IMMUNE_LIGHTNING | IMMUNE_NULL_40, 0, 0, 0, TEXT_GARBUD1 }, - { MT_SKING, N_("Skeleton King"), "GENRL", 0, 240, AI_SKELKING, 3, 6, 16, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, 1, 0, 0, TEXT_NONE }, - { MT_COUNSLR, N_("Zhar the Mad"), "GENERAL", 8, 360, AI_ZHAR, 3, 16, 40, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING , 0, 0, 0, TEXT_ZHAR1 }, - { MT_BFALLSP, N_("Snotspill"), "BNG", 4, 220, AI_SNOTSPIL, 3, 10, 18, RESIST_LIGHTNING , 0, 0, 0, TEXT_BANNER10 }, - { MT_ADVOCATE, N_("Arch-Bishop Lazarus"), "GENERAL", 0, 600, AI_LAZARUS, 3, 30, 50, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, 0, 0, 0, TEXT_VILE13 }, - { MT_HLSPWN, N_("Red Vex"), "REDV", 0, 400, AI_LAZHELP, 3, 30, 50, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, 0, 0, 0, TEXT_VILE13 }, - { MT_HLSPWN, N_("Black Jade"), "BLKJD", 0, 400, AI_LAZHELP, 3, 30, 50, IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40, 0, 0, 0, TEXT_VILE13 }, - { MT_RBLACK, "Lachdanan", "BHKA", 14, 500, AI_LACHDAN, 3, 0, 0, 0 , 0, 0, 0, TEXT_VEIL9 }, - { MT_BTBLACK, N_("Warlord of Blood"), "GENERAL", 13, 850, AI_WARLORD, 3, 35, 50, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, 0, 0, 0, TEXT_WARLRD9 }, - { MT_CLEAVER, N_("The Butcher"), "GENRL", 0, 220, AI_CLEAVER, 3, 6, 12, RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_HORKDMN, N_("Hork Demon"), "GENRL", 19, 300, AI_HORKDMN, 3, 20, 35, RESIST_LIGHTNING , 0, 0, 0, TEXT_NONE }, - { MT_DEFILER, N_("The Defiler"), "GENRL", 20, 480, AI_SKELSD, 3, 30, 40, RESIST_MAGIC | RESIST_FIRE | IMMUNE_LIGHTNING , 0, 0, 0, TEXT_NONE }, - { MT_NAKRUL, "Na-Krul", "GENRL", 0, 1332, AI_SKELSD, 3, 40, 50, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_TSKELAX, N_("Bonehead Keenaxe"), "BHKA", 2, 91, AI_SKELSD, 2, 4, 10, IMMUNE_MAGIC | IMMUNE_NULL_40, 7, 100, 0, TEXT_NONE }, - { MT_RFALLSD, N_("Bladeskin the Slasher"), "BSTS", 2, 51, AI_FALLEN, 0, 6, 18, RESIST_FIRE , 11, 45, 0, TEXT_NONE }, - { MT_NZOMBIE, N_("Soulpus"), "GENERAL", 2, 133, AI_ZOMBIE, 0, 4, 8, RESIST_FIRE | RESIST_LIGHTNING , 0, 0, 0, TEXT_NONE }, - { MT_RFALLSP, N_("Pukerat the Unclean"), "PTU", 2, 77, AI_FALLEN, 3, 1, 5, RESIST_FIRE , 0, 0, 0, TEXT_NONE }, - { MT_WSKELAX, N_("Boneripper"), "BR", 2, 54, AI_BAT, 0, 6, 15, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_NZOMBIE, N_("Rotfeast the Hungry"), "ETH", 2, 85, AI_SKELSD, 3, 4, 12, IMMUNE_MAGIC | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_DFALLSD, N_("Gutshank the Quick"), "GTQ", 3, 66, AI_BAT, 2, 6, 16, RESIST_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_TSKELSD, N_("Brokenhead Bangshield"), "BHBS", 3, 108, AI_SKELSD, 3, 12, 20, IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_YFALLSP, "Bongo", "BNG", 3, 178, AI_FALLEN, 3, 9, 21, 0 , 3, 0, 0, TEXT_NONE }, - { MT_BZOMBIE, N_("Rotcarnage"), "RCRN", 3, 102, AI_ZOMBIE, 3, 9, 24, IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40, 11, 45, 0, TEXT_NONE }, - { MT_NSCAV, N_("Shadowbite"), "SHBT", 2, 60, AI_SKELSD, 3, 3, 20, IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_WSKELBW, N_("Deadeye"), "DE", 2, 49, AI_GOATBOW, 0, 6, 9, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_RSKELAX, N_("Madeye the Dead"), "MTD", 4, 75, AI_BAT, 0, 9, 21, IMMUNE_MAGIC | IMMUNE_FIRE , 11, 30, 0, TEXT_NONE }, - { MT_BSCAV, "El Chupacabras", "GENERAL", 3, 120, AI_GOATMC, 0, 10, 18, RESIST_FIRE , 3, 30, 0, TEXT_NONE }, - { MT_TSKELBW, N_("Skullfire"), "SKFR", 3, 125, AI_GOATBOW, 1, 6, 10, IMMUNE_FIRE , 0, 100, 0, TEXT_NONE }, - { MT_SNEAK, N_("Warpskull"), "TSPO", 3, 117, AI_SNEAK, 2, 6, 18, RESIST_FIRE | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_GZOMBIE, N_("Goretongue"), "PMR", 3, 156, AI_SKELSD, 1, 15, 30, IMMUNE_MAGIC | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_WSCAV, N_("Pulsecrawler"), "BHKA", 4, 150, AI_SCAV, 0, 16, 20, IMMUNE_FIRE | RESIST_LIGHTNING , 11, 45, 0, TEXT_NONE }, - { MT_BLINK, N_("Moonbender"), "GENERAL", 4, 135, AI_BAT, 0, 9, 27, IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_BLINK, N_("Wrathraven"), "GENERAL", 5, 135, AI_BAT, 2, 9, 22, IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_YSCAV, N_("Spineeater"), "GENERAL", 4, 180, AI_SCAV, 1, 18, 25, IMMUNE_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_RSKELBW, N_("Blackash the Burning"), "BASHTB", 4, 120, AI_GOATBOW, 0, 6, 16, IMMUNE_MAGIC | IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_BFALLSD, N_("Shadowcrow"), "GENERAL", 5, 270, AI_SNEAK, 2, 12, 25, 0 , 3, 0, 0, TEXT_NONE }, - { MT_LRDSAYTR, N_("Blightstone the Weak"), "BHKA", 4, 360, AI_SKELSD, 0, 4, 12, IMMUNE_MAGIC | RESIST_LIGHTNING , 7, 70, 0, TEXT_NONE }, - { MT_FAT, N_("Bilefroth the Pit Master"), "BFTP", 6, 210, AI_BAT, 1, 16, 23, IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_NGOATBW, N_("Bloodskin Darkbow"), "BSDB", 5, 207, AI_GOATBOW, 0, 3, 16, RESIST_FIRE | RESIST_LIGHTNING , 11, 55, 0, TEXT_NONE }, - { MT_GLOOM, N_("Foulwing"), "DB", 5, 246, AI_RHINO, 3, 12, 28, RESIST_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_XSKELSD, N_("Shadowdrinker"), "SHDR", 5, 300, AI_SNEAK, 1, 18, 26, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, 8, 45, 0, TEXT_NONE }, - { MT_UNSEEN, N_("Hazeshifter"), "BHKA", 5, 285, AI_SNEAK, 3, 18, 30, IMMUNE_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_NACID, N_("Deathspit"), "BFDS", 6, 303, AI_ACIDUNIQ, 0, 12, 32, RESIST_FIRE | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_RGOATMC, N_("Bloodgutter"), "BGBL", 6, 315, AI_BAT, 1, 24, 34, IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_BGOATMC, N_("Deathshade Fleshmaul"), "DSFM", 6, 276, AI_RHINO, 0, 12, 24, IMMUNE_MAGIC | RESIST_FIRE , 8, 65, 0, TEXT_NONE }, - { MT_WYRM, N_("Warmaggot the Mad"), "GENERAL", 6, 246, AI_BAT, 3, 15, 30, RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_STORM, N_("Glasskull the Jagged"), "BHKA", 7, 354, AI_STORM, 0, 18, 30, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_RGOATBW, N_("Blightfire"), "BLF", 7, 321, AI_SUCC, 2, 13, 21, IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_GARGOYLE, N_("Nightwing the Cold"), "GENERAL", 7, 342, AI_BAT, 1, 18, 26, IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_GGOATBW, N_("Gorestone"), "GENERAL", 7, 303, AI_GOATBOW, 1, 15, 28, RESIST_LIGHTNING | IMMUNE_NULL_40, 7, 70, 0, TEXT_NONE }, - { MT_BMAGMA, N_("Bronzefist Firestone"), "GENERAL", 8, 360, AI_MAGMA, 0, 30, 36, IMMUNE_MAGIC | RESIST_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_INCIN, N_("Wrathfire the Doomed"), "WFTD", 8, 270, AI_SKELSD, 2, 20, 30, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_NMAGMA, N_("Firewound the Grim"), "BHKA", 8, 303, AI_MAGMA, 0, 18, 22, IMMUNE_MAGIC | RESIST_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_MUDMAN, N_("Baron Sludge"), "BSM", 8, 315, AI_SNEAK, 3, 25, 34, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, 11, 75, 0, TEXT_NONE }, - { MT_GGOATMC, N_("Blighthorn Steelmace"), "BHSM", 7, 250, AI_RHINO, 0, 20, 28, RESIST_LIGHTNING , 11, 45, 0, TEXT_NONE }, - { MT_RACID, N_("Chaoshowler"), "GENERAL", 8, 240, AI_ACIDUNIQ, 0, 12, 20, 0 , 3, 0, 0, TEXT_NONE }, - { MT_REDDTH, N_("Doomgrin the Rotting"), "GENERAL", 8, 405, AI_STORM, 3, 25, 50, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_FLAMLRD, N_("Madburner"), "GENERAL", 9, 270, AI_STORM, 0, 20, 40, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_LTCHDMN, N_("Bonesaw the Litch"), "GENERAL", 9, 495, AI_STORM, 2, 30, 55, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_MUDRUN, N_("Breakspine"), "GENERAL", 9, 351, AI_RHINO, 0, 25, 34, RESIST_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_REDDTH, N_("Devilskull Sharpbone"), "GENERAL", 9, 444, AI_STORM, 1, 25, 40, IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_STORM, N_("Brokenstorm"), "GENERAL", 9, 411, AI_STORM, 2, 25, 36, IMMUNE_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_RSTORM, N_("Stormbane"), "GENERAL", 9, 555, AI_STORM, 3, 30, 30, IMMUNE_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_TOAD, N_("Oozedrool"), "GENERAL", 9, 483, AI_FAT, 3, 25, 30, RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_BLOODCLW, N_("Goldblight of the Flame"), "GENERAL", 10, 405, AI_GARG, 0, 15, 35, IMMUNE_MAGIC | IMMUNE_FIRE , 11, 80, 0, TEXT_NONE }, - { MT_OBLORD, N_("Blackstorm"), "GENERAL", 10, 525, AI_RHINO, 3, 20, 40, IMMUNE_MAGIC | IMMUNE_LIGHTNING , 11, 90, 0, TEXT_NONE }, - { MT_RACID, N_("Plaguewrath"), "GENERAL", 10, 450, AI_ACIDUNIQ, 2, 20, 30, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_RSTORM, N_("The Flayer"), "GENERAL", 10, 501, AI_STORM, 1, 20, 35, RESIST_MAGIC | RESIST_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_FROSTC, N_("Bluehorn"), "GENERAL", 11, 477, AI_RHINO, 1, 25, 30, IMMUNE_MAGIC | RESIST_FIRE , 11, 90, 0, TEXT_NONE }, - { MT_HELLBURN, N_("Warpfire Hellspawn"), "GENERAL", 11, 525, AI_FIREMAN, 3, 10, 40, RESIST_MAGIC | IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_NSNAKE, N_("Fangspeir"), "GENERAL", 11, 444, AI_SKELSD, 1, 15, 32, IMMUNE_FIRE | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_UDEDBLRG, N_("Festerskull"), "GENERAL", 11, 600, AI_STORM, 2, 15, 30, IMMUNE_MAGIC | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_NBLACK, N_("Lionskull the Bent"), "GENERAL", 12, 525, AI_SKELSD, 2, 25, 25, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_COUNSLR, N_("Blacktongue"), "GENERAL", 12, 360, AI_COUNSLR, 3, 15, 30, RESIST_FIRE | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_DEATHW, N_("Viletouch"), "GENERAL", 12, 525, AI_GARG, 3, 20, 40, IMMUNE_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_RSNAKE, N_("Viperflame"), "GENERAL", 12, 570, AI_SKELSD, 1, 25, 35, IMMUNE_FIRE | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_BSNAKE, N_("Fangskin"), "BHKA", 14, 681, AI_SKELSD, 2, 15, 50, IMMUNE_MAGIC | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_SUCCUBUS, N_("Witchfire the Unholy"), "GENERAL", 12, 444, AI_SUCC, 3, 10, 20, IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_BALROG, N_("Blackskull"), "BHKA", 13, 750, AI_SKELSD, 3, 25, 40, IMMUNE_MAGIC | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_UNRAV, N_("Soulslash"), "GENERAL", 12, 450, AI_SKELSD, 0, 25, 25, IMMUNE_MAGIC | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_VTEXLRD, N_("Windspawn"), "GENERAL", 12, 711, AI_SKELSD, 1, 35, 40, IMMUNE_MAGIC | IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_GSNAKE, N_("Lord of the Pit"), "GENERAL", 13, 762, AI_SKELSD, 2, 25, 42, RESIST_FIRE | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_RTBLACK, N_("Rustweaver"), "GENERAL", 13, 400, AI_SKELSD, 3, 1, 60, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_HOLOWONE, N_("Howlingire the Shade"), "GENERAL", 13, 450, AI_SKELSD, 2, 40, 75, RESIST_FIRE | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_MAEL, N_("Doomcloud"), "GENERAL", 13, 612, AI_STORM, 1, 1, 60, RESIST_FIRE | IMMUNE_LIGHTNING , 0, 0, 0, TEXT_NONE }, - { MT_PAINMSTR, N_("Bloodmoon Soulfire"), "GENERAL", 13, 684, AI_SKELSD, 1, 15, 40, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_SNOWWICH, N_("Witchmoon"), "GENERAL", 13, 310, AI_SUCC, 3, 30, 40, RESIST_LIGHTNING , 0, 0, 0, TEXT_NONE }, - { MT_VTEXLRD, N_("Gorefeast"), "GENERAL", 13, 771, AI_SKELSD, 3, 20, 55, RESIST_FIRE | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_RTBLACK, N_("Graywar the Slayer"), "GENERAL", 14, 672, AI_SKELSD, 1, 30, 50, RESIST_LIGHTNING | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_MAGISTR, N_("Dreadjudge"), "GENERAL", 14, 540, AI_COUNSLR, 1, 30, 40, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING , 3, 0, 0, TEXT_NONE }, - { MT_HLSPWN, N_("Stareye the Witch"), "GENERAL", 14, 726, AI_SUCC, 2, 30, 50, IMMUNE_FIRE , 0, 0, 0, TEXT_NONE }, - { MT_BTBLACK, N_("Steelskull the Hunter"), "GENERAL", 14, 831, AI_SKELSD, 3, 40, 50, RESIST_LIGHTNING | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_RBLACK, N_("Sir Gorash"), "GENERAL", 16, 1050, AI_SKELSD, 1, 20, 60, IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_CABALIST, N_("The Vizier"), "GENERAL", 15, 850, AI_COUNSLR, 2, 25, 40, IMMUNE_FIRE , 3, 0, 0, TEXT_NONE }, - { MT_REALWEAV, "Zamphir", "GENERAL", 15, 891, AI_SKELSD, 2, 30, 50, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_HLSPWN, N_("Bloodlust"), "GENERAL", 15, 825, AI_SUCC, 1, 20, 55, IMMUNE_MAGIC | IMMUNE_LIGHTNING | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_HLSPWN, "Webwidow", "GENERAL", 16, 774, AI_SUCC, 1, 20, 50, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_SOLBRNR, N_("Fleshdancer"), "GENERAL", 16, 999, AI_SUCC, 3, 30, 50, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, 0, 0, 0, TEXT_NONE }, - { MT_OBLORD, N_("Grimspike"), "GENERAL", 19, 534, AI_SNEAK, 1, 25, 40, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, + { MT_NGOATMC, N_("Gharbad the Weak"), "BSDB", 4, 120, AI_GARBUD, 3, 8, 16, IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_GARBUD1 }, + { MT_SKING, N_("Skeleton King"), "GENRL", 0, 240, AI_SKELKING, 3, 6, 16, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Independent, 0, 0, TEXT_NONE }, + { MT_COUNSLR, N_("Zhar the Mad"), "GENERAL", 8, 360, AI_ZHAR, 3, 16, 40, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::None, 0, 0, TEXT_ZHAR1 }, + { MT_BFALLSP, N_("Snotspill"), "BNG", 4, 220, AI_SNOTSPIL, 3, 10, 18, RESIST_LIGHTNING , UniqueMonsterPack::None, 0, 0, TEXT_BANNER10 }, + { MT_ADVOCATE, N_("Arch-Bishop Lazarus"), "GENERAL", 0, 600, AI_LAZARUS, 3, 30, 50, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_VILE13 }, + { MT_HLSPWN, N_("Red Vex"), "REDV", 0, 400, AI_LAZHELP, 3, 30, 50, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_VILE13 }, + { MT_HLSPWN, N_("Black Jade"), "BLKJD", 0, 400, AI_LAZHELP, 3, 30, 50, IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_VILE13 }, + { MT_RBLACK, "Lachdanan", "BHKA", 14, 500, AI_LACHDAN, 3, 0, 0, 0 , UniqueMonsterPack::None, 0, 0, TEXT_VEIL9 }, + { MT_BTBLACK, N_("Warlord of Blood"), "GENERAL", 13, 850, AI_WARLORD, 3, 35, 50, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_WARLRD9 }, + { MT_CLEAVER, N_("The Butcher"), "GENRL", 0, 220, AI_CLEAVER, 3, 6, 12, RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_HORKDMN, N_("Hork Demon"), "GENRL", 19, 300, AI_HORKDMN, 3, 20, 35, RESIST_LIGHTNING , UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_DEFILER, N_("The Defiler"), "GENRL", 20, 480, AI_SKELSD, 3, 30, 40, RESIST_MAGIC | RESIST_FIRE | IMMUNE_LIGHTNING , UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_NAKRUL, "Na-Krul", "GENRL", 0, 1332, AI_SKELSD, 3, 40, 50, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_TSKELAX, N_("Bonehead Keenaxe"), "BHKA", 2, 91, AI_SKELSD, 2, 4, 10, IMMUNE_MAGIC | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 100, 0, TEXT_NONE }, + { MT_RFALLSD, N_("Bladeskin the Slasher"), "BSTS", 2, 51, AI_FALLEN, 0, 6, 18, RESIST_FIRE , UniqueMonsterPack::Leashed, 0, 45, TEXT_NONE }, + { MT_NZOMBIE, N_("Soulpus"), "GENERAL", 2, 133, AI_ZOMBIE, 0, 4, 8, RESIST_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_RFALLSP, N_("Pukerat the Unclean"), "PTU", 2, 77, AI_FALLEN, 3, 1, 5, RESIST_FIRE , UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_WSKELAX, N_("Boneripper"), "BR", 2, 54, AI_BAT, 0, 6, 15, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_NZOMBIE, N_("Rotfeast the Hungry"), "ETH", 2, 85, AI_SKELSD, 3, 4, 12, IMMUNE_MAGIC | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_DFALLSD, N_("Gutshank the Quick"), "GTQ", 3, 66, AI_BAT, 2, 6, 16, RESIST_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_TSKELSD, N_("Brokenhead Bangshield"), "BHBS", 3, 108, AI_SKELSD, 3, 12, 20, IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_YFALLSP, "Bongo", "BNG", 3, 178, AI_FALLEN, 3, 9, 21, 0 , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_BZOMBIE, N_("Rotcarnage"), "RCRN", 3, 102, AI_ZOMBIE, 3, 9, 24, IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 45, TEXT_NONE }, + { MT_NSCAV, N_("Shadowbite"), "SHBT", 2, 60, AI_SKELSD, 3, 3, 20, IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_WSKELBW, N_("Deadeye"), "DE", 2, 49, AI_GOATBOW, 0, 6, 9, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_RSKELAX, N_("Madeye the Dead"), "MTD", 4, 75, AI_BAT, 0, 9, 21, IMMUNE_MAGIC | IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 30, TEXT_NONE }, + { MT_BSCAV, "El Chupacabras", "GENERAL", 3, 120, AI_GOATMC, 0, 10, 18, RESIST_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_TSKELBW, N_("Skullfire"), "SKFR", 3, 125, AI_GOATBOW, 1, 6, 10, IMMUNE_FIRE , UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_SNEAK, N_("Warpskull"), "TSPO", 3, 117, AI_SNEAK, 2, 6, 18, RESIST_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_GZOMBIE, N_("Goretongue"), "PMR", 3, 156, AI_SKELSD, 1, 15, 30, IMMUNE_MAGIC | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_WSCAV, N_("Pulsecrawler"), "BHKA", 4, 150, AI_SCAV, 0, 16, 20, IMMUNE_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 45, TEXT_NONE }, + { MT_BLINK, N_("Moonbender"), "GENERAL", 4, 135, AI_BAT, 0, 9, 27, IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_BLINK, N_("Wrathraven"), "GENERAL", 5, 135, AI_BAT, 2, 9, 22, IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_YSCAV, N_("Spineeater"), "GENERAL", 4, 180, AI_SCAV, 1, 18, 25, IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_RSKELBW, N_("Blackash the Burning"), "BASHTB", 4, 120, AI_GOATBOW, 0, 6, 16, IMMUNE_MAGIC | IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_BFALLSD, N_("Shadowcrow"), "GENERAL", 5, 270, AI_SNEAK, 2, 12, 25, 0 , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_LRDSAYTR, N_("Blightstone the Weak"), "BHKA", 4, 360, AI_SKELSD, 0, 4, 12, IMMUNE_MAGIC | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 70, 0, TEXT_NONE }, + { MT_FAT, N_("Bilefroth the Pit Master"), "BFTP", 6, 210, AI_BAT, 1, 16, 23, IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_NGOATBW, N_("Bloodskin Darkbow"), "BSDB", 5, 207, AI_GOATBOW, 0, 3, 16, RESIST_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 55, TEXT_NONE }, + { MT_GLOOM, N_("Foulwing"), "DB", 5, 246, AI_RHINO, 3, 12, 28, RESIST_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_XSKELSD, N_("Shadowdrinker"), "SHDR", 5, 300, AI_SNEAK, 1, 18, 26, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 45, TEXT_NONE }, + { MT_UNSEEN, N_("Hazeshifter"), "BHKA", 5, 285, AI_SNEAK, 3, 18, 30, IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_NACID, N_("Deathspit"), "BFDS", 6, 303, AI_ACIDUNIQ, 0, 12, 32, RESIST_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_RGOATMC, N_("Bloodgutter"), "BGBL", 6, 315, AI_BAT, 1, 24, 34, IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_BGOATMC, N_("Deathshade Fleshmaul"), "DSFM", 6, 276, AI_RHINO, 0, 12, 24, IMMUNE_MAGIC | RESIST_FIRE , UniqueMonsterPack::None, 0, 65, TEXT_NONE }, + { MT_WYRM, N_("Warmaggot the Mad"), "GENERAL", 6, 246, AI_BAT, 3, 15, 30, RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_STORM, N_("Glasskull the Jagged"), "BHKA", 7, 354, AI_STORM, 0, 18, 30, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_RGOATBW, N_("Blightfire"), "BLF", 7, 321, AI_SUCC, 2, 13, 21, IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_GARGOYLE, N_("Nightwing the Cold"), "GENERAL", 7, 342, AI_BAT, 1, 18, 26, IMMUNE_MAGIC | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_GGOATBW, N_("Gorestone"), "GENERAL", 7, 303, AI_GOATBOW, 1, 15, 28, RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 70, 0, TEXT_NONE }, + { MT_BMAGMA, N_("Bronzefist Firestone"), "GENERAL", 8, 360, AI_MAGMA, 0, 30, 36, IMMUNE_MAGIC | RESIST_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_INCIN, N_("Wrathfire the Doomed"), "WFTD", 8, 270, AI_SKELSD, 2, 20, 30, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_NMAGMA, N_("Firewound the Grim"), "BHKA", 8, 303, AI_MAGMA, 0, 18, 22, IMMUNE_MAGIC | RESIST_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_MUDMAN, N_("Baron Sludge"), "BSM", 8, 315, AI_SNEAK, 3, 25, 34, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 75, TEXT_NONE }, + { MT_GGOATMC, N_("Blighthorn Steelmace"), "BHSM", 7, 250, AI_RHINO, 0, 20, 28, RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 45, TEXT_NONE }, + { MT_RACID, N_("Chaoshowler"), "GENERAL", 8, 240, AI_ACIDUNIQ, 0, 12, 20, 0 , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_REDDTH, N_("Doomgrin the Rotting"), "GENERAL", 8, 405, AI_STORM, 3, 25, 50, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_FLAMLRD, N_("Madburner"), "GENERAL", 9, 270, AI_STORM, 0, 20, 40, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_LTCHDMN, N_("Bonesaw the Litch"), "GENERAL", 9, 495, AI_STORM, 2, 30, 55, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_MUDRUN, N_("Breakspine"), "GENERAL", 9, 351, AI_RHINO, 0, 25, 34, RESIST_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_REDDTH, N_("Devilskull Sharpbone"), "GENERAL", 9, 444, AI_STORM, 1, 25, 40, IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_STORM, N_("Brokenstorm"), "GENERAL", 9, 411, AI_STORM, 2, 25, 36, IMMUNE_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_RSTORM, N_("Stormbane"), "GENERAL", 9, 555, AI_STORM, 3, 30, 30, IMMUNE_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_TOAD, N_("Oozedrool"), "GENERAL", 9, 483, AI_FAT, 3, 25, 30, RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_BLOODCLW, N_("Goldblight of the Flame"), "GENERAL", 10, 405, AI_GARG, 0, 15, 35, IMMUNE_MAGIC | IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 80, TEXT_NONE }, + { MT_OBLORD, N_("Blackstorm"), "GENERAL", 10, 525, AI_RHINO, 3, 20, 40, IMMUNE_MAGIC | IMMUNE_LIGHTNING , UniqueMonsterPack::Leashed, 0, 90, TEXT_NONE }, + { MT_RACID, N_("Plaguewrath"), "GENERAL", 10, 450, AI_ACIDUNIQ, 2, 20, 30, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_RSTORM, N_("The Flayer"), "GENERAL", 10, 501, AI_STORM, 1, 20, 35, RESIST_MAGIC | RESIST_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_FROSTC, N_("Bluehorn"), "GENERAL", 11, 477, AI_RHINO, 1, 25, 30, IMMUNE_MAGIC | RESIST_FIRE , UniqueMonsterPack::Leashed, 0, 90, TEXT_NONE }, + { MT_HELLBURN, N_("Warpfire Hellspawn"), "GENERAL", 11, 525, AI_FIREMAN, 3, 10, 40, RESIST_MAGIC | IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_NSNAKE, N_("Fangspeir"), "GENERAL", 11, 444, AI_SKELSD, 1, 15, 32, IMMUNE_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_UDEDBLRG, N_("Festerskull"), "GENERAL", 11, 600, AI_STORM, 2, 15, 30, IMMUNE_MAGIC | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_NBLACK, N_("Lionskull the Bent"), "GENERAL", 12, 525, AI_SKELSD, 2, 25, 25, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_COUNSLR, N_("Blacktongue"), "GENERAL", 12, 360, AI_COUNSLR, 3, 15, 30, RESIST_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_DEATHW, N_("Viletouch"), "GENERAL", 12, 525, AI_GARG, 3, 20, 40, IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_RSNAKE, N_("Viperflame"), "GENERAL", 12, 570, AI_SKELSD, 1, 25, 35, IMMUNE_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_BSNAKE, N_("Fangskin"), "BHKA", 14, 681, AI_SKELSD, 2, 15, 50, IMMUNE_MAGIC | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_SUCCUBUS, N_("Witchfire the Unholy"), "GENERAL", 12, 444, AI_SUCC, 3, 10, 20, IMMUNE_MAGIC | IMMUNE_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_BALROG, N_("Blackskull"), "BHKA", 13, 750, AI_SKELSD, 3, 25, 40, IMMUNE_MAGIC | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_UNRAV, N_("Soulslash"), "GENERAL", 12, 450, AI_SKELSD, 0, 25, 25, IMMUNE_MAGIC | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_VTEXLRD, N_("Windspawn"), "GENERAL", 12, 711, AI_SKELSD, 1, 35, 40, IMMUNE_MAGIC | IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_GSNAKE, N_("Lord of the Pit"), "GENERAL", 13, 762, AI_SKELSD, 2, 25, 42, RESIST_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_RTBLACK, N_("Rustweaver"), "GENERAL", 13, 400, AI_SKELSD, 3, 1, 60, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_HOLOWONE, N_("Howlingire the Shade"), "GENERAL", 13, 450, AI_SKELSD, 2, 40, 75, RESIST_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_MAEL, N_("Doomcloud"), "GENERAL", 13, 612, AI_STORM, 1, 1, 60, RESIST_FIRE | IMMUNE_LIGHTNING , UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_PAINMSTR, N_("Bloodmoon Soulfire"), "GENERAL", 13, 684, AI_SKELSD, 1, 15, 40, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_SNOWWICH, N_("Witchmoon"), "GENERAL", 13, 310, AI_SUCC, 3, 30, 40, RESIST_LIGHTNING , UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_VTEXLRD, N_("Gorefeast"), "GENERAL", 13, 771, AI_SKELSD, 3, 20, 55, RESIST_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_RTBLACK, N_("Graywar the Slayer"), "GENERAL", 14, 672, AI_SKELSD, 1, 30, 50, RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_MAGISTR, N_("Dreadjudge"), "GENERAL", 14, 540, AI_COUNSLR, 1, 30, 40, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_HLSPWN, N_("Stareye the Witch"), "GENERAL", 14, 726, AI_SUCC, 2, 30, 50, IMMUNE_FIRE , UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_BTBLACK, N_("Steelskull the Hunter"), "GENERAL", 14, 831, AI_SKELSD, 3, 40, 50, RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_RBLACK, N_("Sir Gorash"), "GENERAL", 16, 1050, AI_SKELSD, 1, 20, 60, IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_CABALIST, N_("The Vizier"), "GENERAL", 15, 850, AI_COUNSLR, 2, 25, 40, IMMUNE_FIRE , UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_REALWEAV, "Zamphir", "GENERAL", 15, 891, AI_SKELSD, 2, 30, 50, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_HLSPWN, N_("Bloodlust"), "GENERAL", 15, 825, AI_SUCC, 1, 20, 55, IMMUNE_MAGIC | IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_HLSPWN, "Webwidow", "GENERAL", 16, 774, AI_SUCC, 1, 20, 50, IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_SOLBRNR, N_("Fleshdancer"), "GENERAL", 16, 999, AI_SUCC, 3, 30, 50, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_NONE }, + { MT_OBLORD, N_("Grimspike"), "GENERAL", 19, 534, AI_SNEAK, 1, 25, 40, IMMUNE_MAGIC | RESIST_FIRE | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, // TRANSLATORS: Unique Monster Block end - { MT_STORML, N_("Doomlock"), "GENERAL", 28, 534, AI_SNEAK, 1, 35, 55, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, 3, 0, 0, TEXT_NONE }, - { MT_INVALID, nullptr, nullptr, 0, 0, AI_INVALID, 0, 0, 0, 0 , 0, 0, 0, TEXT_NONE }, + { MT_STORML, N_("Doomlock"), "GENERAL", 28, 534, AI_SNEAK, 1, 35, 55, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Leashed, 0, 0, TEXT_NONE }, + { MT_INVALID, nullptr, nullptr, 0, 0, AI_INVALID, 0, 0, 0, 0 , UniqueMonsterPack::None, 0, 0, TEXT_NONE }, // clang-format on }; diff --git a/Source/monstdat.h b/Source/monstdat.h index dd384b2b9..fcf3022f9 100644 --- a/Source/monstdat.h +++ b/Source/monstdat.h @@ -263,6 +263,24 @@ enum _monster_availability : uint8_t { MAT_RETAIL, }; +/** + * @brief Defines if and how a group of monsters should be spawned with the unique monster + */ +enum class UniqueMonsterPack { + /** + * @brief Don't spawn a group of monsters with the unique monster + */ + None, + /** + * @brief Spawn a group of monsters that are independent from the unique monster + */ + Independent, + /** + * @brief Spawn a group of monsters that are leashed to the unique monster + */ + Leashed, +}; + struct UniqMonstStruct { _monster_id mtype; const char *mName; @@ -275,9 +293,13 @@ struct UniqMonstStruct { uint8_t mMaxDamage; /** Using monster_resistance as bitflags */ uint16_t mMagicRes; - uint16_t mUnqAttr; // TODO create enum - uint8_t mUnqVar1; - uint8_t mUnqVar2; + /** + * @brief Defines if and how a group of monsters should be spawned with the unique monster + */ + + UniqueMonsterPack monsterPack; + uint8_t customHitpoints; + uint8_t customArmorClass; _speech_id mtalkmsg; }; diff --git a/Source/monster.cpp b/Source/monster.cpp index 031c2ef99..e2197c9f4 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -267,7 +267,7 @@ void InitMonster(MonsterStruct &monster, Direction rd, int mtype, Point position } } -bool MonstPlace(int xp, int yp) +bool CanPlaceMonster(int xp, int yp) { char f; @@ -309,7 +309,7 @@ void PlaceMonster(int i, int mtype, int x, int y) InitMonster(Monsters[i], rd, mtype, { x, y }); } -void PlaceGroup(int mtype, int num, int leaderAttributes, int leaderId) +void PlaceGroup(int mtype, int num, UniqueMonsterPack uniqueMonsterPack, int leaderId) { int placed = 0; @@ -325,7 +325,7 @@ void PlaceGroup(int mtype, int num, int leaderAttributes, int leaderId) int xp; int yp; - if ((leaderAttributes & 1) != 0) { + if (uniqueMonsterPack != UniqueMonsterPack::None) { int offset = GenerateRnd(8); auto position = leader.position.tile + static_cast(offset); xp = position.x; @@ -334,7 +334,7 @@ void PlaceGroup(int mtype, int num, int leaderAttributes, int leaderId) do { xp = GenerateRnd(80) + 16; yp = GenerateRnd(80) + 16; - } while (!MonstPlace(xp, yp)); + } while (!CanPlaceMonster(xp, yp)); } int x1 = xp; int y1 = yp; @@ -345,21 +345,21 @@ void PlaceGroup(int mtype, int num, int leaderAttributes, int leaderId) int j = 0; for (int try2 = 0; j < num && try2 < 100; xp += Displacement::fromDirection(static_cast(GenerateRnd(8))).deltaX, yp += Displacement::fromDirection(static_cast(GenerateRnd(8))).deltaX) { /// BUGFIX: `yp += Point.y` - if (!MonstPlace(xp, yp) + if (!CanPlaceMonster(xp, yp) || (dTransVal[xp][yp] != dTransVal[x1][y1]) - || ((leaderAttributes & 2) != 0 && (abs(xp - x1) >= 4 || abs(yp - y1) >= 4))) { + || (uniqueMonsterPack == UniqueMonsterPack::Leashed && (abs(xp - x1) >= 4 || abs(yp - y1) >= 4))) { try2++; continue; } PlaceMonster(ActiveMonsterCount, mtype, xp, yp); - if ((leaderAttributes & 1) != 0) { + if (uniqueMonsterPack != UniqueMonsterPack::None) { auto &minion = Monsters[ActiveMonsterCount]; minion._mmaxhp *= 2; minion._mhitpoints = minion._mmaxhp; minion._mint = leader._mint; - if ((leaderAttributes & 2) != 0) { + if (uniqueMonsterPack == UniqueMonsterPack::Leashed) { minion.leader = leaderId; minion.leaderRelation = LeaderRelation::Leashed; minion._mAi = leader._mAi; @@ -382,7 +382,7 @@ void PlaceGroup(int mtype, int num, int leaderAttributes, int leaderId) } } - if ((leaderAttributes & 2) != 0) { + if (uniqueMonsterPack == UniqueMonsterPack::Leashed) { leader.packsize = placed; } } @@ -412,7 +412,7 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize) int count2 = 0; for (int x = xp - 3; x < xp + 3; x++) { for (int y = yp - 3; y < yp + 3; y++) { - if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX && MonstPlace(x, y)) { + if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX && CanPlaceMonster(x, y)) { count2++; } } @@ -425,7 +425,7 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize) } } - if (MonstPlace(xp, yp)) { + if (CanPlaceMonster(xp, yp)) { break; } } @@ -576,9 +576,9 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize) monster._uniqtrans = uniquetrans++; - if ((uniqueData.mUnqAttr & 4) != 0) { - monster.mHit = uniqueData.mUnqVar1; - monster.mHit2 = uniqueData.mUnqVar1; + if (uniqueData.customHitpoints != 0) { + monster.mHit = uniqueData.customHitpoints; + monster.mHit2 = uniqueData.customHitpoints; if (sgGameInitInfo.nDifficulty == DIFF_NIGHTMARE) { monster.mHit += NIGHTMARE_TO_HIT_BONUS; @@ -588,8 +588,8 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize) monster.mHit2 += HELL_TO_HIT_BONUS; } } - if ((uniqueData.mUnqAttr & 8) != 0) { - monster.mArmorClass = uniqueData.mUnqVar1; + if (uniqueData.customArmorClass != 0) { + monster.mArmorClass = uniqueData.customArmorClass; if (sgGameInitInfo.nDifficulty == DIFF_NIGHTMARE) { monster.mArmorClass += NIGHTMARE_AC_BONUS; @@ -600,8 +600,8 @@ void PlaceUniqueMonst(int uniqindex, int miniontype, int bosspacksize) ActiveMonsterCount++; - if ((uniqueData.mUnqAttr & 1) != 0) { - PlaceGroup(miniontype, bosspacksize, uniqueData.mUnqAttr, ActiveMonsterCount - 1); + if (uniqueData.monsterPack != UniqueMonsterPack::None) { + PlaceGroup(miniontype, bosspacksize, uniqueData.monsterPack, ActiveMonsterCount - 1); } if (monster._mAi != AI_GARG) { @@ -3987,7 +3987,7 @@ void InitMonsters() na = GenerateRnd(2) + 2; else na = GenerateRnd(3) + 3; - PlaceGroup(mtype, na, 0, 0); + PlaceGroup(mtype, na, UniqueMonsterPack::None, 0); } } for (int i = 0; i < nt; i++) { @@ -4570,7 +4570,7 @@ bool DirOK(int i, Direction mdir) if (monster.leaderRelation == LeaderRelation::Leashed) { return futurePosition.WalkingDistance(Monsters[monster.leader].position.future) < 4; } - if (monster._uniqtype == 0 || (UniqMonst[monster._uniqtype - 1].mUnqAttr & 2) == 0) + if (monster._uniqtype == 0 || UniqMonst[monster._uniqtype - 1].monsterPack == UniqueMonsterPack::Leashed) return true; int mcount = 0; for (int x = futurePosition.x - 3; x <= futurePosition.x + 3; x++) {