diff options
author | j-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573> | 2009-01-04 20:50:21 +0000 |
---|---|---|
committer | j-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573> | 2009-01-04 20:50:21 +0000 |
commit | e828bafa67e06c97dad7b9fcf2851e6ab5b00f28 (patch) | |
tree | 77fbcd20c3485501851302796dfa70640a5e2c90 /crawl-ref/source | |
parent | 07828b78525d85498811687311f0a9cff5901e03 (diff) | |
download | crawl-ref-e828bafa67e06c97dad7b9fcf2851e6ab5b00f28.tar.gz crawl-ref-e828bafa67e06c97dad7b9fcf2851e6ab5b00f28.zip |
Introduce a number of new uniques taken from a patch by castamir.
These are:
* Roxanne (statue spellcaster)
* Sonja (Kobold assassin)
* Eustachio (human summoner, was: Francisco)
* Azrael (efreet, was: Abdul)
* Ilsuiw (Merfolk witch
* Prince Ribbit (blink frog prince)
* Nergalle (orc sorceress)
* Saint Roka (orc priest of Beogh)
Tweaked make_book_theme_randart() to allow for one forced spell and
owner's name. Used to occasionally give Roxanne a randart book containing
Statue Form. (Was: always book of earth)
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8207 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r-- | crawl-ref/source/dat/database/monspeak.txt | 335 | ||||
-rw-r--r-- | crawl-ref/source/dat/descript/monsters.txt | 40 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 42 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 112 | ||||
-rw-r--r-- | crawl-ref/source/fight.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/makeitem.cc | 91 | ||||
-rw-r--r-- | crawl-ref/source/mon-data.h | 317 | ||||
-rw-r--r-- | crawl-ref/source/mon-spll.h | 267 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 14 | ||||
-rw-r--r-- | crawl-ref/source/monplace.cc | 37 | ||||
-rw-r--r-- | crawl-ref/source/monplace.h | 4 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/mstuff2.cc | 15 | ||||
-rw-r--r-- | crawl-ref/source/place.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/randart.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/spells4.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/spl-book.cc | 78 | ||||
-rw-r--r-- | crawl-ref/source/spl-book.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/spl-data.h | 13 |
19 files changed, 1059 insertions, 327 deletions
diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt index f7fdda77e8..59bbaed4f1 100644 --- a/crawl-ref/source/dat/database/monspeak.txt +++ b/crawl-ref/source/dat/database/monspeak.txt @@ -1078,6 +1078,41 @@ _Agnes_rare_ ## END Agnes ## %%%% +# efreet +Azrael + +@_Azrael_common_@ + +w:2 +@_Azrael_rare_@ +%%%% +adj_flammable + +flammable + +inflammable +%%%% +_Azrael_common_ + +@The_monster@ laughs insanely. + +@The_monster@ howls in rage. + +@The_monster@ screams, "No! No! YES! No!" + +@The_monster@ screams, "Burn! Burn! All of it must BURN!" + +VISUAL:@The_monster@ blows smoke rings. +%%%% +_Azrael_rare_ + +@The_monster@ grins and asks, "Are you @adj_flammable@?" + +@The_monster@ says, "We're having tasty @player_genus@ kabobs tonight!" + +VISUAL:@The_monster@ whirls about in circles. +## END Azrael ## +%%%% # In case Blork ends up polymorphed. Blork @@ -1326,6 +1361,38 @@ _Erolcha_rare_ @The_monster@ screams, "Erolcha angry!" ## END Erolcha ## %%%% +# apprentice summoner, has funny ideas about honour +Eustachio + +@_Eustachio_common_@ + +w:5 +@_Eustachio_rare_@ +%%%% +_Eustachio_common_ + +@The_monster@ screams, "At last I'll have my revenge!" + +@The_monster@ screams, "Hey, you killed my favorite bat!" + +@The_monster@ says, "Summoning is fun!" + +@The_monster@ says, "My allies will avenge me." +%%%% +_Eustachio_rare_ + +@The_monster@ yells, "Perjured traitor, DIE!" + +VISUAL:@The_monster@ twirls his moustache. + +# doesn't really work if there are no summons nearby +#VISUAL:@The_monster@ strokes his familiar. + +SPELL:@The_monster@ calls on the powers of Hell! + +@The_monster@ brags, "I can call spirits from the vastly deeps." +## END Eustachio ## +%%%% # A mercenary guarding the dungeon Frances @@ -1472,6 +1539,53 @@ _Harold_rare_ @The_monster@ says, "Mine is not to reason why. Mine's to do, yours to die." ## END Harold ## %%%% +# a pretty merfolk witch +Ilsuiw + +@_Ilsuiw_common_@ + +w:5 +@_Ilsuiw_rare_@ +%%%% +_Ilsuiw_common_ + +@The_monster@ asks, "Won't you come swim with me?" + +@The_monster@ whispers, "Come on in, the water's fine." + +@The_monster@ sings a @strange_or_haunting@ @chanty@. + +VISUAL:@The_monster@ runs @possessive@ fingers through @possessive@ long green hair. +%%%% +_Ilsuiw_rare_ + +VISUAL:@The_monster@ gazes at you @hypnot_or_seductively@. + +@The_monster@ sings, "To sleep, to sleep ... mayhap to drown." + +@The_monster@ says, "It's lovely beneath the waves -- you'll see!" + +@The_monster@ asks, "Do you dare to walk upon the beach?" +%%%% +hypnot_or_seductively + +hypnotically + +seductively +%%%% +strange_or_haunting + +strange + +haunting +%%%% +chanty + +sea-chanty + +melody +## END Ilsuiw ## +%%%% # A sorceress disturbed by player Jessica @@ -1822,6 +1936,32 @@ VISUAL:@The_monster@ seems to say something. VISUAL:@The_monster@ says something you can't hear. It was probably not a compliment. ## END silenced Murray ## %%%% +# ugly orc sorceress +Nergalle + +@_Nergalle_common_@ + +@_Nergalle_rare_@ +%%%% +_Nergalle_common_ + +VISUAL:@The_monster@ grimaces horribly. + +@The_monster@ mutters something to herself. + +@The_monster@ asks, "There's a tasty morsel, hm?" +%%%% +_Nergalle_rare_ + +@The_monster@ yells, "What are YOU looking at?" + +@The_monster@ shouts, "Kill, kill, my pretties!" + +@The_monster@ says, "THAT's why. How awful. You!" + +@The_monster@ blows @possessive@ nose. +## END Nergalle ## +%%%% # A skilled warrior looking for some fame. More kills = more fame. Norbert @@ -1967,6 +2107,42 @@ VISUAL:@The_monster@ looks around for something heavy to throw at you. @The_monster@ says, "@player_genus@ for dinner? Sounds delicious!" ## END Polyphemus ## %%%% +Prince Ribbit + +@_Prince_Ribbit_common_@ + +w:2 +@_Prince_Ribbit_rare_@ +%%%% +_Prince_Ribbit_common_ + +@The_monster@ croaks regally. + +@The_monster@ lets out a mournful croak. + +VISUAL:@The_monster@ hops awkwardly around. + +VISUAL:@The_monster@ catches a @_frog_food_@ with @possessive@ tongue. +%%%% +_Prince_Ribbit_rare_ + +@The_monster@ asks, "Just a little smooch?" + +@The_monster@ sighs, "It's not easy being green!" + +@The_monster@ says, "You're just another fly to me." +%%%% +_frog_food_ + +fly + +w:5 +bug + +w:1 +small bird +## END Prince Ribbit ## +%%%% # An insane sorceress Psyche @@ -2058,6 +2234,95 @@ _Rupert_rare_ @The_monster@ screams, "Red! No, blue!" ## END Rupert ## %%%% +# a sapphire statue of an earth mage +Roxanne + +@_Roxanne_common_@ + +w:5 +@_Roxanne_medium_@ + +w:1 +@_Roxanne_rare_@ +%%%% +_Roxanne_common_ + +@The_monster@ says, "Come a little closer, will you?" + +@The_monster@ mutters, "When I said I wanted to live forever... this was not what I had in mind." + +@The_monster@ says, "At least I didn't end up somewhere with nobody to talk to." + +@The_monster@ wails, "NOOOO!" + +w:20 +__NONE +%%%% +_Roxanne_medium_ + +@The_monster@ asks, "Could you be a darling and pick up those spellbooks for me?" + +@The_monster@ asks, "Say, could you scratch my back for me?" + +@The_monster@ sighs and says, "It wouldn't be so bad were it not for the bird droppings." +%%%% +_Roxanne_rare_ + +@The_monster@ shouts, "I'd kick your ass right now if I could just get over there!" + +@The_monster@ prays for a Stone to Flesh spell. + +@The_monster@ wonders, "Maybe oil would work? Probably not." + +@The_monster@ says, "They said I was crazy for my new spells... Turns out they were right." +## END Roxanne ## +%%%% +# orc warlord +# Only used if the player is not a Hill Orc. +Saint Roka + +w:7 +@related Saint Roka@ + +@The_monster@ says, "Down here, you're an orc or you're nobody." + +@The_monster@ says, "In the orcish mines, orcs kill the likes of you." +%%%% +related Saint Roka + +w:2 +@_generic_orc_speech_@ + +@The_monster@ calls out, "Orcs! Behind me!" + +@The_monster@ calls out, "Only Beogh rules here!" + +@The_monster@ says, "I shall smite you and smash you." + +@The_monster@ lets out a mighty cry! + +@The_monster@ cries, "Beogh give me strength!" + +@The_monster@ cries, "In the name of Beogh, DIE!" + +@The_monster@ calls out, "Join me or die!" +%%%% +# need different speech if you also worship Beogh +related beogh Saint Roka + +@related Saint Roka@ + +w:20 +@_hostile_orc_beogh_believer_common_@ + +w:5 +@_hostile_orc_beogh_believer_rare_@ + +w:1 +@The_monster@ shouts, "There can only be one messiah: ME!" + +## END Saint Roka ## +%%%% # Mad old wizard Sigmund @@ -2106,6 +2371,39 @@ VISUAL:@The_monster@ tries to bite you. @The_monster@ whispers, "You'll know eternity soon." ## END Sigmund ## %%%% +# female kobold assassin +Sonja + +@_Sonja_common_@ + +w:5 +@_Sonja_rare_@ +%%%% +_Sonja_common_ + +@The_monster@ says, "I'm academy-trained, you know." + +@The_monster@ shouts, "Too slow!" + +VISUAL:@The_monster@ twirls her cape. + +VISUAL:@The_monster@ bows elegantly. + +VISUAL:@The_monster@ plants her feet in a plie. +%%%% +_Sonja_rare_ + +@The_monster@ shouts, "Hah! Missed me again!" + +@The_monster@ says, "The Royal Ballet doesn't accept kobolds. That's why I went into killing people." + +@The_monster@ says, "If only old Madame Brzewit could see me now!" + +@The_monster@ shouts, "Some dancing partner you are!" + +@The_monster@ says, "Someone hired me to kill you, but I'm not supposed to say who." +## END Sonja ## +%%%% # A fighter who likes to kill Terence @@ -2681,14 +2979,14 @@ _hostile_beogh_speech_ w:4 @_hostile_beogh_speech_rare_@ %%%% -_hostile_beogh_speech_common_ +_hostile__orc_beogh_unbeliever_common_ -# unbelievers @The_monster@ @orc_says@, "I don't believe in Beogh!" @The_monster@ @shouts@, "You're not the messiah, I am!" +%%%% +_hostile_orc_beogh_believer_common_ -# orcs doubting you @The_monster@ mutters, "You're NOT the saviour of the Orcs." @The_monster@ grumbles, "You're not even a proper Orc..." @@ -2713,20 +3011,20 @@ _hostile_beogh_speech_common_ VISUAL:@The_monster@ grimaces. %%%% -_hostile_beogh_speech_rare_ +_hostile_orc_beogh_unbeliever_rare_ -# unbelievers @The_monster@ @orc_says@, "Orcs don't need Beogh!" @The_monster@ @orc_says@, "Beogh's messiah is just a fairy-tale." -# orcs doubting you +@The_monster@ says, "Even if there was a messiah, it wouldn't be you." +%%%% +_hostile_orc_beogh_believer_rare_ + @The_monster@ laughs, "You, our saviour!?" @The_monster@ @shouts@, "Orcs! @player_name@ is lying!" -@The_monster@ says, "Even if there was a messiah, it wouldn't be you." - @The_monster@ @orc_says@, "For a messiah, you look rather @orc_pathetic@." @The_monster@ @orc_says@, "Your @costumes_or_trick@ cannot @fool_or_deceive@ me." @@ -2736,6 +3034,27 @@ _hostile_beogh_speech_rare_ VISUAL:@The_monster@ shakes @possessive@ head. VISUAL:@The_monster@ stares at you quizzically. +%%%% +_hostile_beogh_speech_common_ + +# unbelievers +w:1 +@_hostile_orc_beogh_unbeliever_common_@ + +# orcs doubting you +w:6 +@_hostile_orc_beogh_believer_common_@ +%%%% +_hostile_beogh_speech_rare_ + +# unbelievers +w:3 +@_hostile_orc_beogh_unbeliever_rare_@ + +# orcs doubting you +w:7 +@_hostile_orc_beogh_believer_rare_@ + ################################################### # Orcish followers of Beogh's messiah ################################################### diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt index da7a332d21..35ff550b87 100644 --- a/crawl-ref/source/dat/descript/monsters.txt +++ b/crawl-ref/source/dat/descript/monsters.txt @@ -24,6 +24,10 @@ Asmodeus One of the arch-demons who dwell in the depths of Hell. %%%% +Azrael + +A powerful, belligerent Efreet. (Is there any other kind?) +%%%% Balrug A huge and very powerful demon, wreathed in fire and shadows. @@ -86,6 +90,11 @@ Erolcha An especially cunning ogre mage. %%%% +Eustachio + +An apprentice summoner with a flowing moustache. He has funny ideas about +honour. +%%%% Executioner A horribly powerful demon. @@ -141,6 +150,10 @@ Ijyb A small and twisted goblin, wearing some ugly blue rags. %%%% +Ilsuiw + +A cunning merfolk water-witch, who uses her beauty and spellcraft to draw unwitting adventurers to their death. +%%%% Jessica An evil apprentice sorceress. @@ -193,6 +206,10 @@ Murray A demonic skull rolling along the dungeon floor. %%%% +Nergalle + +A withered sorceress, exceptionally ugly even by orc standards. +%%%% Norbert A skilled warrior. @@ -214,16 +231,30 @@ Pit Fiend A huge winged fiend with incredibly tough skin. %%%% Polyphemus + +A cyclops shepherd, he is very protective of his charges. +%%%% +Prince Ribbit + +A handsome prince before he was cursed, now adventures for a cure. %%%% Psyche -A fair-haired mage, wandering and seemingly half-mad -with grief and guilt. +A fair-haired mage, wandering and seemingly half-mad with grief and guilt. +%%%% +Roxanne + +A beautiful sapphire statue of a famous earth mage who disappeared after a +catastrophic spell failure. %%%% Rupert An evil crusader. %%%% +Saint Roka + +A mighty warlord. Some orcs even say he is the Chosen One of Beogh. +%%%% Serpent of Hell A huge red glowing dragon, burning with hellfire. @@ -251,6 +282,11 @@ Snorg A hairy troll, angry and mean. %%%% +Sonja + +A graceful kobold assassin. Admire her graceful pirouettes, thrill at her +daring leaps! But watch out for her knives! +%%%% Terence An evil human fighter. diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index aae4d56d59..09d02f83fa 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -3222,8 +3222,8 @@ static bool _make_room(int sx,int sy,int ex,int ey,int max_doors, int doorlevel) return (true); } -// Doesn't include Polyphemus (only appears in the Shoals), Murray (Hell), -// or Tiamat (Zot). +// Doesn't include Polyphemus or Ilsuiw (only appear in the Shoals), +// Murray (Hell), or Tiamat (Zot). static monster_type _choose_unique_by_depth(int step) { int ret; @@ -3239,29 +3239,32 @@ static monster_type _choose_unique_by_depth(int step) break; case 2: // depth <= 9 ret = random_choose(MONS_BLORK_THE_ORC, MONS_EDMUND, MONS_PSYCHE, - MONS_EROLCHA, -1); + MONS_EROLCHA, MONS_PRINCE_RIBBIT, -1); break; case 3: // depth <= 13 ret = random_choose(MONS_PSYCHE, MONS_EROLCHA, MONS_DONALD, MONS_URUG, - MONS_MICHAEL, -1); + MONS_MICHAEL, MONS_PRINCE_RIBBIT, -1); break; case 4: // depth <= 16 ret = random_choose(MONS_URUG, MONS_MICHAEL, MONS_JOSEPH, MONS_SNORG, MONS_ERICA, MONS_JOSEPHINE, MONS_HAROLD, - MONS_NORBERT, MONS_JOZEF, -1); + MONS_NORBERT, MONS_JOZEF, MONS_AZRAEL, + MONS_EUSTACHIO, MONS_SONJA, -1); break; case 5: // depth <= 19 ret = random_choose(MONS_SNORG, MONS_ERICA, MONS_JOSEPHINE, MONS_HAROLD, MONS_NORBERT, MONS_JOZEF, MONS_AGNES, MONS_MAUD, MONS_LOUISE, MONS_FRANCIS, MONS_FRANCES, - -1); + MONS_AZRAEL, MONS_EUSTACHIO, MONS_NERGALLE, + MONS_SONJA, -1); break; case 6: // depth > 19 default: ret = random_choose(MONS_LOUISE, MONS_FRANCIS, MONS_FRANCES, MONS_RUPERT, MONS_WAYNE, MONS_DUANE, MONS_XTAHUA, MONS_NORRIS, MONS_FREDERICK, MONS_MARGERY, - MONS_BORIS, -1); + MONS_BORIS, MONS_ROXANNE, MONS_NERGALLE, + MONS_SAINT_ROKA, -1); } return static_cast<monster_type>(ret); @@ -3281,16 +3284,22 @@ static monster_type _pick_unique(int lev) // If applicable, replace it with one of the uniques appearing // only in some branches. - if (player_in_branch(BRANCH_VESTIBULE_OF_HELL) && one_chance_in(7)) - which_unique = MONS_MURRAY; - - if (player_in_branch(BRANCH_HALL_OF_ZOT) && one_chance_in(3)) - which_unique = MONS_TIAMAT; - - if (player_in_branch(BRANCH_SHOALS) && player_branch_depth() > 1 - && coinflip()) + if (player_in_branch(BRANCH_VESTIBULE_OF_HELL)) + { + if (one_chance_in(7)) + which_unique = MONS_MURRAY; + } + else if (player_in_branch(BRANCH_HALL_OF_ZOT)) { - which_unique = MONS_POLYPHEMUS; + if (one_chance_in(3)) + which_unique = MONS_TIAMAT; + } + else if (player_in_branch(BRANCH_SHOALS)) + { + if (player_branch_depth() > 1 && coinflip()) + which_unique = MONS_POLYPHEMUS; + else if (player_branch_depth() > 2 && coinflip()) + which_unique = MONS_ILSUIW; } return static_cast<monster_type>(which_unique); @@ -3349,6 +3358,7 @@ static int _place_uniques(int level_number, char level_type) ++num_placed; } } + return num_placed; } diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index c4f0e87a38..478ee41c13 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -1563,12 +1563,12 @@ enum menu_type enum mon_holy_type { - MH_HOLY, // 0 - was -1 - MH_NATURAL, // 1 - was 0 - MH_UNDEAD, // 2 - was 1 - MH_DEMONIC, // 3 - was 2 - MH_NONLIVING, // golems and other constructs - MH_PLANT // plants + MH_HOLY, // 0 + MH_NATURAL, // 1 + MH_UNDEAD, // 2 + MH_DEMONIC, // 3 + MH_NONLIVING, // 4, golems and other constructs + MH_PLANT // 5, plants }; enum targ_mode_type @@ -1579,7 +1579,7 @@ enum targ_mode_type TARG_NUM_MODES }; -// note this order is very sensitive... look at mons_is_unique() +// NOTE: Changing this order will break saves! enum monster_type // (int) menv[].type { MONS_GIANT_ANT, // 0 @@ -1910,7 +1910,7 @@ enum monster_type // (int) menv[].type MONS_DEEP_ELF_BLADEMASTER, // 330 MONS_DEEP_ELF_MASTER_ARCHER, - // The Lords of Hell: + // The Lords of Hell (also unique): MONS_GERYON = 340, // 340 MONS_DISPATER, MONS_ASMODEUS, @@ -1992,6 +1992,16 @@ enum monster_type // (int) menv[].type MONS_SILVER_STATUE, MONS_ICE_STATUE, + // Third batch of uniques + MONS_ROXANNE = 450, // -- statue, too! + MONS_SONJA, + MONS_EUSTACHIO, + MONS_AZRAEL, + MONS_ILSUIW, + MONS_PRINCE_RIBBIT, // 455 + MONS_NERGALLE, + MONS_SAINT_ROKA, + // Testing monsters MONS_TEST_SPAWNER, @@ -2123,87 +2133,94 @@ enum mon_spellbook_type MST_BRAIN_WORM, MST_GIANT_ORANGE_BRAIN, MST_RAKSHASA, - MST_GREAT_ORB_OF_EYES, // 55 + MST_GREAT_ORB_OF_EYES, // 55 MST_ORC_SORCERER, MST_STEAM_DRAGON, - MST_HELL_KNIGHT_I, + MST_HELL_KNIGHT_I = 60, MST_HELL_KNIGHT_II, - MST_NECROMANCER_I, // 60 + MST_NECROMANCER_I = 65, MST_NECROMANCER_II, - MST_WIZARD_I, + MST_WIZARD_I = 70, MST_WIZARD_II, MST_WIZARD_III, - MST_WIZARD_IV, // 65 + MST_WIZARD_IV, MST_WIZARD_V, - MST_ORC_PRIEST, + MST_ORC_PRIEST = 80, MST_ORC_HIGH_PRIEST, MST_MOTTLED_DRAGON, - MST_ICE_FIEND, // 70 + MST_ICE_FIEND, MST_SHADOW_FIEND, - MST_TORMENTOR, + MST_TORMENTOR, // 85 MST_STORM_DRAGON, MST_WHITE_IMP, - MST_YNOXINUL, // 75 + MST_YNOXINUL, MST_NEQOXEC, - MST_HELLWING, + MST_HELLWING, // 90 MST_SMOKE_DEMON, MST_CACODEMON, - MST_GREEN_DEATH, // 80 + MST_GREEN_DEATH, MST_BALRUG, - MST_BLUE_DEATH, - MST_GERYON, - MST_DISPATER, - MST_ASMODEUS, // 85 - MST_ERESHKIGAL, - MST_ANTAEUS, // 87 - MST_MNOLEG = 90, - MST_LOM_LOBON, - MST_CEREBOV, - MST_GLOORX_VLOQ, + MST_BLUE_DEATH, // 95 MST_TITAN, - MST_GOLDEN_DRAGON, // 95 + MST_GOLDEN_DRAGON, MST_DEEP_ELF_SUMMONER, MST_DEEP_ELF_CONJURER_I, - MST_DEEP_ELF_CONJURER_II, + MST_DEEP_ELF_CONJURER_II, // 100 MST_DEEP_ELF_PRIEST, - MST_DEEP_ELF_HIGH_PRIEST, // 100 + MST_DEEP_ELF_HIGH_PRIEST, MST_DEEP_ELF_DEMONOLOGIST, MST_DEEP_ELF_ANNIHILATOR, - MST_DEEP_ELF_SORCERER, + MST_DEEP_ELF_SORCERER, // 105 MST_DEEP_ELF_DEATH_MAGE, - MST_KOBOLD_DEMONOLOGIST, // 105 + MST_KOBOLD_DEMONOLOGIST, MST_NAGA, MST_NAGA_MAGE, - MST_CURSE_SKULL, + MST_CURSE_SKULL, // 110 MST_SHINING_EYE, - MST_FROST_GIANT, // 110 + MST_FROST_GIANT, MST_ANGEL, MST_DAEVA, - MST_SHADOW_DRAGON, + MST_SHADOW_DRAGON, // 115 MST_SPHINX, - MST_MUMMY, // 115 + MST_MUMMY, MST_ELECTRIC_GOLEM, MST_ORB_OF_FIRE, - MST_SHADOW_IMP, + MST_SHADOW_IMP, // 120 MST_GHOST, - MST_HELL_HOG, // 120 + MST_HELL_HOG, MST_SWAMP_DRAGON, MST_SWAMP_DRAKE, - MST_SERPENT_OF_HELL, + MST_SERPENT_OF_HELL, // 125 MST_BOGGART, - MST_EYE_OF_DEVASTATION, // 125 + MST_EYE_OF_DEVASTATION, MST_QUICKSILVER_DRAGON, MST_IRON_DRAGON, - MST_SKELETAL_WARRIOR, + MST_SKELETAL_WARRIOR, // 130 MST_MYSTIC, - MST_DEATH_DRAKE, // 130 + MST_DEATH_DRAKE, MST_DRAC_SCORCHER, // As Bioster would say.. pig*s MST_DRAC_CALLER, - MST_DRAC_SHIFTER, + MST_DRAC_SHIFTER, // 135 MST_CURSE_TOE, - MST_RUPERT, // 135 MST_ICE_STATUE, - MST_TEST_SPAWNER, + // unique monsters' "spellbooks" + MST_RUPERT = 140, + MST_ROXANNE, + MST_SONJA, + MST_EUSTACHIO, + MST_ILSUIW, + MST_PRINCE_RIBBIT, + MST_GERYON = 150, + MST_DISPATER, + MST_ASMODEUS, + MST_ERESHKIGAL, + MST_ANTAEUS, + MST_MNOLEG = 160, + MST_LOM_LOBON, + MST_CEREBOV, + MST_GLOORX_VLOQ, + + MST_TEST_SPAWNER = 170, NUM_MSTYPES, MST_NO_SPELLS = 250 }; @@ -2811,6 +2828,7 @@ enum spell_type SPELL_FIRE_BREATH, SPELL_COLD_BREATH, SPELL_DRACONIAN_BREATH, + SPELL_WATER_ELEMENTALS, NUM_SPELLS }; diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index db65503add..fd59197c1c 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -2079,7 +2079,8 @@ bool melee_attack::distortion_affects_defender() //jmf: blink frogs *like* distortion // I think could be amended to let blink frogs "grow" like // jellies do {dlb} - if (defender->id() == MONS_BLINK_FROG) + if (defender->id() == MONS_BLINK_FROG + || defender->id() == MONS_PRINCE_RIBBIT) { if (one_chance_in(5)) { diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index 9f93c38301..15908d2f89 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -2639,7 +2639,7 @@ static void _generate_misc_item(item_def& item, int force_type, int item_race) (item.sub_type == MISC_RUNE_OF_ZOT || item.sub_type == MISC_HORN_OF_GERYON || item.sub_type == MISC_DECK_OF_PUNISHMENT - // pure decks are rare in the dungeon + // Pure decks are rare in the dungeon. || (item.sub_type == MISC_DECK_OF_ESCAPE || item.sub_type == MISC_DECK_OF_DESTRUCTION || item.sub_type == MISC_DECK_OF_DUNGEONS @@ -2931,17 +2931,33 @@ static void _give_monster_item(monsters *mon, int thing, static void _give_scroll(monsters *mon, int level) { - //mv - give scroll - if (mons_is_unique( mon->type ) && one_chance_in(3)) + int thing_created = NON_ITEM; + + if (mon->type == MONS_ROXANNE) { - const int thing_created = - items(0, OBJ_SCROLLS, OBJ_RANDOM, true, level, 0); - if (thing_created == NON_ITEM) - return; + // Not a scroll, but this comes closest. + int which_book = (one_chance_in(3) ? BOOK_TRANSFIGURATIONS + : BOOK_EARTH); - mitm[thing_created].flags = 0; - _give_monster_item(mon, thing_created); + thing_created = items(0, OBJ_BOOKS, which_book, true, level, 0); + + if (thing_created != NON_ITEM && coinflip()) + { + // Give Roxanne a random book containing Statue Form instead. + item_def &item(mitm[thing_created]); + make_book_Roxanne_special(&item); + _give_monster_item(mon, thing_created, true); + return; + } } + else if (mons_is_unique( mon->type ) && one_chance_in(3)) + thing_created = items(0, OBJ_SCROLLS, OBJ_RANDOM, true, level, 0); + + if (thing_created == NON_ITEM) + return; + + mitm[thing_created].flags = 0; + _give_monster_item(mon, thing_created, true); } static void _give_wand(monsters *mon, int level) @@ -2954,16 +2970,16 @@ static void _give_wand(monsters *mon, int level) if (thing_created == NON_ITEM) return; - // don't give top-tier wands before 5 HD - if ( mon->hit_dice < 5 ) + // Don't give top-tier wands before 5 HD. + if (mon->hit_dice < 5) { - // technically these wands will be undercharged, but it + // Technically these wands will be undercharged, but it // doesn't really matter - if ( mitm[thing_created].sub_type == WAND_FIRE ) + if (mitm[thing_created].sub_type == WAND_FIRE) mitm[thing_created].sub_type = WAND_FLAME; - if ( mitm[thing_created].sub_type == WAND_COLD ) + if (mitm[thing_created].sub_type == WAND_COLD) mitm[thing_created].sub_type = WAND_FROST; - if ( mitm[thing_created].sub_type == WAND_LIGHTNING ) + if (mitm[thing_created].sub_type == WAND_LIGHTNING) { mitm[thing_created].sub_type = (coinflip() ? WAND_FLAME : WAND_FROST); @@ -3279,6 +3295,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, break; } case MONS_ORC_WARLORD: + case MONS_SAINT_ROKA: // being at the top has its privileges if (one_chance_in(3)) level = MAKE_GOOD_ITEM; @@ -3422,6 +3439,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, case MONS_EFREET: case MONS_ERICA: + case MONS_AZRAEL: force_item = true; item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_WEAPONS; @@ -3543,6 +3561,7 @@ static item_make_species_type _give_weapon(monsters *mon, int level, case MONS_ORC_WIZARD: case MONS_ORC_SORCERER: + case MONS_NERGALLE: item_race = MAKE_ITEM_ORCISH; // deliberate fall-through, I guess {dlb} case MONS_KOBOLD_DEMONOLOGIST: @@ -3562,6 +3581,36 @@ static item_make_species_type _give_weapon(monsters *mon, int level, level = MAKE_GOOD_ITEM; break; + case MONS_SONJA: + if (!melee_only) + { + item.base_type = OBJ_WEAPONS; + item.sub_type = WPN_BLOWGUN; + item_race = MAKE_ITEM_NO_RACE; + break; + } + force_item = true; + item_race = MAKE_ITEM_NO_RACE; + item.base_type = OBJ_WEAPONS; + item.sub_type = coinflip()? WPN_DAGGER : WPN_SHORT_SWORD; + { + const int temp_rand = random2(5); + set_item_ego_type( item, OBJ_WEAPONS, + ((temp_rand == 0) ? SPWPN_VENOM : + (temp_rand == 1) ? SPWPN_DRAINING : + (temp_rand == 2) ? SPWPN_VAMPIRICISM : + (temp_rand == 3) ? SPWPN_DISTORTION + : SPWPN_NORMAL) ); + } + break; + + case MONS_EUSTACHIO: + item_race = MAKE_ITEM_NO_RACE; + item.base_type = OBJ_WEAPONS; + item.sub_type = (one_chance_in(3) ? WPN_FALCHION + : WPN_SABRE); + break; + case MONS_CEREBOV: force_item = true; make_item_fixed_artefact( item, false, SPWPN_SWORD_OF_CEREBOV ); @@ -4011,6 +4060,7 @@ void give_armour(monsters *mon, int level) break; case MONS_ORC_WARLORD: + case MONS_SAINT_ROKA: // being at the top has its privileges if (one_chance_in(3)) level = MAKE_GOOD_ITEM; @@ -4101,6 +4151,7 @@ void give_armour(monsters *mon, int level) case MONS_DRACONIAN_ZEALOT: case MONS_DRACONIAN_KNIGHT: case MONS_WIZARD: + case MONS_ILSUIW: item_race = MAKE_ITEM_NO_RACE; mitm[bp].base_type = OBJ_ARMOUR; mitm[bp].sub_type = ARM_ROBE; @@ -4114,6 +4165,7 @@ void give_armour(monsters *mon, int level) case MONS_ORC_WIZARD: case MONS_BLORK_THE_ORC: + case MONS_NERGALLE: item_race = MAKE_ITEM_ORCISH; mitm[bp].base_type = OBJ_ARMOUR; mitm[bp].sub_type = ARM_ROBE; @@ -4132,6 +4184,12 @@ void give_armour(monsters *mon, int level) force_colour = DARKGREY; //mv: always darkgrey break; + case MONS_EUSTACHIO: + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_ARMOUR; + mitm[bp].sub_type = ARM_LEATHER_ARMOUR; + break; + default: return; } @@ -4159,8 +4217,7 @@ void give_armour(monsters *mon, int level) mitm[thing_created].colour = force_colour; } -void give_item(int mid, int level_number, - bool mons_summoned) //mv: cleanup+minor changes +void give_item(int mid, int level_number, bool mons_summoned) { monsters *mons = &menv[mid]; diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index 3da1ff608a..35c1d2edb8 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -3879,7 +3879,7 @@ static monsterentry mondata[] = { // non-human uniques { MONS_IJYB, 'g', BLUE, "Ijyb", - M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, + M_UNIQUE | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 5, MONS_GOBLIN, MONS_GOBLIN, MH_NATURAL, -3, { {AT_HIT, AF_PLAIN, 4}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -3889,55 +3889,8 @@ static monsterentry mondata[] = { }, { - MONS_BLORK_THE_ORC, 'o', BROWN, "Blork the orc", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE, - MR_NO_FLAGS, - 0, 15, MONS_ORC, MONS_ORC, MH_NATURAL, -4, - { {AT_HIT, AF_PLAIN, 7}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, - { 3, 0, 0, 32 }, - 0, 9, MST_ORC_WIZARD_III, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, - HT_LAND, 8, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM -}, - -{ - MONS_URUG, 'o', RED, "Urug", - M_FIGHTER | M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, - MR_NO_FLAGS, - 0, 20, MONS_ORC, MONS_ORC, MH_NATURAL, -5, - { {AT_HIT, AF_PLAIN, 12}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, - { 6, 0, 0, 66 }, - 0, 11, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, - HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM -}, - -{ - MONS_EROLCHA, 'O', LIGHTBLUE, "Erolcha", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD - | M_SPEAKS | M_EVIL | M_UNIQUE, - MR_NO_FLAGS, - 0, 20, MONS_OGRE, MONS_OGRE, MH_NATURAL, -7, - { {AT_HIT, AF_PLAIN, 20}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, - { 6, 0, 0, 54 }, - 3, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, - HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_LARGE -}, - -{ - // Snorg can go berserk. - MONS_SNORG, 'T', GREEN, "Snorg", - M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, - MR_NO_FLAGS, - 0, 25, MONS_TROLL, MONS_TROLL, MH_NATURAL, -6, - { {AT_BITE, AF_PLAIN, 20}, {AT_CLAW, AF_PLAIN, 15}, - {AT_CLAW, AF_PLAIN, 15}, AT_NO_ATK }, - { 8, 0, 0, 96 }, - 0, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, - HT_LAND, 10, DEFAULT_ENERGY, MONUSE_OPEN_DOORS, SIZE_LARGE -}, - -{ MONS_POLYPHEMUS, 'C', GREEN, "Polyphemus", - M_WARM_BLOOD | M_UNIQUE | M_SPEAKS, + M_UNIQUE | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 2500, 10, MONS_HILL_GIANT, MONS_CYCLOPS, MH_NATURAL, -3, { {AT_HIT, AF_PLAIN, 35}, {AT_HIT, AF_PLAIN, 30}, AT_NO_ATK, AT_NO_ATK }, @@ -3949,7 +3902,7 @@ static monsterentry mondata[] = { // Antaeus is now demonic so that he'll resist torment. -- bwr { MONS_ANTAEUS, 'C', LIGHTCYAN, "Antaeus", - M_FIGHTER | M_SPELLCASTER | M_EVIL | M_SPEAKS | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_SPELLCASTER | M_EVIL | M_SPEAKS, MR_RES_ELEC | MR_VUL_FIRE | mrd(MR_RES_COLD, 2), 0, 15, MONS_HILL_GIANT, MONS_ANTAEUS, MH_DEMONIC, -9, { {AT_HIT, AF_COLD, 75}, {AT_HIT, AF_COLD, 30}, AT_NO_ATK, AT_NO_ATK }, @@ -3959,8 +3912,20 @@ static monsterentry mondata[] = { }, { + MONS_TIAMAT, 'd', MAGENTA, "Tiamat", + M_UNIQUE | M_SEE_INVIS | M_FLIES | M_COLD_BLOOD | M_SPEAKS, + MR_RES_POISON, + 0, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -5, + { {AT_HIT, AF_PLAIN, 65}, {AT_TAIL_SLAP, AF_PLAIN, 45}, + AT_NO_ATK, AT_NO_ATK }, + { 22, 0, 0, 380 }, + 25, 10, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_ROAR, I_HIGH, + HT_LAND, 10, DEFAULT_ENERGY, MONUSE_STARTING_EQUIPMENT, SIZE_MEDIUM +}, + +{ MONS_XTAHUA, 'D', RED, "Xtahua", - M_SEE_INVIS | M_FLIES | M_SPECIAL_ABILITY | M_UNIQUE | M_WARM_BLOOD + M_UNIQUE | M_SEE_INVIS | M_FLIES | M_SPECIAL_ABILITY | M_WARM_BLOOD | M_SPEAKS, MR_RES_POISON | mrd(MR_RES_FIRE, 2) | MR_VUL_COLD, 0, 18, MONS_DRAGON, MONS_DRAGON, MH_NATURAL, -7, @@ -3973,21 +3938,44 @@ static monsterentry mondata[] = { { - MONS_TIAMAT, 'd', MAGENTA, "Tiamat", - M_SEE_INVIS | M_UNIQUE | M_FLIES | M_COLD_BLOOD | M_SPEAKS, - MR_RES_POISON, - 0, 10, MONS_DRACONIAN, MONS_DRACONIAN, MH_NATURAL, -5, - { {AT_HIT, AF_PLAIN, 65}, {AT_TAIL_SLAP, AF_PLAIN, 45}, - AT_NO_ATK, AT_NO_ATK }, - { 22, 0, 0, 380 }, - 25, 10, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_ROAR, I_HIGH, - HT_LAND, 10, DEFAULT_ENERGY, MONUSE_STARTING_EQUIPMENT, SIZE_MEDIUM + MONS_AZRAEL, 'E', LIGHTRED, "Azrael", + M_UNIQUE | M_SPELLCASTER | M_LEVITATE | M_EVIL | M_GLOWS | M_SPEAKS, + MR_RES_POISON | mrd(MR_RES_FIRE, 3) | MR_VUL_COLD, + 0, 12, MONS_EFREET, MONS_EFREET, MH_DEMONIC, -3, + { {AT_HIT, AF_PLAIN, 12}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 11, 3, 5, 0 }, + 10, 5, MST_DRAC_SCORCHER, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH, + HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_LARGE }, { + MONS_PRINCE_RIBBIT, 'F', LIGHTCYAN, "Prince Ribbit", + M_UNIQUE | M_COLD_BLOOD | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS, + MR_NO_FLAGS, + 800, 12, MONS_BLINK_FROG, MONS_HUMAN, MH_NATURAL, -5, + { {AT_HIT, AF_PLAIN, 20}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 6, 3, 5, 0 }, + 3, 12, MST_PRINCE_RIBBIT, CE_CONTAMINATED, Z_SMALL, S_CROAK, I_NORMAL, + HT_AMPHIBIOUS_LAND, 14, DEFAULT_ENERGY, MONUSE_NOTHING, SIZE_LITTLE +}, + +{ + MONS_SONJA, 'K', RED, "Sonja", + M_UNIQUE | M_WARM_BLOOD | M_SPEAKS | M_SPELLCASTER | M_ACTUAL_SPELLS + | M_SPEAKS, + MR_NO_FLAGS, + 400, 10, MONS_KOBOLD, MONS_KOBOLD, MH_NATURAL, -1, + { {AT_HIT, AF_PLAIN, 9}, {AT_HIT, AF_PLAIN, 5}, {AT_HIT, AF_PLAIN, 5}, AT_NO_ATK }, + { 6, 2, 3, 0 }, + 2, 24, MST_SONJA, CE_POISONOUS, Z_SMALL, S_SHOUT, I_NORMAL, + HT_LAND, 14, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_SMALL +}, + +{ + // May be re-spawned after his death. MONS_BORIS, 'L', RED, "Boris", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_SPEAKS | M_EVIL - | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_EVIL + | M_SPEAKS, MR_RES_POISON | MR_RES_COLD | MR_RES_ELEC, 0, 15, MONS_LICH, MONS_LICH, MH_UNDEAD, -11, { {AT_HIT, AF_PLAIN, 25}, {AT_TOUCH, AF_DRAIN_XP, 15}, AT_NO_ATK, @@ -3998,9 +3986,90 @@ static monsterentry mondata[] = { }, { + MONS_ILSUIW, 'm', GREEN, "Ilsuiw", + M_UNIQUE | M_WARM_BLOOD | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS, + MR_RES_POISON | MR_RES_COLD, + 500, 10, MONS_MERFOLK, MONS_MERFOLK, MH_NATURAL, 90, + { {AT_HIT, AF_PLAIN, 10}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 9, 2, 4, 0 }, + 5, 18, MST_ILSUIW, CE_CONTAMINATED, Z_SMALL, S_SHOUT, I_NORMAL, + HT_AMPHIBIOUS_WATER, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM +}, + +{ + MONS_BLORK_THE_ORC, 'o', BROWN, "Blork the orc", + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS| M_WARM_BLOOD | M_SPEAKS, + MR_NO_FLAGS, + 0, 15, MONS_ORC, MONS_ORC, MH_NATURAL, -4, + { {AT_HIT, AF_PLAIN, 7}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 3, 0, 0, 32 }, + 0, 9, MST_ORC_WIZARD_III, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, + HT_LAND, 8, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM +}, + +{ + MONS_URUG, 'o', RED, "Urug", + M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPEAKS, + MR_NO_FLAGS, + 0, 20, MONS_ORC, MONS_ORC, MH_NATURAL, -5, + { {AT_HIT, AF_PLAIN, 12}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 6, 0, 0, 66 }, + 0, 11, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, + HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM +}, + +{ + MONS_NERGALLE, 'o', WHITE, "Nergalle", + M_UNIQUE | M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_ACTUAL_SPELLS + | M_WARM_BLOOD | M_SPEAKS, + MR_RES_FIRE | MR_RES_COLD, + 600, 12, MONS_ORC, MONS_ORC, MH_NATURAL, 50, + { {AT_HIT, AF_PLAIN, 6}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 10, 2, 3, 0 }, + 9, 11, MST_ORC_SORCERER, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_HIGH, + HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM +}, + +{ + MONS_SAINT_ROKA, 'o', LIGHTBLUE, "Saint Roka", + M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPELLCASTER | M_PRIEST | M_EVIL + | M_SPEAKS, + MR_NO_FLAGS, + 600, 15, MONS_ORC, MONS_ORC, MH_NATURAL, -3, + { {AT_HIT, AF_PLAIN, 32}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 15, 4, 7, 0 }, + 3, 10, MST_DAEVA, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, + HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM +}, + +{ + MONS_EROLCHA, 'O', LIGHTBLUE, "Erolcha", + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SEE_INVIS | M_WARM_BLOOD + | M_EVIL | M_SPEAKS, + MR_NO_FLAGS, + 0, 20, MONS_OGRE, MONS_OGRE, MH_NATURAL, -7, + { {AT_HIT, AF_PLAIN, 20}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 6, 0, 0, 54 }, + 3, 7, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, + HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_LARGE +}, + +{ + // Snorg can go berserk. + MONS_SNORG, 'T', GREEN, "Snorg", + M_UNIQUE | M_WARM_BLOOD | M_SPEAKS, + MR_NO_FLAGS, + 0, 25, MONS_TROLL, MONS_TROLL, MH_NATURAL, -6, + { {AT_BITE, AF_PLAIN, 20}, {AT_CLAW, AF_PLAIN, 15}, + {AT_CLAW, AF_PLAIN, 15}, AT_NO_ATK }, + { 8, 0, 0, 96 }, + 0, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, + HT_LAND, 10, DEFAULT_ENERGY, MONUSE_OPEN_DOORS, SIZE_LARGE +}, + +{ MONS_MURRAY, 'z', LIGHTRED, "Murray", - M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_SPEAKS | M_UNIQUE - | M_NOISY_SPELLS, + M_UNIQUE | M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_NOISY_SPELLS | M_SPEAKS, MR_RES_ELEC | MR_RES_POISON | MR_RES_HELLFIRE | mrd(MR_RES_COLD, 2), 0, 10, MONS_LICH, MONS_CURSE_SKULL, MH_UNDEAD, MAG_IMMUNE, { {AT_BITE, AF_PLAIN, 20}, {AT_BITE, AF_PLAIN, 20}, AT_NO_ATK, AT_NO_ATK }, @@ -4009,10 +4078,23 @@ static monsterentry mondata[] = { HT_LAND, 10, DEFAULT_ENERGY, MONUSE_NOTHING, SIZE_TINY }, +{ + // Roxanne obviously can't use items, but we want to equip her with + // a spellbook, so MONUSE_STARTING_EQUIPMENT is necessary. + MONS_ROXANNE, '8', LIGHTGREEN, "Roxanne", + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_STATIONARY | M_SPEAKS, + mrd(MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC, 2), + 0, 10, MONS_CLAY_GOLEM, MONS_ROXANNE, MH_NONLIVING, MAG_IMMUNE, + { AT_NO_ATK, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 14, 0, 0, 180 }, + 20, 0, MST_ROXANNE, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT, I_HIGH, + HT_LAND, 10, DEFAULT_ENERGY, MONUSE_STARTING_EQUIPMENT, SIZE_LARGE +}, + // human uniques ('@') { MONS_TERENCE, '@', LIGHTCYAN, "Terence", - M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, + M_UNIQUE | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -3, { {AT_HIT, AF_PLAIN, 5}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4023,7 +4105,7 @@ static monsterentry mondata[] = { { MONS_JESSICA, '@', LIGHTGREY, "Jessica", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -3, { {AT_HIT, AF_PLAIN, 5}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4034,7 +4116,7 @@ static monsterentry mondata[] = { { MONS_SIGMUND, '@', YELLOW, "Sigmund", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS| M_WARM_BLOOD | M_SPEAKS , MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -3, { {AT_HIT, AF_PLAIN, 5}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4045,7 +4127,7 @@ static monsterentry mondata[] = { { MONS_EDMUND, '@', RED, "Edmund", - M_FIGHTER | M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -4, { {AT_HIT, AF_PLAIN, 6}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4056,7 +4138,7 @@ static monsterentry mondata[] = { { MONS_PSYCHE, '@', LIGHTMAGENTA, "Psyche", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -4, { {AT_HIT, AF_PLAIN, 7}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4067,7 +4149,7 @@ static monsterentry mondata[] = { { MONS_DONALD, '@', BLUE, "Donald", - M_FIGHTER | M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 8}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4078,7 +4160,7 @@ static monsterentry mondata[] = { { MONS_MICHAEL, '@', LIGHTGREY, "Michael", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 9}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4089,7 +4171,7 @@ static monsterentry mondata[] = { { MONS_JOSEPH, '@', CYAN, "Joseph", - M_FIGHTER | M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 9}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4100,7 +4182,7 @@ static monsterentry mondata[] = { { MONS_ERICA, '@', MAGENTA, "Erica", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 10}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4111,8 +4193,8 @@ static monsterentry mondata[] = { { MONS_JOSEPHINE, '@', WHITE, "Josephine", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_EVIL - | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_EVIL + | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 11}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4123,8 +4205,8 @@ static monsterentry mondata[] = { { MONS_HAROLD, '@', LIGHTGREEN, "Harold", - M_FIGHTER | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD - | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD + | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 12}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4135,7 +4217,7 @@ static monsterentry mondata[] = { { MONS_NORBERT, '@', BROWN, "Norbert", - M_FIGHTER | M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 25}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4146,8 +4228,8 @@ static monsterentry mondata[] = { { MONS_JOZEF, '@', LIGHTMAGENTA, "Jozef", - M_FIGHTER | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD - | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD + | M_SPEAKS, MR_NO_FLAGS, 0, 15, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 18}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4158,7 +4240,7 @@ static monsterentry mondata[] = { { MONS_AGNES, '@', LIGHTBLUE, "Agnes", - M_FIGHTER | M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 15, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 30}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4169,7 +4251,7 @@ static monsterentry mondata[] = { { MONS_MAUD, '@', RED, "Maud", - M_FIGHTER | M_WARM_BLOOD | M_SPEAKS | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_WARM_BLOOD | M_SPEAKS, MR_NO_FLAGS, 0, 15, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 24}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4180,8 +4262,8 @@ static monsterentry mondata[] = { { MONS_LOUISE, '@', BLUE, "Louise", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_EVIL - | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_EVIL + | M_SPEAKS, MR_NO_FLAGS, 0, 15, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 17}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4192,8 +4274,8 @@ static monsterentry mondata[] = { { MONS_FRANCIS, '@', YELLOW, "Francis", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD - | M_SEE_INVIS | M_EVIL | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS + | M_EVIL | M_SPEAKS, MR_NO_FLAGS, 0, 15, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 19}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4204,8 +4286,8 @@ static monsterentry mondata[] = { { MONS_FRANCES, '@', YELLOW, "Frances", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD - | M_SEE_INVIS | M_EVIL | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS + | M_EVIL | M_SPEAKS, MR_NO_FLAGS, 0, 15, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 29}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4216,8 +4298,8 @@ static monsterentry mondata[] = { { MONS_RUPERT, '@', RED, "Rupert", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD - | M_SEE_INVIS | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS + | M_SPEAKS, MR_NO_FLAGS, 0, 12, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 21}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4228,8 +4310,8 @@ static monsterentry mondata[] = { { MONS_WAYNE, '@', YELLOW, "Wayne", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD - | M_SEE_INVIS | M_EVIL | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS + | M_EVIL | M_SPEAKS, MR_NO_FLAGS, 0, 12, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 22}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4240,8 +4322,8 @@ static monsterentry mondata[] = { { MONS_DUANE, '@', YELLOW, "Duane", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD | M_SEE_INVIS - | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS + | M_SPEAKS, MR_NO_FLAGS, 0, 10, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 22}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4252,8 +4334,8 @@ static monsterentry mondata[] = { { MONS_NORRIS, '@', LIGHTRED, "Norris", - M_FIGHTER | M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD - | M_SEE_INVIS | M_EVIL | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD + | M_SEE_INVIS | M_EVIL | M_SPEAKS, MR_NO_FLAGS, 0, 10, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 36}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4264,8 +4346,8 @@ static monsterentry mondata[] = { { MONS_FREDERICK, '@', GREEN, "Frederick", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD - | M_SEE_INVIS | M_EVIL | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS + | M_EVIL | M_SPEAKS, MR_NO_FLAGS, 0, 12, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 27}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4276,8 +4358,8 @@ static monsterentry mondata[] = { { MONS_MARGERY, '@', LIGHTRED, "Margery", - M_SPELLCASTER | M_ACTUAL_SPELLS | M_SPEAKS | M_WARM_BLOOD - | M_SEE_INVIS | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SEE_INVIS + | M_SPEAKS, MR_NO_FLAGS, 0, 15, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, -5, { {AT_HIT, AF_PLAIN, 30}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4286,10 +4368,21 @@ static monsterentry mondata[] = { HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM }, +{ + MONS_EUSTACHIO, '@', GREEN, "Eustachio", + M_UNIQUE | M_SPELLCASTER | M_ACTUAL_SPELLS | M_WARM_BLOOD | M_SPEAKS, + MR_NO_FLAGS, + 0, 20, MONS_HUMAN, MONS_HUMAN, MH_NATURAL, 24, + { {AT_HIT, AF_PLAIN, 6}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, + { 4, 0, 0, 40 }, + 0, 13, MST_EUSTACHIO, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, + HT_LAND, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, SIZE_MEDIUM +}, + // unique major demons ('&') { MONS_MNOLEG, '&', LIGHTGREEN, "Mnoleg", - M_FIGHTER | M_SEE_INVIS | M_SPELLCASTER | M_SPEAKS | M_EVIL | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_SEE_INVIS | M_SPELLCASTER | M_EVIL | M_SPEAKS, MR_RES_ELEC | MR_RES_POISON | MR_RES_FIRE, 0, 15, MONS_MNOLEG, MONS_MNOLEG, MH_DEMONIC, MAG_IMMUNE, { {AT_HIT, AF_PLAIN, 35}, {AT_HIT, AF_PLAIN, 23}, AT_NO_ATK, AT_NO_ATK }, @@ -4300,8 +4393,8 @@ static monsterentry mondata[] = { { MONS_LOM_LOBON, '&', LIGHTBLUE, "Lom Lobon", - M_FIGHTER | M_LEVITATE | M_SEE_INVIS | M_SPELLCASTER | M_SPEAKS - | M_EVIL | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_LEVITATE | M_SEE_INVIS | M_SPELLCASTER | M_EVIL + | M_SPEAKS, MR_RES_POISON | MR_RES_FIRE | mrd(MR_RES_COLD | MR_RES_ELEC, 3), 0, 15, MONS_LOM_LOBON, MONS_LOM_LOBON, MH_DEMONIC, MAG_IMMUNE, { {AT_HIT, AF_PLAIN, 40}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4312,7 +4405,7 @@ static monsterentry mondata[] = { { MONS_CEREBOV, '&', RED, "Cerebov", - M_FIGHTER | M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_SPEAKS, MR_RES_POISON | mrd(MR_RES_HELLFIRE, 3), 0, 15, MONS_CEREBOV, MONS_CEREBOV, MH_DEMONIC, -6, { {AT_HIT, AF_PLAIN, 60}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4323,8 +4416,8 @@ static monsterentry mondata[] = { { MONS_GLOORX_VLOQ, '&', LIGHTGREY, "Gloorx Vloq", - M_FIGHTER | M_LEVITATE | M_SEE_INVIS | M_SPELLCASTER | M_SPEAKS | M_EVIL - | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_LEVITATE | M_SEE_INVIS | M_SPELLCASTER | M_EVIL + | M_SPEAKS, MR_RES_POISON | MR_RES_COLD | MR_RES_ELEC, 0, 15, MONS_GLOORX_VLOQ, MONS_GLOORX_VLOQ, MH_DEMONIC, -14, { {AT_HIT, AF_PLAIN, 45}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4335,8 +4428,8 @@ static monsterentry mondata[] = { { MONS_GERYON, '&', GREEN, "Geryon", - M_FIGHTER | M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_FLIES - | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_FLIES + | M_SPEAKS, MR_NO_FLAGS, 0, 15, MONS_GERYON, MONS_GERYON, MH_DEMONIC, -6, { {AT_HIT, AF_PLAIN, 35}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4347,7 +4440,7 @@ static monsterentry mondata[] = { { MONS_DISPATER, '&', MAGENTA, "Dispater", - M_FIGHTER | M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_SPEAKS, MR_RES_ELEC | MR_RES_POISON | MR_RES_HELLFIRE | MR_RES_COLD, 0, 15, MONS_DISPATER, MONS_DISPATER, MH_DEMONIC, -10, { {AT_HIT, AF_PLAIN, 50}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4358,8 +4451,8 @@ static monsterentry mondata[] = { { MONS_ASMODEUS, '&', LIGHTMAGENTA, "Asmodeus", - M_FIGHTER | M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_SPEAKS | M_EVIL - | M_UNIQUE, + M_UNIQUE | M_FIGHTER | M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_EVIL + | M_SPEAKS, MR_RES_ELEC | MR_RES_POISON | MR_RES_HELLFIRE, 0, 25, MONS_ASMODEUS, MONS_ASMODEUS, MH_DEMONIC, -12, { {AT_HIT, AF_PLAIN, 50}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, @@ -4370,7 +4463,7 @@ static monsterentry mondata[] = { { MONS_ERESHKIGAL, '&', WHITE, "Ereshkigal", - M_SPELLCASTER | M_SEE_INVIS | M_SPEAKS | M_EVIL | M_UNIQUE, + M_UNIQUE | M_SPELLCASTER | M_SEE_INVIS | M_EVIL | M_SPEAKS, MR_RES_ELEC | MR_RES_POISON | MR_RES_COLD, 0, 15, MONS_ERESHKIGAL, MONS_ERESHKIGAL, MH_DEMONIC, -10, { {AT_HIT, AF_PLAIN, 40}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, diff --git a/crawl-ref/source/mon-spll.h b/crawl-ref/source/mon-spll.h index fed39f962b..ad4783c30d 100644 --- a/crawl-ref/source/mon-spll.h +++ b/crawl-ref/source/mon-spll.h @@ -506,105 +506,6 @@ } }, - { MST_GERYON, - { - SPELL_SUMMON_BEAST, - SPELL_SUMMON_BEAST, - SPELL_NO_SPELL, - SPELL_SUMMON_BEAST, - SPELL_NO_SPELL, - SPELL_SUMMON_BEAST - } - }, - - { MST_DISPATER, - { - SPELL_SUMMON_GREATER_DEMON, - SPELL_BOLT_OF_IRON, - SPELL_SUMMON_DEMON, - SPELL_LIGHTNING_BOLT, - SPELL_HELLFIRE, - SPELL_SUMMON_GREATER_DEMON - } - }, - - { MST_ASMODEUS, - { - SPELL_BOLT_OF_FIRE, - SPELL_HELLFIRE, - SPELL_SUMMON_DEMON, - SPELL_SUMMON_GREATER_DEMON, - SPELL_BOLT_OF_DRAINING, - SPELL_TELEPORT_SELF - } - }, - - { MST_ERESHKIGAL, - { - SPELL_BOLT_OF_DRAINING, - SPELL_BOLT_OF_COLD, - SPELL_SUMMON_GREATER_DEMON, - SPELL_SYMBOL_OF_TORMENT, - SPELL_PARALYSE, - SPELL_LESSER_HEALING - } - }, - - { MST_ANTAEUS, - { - SPELL_BOLT_OF_COLD, - SPELL_LIGHTNING_BOLT, - SPELL_NO_SPELL, - SPELL_NO_SPELL, - SPELL_NO_SPELL, - SPELL_NO_SPELL - } - }, - - { MST_MNOLEG, - { - SPELL_SUMMON_GREATER_DEMON, - SPELL_SMITING, - SPELL_INVISIBILITY, - SPELL_SUMMON_HORRIBLE_THINGS, - SPELL_SUMMON_HORRIBLE_THINGS, - SPELL_TELEPORT_SELF - } - }, - - { MST_LOM_LOBON, - { - SPELL_ICE_STORM, - SPELL_CONJURE_BALL_LIGHTNING, - SPELL_GREATER_HEALING, - SPELL_BLINK, - SPELL_BLINK, - SPELL_TELEPORT_SELF - } - }, - - { MST_CEREBOV, - { - SPELL_FIRE_STORM, - SPELL_BOLT_OF_IRON, - SPELL_HASTE, - SPELL_HASTE, - SPELL_SUMMON_GREATER_DEMON, - SPELL_HASTE - } - }, - - { MST_GLOORX_VLOQ, - { - SPELL_POISON_ARROW, - SPELL_MIASMA, - SPELL_SYMBOL_OF_TORMENT, - SPELL_BOLT_OF_DRAINING, - SPELL_DISPEL_UNDEAD, - SPELL_INVISIBILITY - } - }, - { MST_TITAN, { SPELL_LIGHTNING_BOLT, @@ -1047,6 +948,21 @@ } }, + { MST_ICE_STATUE, + { + SPELL_BOLT_OF_COLD, + SPELL_ICE_BOLT, + SPELL_NO_SPELL, + SPELL_FREEZING_CLOUD, + SPELL_SUMMON_ICE_BEAST, + SPELL_SUMMON_ICE_BEAST + } + }, + + // --------------------- + // unique's "spellbooks" + // --------------------- + // Crusader theme. { MST_RUPERT, { @@ -1059,14 +975,157 @@ } }, - { MST_ICE_STATUE, + { MST_ROXANNE, { + SPELL_LEHUDIBS_CRYSTAL_SPEAR, + SPELL_BOLT_OF_IRON, + SPELL_BOLT_OF_MAGMA, + SPELL_STONE_ARROW, + SPELL_ISKENDERUNS_MYSTIC_BLAST, + SPELL_SANDBLAST + } + }, + + { MST_SONJA, + { + SPELL_NO_SPELL, + SPELL_NO_SPELL, + SPELL_BLINK, + SPELL_NO_SPELL, + SPELL_NO_SPELL, + SPELL_TELEPORT_SELF + } + }, + + { MST_EUSTACHIO, + { + SPELL_SUMMON_SMALL_MAMMALS, + SPELL_CALL_IMP, + SPELL_BLINK, + SPELL_NO_SPELL, + SPELL_NO_SPELL, + SPELL_BLINK + } + }, + + { MST_ILSUIW, + { + SPELL_THROW_FROST, // was: SPELL_CONFUSED + SPELL_SLOW, + SPELL_INVISIBILITY, + SPELL_BLINK, + SPELL_WATER_ELEMENTALS, + SPELL_WATER_ELEMENTALS + } + }, + + { MST_PRINCE_RIBBIT, + { + SPELL_NO_SPELL, + SPELL_NO_SPELL, + SPELL_NO_SPELL, + SPELL_NO_SPELL, + SPELL_NO_SPELL, + SPELL_TELEPORT_SELF + } + }, + + { MST_GERYON, + { + SPELL_SUMMON_BEAST, + SPELL_SUMMON_BEAST, + SPELL_NO_SPELL, + SPELL_SUMMON_BEAST, + SPELL_NO_SPELL, + SPELL_SUMMON_BEAST + } + }, + + { MST_DISPATER, + { + SPELL_SUMMON_GREATER_DEMON, + SPELL_BOLT_OF_IRON, + SPELL_SUMMON_DEMON, + SPELL_LIGHTNING_BOLT, + SPELL_HELLFIRE, + SPELL_SUMMON_GREATER_DEMON + } + }, + + { MST_ASMODEUS, + { + SPELL_BOLT_OF_FIRE, + SPELL_HELLFIRE, + SPELL_SUMMON_DEMON, + SPELL_SUMMON_GREATER_DEMON, + SPELL_BOLT_OF_DRAINING, + SPELL_TELEPORT_SELF + } + }, + + { MST_ERESHKIGAL, + { + SPELL_BOLT_OF_DRAINING, SPELL_BOLT_OF_COLD, - SPELL_ICE_BOLT, + SPELL_SUMMON_GREATER_DEMON, + SPELL_SYMBOL_OF_TORMENT, + SPELL_PARALYSE, + SPELL_LESSER_HEALING + } + }, + + { MST_ANTAEUS, + { + SPELL_BOLT_OF_COLD, + SPELL_LIGHTNING_BOLT, SPELL_NO_SPELL, - SPELL_FREEZING_CLOUD, - SPELL_SUMMON_ICE_BEAST, - SPELL_SUMMON_ICE_BEAST + SPELL_NO_SPELL, + SPELL_NO_SPELL, + SPELL_NO_SPELL + } + }, + + { MST_MNOLEG, + { + SPELL_SUMMON_GREATER_DEMON, + SPELL_SMITING, + SPELL_INVISIBILITY, + SPELL_SUMMON_HORRIBLE_THINGS, + SPELL_SUMMON_HORRIBLE_THINGS, + SPELL_TELEPORT_SELF + } + }, + + { MST_LOM_LOBON, + { + SPELL_ICE_STORM, + SPELL_CONJURE_BALL_LIGHTNING, + SPELL_GREATER_HEALING, + SPELL_BLINK, + SPELL_BLINK, + SPELL_TELEPORT_SELF + } + }, + + { MST_CEREBOV, + { + SPELL_FIRE_STORM, + SPELL_BOLT_OF_IRON, + SPELL_HASTE, + SPELL_HASTE, + SPELL_SUMMON_GREATER_DEMON, + SPELL_HASTE + } + }, + + { MST_GLOORX_VLOQ, + { + SPELL_POISON_ARROW, + SPELL_MIASMA, + SPELL_SYMBOL_OF_TORMENT, + SPELL_BOLT_OF_DRAINING, + SPELL_DISPEL_UNDEAD, + SPELL_INVISIBILITY } }, diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 4b00e1208c..58499bc276 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -633,7 +633,8 @@ bool mons_is_statue(int mc) { return (mc == MONS_ORANGE_STATUE || mc == MONS_SILVER_STATUE - || mc == MONS_ICE_STATUE); + || mc == MONS_ICE_STATUE + || mc == MONS_ROXANNE); } bool mons_is_mimic(int mc) @@ -3129,6 +3130,10 @@ const char *mons_pronoun(monster_type mon_type, pronoun_type variant, case MONS_ERICA: case MONS_TIAMAT: case MONS_ERESHKIGAL: + case MONS_ROXANNE: + case MONS_SONJA: + case MONS_ILSUIW: + case MONS_NERGALLE: gender = GENDER_FEMALE; break; case MONS_ROYAL_JELLY: @@ -4908,6 +4913,10 @@ bool monsters::pickup_item(item_def &item, int near, bool force) return pickup_scroll(item, near); case OBJ_POTIONS: return pickup_potion(item, near); + case OBJ_BOOKS: + if (force) + return pickup_misc(item, near); + // else fall through default: return (false); } @@ -7513,6 +7522,9 @@ static inline monster_type _royal_jelly_ejectable_monster() bool monsters::can_drink_potion(potion_type ptype) const { + if (mons_class_is_stationary(this->type)) + return (false); + if (mons_itemuse(this) >= MONUSE_STARTING_EQUIPMENT) { if (mons_is_skeletal(type) || mons_is_insubstantial(type) diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc index dd15159111..1437bf68bb 100644 --- a/crawl-ref/source/monplace.cc +++ b/crawl-ref/source/monplace.cc @@ -1417,6 +1417,7 @@ static band_type _choose_band(int mon_type, int power, int &band_size) break; case MONS_ORC_WARLORD: + case MONS_SAINT_ROKA: band_size = 5 + random2(5); // warlords have large bands // intentional fall through case MONS_ORC_KNIGHT: @@ -1582,58 +1583,72 @@ static band_type _choose_band(int mon_type, int power, int &band_size) band = BAND_NAGAS; band_size = 3 + random2(4); break; + case MONS_WAR_DOG: band = BAND_WAR_DOGS; band_size = 2 + random2(4); break; + case MONS_GREY_RAT: band = BAND_GREY_RATS; band_size = 4 + random2(6); break; + case MONS_GREEN_RAT: band = BAND_GREEN_RATS; band_size = 4 + random2(6); break; + case MONS_ORANGE_RAT: band = BAND_ORANGE_RATS; band_size = 3 + random2(4); break; + case MONS_SHEEP: band = BAND_SHEEP; band_size = 3 + random2(5); break; + case MONS_GHOUL: band = BAND_GHOULS; band_size = 2 + random2(3); break; + case MONS_HOG: band = BAND_HOGS; band_size = 1 + random2(3); break; + case MONS_GIANT_MOSQUITO: band = BAND_GIANT_MOSQUITOES; band_size = 1 + random2(3); break; + case MONS_DEEP_TROLL: band = BAND_DEEP_TROLLS; band_size = 3 + random2(3); break; + case MONS_HELL_HOG: band = BAND_HELL_HOGS; band_size = 1 + random2(3); break; + case MONS_BOGGART: band = BAND_BOGGARTS; band_size = 2 + random2(3); break; + case MONS_BLINK_FROG: band = BAND_BLINK_FROGS; band_size = 2 + random2(3); break; + case MONS_SKELETAL_WARRIOR: band = BAND_SKELETAL_WARRIORS; band_size = 2 + random2(3); break; + case MONS_CYCLOPS: if (one_chance_in(5) || player_in_branch(BRANCH_SHOALS)) { @@ -1641,10 +1656,12 @@ static band_type _choose_band(int mon_type, int power, int &band_size) band_size = 2 + random2(3); } break; + case MONS_POLYPHEMUS: band = BAND_DEATH_YAKS; band_size = 3 + random2(3); break; + case MONS_HARPY: band = BAND_HARPIES; band_size = 2 + random2(3); @@ -1665,6 +1682,7 @@ static band_type _choose_band(int mon_type, int power, int &band_size) band_size = random_range(2, 4); } break; + case MONS_DRACONIAN_CALLER: case MONS_DRACONIAN_MONK: case MONS_DRACONIAN_SCORCHER: @@ -1678,11 +1696,22 @@ static band_type _choose_band(int mon_type, int power, int &band_size) band_size = random_range(3, 6); } break; + case MONS_TIAMAT: band = BAND_DRACONIAN; // yup, scary band_size = random_range(3,6) + random_range(3,6) + 2; break; + + case MONS_ILSUIW: + band = BAND_ILSUIW; + band_size = 3 + random2(3); + break; + + case MONS_AZRAEL: + band = BAND_AZRAEL; + band_size = 4 + random2(5); + break; } // end switch if (band != BAND_NO_BAND && band_size == 0) @@ -1973,6 +2002,14 @@ static monster_type _band_member(band_type band, int power) MONS_RED_DRACONIAN ); // 3 in 34 break; } + case BAND_ILSUIW: + mon_type = coinflip()? MONS_MERFOLK : MONS_MERMAID; + break; + + case BAND_AZRAEL: + mon_type = coinflip()? MONS_FIRE_ELEMENTAL : MONS_HELL_HOUND; + break; + default: break; } diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/monplace.h index 3ff4de443d..c71f9252f7 100644 --- a/crawl-ref/source/monplace.h +++ b/crawl-ref/source/monplace.h @@ -63,7 +63,9 @@ enum band_type BAND_SKELETAL_WARRIORS, BAND_DRACONIAN, // 45 BAND_PANDEMONIUM_DEMON, - BAND_HARPIES, // 47 + BAND_HARPIES, + BAND_ILSUIW, + BAND_AZRAEL, NUM_BANDS // always last }; diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index b7fc6972a3..06cba432f1 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -4991,6 +4991,7 @@ static bool _handle_special_ability(monsters *monster, bolt & beem) { case MONS_ORC_KNIGHT: case MONS_ORC_WARLORD: + case MONS_SAINT_ROKA: if (is_sanctuary(monster->pos())) break; @@ -5243,6 +5244,7 @@ static bool _handle_special_ability(monsters *monster, bolt & beem) case MONS_INSUBSTANTIAL_WISP: case MONS_BLINK_FROG: case MONS_KILLER_KLOWN: + case MONS_PRINCE_RIBBIT: if (one_chance_in(7) || mons_is_caught(monster) && one_chance_in(3)) { simple_monster_message(monster, " blinks."); diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc index 32fce22cdf..8fc3248470 100644 --- a/crawl-ref/source/mstuff2.cc +++ b/crawl-ref/source/mstuff2.cc @@ -230,6 +230,20 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast, } return; + case SPELL_WATER_ELEMENTALS: + if (_mons_abjured(monster, monsterNearby)) + return; + + sumcount2 = 1 + random2(4) + random2(monster->hit_dice / 7 + 1); + + for (sumcount = 0; sumcount < sumcount2; sumcount++) + { + create_monster( + mgen_data(MONS_WATER_ELEMENTAL, SAME_ATTITUDE(monster), 3, + spell_cast, monster->pos(), monster->foe)); + } + return; + case SPELL_FAKE_RAKSHASA_SUMMON: sumcount2 = (coinflip() ? 2 : 3); @@ -960,6 +974,7 @@ void setup_mons_cast(monsters *monster, bolt &pbolt, case SPELL_SUMMON_GREATER_DEMON: case SPELL_CANTRIP: case SPELL_BERSERKER_RAGE: + case SPELL_WATER_ELEMENTALS: return; default: break; diff --git a/crawl-ref/source/place.cc b/crawl-ref/source/place.cc index aa09c9ef45..78bd1d68c7 100644 --- a/crawl-ref/source/place.cc +++ b/crawl-ref/source/place.cc @@ -160,7 +160,7 @@ int absdungeon_depth(branch_type branch, int subdepth) else { --subdepth; - while ( branch != BRANCH_MAIN_DUNGEON ) + while (branch != BRANCH_MAIN_DUNGEON) { subdepth += branches[branch].startdepth; branch = branches[branch].parent_branch; diff --git a/crawl-ref/source/randart.cc b/crawl-ref/source/randart.cc index d79cdc5c29..74f59e7b3e 100644 --- a/crawl-ref/source/randart.cc +++ b/crawl-ref/source/randart.cc @@ -1584,7 +1584,7 @@ int find_unrandart_index(const item_def& artefact) static unrandart_entry *_seekunrandart( const item_def &item ) { const int idx = find_unrandart_index(item); - if ( idx == -1 ) + if (idx == -1) return &unranddata[0]; // dummy unrandart else return &unranddata[idx]; diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc index 991f481542..8b840a214c 100644 --- a/crawl-ref/source/spells4.cc +++ b/crawl-ref/source/spells4.cc @@ -890,7 +890,8 @@ static int _distortion_monsters(coord_def where, int pow, int message) int specdam = 0; monsters *defender = &menv[monster_attacked]; - if (defender->type == MONS_BLINK_FROG) // any others resist? + if (defender->type == MONS_BLINK_FROG + || defender->type == MONS_PRINCE_RIBBIT) // any others resist? { int hp = defender->hit_points; int max_hp = defender->max_hit_points; @@ -963,7 +964,8 @@ int disperse_monsters(coord_def where, int pow, int message) monsters *defender = &menv[monster_attacked]; - if (defender->type == MONS_BLINK_FROG) + if (defender->type == MONS_BLINK_FROG + || defender->type == MONS_PRINCE_RIBBIT) { simple_monster_message(defender, " resists."); return 1; @@ -1010,6 +1012,7 @@ static int _spell_swap_func(coord_def where, int pow, int message) monsters *defender = &menv[monster_attacked]; if (defender->type == MONS_BLINK_FROG + || defender->type == MONS_PRINCE_RIBBIT || check_mons_resist_magic( defender, pow )) { simple_monster_message( defender, mons_immune_magic(defender) ? diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc index 272d65579d..a1425a68fe 100644 --- a/crawl-ref/source/spl-book.cc +++ b/crawl-ref/source/spl-book.cc @@ -2162,7 +2162,8 @@ static void _get_weighted_spells(bool completely_random, god_type god, } static void _remove_nondiscipline_spells(spell_type chosen_spells[], - int d1, int d2) + int d1, int d2, + spell_type exclude = SPELL_NO_SPELL) { int replace = -1; for (int i = 0; i < SPELLBOOK_SIZE; i++) @@ -2170,6 +2171,9 @@ static void _remove_nondiscipline_spells(spell_type chosen_spells[], if (chosen_spells[i] == SPELL_NO_SPELL) break; + if (chosen_spells[i] == exclude) + continue; + // If a spell matches neither the first nor the second type // (that may be the same) remove it. if (!spell_typematch(chosen_spells[i], d1) @@ -2188,8 +2192,18 @@ static void _remove_nondiscipline_spells(spell_type chosen_spells[], } } +// Takes a book of any type, a spell discipline or two, the number of spells +// (up to 8), the total spell levels of all spells, a spell that absolutely +// has to be included, and the name of whomever the book should be named after. +// With all that information the book is turned into a random artefact +// containing random spells of the given disciplines (random if none set). +// NOTE: This function calls make_item_randart() which recursively calls +// make_book_theme_randart() again but without all those parameters, +// so they have to be stored in the book attributes so as to not +// forget them. bool make_book_theme_randart(item_def &book, int disc1, int disc2, - int num_spells, int max_levels) + int num_spells, int max_levels, + spell_type incl_spell, std::string owner) { ASSERT(book.base_type == OBJ_BOOKS); @@ -2201,6 +2215,12 @@ bool make_book_theme_randart(item_def &book, int disc1, int disc2, if (!is_random_artefact(book)) { + // Store spell and owner for later use. + if (incl_spell != SPELL_NO_SPELL) + book.props["spell"].get_long() = incl_spell; + if (!owner.empty()) + book.props["owner"].get_string() = owner; + // Stuff parameters into book.plus and book.plus2, then call // make_item_randart(), which will then call us back. if (num_spells == -1) @@ -2238,8 +2258,14 @@ bool make_book_theme_randart(item_def &book, int disc1, int disc2, return (make_item_randart(book)); } - // We're being called from make_item_randart() + // Re-read spell and owner, if applicable. + if (incl_spell == SPELL_NO_SPELL && book.props.exists("spell")) + incl_spell = (spell_type) book.props["spell"].get_long(); + if (owner.empty() && book.props.exists("owner")) + owner = book.props["owner"].get_string(); + + // We're being called from make_item_randart() ASSERT(book.sub_type == BOOK_RANDART_THEME); ASSERT(disc1 == 0 && disc2 == 0); ASSERT(num_spells == -1 && max_levels == -1); @@ -2275,6 +2301,23 @@ bool make_book_theme_randart(item_def &book, int disc1, int disc2, _get_weighted_spells(completely_random, god, disc1, disc2, num_spells, max_levels, spell_list, chosen_spells); + if (!is_valid_spell(incl_spell)) + incl_spell = SPELL_NO_SPELL; + else + { + bool is_included = false; + for (int i = 0; i < SPELLBOOK_SIZE; i++) + { + if (chosen_spells[i] == incl_spell) + { + is_included = true; + break; + }; + } + if (!is_included) + chosen_spells[0] = incl_spell; + } + std::sort(chosen_spells, chosen_spells + SPELLBOOK_SIZE, _compare_spells); ASSERT(chosen_spells[0] != SPELL_NO_SPELL); @@ -2338,7 +2381,8 @@ bool make_book_theme_randart(item_def &book, int disc1, int disc2, max2 = max1; // Remove spells that don't fit either discipline. - _remove_nondiscipline_spells(chosen_spells, 1 << max1, 1 << max2); + _remove_nondiscipline_spells(chosen_spells, 1 << max1, 1 << max2, + incl_spell); // Finally fill the spell vector. for (int i = 0; i < SPELLBOOK_SIZE; i++) @@ -2354,19 +2398,18 @@ bool make_book_theme_randart(item_def &book, int disc1, int disc2, std::string name; bool need_quotes = true; - if (god != GOD_NO_GOD) - { - name = '"'; - name += god_name(god, false) + "'s "; - } + if (!owner.empty()) + name = owner; + else if (god != GOD_NO_GOD) + name = god_name(god, false); else if (one_chance_in(5)) // Occasionally, use a random name. - { - name = '"'; - name += make_name(random_int(), false) + "'s "; - } + name = make_name(random_int(), false); else need_quotes = false; + if (need_quotes) + name = '"' + name + "'s "; + name += getRandNameString("book_noun"); name += " of "; @@ -2431,6 +2474,15 @@ bool make_book_theme_randart(item_def &book, int disc1, int disc2, return (true); } +// Give Roxanne a randart spellbook of the disciplines Transmigration/Earth +// that includes Statue Form and is named after her. +void make_book_Roxanne_special(item_def *book) +{ + int disc = coinflip() ? SPTYP_TRANSMIGRATION : SPTYP_EARTH; + make_book_theme_randart(*book, disc, 0, 5, 19, + SPELL_STATUE_FORM, "Roxanne"); +} + bool book_has_title(const item_def &book) { ASSERT(book.base_type == OBJ_BOOKS); diff --git a/crawl-ref/source/spl-book.h b/crawl-ref/source/spl-book.h index b43aeddf53..e48ea6fe09 100644 --- a/crawl-ref/source/spl-book.h +++ b/crawl-ref/source/spl-book.h @@ -73,7 +73,10 @@ bool make_book_level_randart(item_def &book, int level = -1, int num_spells = -1); bool make_book_theme_randart(item_def &book, int disc1 = 0, int disc2 = 0, - int num_spells = -1, int max_levels = -1); + int num_spells = -1, int max_levels = -1, + spell_type incl_spell = SPELL_NO_SPELL, + std::string owner = ""); +void make_book_Roxanne_special(item_def *book); bool book_has_title(const item_def &book); #endif diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h index 4709251890..dbc61f2739 100644 --- a/crawl-ref/source/spl-data.h +++ b/crawl-ref/source/spl-data.h @@ -2904,6 +2904,19 @@ }, { + SPELL_WATER_ELEMENTALS, "Summon Water Elementals", + SPTYP_SUMMONING, + SPFLAG_NONE, + 5, + 0, + -1, -1, + 0, + NULL, + false, + false +}, + +{ SPELL_NO_SPELL, "nonexistent spell", 0, SPFLAG_TESTING, |