summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-04 20:50:21 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-04 20:50:21 +0000
commite828bafa67e06c97dad7b9fcf2851e6ab5b00f28 (patch)
tree77fbcd20c3485501851302796dfa70640a5e2c90 /crawl-ref/source
parent07828b78525d85498811687311f0a9cff5901e03 (diff)
downloadcrawl-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.txt335
-rw-r--r--crawl-ref/source/dat/descript/monsters.txt40
-rw-r--r--crawl-ref/source/dungeon.cc42
-rw-r--r--crawl-ref/source/enum.h112
-rw-r--r--crawl-ref/source/fight.cc3
-rw-r--r--crawl-ref/source/makeitem.cc91
-rw-r--r--crawl-ref/source/mon-data.h317
-rw-r--r--crawl-ref/source/mon-spll.h267
-rw-r--r--crawl-ref/source/mon-util.cc14
-rw-r--r--crawl-ref/source/monplace.cc37
-rw-r--r--crawl-ref/source/monplace.h4
-rw-r--r--crawl-ref/source/monstuff.cc2
-rw-r--r--crawl-ref/source/mstuff2.cc15
-rw-r--r--crawl-ref/source/place.cc2
-rw-r--r--crawl-ref/source/randart.cc2
-rw-r--r--crawl-ref/source/spells4.cc7
-rw-r--r--crawl-ref/source/spl-book.cc78
-rw-r--r--crawl-ref/source/spl-book.h5
-rw-r--r--crawl-ref/source/spl-data.h13
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,