1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-07-28 08:22:24 +01:00

Merge branch 'devel-drowHealer' into devel-3.22.0

# Conflicts:
#	dat/dngnch1.def
#	dat/dngnch2.def
#	src/display.c
#	src/dungeon.c
#	src/monmove.c
This commit is contained in:
chris 2023-01-24 23:11:25 -05:00
commit 1ba0f0c1b3
87 changed files with 7374 additions and 843 deletions

View file

@ -191,7 +191,7 @@ $(AUTO_C:%.c=%.d): ;
##### DATA FILES #####
QUEST_DES = Arch.des Anachrononaut.des Android.des Barb.des Bard.des Binder.des Caveman.des \
Convict.des Drow.des DrowNoble.des Elf.des Erebor.des GnomeRanger.des \
Convict.des Drow.des DrowNoble.des DrowHealer.des Elf.des Erebor.des GnomeRanger.des \
HalfDragonFemaleNoble.des Healer.des Hedrow.des HedrowNoble.des Knight.des \
Monk.des Moria.des Madman.des Noble.des Pirate.des Priest.des Ranger.des Rogue.des \
Samurai.des Tourist.des Valkyrie.des Wizard.des

1487
dat/DrowHealer.des Normal file

File diff suppressed because it is too large Load diff

View file

@ -376,8 +376,9 @@ OBJECT:'#',"+1 uncursed iron axe",contained
OBJECT:'#',"+3 blessed elven boots",contained
OBJECT:'#',"+3 blessed high-elven gauntlets",contained
OBJECT:'#',"+3 blessed reflective high-elven plate",contained
OBJECT:'#',"+3 holy-armor elven cloak",contained
OBJECT:'#',"+3 holy-armor dragonhide prayer-warded elven cloak",contained
OBJECT:'#',"+3 blessed high-elven helm",contained
OBJECT:'#',"+3 holy-armor elven shield",contained
OBJECT:'#',"+3 holy-weapon wrathful mithril elven broadsword",contained
OBJECT:random,random,(36,09)

View file

@ -10,6 +10,68 @@
#
MAZE: "Hea-strt",' '
FLAGS: noteleport,hardfloor
GEOMETRY:center,center
#0 1 2 3 4 5 6 7
#0123456789012345678901234567890123456789012345678901234567890123456789012345
MAP
0PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
1PPPPeeeeeeeePPPPeeeeePPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPePeePPPPPeeeeeePPPPPPPP
2PPPeeeeeeeeeePPPPeeePPPPPeeeeeeeeeeeeeeeeeeeeeeeeePPPPeePPPPPeeeeeeeePPPPPPP
3PPeeeeeeeeeeeePPPPPPPPeeeeeeeeeeeeeeeeeeeeeeeeeeeeeePPPeeePPPPeeeeeePPPPPPPP
4PeeeeePPPPPPPPPPPPPPPeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeePPPPPPPPPPPPPPPPPPPPPPP
5PPPPeeeePPPPPPPPPPPPeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeePPPPPePPPPPPPPPPPPPPP
6PPPPeeeeeeeePPPPPeeeeeeeee-----------------------eeeeeeeePPeeePPPPPPPeeeeePP
7PPPeeeeeeeeeeeePPPPPeeee--| | |--eeeeePPPPePPPPPPPeeeeeeeP
8PPPPeeeeeeeeeePPPPPeeeee| | -----------| | |eeeeeePPPPPPePPPeeeeeeePP
9PPPPPPeeeeeePPPPPPeeeeee| | | | | | | |eeeeePPPPPPeeePPeeeeeeePP
0PPPPPPPPPPPPPPPPPPPeeeee | | | | eeeeeePPPPPPePPPPeeeeeeeP
1PPPeeePPPPPeeePPPPeeeeee| | | | | | | |eeeeeeePPPPPPPPPPPeeeeePP
2PPeeeeePPPeeeeePPPeeeeee| | |----------- | |eeeeeePPPPPPPPPPPPPPPPPPP
3PPPeePPPPPeeePPPPeeeeeee--| | |--eeeeePPPPPPPPPeeeePPPPPPP
4PPPPPPPPPPPPPPPPeeeeeeeeee-----------------------eeeeeeeeeePPPPPeeeeeeeeeePP
5PPPPPPPPPPPPPPPPPeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeePPPPPPeeeeeeeeeeeeP
6PPPeeeeeeeeeeeeePPPPeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeePPPeePPPPeeeeeeeeeePP
7PPeeeeeeeeeeeeeeePPPPPeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeePPPPeeePPPPeeeeeeeePPP
8PPPeeeeeeeeeeeeePPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPeeeePPPPPP
9PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
ENDMAP
#0123456789012345678901234567890123456789012345678901234567890123456789012345
#0 1 2 3 4 5 6 7
# Random traps
TRAP:random,random
TRAP:random,random
TRAP:random,random
TRAP:random,random
TRAP:random,random
TRAP:random,random
# Monsters on siege duty.
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: ';',"giant eel",random
MONSTER: ';',"shark",random
MONSTER: ';', random, random
MONSTER: 'D',random,random,hostile
MONSTER: 'D',random,random,hostile
MONSTER: 'D',random,random,hostile
MONSTER: 'D',random,random,hostile
MONSTER: 'D',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER[50%]:'H',"hill giant",random,hostile
GEOMETRY:center,center
#0 1 2 3 4 5 6 7
#0123456789012345678901234567890123456789012345678901234567890123456789012345
@ -77,39 +139,39 @@ MONSTER:'@',"attendant",(40,10)
MONSTER:'@',"attendant",(40,11)
MONSTER:'@',"attendant",(40,12)
MONSTER:'@',"nurse",(40,13),peaceful
# Non diggable walls
NON_DIGGABLE:(00,00,75,19)
# Random traps
TRAP:random,random
TRAP:random,random
TRAP:random,random
TRAP:random,random
TRAP:random,random
TRAP:random,random
# Monsters on siege duty.
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: 'r',"rabid rat",random
MONSTER: ';',"giant eel",random
MONSTER: ';',"shark",random
MONSTER: ';', random, random
MONSTER: 'D',random,random,hostile
MONSTER: 'D',random,random,hostile
MONSTER: 'D',random,random,hostile
MONSTER: 'D',random,random,hostile
MONSTER: 'D',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
# Plague victims.
OBJECT:'\\', "bedroll",(34,08),uncursed,2
OBJECT:'\\', "bedroll",(33,08),uncursed,2
OBJECT:'\\', "bedroll",(32,08),uncursed,2
OBJECT:'\\', "bedroll",(31,08),uncursed,2
OBJECT:'\\', "bedroll",(30,08),uncursed,2
OBJECT:'\\', "bedroll",(34,11),uncursed,2
OBJECT:'\\', "bedroll",(33,11),uncursed,2
OBJECT:'\\', "bedroll",(32,11),uncursed,2
OBJECT:'\\', "bedroll",(31,11),uncursed,2
OBJECT:'\\', "bedroll",(30,11),uncursed,2
OBJECT:'\\', "bedroll",(45,09),uncursed,2
OBJECT:'\\', "bedroll",(45,10),uncursed,2
OBJECT:'\\', "bedroll",(45,11),uncursed,2
OBJECT:'\\', "bedroll",(45,12),uncursed,2
OBJECT:'\\', "bedroll",(45,13),uncursed,2
OBJECT:'\\', "bedroll",(43,10),uncursed,2
OBJECT:'\\', "bedroll",(43,11),uncursed,2
OBJECT:'\\', "bedroll",(43,12),uncursed,2
OBJECT:'\\', "bedroll",(43,13),uncursed,2
OBJECT:'\\', "bedroll",(41,09),uncursed,2
OBJECT:'\\', "bedroll",(41,10),uncursed,2
OBJECT:'\\', "bedroll",(41,11),uncursed,2
OBJECT:'\\', "bedroll",(41,12),uncursed,2
#
# The "locate" level for the quest.
#
@ -146,7 +208,13 @@ DOOR:locked,(11,03)
DOOR:locked,(11,06)
# Stairs
STAIR:(04,04),up
STAIR:(20,06),down
STAIR:(19,06),down
# Statue
CONTAINER:'`',"statue",(18,06),uncursed,"Iasoian Archon",5
CONTAINER:'`',"statue",(20,06),uncursed,"Hygieian Archon",5
CONTAINER:'`',"statue",(19,05),uncursed,"Panakeian Archon",5
# Non diggable walls
NON_DIGGABLE:(11,02,21,07)
# Altar in the temple.
@ -212,6 +280,8 @@ MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER:'H',"hill giant",random,hostile
MONSTER[50%]:'H',"hill giant",random,hostile
#
# The "goal" level for the quest.
@ -249,8 +319,26 @@ REGION:(00,00,40,11),lit,"ordinary"
STAIR:(39,10),up
# Non diggable walls
NON_DIGGABLE:(00,00,40,11)
# Objects
# Nemesis
MONSTER:'H',"Cyclops",(20,06),hostile
OBJECT:')',"quarterstaff",(20,06),blessed,0,"The Staff of Aesculapius"
# Plague victims (placed via level loader)
OBJECT: '_', "chain", random
OBJECT: '_', "chain", random
OBJECT: '_', "chain", random
OBJECT: '_', "chain", random
OBJECT: '_', "chain", random
OBJECT: '_', "chain", random
OBJECT: '_', "chain", random
OBJECT: '_', "chain", random
OBJECT: '_', "chain", random
OBJECT: '_', "chain", random
MONSTER:'H',"hill giant",random,hostile
MONSTER:'H',"hill giant",random,hostile
MONSTER:'H',"hill giant",random,hostile
# Objects
OBJECT:'/',"lightning",(20,06)
OBJECT:'(',"trephination kit",random
OBJECT:random,random,random
@ -275,7 +363,6 @@ TRAP:random,random
TRAP:random,random
TRAP:random,random
# Random monsters.
MONSTER:'H',"Cyclops",(20,06),hostile
MONSTER:'r',"rabid rat",random
MONSTER:'r',"rabid rat",random
MONSTER:'r',"rabid rat",random
@ -346,6 +433,8 @@ MONSTER: 'D',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER[75%]:'H',"hill giant",random,hostile
MONSTER[25%]:'H',"hill giant",random,hostile
#
TRAP: random, random
TRAP: random, random
@ -389,6 +478,9 @@ MONSTER: 'D',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER: 'S',random,random,hostile
MONSTER:'H',"hill giant",random,hostile
MONSTER[50%]:'H',"hill giant",random,hostile
MONSTER[50%]:'H',"hill giant",random,hostile
#
TRAP: random, random
TRAP: random, random

View file

@ -229,7 +229,7 @@ LEVEL: "bore4" "none" @ (15, 0)
# A special "x-fill" level must be defined in the levels description
# file. It will be used for all levels not defined explicitly below.
#
DUNGEON: "The Quest" "Q" (5, 2)
DUNGEON: "The Quest" "Q" (5, 3)
LEVEL: "x-strt" "none" @ (1, 1)
LEVEL: "x-loca" "L" @ (3, 1)
LEVEL: "x-goal" "none" @ (-1, 0)

View file

@ -2110,6 +2110,262 @@ the Astral plane. There you must offer the Amulet
to %d."
%E
#
# Drow Healer
#
%Cc Dhl 00001
What sorcery has brought you back to Menzoberranzan?
You thought you had finally escaped from your depraved homeland.
Despair chokes your mind. Why have your companions betrayed you?
The priestesses of Lolth will destroy you for fleeing their mercy.
...Yet, all is not as it should be. You %x the shrieker mushrooms
are feral and hungry, and the scent of disease hangs in the cavern
air.
Perhaps you should seek out Sister T'eirastra, the head of the
mendicant order to which you now belong?
%E
%Cp Dhl 00002
After your last experience you expected to be here, but you certainly
did not expect to see things so much worse. This time you must
succeed.
%E
%Cp Dhl 00003
You have the oddest feeling that this may be the last time you
are to vist %H.
%E
%Cp Dhl 00005
"We were sent by the surface alliance to investigate the Underdark disturbance"
%E
%Cp Dhl 00006
"The demonic incursion has been delt with, but now something drives these kuo-toa against you."
%E
%Cp Dhl 00007
"Lolth has betrayed you!"
%E
%Cp Dhl 00008
"We've occupied as much of the city as possible. Ilmater shall send aid!"
%E
%Cp Dhl 00009
"The dwarf-giants have taken much of the lower levels."
%E
%Cp Dhl 00010
"We must work together to save all our peoples."
%E
%Cp Dhl 00011
"I think a demon lord was behind the attacks."
%E
%Cp Dhl 00012
"Pen'a and Ilmater shall free this city from the webs of Lolth!"
%E
%Cp Dhl 00013
"We're holding as much of the city as possible. Ilmater shall send aid!"
%E
%Cp Dhl 00014
"The dwarf-giants have taken much of the lower levels."
%E
%Cc Dhl 00015
You approach the strange purple frog-creature. He is unlike any
kuo toa you've ever %x, for he exudes an aura of calm
enlightenment.
"Greetings %p, my %S. I am glad to see you whole.
"Though we have never met, the cadence has shown me that you
alone can reverse the great harm that my people have
unleashed on the world.
"Come closer and let me lay hands on you, and determine if you have
the skills necessary to accomplish this mission."
%E
%Cp Dhl 00016
"Again, my %S, you stand before me. Have you improved your skills since
our last meeting?"
%E
%Cp Dhl 00017
"Once more, %p, you have returned. Hopefully %d has been
with you and your skills have improved."
%E
%Cc Dhl 00018
"You have become polluted my %S.
"The cadence has turned away from you. Begon from this place,
inflict no more harm on your %shood. Lolth will be happy to
hear that you are once again practicing your arts on the
unsuspecting, but I hope you will someday find forgiveness."
%E
%Cc Dhl 00019
"Alas, %p, you are yet too inexperienced to deal with the rigors
of such a task. You must be able to draw on the knowledge of botany,
vetenary, and alchemy before I can send you on this quest with good
conscience.
"Return when you wear %Ra's caduceus."
%E
%Cc Dhl 00020
"You have learned much of the remedies that benefit, but you must also
know which physic for which ail. That is why %ds teachings are a
part of your training.
"Return to us when you have healed thyself."
%E
%Cc Dhl 00021
"You are ready. As I said before, a great evil has been unleashed
on the world by my people. With the help of a mad mind flayer and
the Ana'auo, an artifact of healing stolen from your %shood,
they have graven an image of Blibdoolpoolp into the world.
"This plague is the result of Ana'auo's perversion. It now draws
the health from your people in order to power the image of
Blibdoolpoolp.
"You must travel to the slums below Menzoberranzan, recover
the Ana'auo, and put an end to this monstrosity. Be careful."
%E
%Cp Dhl 00025
"Go with %d as your guide, %p."
%E
%Cp Dhl 00026
"Beware the water-magic of Blibdoolpoolp."
%E
%Cp Dhl 00027
"Be pure, my %S."
%o."
%E
%Cp Dhl 00028
"Remember your studies, and you will prevail!"
%E
%Cp Dhl 00029
"Remember this, %n can twist the powers of the Ana'auo to hurt instead of heal."
%E
%Cp Dhl 00030
"Call upon %d when your need is greatest. You will be answered."
%E
%Cp Dhl 00031
"You will face many foes. Consider well the strengths of each!"
%E
%Cp Dhl 00032
"The plague grows worse as we speak. Hurry, %p!"
%E
%Cp Dhl 00033
"I fear that which drives the cult of 'Y' will move against
you if you tary."
%E
%Cp Dhl 00034
"Reclaim the Ana'auo as soon as possible. Blibdoolpoolp may prove immortal otherwise."
%E
%Cc Dhl 00035
You have nearly reached %i, where the commoners live.
Screams, shouts, and the smell of sickness fill the air.
You fear that whatever suffering was felt by the nobles
has been visited a hundredfold upon the commoners.
%E
%Cp Dhl 00036
Once again you approach the %i.
%E
%Cc Dhl 00040
You sense that you have reached the ritual site. You must find
the perpetrators of this madness.
Steeling yourself against the wails of the ill that pierce your ears,
you hurry on your task. Maybe with the Ana'auo you can heal them on
your return, but not now.
%E
%Cp Dhl 00041
Once again, you have reached the ritual site.
%E
%Cc Dhl 00050
"Plib! Blip! Blibdoolpoolp! Plip! Blib! Blibdoolpoolp!"
%E
%Cp Dhl 00051
"Burblipahgug!"
%E
%Cp Dhl 00052
"Blubruploopl!"
%E
%Cp Dhl 00053
"Chchchchchshshhhhh!"
%E
%Cp Dhl 00060
"Glubarub!"
%E
%Cp Dhl 00061
"Bloopblorborbdor!"
%E
%Cp Dhl 00062
"Blorpblooboolflp!"
%E
%Cp Dhl 00063
"Glackdakk!"
%E
%Cp Dhl 00064
"Bloogagadool!"
%E
%Cp Dhl 00065
"Gloopglop!"
%E
%Cp Dhl 00066
"Drip. Drop."
%E
%Cp Dhl 00067
"Dumoogoolgoorn! Dumoogoolgoorn!"
%E
%Cp Dhl 00068
"Loolooploop! Blibloolooploop!"
%E
%Cp Dhl 00069
"Voonroondoo."
%E
%Cc Dhl 00070
This double sword has been crudely fashioned by fusing the
hilts of two long swords together with a pair of claw-ended
shackles. Your heart sinks as you recognize the melted
remnants of the Ana'auo.
As you pick up the swordstaff, though, you feel its healing
begin to warm your soul. You breathe a sigh of relief as it
does, for it seems the Ana'auo still functions despite
the frightful, half-seen muatations wrought upon it by
the imaginations of the kuo toa.
%E
%Cc Dhl 00080
The battered body of %n slumps to the ground and rots to a
putrescent puddle, separating into its constituent parts
as it does.
%E
%Cc Dhl 00081
As soon as %l sees %o he summons your %ss.
Gently, %l reaches out and touches %o.
He instructs each of the assembled to do the same. When everyone
has finished he speaks to you.
Now that we have been replenished we can defeat this plague. You must
take %o with you and replenish the worlds you have
been called upon to travel next. It seems my people have imagined
a great and holy weapon. Use it well.
%E
%Cc Dhl 00082
%l cautiously handles %o while watching you.
"You are its keeper now, and the time has come to resume your search
for the Amulet. %Z await your return through the
magic portal which brought you here."
%E
%Cp Dhl 00090
"You have again returned to us, %p. We have done well in your
absence, yes? How fare you upon your quest for the Amulet?"
%E
%Cc Dhl 00091
"Ah, you have recovered the Amulet, %p. Well done!
"Now, you should know that you must travel through the Elemental Planes
to the Astral, and there return the Amulet to %d. Go forth and
may our prayers be as a wind upon your back."
%E
#
# Drow general quest
#
%Cc Dro 00001

View file

@ -301,6 +301,7 @@ struct artinstance{
#define PlagueDuration avar1
#define IMAlitness avar1
#define LeagueMod avar1
#define Esscoo_mid avar1
long avar2;
#define SnSd2 avar2
#define RoSPflights avar2
@ -407,6 +408,7 @@ extern struct artifact * artilist;
#define DETESTATION (LAST_PROP+85)
#define INVULNERABILITY (LAST_PROP+86)
#define IBITE_ARM (LAST_PROP+87)
#define LOOT_SELF (LAST_PROP+88)
#define MASTERY_ARTIFACT_LEVEL 20
@ -472,7 +474,7 @@ extern struct artifact * artilist;
/* artifact has no specific material or size, eg "silver Grimtooth" */
#define is_malleable_artifact(a) (is_nameable_artifact((a)) || (a) == &artilist[ART_EXCALIBUR] || (a) == &artilist[ART_GUNGNIR] || (a) == &artilist[ART_DIRGE])
#define is_living_artifact(obj) ((obj)->oartifact == ART_TENTACLE_ROD || (obj)->oartifact == ART_DRAGONHEAD_SHIELD || (obj)->oartifact == ART_CRUCIFIX_OF_THE_MAD_KING || (obj)->oartifact == ART_RITUAL_RINGED_SPEAR || (obj)->oartifact == ART_RINGED_BRASS_ARMOR || (obj)->oartifact == ART_IBITE_ARM)
#define is_living_artifact(obj) ((obj)->oartifact == ART_TENTACLE_ROD || (obj)->oartifact == ART_DRAGONHEAD_SHIELD || (obj)->oartifact == ART_CRUCIFIX_OF_THE_MAD_KING || (obj)->oartifact == ART_RITUAL_RINGED_SPEAR || (obj)->oartifact == ART_RINGED_BRASS_ARMOR || (obj)->oartifact == ART_IBITE_ARM || (obj)->oartifact == ART_ESSCOOAHLIPBOOURRR)
#define is_bloodthirsty_artifact(obj) (arti_is_prop(obj, ARTI_BLOODTHRST) && roll_generic_flat_madness(FALSE))
#define is_mastery_artifact_nameable(a) (\

View file

@ -2367,6 +2367,17 @@ A("The Cloak of the Consort", DROVEN_CLOAK, (const char *)0,
NOINVOKE, NOFLAG
),
/*Needs encyc entry*/
A("Esscooahlipboourrr", DOUBLE_SWORD, "tentacle-auraed shackle-wrapped %s",
4000L, MT_DEFAULT, MZ_DEFAULT, WT_DEFAULT,
A_NEUTRAL, PM_HEALER, PM_DROW, TIER_S, (ARTG_NOGEN|ARTG_MAJOR|ARTG_FXALGN),
NO_MONS(),
ATTK(AD_PHYS, 20, 10), (ARTA_DRAIN),
PROPS(DRAIN_RES, SEARCHING), (ARTP_SEEK),
PROPS(), NOFLAG,
LOOT_SELF, NOFLAG
),
/*Needs encyc entry*/
A("Painting Fragment", SCR_BLANK_PAPER, "scroll fragment",
200L, CLOTH, MZ_DEFAULT, WT_DEFAULT,

View file

@ -66,6 +66,11 @@ typedef struct dungeon { /* basic dungeon identifier */
int dunlev_ureturn; /* where should you return to in this dungeon? */
int ledger_start, /* the starting depth in "real" terms */
depth_start; /* the starting depth in "logical" terms */
char connect_side[7];/* for fancy quests like drow healer. What level sides are connected? */
#define CON_UNSPECIFIED 0
#define CONNECT_LEFT 1
#define CONNECT_CENT 2
#define CONNECT_RGHT 3
} dungeon;
/*

View file

@ -166,17 +166,18 @@ struct engr {
#define GHAUNADAUR_SYMBOL 40
#define LOST_HOUSE 41
#define EDDER_SYMBOL 42
#define Y_CULT_SYMBOL 43
#define LAST_DROW_SYM EDDER_SYMBOL
#define LAST_DROW_SYM Y_CULT_SYMBOL
#define FOOTPRINT 43
#define HOOFPRINT 44
#define FOOTPRINT 44
#define HOOFPRINT 45
#define FIRST_PLANE_SYMBOL 45
#define LAST_PLANE_SYMBOL 60
#define FIRST_PLANE_SYMBOL 46
#define LAST_PLANE_SYMBOL 61
#define CLAW_MARKS 61
#define CLAW_MARKS 62
xchar halu_ward; /* If you draw while halucinating, you inscribe a halucinatory symbol */

View file

@ -78,6 +78,7 @@ E int NDECL(partial_action);
E int NDECL(check_partial_action);
E int FDECL(check_res_engine, (struct monst *, int));
E void FDECL(add_class, (char *, char));
E boolean FDECL(set_obj_shape, (struct obj *, long));
E void FDECL(salve_effect, (struct obj *));
/* ### artifact.c ### */
@ -493,7 +494,7 @@ E void NDECL(save_currentstate);
#endif
E void FDECL(goto_level, (d_level *,BOOLEAN_P,BOOLEAN_P,int));
E void FDECL(schedule_goto, (d_level *,BOOLEAN_P,BOOLEAN_P,int,
const char *,const char *));
const char *,const char *,int));
E void NDECL(deferred_goto);
E boolean FDECL(revive_corpse, (struct obj *, int));
E void FDECL(revive_mon, (genericptr_t, long));
@ -633,6 +634,7 @@ E void FDECL(doliving_ringed_armor, (struct monst *, struct obj *, boolean));
E void FDECL(doliving_ibite_arm, (struct monst *, struct obj *, boolean));
E void FDECL(doliving_healing_armor, (struct monst *, struct obj *, boolean));
E void FDECL(doliving_armor_salve, (struct monst *, struct obj *));
E void FDECL(dotsmi_theft, (struct monst *, struct monst *, struct obj *, struct obj *));
/* ### dog.c ### */
@ -667,6 +669,7 @@ E boolean FDECL(acceptable_pet_target, (struct monst *,struct monst *,BOOLEAN_P)
E boolean FDECL(betrayed, (struct monst *));
E int FDECL(dog_nutrition, (struct monst *,struct obj *));
E int FDECL(dog_eat, (struct monst *,struct obj *,int,int,BOOLEAN_P));
E void FDECL(give_mon_corpse_intrinsic, (struct monst *,int));
E int FDECL(monster_eat, (struct monst *,struct obj *,int,int,BOOLEAN_P));
E int FDECL(dog_move, (struct monst *,int));
#ifdef USE_TRAMPOLI
@ -832,6 +835,7 @@ E void FDECL(food_substitution, (struct obj *,struct obj *));
E boolean FDECL(bite_monster, (struct monst *));
E void FDECL(give_intrinsic, (int, long));
E void NDECL(fix_petrification);
E int FDECL(intrinsic_possible, (int,struct permonst *));
E void FDECL(consume_oeaten, (struct obj *,int));
E int FDECL(obj_nutrition, (struct obj *));
E boolean FDECL(maybe_finished_meal, (BOOLEAN_P));
@ -856,6 +860,7 @@ E void VDECL(panic, (const char *,...)) PRINTF_F(1,2);
E const char* NDECL(get_alignment_code);
E const char* NDECL(get_alignment_adj);
E boolean NDECL(Check_crystal_lifesaving);
E boolean NDECL(Check_iaso_lifesaving);
E void FDECL(done, (int));
E void FDECL(container_contents, (struct obj *,BOOLEAN_P,BOOLEAN_P));
#ifdef DUMP_LOG
@ -939,6 +944,7 @@ E long FDECL(rndexp, (BOOLEAN_P));
/* ### explode.c ### */
E void FDECL(explode, (int,int,int,int,int,int,int));
E void FDECL(explode_pa, (int,int,int,int,int,int,int,struct permonst *));
E void FDECL(explode_yours, (int,int,int,int,int,int,int,boolean));
E void FDECL(splash, (int,int,int,int,int,int,int,int));
E long FDECL(scatter, (int, int, int, unsigned int, struct obj *, long *, struct monst *));
@ -1232,6 +1238,7 @@ E struct obj *NDECL(getnextgetobj);
#ifdef SORTLOOT
E int FDECL(sortloot_cmp, (struct obj *, struct obj *));
#endif
E int FDECL(mon_healing_penalty, (struct monst *));
E int NDECL(u_healing_penalty);
E int NDECL(u_clothing_discomfort);
E struct obj * FDECL(outermost_armor, (struct monst *));
@ -1559,6 +1566,7 @@ E void FDECL(dealloc_obj, (struct obj *));
E int FDECL(hornoplenty, (struct obj *, boolean));
E void FDECL(obj_ice_effects, (int, int, BOOLEAN_P));
E long FDECL(peek_at_iced_corpse_age, (struct obj *));
E void FDECL(size_and_shape_to_fit, (struct obj *, struct monst *));
E void FDECL(doMaskStats, (struct obj *));
#ifdef WIZARD
E void NDECL(obj_sanity_check);
@ -1570,11 +1578,13 @@ E boolean FDECL(isspacious, (struct mkroom *));
E void NDECL(mksepulcher);
E void NDECL(mkmivault);
E void FDECL(mkmivaultitem,(struct obj *));
E struct obj * NDECL(mkjewel);
E struct obj * NDECL(mklolthvaultitem);
E struct obj * FDECL(mkhellvaultitem,(int));
E void FDECL(mkhellvaultitem_cnt,(struct obj *, int, boolean));
E void NDECL(place_lolth_vaults);
E void NDECL(place_chaos_forest_features);
E void NDECL(place_drow_healer_features);
E void NDECL(place_law_features);
E void NDECL(place_neutral_features);
E void NDECL(place_sum_all_features);
@ -1787,6 +1797,7 @@ E void FDECL(timeout_problems, (struct monst *));
E int FDECL(dochugw, (struct monst *));
E boolean FDECL(onscary, (int,int,struct monst *));
E void FDECL(monflee, (struct monst *, int, BOOLEAN_P, BOOLEAN_P));
E void FDECL(dracae_eladrin_spawn_equip, (struct monst *, int));
E int FDECL(dochug, (struct monst *));
E int FDECL(m_move, (struct monst *,int));
E void FDECL(break_iron_bars, (int, int, boolean));
@ -1881,7 +1892,7 @@ E int FDECL(set_destroy_thrown, (int));
//E int FDECL(breamu, (struct monst *,struct attack *));
//E int FDECL(breamm, (struct monst *,struct monst *,struct attack *));
E boolean FDECL(mtarget_adjacent, (struct monst *));
E struct monst *FDECL(mfind_target, (struct monst *, int));
E struct monst *FDECL(mfind_target, (struct monst *, boolean, boolean));
E boolean FDECL(linedup, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
E boolean FDECL(lined_up, (struct monst *));
E int FDECL(m_pole_range, (struct monst *));
@ -2183,6 +2194,7 @@ E void FDECL(open_coffin, (struct obj *, BOOLEAN_P));
E void FDECL(open_sarcophagus, (struct obj *, BOOLEAN_P));
E void FDECL(open_crazy_box, (struct obj *, BOOLEAN_P));
E boolean FDECL(open_madstuff_box, (struct obj *, BOOLEAN_P));
E void FDECL(open_giants_sack, (struct obj *, BOOLEAN_P));
#ifdef GOLDOBJ
E int FDECL(collect_obj_classes,
(char *,struct obj *,BOOLEAN_P,boolean FDECL((*),(OBJ_P)), int *));
@ -2314,6 +2326,7 @@ E boolean FDECL(can_pray, (BOOLEAN_P));
E int NDECL(dopray);
E const char *NDECL(u_gname);
E int NDECL(doturn);
E int FDECL(mon_doturn, (struct monst *));
E const char *NDECL(a_gname);
E const char *FDECL(a_gname_at, (XCHAR_P x,XCHAR_P y));
E const char *FDECL(align_gname, (ALIGNTYP_P));
@ -2441,7 +2454,7 @@ E void NDECL(unpunish);
E boolean FDECL(cant_create, (int *, BOOLEAN_P));
#ifdef WIZARD
E int NDECL(wiz_kill_all);
E struct monst * FDECL(create_particular, (unsigned long, int, int, unsigned long, unsigned long, int));
E struct monst * FDECL(create_particular, (int, int, unsigned long, int, int, unsigned long, unsigned long, int, char *));
#endif
/* ### rect.c ### */
@ -2775,6 +2788,9 @@ E int NDECL(throwgaze);
E int NDECL(dovspell);
E int NDECL(base_casting_stat);
E void FDECL(initialspell, (struct obj *));
E void FDECL(initialforgotwizardspells, (int));
E void FDECL(initialforgotpriestspells, (int));
E void FDECL(initialforgotspell, (int));
E void FDECL(initialward, (struct obj *));
E void FDECL(set_spirit_powers, (long));
E int NDECL(reorder_spirit_powers);
@ -3247,6 +3263,7 @@ E void FDECL(genl_preference_update, (const char *));
E void NDECL(amulet);
E int FDECL(mon_has_amulet, (struct monst *));
E int FDECL(mon_has_special, (struct monst *));
E boolean FDECL(mon_has_arti, (struct monst *,SHORT_P));
E int FDECL(tactics, (struct monst *));
E void NDECL(aggravate);
E void NDECL(clonewiz);

View file

@ -214,6 +214,7 @@ GOD_V2("Thoth", A_NEUTRAL, NEUTRAL_HOLINESS,
GOD_V2("Anhur", A_CHAOTIC, UNHOLY_HOLINESS,
MINIONS(PM_VROCK,PM_MARILITH,PM_ANUBITE,PM_AMMIT)
),
/*Note: Orome is assumed to be first elf god*/
/* elf ranger */
GOD_V2("Orome", A_LAWFUL, HOLY_HOLINESS,
MINIONS(PM_PLAINS_CENTAUR,PM_FOREST_CENTAUR,PM_MOUNTAIN_CENTAUR,PM_HUNTER,PM_TITAN)
@ -244,6 +245,7 @@ GOD_V2("Mandos", A_NEUTRAL, HOLY_HOLINESS,
GOD_V2("Lorien", A_CHAOTIC, HOLY_HOLINESS,
MINIONS(Cangels)
),
/*Note: Lorien is assumed to be last elf god*/
/* anachrononaut */
GOD_V2("_Ilsensine", A_LAWFUL, UNHOLY_HOLINESS,
MINIONS(PM_MIND_FLAYER,PM_BRAIN_GOLEM,PM_SEMBLANCE,PM_MASTER_MIND_FLAYER)

View file

@ -143,6 +143,7 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
(u.sealsActive&SEAL_PAIMON && is_magical((mon)->data)) || \
(u.sealsActive&SEAL_ANDROMALIUS && is_thief((mon)->data)) || \
(u.sealsActive&SEAL_TENEBROUS && !nonliving(mon->data)) || \
(P_SKILL(P_BEAST_MASTERY) > P_ISRESTRICTED && mon->mtame && distmin(u.ux, u.uy, mon->mx, mon->my) <= (P_SKILL(P_BEAST_MASTERY) - P_ISRESTRICTED)) || \
(Upolyd && youmonst.data->mtyp == PM_SHARK && has_blood((mon)->data) && \
(mon)->mhp < (mon)->mhpmax && is_pool(u.ux, u.uy, TRUE) && is_pool((mon)->mx, (mon)->my, TRUE)) || \
(u.specialSealsActive&SEAL_ACERERAK && is_undead(mon->data)) || \
@ -169,8 +170,9 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
)
#define Weightless (Is_airlevel(&u.uz) || \
(Is_lolth_level(&u.uz) && levl[u.ux][u.uy].typ == CLOUD) || \
(Role_if(PM_MADMAN) && In_quest(&u.uz) && (levl[u.ux][u.uy].typ == AIR || levl[u.ux][u.uy].typ == CLOUD)))
(Is_lolth_level(&u.uz) && levl[u.ux][u.uy].typ == CLOUD) \
|| (Role_if(PM_MADMAN) && In_quest(&u.uz) && (levl[u.ux][u.uy].typ == CLOUD)) \
|| (!In_endgame(&u.uz) && levl[u.ux][u.uy].typ == AIR))
#include "trap.h"
#include "flag.h"

View file

@ -227,11 +227,12 @@
#define AD_PERH 147 /* "Per-Hit-Die damage (x damage per HD of the defender, be careful with damage die size!) */
#define AD_SVPN 148 /* Severe poison that partially pierces poison resistance */
#define AD_HLUH 149 /* Holy/Unholy energy (MM-stype damage not resisted by MR and doubled against both holy- and unholy-haters) */
#define AD_TSMI 150 /* Tentacles Steal Magic Items */
//#define AD_AHAZU 116 /* */
//Amon is a headbutt (AT_BUTT/AD_PHYS)
//Chupoclops is a poisonous bite (AT_BITE/AD_DRST)
#define AD_DUNSTAN 150
#define AD_DUNSTAN 151
#define AD_IRIS AD_DUNSTAN+1
#define AD_NABERIUS AD_DUNSTAN+2
#define AD_OTIAX AD_DUNSTAN+3

View file

@ -18,6 +18,7 @@
#define pm_resistance(ptr,typ) (((ptr)->mresists & (typ)) != 0)
#define mon_intrinsic(mon,typ) (((mon)->mintrinsics[((typ)-1)/32] & (0x1L << ((typ)-1)%32)) != 0)
#define mon_extrinsic(mon,typ) (((mon)->mextrinsics[((typ)-1)/32] & (0x1L << ((typ)-1)%32)) != 0)
#define mon_acquired_trinsic(mon,typ) (((mon)->acquired_trinsics[((typ)-1)/32] & (0x1L << ((typ)-1)%32)) != 0)
#define mon_resistance(mon,typ) (mon_intrinsic(mon,typ) || mon_extrinsic(mon,typ) || (typ == SWIMMING && Is_waterlevel(&u.uz)) || (typ == TELEPORT && mad_monster_turn(mon, MAD_NON_EUCLID) && !(mon)->mpeaceful) || (typ == TELEPORT_CONTROL && mad_monster_turn(mon, MAD_NON_EUCLID)))
#define species_resists_fire(mon) (((mon)->data->mresists & MR_FIRE) != 0)
@ -375,6 +376,14 @@
(ptr)->mtyp == PM_UNEARTHLY_DROW ||\
(ptr)->mtyp == PM_STINKING_CLOUD ||\
(ptr)->mtyp == PM_DEMONIC_BLACK_WIDOW)
#define is_duergar(ptr) ((ptr)->mtyp == PM_DUERGAR ||\
(ptr)->mtyp == PM_GIANT_DUERGAR ||\
(ptr)->mtyp == PM_DUERGAR_STONEGUARD ||\
(ptr)->mtyp == PM_GIANT_STONEGUARD ||\
(ptr)->mtyp == PM_DUERGAR_DEBILITATOR ||\
(ptr)->mtyp == PM_DUERGAR_ANNIHILATOR)
#define is_kuo_toa(ptr) ((ptr)->mtyp == PM_KUO_TOA ||\
(ptr)->mtyp == PM_KUO_TOA_WHIP)
#define is_vampire(ptr) (((ptr)->mflagsa & MA_VAMPIRE) != 0L)
#define is_half_dragon(ptr) attacktype_fordmg(ptr, AT_BREA, AD_HDRG)
#define is_boreal_dragoon(ptr) (attacktype_fordmg(ptr, AT_WEAP, AD_HDRG) || attacktype_fordmg(ptr, AT_XWEP, AD_HDRG))
@ -533,6 +542,11 @@
|| (ptr)->mtyp == PM_WANDERING_HORROR\
|| (ptr)->mtyp == PM_NAMELESS_HORROR\
)
#define is_chuul(ptr) ( (ptr)->mtyp == PM_CHUUL \
|| (ptr)->mtyp == PM_ELDER_CHUUL \
|| (ptr)->mtyp == PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION \
|| (ptr)->mtyp == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH \
)
#define is_mercenary(ptr) (((ptr)->mflagsg & MG_MERC) != 0L)
#define is_army_pm(pm) (pm == PM_CAPTAIN || pm == PM_LIEUTENANT || pm == PM_SERGEANT || pm == PM_SOLDIER)
#define is_bardmon(ptr) ((ptr)->mtyp == PM_LILLEND || (ptr)->mtyp == PM_RHYMER || (ptr)->mtyp == PM_BARD)
@ -557,7 +571,7 @@
#define is_tailslap_mon(mon) (is_tailslap_mtyp((mon)->data))
#define is_vines_mon(mon) ((mon)->mtyp == PM_GAE_ELADRIN && (mon)->m_lev >= 20)
#define is_star_blades_mtyp(ptr) ((ptr)->mtyp == PM_COURE_ELADRIN || (ptr)->mtyp == PM_MOTE_OF_LIGHT)
#define is_star_blades_mtyp(ptr) ((ptr)->mtyp == PM_COURE_ELADRIN || (ptr)->mtyp == PM_MOTE_OF_LIGHT || (ptr)->mtyp == PM_IASOIAN_ARCHON)
#define is_star_blades_mon(mon) (is_star_blades_mtyp((mon)->data))
#define is_storm_mtyp(ptr) ((ptr)->mtyp == PM_DAO_LAO_GUI_MONK)
#define is_level_storm_mtyp(ptr) ((ptr)->mtyp == PM_CAILLEA_ELADRIN || (ptr)->mtyp == PM_MOONSHADOW\
@ -630,7 +644,15 @@
|| has_template(magr, TOMB_HERD)\
|| has_template(magr, SLIME_REMNANT)\
)
#define always_one_hand_mtyp(ptr) (ptr->mtyp == PM_THRONE_ARCHON \
|| ptr->mtyp == PM_OCCULTIST \
|| ptr->mtyp == PM_LUNGORTHIN \
|| ptr->mtyp == PM_BASTARD_OF_THE_BOREAL_VALLEY \
|| ptr->mtyp == PM_GUG \
|| ptr->mtyp == PM_Y_CULTIST_MATRON \
|| ptr->mtyp == PM_Y_CULTIST_PATRON \
|| ptr->mtyp == PM_DEMOGORGON \
)
#define always_hostile(ptr) (((ptr)->mflagst & MT_HOSTILE) != 0L)
#define always_hostile_mon(mon) (always_hostile((mon)->data))
#define always_peaceful(ptr) (((ptr)->mflagst & MT_PEACEFUL) != 0L)
@ -719,11 +741,15 @@
#define arm_size_fits(ptr,obj) (Is_dragon_scales(obj) || \
obj->objsize == (ptr)->msize || \
(is_elven_armor(obj) && abs(obj->objsize - (ptr)->msize) <= 1))
#define arm_match(ptr,obj) (Is_dragon_scales(obj) || \
#define arm_match(ptr,obj) (Is_dragon_scales(obj) || obj->otyp == WAISTCLOTH ||\
((obj->otyp == ELVEN_TOGA || obj->otyp == NOBLE_S_DRESS || obj->otyp == GENTLEWOMAN_S_DRESS) && upper_body_match(ptr,obj)) ||\
(ptr->mtyp == PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION && upper_body_match(ptr,obj)) ||\
(full_body_match(ptr,obj)))
#define full_body_match(ptr,obj) (((ptr->mflagsb&MB_BODYTYPEMASK) != 0) && \
((ptr->mflagsb&MB_BODYTYPEMASK) == (obj->bodytypeflag&MB_BODYTYPEMASK)))
#define boots_size_fits(ptr,obj) (ptr->mtyp == PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION ? \
(ptr->msize+1 == obj->objsize) : \
(ptr->msize == obj->objsize))
#define can_wear_gloves(ptr) (!nogloves(ptr) && !nohands(ptr))
#define can_wear_amulet(ptr) (has_head(ptr) || (ptr->mflagsb&MB_CAN_AMULET))
#define can_wear_blindf(ptr) (has_head(ptr))
@ -732,8 +758,10 @@
full_body_match(ptr,obj))
#define upper_body_match(ptr,obj) (((ptr->mflagsb&MB_HUMANOID) && (obj->bodytypeflag&MB_HUMANOID)) || \
(((ptr->mflagsb&MB_BODYTYPEMASK) != 0) && ((ptr->mflagsb&MB_BODYTYPEMASK) == (obj->bodytypeflag&MB_BODYTYPEMASK))))
#define helm_match(ptr,obj) (((ptr->mflagsb&MB_HEADMODIMASK) == (obj->bodytypeflag&MB_HEADMODIMASK)))
#define helm_match(ptr,obj) ((!has_horns(ptr) || obj->otyp == find_gcirclet() || is_flimsy(obj)) && \
(is_hat(obj) || (has_head(ptr) && (ptr->mflagsb&MB_HEADMODIMASK) == (obj->bodytypeflag&MB_HEADMODIMASK))))
/*Note: No-modifier helms are "normal"*/
#define helm_size_fits(ptr,obj) (obj->objsize == ptr->msize || (is_hat(obj) && obj->objsize <= ptr->msize))
#define hates_holy_mon(mon) ((mon) == &youmonst ? hates_holy(youracedata) : hates_holy((mon)->data))
#define hates_holy(ptr) (is_demon(ptr) || is_undead(ptr) || (((ptr)->mflagsg&MG_HATESHOLY) != 0))
@ -948,6 +976,7 @@
#define is_mind_flayer(ptr) ((ptr)->mtyp == PM_MIND_FLAYER || \
(ptr)->mtyp == PM_MASTER_MIND_FLAYER || \
(ptr)->mtyp == PM_STAR_SPAWN || \
(ptr)->mtyp == PM_MAD_GRAZI || \
(ptr)->mtyp == PM_PARASITIZED_ANDROID || \
(ptr)->mtyp == PM_PARASITIZED_GYNOID || \
(ptr)->mtyp == PM_PARASITIC_MIND_FLAYER || \
@ -1074,29 +1103,53 @@
#define is_elemental(ptr) ( (ptr->mflagsa & MA_ELEMENTAL) )
#define mon_archeologist(mon) ((mon)->mtyp == PM_ARCHEOLOGIST || (mon)->mtyp == PM_LORD_CARNARVON || (mon)->mtyp == PM_STUDENT || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_ARCHEOLOGIST)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_ARCHEOLOGIST))
#define mon_anachrononaut(mon) ((mon)->mtyp == PM_ANACHRONONAUT || (mon)->mtyp == PM_TROOPER || is_myrkalfr(mon) || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_ANACHRONONAUT)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_ANACHRONONAUT))
#define mon_barbarian(mon) ((mon)->mtyp == PM_BARBARIAN || (mon)->mtyp == PM_HALF_DRAGON || (mon)->mtyp == PM_ORC_WARCHIEF || \
(mon)->mtyp == PM_CHIEFTAIN || (mon)->mtyp == PM_ORC_WARRIOR || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_BARBARIAN)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_BARBARIAN))
#define mon_bard(mon) ((mon)->mtyp == PM_BARD || (mon)->mtyp == PM_PINDAR || (mon)->mtyp == PM_RHYMER || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_BARD)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_BARD))
#define mon_caveman(mon) ((mon)->mtyp == PM_CAVEMAN || (mon)->mtyp == PM_CAVEWOMAN || (mon)->mtyp == PM_SHAMAN_KARNOV || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_CAVEMAN)) || \
(mon)->mtyp == PM_NEANDERTHAL || ((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_CAVEMAN))
#define mon_convict(mon) ((mon)->mtyp == PM_CONVICT || (mon)->mtyp == PM_ROBERT_THE_LIFER || (mon)->mtyp == PM_INMATE || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_CONVICT)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_CONVICT))
#define mon_undead_hunter(mon) (((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_HUNTER))
#define mon_knight(mon) ((mon)->mtyp == PM_KNIGHT || (mon)->mtyp == PM_KING_ARTHUR || (mon)->mtyp == PM_SIR_GARLAND || \
(mon)->mtyp == PM_GARLAND || (mon)->mtyp == PM_CELEBORN || (mon)->mtyp == PM_DANTRAG || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_KNIGHT)) || \
(mon)->mtyp == PM_PAGE || ((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_KNIGHT))
#define mon_turn_undead(mon) ((mon)->mtyp == PM_KNIGHT || (mon)->mtyp == PM_KING_ARTHUR || \
(mon)->mtyp == PM_PYROCLASTIC_VORTEX || (mon)->mtyp == PM_BRIGHID_ELADRIN || \
(mon)->mtyp == PM_DRACAE_ELADRIN || \
(mon)->mtyp == PM_KUKER || (mon)->mtyp == PM_SHIELD_ARCHON || \
(mon)->mtyp == PM_MONADIC_DEVA || \
(mon)->mtyp == PM_ALRUNES || (mon)->mtyp == PM_HATEFUL_WHISPERS || \
(mon)->mtyp == PM_ELF_LORD || (mon)->mtyp == PM_ELVENKING || \
(mon)->mtyp == PM_CELEBORN || (mon)->mtyp == PM_DANTRAG || \
(mon)->mtyp == PM_ARIANNA || (mon)->mtyp == PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION || \
(mon)->mtyp == PM_REBEL_RINGLEADER || (mon)->mtyp == PM_RADIANT_PYRAMID || \
(mon)->mtyp == PM_SIR_ALJANOR || (mon)->mtyp == PM_ALLIANCE_VANGUARD || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_KNIGHT)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_KNIGHT))
#define mon_healing_turn(mon) ((mon)->mtyp == PM_DRACAE_ELADRIN)
#define mon_monk(mon) ((mon)->mtyp == PM_MONK || (mon)->mtyp == PM_GRAND_MASTER || (mon)->mtyp == PM_MASTER_KAEN || (mon)->mtyp == PM_ABBOT || \
(mon)->mtyp == PM_XORN_MONK || (mon)->mtyp == PM_DAO_LAO_GUI_MONK || (mon)->mtyp == PM_ZHI_REN_MONK || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_MONK)) || \
(mon)->mtyp == PM_XUENU_MONK || ((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_MONK))
#define mon_madman(mon) ((mon)->mtyp == PM_MADMAN || (mon)->mtyp == PM_MADWOMAN || (mon)->mtyp == PM_CASSILDA_THE_IRON_MAIDEN || \
(mon)->mtyp == PM_PATIENT || (mon)->mtyp == PM_CONTAMINATED_PATIENT || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_MADMAN)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_MADMAN))
#define mon_pirate(mon) ((mon)->mtyp == PM_PIRATE || (mon)->mtyp == PM_MAYOR_CUMMERBUND || (mon)->mtyp == PM_BLACKBEARD_S_GHOST || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_PIRATE)) || \
(mon)->mtyp == PM_PIRATE_BROTHER || ((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_PIRATE))
#define mon_priest(mon) ((mon)->mtyp == PM_PRIEST || (mon)->mtyp == PM_PRIESTESS ||\
(mon)->mtyp == PM_ECLAVDRA || (mon)->mtyp == PM_GALADRIEL || (mon)->mtyp == PM_MOTHER ||\
@ -1105,18 +1158,27 @@
(mon)->mtyp == PM_STJARNA_ALFR || (mon)->mtyp == PM_SISTER || (mon)->mtyp == PM_ACOLYTE || \
(mon)->mtyp == PM_PRIEST_OF_GHAUNADAUR || (mon)->mtyp == PM_DWARF_CLERIC || (mon)->mtyp == PM_DWARF_QUEEN || \
(mon)->mtyp == PM_ELVENKING || (mon)->mtyp == PM_ELVENQUEEN || (mon)->mtyp == PM_MILITANT_CLERIC || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_PRIEST)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_PRIEST))
#define mon_ranger(mon) ((mon)->mtyp == PM_RANGER || (mon)->mtyp == PM_ORION || (mon)->mtyp == PM_HALF_ELF_RANGER || (mon)->mtyp == PM_HUNTER || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_RANGER)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_RANGER))
#define mon_rogue(mon) ((mon)->mtyp == PM_ROGUE || (mon)->mtyp == PM_MASTER_OF_THIEVES || ((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_ROGUE))
#define mon_rogue(mon) ((mon)->mtyp == PM_ROGUE || (mon)->mtyp == PM_MASTER_OF_THIEVES || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_ROGUE)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_ROGUE))
#define mon_samurai(mon) ((mon)->mtyp == PM_SAMURAI || (mon)->mtyp == PM_LORD_SATO || (mon)->mtyp == PM_ASHIKAGA_TAKAUJI || (mon)->mtyp == PM_ROSHI || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_SAMURAI)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_SAMURAI))
#define mon_tourist(mon) ((mon)->mtyp == PM_TOURIST || (mon)->mtyp == PM_TWOFLOWER || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_TOURIST)) || \
((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_TOURIST))
#define mon_valkyrie(mon) ((mon)->mtyp == PM_VALKYRIE || (mon)->mtyp == PM_WARRIOR || ((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_VALKYRIE))
#define mon_valkyrie(mon) ((mon)->mtyp == PM_VALKYRIE || (mon)->mtyp == PM_AWAKENED_VALKYRIE || (mon)->mtyp == PM_TRANSCENDENT_VALKYRIE || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_VALKYRIE)) || \
(mon)->mtyp == PM_WARRIOR || ((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_VALKYRIE))
#define mon_wizard(mon) ((mon)->mtyp == PM_WIZARD || (mon)->mtyp == PM_WORM_THAT_WALKS || (mon)->mtyp == PM_INCANTIFIER || \
(mon)->mtyp == PM_NEFERET_THE_GREEN || (mon)->mtyp == PM_NIMUNE || (mon)->mtyp == PM_ADVENTURING_WIZARD || \
(mon)->mtyp == PM_HEDROW_MASTER_WIZARD || (mon)->mtyp == PM_GROMPH || (mon)->mtyp == PM_GUIDE || \
((mon)->mtyp == PM_HOD_SEPHIRAH && Role_if(PM_WIZARD)) || \
(mon)->mtyp == PM_APPRENTICE || ((mon)->mtyp == PM_DEMINYMPH && (mon)->mvar_deminymph_role == PM_WIZARD))
#define likes_swamp(ptr) ((ptr)->mlet == S_PUDDING || \

View file

@ -64,6 +64,8 @@
#define MS_SCREAM 53 /* Screams in madness */
#define MS_HARROW 54 /* Summon wraiths */
#define MS_APOC 55 /* Dire Revelations */
#define MS_COUGH 56 /* Sick coughing */
#define MS_RIBBIT 57 /* Frog sounds */
#define MR_FIRE 0x0001 /* 1 resists fire */
@ -426,8 +428,10 @@
#define EARTH_CRACK STARFALL+1
#define MON_AURA_BOLT EARTH_CRACK+1
#define RAIN MON_AURA_BOLT+1
#define BLOOD_RAIN RAIN+1
#define STEAM_GEYSER BLOOD_RAIN+1
#define MON_LASTSPELL RAIN
#define MON_LASTSPELL STEAM_GEYSER
//Not yet implemented
// #define MON_FIRE STRANGLE+1
// #define MON_BLIZZARD MON_FIRAGA+1

View file

@ -193,6 +193,7 @@ struct monst {
Bitfield(mnoise,1); /* made noise in the last turn (dochug) */ /*118*/
Bitfield(marriving,1); /* monster is arriving on the level and should be placed when there's space */ /*119*/
Bitfield(mflamemarked,1); /* monster was damaged by a silver flame weapon and will be sacced if they die */ /*120*/
Bitfield(mspores,1); /* monster is being consumed by Zuggutmoy's spores */ /*121*/
unsigned long long int seenmadnesses; /* monster has seen these madnesses */
@ -205,7 +206,7 @@ struct monst {
int entangled;/* The monster is entangled, and in what? */
#define imprisoned(mon) ((mon)->entangled == SHACKLES || ((mon)->mtrapped && t_at((mon)->mx, (mon)->my) && t_at((mon)->mx, (mon)->my)->ttyp == VIVI_TRAP))
#define noactions(mon) ((mon)->entangled || imprisoned(mon))
#define nonthreat(mon) (imprisoned(mon))
#define nonthreat(mon) (imprisoned(mon) || has_template(mon, PLAGUE_TEMPLATE))
#define helpless(mon) (mon->msleeping || !(mon->mcanmove) || !(mon->mnotlaugh) || noactions(mon))
#define helpless_still(mon) (mon->msleeping || !(mon->mcanmove) || noactions(mon))
long mstrategy; /* for monsters with mflag3: current strategy */
@ -280,7 +281,10 @@ struct monst {
#define MINDLESS 21 /* brain eaten by mind flayers */
#define POISON_TEMPLATE 22 /* turned evil by poison */
#define MOLY_TEMPLATE 23 /* off-turn snake-bite + insight */
#define MAXTEMPLATE MOLY_TEMPLATE
#define PLAGUE_TEMPLATE 24 /* suffering from a life-drain plague, cure to recruit */
#define SPORE_ZOMBIE 25 /* fungus zombie */
#define CORDYCEPS 26 /* spore shedder */
#define MAXTEMPLATE CORDYCEPS
//define HALF_DEMON FACTION_PADDING+1 /* half-demon ??? */
//define HALF_DEVIL FACTION_PADDING+2 /* half-devil ??? */

View file

@ -179,7 +179,6 @@ struct obj {
#define oarmed olocked
#define odrained olocked /* drained corpse */
Bitfield(obroken,1); /* lock has been broken */
#define ohaluengr obroken /* engraving on ring isn't a ward */
#define odebone obroken /* corpse has been de-boned */
Bitfield(otrapped,1); /* container is trapped */
#define obolted otrapped /* magic chest is permanently attached to floor */
@ -209,7 +208,8 @@ struct obj {
//See objclass for values
Bitfield(nomerge,1); /* temporarily block from merging */
Bitfield(forceconf,1); /* when set on a scroll, forces the confusion effect. Meant for use with pseudo objects, isn't checked while merging */
/* 11 free bits in this field, I think -CM */
Bitfield(ohaluengr,1); /* engraving on item isn't a "real" ward */
/* 10 free bits in this field, I think -CM */
int obj_color;
union {
@ -302,6 +302,7 @@ struct obj {
/*Records runes for wooden weapons */
long ovar1; /* extra variable. Specifies: */
#define ovar1_darklight ovar1
/* Number of viperwhip heads */
/* Moon axe phase */
/* Acid venom non-1d6 damage */
@ -326,6 +327,7 @@ struct obj {
|| (otmp)->otyp == HYPOSPRAY_AMPULE \
|| (otmp)->oclass == RING_CLASS \
|| (otmp)->otyp == DOLL_S_TEAR \
|| (otmp)->otyp == PINCER_STAFF \
)
#define ECLIPSE_MOON 0
#define CRESCENT_MOON 1
@ -541,6 +543,7 @@ struct obj {
|| (otmp)->otyp == SPIRITUAL_SOULSTONE\
|| ((otmp)->otyp >= EFFIGY && (otmp)->otyp <= DOLL_S_TEAR)\
|| (otmp)->otyp == HOLY_SYMBOL_OF_THE_BLACK_MOTHE\
|| (otmp)->oartifact == ART_ESSCOOAHLIPBOOURRR\
|| (otmp)->otyp == MAGIC_LAMP\
|| (otmp)->otyp == CANDLE_OF_INVOCATION\
|| (otmp)->otyp == RIN_WISHES\
@ -850,10 +853,10 @@ struct obj {
|| (otmp)->otyp == DWARVISH_ROUNDSHIELD)
#define is_gnomish_armor(otmp) ((otmp)->otyp == GNOMISH_POINTY_HAT)
#define is_wide_helm(otmp) ((otmp)->otyp == SEDGE_HAT\
|| (otmp)->otyp == WAR_HAT\
|| (otmp)->otyp == WIDE_HAT\
|| (otmp)->otyp == WITCH_HAT)
#define is_wide_helm(otmp) ((otmp)->otyp == SEDGE_HAT \
|| (otmp)->otyp == WAR_HAT \
|| (otmp)->otyp == WIDE_HAT \
|| (otmp)->otyp == WITCH_HAT )
#define is_plusten(otmp) (arti_plusten(otmp)\
|| is_rakuyo(otmp)\
@ -1021,6 +1024,7 @@ struct obj {
#define MAX_OIL_IN_FLASK 400 /* maximum amount of oil in a potion of oil */
#define Is_darklight_source(otmp) ((otmp)->otyp == SHADOWLANDER_S_TORCH || \
(otmp)->otyp == CHUNK_OF_FOSSIL_DARK ||\
((otmp)->otyp == DWARVISH_HELM && (otmp)->ovar1_darklight) ||\
(is_lightsaber(otmp) && otmp->cobj && otmp->cobj->otyp == CHUNK_OF_FOSSIL_DARK))
// NOT an exhaustive list, but this SHOULD be everything that would fall under snuff_lit
// and shouldn't be put out by darkness spells
@ -1033,6 +1037,7 @@ struct obj {
#define age_is_relative(otmp) ((otmp)->otyp == LANTERN\
|| (otmp)->otyp == OIL_LAMP\
|| (otmp)->otyp == DWARVISH_HELM\
|| (otmp)->otyp == LANTERN_PLATE_MAIL\
|| (otmp)->otyp == LIGHTSABER\
|| (otmp)->otyp == BEAMSWORD\
|| (otmp)->otyp == DOUBLE_LIGHTSABER\
@ -1089,9 +1094,22 @@ struct obj {
#define is_dress(onum) (onum == NOBLE_S_DRESS || onum == GENTLEWOMAN_S_DRESS || onum == PLAIN_DRESS || onum == VICTORIAN_UNDERWEAR)
#define is_hat(otmp) (otmp->otyp == SEDGE_HAT \
|| otmp->otyp == WIDE_HAT \
|| otmp->otyp == GNOMISH_POINTY_HAT \
|| otmp->otyp == FEDORA \
|| otmp->otyp == CORNUTHAUM \
|| otmp->otyp == WITCH_HAT \
|| otmp->otyp == DUNCE_CAP \
|| otmp->otyp == WAR_HAT \
|| otmp->otyp == SHEMAGH \
|| otmp->otyp == find_gcirclet() \
)
#define arm_blocks_upper_body(onum) (objects[onum].oc_dtyp&UPPER_TORSO_DR)
#define arm_blocks_lower_body(onum) (objects[onum].oc_dtyp&LOWER_TORSO_DR)
#define is_magic_obj(obj) (objects[(obj)->otyp].oc_magic || ((is_enchantable(obj)) && (obj)->spe > 0))
#define is_cha_otyp(onum) (onum == NOBLE_S_DRESS\
|| onum == GENTLEWOMAN_S_DRESS\
|| onum == PLAIN_DRESS\
@ -1107,6 +1125,8 @@ struct obj {
|| onum == CONSORT_S_SUIT\
)
#define is_readable_armor(obj) ((obj)->oward)
#define is_museable_amulet(otyp) (otyp == AMULET_OF_LIFE_SAVING \
||otyp == AMULET_OF_REFLECTION \
||otyp == AMULET_OF_NULLIFY_MAGIC \

View file

@ -5,7 +5,7 @@
#ifndef QTEXT_H
#define QTEXT_H
#define N_HDR 31 /* Maximum number of categories */
#define N_HDR 32 /* Maximum number of categories */
/* (i.e., num roles + 1) */
#define LEN_HDR 3 /* Maximum length of a category name */

View file

@ -13,6 +13,7 @@ typedef union any {
struct obj *a_obj;
int a_int;
char a_char;
long a_long;
schar a_schar;
/* add types as needed */
} anything;

View file

@ -34,6 +34,7 @@
#define Half_spel(mon) ((mon)==&youmonst ? Half_spell_damage : mon_resistance((mon), HALF_SPDAM))
#define Change_res(mon) ((mon)==&youmonst ? Unchanging : mon_resistance((mon), UNCHANGING))
#define Breathless_res(mon) ((mon)==&youmonst ? Breathless : breathless_mon(mon))
#define Water_res(mon) ((mon)==&youmonst ? Waterproof : mon_resistance((mon), WATERPROOF))
#define creature_at(x,y) (isok(x,y) ? MON_AT(x, y) ? level.monsters[x][y] : (x==u.ux && y==u.uy) ? &youmonst : (struct monst *)0 : (struct monst *)0)
#define FATAL_DAMAGE_MODIFIER 9001

View file

@ -634,7 +634,7 @@
#define Fixed_abil (u.uprops[FIXED_ABIL].extrinsic) /* KMH */
#define ELifesaved u.uprops[LIFESAVED].extrinsic
#define Lifesaved (ELifesaved || Check_crystal_lifesaving() || (uleft && uleft->otyp == RIN_WISHES && uleft->spe > 0) || (uright && uright->otyp == RIN_WISHES && uright->spe > 0)) /*Note: the rings only give life saving when charged, so it can't be a normal property*/
#define Lifesaved (ELifesaved || Check_crystal_lifesaving() || Check_iaso_lifesaving() || (uleft && uleft->otyp == RIN_WISHES && uleft->spe > 0) || (uright && uright->otyp == RIN_WISHES && uright->spe > 0)) /*Note: the rings only give life saving when charged, so it can't be a normal property*/
#define Necrospellboost (u.uprops[NECROSPELLS].extrinsic)

View file

@ -999,7 +999,7 @@ you_regen_hp()
if (Race_if(PM_ELF) && !Upolyd)
reglevel += 7;
if (Race_if(PM_DROW) && !Upolyd)
reglevel += 8;
reglevel += flags.female ? 4 : 8; //Note: blessing of Lolth
// Healer role bonus
if (Role_if(PM_HEALER) && !Upolyd)
reglevel += 10;
@ -1146,7 +1146,7 @@ you_regen_pw()
if (Race_if(PM_ELF) && !Upolyd)
reglevel += 7;
if (Race_if(PM_DROW) && !Upolyd)
reglevel += 8;
reglevel += flags.female ? 8 : 4;//Note: blessing of Lolth
if (Race_if(PM_GNOME) && !Upolyd)
reglevel += 12;
// penalty for being itchy
@ -3423,7 +3423,8 @@ boolean new_game; /* false => restoring an old game */
You("have psychic powers. Type #ability or press Shift-B to access your powers!");
}
if(Race_if(PM_DROW)){
pline("Beware, droven armor evaporates in light!");
if(!(Role_if(PM_HEALER) || Role_if(PM_EXILE)))
pline("Beware, droven armor evaporates in light!");
pline("Use #monster to create a patch of darkness.");
}
if(Race_if(PM_ANDROID)){
@ -5190,6 +5191,8 @@ struct monst *magr;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || (!!mdef->mtame == !!magr->mtame)))
continue;
if(youdef && u.uswallow)
continue;
if(!youdef && nonthreat(mdef))
continue;
@ -5275,6 +5278,8 @@ struct monst *magr;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || (!!mdef->mtame == !!magr->mtame)))
continue;
if(youdef && u.uswallow)
continue;
if(!youdef && nonthreat(mdef))
continue;
@ -5555,6 +5560,8 @@ struct monst *magr;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || (!!mdef->mtame == !!magr->mtame)))
continue;
if(youdef && u.uswallow)
continue;
if(!youdef && nonthreat(mdef))
continue;
@ -5634,6 +5641,8 @@ struct monst *magr;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || (!!mdef->mtame == !!magr->mtame)))
continue;
if(youdef && u.uswallow)
continue;
if(!youdef && nonthreat(mdef))
continue;
@ -5708,6 +5717,8 @@ struct monst *magr;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || (!!mdef->mtame == !!magr->mtame)))
continue;
if(youdef && u.uswallow)
continue;
if(!youdef && nonthreat(mdef))
continue;
@ -5780,6 +5791,8 @@ struct monst *magr;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || (!!mdef->mtame == !!magr->mtame)))
continue;
if(youdef && u.uswallow)
continue;
if(!youdef && nonthreat(mdef))
continue;
@ -5850,6 +5863,8 @@ struct monst *magr;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || (!!mdef->mtame == !!magr->mtame)))
continue;
if(youdef && u.uswallow)
continue;
if(!youdef && nonthreat(mdef))
continue;
@ -5920,6 +5935,8 @@ struct monst *magr;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || (!!mdef->mtame == !!magr->mtame)))
continue;
if(youdef && u.uswallow)
continue;
if(!youdef && nonthreat(mdef))
continue;

View file

@ -33,6 +33,7 @@ STATIC_DCL void FDECL(use_candelabrum, (struct obj *));
STATIC_DCL void FDECL(use_candle, (struct obj **));
STATIC_DCL void FDECL(use_lamp, (struct obj *));
STATIC_DCL int FDECL(swap_aegis, (struct obj *));
STATIC_DCL int FDECL(aesculapius_poke, (struct obj *));
STATIC_DCL int FDECL(use_rakuyo, (struct obj *));
STATIC_DCL int FDECL(use_mercy_blade, (struct obj *));
STATIC_DCL int FDECL(use_force_blade, (struct obj *));
@ -1483,7 +1484,8 @@ struct obj *obj;
if (obj->lamplit) {
if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
obj->otyp == LANTERN || obj->otyp == POT_OIL ||
obj->otyp == LANTERN || obj->otyp == LANTERN_PLATE_MAIL ||
obj->otyp == POT_OIL ||
obj->otyp == DWARVISH_HELM || obj->otyp == GNOMISH_POINTY_HAT) {
(void) get_obj_location(obj, &x, &y, 0);
if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
@ -1516,8 +1518,8 @@ struct obj *obj;
if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->cursed)
return FALSE;
if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
obj->otyp == LANTERN || obj->otyp == DWARVISH_HELM ||
obj->otyp == GNOMISH_POINTY_HAT) &&
obj->otyp == LANTERN || obj->otyp == LANTERN_PLATE_MAIL ||
obj->otyp == DWARVISH_HELM || obj->otyp == GNOMISH_POINTY_HAT) &&
obj->cursed && !rn2(2))
return FALSE;
if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
@ -1557,6 +1559,254 @@ struct obj *obj;
}
}
STATIC_OVL int
aesculapius_poke(obj)
struct obj *obj;
{
struct monst *mon;
boolean shackles = obj->oartifact == ART_ESSCOOAHLIPBOOURRR;
if(obj != uwep){
if (!wield_tool(obj, "staff")) return MOVE_CANCELLED;
}
if(!getdir((char *)0)) {
return MOVE_CANCELLED;
}
if(u.dz > 0){
if(u.usteed)
mon = u.usteed;
else if(u.uswallow)
mon = u.ustuck;
else {
You("doubt that will have any further effect.");
return MOVE_CANCELLED;
}
}
else if(u.dz < 0){
if(u.uswallow)
mon = u.ustuck;
else {
if(shackles)
You("don't see anything up there to touch with your broken shackles.");
else
You("don't see anything up there to poke with your staff.");
return MOVE_CANCELLED;
}
}
else if(!u.dx && !u.dy){
use_unicorn_horn(obj);
return MOVE_STANDARD;
}
else if(!isok(u.ux + u.dx, u.uy + u.dy)){
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff doesn't touch anything.");
return MOVE_STANDARD;
}
else {
mon = m_at(u.ux + u.dx, u.uy + u.dy);
}
if(!mon){
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff doesn't touch anything.");
return MOVE_STANDARD;
}
boolean good_effect = (mon->mpeaceful && !obj->cursed) || (!mon->mpeaceful && obj->cursed);
if(good_effect){
if (!mon->mcansee) {
mon->mcansee = 1;
mon->mblinded = 0;
if (canseemon(mon)) pline("%s can see again.", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (!mon->mcanhear) {
mon->mcanhear = 1;
mon->mdeafened = 0;
if (canseemon(mon)) pline("%s can hear again.", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (mon->mconf || mon->mstun) {
mon->mconf = mon->mstun = 0;
if (canseemon(mon))
pline("%s seems steadier now.", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (mon->msleeping) {
mon->msleeping = 0;
if (canseemon(mon)) pline("%s wakes up!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (!mon->mcanmove) {
mon->mcanmove = 1;
mon->mfrozen = 0;
if (canseemon(mon)) pline("%s can move again!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (mon->mcan) {
set_mcan(mon, FALSE);
if (canseemon(mon)) pline("%s looks special again!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
}
else if(has_template(mon, PLAGUE_TEMPLATE)){
set_template(mon, 0);
mon->mhpmax = max(3, (mon->m_lev * hd_size(mon->data))-1);
if (canseemon(mon)) pline("%s has been cured!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
if(rnd(!always_hostile(mon->data) ? 12 : 20) < ACURR(A_CHA)){
struct monst *newmon = tamedog_core(mon, (struct obj *)0, TRUE);
if(newmon){
mon = newmon;
newsym(mon->mx, mon->my);
pline("%s is very grateful!", Monnam(mon));
}
}
}
else {
if (canseemon(mon)) pline("%s looks really healthy!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
}
}
//bad effect
else {
if (mon->mcanhear) {
mon->mcanhear = 0;
mon->mdeafened = d(6,6);
if (canseemon(mon)) pline("%s is stricken deaf!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (mon->mcansee) {
mon->mcansee = 0;
mon->mblinded = d(6,6);
if (canseemon(mon)) pline("%s is stricken blind!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (!mon->mstun) {
mon->mstun = 1;
if (canseemon(mon))
pline("%s wobbles!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (!mon->mconf) {
mon->mconf = 1;
if (canseemon(mon))
pline("%s seems confused!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (mon->mcanmove && !mon_resistance(mon, FREE_ACTION)) {
mon->mcanmove = 0;
mon->mfrozen = d(2,2);
if (canseemon(mon))
pline("%s seems frozen!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if(!mon->mcan){
set_mcan(mon, TRUE);
if (canseemon(mon)) pline("%s looks mediocre!", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else if (mon->mcanmove && !mon_resistance(mon, SICK_RES)) {
int dmg = d(3, 12);
if(!rn2(10))
dmg += 100;
if(m_losehp(mon, dmg, TRUE, "illness"));
else if (canseemon(mon))
pline("%s looks slightly ill.", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
} else {
if (canseemon(mon)) pline("%s looks stubbornly healthy.", Monnam(mon));
else {
if(shackles)
pline("Your broken shackles touch it!");
else
pline("Your staff touches it!");
map_invisible(u.ux+u.dx,u.uy+u.dy);
}
}
}
return MOVE_STANDARD;
}
int
do_bloodletter(obj)
struct obj *obj;
@ -1799,7 +2049,7 @@ struct obj *obj;
}
if(obj->lamplit) {
if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
obj->otyp == LANTERN ||
obj->otyp == LANTERN || obj->otyp == LANTERN_PLATE_MAIL ||
obj->otyp == DWARVISH_HELM)
pline("%s lamp is now off.", Shk_Your(buf, obj));
else if(is_lightsaber(obj)) {
@ -1824,6 +2074,7 @@ struct obj *obj;
|| (obj->otyp == MAGIC_LAMP && obj->spe == 0)
) {
if (obj->otyp == LANTERN ||
obj->otyp == LANTERN_PLATE_MAIL ||
obj->otyp == DWARVISH_HELM ||
is_lightsaber(obj)
)
@ -1851,7 +2102,8 @@ struct obj *obj;
Tobjnam(obj, "flicker"), otense(obj, "die"));
} else {
if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
obj->otyp == LANTERN || obj->otyp == DWARVISH_HELM) {
obj->otyp == LANTERN || obj->otyp == LANTERN_PLATE_MAIL ||
obj->otyp == DWARVISH_HELM) {
check_unpaid(obj);
pline("%s lamp is now on.", Shk_Your(buf, obj));
} else if (is_lightsaber(obj)) {
@ -2070,7 +2322,7 @@ dorub()
} else if (rn2(2) && !Blind)
You("see a puff of smoke.");
else pline1(nothing_happens);
} else if (obj->otyp == LANTERN || obj->otyp == DWARVISH_HELM) {
} else if (obj->otyp == LANTERN || obj->otyp == LANTERN_PLATE_MAIL || obj->otyp == DWARVISH_HELM) {
/* message from Adventure */
pline("Rubbing the electric lamp is not particularly rewarding.");
pline("Anyway, nothing exciting happens.");
@ -2913,6 +3165,16 @@ coord *cc;
}
mark_mon_as_summoned(mtmp, master, ESUMMON_PERMANENT, 0);
mtmp->mextra_p->esum_p->sm_o_id = obj->o_id;
//Dodge being marked as summoned :(
if(mtmp->mtyp == PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION && !art_already_exists(ART_ESSCOOAHLIPBOOURRR)){
otmp = mksartifact(ART_ESSCOOAHLIPBOOURRR);
if(otmp){
otmp->blessed = TRUE;
otmp->cursed = FALSE;
otmp->spe = 3;
(void) mpickobj(mtmp, otmp);
}
}
}
}
@ -3579,7 +3841,7 @@ struct obj *hypo;
case POT_HEALING:
You_feel("better.");
healup(d(6 + 2 * bcsign(amp), 4),
(!amp->cursed ? 1 : 0), !!amp->blessed, !amp->cursed);
(!amp->cursed ? 1 : 0), amp->blessed, !amp->cursed);
exercise(A_CON, TRUE);
break;
case POT_EXTRA_HEALING:
@ -5702,7 +5964,7 @@ struct obj *obj;
}
break;
case SUMMON_SERVANT:
mtmp = create_particular(MT_DOMESTIC, 0, FALSE, MA_MINION | MA_DEMON | MA_FEY | MA_PRIMORDIAL, MG_NOWISH | MG_NOTAME, G_UNIQ);
mtmp = create_particular(u.ux, u.uy, MT_DOMESTIC, 0, FALSE, MA_MINION | MA_DEMON | MA_FEY | MA_PRIMORDIAL, MG_NOWISH | MG_NOTAME, G_UNIQ, (char *)0);
if (!mtmp) {
pline("Perhaps try summoning something else?");
consumed = FALSE;
@ -6234,7 +6496,7 @@ struct obj *obj;
}
break;
case WAGE_OF_LUST:
tmp = obj->cursed ? 99 : 9;
tmp = obj->cursed ? 22 : 9;
if(!BlowingWinds){
pline("Hurricane-force winds surround you!");
@ -6261,10 +6523,10 @@ struct obj *obj;
}
else {
if(obj->cursed){
mtmp->mhp -= min(999, mtmp->mhpmax);
mtmp->mhp -= min(333, mtmp->mhpmax);
}
else {
mtmp->mhp -= min(99, mtmp->mhpmax/2);
mtmp->mhp -= max(33, min(99, mtmp->mhpmax/2));
}
if(mtmp->mhp <= 0){
pline("%s starves.", Monnam(mtmp));
@ -6893,7 +7155,8 @@ pick_carvee()
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, buf, MENU_UNSELECTED);
for(otmp = invent; otmp; otmp = otmp->nobj){
if(otmp->oclass == WEAPON_CLASS && otmp->obj_material == WOOD && otmp->otyp != MOON_AXE
&& otmp->oartifact != ART_BOW_OF_SKADI && otmp->oartifact != ART_GUNGNIR && otmp->oartifact != ART_STAFF_OF_AESCULAPIUS){
&& otmp->oartifact != ART_BOW_OF_SKADI && otmp->oartifact != ART_GUNGNIR
&& otmp->oartifact != ART_STAFF_OF_AESCULAPIUS && otmp->oartifact != ART_ESSCOOAHLIPBOOURRR){
Sprintf1(buf, doname(otmp));
any.a_char = otmp->invlet; /* must be non-zero */
add_menu(tmpwin, NO_GLYPH, &any,
@ -7289,6 +7552,39 @@ upgradeMenu()
return 0;
}
boolean
set_obj_shape(obj, shape)
struct obj *obj;
long shape;
{
long starting_shape = obj->bodytypeflag;
//Dragon scales don't have a shape.
if(Is_dragon_scales(obj))
return FALSE;
if(is_shirt(obj) || is_suit(obj)){
//Only CHANGE the shape if the result will be valid.
if(shape&MB_BODYTYPEMASK){
//Body gloves cover the whole body.
if(obj->otyp == BODYGLOVE)
obj->bodytypeflag = shape&MB_BODYTYPEMASK;
//Shirts, dresses, and togas aren't concerned by the shape of the lower body.
else if (is_shirt(obj) || obj->otyp == ELVEN_TOGA || is_dress(obj->otyp))
obj->bodytypeflag = (shape&MB_HUMANOID) ? MB_HUMANOID : (shape&MB_BODYTYPEMASK);
else if (is_suit(obj))
obj->bodytypeflag = shape&MB_BODYTYPEMASK;
}
//If the given shape is invalid and the object's current shape is invalid, set the object to humanoid.
// I believe this will never happen, as armor is initialized to humanoid.
else if((obj->bodytypeflag&MB_BODYTYPEMASK) == 0)
obj->bodytypeflag = MB_HUMANOID;
}
else if (is_helmet(obj) && !is_hat(obj))
obj->bodytypeflag = shape&MB_HEADMODIMASK;
if(obj->bodytypeflag != starting_shape)
return TRUE;
return FALSE;
}
STATIC_OVL int
resizeArmor()
{
@ -7296,6 +7592,7 @@ resizeArmor()
struct permonst *ptr;
struct monst *mtmp;
int rx, ry;
boolean changed = FALSE;
if (!getdir("Resize armor to fit what creature? (in what direction)")) {
/* decided not to */
@ -7337,39 +7634,35 @@ resizeArmor()
}
// change shape
if (is_shirt(otmp) || otmp->otyp == ELVEN_TOGA){
if (is_shirt(otmp) || otmp->otyp == ELVEN_TOGA || is_suit(otmp)){
//Check that the monster can actually have armor that fits it.
if(!(ptr->mflagsb&MB_BODYTYPEMASK)){
You("can't figure out how to make it fit.");
return MOVE_CANCELLED;
}
if(otmp->otyp == BODYGLOVE)
otmp->bodytypeflag = (ptr->mflagsb&MB_BODYTYPEMASK);
else
otmp->bodytypeflag = (ptr->mflagsb&MB_HUMANOID) ? MB_HUMANOID : (ptr->mflagsb&MB_BODYTYPEMASK);
changed |= set_obj_shape(otmp, ptr->mflagsb);
}
else if (is_suit(otmp)){
//Check that the monster can actually have armor that fits it.
if(!(ptr->mflagsb&MB_BODYTYPEMASK)){
You("can't figure out how to make it fit.");
return MOVE_CANCELLED;
}
otmp->bodytypeflag = (ptr->mflagsb&MB_BODYTYPEMASK);
}
else if (is_helmet(otmp)){
else if (is_helmet(otmp) && !is_hat(otmp)){
//Check that the monster can actually have armor that fits it.
if(!has_head(ptr)){
pline("No head!");
return MOVE_CANCELLED;
}
otmp->bodytypeflag = (ptr->mflagsb&MB_HEADMODIMASK);
changed |= set_obj_shape(otmp, ptr->mflagsb);
}
// change size (AFTER shape, because this may be aborted during that step.
otmp->objsize = ptr->msize;
if(otmp->objsize != ptr->msize){
otmp->objsize = ptr->msize;
changed = TRUE;
}
fix_object(otmp);
if(!changed){
You("figure it already fits fine.");
return MOVE_CANCELLED;
}
You("resize the armor to fit.");
pline("The kit is used up.");
return MOVE_STANDARD;
@ -7541,8 +7834,9 @@ doapply()
Strcpy(class_list, tools);
if (carrying(CREAM_PIE) || carrying(EUCALYPTUS_LEAF))
add_class(class_list, FOOD_CLASS);
if (carrying(DWARVISH_HELM) || carrying(GNOMISH_POINTY_HAT)
|| carrying(DROVEN_CLOAK) || carrying_art(ART_AEGIS))
if (carrying(DWARVISH_HELM) || carrying(LANTERN_PLATE_MAIL) ||
carrying(GNOMISH_POINTY_HAT) || carrying(DROVEN_CLOAK) ||
carrying_art(ART_AEGIS))
add_class(class_list, ARMOR_CLASS);
if(carrying_applyable_ring()){
add_class(class_list, RING_CLASS);
@ -7583,6 +7877,8 @@ doapply()
else if(obj->oartifact == ART_HOLY_MOONLIGHT_SWORD && !u.veil) use_lamp(obj);
else if(obj->oartifact == ART_BLOODLETTER && artinstance[obj->oartifact].BLactive >= monstermoves) res = do_bloodletter(obj);
else if(obj->oartifact == ART_AEGIS) res = swap_aegis(obj);
else if(obj->oartifact == ART_STAFF_OF_AESCULAPIUS) res = aesculapius_poke(obj);
else if(obj->oartifact == ART_ESSCOOAHLIPBOOURRR) res = aesculapius_poke(obj);
else if(obj->otyp == RAKUYO || obj->otyp == RAKUYO_SABER){
return use_rakuyo(obj);
}
@ -7913,6 +8209,7 @@ doapply()
* Code by Malcom Ryan
*/
case DWARVISH_HELM:
case LANTERN_PLATE_MAIL:
case OIL_LAMP:
case MAGIC_LAMP:
case LANTERN:

View file

@ -4625,6 +4625,12 @@ int dieroll; /* needed for Magicbane and vorpal blades */
// pline("off: %d", *hp(mdef)/factor);
}
}
if(otmp->otyp == PINCER_STAFF && u.uinsight >= 10){
if(otmp->ovar1 == mdef->m_id)
*plusdmgptr += basedmg;
else otmp->ovar1 = mdef->m_id;
}
}
/* returns MM_style hitdata now, and is used for both artifacts and weapon properties */
@ -6343,6 +6349,12 @@ boolean printmessages; /* print generic elemental damage messages */
}
}
if(otmp->oartifact == ART_ESSCOOAHLIPBOOURRR){
if(artinstance[otmp->oartifact].Esscoo_mid == mdef->m_id)
*plusdmgptr += basedmg;
else artinstance[otmp->oartifact].Esscoo_mid = mdef->m_id;
}
/* ********************************************
KLUDGE ALERT AND WARNING: FROM THIS POINT ON, NON-ARTIFACTS OR ARTIFACTS THAT DID NOT TRIGGER SPEC_DBON_APPLIES WILL NOT OCCUR
********************************************************
@ -6756,6 +6768,12 @@ arti_invoke(obj)
}
break;
}
case LOOT_SELF:
if(!use_container(obj, TRUE)){
obj->age = 0;
return MOVE_CANCELLED;
}
break;
case QUEST_PORTAL: {
int i;
d_level newlev;
@ -6791,7 +6809,7 @@ arti_invoke(obj)
schedule_goto(&newlev, FALSE, FALSE, FALSE,
"You feel dizzy for a moment, but the sensation passes.",
(char *)0);
(char *)0, 0);
}break;
case ENLIGHTENING:
(void)doenlightenment();

View file

@ -1721,7 +1721,6 @@ struct monst *mon;
if(d(2,u.ulevel) > mon->m_lev){
if(madflag == MAD_DELUSIONS
|| madflag == MAD_REAL_DELUSIONS
|| madflag == MAD_SPORES
|| madflag == MAD_SPIRAL
|| madflag == MAD_FORMICATION
){
@ -1730,6 +1729,9 @@ struct monst *mon;
else if(madflag == MAD_SANCTITY){
mon->msanctity = 1;
}
else if(madflag == MAD_SPORES){
mon->mspores = 1;
}
else if(madflag == MAD_GLUTTONY){
mon->mgluttony = 1;
}

View file

@ -1327,7 +1327,7 @@ wiz_map()
STATIC_PTR int
wiz_genesis()
{
if (wizard) (void) create_particular(-1, -1, TRUE, 0, 0, 0);
if (wizard) (void) create_particular(u.ux, u.uy, -1, -1, TRUE, 0, 0, 0, (char *)0);
else pline("Unavailable command '^G'.");
return MOVE_CANCELLED;
}

View file

@ -1126,7 +1126,7 @@ openfakedoor()
Sprintf(msgbuf, "The hole in the %s above you closes up.",
ceiling(u.ux,u.uy));
schedule_goto(&dtmp, FALSE, TRUE, 0,
(char *)0, !Blind ? msgbuf : (char *)0);
(char *)0, !Blind ? msgbuf : (char *)0, 0);
}
/* return TRUE if digging succeeded, FALSE otherwise */

View file

@ -152,6 +152,15 @@ const char *verb;
/* make sure things like water_damage() have no pointers to follow */
obj->nobj = obj->nexthere = (struct obj *)0;
if(In_quest(&u.uz) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && levl[x][y].typ == AIR){
add_to_migration(obj);
obj->ox = u.uz.dnum;
obj->oy = qlocate_level.dlevel+1;
obj->owornmask = (long)MIGR_RANDOM;
newsym(x,y);
return TRUE;
}
if (is_boulder(obj) && boulder_hits_pool(obj, x, y, FALSE))
return TRUE;
else if (is_boulder(obj) && (t = t_at(x,y)) != 0 &&
@ -945,7 +954,14 @@ dodown()
if (Is_hell3(&u.uz) && !(u.ux == xupstair && u.uy == yupstair)){
pline("These stairs are fake!");
levl[u.ux][u.uy].typ = ROOM;
} else pline("These stairs don't go down!");
} else {
if(levl[u.ux][u.uy].ladder != LA_DOWN){
pline("These stairs don't go down!");
}
else {
pline("These stairs have been blocked by rubble!");
}
}
}
else You_cant("go down here.");
return MOVE_CANCELLED;
@ -1023,7 +1039,12 @@ doup()
}
else{
if(levl[u.ux][u.uy].typ == STAIRS){
pline("These stairs don't go up!");
if(levl[u.ux][u.uy].ladder != LA_UP){
pline("These stairs don't go up!");
}
else {
pline("These stairs have been blocked by rubble!");
}
}
else You_cant("go up here.");
}
@ -1653,6 +1674,15 @@ misc_levelport:
pline("Your help is urgently needed at Archer Asylum! Look for a ...ic transporter.");
pline("You couldn't quite make out that last message.");
}
} else if(Role_if(PM_HEALER) && Race_if(PM_DROW)){
if(u.uevent.qcalled){
You("again sense Sister T'eirastra pleading for help.");
}
else {
You("receive a faint telepathic message from T'eirastra:");
pline("Your help is urgently needed at Menzoberranzan! Look for a ...ic transporter.");
pline("You couldn't quite make out that last message.");
}
} else {
if (u.uevent.qcalled) {
com_pager(Role_if(PM_ROGUE) ? 4 : 3);
@ -1769,13 +1799,16 @@ final_level()
static char *dfr_pre_msg = 0, /* pline() before level change */
*dfr_post_msg = 0; /* pline() after level change */
static int dfr_post_dmg = 0;
/* change levels at the end of this turn, after monsters finish moving */
void
schedule_goto(tolev, at_stairs, falling, portal_flag, pre_msg, post_msg)
schedule_goto(tolev, at_stairs, falling, portal_flag, pre_msg, post_msg, post_dmg)
d_level *tolev;
boolean at_stairs, falling;
int portal_flag;
const char *pre_msg, *post_msg;
int post_dmg;
{
int typmask = 0100; /* non-zero triggers `deferred_goto' */
@ -1793,6 +1826,8 @@ const char *pre_msg, *post_msg;
dfr_pre_msg = strcpy((char *)alloc(strlen(pre_msg) + 1), pre_msg);
if (post_msg)
dfr_post_msg = strcpy((char *)alloc(strlen(post_msg)+1), post_msg);
if(post_dmg)
dfr_post_dmg = post_dmg;
}
/* handle something like portal ejection */
@ -1815,6 +1850,10 @@ deferred_goto()
}
}
if (dfr_post_msg) pline1(dfr_post_msg);
if (dfr_post_dmg){
losehp(dfr_post_dmg, "abrupt arrival", KILLED_BY_AN);
dfr_post_dmg = 0;
}
}
u.utotype = 0; /* our caller keys off of this */
if (dfr_pre_msg)
@ -1874,7 +1913,13 @@ int different;
chewed = !different && (mtmp->mhp < mtmp->mhpmax);
if (chewed) cname = cname_buf; /* include "bite-covered" prefix */
if(different==REVIVE_ZOMBIE){
set_template(mtmp, ZOMBIFIED);
if(mtmp->mspores){
set_template(mtmp, SPORE_ZOMBIE);
mtmp->mspores = 0;
}
else {
set_template(mtmp, ZOMBIFIED);
}
mtmp->zombify = 0;
if(mtmp->mpeaceful && !mtmp->mtame){
mtmp->mpeaceful = 0;
@ -2294,7 +2339,7 @@ long timeout;
if (pmtype != -1) {
/* We don't want special case revivals */
if (cant_create(&pmtype, TRUE) || (get_ox(body, OX_EMON) && !(EMON(body)->zombify)))
if (cant_create(&pmtype, TRUE) || (get_ox(body, OX_EMON) && !(EMON(body)->zombify || EMON(body)->mspores)))
pmtype = -1; /* cantcreate might have changed it so change it back */
else {
body->corpsenm = pmtype;
@ -2408,7 +2453,7 @@ donull()
{
static long lastreped = -13;//hacky way to tell if the player has recently tried repairing themselves
u.unull = TRUE;
if(uclockwork){
if(!Upolyd && u.uhp<u.uhpmax){
if(lastreped < monstermoves-13) You("attempt to make repairs.");

View file

@ -715,10 +715,10 @@ const char *name;
/* body type */
if (is_malleable_artifact(&artilist[obj->oartifact])); //keep current/default body type
else if (Role_if(PM_PRIEST) && obj->oartifact == ART_MITRE_OF_HOLINESS)
obj->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_HEADMODIMASK);
set_obj_shape(obj, mons[urace.malenum].mflagsb);
else if (Pantheon_if(PM_NOBLEMAN) && (obj->oartifact == ART_HELM_OF_THE_DARK_LORD || obj->oartifact == ART_CROWN_OF_THE_SAINT_KING))
obj->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_HEADMODIMASK);
else obj->bodytypeflag = MB_HUMANOID;
set_obj_shape(obj, mons[urace.malenum].mflagsb);
else set_obj_shape(obj, MB_HUMANOID);
/* viperwhip heads */
if (obj->oartifact == ART_SCOURGE_OF_LOLTH)
@ -928,6 +928,9 @@ boolean full;
if (mtmp->female) Sprintf(buf2, "%s, Daughter of the Black Goat", buf);
else Sprintf(buf2, "%s, Child of the Black Goat", buf);
}
else if (full && template == PLAGUE_TEMPLATE) Sprintf(buf2, "%s, plague victim", buf);
else if (full && template == SPORE_ZOMBIE) Sprintf(buf2, "%s, spore infectee", buf);
else if (full && template == CORDYCEPS) Sprintf(buf2, "%s's sporulating corpse", buf);
else Strcpy(buf2, buf);
}
else {
@ -954,6 +957,9 @@ boolean full;
if (mtmp->female) Sprintf(buf2, "%s dark daughter", buf);
else Sprintf(buf2, "%s dark child", buf);
}
else if (full && template == PLAGUE_TEMPLATE) Sprintf(buf2, "%s plague-victim", buf);
else if (full && template == SPORE_ZOMBIE) Sprintf(buf2, "%s infectee", buf);
else if (full && template == CORDYCEPS) Sprintf(buf2, "%s cordyceps", buf);
else Strcpy(buf2, buf);
}
@ -1134,7 +1140,7 @@ boolean called;
if(is_drow(mdat)){
struct obj *otmp;
for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
if (is_readable_armor_otyp(otmp->otyp)
if (is_readable_armor(otmp)
&& otmp->owornmask & mtmp->misc_worn_check && otmp->oward
){
Sprintf(eos(buf), "%s ", getDrowHouse(otmp->oward));
@ -1198,7 +1204,7 @@ boolean called;
if(is_drow(mdat)){
struct obj *otmp;
for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
if (is_readable_armor_otyp(otmp->otyp)
if (is_readable_armor(otmp)
&& otmp->owornmask & mtmp->misc_worn_check && otmp->oward){
Sprintf(eos(buf), "%s ", getDrowHouse(otmp->oward));
name_at_start = FALSE;
@ -1687,6 +1693,8 @@ long hnum;
return "silver-sign bearing";
case EDDER_SYMBOL:
return u.uevent.knoweddergud ? "Edderkirke" : "black-webbed";
case Y_CULT_SYMBOL:
return "Y bearing";
}
return "";
}

View file

@ -1643,28 +1643,34 @@ boolean noisy;
if (uarmh) {
if (noisy) already_wearing(an(c_helmet));
err++;
} else if (!is_flimsy(otmp) && otmp->otyp != find_gcirclet()){
} else if (!helm_match(youracedata, otmp)){
/* (flimsy exception matches polyself handling), you can even just set a hat on top of your body (no head requried)*/
if(!has_head_mon(&youmonst)){
boolean hat = is_hat(otmp);
if(!has_head_mon(&youmonst) && !hat){
if (noisy)
You("don't have a head.");
err++;
} else if(youracedata->msize != otmp->objsize){
if (noisy)
pline_The("%s is the wrong size for you.", c_helmet);
err++;
} else if(!helm_match(youracedata,otmp)){
} else if(!helm_match(youracedata,otmp) && !hat){
if (noisy)
pline_The("%s is the wrong shape for your head.", c_helmet);
err++;
} else if(has_horns(youracedata)){
} else if(has_horns(youracedata) && !(otmp->otyp == find_gcirclet() || is_flimsy(otmp))){
if (noisy)
pline_The("%s won't fit over your horn%s.",
c_helmet, plur(num_horns(youracedata)));
err++;
} else
*mask = W_ARMH;
} else
} else {
if (noisy)
pline_The("%s won't fit for some reason.", c_helmet);
err++;
}
}
else if(!helm_size_fits(youracedata, otmp)){
if (noisy)
pline_The("%s is the wrong size for you.", c_helmet);
err++;
}
else
*mask = W_ARMH;
} else if (is_shield(otmp)) {
if (uarms) {
@ -1692,7 +1698,7 @@ boolean noisy;
} else if (!humanoid(youracedata) && !can_wear_boots(youracedata)) {
if (noisy) pline("You have too many legs to wear %s.", c_boots);
err++;
} else if(youracedata->msize != otmp->objsize){
} else if(!(boots_size_fits(youracedata, otmp))){
if (noisy)
pline_The("%s are the wrong size for you.", c_boots);
err++;
@ -4064,7 +4070,7 @@ struct obj *armor;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || !rn2(4)))
continue;
if(!youdef && imprisoned(mdef))
if(!youdef && nonthreat(mdef))
continue;
//Note: the armor avoids touching petrifying things even if you're immune
@ -4121,7 +4127,7 @@ struct obj *wep;
if(!youagr && !youdef && (mdef->mpeaceful == magr->mpeaceful))
continue;
if(!youdef && imprisoned(mdef))
if(!youdef && nonthreat(mdef))
continue;
mdef->movement -= 12;
@ -4172,7 +4178,7 @@ struct obj *wep;
if(!youagr && !youdef && (mdef->mpeaceful == magr->mpeaceful))
continue;
if(!youdef && imprisoned(mdef))
if(!youdef && nonthreat(mdef))
continue;
//Note: petrifying targets are safe, it's a weapon attack
@ -4246,7 +4252,7 @@ struct obj *wep;
break; //break out of inner loop now, we found a bad target.
}
if(!youdef && imprisoned(mdef)){
if(!youdef && nonthreat(mdef)){
gooddir = FALSE;
break; //break out of inner loop now, we found a bad target.
}
@ -4346,7 +4352,7 @@ struct obj *wep;
if(!youagr && !youdef && (mdef->mpeaceful == magr->mpeaceful))
continue;
if(!youdef && imprisoned(mdef))
if(!youdef && nonthreat(mdef))
continue;
if(youdef){
@ -4637,7 +4643,7 @@ char etyp;
if(!youagr && !youdef && ((mdef->mpeaceful == magr->mpeaceful) || !rn2(4)))
continue;
if(!youdef && imprisoned(mdef))
if(!youdef && nonthreat(mdef))
continue;
//Note: the armor avoids touching petrifying things even if you're immune
@ -4817,7 +4823,7 @@ struct obj *wep;
if(!peaceSafe && youdef && !mdef->mpeaceful)
continue;
if(!youdef && imprisoned(mdef))
if(!youdef && nonthreat(mdef))
continue;
//Note: petrifying targets are safe, it's a weapon attack
@ -4860,7 +4866,7 @@ struct obj *wep;
if(!peaceSafe && youdef && !mdef->mpeaceful)
continue;
if(!youdef && imprisoned(mdef))
if(!youdef && nonthreat(mdef))
continue;
if (magr_can_attack_mdef(magr, mdef, i, j, FALSE)){
@ -4979,6 +4985,265 @@ boolean invoked;
}
}
void
dotsmi_theft(magr, mdef, inventory, artifact)
struct monst *magr;
struct monst *mdef;
struct obj *inventory;
struct obj *artifact;
{
boolean youagr = (magr == &youmonst);
boolean youdef = (mdef == &youmonst);
struct obj *nobj, *obj;
int n = rnd(3), taken = 0, weapon = 0, armor = 0;
int ox = 0, oy = 0;
for(obj = inventory; obj; obj = nobj){
nobj = obj->where == OBJ_FLOOR ? obj->nexthere : obj->nobj;
if(is_magic_obj(obj) && (n > 0 || !rn2(5))){
n--;
taken++;
if((obj->owornmask&W_WEP) || ((obj->owornmask&W_SWAPWEP) && (!youdef || u.twoweap)))
weapon++;
if(obj->owornmask&W_ARMOR)
armor++;
if(obj->where == OBJ_FLOOR){
ox = obj->ox;
oy = obj->oy;
}
obj_extract_and_unequip_self(obj);
if(artifact)
add_to_container(artifact, obj);
else
mpickobj(magr, obj);
if(ox || oy)
newsym(ox, oy);
ox = oy = 0;
}
}
if(taken){
if(!mdef)
pline("The tentacles pick up %s.", taken > 1 ? "some objects" : "an object");
else if(!youdef && !canseemon(mdef))
pline("The tentacles acquire %s.", taken > 1 ? "some objects" : "an object");
else if(armor && weapon && armor+weapon < taken){
if(youdef){
pline("The tentacles somehow disentangle several objects from your person, including %s from your grip and %s from your body!",
u.twoweap && weapon > 1 ? "your weapons" : u.twoweap ? "a weapon" : "your weapon",
(uarm || uarmc || uarmu || uarmh || uarmg || uarmf) ? "some clothes" : "the clothes"
);
pline("You're pretty sure that wasn't physically possible.");
}
else {
pline("The tentacles somehow disentangle several objects from %s, including %s from %s grip and %s from %s body!",
mon_nam(mdef),
!(MON_WEP(mdef) || MON_SWEP(mdef)) && weapon > 1 ? "the weapons" : u.twoweap ? "a weapon" : "the weapon",
mhis(mdef),
(mdef->misc_worn_check&W_ARMOR) ? "some clothes" : "the clothes",
mhis(mdef)
);
}
}
else if(armor && weapon){
if(youdef){
pline("The tentacles somehow disentangle %s from your grip and %s from your body!",
u.twoweap && weapon > 1 ? "your weapons" : u.twoweap ? "a weapon" : "your weapon",
(uarm || uarmc || uarmu || uarmh || uarmg || uarmf) ? "some clothes" : "the clothes"
);
pline("You're pretty sure that wasn't physically possible.");
}
else {
pline("The tentacles somehow disentangle %s from %s grip and %s from %s body!",
!(MON_WEP(mdef) || MON_SWEP(mdef)) && weapon > 1 ? "the weapons" : u.twoweap ? "a weapon" : "the weapon",
mon_nam(mdef),
(mdef->misc_worn_check&W_ARMOR) ? "some clothes" : "the clothes",
mhis(mdef)
);
}
}
else if(armor+weapon < taken){
if(weapon){
if(youdef){
pline("The tentacles somehow disentangle several objects from your person, including %s from your grip!",
u.twoweap && weapon > 1 ? "your weapons" : u.twoweap ? "a weapon" : "your weapon"
);
pline("You're pretty sure that wasn't physically possible.");
}
else {
pline("The tentacles somehow disentangle several objects from %s, including %s from %s grip!",
mon_nam(mdef),
!(MON_WEP(mdef) || MON_SWEP(mdef)) && weapon > 1 ? "the weapons" : u.twoweap ? "a weapon" : "the weapon",
mhis(mdef)
);
}
}
else if(armor){
if(youdef){
pline("The tentacles somehow disentangle several objects from your person, including %s from your body!",
(uarm || uarmc || uarmu || uarmh || uarmg || uarmf) ? "some clothes" : "the clothes"
);
pline("You're pretty sure that wasn't physically possible.");
}
else {
pline("The tentacles somehow disentangle several objects from %s, including %s from %s body!",
mon_nam(mdef),
(mdef->misc_worn_check&W_ARMOR) ? "some clothes" : "the clothes",
mhis(mdef)
);
}
}
else {//armor+weapon == 0
if(youdef){
pline("The tentacles somehow disentangle %s from your person!", taken > 1 ? "some objects" : "an object");
}
else {
pline("The tentacles somehow disentangle %s from %s!",
taken > 1 ? "some objects" : "an object",
mon_nam(mdef)
);
}
}
}
else {//armor == taken ^ weapon == taken
if(weapon){
if(youdef){
pline("The tentacles somehow disentangle %s from your grip!",
u.twoweap && weapon > 1 ? "your weapons" : u.twoweap ? "a weapon" : "your weapon"
);
pline("You're pretty sure that wasn't physically possible.");
}
else {
pline("The tentacles somehow disentangle %s from %s grip!",
!(MON_WEP(mdef) || MON_SWEP(mdef)) && weapon > 1 ? "the weapons" : u.twoweap ? "a weapon" : "the weapon",
s_suffix(mon_nam(mdef))
);
}
}
else if(armor){
if(youdef){
pline("The tentacles somehow disentangle %s from your body!",
(uarm || uarmc || uarmu || uarmh || uarmg || uarmf) ? "some clothes" : "the clothes"
);
pline("You're pretty sure that wasn't physically possible.");
}
else {
pline("The tentacles somehow disentangle %s from %s body!",
(mdef->misc_worn_check&W_ARMOR) ? "some clothes" : "the clothes",
s_suffix(mon_nam(mdef))
);
}
}
}
}
}
static void
doesscoo_theft(magr, wep)
struct monst *magr;
struct obj *wep;
{
struct monst *mdef;
extern const int clockwisex[8];
extern const int clockwisey[8];
int i = rnd(8),j;
boolean youagr = (magr == &youmonst);
boolean youdef;
struct obj *inventory;
for(j=8;j>=1;j--){
if(youagr && u.ustuck && u.uswallow)
mdef = u.ustuck;
else if(!isok(x(magr)+clockwisex[(i+j)%8], y(magr)+clockwisey[(i+j)%8]))
continue;
else mdef = m_u_at(x(magr)+clockwisex[(i+j)%8], y(magr)+clockwisey[(i+j)%8]);
youdef = (mdef == &youmonst);
if(mdef && DEADMONSTER(mdef))
mdef = (struct monst *)0;
if(mdef){
if(youagr && mdef->mpeaceful)
continue;
if(youdef && magr->mpeaceful)
continue;
if(!youagr && !youdef && (mdef->mpeaceful == magr->mpeaceful))
continue;
if(!youdef && nonthreat(mdef))
continue;
//Note: petrifying targets are safe, it's not an attack
if(mdef->mtyp == PM_PALE_NIGHT) continue;
}
inventory = youdef ? invent : mdef ? mdef->minvent : level.objects[x(magr)+clockwisex[(i+j)%8]][y(magr)+clockwisey[(i+j)%8]];
// inventory = youdef ? invent : mdef ? mdef->minvent : (struct obj *)0;
if(!inventory)
continue;
if(!mdef){
if(youagr || canseemon(magr))
pline("The aura of strange tentacles investigates a pile of debris!");
else
pline("Strange tentacles investigate a pile of debris!");
}
else if(youdef){
if(canseemon(magr))
pline("The aura of strange tentacles investigates your belongings!");
else pline("Strange tentacles investigate your belongings!");
}
else if(youagr){
if(canseemon(mdef))
pline("The aura of strange tentacles investigates %s belongings!", s_suffix(mon_nam(mdef)));
else pline("The aura of strange tentacles investigates something!");
}
else {
if(canseemon(mdef) && canseemon(magr))
pline("The aura of strange tentacles investigates %s belongings!", s_suffix(mon_nam(mdef)));
else if(canseemon(magr))
pline("The aura of strange tentacles investigates something!");
else
pline("Strange tentacles investigate something!");
}
dotsmi_theft(magr, mdef, inventory, wep);
break;//Only one target per proc
}
}
boolean
floor_magic(magr)
struct monst *magr;
{
extern const int clockwisex[8];
extern const int clockwisey[8];
int i;
for(i=7;i>=0;i--){
if(OBJ_AT(x(magr)+clockwisex[i], y(magr)+clockwisey[i]))
return TRUE;
}
return FALSE;
}
void
doliving_esscoo(magr, wep, invoked)
struct monst *magr;
struct obj *wep;
boolean invoked;
{
if(!invoked){
if(rn2(5))
return;
if(!floor_magic(magr) && !nearby_targets(magr))
return;
}
doesscoo_theft(magr, wep); /*Can steal magic powers (cancel target, and if successful gain a pot of gain energy)*/
}
void
doliving_healing_armor(magr, wep, invoked)
struct monst *magr;
@ -5092,7 +5357,7 @@ struct obj *wep;
continue;
}
if(!youdef && imprisoned(mdef))
if(!youdef && nonthreat(mdef))
continue;
//Note: petrifying targets are safe, it's a weapon attack
@ -5122,6 +5387,8 @@ struct obj *wep;
doliving_ringed_armor(magr, wep, FALSE);
else if(wep->oartifact == ART_IBITE_ARM)
doliving_ibite_arm(magr, wep, FALSE);
else if(wep->oartifact == ART_ESSCOOAHLIPBOOURRR)
doliving_esscoo(magr, wep, FALSE);
else doliving_single_attack(magr, wep);
}

View file

@ -56,13 +56,16 @@ pet_type()
return PM_SECRET_WHISPERER;
}
else if(Race_if(PM_DROW)){
if (Role_if(PM_HEALER)){
return (PM_KNIGHT);
}
if(Role_if(PM_NOBLEMAN)){
if(flags.initgend) return (PM_GIANT_SPIDER);
else return (PM_SMALL_CAVE_LIZARD);
}
if(preferred_pet == 's')
return (PM_CAVE_SPIDER);
else if(preferred_pet == ':' || preferred_pet == 'l')
else if(preferred_pet == ':')
return (PM_BABY_CAVE_LIZARD);
else
return (rn2(3) ? PM_CAVE_SPIDER : PM_BABY_CAVE_LIZARD);
@ -272,6 +275,44 @@ makedog()
if(mtmp->m_lev < mtmp->data->mlevel) mtmp->m_lev = mtmp->data->mlevel;
if(pettype == PM_KNIGHT){
struct obj *obj;
mtmp->m_lev = 1;
mon_adjust_speed(mtmp, -1, (struct obj *) 0);
obj = mongets(mtmp, CRAM_RATION, MKOBJ_NOINIT);
if(obj){
obj->quan = 3;
fix_object(obj);
fully_identify_obj(obj);
}
obj = mongets(mtmp, FOOD_RATION, MKOBJ_NOINIT);
if(obj){
obj->quan = 1;
fix_object(obj);
fully_identify_obj(obj);
}
obj = mongets(mtmp, HIGH_BOOTS, MKOBJ_NOINIT);
if(obj) fully_identify_obj(obj);
obj = mongets(mtmp, CHAIN_MAIL, MKOBJ_NOINIT);
if(obj) fully_identify_obj(obj);
obj = mongets(mtmp, GAUNTLETS, MKOBJ_NOINIT);
if(obj) fully_identify_obj(obj);
obj = mongets(mtmp, AMULET_OF_NULLIFY_MAGIC, MKOBJ_NOINIT);
fully_identify_obj(obj);
obj = mongets(mtmp, HELMET, MKOBJ_NOINIT);
if(obj) fully_identify_obj(obj);
obj = mongets(mtmp, KITE_SHIELD, MKOBJ_NOINIT);
if(obj) fully_identify_obj(obj);
obj = mongets(mtmp, LONG_SWORD, MKOBJ_NOINIT);
if(obj){
bless(obj);
obj->spe = 1;
fully_identify_obj(obj);
}
m_dowear(mtmp, TRUE);
init_mon_wield_item(mtmp);
}
if(Role_if(PM_HEALER)){
grow_up(mtmp, (struct monst *) 0);
//Technically might grow into a genocided form.
@ -1266,32 +1307,43 @@ int numdogs;
// finds weakest pet, and if there's more than 6 pets that count towards your limit
// it sets the weakest friendly
struct monst *curmon = 0, *weakdog = 0;
int witches = 0, familiars = 0;
for(curmon = fmon; curmon; curmon = curmon->nmon){
if(curmon->mtame && !(EDOG(curmon)->friend) && !(EDOG(curmon)->loyal) && !(EDOG(curmon)->dominated) && !is_suicidal(curmon->data)
&& !curmon->mspiritual && !(get_timer(curmon->timed, DESUMMON_MON) && !(get_mx(curmon, MX_ESUM) && curmon->mextra_p->esum_p->permanent))
){
if(curmon->mtame && !(EDOG(curmon)->friend) && !(EDOG(curmon)->loyal) && !(EDOG(curmon)->dominated) && !is_suicidal(curmon->data)
&& !curmon->mspiritual && !(get_timer(curmon->timed, DESUMMON_MON) && !(get_mx(curmon, MX_ESUM) && curmon->mextra_p->esum_p->permanent))
){
if(is_witch_mon(curmon)){
if(witches >= familiars)
numdogs++;
witches++;
}
else if(curmon->mtyp == PM_WITCH_S_FAMILIAR){
if(familiars >= witches)
numdogs++;
familiars++;
}
else
numdogs++;
if(!weakdog) weakdog = curmon;
if(weakdog->m_lev > curmon->m_lev)
weakdog = curmon; /* The weakest pet is stronger than the current pet */
else if(weakdog->m_lev == curmon->m_lev){ /* Do we need tiebreakers? */
if(weakdog->mtame > curmon->mtame)
weakdog = curmon; /* Tiebreaker 1: the weakest pet is more tame than the current pet */
else if(weakdog->mtame == curmon->mtame){ /* Do we need another tiebreaker? */
int weakdog_mlev = mon_max_lev(weakdog);
int curmon_mlev = mon_max_lev(curmon);
if(weakdog_mlev > curmon_mlev)
weakdog = curmon; /* Tiebreaker 2: the weakest pet has greater potential than the current pet */
else if(weakdog_mlev == curmon_mlev){
extern int monstr[];
if(monstr[weakdog->mtyp] > monstr[curmon->mtyp])
weakdog = curmon; /* Tiebreaker 3: the weakest pet has greater starting strength than the current pet */
}
if(!weakdog) weakdog = curmon;
if(weakdog->m_lev > curmon->m_lev)
weakdog = curmon; /* The weakest pet is stronger than the current pet */
else if(weakdog->m_lev == curmon->m_lev){ /* Do we need tiebreakers? */
if(weakdog->mtame > curmon->mtame)
weakdog = curmon; /* Tiebreaker 1: the weakest pet is more tame than the current pet */
else if(weakdog->mtame == curmon->mtame){ /* Do we need another tiebreaker? */
int weakdog_mlev = mon_max_lev(weakdog);
int curmon_mlev = mon_max_lev(curmon);
if(weakdog_mlev > curmon_mlev)
weakdog = curmon; /* Tiebreaker 2: the weakest pet has greater potential than the current pet */
else if(weakdog_mlev == curmon_mlev){
extern int monstr[];
if(monstr[weakdog->mtyp] > monstr[curmon->mtyp])
weakdog = curmon; /* Tiebreaker 3: the weakest pet has greater starting strength than the current pet */
}
}
}
}
}
if(weakdog && numdogs > dog_limit()) EDOG(weakdog)->friend = 1;
}

View file

@ -57,8 +57,8 @@ register struct obj *otmp;
if (is_cloak(otmp) && ((abs(otmp->objsize - mtmp->data->msize) > 1)))
return FALSE;
if (is_helmet(otmp) && (!has_head_mon(mtmp) || otmp->objsize != mtmp->data->msize || !helm_match(mtmp->data,otmp)) && !is_flimsy(otmp))
if (is_helmet(otmp) && !(helm_match(mtmp->data, otmp) && helm_size_fits(mtmp->data, otmp)))
return FALSE;
if (is_shield(otmp) && (
@ -72,7 +72,7 @@ register struct obj *otmp;
if (is_gloves(otmp) && (otmp->objsize != mtmp->data->msize || !can_wear_gloves(mtmp->data))) return FALSE;
if (is_boots(otmp) &&
(otmp->objsize != mtmp->data->msize || !can_wear_boots(mtmp->data)))
(!boots_size_fits(mtmp->data, otmp) || !can_wear_boots(mtmp->data)))
return FALSE;
if (is_helmet(otmp) &&
@ -308,11 +308,11 @@ struct obj *obj;
*/
if (obj->oclass == FOOD_CLASS) {
if(obj->otyp == CORPSE) {
mtmp->meating = 3 + (mons[obj->corpsenm].cwt >> 6);
nutrit = mons[obj->corpsenm].cnutrit;
mtmp->meating = 3 + (mons[obj->corpsenm].cwt >> 6);
nutrit = mons[obj->corpsenm].cnutrit;
} else {
mtmp->meating = objects[obj->otyp].oc_delay;
nutrit = objects[obj->otyp].oc_nutrition;
mtmp->meating = objects[obj->otyp].oc_delay;
nutrit = objects[obj->otyp].oc_nutrition;
}
switch(mtmp->data->msize) {
case MZ_TINY: nutrit *= 8; break;
@ -362,6 +362,7 @@ boolean devour;
int nutrit;
boolean vampiric = is_vampire(mtmp->data);
boolean eatonlyone = (obj->oclass == FOOD_CLASS || obj->oclass == CHAIN_CLASS || obj->oclass == POTION_CLASS);
int mtyp = NON_PM;
// boolean can_choke = (edog->hungrytime >= monstermoves + DOG_SATIATED && !vampiric);
boolean can_choke = mtmp->mgluttony && !Breathless_res(mtmp);
@ -377,7 +378,7 @@ boolean devour;
ston = (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN || obj->otyp == POT_BLOOD) && obj->corpsenm >= LOW_PM && touch_petrifies(&mons[obj->corpsenm]) && !Stone_res(mtmp);
if(obj->otyp == CORPSE){
int mtyp = obj->corpsenm;
mtyp = obj->corpsenm;
if (mtyp != PM_LIZARD && mtyp != PM_SMALL_CAVE_LIZARD && mtyp != PM_CAVE_LIZARD
&& mtyp != PM_LARGE_CAVE_LIZARD && mtyp != PM_LICHEN && mtyp != PM_BEHOLDER
) {
@ -559,6 +560,9 @@ boolean devour;
if (!grow_up(mtmp, (struct monst *)0)) return 2;
}
if (heal) mtmp->mhp = mtmp->mhpmax;
if(mtyp != NON_PM){
give_mon_corpse_intrinsic(mtmp, mtyp);
}
return 1;
}
@ -656,6 +660,70 @@ dog_died:
return(FALSE);
}
void
give_mon_corpse_intrinsic(mon, mtyp)
struct monst *mon;
int mtyp;
{
struct permonst *ptr = &mons[mtyp];
for (int i = 1; i <= LAST_PROP; i++) {
if (intrinsic_possible(i, ptr)) {
if(mon_acquired_trinsic(mon, i))
continue;
if(ptr->mlevel <= rn2(15))
continue;
give_mintrinsic(mon, i);
if(canspotmon(mon)){
#define Mon(str) pline("%s %s", Monnam(mon), str)
switch (i) {
case FIRE_RES:
Mon(Hallucination ? "be chillin'." :"looks cool.");
break;
case SLEEP_RES:
Mon("looks wide awake.");
break;
case COLD_RES:
Mon("looks warm.");
break;
case DISINT_RES:
Mon(Hallucination ? "has it totally together, man." : "looks very firm.");
break;
case SHOCK_RES: /* shock (electricity) resistance */
if (Hallucination)
rn2(2) ? Mon("is grounded in reality.") : pline("%s health is currently amplified!", s_suffix(Monnam(mon)));
else Mon("looks well grounded.");
break;
case ACID_RES: /* acid resistance */
if (Hallucination)
rn2(2) ? Mon("has really gotten back to basics!") : Mon("looks insoluble.");
else Mon("looks tough.");
break;
case POISON_RES:
Mon("looks healthy.");
break;
case DISPLACED: /* displacement resistance */
if (Hallucination) pline("%s is quite beside %sself!", Monnam(mon), mhim(mon));
else pline("%s outline shimmers and shifts.", s_suffix(Monnam(mon)));
break;
case TELEPORT:
Mon(Hallucination ? "looks diffuse." : "looks very jumpy.");
break;
case TELEPORT_CONTROL:
Mon(Hallucination ? "looks centered." : "looks in control.");
break;
case TELEPAT:
if(Hallucination){
Mon("is in touch with the cosmos.");
change_uinsight(1);
}
//else nothing
break;
}
}
}
}
}
/* do something with object (drop, pick up, eat) at current position
* returns 1 if object eaten (since that counts as dog's move), 2 if died
*/
@ -995,10 +1063,18 @@ betrayed(mtmp)
register struct monst *mtmp;
{
int udist = distu(mtmp->mx, mtmp->my);
if(get_mx(mtmp, MX_EDOG)){
if(EDOG(mtmp)->loyal)
return FALSE;
else if(EDOG(mtmp)->waspeaceful && mtmp->mpeacetime == 0 && u.uhp >= u.uhpmax/10)
return FALSE;
}
// pline("testing for betrayal");
if ( (udist < 4 || !rn2(3))
&& get_mx(mtmp, MX_EDOG)
&& (can_betray(mtmp->data) || roll_madness(MAD_PARANOIA))
&& u.uhp < u.uhpmax/2 /* You look like you're in a bad spot */
&& mtmp->mhp >= u.uhp /* Pet is buff enough */
&& rn2(22) > mtmp->mtame - 10 /* Roll against tameness */
&& rn2(EDOG(mtmp)->abuse + 2)) {
@ -1164,7 +1240,7 @@ register int after; /* this is extra fast monster movement */
{
if(!mtarget_adjacent(mtmp)){ /* don't fight at range if there's a melee target */
/* Look for monsters to fight (at a distance) */
struct monst *mtmp2 = mfind_target(mtmp, FALSE);
struct monst *mtmp2 = mfind_target(mtmp, FALSE, TRUE);
if (mtmp2 && (mtmp2 != mtmp)
&& (mtmp2 != &youmonst)
&& acceptable_pet_target(mtmp, mtmp2, TRUE))

View file

@ -901,10 +901,20 @@ init_dungeons() /* initialize the "dungeon" structs */
dungeons[i].boneid = pd.tmpdungeon[i].boneschar;
if(pd.tmpdungeon[i].lev.rand)
dungeons[i].num_dunlevs = (int)rn1(pd.tmpdungeon[i].lev.rand,
pd.tmpdungeon[i].lev.base);
dungeons[i].num_dunlevs = (int)rn1(pd.tmpdungeon[i].lev.rand,
pd.tmpdungeon[i].lev.base);
else dungeons[i].num_dunlevs = (int)pd.tmpdungeon[i].lev.base;
if(!strcmp(dungeons[i].dname, "The Quest")){
quest_i = TRUE;
if(urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH){
if(dungeons[i].num_dunlevs < 6){
dungeons[i].num_dunlevs = 6;
}
}
}
else quest_i = FALSE;
if(!i) {
dungeons[i].ledger_start = 0;
dungeons[i].depth_start = 1;
@ -990,10 +1000,23 @@ init_dungeons() /* initialize the "dungeon" structs */
* special levels until they are all placed.
*/
for(; cl < pd.n_levs; cl++) {
Fread((genericptr_t)&pd.tmplevel[cl],
sizeof(struct tmplevel), 1, dgn_file);
init_level(i, cl, &pd);
Fread((genericptr_t)&pd.tmplevel[cl],
sizeof(struct tmplevel), 1, dgn_file);
init_level(i, cl, &pd);
}
//If the quest is long enough, move the locate level to create one to two of each filler level
// New levels are added to the end of tmplevel, this asumes that the locate level is 2nd to last :(
if(quest_i){
if(urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH){
pd.tmplevel[pd.n_levs-2].lev.base++;
}
else if(dungeons[i].num_dunlevs == 7){
pd.tmplevel[pd.n_levs-2].lev.base++;
}
else if(dungeons[i].num_dunlevs == 6){
pd.tmplevel[pd.n_levs-2].lev.base += rn2(2);
}
}
/*
* Recursively place the generated levels for this dungeon. This
* routine will attempt all possible combinations before giving
@ -1994,6 +2017,7 @@ print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices)
add_menu(win, NO_GLYPH, &any, lchoices->menuletter,
0, ATR_NONE, buf, MENU_UNSELECTED);
if (lchoices->menuletter == 'z') lchoices->menuletter = 'A';
else if (lchoices->menuletter == 'Z') lchoices->menuletter = 'a';
else lchoices->menuletter++;
lchoices->idx++;
} else
@ -2061,6 +2085,7 @@ int *rdgn; /* returns selected level dungeon number */
lchoices.dgn[lchoices.idx] = i;
add_menu(win, NO_GLYPH, &any, lchoices.menuletter, 0, dungeonsfirst ? ATR_NONE : iflags.menu_headings, buf, MENU_UNSELECTED);
if (lchoices.menuletter == 'z') lchoices.menuletter = 'A';
else if (lchoices.menuletter == 'Z') lchoices.menuletter = 'a';
else lchoices.menuletter++;
lchoices.idx++;
}

View file

@ -25,7 +25,6 @@ STATIC_DCL void NDECL(recalc_wt);
STATIC_DCL struct obj *FDECL(touchfood, (struct obj *));
STATIC_DCL void NDECL(do_reset_eat);
STATIC_DCL void FDECL(done_eating, (BOOLEAN_P));
STATIC_DCL int FDECL(intrinsic_possible, (int,struct permonst *));
STATIC_DCL void FDECL(givit, (int,struct permonst *,SHORT_P,BOOLEAN_P));
STATIC_DCL void FDECL(start_tin, (struct obj *));
STATIC_DCL int FDECL(eatcorpse, (struct obj *));
@ -861,7 +860,7 @@ fix_petrification()
*/
/* intrinsic_possible() returns TRUE iff a monster can give an intrinsic. */
STATIC_OVL int
int
intrinsic_possible(type, ptr)
int type;
register struct permonst *ptr;
@ -869,7 +868,7 @@ register struct permonst *ptr;
switch (type) {
case FIRE_RES:
if (ptr->mconveys & MR_FIRE) {
//debugpline("can get fire resistance");
debugpline("can get fire resistance");
return(TRUE);
} else return(FALSE);
case SLEEP_RES:

View file

@ -858,6 +858,18 @@ Check_crystal_lifesaving()
return FALSE;
}
boolean
Check_iaso_lifesaving()
{
for(struct monst *mon = fmon; mon; mon = mon->nmon)
if(mon->mtyp == PM_IASOIAN_ARCHON
&& !mon->mcan && !nonthreat(mon)
&& mon->mtame
)
return TRUE;
return FALSE;
}
STATIC_OVL void
Use_crystal_lifesaving()
{
@ -916,6 +928,36 @@ Use_crystal_lifesaving()
impossible("Crystal lifesaving with invalid crystals!?");
}
STATIC_OVL void
Use_iaso_lifesaving()
{
struct monst *mon;
int count = 0;
for(mon = fmon; mon; mon = mon->nmon)
if(mon->mtyp == PM_IASOIAN_ARCHON
&& !mon->mcan && !nonthreat(mon)
&& mon->mtame
)
count++;
if(count){
count = rn2(count);
for(mon = fmon; mon; mon = mon->nmon)
if(mon->mtyp == PM_IASOIAN_ARCHON
&& !mon->mcan && !nonthreat(mon)
&& mon->mtame
){
if(!count){
set_mcan(mon, TRUE);
if(canspotmon(mon))
pline("%s seems lackluster.", Monnam(mon));
return;
}
else count--;
}
}
impossible("Iasoian lifesaving but can't find pet!?");
}
/* Be careful not to call panic from here! */
void
done(how)
@ -995,10 +1037,10 @@ int how;
if(uarmh && uarmh->oartifact == ART_HELM_OF_UNDEATH) {
otmp = uarmh;
if (!(
((mvitals[PM_DEATH_KNIGHT].mvflags & G_GENOD) && !In_quest(&u.uz)) ||/* G_EXTINCT okay */
(mvitals[PM_DEATH_KNIGHT].mvflags & G_GENOD) ||/* G_EXTINCT okay */
(Unchanging) ||
is_undead(youracedata)
)) {
)) {
You_feel("a curse fall upon your soul!");
if (Upolyd && uskin && uskin->oartifact == ART_MIRRORED_MASK) {
pline("Your mask falls to pieces!");
@ -1024,6 +1066,20 @@ int how;
obfree(otmp, (struct obj *)0);
}
}
else if(Check_iaso_lifesaving()){
if(Hallucination){
//"I got better..."
You("get better.");
}
else {
if (how == CHOKING) You("vomit ...");
if (how == DISINTEGRATED) You("reconstitute!");
else if (how == OVERWOUND) You("reassemble!");
else You("miraculously recover!");
}
Use_iaso_lifesaving();
lsvd = LSVD_MISC;
}
else if(uamul && uamul->otyp == AMULET_OF_LIFE_SAVING){
if(!check_oprop(uamul, OPROP_LIFE))
makeknown(AMULET_OF_LIFE_SAVING);

View file

@ -712,6 +712,9 @@ const char * haluWard[] = {
/* Eddergud holy symbol */
"an obsidian spiderweb",
/* Y-cult holy symbol */
"a Y with curled tips",
/* Footprint */
"a footprint",
/* Hoofprint */
@ -4522,15 +4525,41 @@ int f1,f2;
f1 = f2;
f2 = tmp;
}
/*Ruling houses*/
if(f1 >= FIRST_HOUSE && f1 <= LAST_HOUSE){
return (f2 >= FIRST_TOWER && f2 <= LAST_TOWER) || (f2 == LOLTH_SYMBOL || f2 == PEN_A_SYMBOL);
} else if(f1 >= FIRST_FALLEN_HOUSE && f1 <= LAST_FALLEN_HOUSE){
return (f2 >= FIRST_TOWER && f2 <= LAST_TOWER) || (f2 == KIARANSALEE_SYMBOL || f2 == PEN_A_SYMBOL);
} else if(f1 >= FIRST_TOWER && f1 <= LAST_TOWER){
return (f2 >= FIRST_GODDESS && f2 <= LAST_GODDESS) || f2 == XAXOX;
} else if(f1 == XAXOX){
/*with elite towers, lolth, and pen'a*/
return (f2 >= FIRST_TOWER && f2 <= LAST_TOWER) || f2 == LOLTH_SYMBOL || f2 == PEN_A_SYMBOL || f2 == GHAUNADAUR_SYMBOL;
}
/*Fallen houses*/
else if(f1 >= FIRST_FALLEN_HOUSE && f1 <= LAST_FALLEN_HOUSE){
/*with elite towers, kiaransalee, and pen'a*/
return (f2 >= FIRST_TOWER && f2 <= LAST_TOWER) || f2 == KIARANSALEE_SYMBOL || f2 == PEN_A_SYMBOL || f2 == GHAUNADAUR_SYMBOL;
}
/*Elite towers*/
else if(f1 >= FIRST_TOWER && f1 <= LAST_TOWER){
/*with all goddesses (except eilistraee) and tower xaxox*/
return (f2 >= FIRST_GODDESS && f2 <= LAST_GODDESS) || f2 == XAXOX || f2 == GHAUNADAUR_SYMBOL;
}
/*Tower xaxox*/
else if(f1 == XAXOX){
/*also with the eddergud*/
return (f2 == EDDER_SYMBOL);
}
else if(f1 == LOLTH_SYMBOL){
return (f2 >= FIRST_GODDESS && f2 <= LAST_GODDESS) || f2 == GHAUNADAUR_SYMBOL;
}
else if(f1 == KIARANSALEE_SYMBOL){
return f2 == PEN_A_SYMBOL || f2 == GHAUNADAUR_SYMBOL;
}
else if(f1 == PEN_A_SYMBOL){
return (f2 >= FIRST_GODDESS && f2 <= LAST_GODDESS) || f2 == EILISTRAEE_SYMBOL || f2 == GHAUNADAUR_SYMBOL || f2 == LOST_HOUSE;
}
else if(f1 == VER_TAS_SYMBOL){
return f2 == GHAUNADAUR_SYMBOL;
}
else if(f1 == GHAUNADAUR_SYMBOL){
return f2 == LOST_HOUSE;
}
else return FALSE;
}

View file

@ -707,7 +707,7 @@ boolean dumping;
}
if(has_blood(youracedata)){
if (u.umadness&MAD_FRENZY){
Sprintf(buf, "your %s seethe below your %s", body_part(BLOOD), body_part(BODY_SKIN));
Sprintf(buf, "your %s seethes below your %s", body_part(BLOOD), body_part(BODY_SKIN));
enl_msg("You ", "feel ", "felt ", buf);
}
}
@ -1327,7 +1327,7 @@ resistances_enlightenment()
}
if(has_blood(youracedata)){
if (u.umadness&MAD_FRENZY){
Sprintf(buf, "You feel your %s seethe below your %s.", body_part(BLOOD), body_part(BODY_SKIN));
Sprintf(buf, "You feel your %s seethes below your %s.", body_part(BLOOD), body_part(BODY_SKIN));
putstr(en_win, 0, buf);
messaged++;
}

View file

@ -122,7 +122,7 @@ ExplodeRegion *reg;
/* This is the "do-it-all" explosion command */
STATIC_DCL void FDECL(do_explode,
(int,int,ExplodeRegion *,int,int,int,int,int,BOOLEAN_P));
(int,int,ExplodeRegion *,int,int,int,int,int,BOOLEAN_P, struct permonst *));
/* Note: I had to choose one of three possible kinds of "type" when writing
* this function: a wand type (like in zap.c), an adtyp, or an object type.
@ -140,6 +140,19 @@ int olet;
int dam;
int color;
int radius;
{
explode_pa(x, y, adtyp, olet, dam, color, radius, (struct permonst *) 0);
}
void
explode_pa(x, y, adtyp, olet, dam, color, radius, pa)
int x, y;
int adtyp; /* the same as in zap.c */
int olet;
int dam;
int color;
int radius;
struct permonst *pa;
{
ExplodeRegion *area;
area = create_explode_region();
@ -161,7 +174,7 @@ int radius;
do_clear_area(x, y, radius, add_location_to_explode_region, (genericptr_t)(area));
}
do_explode(x, y, area, adtyp, olet, dam, color, 0, !flags.mon_moving);
do_explode(x, y, area, adtyp, olet, dam, color, 0, !flags.mon_moving, pa);
free_explode_region(area);
}
@ -195,7 +208,7 @@ boolean yours; /* is it your fault (for killing monsters) */
do_clear_area(x, y, radius, add_location_to_explode_region, (genericptr_t)(area));
}
do_explode(x, y, area, adtyp, olet, dam, color, 0, yours);
do_explode(x, y, area, adtyp, olet, dam, color, 0, yours, (struct permonst *)0);
free_explode_region(area);
}
@ -230,12 +243,12 @@ int color;
if (isok(x + i, y + j) && ((!i && dx) || (!j && dy) || ((!dx || i == dx) & (!dy || j == dy))) && ((ZAP_POS(levl[x][y].typ) || distmin(x - dx, y - dy, x + i, y + j) == 1) || ZAP_POS(levl[x - dx + i][y - dy + j].typ))) // it looks strange, but it works
add_location_to_explode_region(x + i, y + j, area);
do_explode(x, y, area, adtyp, olet, dam, color, 0, !flags.mon_moving);
do_explode(x, y, area, adtyp, olet, dam, color, 0, !flags.mon_moving, (struct permonst *)0);
free_explode_region(area);
}
STATIC_DCL void
do_explode(x, y, area, adtyp, olet, dam, color, dest, yours)
do_explode(x, y, area, adtyp, olet, dam, color, dest, yours, pa)
int x, y;
ExplodeRegion *area;
int adtyp; /* AD_TYPE and O_CLASS describing the cause of the explosion */
@ -244,6 +257,7 @@ int dam;
int color;
int dest; /* 0 = normal, 1 = silent, 2 = silent/remote */
boolean yours; /* is it your fault (for killing monsters) */
struct permonst *pa; /* permonst of the attacker (used for disease) */
{
int i, k, damu = dam;
boolean starting = 1, silver = FALSE;
@ -356,9 +370,10 @@ boolean yours; /* is it your fault (for killing monsters) */
case AD_SLIM:
explmask = (Acid_resistance || Slime_res(&youmonst));
break;
case AD_DISE: /*assumes only swamp ferns have disease explosions*/
case AD_DISE:
explmask = !!Sick_resistance;
diseasemu(&mons[PM_SWAMP_FERN_SPORE]);
if(pa)
diseasemu(pa);
break;
case AD_DARK:
explmask = !!Dark_immune;
@ -1229,7 +1244,7 @@ int dest;
grenade_effects(obj, x, y, fiery_area, gas_area, dig_area, isyou);
if (fiery_area->nlocations) {
adtyp = AD_FIRE;
do_explode(x, y, fiery_area, adtyp, WEAPON_CLASS, d(3,6), EXPL_FIERY, dest, isyou);
do_explode(x, y, fiery_area, adtyp, WEAPON_CLASS, d(3,6), EXPL_FIERY, dest, isyou, (struct permonst *)0);
}
wake_nearto(x, y, 400);
/* Like cartoons - the explosion first, then
@ -1255,7 +1270,7 @@ int dest;
if (gas_area->nlocations) {
adtyp = AD_DRST;
do_explode(x, y, gas_area, adtyp, WEAPON_CLASS, d(3,6),
EXPL_NOXIOUS, dest, isyou);
EXPL_NOXIOUS, dest, isyou, (struct permonst *)0);
}
free_explode_region(gas_area);
if (shop_damage) pay_for_damage("damage", FALSE);

View file

@ -1894,6 +1894,17 @@ stillinwater:;
zap_over_floor(u.ux, u.uy, AD_COLD, WAND_CLASS, FALSE, NULL);
}
}
if(!Levitation && !Flying && In_quest(&u.uz) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && levl[u.ux][u.uy].typ == AIR){
if(on_level(&u.uz, &qstart_level) && !ok_to_quest()){
pline("A mysterious force prevents you from falling.");
} else {
struct d_level target_level;
target_level.dnum = u.uz.dnum;
target_level.dlevel = qlocate_level.dlevel+1;
int dist = qlocate_level.dlevel+1 - u.uz.dlevel;
schedule_goto(&target_level, FALSE, TRUE, FALSE, "You plummet through the cavern air!", "You slam into the rocky floor!", d(dist*5,6));
}
}
check_special_room(FALSE);
#ifdef SINKS
if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)

View file

@ -36,6 +36,8 @@ STATIC_DCL boolean FDECL(tool_in_use, (struct obj *));
STATIC_DCL char FDECL(obj_to_let,(struct obj *));
STATIC_PTR int FDECL(u_material_next_to_skin,(int));
STATIC_PTR int FDECL(u_bcu_next_to_skin,(int));
STATIC_PTR int FDECL(mon_material_next_to_skin,(struct monst *, int));
STATIC_PTR int FDECL(mon_bcu_next_to_skin,(struct monst *, int));
STATIC_DCL int FDECL(itemactions,(struct obj *));
#ifdef OVLB
@ -859,6 +861,7 @@ carrying_readable_weapon()
otmp->oartifact == ART_GUNGNIR ||
otmp->oartifact == ART_PEN_OF_THE_VOID ||
otmp->oartifact == ART_HOLY_MOONLIGHT_SWORD ||
otmp->oartifact == ART_ESSCOOAHLIPBOOURRR ||
otmp->oartifact == ART_STAFF_OF_NECROMANCY
))
)
@ -890,8 +893,7 @@ carrying_readable_armor()
for(otmp = invent; otmp; otmp = otmp->nobj)
if(otmp->oclass == ARMOR_CLASS
&& ((otmp->ohaluengr
&& otmp->oward
&& is_readable_armor_otyp(otmp->otyp)
&& is_readable_armor(otmp)
) || (otmp->oartifact && (
otmp->oartifact == ART_ITLACHIAYAQUE
)
@ -1281,10 +1283,13 @@ register const char *let,*word;
otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF) ||
/* MRKR: mining helmets */
(otmp->oclass == ARMOR_CLASS &&
otyp != LANTERN_PLATE_MAIL &&
otyp != DWARVISH_HELM &&
otyp != DROVEN_CLOAK &&
otyp != GNOMISH_POINTY_HAT &&
otmp->oartifact != ART_AEGIS
otmp->oartifact != ART_AEGIS &&
otmp->oartifact != ART_STAFF_OF_AESCULAPIUS &&
otmp->oartifact != ART_ESSCOOAHLIPBOOURRR
) ||
(otmp->oclass == GEM_CLASS && !is_graystone(otmp)
&& otyp != CATAPSI_VORTEX && otyp != ANTIMAGIC_RIFT
@ -2426,7 +2431,7 @@ struct obj *obj;
else if (obj->oartifact == ART_STAFF_OF_NECROMANCY)
add_menu(win, NO_GLYPH, &any, 'r', 0, ATR_NONE,
"Study the forbidden secrets of necromancy", MENU_UNSELECTED);
else if (obj->oartifact == ART_STAFF_OF_AESCULAPIUS)
else if (obj->oartifact == ART_STAFF_OF_AESCULAPIUS || obj->oartifact == ART_ESSCOOAHLIPBOOURRR)
add_menu(win, NO_GLYPH, &any, 'r', 0, ATR_NONE,
"Study the grand magic of healing", MENU_UNSELECTED);
else if (obj->oartifact == ART_HOLY_MOONLIGHT_SWORD && obj->lamplit)
@ -5551,6 +5556,42 @@ boolean as_if_seen;
return n;
}
int
mon_healing_penalty(mon)
struct monst *mon;
{
int penalty = 0;
if(hates_silver(mon->data)){
penalty += (20*mon_material_next_to_skin(mon, SILVER))/2;
}
if(hates_iron(mon->data)){
penalty += (mon->m_lev * mon_material_next_to_skin(mon, IRON)+1)/2;
penalty += (mon->m_lev * mon_material_next_to_skin(mon, GREEN_STEEL)+1)/2;
}
if(hates_unholy_mon(mon)){
penalty += (9*mon_bcu_next_to_skin(mon, -1)+1)/2;
penalty += 9*mon_material_next_to_skin(mon, GREEN_STEEL);
}
if(hates_unblessed_mon(mon)){
penalty += (8*mon_bcu_next_to_skin(mon, 0)+1)/2;
}
if(hates_holy_mon(mon)){
penalty += (4*mon_bcu_next_to_skin(mon, 1)+1)/2;
}
if(is_chaotic_mon(mon)){
int plat_penalty = 5 * mon_material_next_to_skin(mon, PLATINUM);
if(is_minion(mon->data) || is_demon(mon->data))
plat_penalty *= 2;
/* strongly chaotic beings are hurt more */
if(mon->mtyp == PM_ANGEL || mon->data->maligntyp <= -10)
plat_penalty *= 2;
penalty += plat_penalty/2;
}
return penalty;
}
int
u_healing_penalty()
{
@ -5656,6 +5697,131 @@ u_clothing_discomfort()
return count; //0-25
}
STATIC_OVL int
mon_material_next_to_skin(mon, material)
struct monst *mon;
int material;
{
int count = 0;
struct obj *curarm;
boolean marm_blocks_ub = FALSE;
boolean hasgloves = !!which_armor(mon, W_ARMG);
boolean hasshirt = !!which_armor(mon, W_ARMU);
curarm = which_armor(mon, W_ARMU);
if(curarm && curarm->obj_material == material)
count += curarm->otyp == BODYGLOVE ? 5 : 1;
if(curarm && curarm->otyp == BODYGLOVE)
return count;
if(MON_WEP(mon) && MON_WEP(mon)->obj_material == material && !hasgloves)
count++;
curarm = which_armor(mon, W_ARM);
if(curarm && curarm->obj_material == material && !hasshirt)
count++;
if(curarm && arm_blocks_upper_body(curarm->otyp))
marm_blocks_ub = TRUE;
curarm = which_armor(mon, W_ARMC);
if(curarm && curarm->obj_material == material && !hasshirt && !marm_blocks_ub)
count++;
curarm = which_armor(mon, W_ARMH);
if(curarm && curarm->obj_material == material)
count++;
curarm = which_armor(mon, W_ARMS);
if(curarm && curarm->obj_material == material && !hasgloves)
count++;
curarm = which_armor(mon, W_ARMG);
if(curarm && curarm->obj_material == material)
count++;
curarm = which_armor(mon, W_ARMF);
if(curarm && curarm->obj_material == material)
count++;
curarm = which_armor(mon, W_AMUL);
if(curarm && curarm->obj_material == material && !hasshirt && !marm_blocks_ub)
count++;
if(mon->entangled && !hasshirt && !marm_blocks_ub && !which_armor(mon, W_ARMC) && entangle_material(mon, material))
count++;
curarm = which_armor(mon, W_TOOL);
if(curarm && curarm->obj_material == material)
count++;
if(MON_SWEP(mon) && MON_SWEP(mon)->obj_material == material && !hasgloves)
count++;
return count;
}
STATIC_OVL int
mon_bcu_next_to_skin(mon, bcu)
struct monst *mon;
int bcu;
{
#define bcu(otmp) (is_unholy(otmp) ? -1 : otmp->blessed ? 1 : 0)
int count = 0;
struct obj *curarm;
boolean marm_blocks_ub = FALSE;
boolean hasgloves = !!which_armor(mon, W_ARMG);
boolean hasshirt = !!which_armor(mon, W_ARMU);
curarm = which_armor(mon, W_ARMU);
if(curarm && bcu(curarm) == bcu)
count += curarm->otyp == BODYGLOVE ? 5 : 1;
if(curarm && curarm->otyp == BODYGLOVE)
return count;
if(MON_WEP(mon) && bcu(MON_WEP(mon)) == bcu && !hasgloves)
count++;
curarm = which_armor(mon, W_ARM);
if(curarm && bcu(curarm) == bcu && !hasshirt)
count++;
if(curarm && arm_blocks_upper_body(curarm->otyp))
marm_blocks_ub = TRUE;
curarm = which_armor(mon, W_ARMC);
if(curarm && bcu(curarm) == bcu && !hasshirt && !marm_blocks_ub)
count++;
curarm = which_armor(mon, W_ARMH);
if(curarm && bcu(curarm) == bcu)
count++;
curarm = which_armor(mon, W_ARMS);
if(curarm && bcu(curarm) == bcu && !hasgloves)
count++;
curarm = which_armor(mon, W_ARMG);
if(curarm && bcu(curarm) == bcu)
count++;
curarm = which_armor(mon, W_ARMF);
if(curarm && bcu(curarm) == bcu)
count++;
curarm = which_armor(mon, W_AMUL);
if(curarm && bcu(curarm) == bcu && !hasshirt && !marm_blocks_ub)
count++;
if(mon->entangled && !hasshirt && !marm_blocks_ub && !which_armor(mon, W_ARMC) && entangle_beatitude(mon, bcu))
count++;
curarm = which_armor(mon, W_TOOL);
if(curarm && bcu(curarm) == bcu)
count++;
if(MON_SWEP(mon) && bcu(MON_SWEP(mon)) == bcu && !hasgloves)
count++;
return count;
}
STATIC_OVL int
u_material_next_to_skin(material)
int material;

View file

@ -618,6 +618,7 @@ obj_is_burning(obj)
return (obj->lamplit &&
( ignitable(obj) /* lightsource uses a flame */
|| obj->otyp == LANTERN /* electric */
|| obj->otyp == LANTERN_PLATE_MAIL /* electric */
|| obj->otyp == DWARVISH_HELM /* electric */
|| (is_lightsaber(obj) && obj->oartifact != ART_INFINITY_S_MIRRORED_ARC && obj->otyp != KAMEREL_VAJRA) /* future-electric */
|| obj->oartifact == ART_HOLY_MOONLIGHT_SWORD)); /* magical fire */

View file

@ -256,20 +256,24 @@ forcelock() /* try to force a locked chest */
pline("In fact, you've totally destroyed %s.",
the(xname(xlock.box)));
/* Put the contents on ground at the hero's feet. */
if (xlock.box->spe == 1) {
observe_quantum_cat(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 4){
open_coffin(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 5){
open_sarcophagus(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 6){ /*Note: destroying the box always releases the crazy*/
open_crazy_box(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 7){
// Madman reclaims their stuff. Contents handled by the level loader.
open_madstuff_box(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 8){
// Nothing.
if(Is_real_container(xlock.box)){
/* Put the contents on ground at the hero's feet. */
if (xlock.box->spe == 1) {
observe_quantum_cat(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 4){
open_coffin(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 5){
open_sarcophagus(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 6){ /*Note: destroying the box always releases the crazy*/
open_crazy_box(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 7){
// Madman reclaims their stuff. Contents handled by the level loader.
open_madstuff_box(xlock.box, TRUE); //TRUE: use past tense
}else if(xlock.box->spe == 8){
// Nothing.
}else if(xlock.box->spe == 9){
open_giants_sack(xlock.box, TRUE); //TRUE: use past tense
}
}
while ((otmp = xlock.box->cobj) != 0) {
obj_extract_self(otmp);

View file

@ -20,7 +20,7 @@ struct monst zeromonst;
#ifdef OVL0
STATIC_DCL int FDECL(makemon_set_template, (struct permonst **, int, boolean));
STATIC_DCL int FDECL(makemon_get_permonst_faction, (struct permonst *, int));
STATIC_DCL int FDECL(makemon_get_permonst_faction, (struct permonst *, int, int, int, int));
STATIC_DCL void FDECL(makemon_set_monster_faction, (struct monst *));
STATIC_DCL boolean FDECL(uncommon, (int));
STATIC_DCL int FDECL(align_shift, (struct permonst *));
@ -503,6 +503,14 @@ boolean goodequip;
if (ptr->mtyp == PM_MINOTAUR) {
if (!rn2(3) || (in_mklev && Is_earthlevel(&u.uz)))
(void) mongets(mtmp, WAN_DIGGING, mkobjflags);
} else if(ptr->mtyp == PM_HILL_GIANT){
if(In_quest(&u.uz) && urole.neminum == PM_CYCLOPS && in_mklev){
otmp = mongets(mtmp, SACK, NO_MKOBJ_FLAGS);
if(otmp){
otmp->spe = 9; //plague victim
fix_object(otmp);
}
}
} else if(ptr->mtyp == PM_DEEPEST_ONE
|| ptr->mtyp == PM_FATHER_DAGON
|| ptr->mtyp == PM_MOTHER_HYDRA) {
@ -919,6 +927,7 @@ boolean goodequip;
int chance;
struct permonst *ptr = mtmp->data;
struct obj *otmp;
int y_cult_masks[] = {PM_SUCCUBUS, PM_INCUBUS, PM_HEZROU, PM_LILITU, PM_NALFESHNEE, PM_MARILITH, PM_BALROG, PM_SNAKE, PM_PIT_VIPER, PM_PYTHON, PM_APE, PM_CARNIVOROUS_APE };
if(mm == PM_ELDER_PRIEST){
otmp = mksobj(QUARTERSTAFF, mkobjflags);
bless(otmp);
@ -1159,7 +1168,7 @@ boolean goodequip;
otmp = mksobj(PLATE_MAIL, mkobjflags|MKOBJ_NOINIT);
set_material_gm(otmp, METAL);
otmp->bodytypeflag = MB_ANIMAL;
set_obj_shape(otmp, MB_ANIMAL);
fix_object(otmp);
(void) mpickobj(mtmp,otmp);
@ -1170,7 +1179,7 @@ boolean goodequip;
otmp = mksobj(FACELESS_HELM, mkobjflags|MKOBJ_NOINIT);
set_material_gm(otmp, METAL);
otmp->bodytypeflag = MB_LONGHEAD;
set_obj_shape(otmp, MB_LONGHEAD);
fix_object(otmp);
(void) mpickobj(mtmp,otmp);
} else if(ptr->mtyp == PM_SHATTERED_ZIGGURAT_CULTIST) {
@ -1830,6 +1839,175 @@ boolean goodequip;
(void)mongets(mtmp, DROVEN_SPEAR, mkobjflags);
break;
}
} else if(mm == PM_SISTER_T_EIRASTRA){
otmp = mongets(mtmp, SHOES, mkobjflags);
if(otmp){
set_material_gm(otmp, CLOTH);
bless(otmp);
otmp->obj_color = CLR_BLUE;
}
otmp = mongets(mtmp, WAISTCLOTH, mkobjflags);
if(otmp){
otmp->obj_color = CLR_BRIGHT_BLUE;
bless(otmp);
}
otmp = mongets(mtmp, DROVEN_CLOAK, mkobjflags);
if(otmp){
otmp->obj_color = CLR_BLUE;
bless(otmp);
}
otmp = mongets(mtmp, KHAKKHARA, mkobjflags);
if(otmp){
otmp->spe = max(3, otmp->spe);
add_oprop(otmp, OPROP_HOLYW);
bless(otmp);
}
}
else if(mm == PM_PEN_A_MENDICANT){
otmp = mongets(mtmp, SHOES, mkobjflags);
if(otmp){
set_material_gm(otmp, CLOTH);
otmp->obj_color = CLR_BLUE;
}
otmp = mongets(mtmp, WAISTCLOTH, mkobjflags);
if(otmp)
otmp->obj_color = CLR_BRIGHT_BLUE;
otmp = mongets(mtmp, DROVEN_CLOAK, mkobjflags);
if(otmp)
otmp->obj_color = CLR_BLUE;
otmp = mongets(mtmp, KHAKKHARA, mkobjflags);
} else if(mm == PM_Y_CULTIST){
otmp = mongets(mtmp, DROVEN_CLOAK, mkobjflags);
if(otmp) otmp->oeroded3 = 1;
otmp = mongets(mtmp, LEATHER_ARMOR, mkobjflags);
if(otmp) otmp->oeroded2 = 1;
otmp = mongets(mtmp, LOW_BOOTS, mkobjflags);
if(otmp) otmp->oeroded2 = 1;
otmp = mongets(mtmp, !rn2(10) ? STILETTO : KNIFE, mkobjflags);
if(otmp){
set_material_gm(otmp, rn2(2) ? IRON : rn2(2) ? OBSIDIAN_MT : BONE);
if(!rn2(20))
otmp->opoisoned = OPOISON_FILTH;
}
otmp = mongets(mtmp, MASK, mkobjflags);
if(otmp) otmp->corpsenm = ROLL_FROM(y_cult_masks);
} else if(mm == PM_Y_CULTIST_FIGHTER){
otmp = mongets(mtmp, DROVEN_CLOAK, mkobjflags);
if(otmp) otmp->oeroded3 = 1;
otmp = mongets(mtmp, SCALE_MAIL, mkobjflags);
if(otmp) otmp->oeroded = 1;
otmp = mongets(mtmp, HIGH_BOOTS, mkobjflags);
if (rn2(2)) (void)mongets(mtmp, DROVEN_DAGGER, mkobjflags);
(void)mongets(mtmp, DROVEN_SHORT_SWORD, mkobjflags);
switch (rn2(3)) {
case 0:
if (!rn2(4)) (void)mongets(mtmp, BUCKLER, mkobjflags);
if (rn2(3)) (void)mongets(mtmp, DROVEN_SHORT_SWORD, mkobjflags);
(void)mongets(mtmp, DROVEN_CROSSBOW, mkobjflags);
m_initthrow(mtmp, DROVEN_BOLT, 24, mkobjflags);
break;
case 1:
(void)mongets(mtmp, DROVEN_SHORT_SWORD, mkobjflags);
if (rn2(2)) (void)mongets(mtmp, KITE_SHIELD, mkobjflags);
(void)mongets(mtmp, DROVEN_DAGGER, mkobjflags);
(void)mongets(mtmp, DROVEN_DAGGER, mkobjflags);
break;
case 2:
if (!rn2(4)) {
(void)mongets(mtmp, DROVEN_SHORT_SWORD, mkobjflags);
(void)mongets(mtmp, BUCKLER, mkobjflags);
} else if(!rn2(3)){
(void)mongets(mtmp, DROVEN_SPEAR, mkobjflags);
} else if(!rn2(2)){
(void)mongets(mtmp, MORNING_STAR, mkobjflags);
} else {
(void)mongets(mtmp, DROVEN_GREATSWORD, mkobjflags);
}
break;
}
otmp = mongets(mtmp, MASK, mkobjflags);
if(otmp) otmp->corpsenm = ROLL_FROM(y_cult_masks);
} else if(mm == PM_Y_CULTIST_WIZARD){
otmp = mongets(mtmp, DROVEN_CLOAK, mkobjflags);
if(otmp) otmp->oeroded3 = 1;
(void)mongets(mtmp, LEATHER_ARMOR, mkobjflags);
(void)mongets(mtmp, HIGH_BOOTS, mkobjflags);
(void)mongets(mtmp, DROVEN_DAGGER, mkobjflags);
otmp = mongets(mtmp, DROVEN_SHORT_SWORD, mkobjflags);
if(otmp){
if(!rn2(20))
otmp->opoisoned = OPOISON_FILTH;
}
(void)mongets(mtmp, DROVEN_SHORT_SWORD, mkobjflags);
otmp = mongets(mtmp, MASK, mkobjflags);
if(otmp) otmp->corpsenm = ROLL_FROM(y_cult_masks);
} else if(mm == PM_Y_CULTIST_MATRON){
otmp = mongets(mtmp, DROVEN_CLOAK, mkobjflags);
if(otmp) otmp->oeroded3 = 1;
otmp = mongets(mtmp, PLAIN_DRESS, mkobjflags);
if(otmp){
otmp->oeroded2 = 1;
otmp->spe += 1;
}
otmp = mongets(mtmp, LEATHER_ARMOR, mkobjflags);
if(otmp) otmp->oeroded2 = 1;
otmp = mongets(mtmp, HIGH_BOOTS, mkobjflags);
if(otmp) otmp->oeroded2 = 1;
if(!rn2(20)){
otmp = mksobj(VIPERWHIP, mkobjflags);
otmp->spe = 2;
otmp->opoisoned = !rn2(20) ? OPOISON_FILTH : rn2(4) ? OPOISON_BASIC : OPOISON_PARAL;
otmp->opoisonchrgs = 1;
otmp->ovar1 = 6;
(void) mpickobj(mtmp, otmp);
otmp = mongets(mtmp, KHAKKHARA, mkobjflags);
if(otmp) set_material_gm(otmp, IRON);
(void)mongets(mtmp, DROVEN_DAGGER, mkobjflags);
(void)mongets(mtmp, DROVEN_DAGGER, mkobjflags);
(void)mongets(mtmp, DROVEN_DAGGER, mkobjflags);
} else {
otmp = mksobj(VIPERWHIP, mkobjflags);
otmp->spe = 2;
otmp->opoisoned = !rn2(20) ? OPOISON_FILTH : rn2(4) ? OPOISON_BASIC : OPOISON_PARAL;
otmp->opoisonchrgs = 1;
otmp->ovar1 = 2;
(void) mpickobj(mtmp, otmp);
(void)mongets(mtmp, DROVEN_SHORT_SWORD, mkobjflags);
otmp = mongets(mtmp, KITE_SHIELD, mkobjflags);
if(otmp) set_material_gm(otmp, SHADOWSTEEL);
}
otmp = mongets(mtmp, MASK, mkobjflags);
if(otmp) otmp->corpsenm = ROLL_FROM(y_cult_masks);
if(check_insight()){
set_template(mtmp, MOLY_TEMPLATE);
otmp = mongets(mtmp, MASK, mkobjflags);
if(otmp) otmp->corpsenm = ROLL_FROM(y_cult_masks);
}
} else if(mm == PM_Y_CULTIST_PATRON){
otmp = mksobj(STUDDED_LEATHER_ARMOR, mkobjflags);
otmp->spe += 6;
(void) mpickobj(mtmp, otmp);
otmp = mongets(mtmp, DROVEN_CLOAK, mkobjflags);
if(otmp) otmp->spe += 2;
otmp = mongets(mtmp, HIGH_BOOTS, mkobjflags);
if(otmp) otmp->spe += 2;
otmp = mongets(mtmp, BULLWHIP, mkobjflags);
if(otmp){
set_material_gm(otmp, BONE);
otmp->spe = 6;
}
otmp = mongets(mtmp, DROVEN_GREATSWORD, mkobjflags);
if(otmp){
otmp->spe = 4;
otmp->opoisoned = !rn2(4) ? OPOISON_FILTH : rn2(3) ? OPOISON_SLEEP : OPOISON_PARAL;
}
otmp = mongets(mtmp, MASK, mkobjflags);
if(otmp) otmp->corpsenm = ROLL_FROM(y_cult_masks);
if(check_insight()){
set_template(mtmp, MOLY_TEMPLATE);
otmp = mongets(mtmp, MASK, mkobjflags);
if(otmp) otmp->corpsenm = ROLL_FROM(y_cult_masks);
}
} else if(mm == PM_DROW_MATRON || mm == PM_DROW_MATRON_MOTHER || is_yochlol(mtmp->data)){
otmp = mksobj(DROVEN_PLATE_MAIL, mkobjflags);
otmp->ohaluengr = TRUE;
@ -2679,6 +2857,59 @@ boolean goodequip;
(void) mongets(mtmp, POT_EXTRA_HEALING, mkobjflags);
(void) mongets(mtmp, POT_HEALING, mkobjflags);
(void)mongets(mtmp, POT_HEALING, mkobjflags);
} else if (mm == PM_SIR_ALJANOR){
otmp = mongets(mtmp, ARMORED_BOOTS, mkobjflags);
if(otmp){
otmp->spe = max(3, otmp->spe);
bless(otmp);
}
otmp = mongets(mtmp, GAUNTLETS, mkobjflags);
if(otmp){
otmp->spe = max(3, otmp->spe);
bless(otmp);
}
otmp = mongets(mtmp, LANTERN_PLATE_MAIL, mkobjflags);
if(otmp){
bless(otmp);
otmp->spe = max(3, otmp->spe);
if (!levl[mtmp->mx][mtmp->my].lit) {
begin_burn(otmp);
}
}
otmp = mongets(mtmp, HELMET, mkobjflags);
if(otmp){
otmp->spe = max(3, otmp->spe);
bless(otmp);
}
otmp = mongets(mtmp, KITE_SHIELD, mkobjflags);
if(otmp){
otmp->spe = max(3, otmp->spe);
bless(otmp);
}
otmp = mongets(mtmp, rn2(3) ? SPEAR : LONG_SWORD, mkobjflags);
if(otmp){
set_material_gm(otmp, GOLD);
add_oprop(otmp, OPROP_HOLYW);
otmp->spe = max(3, otmp->spe);
bless(otmp);
}
} else if (mm == PM_ALLIANCE_VANGUARD){
(void) mongets(mtmp, HIGH_BOOTS, mkobjflags);
(void) mongets(mtmp, GAUNTLETS, mkobjflags);
otmp = mongets(mtmp, LANTERN_PLATE_MAIL, mkobjflags);
if(otmp){
bless(otmp);
if (!levl[mtmp->mx][mtmp->my].lit) {
begin_burn(otmp);
}
}
(void) mongets(mtmp, HELMET, mkobjflags);
(void) mongets(mtmp, KITE_SHIELD, mkobjflags);
otmp = mongets(mtmp, rn2(3) ? SPEAR : LONG_SWORD, mkobjflags);
if(otmp){
otmp->spe = max(1, otmp->spe);
bless(otmp);
}
} else if (mm == PM_PAGE){
(void) mongets(mtmp, SHORT_SWORD, mkobjflags);
(void) mongets(mtmp, BUCKLER, mkobjflags);
@ -3825,6 +4056,92 @@ boolean goodequip;
}
}
STATIC_OVL void
elemental_initinv(mtmp, mkobjflags, faction, goodequip)
register struct monst *mtmp;
int mkobjflags;
int faction;
boolean goodequip;
{
int mm = mtmp->mtyp;
int chance;
struct permonst *ptr = mtmp->data;
struct obj *otmp;
}
STATIC_OVL void
umber_initweap(mtmp, mkobjflags, faction, goodequip)
register struct monst *mtmp;
int mkobjflags;
int faction;
boolean goodequip;
{
int mm = mtmp->mtyp;
int chance;
struct permonst *ptr = mtmp->data;
struct obj *otmp;
}
STATIC_OVL void
umber_initinv(mtmp, mkobjflags, faction, goodequip)
register struct monst *mtmp;
int mkobjflags;
int faction;
boolean goodequip;
{
int mm = mtmp->mtyp;
int chance;
struct permonst *ptr = mtmp->data;
struct obj *otmp;
switch(mm){
case PM_UVUUDAUM:
otmp = mongets(mtmp, ROBE, mkobjflags);
if(otmp){
switch(rn2(2)){
case 0:
otmp->oeroded3 = 3;
break;
case 1:
otmp->spe = rnd(3);
break;
}
}
break;
case PM_ELDER_CHUUL:{
if(rn2(2)) mongets(mtmp, rnd_attack_wand(mtmp), mkobjflags);
if(rn2(2)) mongets(mtmp, rnd_utility_wand(mtmp), mkobjflags);
if(rn2(2)) mongets(mtmp, rnd_utility_potion(mtmp), mkobjflags);
if(rn2(2)) mongets(mtmp, rnd_attack_potion(mtmp), mkobjflags);
otmp = (struct obj *)0;
do {
if(otmp) delobj(otmp);
otmp = mkobj(RANDOM_CLASS, TRUE);
} while (!(objects[otmp->otyp].oc_magic || otmp->oartifact || Is_container(otmp)));
(void)mpickobj(mtmp, otmp);
}
case PM_CHUUL:{
if(!rn2(4)) mongets(mtmp, rnd_attack_wand(mtmp), mkobjflags);
if(!rn2(4)) mongets(mtmp, rnd_utility_wand(mtmp), mkobjflags);
if(!rn2(4)) mongets(mtmp, rnd_utility_potion(mtmp), mkobjflags);
if(!rn2(4)) mongets(mtmp, rnd_attack_potion(mtmp), mkobjflags);
if(In_quest(&u.uz) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && in_mklev){
otmp = mongets(mtmp, SACK, NO_MKOBJ_FLAGS);
if(otmp){
otmp->spe = 9; //plague victim
fix_object(otmp);
}
}
otmp = (struct obj *)0;
do {
if(otmp) delobj(otmp);
otmp = mkobj(RANDOM_CLASS, TRUE);
} while (!(objects[otmp->otyp].oc_magic || otmp->oartifact || Is_container(otmp)));
(void)mpickobj(mtmp, otmp);
}
break;
}
}
STATIC_OVL void
m_initweap(mtmp, mkobjflags, faction, goodequip, mmflags)
register struct monst *mtmp;
@ -4470,6 +4787,76 @@ int mmflags;
otmp = mongets(mtmp, PLATE_MAIL, mkobjflags);
if(otmp) set_material_gm(otmp, GLASS);
} else if(ptr->mtyp == PM_PANAKEIAN_ARCHON){
if(In_quest(&u.uz) && urole.neminum == PM_CYCLOPS){
set_template(mtmp, PLAGUE_TEMPLATE);
}
else {
if(In_endgame(&u.uz) || goodequip){
#define HOLY_PANAKEIAN_ARMOR(item) otmp = mongets(mtmp, item, mkobjflags);\
if(otmp){\
add_oprop(otmp, OPROP_HOLY);\
add_oprop(otmp, OPROP_HEAL);\
if(is_gloves(otmp) || is_boots(otmp))\
add_oprop(otmp, OPROP_HOLYW);\
bless(otmp);\
}
otmp = mongets(mtmp, SCALPEL, mkobjflags);
if(otmp) set_material_gm(otmp, SILVER);
HOLY_PANAKEIAN_ARMOR(HEALER_UNIFORM);
HOLY_PANAKEIAN_ARMOR(CLOAK_OF_MAGIC_RESISTANCE);
if(otmp)
add_oprop(otmp, OPROP_MAGC);
HOLY_PANAKEIAN_ARMOR(GLOVES);
HOLY_PANAKEIAN_ARMOR(LOW_BOOTS);
}
else {
mongets(mtmp, SCALPEL, mkobjflags);
mongets(mtmp, HEALER_UNIFORM, mkobjflags);
mongets(mtmp, GLOVES, mkobjflags);
mongets(mtmp, LOW_BOOTS, mkobjflags);
}
}
} else if(ptr->mtyp == PM_HYGIEIAN_ARCHON){
if(In_quest(&u.uz) && urole.neminum == PM_CYCLOPS){
set_template(mtmp, PLAGUE_TEMPLATE);
}
else {
if(In_endgame(&u.uz) || goodequip){
#define HOLY_HYGIEIAN_ARMOR(item) otmp = mongets(mtmp, item, mkobjflags);\
if(otmp){\
set_material_gm(otmp, SILVER);\
add_oprop(otmp, OPROP_HOLY);\
if(is_gloves(otmp) || is_boots(otmp))\
add_oprop(otmp, OPROP_HOLYW);\
bless(otmp);\
}
otmp = mongets(mtmp, QUARTERSTAFF, mkobjflags);
if(otmp){
set_material_gm(otmp, SILVER);
add_oprop(otmp, OPROP_HOLYW);
add_oprop(otmp, OPROP_FIREW);
}
HOLY_HYGIEIAN_ARMOR(ARCHAIC_HELM);
HOLY_HYGIEIAN_ARMOR(ARCHAIC_GAUNTLETS);
HOLY_HYGIEIAN_ARMOR(ARCHAIC_PLATE_MAIL);
HOLY_HYGIEIAN_ARMOR(ARCHAIC_BOOTS);
HOLY_HYGIEIAN_ARMOR(CLOAK);
if(otmp){
set_material_gm(otmp, CLOTH);
set_material_gm(otmp, OPROP_BCRS);
}
}
else {
otmp = mongets(mtmp, QUARTERSTAFF, mkobjflags);
if(otmp) set_material_gm(otmp, SILVER);
otmp = mongets(mtmp, HEALER_UNIFORM, mkobjflags);
otmp = mongets(mtmp, GLOVES, mkobjflags);
otmp = mongets(mtmp, LOW_BOOTS, mkobjflags);
otmp = mongets(mtmp, CLOAK, mkobjflags);
if(otmp) set_material_gm(otmp, CLOTH);
}
}
} else if(ptr->mtyp == PM_MONADIC_DEVA){
otmp = mongets(mtmp, TWO_HANDED_SWORD, mkobjflags);
if(otmp){
@ -6066,6 +6453,17 @@ int mmflags;
}
}
}
} else if(mm == PM_MAD_GRAZI){
mongets(mtmp, QUARTERSTAFF, mkobjflags);
otmp = mongets(mtmp, CLOAK, mkobjflags);
if(otmp)
otmp->obj_color = rn2(3) ? CLR_MAGENTA : CLR_BRIGHT_MAGENTA;
mongets(mtmp, GLOVES, mkobjflags);
mongets(mtmp, HIGH_BOOTS, mkobjflags);
mongets(mtmp, LEATHER_HELM, mkobjflags);
mongets(mtmp, CRYSTAL_SKULL, NO_MKOBJ_FLAGS);
if(check_insight() || check_insight())
set_template(mtmp, MOLY_TEMPLATE);
} else if((mm == PM_MIND_FLAYER || mm == PM_MASTER_MIND_FLAYER)){
if(on_level(&rlyeh_level,&u.uz)){
otmp = mksobj(BULLWHIP, mkobjflags);
@ -6228,7 +6626,9 @@ int mmflags;
}
} else {
mongets(mtmp, QUARTERSTAFF, mkobjflags);
mongets(mtmp, CLOAK, mkobjflags);
otmp = mongets(mtmp, CLOAK, mkobjflags);
if(otmp)
otmp->obj_color = rn2(3) ? CLR_MAGENTA : CLR_BRIGHT_MAGENTA;
mongets(mtmp, GLOVES, mkobjflags);
mongets(mtmp, HIGH_BOOTS, mkobjflags);
mongets(mtmp, LEATHER_HELM, mkobjflags);
@ -6274,6 +6674,139 @@ int mmflags;
} else if (ptr->mtyp == PM_ELOCATOR) {
otmp = mongets(mtmp, rn2(11) ? ROBE : CLOAK_OF_MAGIC_RESISTANCE, mkobjflags);
if(otmp) otmp->obj_color = CLR_ORANGE;
} else if (is_duergar(ptr)) {//Note Duergars are dwarves, so do this case first
if(mm == PM_DUERGAR_STONEGUARD){
otmp = mongets(mtmp, DWARVISH_CLOAK, mkobjflags);
if(otmp){
if(otmp->obj_material == LEATHER){
if(!rn2(4))
otmp->obj_color = CLR_MAGENTA;
}
else
otmp->obj_color = CLR_BLACK;
}
otmp = mongets(mtmp, ARMORED_BOOTS, mkobjflags);
if(otmp)
set_material_gm(otmp, IRON);
otmp = mongets(mtmp, DWARVISH_SHORT_SWORD, mkobjflags);
if(otmp)
set_material_gm(otmp, IRON);
otmp = mongets(mtmp, TOWER_SHIELD, mkobjflags);
if(otmp){
set_material_gm(otmp, WOOD);
otmp->obj_color = CLR_WHITE;//Fungus "wood"
}
otmp = mongets(mtmp, DAGGER, mkobjflags);
if(otmp){
set_material_gm(otmp, IRON);
otmp->quan = rnd(5);
fix_object(otmp);
}
otmp = mksobj(DWARVISH_HELM, mkobjflags);
otmp->ovar1_darklight = TRUE;
set_material_gm(otmp, IRON);
(void) mpickobj(mtmp, otmp);
if (levl[mtmp->mx][mtmp->my].lit) {
begin_burn(otmp);
}
otmp = mongets(mtmp, rn2(10) ? CHAIN_MAIL : PLATE_MAIL, mkobjflags);
if(otmp)
set_material_gm(otmp, IRON);
otmp = mongets(mtmp, GAUNTLETS, mkobjflags);
if(otmp)
set_material_gm(otmp, IRON);
}
else if(mm == PM_DUERGAR_DEBILITATOR){
otmp = mongets(mtmp, DWARVISH_CLOAK, mkobjflags);
if(otmp){
otmp->spe = max(otmp->spe, 2);
if(otmp->obj_material == LEATHER){
if(!rn2(4))
otmp->obj_color = CLR_MAGENTA;
}
else
otmp->obj_color = CLR_BLACK;
}
otmp = mongets(mtmp, HIGH_BOOTS, mkobjflags);
if(otmp)
otmp->spe = max(otmp->spe, 2);
otmp = mongets(mtmp, STILETTO, mkobjflags);
if(otmp){
otmp->spe = max(otmp->spe, 2);
set_material_gm(otmp, IRON);
}
otmp = mongets(mtmp, DAGGER, mkobjflags);
if(otmp){
otmp->spe = max(otmp->spe, 2);
set_material_gm(otmp, IRON);
otmp->quan = d(2,5);
fix_object(otmp);
}
otmp = mongets(mtmp, LEATHER_HELM, mkobjflags);
if(otmp)
otmp->spe = max(otmp->spe, 2);
otmp = mongets(mtmp, LEATHER_ARMOR, mkobjflags);
if(otmp)
otmp->spe = max(otmp->spe, 2);
otmp = mongets(mtmp, GLOVES, mkobjflags);
if(otmp)
otmp->spe = max(otmp->spe, 2);
if(In_quest(&u.uz) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && in_mklev){
otmp = mongets(mtmp, SACK, NO_MKOBJ_FLAGS);
if(otmp){
otmp->spe = 9; //plague victim
fix_object(otmp);
}
}
}
else { //PM_DUERGAR
otmp = mongets(mtmp, DWARVISH_CLOAK, mkobjflags);
if(otmp){
if(otmp->obj_material == LEATHER){
if(!rn2(4))
otmp->obj_color = CLR_MAGENTA;
}
else
otmp->obj_color = CLR_BLACK;
}
otmp = mongets(mtmp, SHOES, mkobjflags);
if(!rn2(5)){
otmp = mongets(mtmp, DWARVISH_MATTOCK, mkobjflags);
if(otmp)
set_material_gm(otmp, IRON);
}
else {
otmp = mongets(mtmp, STILETTO, mkobjflags);
if(otmp)
set_material_gm(otmp, IRON);
otmp = mongets(mtmp, DAGGER, mkobjflags);
if(otmp){
set_material_gm(otmp, IRON);
otmp->quan = rnd(5);
fix_object(otmp);
}
}
otmp = mksobj(DWARVISH_HELM, mkobjflags);
otmp->ovar1_darklight = TRUE;
set_material_gm(otmp, IRON);
(void) mpickobj(mtmp, otmp);
if (levl[mtmp->mx][mtmp->my].lit) {
begin_burn(otmp);
}
otmp = mongets(mtmp, CHAIN_MAIL, mkobjflags);
if(otmp)
set_material_gm(otmp, IRON);
if(!rn2(4) && In_quest(&u.uz) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && in_mklev){
otmp = mongets(mtmp, SACK, NO_MKOBJ_FLAGS);
if(otmp){
otmp->spe = 9; //plague victim
fix_object(otmp);
}
}
}
//Note: 2/3rds get confusion, this is not an error
(void)mongets(mtmp, rn2(3) ? POT_CONFUSION : rn2(2) ? POT_PARALYSIS : POT_HEALING, mkobjflags);
} else if (is_dwarf(ptr)) { //slightly rearanged code so more dwarves get helms -D_E
if(mm == PM_DWARF_KING && In_quest(&u.uz) && u.uz.dlevel == nemesis_level.dlevel && urole.neminum == PM_NECROMANCER && in_mklev){
(void)mongets(mtmp, SHACKLES, mkobjflags);
@ -6402,7 +6935,7 @@ int mmflags;
/* MRKR: Dwarves in dark mines have their lamps on. */
otmp = mksobj(DWARVISH_HELM, mkobjflags);
(void) mpickobj(mtmp, otmp);
if (!levl[mtmp->mx][mtmp->my].lit) {
if (!levl[mtmp->mx][mtmp->my].lit) {
begin_burn(otmp);
}
}
@ -7792,6 +8325,23 @@ int mmflags;
else if(chance >= 6) mongets(mtmp, CLOAK_OF_PROTECTION, mkobjflags);
else if(chance == 5) mongets(mtmp, CONSORT_S_SUIT, mkobjflags);
(void)mongets(mtmp, CRYSTAL_SWORD, mkobjflags);
} else if(ptr->mtyp == PM_MENDICANT_DRIDER){
otmp = mongets(mtmp, KHAKKHARA, mkobjflags);
} else if(ptr->mtyp == PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION){
otmp = mksobj(GAUNTLETS, MKOBJ_NOINIT);
if(otmp){
set_material_gm(otmp, IRON);
(void) mpickobj(mtmp, otmp);
}
otmp = mksobj(LANTERN_PLATE_MAIL, NO_MKOBJ_FLAGS);
if(otmp){
set_material_gm(otmp, IRON);
(void) mpickobj(mtmp, otmp);
}
otmp = mksobj(HELMET, MKOBJ_NOINIT);
if(otmp){
(void) mpickobj(mtmp, otmp);
}
} else if(ptr->mtyp == PM_ALIDER){
otmp = mksobj(WHITE_VIBROZANBATO, mkobjflags);
otmp->spe = 8;
@ -9642,6 +10192,18 @@ boolean goodequip;
}
break;
case S_CENTAUR:
if(mtmp->mtyp == PM_MENDICANT_SPROW){
otmp = mongets(mtmp, WAISTCLOTH, mkobjflags);
if(otmp)
otmp->obj_color = CLR_BRIGHT_BLUE;
otmp = mongets(mtmp, DROVEN_CLOAK, mkobjflags);
if(otmp)
otmp->obj_color = CLR_BLUE;
} else if(mtmp->mtyp == PM_MENDICANT_DRIDER){
otmp = mongets(mtmp, DROVEN_CLOAK, mkobjflags);
if(otmp)
otmp->obj_color = CLR_BLUE;
}
break;
case S_FUNGUS:
{
@ -10375,6 +10937,16 @@ boolean goodequip;
} //else
otmp = mongets(mtmp, rn2(3) ? ROBE : WAISTCLOTH, mkobjflags|MKOBJ_NOINIT);
if(otmp) otmp->oerodeproof = TRUE;
} else if(ptr->mtyp == PM_IASOIAN_ARCHON){
if(In_quest(&u.uz) && urole.neminum == PM_CYCLOPS){
set_template(mtmp, PLAGUE_TEMPLATE);
}
else {
otmp = mongets(mtmp, MIRROR, mkobjflags);
otmp = mongets(mtmp, HEALER_UNIFORM, mkobjflags);
otmp = mongets(mtmp, GLOVES, mkobjflags);
otmp = mongets(mtmp, LOW_BOOTS, mkobjflags);
}
} else if(ptr->mtyp == PM_HARROWER_OF_ZARIEL){
otmp = mksobj(rn2(3) ? ROBE : WAISTCLOTH, mkobjflags|MKOBJ_NOINIT);
otmp->oeroded3 = 3;
@ -10573,7 +11145,39 @@ boolean goodequip;
(void) mongets(mtmp, STILETTOS, mkobjflags);
// (void) mongets(mtmp, POT_FULL_HEALING, mkobjflags);
break;
case PM_AVATAR_OF_LOLTH:
case PM_AVATAR_OF_LOLTH:{
int i;
for(i = 0; i < 4; i++){
otmp = mksobj(DROVEN_SHORT_SWORD, mkobjflags);
add_oprop(otmp, OPROP_LESSER_ACIDW);
set_material_gm(otmp, OBSIDIAN_MT);
otmp->blessed = TRUE;
otmp->cursed = FALSE;
otmp->spe = 2;
fix_object(otmp);
(void) mpickobj(mtmp, otmp);
}
for(i = 0; i < 2; i++){
otmp = mksobj(DROVEN_SHORT_SWORD, mkobjflags);
add_oprop(otmp, OPROP_LESSER_ACIDW);
set_material_gm(otmp, OBSIDIAN_MT);
otmp->blessed = TRUE;
otmp->cursed = FALSE;
otmp->spe = 4;
fix_object(otmp);
(void) mpickobj(mtmp, otmp);
}
otmp = mksobj(ELVEN_SHORT_SWORD, mkobjflags);
set_material_gm(otmp, OBSIDIAN_MT);
add_oprop(otmp, OPROP_ACIDW);
otmp->blessed = TRUE;
otmp->cursed = FALSE;
otmp->spe = 6;
fix_object(otmp);
(void) mpickobj(mtmp, otmp);
otmp->spe = 8;
otmp = mksobj(VIPERWHIP, mkobjflags);
otmp = oname(otmp, artiname(ART_SCOURGE_OF_LOLTH));
otmp->blessed = TRUE;
@ -10583,7 +11187,7 @@ boolean goodequip;
(void) mpickobj(mtmp, otmp);
/*Plate Mail*/
otmp = mksobj(CRYSTAL_PLATE_MAIL, mkobjflags);
otmp->bodytypeflag = (MB_HUMANOID|MB_ANIMAL);
set_obj_shape(otmp, MB_HUMANOID|MB_ANIMAL);
otmp->ohaluengr = TRUE;
otmp->oward = LOLTH_SYMBOL;
otmp->blessed = TRUE;
@ -10606,6 +11210,7 @@ boolean goodequip;
(void) mpickobj(mtmp, otmp);
/*Helm*/
otmp = mksobj(DROVEN_HELM, mkobjflags);
set_material_gm(otmp, GLASS);
otmp->blessed = TRUE;
otmp->cursed = FALSE;
otmp->oerodeproof = TRUE;
@ -10614,7 +11219,7 @@ boolean goodequip;
// (void) mongets(mtmp, POT_FULL_HEALING, mkobjflags);
// (void) mongets(mtmp, POT_FULL_HEALING, mkobjflags);
// (void) mongets(mtmp, POT_FULL_HEALING, mkobjflags);
break;
}break;
case PM_GRAZ_ZT:
otmp = mksobj(TWO_HANDED_SWORD, mkobjflags);
otmp = oname(otmp, artiname(ART_DOOMSCREAMER));
@ -10711,7 +11316,7 @@ boolean goodequip;
(void) mpickobj(mtmp, otmp);
otmp = mksobj(LEATHER_ARMOR, mkobjflags|MKOBJ_NOINIT);
set_material_gm(otmp, DRAGON_HIDE);
otmp->bodytypeflag = (ptr->mflagsb&MB_BODYTYPEMASK);
set_obj_shape(otmp, ptr->mflagsb);
otmp->objsize = MZ_LARGE;
otmp->cursed = TRUE;
fix_object(otmp);
@ -10790,7 +11395,7 @@ boolean goodequip;
otmp->blessed = FALSE;
otmp->cursed = TRUE;
otmp->spe = 9;
otmp->bodytypeflag = MB_LONGHEAD;
set_obj_shape(otmp, MB_LONGHEAD);
otmp->objsize = MZ_HUGE;
otmp->oerodeproof = TRUE;
fix_object(otmp);
@ -11108,7 +11713,10 @@ boolean goodequip;
}
/* Your saddled steeds are waiting */
if(Race_if(PM_DROW) && in_mklev && Is_qstart(&u.uz) && (ptr->mtyp == PM_SPROW || ptr->mtyp == PM_DRIDER || ptr->mtyp == PM_CAVE_LIZARD || ptr->mtyp == PM_LARGE_CAVE_LIZARD)){
if(Race_if(PM_DROW) && in_mklev && Is_qstart(&u.uz)
&& urole.neminum != PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH
&& (ptr->mtyp == PM_SPROW || ptr->mtyp == PM_DRIDER || ptr->mtyp == PM_CAVE_LIZARD || ptr->mtyp == PM_LARGE_CAVE_LIZARD)
){
struct obj *otmp = mksobj(SADDLE, mkobjflags);
if (!get_mx(mtmp, MX_EDOG))
add_mx(mtmp, MX_EDOG);
@ -11128,7 +11736,7 @@ boolean goodequip;
otmp = mksobj(DROVEN_PLATE_MAIL, mkobjflags);
otmp->oward = (long)u.start_house;
otmp->oerodeproof = TRUE;
otmp->bodytypeflag = (ptr->mflagsb&MB_BODYTYPEMASK);
set_obj_shape(otmp, ptr->mflagsb&MB_BODYTYPEMASK);
otmp->blessed = FALSE;
otmp->cursed = TRUE;
otmp->spe = 3;
@ -11433,8 +12041,10 @@ boolean randmonst;
* Returns faction chosen.
*/
int
makemon_get_permonst_faction(ptr, faction)
makemon_get_permonst_faction(ptr, x, y, template, faction)
struct permonst * ptr;
int x,y;
int template;
int faction;
{
int out_faction = 0;
@ -11442,12 +12052,42 @@ int faction;
if (faction != -1)
return faction;
if(template == ZOMBIFIED || template == SKELIFIED || template == CRYSTALFIED
|| template == FRACTURED || template == TOMB_HERD || template == SLIME_REMNANT
|| template == FRACTURED || template == MINDLESS || template == POISON_TEMPLATE
|| template == FALLEN_TEMPLATE || template == MOLY_TEMPLATE
|| template == SPORE_ZOMBIE || template == CORDYCEPS
)
return 0;
if(template == MISTWEAVER)
return GOATMOM_FACTION;
if(template == M_BLACK_WEB || template == M_GREAT_WEB)
return EDDER_SYMBOL;
if(template == DREAM_LEECH || template == YELLOW_TEMPLATE)
return YELLOW_FACTION;
if(Infuture)
return 0;
if(is_drow(ptr) && ptr->mtyp != PM_CHANGED && ptr->mtyp != PM_WARRIOR_CHANGED){
if(is_drow(ptr) && ptr->mtyp != PM_CHANGED && ptr->mtyp != PM_WARRIOR_CHANGED){
if(curhouse) {
out_faction = curhouse;
} else if(ptr->mtyp == PM_PEN_A_MENDICANT || ptr->mtyp == PM_MENDICANT_DRIDER
|| ptr->mtyp == PM_MENDICANT_SPROW || ptr->mtyp == PM_SISTER_T_EIRASTRA
){
out_faction = PEN_A_SYMBOL;
} else if(ptr->mtyp == PM_Y_CULTIST || ptr->mtyp == PM_Y_CULTIST_FIGHTER
|| ptr->mtyp == PM_Y_CULTIST_WIZARD || ptr->mtyp == PM_Y_CULTIST_MATRON
|| ptr->mtyp == PM_Y_CULTIST_PATRON
){
out_faction = Y_CULT_SYMBOL;
} else if(ptr->mtyp == PM_ANULO_DANCER){
out_faction = EILISTRAEE_SYMBOL;
} else if(ptr->mtyp == PM_ANULO){
out_faction = PEN_A_SYMBOL;
} else if((ptr->mtyp == urole.ldrnum && ptr->mtyp != PM_ECLAVDRA) ||
(ptr->mtyp == urole.guardnum && ptr->mtyp != PM_DROW_MATRON_MOTHER && ptr->mtyp != PM_HEDROW_MASTER_WIZARD)
){
@ -11501,6 +12141,20 @@ int faction;
} else if(In_quest(&u.uz)){
if(Race_if(PM_DROW) && Role_if(PM_EXILE)){
out_faction = PEN_A_SYMBOL;
} else if(urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH){
if(u.uz.dlevel >= qlocate_level.dlevel)
out_faction = rn2(LAST_HOUSE+1-FIRST_HOUSE)+FIRST_HOUSE;
else {
if(x < 16){
out_faction = KIARANSALEE_SYMBOL;
}
else if(x < 52){
out_faction = XORLARRIN;
}
else {
out_faction = FAEN_TLABBAR;
}
}
} else if((Race_if(PM_DROW)) && (in_mklev || flags.stag || rn2(3))){
if(Is_qstart(&u.uz)) out_faction = u.start_house;
else if(Role_if(PM_NOBLEMAN)){
@ -11562,6 +12216,7 @@ struct monst * mon;
|| (Role_if(PM_EXILE) && (mon->mtyp == PM_PEASANT))
|| (urole.ldrnum == PM_DAMAGED_ARCADIAN_AVENGER && (mon->mtyp == PM_GNOME || mon->mtyp == PM_GNOME_LORD || mon->mtyp == PM_GNOME_KING
|| mon->mtyp == PM_TINKER_GNOME || mon->mtyp == PM_GNOMISH_WIZARD))
|| (urole.ldrnum == PM_SHUUSHAR_THE_ENLIGHTENED && (mon->mtyp == PM_ALLIANCE_VANGUARD || mon->mtyp == PM_SIR_ALJANOR))
)){
out_faction = QUEST_FACTION;
}
@ -11792,7 +12447,7 @@ int faction;
/* determine faction -- since this does not affect ptr (and therefore location),
* it can just be done at the very end */
out_faction = makemon_get_permonst_faction(ptr, faction);
out_faction = makemon_get_permonst_faction(ptr, x, y, out_template, faction);
return makemon_core(ptr, x, y, mmflags, out_template, out_faction);
}
@ -12303,20 +12958,24 @@ int faction;
break;
case S_HUMANOID:
if(!(mmflags & MM_NOGROUP)){
if(mmflags & MM_BIGGROUP){
if (mndx == PM_DEEPER_ONE){
for(num = rn1(10,3); num >= 0; num--) makemon_full(&mons[PM_DEEP_ONE], mtmp->mx, mtmp->my, MM_ADJACENTOK, template, faction);
}
if(Infuture){
if (mndx == PM_MIND_FLAYER){
m_initsgrp(mtmp, mtmp->mx, mtmp->my);
if(mmflags & MM_BIGGROUP){
if (mndx == PM_DEEPER_ONE){
for(num = rn1(10,3); num >= 0; num--) makemon_full(&mons[PM_DEEP_ONE], mtmp->mx, mtmp->my, MM_ADJACENTOK, template, faction);
}
if (mndx == PM_MASTER_MIND_FLAYER){
for(num = d(2,3); num >= 0; num--) makemon_full(&mons[PM_MIND_FLAYER], mtmp->mx, mtmp->my, MM_ADJACENTOK|MM_NOGROUP, template, faction);
if (mndx == PM_DUERGAR_DEBILITATOR){
tmpm = makemon_full(&mons[PM_DUERGAR_STONEGUARD], mtmp->mx, mtmp->my, MM_ADJACENTOK, template, faction);
if(tmpm) m_initlgrp(tmpm, mtmp->mx, mtmp->my);
}
if(Infuture){
if (mndx == PM_MIND_FLAYER){
m_initsgrp(mtmp, mtmp->mx, mtmp->my);
}
if (mndx == PM_MASTER_MIND_FLAYER){
for(num = d(2,3); num >= 0; num--) makemon_full(&mons[PM_MIND_FLAYER], mtmp->mx, mtmp->my, MM_ADJACENTOK|MM_NOGROUP, template, faction);
}
}
}
}
}
break;
case S_FUNGUS:
if(!(mmflags & MM_NOGROUP)){
@ -12546,7 +13205,13 @@ int faction;
// }
break;
case S_UMBER:
if(mndx == PM_UVUUDAUM){
if(mndx == PM_ELDER_CHUUL){
if(!(mmflags & MM_NOGROUP)){
for(num = d(2,3); num >= 0; num--)
makemon_full(&mons[PM_CHUUL], mtmp->mx, mtmp->my, MM_ADJACENTOK, template, faction);
}
}
else if(mndx == PM_UVUUDAUM){
mtmp->m_lev = 38;
mtmp->mhpmax = d(38, 8);
if(mtmp->mhpmax < 38*4.5)
@ -12937,7 +13602,7 @@ struct permonst *mptr; /* usually null; used for confused reading */
while (cnt--) {
#ifdef WIZARD
if (ask) {
if (create_particular(-1, -1, TRUE, 0, 0, 0)) {
if (create_particular(u.ux, u.uy, -1, -1, TRUE, 0, 0, 0, (char *)0)) {
known = TRUE;
continue;
}
@ -14453,11 +15118,8 @@ int mkobjflags;
otmp->objsize = mtmp->data->msize;
if (otmp->otyp == BULLWHIP && is_drow(mtmp->data) && mtmp->female)
set_material_gm(otmp, SILVER);
if (otmp->oclass == ARMOR_CLASS && !Is_dragon_scales(otmp)){
if (is_suit(otmp) || otmp->otyp == BODYGLOVE) otmp->bodytypeflag = (mtmp->data->mflagsb&MB_BODYTYPEMASK);
else if (is_helmet(otmp)) otmp->bodytypeflag = (mtmp->data->mflagsb&MB_HEADMODIMASK);
else if (is_shirt(otmp)) otmp->bodytypeflag = (mtmp->data->mflagsb&MB_HUMANOID) ? MB_HUMANOID : (mtmp->data->mflagsb&MB_BODYTYPEMASK);
}
if (otmp->oclass == ARMOR_CLASS && !Is_dragon_scales(otmp))
set_obj_shape(otmp, mtmp->data->mflagsb);
if (mtmp->data->mlet == S_GOLEM){
if (otmp->oclass == WEAPON_CLASS || otmp->oclass == ARMOR_CLASS){

View file

@ -581,6 +581,28 @@ unsigned int type;
case PM_ARCH_PRIEST:
quake = TRUE; //Casts earthquake instead of tremor
break;
case PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH:
switch(rn2(6)){
case 0:
return GEYSER;
break;
case 1:
return STEAM_GEYSER;
break;
case 2:
return RAIN;
break;
case 3:
return ACID_RAIN;
break;
case 4:
return BLOOD_RAIN;
break;
case 5:
return FILTH;
break;
}
break;
case PM_STRANGER:
switch (clrc_spell_power % 18) {
case 17:
@ -948,6 +970,77 @@ unsigned int type;
break;
}
break;
case PM_HEALER:
switch(clrc_spell_power/2){
case 14:
return RECOVER;
case 16:
case 13:
return MASS_CURE_FAR;
case 12:
return PARALYZE;
case 11:
return SLEEP;
case 10:
return DESTRY_ARMR;
case 9:
return DESTRY_WEPN;
case 15:
case 8:
case 7:
case 6:
return MASS_CURE_CLOSE;
default:
return CURE_SELF;
}
break;
case PM_PANAKEIAN_ARCHON:
switch(clrc_spell_power/2){
case 14:
return RECOVER;
case 16:
case 13:
case 12:
case 11:
return MASS_CURE_FAR;
case 10:
case 9:
return PARALYZE;
case 15:
case 8:
case 7:
case 6:
return MASS_CURE_CLOSE;
case 5:
case 4:
return SLEEP;
case 3:
return DESTRY_ARMR;
case 2:
return DESTRY_WEPN;
case 1:
return MAKE_WEB;
default:
return CURE_SELF;
}
break;
case PM_HYGIEIAN_ARCHON:
switch(wzrd_spell_power/5){
case 8:
case 7:
return DEATH_TOUCH;
case 6:
return LIGHTNING;
case 5:
return GEYSER;
case 4:
return ACID_RAIN;
case 3:
return CURE_SELF;
default:
return FIRE_PILLAR;
}
break;
case PM_MAHADEVA:
switch(rn2(10)){
case 0:
@ -1038,6 +1131,16 @@ unsigned int type;
break;
}
break;
case PM_COUATL:
switch(rn2(3)){
case 0:
return choose_clerical_spell(clrc_spell_power, mtmp->m_id,!(mtmp->mpeaceful), quake);
case 1:
return choose_psionic_spell(clrc_spell_power, mtmp->m_id,!(mtmp->mpeaceful));
case 2:
return choose_magic_spell(wzrd_spell_power,mtmp->m_id,!(mtmp->mpeaceful));
}
break;
case PM_AMM_KAMEREL:
case PM_HUDOR_KAMEREL:
case PM_ARA_KAMEREL:
@ -1252,6 +1355,43 @@ unsigned int type;
break;
}
break;
case PM_ANULO:
case PM_ANULO_DANCER:
return rn2(2) ? choose_clerical_spell(clrc_spell_power, mtmp->m_id,!(mtmp->mpeaceful), quake)
: choose_magic_spell(wzrd_spell_power,mtmp->m_id,!(mtmp->mpeaceful));
break;
case PM_PEN_A_MENDICANT:
case PM_MENDICANT_SPROW:
case PM_MENDICANT_DRIDER:
case PM_SISTER_T_EIRASTRA:
switch (rnd(8)) {
case 8:
return (!quest_status.offered_artifact ? CURE_SELF : RECOVER);
break;
case 7:
return (!quest_status.offered_artifact ? CURE_SELF : MASS_CURE_CLOSE);
break;
case 6:
return DESTRY_WEPN;
break;
case 5:
return DESTRY_ARMR;
break;
case 4:
return BLIND_YOU;
break;
case 3:
return PARALYZE;
break;
case 2:
return CURSE_ITEMS;
break;
case 1:
return PSI_BOLT;
break;
}
case PM_SHUUSHAR_THE_ENLIGHTENED:
return (!quest_status.offered_artifact ? CURE_SELF : MASS_CURE_CLOSE);
case PM_WITCH_S_FAMILIAR:
return OPEN_WOUNDS;
break;
@ -1777,6 +1917,8 @@ const char * spellname[] =
"EARTH_CRACK",
"AURA_BOLT",
"RAIN",
"BLOOD_RAIN",
"STEAM_GEYSER",
};
@ -2861,6 +3003,7 @@ int tary;
return xdamagey(magr, mdef, attk, dmg);
case GEYSER:
case STEAM_GEYSER:
/* needs direct target */
if (!foundem) {
impossible("geyser with no mdef?");
@ -2869,6 +3012,9 @@ int tary;
else
{
struct obj * boots = (youdef ? uarmf : which_armor(mdef, W_ARMF));
#define TOTAL_DUNK 1
#define PARTIAL_DUNK 2
char dunked = FALSE;
if (boots && boots->otyp == WATER_WALKING_BOOTS) {
/* message part 1*/
@ -2893,11 +3039,15 @@ int tary;
if (ACURR(A_DEX) <= 3) dmg = d(8, 6);
else if (ACURR(A_DEX) <= 6) dmg = d(4, 6);
else if (ACURR(A_DEX) <= 10) dmg = rnd(6);
dunked = PARTIAL_DUNK;
}
}
else {
if (mdef->data->mmove >= 14) pline("%s puts the added monmentum to good use!", Monnam(mdef));
else if (mdef->data->mmove <= 10) pline("%s is knocked around by the geyser's force!", Monnam(mdef));
else if (mdef->data->mmove <= 10){
pline("%s is knocked around by the geyser's force!", Monnam(mdef));
dunked = PARTIAL_DUNK;
}
if (mdef->data->mmove >= 25) mdef->movement += 12;
else if (mdef->data->mmove >= 18) mdef->movement += 8;
@ -2908,6 +3058,7 @@ int tary;
}
}
else {
dunked = TOTAL_DUNK;
/* message */
if (youagr || youdef || canseemon(mdef)) {
pline("A sudden geyser slams into %s from nowhere!",
@ -2926,6 +3077,18 @@ int tary;
else
water_damage(youdef ? invent : mdef->minvent, FALSE, FALSE, FALSE, mdef);
}
if(spell == STEAM_GEYSER && dunked){
if(!Fire_res(mdef)){
if(dunked == TOTAL_DUNK)
dmg += d(3,6);
else
dmg += d(1,10);
}
//Boiling water just boils potions
if(dunked == TOTAL_DUNK && !InvFire_res(mdef)){
destroy_item(mdef, POTION_CLASS, AD_FIRE);
}
}
}
return xdamagey(magr, mdef, attk, dmg);
@ -3017,6 +3180,45 @@ int tary;
}
return xdamagey(magr, mdef, attk, dmg);
case BLOOD_RAIN:
/* needs direct target */
if (!foundem) {
impossible("blood rain with no mdef?");
return MM_MISS;
}
else {
/* message */
if (youagr || youdef || canseemon(mdef)) {
pline("A torrent of blood rains down on %s!",
youdef ? "you" : mon_nam(mdef));
}
struct obj * helm = (youdef ? uarmh : which_armor(mdef, W_ARMH));
if (helm && is_wide_helm(helm)) {
dmg = 0;
if (youagr || youdef || canseemon(mdef)) {
pline("It runs off the brim of %s %s.",
youdef ? "your" : s_suffix(mon_nam(mdef)),
OBJ_DESCR(objects[helm->otyp]));
}
if(helm->blessed)
unbless(helm);
else if(!helm->cursed)
curse(helm);
if(youdef)
change_usanity(save_vs_sanloss() ? 0 : -1*d(1,4), TRUE);
}
else {
/* check resistance and override damage */
dmg = flaming(mdef->data) ? d(8, 6) : 0;
water_damage(youdef ? invent : mdef->minvent, FALSE, FALSE, WD_BLOOD, mdef);
if(youdef)
change_usanity(save_vs_sanloss() ? -1 : -1*d(2,6), TRUE);
}
}
return xdamagey(magr, mdef, attk, dmg);
case HAIL_FLURY:
case ICE_STORM:
/* ice storm is identical to hail flury, except it overrides dmg to 8d8 */
@ -3211,7 +3413,7 @@ int tary;
/* monster */
boolean resisted = FALSE;
if (!(resisted = (Magic_res(mdef) || resists_death(mdef) || resist(mdef, 0, 0, FALSE))) ||
if (!(resisted = (Magic_res(mdef) || resists_death(mdef) || resist(mdef, 0, 0, FALSE))) &&
rn2(mlev(magr)) > 12
){
if (is_delouseable(mdef->data)){
@ -4985,6 +5187,7 @@ int tary;
pline("%s goes blind!", Monnam(mdef));
}
}
mdef->mcansee = 0;
mdef->mblinded = min(dmg, 127);
}
}
@ -5583,8 +5786,10 @@ int spellnum;
case LIGHTNING:
case FIRE_PILLAR:
case GEYSER:
case STEAM_GEYSER:
case ACID_RAIN:
case RAIN:
case BLOOD_RAIN:
case HAIL_FLURY:
case ICE_STORM:
case DEATH_TOUCH:
@ -5919,7 +6124,7 @@ int tary;
return FALSE;
/* all: if nearby ally injured, or enemy near */
for (tmpm = fmon; tmpm; tmpm = tmpm->nmon){
if (magr->mtame == tmpm->mtame || magr->mpeaceful == tmpm->mpeaceful){
if (!magr->mtame == !tmpm->mtame || magr->mpeaceful == tmpm->mpeaceful){
if (!mm_aggression(magr, tmpm)
&& (*hp(tmpm) < *hpmax(tmpm))
&& dist2(magr->mx, magr->my, tmpm->mx, tmpm->my) <= 3 * 3 + 1

View file

@ -1058,6 +1058,16 @@ makelevel()
// pline("%s",fillname);
makemaz(fillname);
}
else if(Role_if(PM_HEALER) && Race_if(PM_DROW) && qstart_level.dnum == u.uz.dnum && qstart_level.dlevel == (u.uz.dlevel-1)){
Sprintf(fillname, "%s-secn", urole.filecode);
// pline("%s",fillname);
makemaz(fillname);
}
else if(Role_if(PM_HEALER) && Race_if(PM_DROW) && qstart_level.dnum == u.uz.dnum && qlocate_level.dlevel == (u.uz.dlevel-1)){
Sprintf(fillname, "%s-flor", urole.filecode);
// pline("%s",fillname);
makemaz(fillname);
}
else {
Sprintf(fillname, "%s-loca", urole.filecode);
loc_lev = find_level(fillname);

View file

@ -731,11 +731,82 @@ fixup_special()
}
}
}
/* DROW QUEST: transfer equip */
if (urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && In_quest(&u.uz)) {
if(qlocate_level.dlevel < u.uz.dlevel)
place_drow_healer_features();
struct obj *chest;
struct obj *obj, *nobj;
struct monst *mon;
int ctyp = CHEST;
if(Is_nemesis(&u.uz))
ctyp = SACK;
for(chest = fobj; chest; chest = chest->nobj){
if(chest->otyp == ctyp)
break;
}
if(chest) for(mon = fmon; mon; mon = mon->nmon){
if(mon->entangled != SHACKLES)
continue;
for(obj = mon->minvent; obj; obj = nobj){
nobj = obj->nobj;
if(obj->otyp == SHACKLES)
continue;
mon->misc_worn_check &= ~obj->owornmask;
update_mon_intrinsics(mon, obj, FALSE, FALSE);
if (obj->owornmask & W_WEP){
setmnotwielded(mon,obj);
MON_NOWEP(mon);
}
if (obj->owornmask & W_SWAPWEP){
setmnotwielded(mon,obj);
MON_NOSWEP(mon);
}
obj->owornmask = 0L;
obj_extract_self(obj);
add_to_container(chest, obj);
}
}
}
/* PRIEST QUEST: make graveyard */
if (Role_if(PM_PRIEST) && In_quest(&u.uz)) {
/* less chance for undead corpses (lured from lower morgues) */
level.flags.graveyard = 1;
}
/* HEALER QUEST: put some plague victims around the map */
if (Role_if(PM_HEALER) && In_quest(&u.uz)) {
if(!Race_if(PM_DROW)) {
int plague_types[] = {PM_HOBBIT, PM_DWARF, PM_BUGBEAR, PM_DWARF_LORD, PM_DWARF_CLERIC,
PM_DWARF_QUEEN, PM_DWARF_KING, PM_DEEP_ONE, PM_IMP, PM_QUASIT, PM_WINGED_KOBOLD,
PM_DRYAD, PM_NAIAD, PM_OREAD, PM_DEMINYMPH, PM_THRIAE, PM_HILL_ORC, PM_ORC_SHAMAN,
PM_ORC_CAPTAIN, PM_JUSTICE_ARCHON,
PM_MOVANIC_DEVA, PM_LILLEND, PM_COURE_ELADRIN,
PM_CHIROPTERAN, PM_PLAINS_CENTAUR, PM_FOREST_CENTAUR, PM_MOUNTAIN_CENTAUR,
PM_DRIDER, PM_FORMIAN_CRUSHER, PM_FORMIAN_TASKMASTER, PM_MYRMIDON_HOPLITE,
PM_MYRMIDON_LOCHIAS, PM_MYRMIDON_YPOLOCHAGOS, PM_MYRMIDON_LOCHAGOS,
PM_GNOME, PM_GNOME_LORD, PM_GNOME_LADY, PM_TINKER_GNOME, PM_GNOME_KING, PM_GNOME_QUEEN,
PM_VAMPIRE, PM_VAMPIRE_LORD, PM_VAMPIRE_LADY,
PM_PEASANT, PM_PEASANT, PM_PEASANT, PM_PEASANT, PM_NURSE, PM_WATCHMAN, PM_WATCH_CAPTAIN,
PM_WOODLAND_ELF, PM_GREEN_ELF, PM_GREY_ELF, PM_ELF_LORD, PM_ELF_LADY, PM_ELVENKING, PM_ELVENQUEEN,
PM_DROW_CAPTAIN, PM_HEDROW_WIZARD,
PM_HORNED_DEVIL, PM_SUCCUBUS, PM_INCUBUS,
PM_BARBARIAN, PM_HALF_DRAGON, PM_BARD, PM_HEALER, PM_RANGER, PM_VALKYRIE,
PM_SMALL_GOAT_SPAWN, PM_GOAT_SPAWN
};
int x, y, tries;
for(int i = d(2,4); i >0; i--){
tries = 10;
do {
x = rn2(COLNO)+1;
y = rn2(ROWNO);
}
while(!(isok(x,y) && levl[x][y].typ == SOIL) && tries-->0);
if(isok(x,y) && levl[x][y].typ == SOIL)
makemon_full(&mons[ROLL_FROM(plague_types)], x, y, NO_MM_FLAGS, PLAGUE_TEMPLATE, -1);
}
}
}
/* KNIGHT QUEST: convert half the swamp to a forest on the knight locate level*/
if (Role_if(PM_KNIGHT) &&
In_quest(&u.uz) &&

View file

@ -616,7 +616,7 @@ int mkflags;
otmp->dknown = 0;
otmp->corpsenm = 0; /* BUGFIX: Where does this get set? shouldn't it be given a default during initialization? */
otmp->objsize = MZ_MEDIUM;
otmp->bodytypeflag = MB_HUMANOID;
otmp->bodytypeflag = 0;
otmp->ovar1 = 0;
otmp->oward = 0;
for(int i = 0; i < OPROP_LISTSIZE; i++)
@ -636,6 +636,8 @@ int mkflags;
set_object_color(otmp);
set_obj_shape(otmp, MB_HUMANOID);
if(otyp == VIPERWHIP) otmp->ovar1 = rn2(2) ? 1 : rn2(5) ? rnd(2) : rnd(5);
if (summon) {
@ -1055,6 +1057,11 @@ int mkflags;
skull = ROLL_FROM(skulls);
}
}
// else if(In_quest(&u.uz) && Role_if(PM_HEALER) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && mvitals[PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION].born == 0){
else if(Role_if(PM_HEALER) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && mvitals[PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION].born == 0){
skull = PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION;
mvitals[PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION].born = 1;
}
else {
int skulls[] = {PM_DWARF_KING, PM_DWARF_QUEEN, PM_MAID,
PM_GITHYANKI_PIRATE, PM_DEMINYMPH, PM_MORDOR_ORC_ELITE, PM_MORDOR_MARSHAL,
@ -1361,6 +1368,10 @@ int mkflags;
otmp->age = (long)rn1(900, 900);//Last longer than dwarvish helms, since the radius is smaller
otmp->lamplit = 0;
}
if (otmp->otyp == LANTERN_PLATE_MAIL) {
otmp->age = (long)rn1(500, 1000);
otmp->lamplit = 0;
}
if (is_readable_armor_otyp(otmp->otyp)){
otmp->ohaluengr = TRUE;
if (Race_if(PM_DROW) && Is_qstart(&u.uz)) otmp->oward = u.start_house;
@ -1502,12 +1513,7 @@ int mkflags;
if (quest_equipment(otmp) && !otmp->oartifact) {
otmp->objsize = (&mons[urace.malenum])->msize;
if (otmp->oclass == ARMOR_CLASS){
if (is_suit(otmp) || otmp->otyp == BODYGLOVE)
otmp->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_BODYTYPEMASK);
else if (is_helmet(otmp))
otmp->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_HEADMODIMASK);
else if (is_shirt(otmp))
otmp->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_HUMANOID) ? MB_HUMANOID : ((&mons[urace.malenum])->mflagsb&MB_BODYTYPEMASK);
set_obj_shape(otmp, mons[urace.malenum].mflagsb);
}
}
}
@ -1542,6 +1548,47 @@ int mkflags;
return(otmp);
}
void
size_and_shape_to_fit(obj, mon)
struct obj *obj;
struct monst *mon;
{
struct permonst *ptr = mon->data;
if (Is_dragon_scales(obj)){
//Fits everything
return;
}
// change shape
if (is_shirt(obj) || obj->otyp == ELVEN_TOGA){
//Check that the monster can actually have armor that fits it.
if(!(ptr->mflagsb&MB_BODYTYPEMASK)){
return;
}
set_obj_shape(obj, ptr->mflagsb);
}
else if (is_suit(obj)){
//Check that the monster can actually have armor that fits it.
if(!(ptr->mflagsb&MB_BODYTYPEMASK)){
return;
}
set_obj_shape(obj, ptr->mflagsb);
}
else if (is_helmet(obj) && !is_hat(obj)){
//Check that the monster can actually have armor that fits it.
if(!has_head(ptr)){
return;
}
set_obj_shape(obj, ptr->mflagsb);
}
// change size (AFTER shape, because this may be aborted during that step.
obj->objsize = ptr->msize;
if(ptr->mtyp == PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION && is_boots(obj))
obj->objsize++;
fix_object(obj);
}
void
doMaskStats(mask)
struct obj *mask;
@ -1704,7 +1751,7 @@ start_corpse_timeout(body)
}
}
chance = (flags.walky_level) ? TROLL_REVIVE_CHANCE :
(attchmon && attchmon->zombify) ? FULL_MOLDY_CHANCE :
(attchmon && (attchmon->zombify || attchmon->mspores)) ? FULL_MOLDY_CHANCE :
(Is_night_level(&u.uz)) ? HALF_MOLDY_CHANCE :
0;
if(action == ROT_CORPSE && chance){
@ -2550,6 +2597,11 @@ register struct obj *obj;
wt += mons[PM_VAMPIRE].cwt;
}else if(obj->spe == 5){
wt += mons[PM_NITOCRIS].cwt;
}else if(obj->spe == 9){
if(urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH)
wt += mons[PM_PRIESTESS_OF_GHAUNADAUR].cwt;
else
wt += mons[PM_VAMPIRE_LADY].cwt;
}
}
if ((Is_container(obj) && obj->otyp != MAGIC_CHEST) || obj->otyp == STATUE) {
@ -3413,10 +3465,15 @@ maid_clean(mon, obj)
if(canseemon(mon)) pline("The maid sticks an ofuda to the offending object.");
obj->cursed = 0;
}
if(obj->otyp == DWARVISH_HELM || obj->otyp == OIL_LAMP || obj->otyp == LANTERN){
if(obj->otyp == DWARVISH_HELM || obj->otyp == OIL_LAMP || obj->otyp == LANTERN || obj->otyp == LANTERN_PLATE_MAIL){
if(obj->age < 750){
obj->age += 750;
if(canseemon(mon)) pline("The maid adds some oil.");
if(canseemon(mon)) {
if(obj->otyp == OIL_LAMP)
pline("The maid adds some oil.");
else if(obj->otyp == LANTERN_PLATE_MAIL)
pline("The maid changes the batteries.");
}
}
}
#ifdef TOURIST

View file

@ -33,6 +33,7 @@ STATIC_DCL void NDECL(mkfishingvillage);
STATIC_DCL void NDECL(mkpluhomestead);
STATIC_DCL void FDECL(mkpluroom, (int));
STATIC_DCL void FDECL(mkelfhut, (int));
STATIC_DCL void FDECL(mkdrowshanty, (int));
STATIC_DCL void FDECL(mkwraithclearing, (int));
STATIC_DCL void NDECL(mkstonepillars);
STATIC_DCL void FDECL(mkmordorfossil, (int));
@ -435,6 +436,20 @@ mkmivaultitem(container)
}
}
struct obj *
mkjewel()
{
int tries = 500;
struct obj *otmp = 0;
do{
if (otmp) {
dealloc_obj(otmp); /* discard it */
}
otmp = mkobj(GEM_CLASS, FALSE);
} while (tries-- > 0 && (otmp->otyp < MAGICITE_CRYSTAL || otmp->otyp > JADE));
return otmp;
}
struct obj *
mklolthvaultitem()
{
@ -3114,6 +3129,339 @@ int left;
}
}
STATIC_OVL
void
drow_shanty_spawn_at(x, y, w)
int x, y, w;
{
struct monst *mon;
int mtyp = 0;
switch(rn2(8)){
case 0:
mon = makemon(&mons[PM_HOUSELESS_DROW], x, y, NO_MM_FLAGS);
if(mon && !rn2(3))
set_template(mon, PLAGUE_TEMPLATE);
break;
case 1:
if(rn2(3))
mtyp = PM_Y_CULTIST;
else if(rn2(3))
mtyp = PM_Y_CULTIST_FIGHTER;
else if(rn2(3))
mtyp = PM_Y_CULTIST_WIZARD;
else{
switch(rn2(8)){
case 0:
mtyp = PM_Y_CULTIST_MATRON;
break;
case 1:
mtyp = PM_Y_CULTIST_PATRON;
break;
case 2:
mtyp = PM_INVIDIAK;
break;
case 3:
mtyp = PM_VROCK;
break;
case 4:
mtyp = PM_MARILITH;
break;
case 5:
mtyp = PM_LILITU;
break;
case 6:
mtyp = PM_NALFESHNEE;
break;
case 7:
mtyp = PM_DAUGHTER_OF_BEDLAM;
break;
}
}
break;
//Risen zombie
case 2:
if(rn2(3))
mtyp = PM_HOUSELESS_DROW;
else if(rn2(3))
mtyp = PM_HEDROW_WARRIOR;
else if(rn2(3))
mtyp = PM_DROW_CAPTAIN;
else{
switch(rn2(6)){
case 0:
mtyp = PM_DROW_MATRON;
break;
case 1:
mtyp = PM_HEDROW_WIZARD;
break;
case 2:
mtyp = PM_HEDROW_BLADEMASTER;
break;
case 3:
mtyp = PM_DRIDER;
break;
case 4:
mtyp = PM_SPROW;
break;
case 5:
mtyp = PM_ELF;
break;
}
}
mon = makemon_full(&mons[mtyp], x, y, NO_MM_FLAGS, ZOMBIFIED, -1);
if(mon){
set_faction(mon, 0);
mon->mpeaceful = 0;
set_malign(mon);
}
break;
//Spore zombie
case 3:
if(rn2(3))
mtyp = PM_HOUSELESS_DROW;
else if(rn2(3))
mtyp = PM_HEDROW_WARRIOR;
else if(rn2(3))
mtyp = PM_DROW_CAPTAIN;
else{
switch(rn2(6)){
case 0:
mtyp = PM_DROW_MATRON;
break;
case 1:
mtyp = PM_HEDROW_WIZARD;
break;
case 2:
mtyp = PM_HEDROW_BLADEMASTER;
break;
case 3:
mtyp = PM_DRIDER;
break;
case 4:
mtyp = PM_SPROW;
break;
case 5:
mtyp = PM_ELF;
break;
}
}
mon = makemon_full(&mons[mtyp], x, y, NO_MM_FLAGS, rn2(20) ? SPORE_ZOMBIE : CORDYCEPS, -1);
if(mon){
set_faction(mon, 0);
mon->mpeaceful = 0;
set_malign(mon);
}
break;
case 4:
mon = makemon(&mons[PM_KUO_TOA], x, y, MM_ADJACENTOK);
if(w > 3){
mon = makemon(&mons[PM_KUO_TOA], x, y, MM_ADJACENTOK);
mon = makemon(&mons[PM_KUO_TOA], x, y, MM_ADJACENTOK);
}
if(w > 4){
mon = makemon(&mons[PM_KUO_TOA], x, y, MM_ADJACENTOK);
mon = makemon(&mons[PM_KUO_TOA_WHIP], x, y, MM_ADJACENTOK);
}
break;
case 5:
mon = makemon(&mons[PM_DUERGAR_STONEGUARD], x, y, MM_ADJACENTOK);
if(w>3){
mon = makemon(&mons[PM_DUERGAR], x, y, MM_ADJACENTOK);
mon = makemon(&mons[PM_DUERGAR_STONEGUARD], x, y, MM_ADJACENTOK);
}
if(w>4){
mon = makemon(&mons[PM_DUERGAR_STONEGUARD], x, y, MM_ADJACENTOK);
mon = makemon(&mons[PM_DUERGAR_STONEGUARD], x, y, MM_ADJACENTOK);
mon = makemon(&mons[PM_DUERGAR_STONEGUARD], x, y, MM_ADJACENTOK);
mon = makemon(&mons[PM_DUERGAR_DEBILITATOR], x, y, MM_ADJACENTOK);
}
break;
case 6:
case 7:
if(rn2(3))
mtyp = PM_HOUSELESS_DROW;
else if(rn2(3))
mtyp = PM_HEDROW_WARRIOR;
else if(rn2(3))
mtyp = PM_DROW_CAPTAIN;
else{
switch(rn2(6)){
case 0:
mtyp = PM_DROW_MATRON;
break;
case 1:
mtyp = PM_HEDROW_WIZARD;
break;
case 2:
mtyp = PM_HEDROW_BLADEMASTER;
break;
case 3:
mtyp = PM_DRIDER;
break;
case 4:
mtyp = PM_SPROW;
break;
case 5:
mtyp = PM_ELF;
break;
}
}
mon = makemon(&mons[mtyp], x, y, NO_MM_FLAGS);
if(mon){
set_faction(mon, 0);
mon->mpeaceful = FALSE;
set_malign(mon);
if(!rn2(3))
set_template(mon, PLAGUE_TEMPLATE);
else switch(rn2(10)){
case 0:
mon->mcrazed = TRUE;
break;
case 1:
mon->mcannibal = TRUE;
break;
case 2:
mon->mgluttony = TRUE;
break;
case 3:
mon->mrage = TRUE;
break;
case 4:
mon->margent = TRUE;
break;
case 5:
mon->msuicide = TRUE;
break;
case 6:
mon->mnudist = TRUE;
break;
case 7:
mon->mparanoid = TRUE;
break;
case 8:
mon->mforgetful = TRUE;
break;
case 9:
mon->mapostasy = TRUE;
break;
}
}
break;
}
}
STATIC_OVL
void
mkdrowshanty(width)
int width;
{
int x,y,tries=0;
int i,j, pathto = 0;
boolean good=FALSE, okspot, accessible;
while(!good && tries < 500){
x = rn2(COLNO-2)+1;
y = rn2(ROWNO-2);
tries++;
okspot = TRUE;
accessible = FALSE;
for(i=-2;i<width+2 && okspot;i++)
for(j=-2;j<width+2 && okspot;j++){
if(isok(x+i,y+j) && levl[x+i][y+j].typ == IRONBARS)
okspot = FALSE;
}
for(i=0;i<width && okspot;i++)
for(j=0;j<width && okspot;j++){
if(!isok(x+i,y+j) || t_at(x+i, y+j))
okspot = FALSE;
// || (levl[x+i][y+j].typ == ROOM && qstart_level.dnum == u.uz.dnum && qlocate_level.dlevel == (u.uz.dlevel-1) && (!i || !j || i == width-1 || j == width-1)))
else if(!(levl[x+i][y+j].typ == STONE || levl[x+i][y+j].typ == SOIL || IS_WALL(levl[x+i][y+j].typ)))
okspot = FALSE;
}
pathto = 0;
j = y-1;
for(i = x+1; i < (x+width-1); i++)
if(isok(i,j) && (levl[i][j].typ == SOIL || levl[i][j].typ == CORR || levl[i][j].typ == ROOM)) pathto++;
j = y+width;
for(i = x+1; i < (x+width-1); i++)
if(isok(i,j) && (levl[i][j].typ == SOIL || levl[i][j].typ == CORR || levl[i][j].typ == ROOM)) pathto++;
i = x+width;
for(j = y+1; j < (y+width-1); j++)
if(isok(i,j) && (levl[i][j].typ == SOIL || levl[i][j].typ == CORR || levl[i][j].typ == ROOM)) pathto++;
i = x-1;
for(j = y+1; j < (y+width-1); j++)
if(isok(i,j) && (levl[i][j].typ == SOIL || levl[i][j].typ == CORR || levl[i][j].typ == ROOM)) pathto++;
if(pathto) accessible = TRUE;
if(okspot && accessible){
good = TRUE;
} else continue;
for(i=0;i<width;i++){
for(j=0;j<width;j++){
levl[x+i][y+j].typ = HWALL;
if(m_at(x+i, y+j)) rloc(m_at(x+i, y+j), TRUE);
}
}
for(i=1;i<width-1;i++){
for(j=1;j<width-1;j++){
levl[x+i][y+j].typ = ROOM;
if(!rn2(20)) mkobj_at(RANDOM_CLASS, x+i, y+j, NO_MKOBJ_FLAGS);
if(!rn2(5))
drow_shanty_spawn_at(x+i, y+j, width);
}
}
// i = rnd(3);
// for(;i>0;i--){
// makemon(&mons[PM_HOUSELESS_DROW], x+rnd(2), y+rnd(2), MM_ADJACENTOK);
// if(!rn2(3))
// mkobj_at(RANDOM_CLASS, x+rnd(2), y+rnd(2), MKOBJ_ARTIF);
// }
// wallification(x, y, x+3, y+3);//Can be adjacent, do wallification after all huts placed
pathto = rn2(pathto);
boolean left, right, top, bottom;
left = right= top = bottom = FALSE;
int d;
j = y-1;
d = y+0;
for(i = x+1; i < (x+width-1); i++)
if(isok(i,j) && (levl[i][j].typ == SOIL || levl[i][j].typ == CORR || levl[i][j].typ == ROOM) && (!(pathto--) || !rn2(3)) && !top){
levl[i][d].typ = DOOR, levl[i][d].doormask = rn2(3) ? D_NODOOR : rn2(3) ? D_CLOSED : D_LOCKED;
top = TRUE;
}
j = y+width;
d = y+width-1;
for(i = x+1; i < (x+width-1); i++)
if(isok(i,j) && (levl[i][j].typ == SOIL || levl[i][j].typ == CORR || levl[i][j].typ == ROOM) && (!(pathto--) || !rn2(3)) && !bottom){
levl[i][d].typ = DOOR, levl[i][d].doormask = rn2(3) ? D_NODOOR : rn2(3) ? D_CLOSED : D_LOCKED;
bottom = TRUE;
}
i = x+width;
d = x+width-1;
for(j = y+1; j < (y+width-1); j++)
if(isok(i,j) && (levl[i][j].typ == SOIL || levl[i][j].typ == CORR || levl[i][j].typ == ROOM) && (!(pathto--) || !rn2(3)) && !right){
levl[d][j].typ = DOOR, levl[d][j].doormask = rn2(3) ? D_NODOOR : rn2(3) ? D_CLOSED : D_LOCKED;
right = TRUE;
}
i = x-1;
d = x+0;
for(j = y+1; j < (y+width-1); j++)
if(isok(i,j) && (levl[i][j].typ == SOIL || levl[i][j].typ == CORR || levl[i][j].typ == ROOM) && (!(pathto--) || !rn2(3)) && !left){
levl[d][j].typ = DOOR, levl[d][j].doormask = rn2(3) ? D_NODOOR : rn2(3) ? D_CLOSED : D_LOCKED;
left = TRUE;
}
}
}
STATIC_OVL
void
mkwraithclearing(right)
@ -5227,6 +5575,36 @@ place_chaos_forest_features()
}
}
void
place_drow_healer_features()
{
int i;
int j = 12;
while(j-->0){
for(i = d(2,8); i > 0; i--)
mkdrowshanty(4);
if(!(qlocate_level.dlevel == (u.uz.dlevel-1))){
for(i = d(1,4); i > 0; i--)
mkdrowshanty(5);
for(i = d(1,4); i > 0; i--)
mkdrowshanty(3);
}
else for(i = d(2,4); i > 0; i--)
mkdrowshanty(3);
}
if(qlocate_level.dlevel == (u.uz.dlevel-1)){
for (i = 1; i<COLNO; i++){
for (j = 0; j<ROWNO; j++){
if (levl[i][j].typ == MOAT){
levl[i][j].typ = VWALL;
levl[i][j].wall_info |= W_NONDIGGABLE;
}
}
}
}
wallification(1,0,COLNO-1,ROWNO-1);
}
void
place_neutral_features()
{
@ -5872,6 +6250,23 @@ int sx,sy;
};
mtyp = ROLL_FROM(prisoners);
}break;
case PM_Y_CULTIST_PATRON:{
int prisoners[] = {
PM_GREEN_ELF, PM_GREEN_ELF, PM_GREY_ELF, PM_GREY_ELF, PM_ELF_LORD, PM_ELF_LADY,
PM_HEDROW_WARRIOR, PM_HEDROW_WIZARD, PM_DROW_CAPTAIN, PM_DROW_CAPTAIN, PM_DROW_MATRON,
PM_HEDROW_WARRIOR, PM_HEDROW_WIZARD, PM_DROW_CAPTAIN, PM_DROW_CAPTAIN, PM_DROW_MATRON,
PM_DROW, PM_DROW, PM_DROW, PM_DROW, PM_DROW,
PM_DRIDER, PM_PRIESTESS_OF_GHAUNADAUR, PM_STJARNA_ALFR,
PM_PEN_A_MENDICANT, PM_PEN_A_MENDICANT, PM_MENDICANT_DRIDER, PM_MENDICANT_SPROW,
PM_DWARF, PM_DWARF, PM_DWARF_CLERIC, PM_DWARF_LORD,
PM_DWARF, PM_DWARF, PM_DWARF_CLERIC, PM_DWARF_LORD,
PM_NOBLEMAN, PM_NOBLEWOMAN, PM_RANGER, PM_RANGER, PM_ROGUE, PM_WIZARD, PM_KNIGHT, PM_KNIGHT,
PM_HOBBIT, PM_GNOME, PM_ALLIANCE_VANGUARD, PM_ALLIANCE_VANGUARD,
PM_UNEARTHLY_DROW, PM_UNEARTHLY_DROW, PM_LILITU, PM_MARILITH,
PM_DEMINYMPH
};
mtyp = ROLL_FROM(prisoners);
}break;
case PM_AVATAR_OF_LOLTH:{
int prisoners[] = {
PM_WOODLAND_ELF, PM_GREEN_ELF, PM_GREY_ELF, PM_GREY_ELF, PM_ELF_LORD, PM_ELVENKING,
@ -5946,6 +6341,9 @@ int sx,sy;
mon->female = FALSE;
set_template(mon, VAMPIRIC);
}
if(kingtype == PM_EMBRACED_DROWESS){
set_mcan(mon, TRUE);
}
if(polyps){
mon->ispolyp = TRUE;
mongets(mon, MASK, NO_MKOBJ_FLAGS);
@ -6076,7 +6474,7 @@ struct mkroom *sroom;
mon = makemon(&mons[ctype], tx, ty, NO_MM_FLAGS|MM_NOCOUNTBIRTH);
if(mon) {
mon->msleeping = 1;
if(ctype == PM_DROW_MATRON || ctype == PM_EMBRACED_DROWESS){
if(ctype == PM_DROW_MATRON || ctype == PM_EMBRACED_DROWESS || ctype == PM_Y_CULTIST_PATRON){
set_curhouse(mon->mfaction);
}
}
@ -6105,16 +6503,20 @@ struct mkroom *sroom;
PM_DROW_MATRON,
PM_EMBRACED_DROWESS
};
do ctype = kingnums[rn2(SIZE(kingnums))];
while((tooweak(ctype, minmlev) || toostrong(ctype,maxmlev)) && tries++ < 40);
if(In_quest(&u.uz) && Role_if(PM_HEALER) && Race_if(PM_DROW)){
ctype = !rn2(3) ? PM_DROW_MATRON : rn2(2) ? PM_Y_CULTIST_PATRON : PM_EMBRACED_DROWESS;
}
else {
do ctype = kingnums[rn2(SIZE(kingnums))];
while((tooweak(ctype, minmlev) || toostrong(ctype,maxmlev)) && tries++ < 40);
}
if(tries < 40){
mon = makemon(&mons[ctype], tx, ty, NO_MM_FLAGS|MM_NOCOUNTBIRTH);
if(mon) {
mon->msleeping = 1;
if (type==COURT) {
//Set curhouse to coordinate equipment
if(ctype == PM_DROW_MATRON || ctype == PM_EMBRACED_DROWESS){
if(ctype == PM_DROW_MATRON || ctype == PM_EMBRACED_DROWESS || ctype == PM_Y_CULTIST_PATRON){
set_curhouse(mon->mfaction);
}
//Note: court monsters are always part of rodney's forces.
@ -6152,7 +6554,8 @@ struct mkroom *sroom;
for(sy = sroom->ly; sy <= sroom->hy; sy++) {
if(type == COURT){
if(ctype == PM_KOBOLD_LORD || ctype == PM_VAMPIRE_LORD || ctype == PM_VAMPIRE_LADY || ctype == PM_DROW_MATRON ||
ctype == PM_EMBRACED_DROWESS || ctype == PM_DEEPEST_ONE || ctype == PM_ORC_OF_THE_AGES_OF_STARS
ctype == PM_EMBRACED_DROWESS || ctype == PM_Y_CULTIST_PATRON ||
ctype == PM_DEEPEST_ONE || ctype == PM_ORC_OF_THE_AGES_OF_STARS
){
levl[tx][ty].lit = 0;
sroom->rlit = 0;
@ -7924,6 +8327,30 @@ courtmon(kingnum)
return &mons[PM_QUASIT];
break;
case PM_Y_CULTIST_PATRON:
i = rnd(100);
if(i>90)
return &mons[PM_LILITU];
if(i>80)
return &mons[PM_Y_CULTIST_WIZARD];
if(i>45)
return &mons[PM_Y_CULTIST_FIGHTER];
if(i>40)
return &mons[PM_Y_CULTIST];
if(i>30)
return &mons[PM_Y_CULTIST_MATRON];
if(i>25)
return &mons[PM_CHUUL];
if(i>15)
return &mons[PM_KUO_TOA];
if(i>10)
return &mons[PM_KUO_TOA_WHIP];
if(i> 5)
return &mons[PM_VROCK];
if(i> 0)
return &mons[PM_QUASIT];
break;
case PM_EMBRACED_DROWESS:
i = rnd(100);
if(i>95)

447
src/mon.c
View file

@ -239,6 +239,7 @@ STATIC_VAR int cham_to_pm[] = {
(get_mx((mon), MX_ESUM)) || \
((mon)->ispolyp) || \
((mon)->zombify) || \
((mon)->mspores) || \
((mon)->mtyp == PM_UNDEAD_KNIGHT) || \
((mon)->mtyp == PM_WARRIOR_OF_SUNLIGHT) || \
((mon)->mtyp == PM_UNDEAD_MAIDEN) || \
@ -1478,76 +1479,76 @@ register struct monst *mtmp;
}
if (inlava) {
/*
* Lava effects much as water effects. Lava likers are able to
* protect their stuff. Fire resistant monsters can only protect
* themselves --ALI
*/
if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) {
if (!resists_fire(mtmp)) {
if (cansee(mtmp->mx,mtmp->my))
pline("%s %s.", Monnam(mtmp),
mtmp->mtyp == PM_WATER_ELEMENTAL ?
"boils away" : "burns to a crisp");
mondead(mtmp);
}
else {
if (--mtmp->mhp < 1) {
if (cansee(mtmp->mx,mtmp->my))
pline("%s surrenders to the fire.", Monnam(mtmp));
mondead(mtmp);
}
else if (cansee(mtmp->mx,mtmp->my))
pline("%s burns slightly.", Monnam(mtmp));
}
if (mtmp->mhp > 0) {
(void) fire_damage(mtmp->minvent, FALSE, FALSE,
mtmp->mx, mtmp->my);
(void) rloc(mtmp, TRUE);
return 0;
}
return (1);
}
} else if (inpool) {
/* Most monsters drown in pools. flooreffects() will take care of
* water damage to dead monsters' inventory, but survivors need to
* be handled here. Swimmers are able to protect their stuff...
*/
if (!is_clinger(mtmp->data)
&& !mon_resistance(mtmp,SWIMMING) && !amphibious_mon(mtmp)) {
if (cansee(mtmp->mx,mtmp->my)) {
if(mtmp->mtyp == PM_ACID_PARAELEMENTAL){
int tx = mtmp->mx, ty = mtmp->my, dn = mtmp->m_lev;
pline("%s explodes.", Monnam(mtmp));
mondead(mtmp);
explode(tx, ty, AD_EACD, MON_EXPLODE, d(dn, 10), EXPL_NOXIOUS, 1);
} else pline("%s drowns.", Monnam(mtmp));
}
if (u.ustuck && u.uswallow && u.ustuck == mtmp) {
/* This can happen after a purple worm plucks you off a
flying steed while you are over water. */
pline("%s sinks as water rushes in and flushes you out.",
Monnam(mtmp));
}
if(!DEADMONSTER(mtmp))
/*
* Lava effects much as water effects. Lava likers are able to
* protect their stuff. Fire resistant monsters can only protect
* themselves --ALI
*/
if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) {
if (!resists_fire(mtmp)) {
if (cansee(mtmp->mx,mtmp->my))
pline("%s %s.", Monnam(mtmp),
mtmp->mtyp == PM_WATER_ELEMENTAL ?
"boils away" : "burns to a crisp");
mondead(mtmp);
if (mtmp->mhp > 0) {
(void) rloc(mtmp, TRUE);
water_damage(mtmp->minvent, FALSE, FALSE, level.flags.lethe, mtmp);
return 0;
}
return (1);
}
} else {
/* but eels have a difficult time outside */
if (mtmp->data->mlet == S_EEL && !Is_waterlevel(&u.uz)) {
/* Puddles can sustain a tiny sea creature, or lessen the burdens of a larger one */
if (!(inshallow && mtmp->data->msize == MZ_TINY))
{
if (mtmp->mhp > 1 && rn2(mtmp->data->msize)) mtmp->mhp--;
monflee(mtmp, 2, FALSE, FALSE);
}
else {
if (--mtmp->mhp < 1) {
if (cansee(mtmp->mx,mtmp->my))
pline("%s surrenders to the fire.", Monnam(mtmp));
mondead(mtmp);
}
else if (cansee(mtmp->mx,mtmp->my))
pline("%s burns slightly.", Monnam(mtmp));
}
if (mtmp->mhp > 0) {
(void) fire_damage(mtmp->minvent, FALSE, FALSE,
mtmp->mx, mtmp->my);
(void) rloc(mtmp, TRUE);
return 0;
}
return (1);
}
} else if (inpool) {
/* Most monsters drown in pools. flooreffects() will take care of
* water damage to dead monsters' inventory, but survivors need to
* be handled here. Swimmers are able to protect their stuff...
*/
if (!is_clinger(mtmp->data)
&& !mon_resistance(mtmp,SWIMMING) && !amphibious_mon(mtmp)) {
if (cansee(mtmp->mx,mtmp->my)) {
if(mtmp->mtyp == PM_ACID_PARAELEMENTAL){
int tx = mtmp->mx, ty = mtmp->my, dn = mtmp->m_lev;
pline("%s explodes.", Monnam(mtmp));
mondead(mtmp);
explode_pa(tx, ty, AD_EACD, MON_EXPLODE, d(dn, 10), EXPL_NOXIOUS, 1, mtmp->data);
} else pline("%s drowns.", Monnam(mtmp));
}
if (u.ustuck && u.uswallow && u.ustuck == mtmp) {
/* This can happen after a purple worm plucks you off a
flying steed while you are over water. */
pline("%s sinks as water rushes in and flushes you out.",
Monnam(mtmp));
}
if(!DEADMONSTER(mtmp))
mondead(mtmp);
if (mtmp->mhp > 0) {
(void) rloc(mtmp, TRUE);
water_damage(mtmp->minvent, FALSE, FALSE, level.flags.lethe, mtmp);
return 0;
}
return (1);
}
} else {
/* but eels have a difficult time outside */
if (mtmp->data->mlet == S_EEL && !Is_waterlevel(&u.uz)) {
/* Puddles can sustain a tiny sea creature, or lessen the burdens of a larger one */
if (!(inshallow && mtmp->data->msize == MZ_TINY))
{
if (mtmp->mhp > 1 && rn2(mtmp->data->msize)) mtmp->mhp--;
monflee(mtmp, 2, FALSE, FALSE);
}
}
}
}
return (0);
}
@ -1831,6 +1832,26 @@ movemon()
insight_vanish(mtmp);
continue;
}
if(mtmp->mtyp == PM_APPRENTICE_WITCH && !mtmp->mtame){
mtmp = tamedog_core(mtmp, (struct obj *)0, TRUE);
mtmp->movement = 0;
continue;
}
if(In_quest(&u.uz) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && levl[mtmp->mx][mtmp->my].typ == AIR
&& !mon_resistance(mtmp,FLYING)
&& !mon_resistance(mtmp,LEVITATION)
&& mtmp != u.ustuck
&& mtmp != u.usteed
){
struct d_level target_level;
target_level.dnum = u.uz.dnum;
target_level.dlevel = qlocate_level.dlevel+1;
mtmp->mhp = 1; //How Lucky! Almost Died!
if(canseemon(mtmp))
pline("%s plummets to the rocky cavern floor below!", Monnam(mtmp));
migrate_to_level(mtmp, ledger_no(&target_level), MIGR_RANDOM, (coord *)0);
continue;
}
if(TimeStop && !is_uvuudaum(mtmp))
continue;
if(mtmp->movement < NORMAL_SPEED)
@ -2172,13 +2193,14 @@ boolean devour;
int nutrit = dog_nutrition(mtmp, obj);
long rotted = 0;
int mtyp = NON_PM;
poly = polyfodder(obj) && !resists_poly(mtmp->data);
grow = mlevelgain(obj);
heal = mhealup(obj);
ston = (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN || obj->otyp == POT_BLOOD) && obj->corpsenm >= LOW_PM && touch_petrifies(&mons[obj->corpsenm]) && !Stone_res(mtmp);
if(obj->otyp == CORPSE){
int mtyp = obj->corpsenm;
mtyp = obj->corpsenm;
if (mtyp != PM_LIZARD && mtyp != PM_SMALL_CAVE_LIZARD && mtyp != PM_CAVE_LIZARD
&& mtyp != PM_LARGE_CAVE_LIZARD && mtyp != PM_LICHEN && mtyp != PM_BEHOLDER
) {
@ -2346,6 +2368,9 @@ boolean devour;
if (!grow_up(mtmp, (struct monst *)0)) return 2;
}
if (heal) mtmp->mhp = mtmp->mhpmax;
if(mtyp != NON_PM){
give_mon_corpse_intrinsic(mtmp, mtyp);
}
return 1;
}
@ -3131,6 +3156,11 @@ nexttry:
) continue;
if(mon->mfrigophobia && ntyp == ICE)
continue;
if(In_quest(&u.uz) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && ntyp == AIR
&& !mon_resistance(mon,FLYING)
&& !mon_resistance(mon,LEVITATION)
)
continue;
if((mdat->mtyp == PM_GRUE) && isdark(mon->mx, mon->my) && !isdark(nx, ny))
continue;
if((mdat->mtyp == PM_WATCHER_IN_THE_WATER || mdat->mtyp == PM_KETO) &&
@ -3344,7 +3374,7 @@ struct monst * mdef; /* another monster which is next to it */
ma = magr->data;
md = mdef->data;
#define mm_undead(mon) (is_undead(mon->data) && mon->mfaction != HOLYDEAD_FACTION)
#define mm_undead(mon) ((is_undead(mon->data) || has_template(mon, CORDYCEPS) || has_template(mon, SPORE_ZOMBIE)) && mon->mfaction != HOLYDEAD_FACTION)
// Pets don't attack:
if(magr->mtame && (
@ -3552,11 +3582,24 @@ struct monst * mdef; /* another monster which is next to it */
return ALLOW_M|ALLOW_TM;
/* elves vs. drow */
if(is_elf(ma) && is_drow(md) && mdef->mfaction != EILISTRAEE_SYMBOL)
if(is_elf(ma) && is_drow(md) && mdef->mfaction != EILISTRAEE_SYMBOL && mdef->mfaction != PEN_A_SYMBOL)
return ALLOW_M|ALLOW_TM;
if(is_elf(md) && is_drow(ma) && magr->mfaction != EILISTRAEE_SYMBOL)
if(is_elf(md) && is_drow(ma) && magr->mfaction != EILISTRAEE_SYMBOL && magr->mfaction != PEN_A_SYMBOL)
return ALLOW_M|ALLOW_TM;
/* drow healer quest: drow vs. invaders */
/* Other houses do fight the Y-cult, but that's handled by the drow faction code */
/* Pen'a's faction is handled by the pet friendly code */
if(In_quest(&u.uz)
&& urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH
&& magr->mfaction != Y_CULT_SYMBOL
&& mdef->mfaction != Y_CULT_SYMBOL
&& magr->mfaction != PEN_A_SYMBOL
&& mdef->mfaction != PEN_A_SYMBOL
&& (!is_drow(ma) + !is_drow(md)) == 1
){
return ALLOW_M|ALLOW_TM;
}
/* undead vs civs */
if(!(In_cha(&u.uz) || Is_rogue_level(&u.uz))){
if(mm_undead(magr) &&
@ -3593,26 +3636,10 @@ struct monst * mdef; /* another monster which is next to it */
/* Note that factions may be different than the displayed house name,
as faction is set during generation and displayed house name goes by equipment! */
if( is_drow(ma) && is_drow(md) &&
magr->mfaction != mdef->mfaction
magr->mfaction != mdef->mfaction &&
!allied_faction(magr->mfaction, mdef->mfaction)
){
int f1 = magr->mfaction, f2 = mdef->mfaction;
boolean truce1 = FALSE, truce2 = FALSE;
if((f1 >= FIRST_GODDESS && f1 <= LAST_GODDESS) ||
(f1 >= FIRST_TOWER && f1 <= LAST_TOWER)
) truce1 = TRUE;
if((f2 >= FIRST_GODDESS && f2 <= LAST_GODDESS) ||
(f2 >= FIRST_TOWER && f2 <= LAST_TOWER)
) truce2 = TRUE;
if((f1 == XAXOX || f1 == EDDER_SYMBOL) && (f2 == XAXOX || f2 == EDDER_SYMBOL));
else if(!truce1 && !truce2) return ALLOW_M|ALLOW_TM;
else if(truce1 && truce2);
else if(truce1 && !(f2 <= LAST_HOUSE && f2 >= FIRST_HOUSE))
return ALLOW_M|ALLOW_TM;
else if(truce2 && !(f1 <= LAST_HOUSE && f1 >= FIRST_HOUSE))
return ALLOW_M|ALLOW_TM;
return ALLOW_M|ALLOW_TM;
}
/* drow vs. edderkops */
@ -3901,6 +3928,86 @@ struct monst *mon;
return (struct obj *)0;
}
boolean
plague_victim_on_level()
{
struct monst *mon;
for(mon = fmon; mon; mon = mon->nmon)
if(has_template(mon, PLAGUE_TEMPLATE))
return TRUE;
return FALSE;
}
boolean
allied_iaso_on_level(mtmp)
struct monst *mtmp;
{
struct monst *mon;
for(mon = fmon; mon; mon = mon->nmon)
if(mon->mtyp == PM_IASOIAN_ARCHON
&& !mon->mcan && !mon->mspec_used
&& !nonthreat(mon)
&& !mon->mtame == !mtmp->mtame
&& mon->mpeaceful == mtmp->mpeaceful
)
return TRUE;
return FALSE;
}
struct monst *
random_plague_victim()
{
struct monst *mon;
int count = 0;
for(mon = fmon; mon; mon = mon->nmon)
if(has_template(mon, PLAGUE_TEMPLATE))
count++;
if(!count)
return (struct monst *) 0;
count = rn2(count);
for(mon = fmon; mon; mon = mon->nmon)
if(has_template(mon, PLAGUE_TEMPLATE)){
if(!count)
return mon;
else count--;
}
return (struct monst *) 0;
}
void
timeout_random_allied_iaso(mtmp)
struct monst *mtmp;
{
struct monst *mon;
int count = 0;
for(mon = fmon; mon; mon = mon->nmon)
if(mon->mtyp == PM_IASOIAN_ARCHON
&& !mon->mcan && !mon->mspec_used
&& !nonthreat(mon)
&& !mon->mtame == !mtmp->mtame
&& mon->mpeaceful == mtmp->mpeaceful
)
count++;
if(!count)
return;
count = rn2(count);
for(mon = fmon; mon; mon = mon->nmon)
if(mon->mtyp == PM_IASOIAN_ARCHON
&& !mon->mcan && !mon->mspec_used
&& !nonthreat(mon)
&& !mon->mtame == !mtmp->mtame
&& mon->mpeaceful == mtmp->mpeaceful
){
if(!count){
mon->mspec_used = mtmp->mhpmax;
return;
}
else count--;
}
}
/* maybe kills mtmp, possibly lifesaving it */
STATIC_OVL void
lifesaved_monster(mtmp)
@ -3910,18 +4017,20 @@ struct monst *mtmp;
boolean messaged = FALSE;
int lifesavers = 0;
int i;
#define LSVD_ANA 0x001 /* anachrononaut quest */
#define LSVD_HLO 0x002 /* Halo (Blessed) */
#define LSVD_UVU 0x004 /* uvuuduam + prayerful thing */
#define LSVD_OBJ 0x008 /* lifesaving items */
#define LSVD_ILU 0x010 /* illuminated */
#define LSVD_FRC 0x020 /* fractured kamerel */
#define LSVD_NBW 0x040 /* nitocris's black wraps */
#define LSVD_PLY 0x080 /* polypoids */
#define LSVD_NIT 0x100 /* Nitocris becoming a ghoul */
#define LSVD_KAM 0x200 /* kamerel becoming fractured */
#define LSVD_ALA 0x400 /* alabaster decay */
#define LSVD_FLS 0x800 /* God of flesh claims body */
#define LSVD_ANA 0x0001 /* anachrononaut quest */
#define LSVD_IAS 0x0002 /* Iasoian Archon grants recovery */
#define LSVD_HLO 0x0004 /* Halo (Blessed) */
#define LSVD_UVU 0x0008 /* uvuuduam + prayerful thing */
#define LSVD_ASC 0x0010 /* drained the life from another */
#define LSVD_OBJ 0x0020 /* lifesaving items */
#define LSVD_ILU 0x0040 /* illuminated */
#define LSVD_FRC 0x0080 /* fractured kamerel */
#define LSVD_NBW 0x0100 /* nitocris's black wraps */
#define LSVD_PLY 0x0200 /* polypoids */
#define LSVD_NIT 0x0400 /* Nitocris becoming a ghoul */
#define LSVD_KAM 0x0800 /* kamerel becoming fractured */
#define LSVD_ALA 0x1000 /* alabaster decay */
#define LSVD_FLS 0x2000 /* God of flesh claims body */
#define LSVDLAST LSVD_FLS /* last lifesaver */
/* set to kill */
@ -3960,6 +4069,12 @@ struct monst *mtmp;
lifesavers |= LSVD_NIT;
if (mtmp->mtyp == PM_BLESSED && !mtmp->mcan && rn2(3))
lifesavers |= LSVD_HLO;
if (mtmp->mtyp == PM_CYCLOPS && !mtmp->mcan && mon_has_arti(mtmp, 0) && plague_victim_on_level())
lifesavers |= LSVD_ASC;
if (mtmp->mtyp == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && !mtmp->mcan && (mon_has_arti(mtmp, 0) || !quest_status.touched_artifact) && plague_victim_on_level())
lifesavers |= LSVD_ASC;
if (allied_iaso_on_level(mtmp))
lifesavers |= LSVD_IAS;
/* some lifesavers do NOT work on stone/gold/glass-ing */
if (stoned || golded || glassed)
@ -4042,6 +4157,40 @@ struct monst *mtmp;
/* set mspec_used */
mtmp->mspec_used = mtmp->mhpmax / 5;
break;
case LSVD_ASC:{
struct monst *victim = random_plague_victim();
if(!victim)
break; //???
/* message */
if (couldsee(mtmp->mx, mtmp->my) || couldsee(victim->mx, victim->my)) {
messaged = TRUE;
pline("But wait...");
pline("A glowing mist rises from %s and flows to %s!",
mon_nam(victim), mon_nam(mtmp));
if (mon_attacktype(mtmp, AT_EXPL)
|| mon_attacktype(mtmp, AT_BOOM))
pline("%s reconstitutes!", Monnam(mtmp));
else
pline("%s looks much better!", Monnam(mtmp));
if(canseemon(victim))
pline("%s dies of %s illness!", Monnam(victim), mhis(victim));
mondied(victim);
}
break;
}
case LSVD_IAS:{
timeout_random_allied_iaso(mtmp);
/* message */
if (couldsee(mtmp->mx, mtmp->my)) {
messaged = TRUE;
pline("But wait...");
if (mon_attacktype(mtmp, AT_EXPL)
|| mon_attacktype(mtmp, AT_BOOM))
pline("%s reconstitutes!", Monnam(mtmp));
pline("%s recovers!", Monnam(mtmp));
}
break;
}
case LSVD_OBJ:
/* message */
if (couldsee(mtmp->mx, mtmp->my)) {
@ -4766,11 +4915,11 @@ boolean was_swallowed; /* digestion */
killer = killer_buf;
killer_format = KILLED_BY_AN;
if(mdat->mattk[i].adtyp == AD_JAILER){
explode(mon->mx, mon->my, AD_FIRE, MON_EXPLODE, tmp, EXPL_FIERY, 1);
explode_pa(mon->mx, mon->my, AD_FIRE, MON_EXPLODE, tmp, EXPL_FIERY, 1, mdat);
u.uevent.ukilled_apollyon = 1;
}
else if(mdat->mtyp == PM_ANCIENT_OF_DEATH){
if(!(u.sealsActive&SEAL_OSE)) explode(mon->mx, mon->my, mdat->mattk[i].adtyp, MON_EXPLODE, tmp, EXPL_DARK, 1);
if(!(u.sealsActive&SEAL_OSE)) explode_pa(mon->mx, mon->my, mdat->mattk[i].adtyp, MON_EXPLODE, tmp, EXPL_DARK, 1, mdat);
}
else if(mdat->mattk[i].adtyp == AD_GARO){
if(couldsee(mon->mx, mon->my)){
@ -4779,10 +4928,10 @@ boolean was_swallowed; /* digestion */
outrumor(rn2(2), BY_OTHER); //either true (3/4) or false (1/4), no mechanism specified.
pline("Belief or disbelief rests with you.");
pline("To die without leaving a corpse....\"");
explode(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, tmp, EXPL_MUDDY, 1);
explode_pa(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, tmp, EXPL_MUDDY, 1, mdat);
pline("\"That is the way of us Garo.\"");
} else {
explode(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, tmp, EXPL_MUDDY, 1);
explode_pa(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, tmp, EXPL_MUDDY, 1, mdat);
}
}
else if(mdat->mattk[i].adtyp == AD_GARO_MASTER){
@ -4793,10 +4942,10 @@ boolean was_swallowed; /* digestion */
outgmaster(); //Gives out a major consultation. Does not set the consultation flags.
pline("Do not forget these words...");
pline("Die I shall, leaving no corpse.\"");
explode(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, tmp, EXPL_MUDDY, 1);
explode_pa(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, tmp, EXPL_MUDDY, 1, mdat);
pline("\"That is the law of us Garo.\"");
} else {
explode(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, tmp, EXPL_MUDDY, 1);
explode_pa(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, tmp, EXPL_MUDDY, 1, mdat);
}
}
else if(mdat->mattk[i].adtyp == AD_FRWK){
@ -4814,7 +4963,7 @@ boolean was_swallowed; /* digestion */
}
else if(mdat->mattk[i].adtyp == AD_SPNL){
struct monst *levi;
explode(mon->mx, mon->my, AD_COLD, MON_EXPLODE, tmp, EXPL_WET, 1);
explode_pa(mon->mx, mon->my, AD_COLD, MON_EXPLODE, tmp, EXPL_WET, 1, mdat);
levi = makemon(&mons[rn2(2) ? PM_LEVISTUS : PM_LEVIATHAN], mon->mx, mon->my, MM_ADJACENTOK);
if(levi)
levi_spawn_items(mon->mx, mon->my, levi);
@ -4850,12 +4999,13 @@ boolean was_swallowed; /* digestion */
} else shieldeff(u.ux,u.uy);
}
else {
explode(mon->mx, mon->my,
explode_pa(mon->mx, mon->my,
mdat->mattk[i].adtyp,
MON_EXPLODE,
tmp,
mon_expl_color(mdat, mdat->mattk[i].adtyp),
1);
1,
mdat);
}
if(mdat->mtyp == PM_GARO_MASTER
|| mdat->mtyp == PM_GARO
@ -4887,7 +5037,7 @@ boolean was_swallowed; /* digestion */
Sprintf(killer_buf, "%s explosion", s_suffix(mdat->mname));
killer = killer_buf;
killer_format = KILLED_BY_AN;
explode(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, d(8,8), EXPL_NOXIOUS, 1);
explode_pa(mon->mx, mon->my, AD_PHYS, MON_EXPLODE, d(8,8), EXPL_NOXIOUS, 1, mdat);
if(mdat->mtyp==PM_GREAT_CTHULHU){
create_gas_cloud(mon->mx, mon->my, 2, 30, FALSE);
}
@ -5671,6 +5821,34 @@ register struct monst *mtmp;
xkilled(mtmp, 1);
}
struct obj *
mk_death_drop_obj(mtmp)
struct monst *mtmp;
{
int typ;
struct obj *otmp;
otmp = mkobj(RANDOM_CLASS, MKOBJ_ARTIF);
if(In_quest(&u.uz) && !Role_if(PM_CONVICT)){
if(otmp->oclass == WEAPON_CLASS || otmp->oclass == ARMOR_CLASS) otmp->objsize = (&mons[urace.malenum])->msize;
if(otmp->oclass == ARMOR_CLASS){
set_obj_shape(otmp, mons[urace.malenum].mflagsb);
}
}
/* Don't create large objects from small monsters */
typ = otmp->otyp;
if (mtmp->data->msize < MZ_HUMAN && typ != FOOD_RATION
&& typ != LEASH
&& typ != FIGURINE
&& (otmp->owt > 3 || objects[typ].oc_size > MZ_MEDIUM)
&& !is_divider(mtmp->data)
) {
delobj(otmp);
otmp = 0;
}
return otmp;
}
/* the player has killed the monster mtmp */
void
xkilled(mtmp, dest)
@ -5681,11 +5859,11 @@ xkilled(mtmp, dest)
*/
int dest;
{
register int tmp, x = mtmp->mx, y = mtmp->my;
register struct permonst *mdat;
int tmp, x = mtmp->mx, y = mtmp->my;
struct permonst *mdat;
int mndx;
register struct obj *otmp;
register struct trap *t;
struct obj *otmp;
struct trap *t;
boolean redisp = FALSE, illalarm = FALSE;
boolean wasinside = u.uswallow && (u.ustuck == mtmp);
@ -5848,32 +6026,21 @@ xkilled(mtmp, dest)
&& mdat->mlet != S_PLANT
&& !(get_mx(mtmp, MX_ESUM))
&& !(mtmp->mclone)
/*Not reviving templates*/
&& !(has_template(mtmp, ZOMBIFIED))
&& !(has_template(mtmp, VAMPIRIC))
&& !(has_template(mtmp, TOMB_HERD))
&& !(has_template(mtmp, YELLOW_TEMPLATE))
&& !(has_template(mtmp, SPORE_ZOMBIE))
&& !(has_template(mtmp, CORDYCEPS))
&& !(is_auton(mtmp->data))
) {
int typ;
/*Death Drop*/
otmp = mkobj_at(RANDOM_CLASS, x, y, MKOBJ_ARTIF);
if(In_quest(&u.uz) && !Role_if(PM_CONVICT)){
if(otmp->oclass == WEAPON_CLASS || otmp->oclass == ARMOR_CLASS) otmp->objsize = (&mons[urace.malenum])->msize;
if(otmp->oclass == ARMOR_CLASS){
if(is_suit(otmp)) otmp->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_BODYTYPEMASK);
else if(is_helmet(otmp)) otmp->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_HEADMODIMASK);
else if(is_shirt(otmp)) otmp->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_HUMANOID) ? MB_HUMANOID : ((&mons[urace.malenum])->mflagsb&MB_BODYTYPEMASK);
}
otmp = mk_death_drop_obj(mtmp);
if(otmp){
place_object(otmp, x, y);
redisp = TRUE;
}
/* Don't create large objects from small monsters */
typ = otmp->otyp;
if (mdat->msize < MZ_HUMAN && typ != FOOD_RATION
&& typ != LEASH
&& typ != FIGURINE
&& (otmp->owt > 3 || objects[typ].oc_size > MZ_MEDIUM)
&& !is_divider(mdat)
) {
delobj(otmp);
} else redisp = TRUE;
}
/* Whether or not it always makes a corpse is, in theory,
* different from whether or not the corpse is "special";
@ -9077,6 +9244,7 @@ struct monst *mtmp;
pline("Some unseen virtue is sucked into the open mouth of %s.", mon_nam(mtmp));
}
damage = d(min(10, (mtmp->m_lev)/3), 8);
if(mon_resistance(tmpm, FREE_ACTION)) damage /= 2;
if(resists_cold(tmpm)) damage /= 2;
if(damage >= tmpm->mhp){
grow_up(mtmp,tmpm);
@ -9232,6 +9400,7 @@ struct monst *mtmp;
pline("%s breathes out static curses.", Monnam(mtmp));
}
if(
!(mon_resistance(targ, FREE_ACTION)) &&
!(targ->misc_worn_check & W_ARMH && (otmp = which_armor(targ, W_ARMH)) && !otmp->cursed) &&
!(targ->misc_worn_check & W_ARMC && (otmp = which_armor(targ, W_ARMC)) && !otmp->cursed) &&
!(targ->misc_worn_check & W_ARM && (otmp = which_armor(targ, W_ARM)) && !otmp->cursed) &&

View file

@ -360,6 +360,44 @@ int template;
/* misc: */
ptr->msound = MS_SILENT;
break;
case CORDYCEPS:
ptr->mflagsm |= (MM_STATIONARY);
case SPORE_ZOMBIE:
/* flags: */
ptr->mflagsm |= (MM_BREATHLESS);
if(ptr->mflagsm&MM_NEEDPICK)
ptr->mflagsm &= ~(MM_TUNNEL|MM_NEEDPICK);
ptr->mflagst = (MT_HOSTILE|MT_MINDLESS|MT_NOTAKE);
ptr->mflagsg &= ~(MG_INFRAVISIBLE);
ptr->mflagsv = (MV_ECHOLOCATE|MV_SCENT);
ptr->mflagsb |= (MB_NOEYES);
//Note: Plant, NOT Undead. It's a living zombie. Also less resistant to damage
ptr->mflagsa |= (MA_PLANT);
/*Zuggtmoy's spores are against natural law*/
if(ptr->maligntyp > 0)
ptr->maligntyp = -1*ptr->maligntyp;
else if(ptr->maligntyp == 0)
ptr->maligntyp = -5;
/*Zombies have no skill*/
/*Note: The actual effect of this is to zero out mflagsf, but flags are removed explicitly for futureproofing reasons.*/
ptr->mflagsf &= ~(MF_MARTIAL_B|MF_MARTIAL_S|MF_MARTIAL_E);
ptr->mflagsf &= ~(MF_BAB_FULL|MF_BAB_HALF);
ptr->mflagsf &= ~(MF_LEVEL_30|MF_LEVEL_45);
ptr->mflagsf &= ~(MF_PHYS_SCALING);
/* defense: */
ptr->dac += -2; /* penalty to dodge AC */
ptr->hdr += 1;
ptr->bdr += 1;
ptr->gdr += 1;
ptr->ldr += 1;
ptr->fdr += 1;
/* resists: */
ptr->mresists |= MR_SICK;
/* misc: */
ptr->msound = MS_SILENT;
break;
case FRACTURED:
/* flags: */
ptr->mflagsm |= (MM_BREATHLESS);
@ -664,6 +702,22 @@ int template;
ptr->pac += 6;
ptr->hdr += 6;
break;
case PLAGUE_TEMPLATE:
ptr->mflagst &= ~(MT_HOSTILE);
ptr->mflagst |= MT_PEACEFUL;
ptr->mlevel = (ptr->mlevel+2)/3;
ptr->mr /= 3;
ptr->dac = -5;
ptr->pac = 0;
ptr->spe_hdr = 0;
ptr->spe_bdr = 0;
ptr->spe_gdr = 0;
ptr->spe_ldr = 0;
ptr->spe_fdr = 0;
ptr->mmove = 0;
ptr->msound = (ptr->msound == MS_SILENT) ? MS_SILENT : MS_COUGH;
ptr->mresists &= ~(MR_POISON|MR_DRAIN|MR_SICK|MR_MAGIC);
break;
}
#undef MT_ITEMS
@ -679,7 +733,7 @@ int template;
insert = FALSE;
/* some templates completely skip specific attacks */
while ((template == ZOMBIFIED || template == SKELIFIED) &&
while ((template == ZOMBIFIED || template == SKELIFIED || template == SPORE_ZOMBIE) &&
(
attk->lev_req > ptr->mlevel ||
attk->aatyp == AT_SPIT ||
@ -699,7 +753,7 @@ int template;
)
){
/* shift all further attacks forwards one slot, and make last one all 0s */
for (j = 0; j < (NATTK - i); j++)
for (j = 0; j < (NATTK - i - 1); j++)
attk[j] = attk[j + 1];
attk[j] = noattack;
}
@ -713,7 +767,7 @@ int template;
)
){
/* shift all further attacks forwards one slot, and make last one all 0s */
for (j = 0; j < (NATTK - i); j++)
for (j = 0; j < (NATTK - i - 1); j++)
attk[j] = attk[j + 1];
attk[j] = noattack;
}
@ -751,7 +805,7 @@ int template;
)
){
/* shift all further attacks forwards one slot, and make last one all 0s */
for (j = 0; j < (NATTK - i); j++)
for (j = 0; j < (NATTK - i - 1); j++)
attk[j] = attk[j + 1];
attk[j] = noattack;
}
@ -768,7 +822,7 @@ int template;
)
){
/* shift all further attacks forwards one slot, and make last one all 0s */
for (j = 0; j < (NATTK - i); j++)
for (j = 0; j < (NATTK - i - 1); j++)
attk[j] = attk[j + 1];
attk[j] = noattack;
}
@ -800,7 +854,7 @@ int template;
{
/* remove attack */
/* shift all further attacks forwards one slot, and make last one all 0s */
for (j = 0; j < (NATTK - i); j++)
for (j = 0; j < (NATTK - i - 1); j++)
attk[j] = attk[j + 1];
attk[j] = noattack;
}
@ -924,6 +978,29 @@ int template;
attk->damd = max(4, max(ptr->msize * 2, attk->damd));
special = TRUE;
}
/* infectees' bites are sickening: pt 1: other bites */
if (template == SPORE_ZOMBIE && (
attk->aatyp == AT_OBIT
|| attk->aatyp == AT_LNCK
)
){
attk->adtyp = AD_DISE;
attk->damn = max(1, attk->damn);
attk->damd = max(4, max(ptr->msize * 2, attk->damd));
}
/* infectees' bites are sickening: pt 2: primary bites*/
if (template == SPORE_ZOMBIE && (
attk->aatyp == AT_BITE
|| (insert_okay && !nomouth(ptr->mtyp))
)
){
maybe_insert();
attk->aatyp = AT_BITE;
attk->adtyp = AD_DISE;
attk->damn = max(1, attk->damn);
attk->damd = max(4, max(ptr->msize * 2, attk->damd));
special = TRUE;
}
/* pseudonatural's bites become int-draining tentacles */
if (template == PSEUDONATURAL && (
(attk->aatyp == AT_BITE)
@ -937,6 +1014,27 @@ int template;
attk->damd = 4;
special = TRUE;
}
/* Cordyceps always have the same attacks */
if(template == CORDYCEPS){
if(i==0){
attk->aatyp = AT_GAZE;
attk->adtyp = AD_SPOR;
attk->damn = 0;
attk->damd = 0;
}
else if(i==1){
attk->aatyp = AT_NONE;
attk->adtyp = AD_DISE;
attk->damn = 0;
attk->damd = 0;
}
else {
/* shift all further attacks forwards one slot, and make last one all 0s */
for (j = 0; j < (NATTK - i - 1); j++)
attk[j] = attk[j + 1];
attk[j] = noattack;
}
}
/* tomb herd's attacks are generally stronger */
if (template == TOMB_HERD && (
!is_null_attk(attk))
@ -1180,6 +1278,9 @@ int mtyp;
return is_minion(ptr);
case MOLY_TEMPLATE:
return is_cha_demon(ptr);
case CORDYCEPS:
case SPORE_ZOMBIE:
return can_undead(ptr);
}
/* default fall through -- allow all */
return TRUE;
@ -2279,21 +2380,54 @@ num_horns(ptr)
struct permonst *ptr;
{
switch (monsndx(ptr)) {
case PM_DRACAE_ELADRIN:
case PM_FIERNA:
case PM_GRAZ_ZT:
return 6;
case PM_TRICERATOPS:
return 3;
case PM_LAMB:
case PM_ROTHE:
case PM_SHEEP:
case PM_DIRE_SHEEP:
case PM_HORNED_DEVIL: /* ? "more than one" */
case PM_MINOTAUR:
case PM_ASMODEUS:
case PM_MINOTAUR_PRIESTESS:
case PM_SMALL_GOAT_SPAWN:
case PM_GOAT_SPAWN:
case PM_GIANT_GOAT_SPAWN:
case PM_BLESSED:
case PM_BAPHOMET:
case PM_MALCANTHET:
case PM_ORCUS:
case PM_BALROG:
case PM_DURIN_S_BANE:
case PM_LUNGORTHIN:
case PM_LEGION_DEVIL_GRUNT:
case PM_LEGION_DEVIL_SOLDIER:
case PM_LEGION_DEVIL_SERGEANT:
case PM_LEGION_DEVIL_CAPTAIN:
case PM_GOOD_NEIGHBOR:
case PM_PIT_FIEND:
case PM_NESSIAN_PIT_FIEND:
case PM_BAEL:
case PM_DISPATER:
case PM_MAMMON:
case PM_GREEN_PIT_FIEND:
case PM_BELIAL:
case PM_MOLEK:
case PM_MEPHISTOPHELES:
case PM_BAALPHEGOR:
case PM_ASMODEUS:
case PM_VERIER:
case PM_GLASYA:
return 2;
case PM_WHITE_UNICORN:
case PM_GRAY_UNICORN:
case PM_BLACK_UNICORN:
case PM_NIGHTMARE:
case PM_KI_RIN:
case PM_ANCIENT_OF_CORRUPTION:
return 1;
default:
break;
@ -2610,6 +2744,9 @@ static const short grownups[][2] = {
{PM_OMEGA_METROID, PM_METROID_QUEEN},
{PM_VAMPIRE, PM_VAMPIRE_LORD}, {PM_VAMPIRE, PM_VAMPIRE_LADY}, {PM_BAT, PM_GIANT_BAT},
{PM_GIANT_BAT, PM_BATTLE_BAT}, {PM_BATTLE_BAT, PM_WARBAT},
{PM_PLAINS_CENTAUR, PM_CENTAUR_CHIEFTAIN},
{PM_FOREST_CENTAUR, PM_CENTAUR_CHIEFTAIN},
{PM_MOUNTAIN_CENTAUR, PM_CENTAUR_CHIEFTAIN},
{PM_BABY_GRAY_DRAGON, PM_GRAY_DRAGON},
{PM_BABY_SILVER_DRAGON, PM_SILVER_DRAGON},
{PM_BABY_DEEP_DRAGON, PM_DEEP_DRAGON},
@ -2630,6 +2767,7 @@ static const short grownups[][2] = {
{PM_BABY_LONG_WORM, PM_LONG_WORM},
{PM_BABY_PURPLE_WORM, PM_PURPLE_WORM},
{PM_BABY_CROCODILE, PM_CROCODILE},
{PM_CHUUL, PM_ELDER_CHUUL},
{PM_BABY_CAVE_LIZARD,PM_SMALL_CAVE_LIZARD}, {PM_SMALL_CAVE_LIZARD, PM_CAVE_LIZARD}, {PM_CAVE_LIZARD, PM_LARGE_CAVE_LIZARD},
{PM_SOLDIER, PM_SERGEANT}, {PM_SERGEANT, PM_LIEUTENANT}, {PM_LIEUTENANT, PM_CAPTAIN},
{PM_MYRMIDON_HOPLITE, PM_MYRMIDON_LOCHIAS}, {PM_MYRMIDON_LOCHIAS, PM_MYRMIDON_YPOLOCHAGOS},
@ -2646,6 +2784,7 @@ static const short grownups[][2] = {
{PM_ACOLYTE, PM_PRIESTESS},
{PM_SECRET_WHISPERER, PM_TRUTH_SEER}, {PM_TRUTH_SEER, PM_DREAM_EATER}, {PM_DREAM_EATER, PM_VEIL_RENDER},
{PM_APPRENTICE, PM_WIZARD},
{PM_VALKYRIE, PM_AWAKENED_VALKYRIE}, {PM_AWAKENED_VALKYRIE, PM_TRANSCENDENT_VALKYRIE},
{PM_DUNGEON_FERN_SPROUT, PM_DUNGEON_FERN},
{PM_SWAMP_FERN_SPROUT, PM_SWAMP_FERN},
{PM_BURNING_FERN_SPROUT, PM_BURNING_FERN},

View file

@ -671,7 +671,7 @@ boolean digest_meal;
if(mon->mtrapped && t_at(mon->mx, mon->my) && t_at(mon->mx, mon->my)->ttyp == VIVI_TRAP)
return;
if(mon->mtame && u.ufirst_life)
if(mon->mtame && u.ufirst_life && mon->mhp < mon->mhpmax)
mon->mhp++;
if(is_alabaster_mummy(mon->data)
@ -762,6 +762,11 @@ boolean digest_meal;
}
//Degeneration cases block normal healing. Only one will take effect (bug?).
/*Blib's image degrades from loss of artifact*/
if(mon->mtyp == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && !mon_has_arti(mon, 0) && quest_status.touched_artifact && mon->mhp > 1){
mon->mhp -= 1;
return;
}
/*Degen from drowning in blood*/
if(mon->mbdrown > 0){
mon->mbdrown--;
@ -837,6 +842,7 @@ boolean digest_meal;
if(uring_art(ART_VILYA)){
perX += heal_vilya()*HEALCYCLE/10;
}
perX -= mon_healing_penalty(mon);
if(!nonliving(mon->data)){
if(perX < 1)
perX = 1;
@ -1042,7 +1048,7 @@ int mtyp;
}
STATIC_OVL void
void
dracae_eladrin_spawn_equip(mtmp, mtyp)
struct monst *mtmp;
int mtyp;
@ -1073,7 +1079,7 @@ int mtyp;
}
else if(rn2(2)){
otmp = mksobj(KITE_SHIELD, MKOBJ_NOINIT);
set_material_gm(otmp, DRAGON_HIDE);
set_material_gm(otmp, SHELL_MAT);
otmp->objsize = size;
fix_object(otmp);
(void) mpickobj(mtmp, otmp);
@ -1082,7 +1088,7 @@ int mtyp;
}
else if(mtyp == PM_NOVIERE_ELADRIN || mtyp == PM_SHIERE_ELADRIN){
otmp = mksobj(KITE_SHIELD, MKOBJ_NOINIT);
set_material_gm(otmp, DRAGON_HIDE);
set_material_gm(otmp, SHELL_MAT);
otmp->objsize = size;
fix_object(otmp);
(void) mpickobj(mtmp, otmp);
@ -1096,8 +1102,7 @@ int mtyp;
otmp = mksobj(armors[i], NO_MKOBJ_FLAGS);
set_material_gm(otmp, SHELL_MAT);
otmp->objsize = size;
if(mtyp == PM_UISCERRE_ELADRIN && armors[i] == PLATE_MAIL)
otmp->bodytypeflag = MB_HUMANOID|MB_SLITHY;
set_obj_shape(otmp, mtmp->data->mflagsb);
fix_object(otmp);
(void) mpickobj(mtmp, otmp);
}
@ -1164,6 +1169,9 @@ register struct monst *mtmp;
familliar->mhpmax = mtmp->mhpmax;
familliar->mvar_witchID = (long)mtmp->m_id;
familliar->mpeaceful = mtmp->mpeaceful;
if(mtmp->mtame){
familliar = tamedog_core(familliar, (struct obj *)0, TRUE);
}
//Stop running
if(mtmp->mflee && mtmp->mhp > mtmp->mhpmax/2){
mtmp->mflee = 0;
@ -1259,6 +1267,16 @@ register struct monst *mtmp;
mtmp->mlaughing=rnd(5);
}
}
if(mtmp->mspores){
if(!rn2(4)){
mtmp->mconf = 1;
(void) set_apparxy(mtmp);
}
if(!rn2(4)){
mtmp->mberserk = 1;
(void) set_apparxy(mtmp);
}
}
if(mtmp->mrage){
extern const int monstr[];
if(!rn2(4)){
@ -1451,7 +1469,7 @@ register struct monst *mtmp;
}
}
if (is_commander(mdat) && mfind_target(mtmp, FALSE))
if (is_commander(mdat) && mfind_target(mtmp, FALSE, TRUE))
m_command(mtmp);
if (((mdat->msound == MS_SHRIEK || mdat->msound == MS_HOWL) && !um_dist(mtmp->mx, mtmp->my, 1))
@ -1556,7 +1574,8 @@ register struct monst *mtmp;
if((is_drow(mtmp->data) || mtmp->mtyp == PM_LUGRIBOSSK || mtmp->mtyp == PM_MAANZECORIAN)
&& (!mtmp->mpeaceful || Darksight)
&& (levl[mtmp->mx][mtmp->my].lit == 1 || viz_array[mtmp->my][mtmp->mx]&TEMP_LIT1)
&& !(mtmp->mpeaceful && !mtmp->mtame && mtmp->mfaction == PEN_A_SYMBOL)
&& (levl[mtmp->mx][mtmp->my].lit == 1 || (viz_array[mtmp->my][mtmp->mx]&TEMP_LIT1 && !(viz_array[mtmp->my][mtmp->mx]&TEMP_DRK1)))
&& !mtmp->mcan && mtmp->mspec_used < 4
&& !(noactions(mtmp))
&& !(mindless_mon(mtmp))
@ -1566,6 +1585,25 @@ register struct monst *mtmp;
vision_full_recalc = 1;
if(mtmp->mtyp == PM_HEDROW_WARRIOR) mtmp->mspec_used += d(4,4);
else mtmp->mspec_used += max(10 - mtmp->m_lev,2);
return 0;
}
if((!mtmp->mpeaceful || !Darksight)
&& (levl[mtmp->mx][mtmp->my].lit == 0 || viz_array[mtmp->my][mtmp->mx]&TEMP_DRK1)
&& !(noactions(mtmp))
&& !(mindless_mon(mtmp))
&& !darksight(mtmp->data)
&& which_armor(mtmp, W_ARM)
){
struct obj *otmp = which_armor(mtmp, W_ARM);
if(otmp->otyp == LANTERN_PLATE_MAIL && !otmp->lamplit && !otmp->cursed){
if (canseemon(mtmp)) {
pline("%s lights %s %s.", Monnam(mtmp), mhis(mtmp),
xname(otmp));
}
begin_burn(otmp);
return 0;
}
}
if (mtmp->mtyp == PM_NURSE || mtmp->mtyp == PM_HEALER || mtmp->mtyp == PM_CLAIRVOYANT_CHANGED){
@ -2105,7 +2143,7 @@ register struct monst *mtmp;
if(!mtarget_adjacent(mtmp)){ /* don't fight at range if there's a melee target */
/* Look for other monsters to fight (at a distance) */
struct monst *mtmp2 = mfind_target(mtmp, FALSE);
struct monst *mtmp2 = mfind_target(mtmp, FALSE, TRUE);
if (mtmp2 &&
(mtmp2 != &youmonst ||
dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > 2) &&

View file

@ -562,6 +562,15 @@ NEARDATA struct permonst mons[] = {
MB_NOLIMBS|MB_NOHEAD|MB_NEUTER /*MB*/, MG_INFRAVISIBLE /*MG*/,
MA_ELEMENTAL /*MA*/, MV_ECHOLOCATE /*MV*/, HI_ZAP),
MON("ballistospore", S_EYE, //2
LVL(6, 13, 0, 0), (G_NOCORPSE|G_NOGEN),
DEF(NAT_AC(0)),
A(ATTK(AT_EXPL, AD_PHYS, 4, 6), ATTK(AT_BOOM, AD_DISE, 2, 6)),
SIZ(WT_DIMINUTIVE, CN_DIMINUTIVE, MS_SILENT, MZ_SMALL), 0, 0,
MM_FLY|MM_FLOAT|MM_BREATHLESS /*MM*/, MT_MINDLESS|MT_HOSTILE /*MT*/, 0 /*MF*/,
MB_NOLIMBS|MB_NOHEAD|MB_NEUTER /*MB*/, 0 /*MG*/,
MA_PLANT /*MA*/, MV_SCENT /*MV*/, CLR_ORANGE),
MON("pursuer", S_EYE, //3 /* needs encyc entry */
LVL(2, 13, 0, 0), (G_NOCORPSE|G_NOGEN),
DEF(NAT_AC(6)),
@ -1953,7 +1962,7 @@ NEARDATA struct permonst mons[] = {
MON("energy vortex", S_VORTEX,//9
LVL(6, 8, 30, 0), (G_GENO|G_NOCORPSE|1), /*Engulfing vorticies slower than 12 get 2x speed when stuck to you*/
DEF(NAT_AC(8)),
A(ATTK(AT_ENGL, AD_ELEC, 2, 6), ATTK(AT_ENGL, AD_DREN, 0, 0),
A(ATTK(AT_ENGL, AD_ELEC, 2, 6), ATTK(AT_ENGL, AD_DREN, 6, 6),
ATTK(AT_NONE, AD_ELEC, 0, 4)),
SIZ(0, 0, MS_SILENT, MZ_HUGE),
MR_ELEC|MR_SLEEP|MR_DISINT|MR_POISON|MR_STONE|MR_SICK, 0,
@ -2184,10 +2193,10 @@ then fill new spaces with our spawn!
MON("couatl", S_LAW_ANGEL,//11
LVL(8, 10, 30, 7), (G_NOHELL|G_SGROUP|G_NOCORPSE|1),
DEF(NAT_AC(5)),
A(ATTK(AT_BITE, AD_DRST, 2, 4), ATTK(AT_BITE, AD_PHYS, 1, 3),
ATTK(AT_HUGS, AD_WRAP, 2, 4)),
A(ATTK(AT_BITE, AD_DRST, 1, 3), ATTK(AT_HUGS, AD_WRAP, 2, 4),
ATTK(AT_MMGC, AD_SPEL, 0, 6)),
SIZ(WT_LARGE, 400, MS_HISS, MZ_LARGE), MR_POISON, 0,
MM_FLY /*MM*/, MT_STALK|MT_BOLD /*MT*/, MF_LEVEL_45 /*MF*/,
MM_FLY /*MM*/, MT_STALK|MT_BOLD /*MT*/, MF_PHYS_SCALING|MF_LEVEL_45 /*MF*/,
MB_STRONG|MB_POIS|MB_SLITHY|MB_LONGHEAD|MB_WINGS|MB_NOHANDS /*MB*/, MG_NOPOLY|MG_INFRAVISIBLE|MG_NASTY|MG_HATESUNHOLY|MG_TRACKER /*MG*/,
MA_MINION|MA_REPTILIAN|MA_AVIAN /*MA*/, MV_INFRAVISION|MV_NORMAL|MV_SCENT /*MV*/, CLR_GREEN),
MON("Aleax", S_LAW_ANGEL,//13
@ -2290,6 +2299,39 @@ then fill new spaces with our spawn!
MB_WINGS|MB_HUMANOID|MB_STRONG /*MB*/, MG_NASTY|MG_LORD|MG_INFRAVISIBLE|MG_NOPOLY|MG_REGEN|MG_HATESUNHOLY|MG_TRACKER /*MG*/,
MA_MINION /*MA*/, MV_EXTRAMISSION|MV_SEE_INVIS /*MV*/, HI_ZAP),
MON("Iasoian Archon", S_LAW_ANGEL,//34 /* Needs encyc entry */
LVL(11, 12, 30, -13), (G_PLANES|G_NOCORPSE|G_NOGEN),
DEF(DEX_AC(3), SPE_AC(3)),
A(ATTK(AT_TUCH, AD_SLEE, 1, 3), ATTK(AT_ESPR, AD_STAR, 4, 4)),
SIZ(WT_LARGE, 400, MS_NURSE, MZ_LARGE),
MR_DRAIN|MR_FIRE|MR_COLD|MR_ELEC|MR_SLEEP|MR_POISON, MF_BAB_HALF,
MM_FLY /*MM*/, MT_STALK|MT_COLLECT|MT_MAGIC /*MT*/, 0 /*MF*/,
MB_HUMANOID /*MB*/, MG_NASTY|MG_INFRAVISIBLE|MG_NOPOLY|MG_REGEN|MG_HATESUNHOLY|MG_HATESIRON /*MG*/,
MA_MINION /*MA*/, MV_EXTRAMISSION|MV_SEE_INVIS /*MV*/, CLR_GRAY),
MON("Panakeian Archon", S_LAW_ANGEL,//34 /* Needs encyc entry */
LVL(22, 16, 30, 0), (G_PLANES|G_NOCORPSE|G_NOGEN),
DEF(NAT_AC(4), DEX_AC(6), SPE_AC(8)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8),
ATTK(AT_MAGC, AD_CLRC, 0, 9)),
SIZ(WT_LARGE, 400, MS_NURSE, MZ_LARGE),
MR_DRAIN|MR_FIRE|MR_COLD|MR_ELEC|MR_SLEEP|MR_POISON|MR_MAGIC, MF_MARTIAL_E|MF_BAB_FULL,
MM_FLY /*MM*/, MT_STALK|MT_COLLECT|MT_MAGIC|MT_BOLD /*MT*/, 0 /*MF*/,
MB_HUMANOID|MB_WINGS /*MB*/, MG_NASTY|MG_LORD|MG_INFRAVISIBLE|MG_NOPOLY|MG_REGEN|MG_HATESUNHOLY|MG_TRACKER /*MG*/,
MA_MINION /*MA*/, MV_EXTRAMISSION|MV_SEE_INVIS /*MV*/, CLR_BRIGHT_MAGENTA),
MON("Hygieian Archon", S_LAW_ANGEL,//34 /* Needs encyc entry */
LVL(27, 17, 77, 17), (G_PLANES|G_NOCORPSE|G_NOGEN),
DEF(NAT_AC(10), SPE_AC(7)),
A(ATTK(AT_WEAP, AD_ACFR, 2, 7), ATTK(AT_WEAP, AD_ACFR, 2, 7),
ATTK(AT_XWEP, AD_ACFR, 2, 7),
ATTK(AT_OBIT, AD_PHYS, 2, 4), ATTK(AT_TUCH, AD_PHYS, 0, 0),
ATTK(AT_HUGS, AD_WRAP, 2, 4), ATTK(AT_HUGS, AD_PHYS, 4, 4),
ATTK(AT_MAGC, AD_SPEL, 0, 7)),
SIZ(WT_LARGE, 400, MS_CUSS, MZ_LARGE),
MR_DRAIN|MR_FIRE|MR_COLD|MR_ELEC|MR_SLEEP|MR_POISON|MR_MAGIC, MF_MARTIAL_E|MF_BAB_FULL,
MM_FLY /*MM*/, MT_STALK|MT_COLLECT|MT_MAGIC|MT_BOLD /*MT*/, 0 /*MF*/,
MB_STRONG|MB_HUMANOID /*MB*/, MG_NASTY|MG_LORD|MG_INFRAVISIBLE|MG_NOPOLY|MG_REGEN|MG_HATESUNHOLY|MG_TRACKER /*MG*/,
MA_MINION /*MA*/, MV_EXTRAMISSION|MV_SEE_INVIS /*MV*/, CLR_BRIGHT_MAGENTA),
MON("harrower of Zariel", S_LAW_ANGEL,//18 /* Needs encyc entry */
LVL(14, 17, 77, 7), (G_PLANES|G_NOCORPSE|G_NOGEN),
DEF(SPE_AC(16), NAT_DR_BODY(9), NAT_DR_GLOV(7), SPE_DR(9), SPE_DR_HEAD(12)),
@ -2686,7 +2728,7 @@ then fill new spaces with our spawn!
SIZ(WT_MEDIUM, 350, MS_HUMANOID, MZ_HUMAN),
MR_FIRE|MR_ELEC|MR_COLD|MR_SLEEP|MR_POISON|MR_MAGIC, MR_SLEEP,
MM_FLY|MM_AMPHIBIOUS|MM_SWIM /*MM*/, MT_COLLECT|MT_OMNIVORE|MT_STALK|MT_WANTSAMUL /*MT*/, MF_MARTIAL_E|MF_BAB_FULL|MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_STRONG|MB_NOGLOVES|MB_WINGS|MB_FEMALE /*MB*/, MG_NOPOLY|MG_INFRAVISIBLE|MG_NASTY|MG_LORD|MG_HATESUNHOLY|MG_TRACKER|MG_REGEN /*MG*/,
MB_HUMANOID|MB_STRONG|MB_NOGLOVES|MB_WINGS|MB_FEMALE /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE|MG_NASTY|MG_LORD|MG_HATESUNHOLY|MG_TRACKER|MG_REGEN /*MG*/,
MA_MINION|MA_FEY /*MA*/, MV_CATSIGHT|MV_SEE_INVIS|MV_INFRAVISION|MV_LOWLIGHT3 /*MV*/, CLR_BRIGHT_CYAN),
MON("kuker", S_CHA_ANGEL,//25 /*Needs tile*/ /* Needs encyc entry */
@ -2993,6 +3035,15 @@ then fill new spaces with our spawn!
0 /*MM*/, MT_OMNIVORE /*MT*/, MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_FEMALE|MB_NOHANDS|MB_NOFEET /*MB*/, MG_INFRAVISIBLE|MG_HATESIRON /*MG*/,
MA_ARACHNID|MA_DEMIHUMAN|MA_DROW|MA_ELF /*MA*/, MV_DARKSIGHT /*MV*/, CLR_BLACK),
MON("centaur chieftain", S_CENTAUR,//
LVL(14, 20, 20, 6), (G_GENO|1),
DEF(NAT_AC(9)),
A(ATTK(AT_WEAP, AD_PHYS, 1,12), ATTK(AT_XWEP, AD_PHYS, 1,6),
ATTK(AT_KICK, AD_PHYS, 1, 8), ATTK(AT_KICK, AD_PHYS, 1,8)),
SIZ(WT_LARGE, 550, MS_HUMANOID, MZ_MEDIUM), 0, 0,
0 /*MM*/, MT_OMNIVORE|MT_GREEDY|MT_COLLECT /*MT*/, MF_MARTIAL_B /*MF*/,
MB_HUMANOID|MB_ANIMAL|MB_STRONG /*MB*/, MG_COMMANDER|MG_INFRAVISIBLE|MG_TRACKER /*MG*/,
MA_ANIMAL|MA_DEMIHUMAN /*MA*/, MV_NORMAL /*MV*/, HI_LORD),
MON("drider", S_CENTAUR,//22
LVL(16, 15, 10, -18), (G_GENO|1),
DEF(NAT_AC(8)),
@ -4073,7 +4124,7 @@ struct permonst _mons2[] = {
ATTK(AT_MAGC, AD_SPEL, 0, 0)),
SIZ(700, 100, MS_MUMBLE, MZ_HUMAN),
MR_FIRE|MR_COLD|MR_SLEEP|MR_ELEC|MR_POISON|MR_STONE, MR_FIRE|MR_COLD,
MM_BREATHLESS|MM_TUNNEL /*MM*/, MT_TRAITOR|MT_MAGIC|MT_HOSTILE|MT_HOSTILE /*MT*/, MF_MARTIAL_E|MF_BAB_FULL /*MF*/,
MM_BREATHLESS|MM_TUNNEL /*MM*/, MT_TRAITOR|MT_MAGIC|MT_HOSTILE /*MT*/, MF_MARTIAL_E|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_POIS|MB_FEMALE /*MB*/, MG_VBLUNT|MG_PRINCE|MG_NOPOLY|MG_REGEN|MG_HATESIRON /*MG*/,
MA_UNDEAD|MA_ELF|MA_DROW /*MA*/, MV_INFRAVISION|MV_DARKSIGHT /*MV*/, CLR_BLACK),
MON("Vecna", S_LICH,//43 /*Needs tile*/ /* Needs encyc entry */
@ -4665,6 +4716,16 @@ struct permonst _mons2[] = {
/*
* Unknown abominations
*/
MON("chuul", S_UMBER,//
LVL(4, 10, 0, -6), (G_GENO|G_SGROUP|1),
DEF(NAT_AC(5)),
A(ATTK(AT_CLAW, AD_PHYS, 2, 6), OFFHND_ATTK(AT_CLAW, AD_PHYS, 2, 6),
ATTK(AT_HUGS, AD_PHYS, 2, 4),
ATTK(AT_TENT, AD_PLYS, 1, 4)),
SIZ(WT_MEDIUM, CN_MEDIUM, MS_SILENT, MZ_MEDIUM), 0, 0,
MM_SWIM|MM_AMPHIBIOUS /*MM*/, MT_CARNIVORE /*MT*/, 0 /*MF*/,
MB_THICK_HIDE|MB_STRONG|MB_ANIMAL|MB_HAS_FEET|MB_OVIPAROUS/*MB*/, MG_TRACKER|MG_SANLOSS|MG_INSIGHT /*MG*/,
MA_AQUATIC /*MA*/, MV_SCENT|MV_INFRAVISION /*MV*/, CLR_GREEN),
MON("umber hulk", S_UMBER,//12
LVL(9, 6, 25, 0), (G_GENO|2),
DEF(NAT_AC(8)),
@ -4680,8 +4741,18 @@ struct permonst _mons2[] = {
A(POLYWEP_ATTK(AT_TUCH, AD_TELE, 0, 0), ATTK(AT_TNKR, AD_TNKR, 0, 0)),
SIZ(0, 0, MS_HUMANOID, MZ_LARGE), 0, 0,
MM_WALLWALK /*MM*/, 0 /*MT*/, 0 /*MF*/,
MB_STRONG|MB_NOLIMBS|MB_NOEYES|MB_INDIGESTIBLE /*MB*/, MG_RALL|MG_INFRAVISIBLE /*MG*/,
MB_STRONG|MB_NOLIMBS|MB_NOEYES|MB_INDIGESTIBLE /*MB*/, MG_RALL|MG_INFRAVISIBLE|MG_INSIGHT /*MG*/,
MA_ET /*MA*/, MV_NORMAL /*MV*/, CLR_BLUE),
MON("elder chuul", S_UMBER,//
LVL(11, 20, 0, -6), (G_GENO|G_NOGEN),
DEF(NAT_AC(10), NAT_DR_ALL(4, 4, 4, 4, 3)),
A(ATTK(AT_CLAW, AD_PHYS, 4, 8), OFFHND_ATTK(AT_CLAW, AD_PHYS, 4, 8),
ATTK(AT_HUGS, AD_PHYS, 2, 6),
ATTK(AT_TENT, AD_PLYS, 1, 6)),
SIZ(WT_LARGE, CN_LARGE, MS_SILENT, MZ_LARGE), 0, 0,
MM_SWIM|MM_AMPHIBIOUS /*MM*/, MT_CARNIVORE /*MT*/, 0 /*MF*/,
MB_THICK_HIDE|MB_STRONG|MB_ANIMAL|MB_HAS_FEET|MB_OVIPAROUS /*MB*/, MG_TRACKER|MG_SANLOSS|MG_INSIGHT /*MG*/,
MA_AQUATIC /*MA*/, MV_SCENT|MV_INFRAVISION /*MV*/, CLR_ORANGE),
/*
* Placeholder for the random creature...
*
@ -5978,7 +6049,7 @@ MON("Daemon", S_HUMAN,//55
LVL(45, 9, 99, 15), (G_NOGEN|G_NOCORPSE|G_UNIQ),
DEF(NAT_AC(5), DEX_AC(5), SPE_AC(9), NAT_DR_GLOV(9), SPE_DR(9)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 8),
OFFHND_ATTK(AT_TUCH, AD_DRLI, 4, 6), OFFHND_ATTK(AT_TUCH, AD_COLD, 6, 6),
OFFHND_ATTK(AT_CLAW, AD_PHYS, 3, 6), OFFHND_ATTK(AT_TUCH, AD_DRLI, 4, 6), OFFHND_ATTK(AT_TUCH, AD_COLD, 6, 6),
ATTK(AT_MAGC, AD_SPEL, 0, 9), ATTK(AT_NONE, AD_FIRE, 9, 9)),
SIZ(1200, 100, MS_MUMBLE, MZ_HUMAN),
MR_FIRE|MR_COLD|MR_SLEEP|MR_ELEC|MR_POISON, MR_FIRE|MR_COLD,
@ -6288,7 +6359,7 @@ is a red right hand
MON("apocalypse angel", S_DEMON,//19 /* Needs encyc entry */
LVL(15, 10, 99, 20), (G_HELL|G_NOCORPSE|G_NOGEN),
DEF(NAT_AC(6), SPE_AC(13), NAT_DR(6), SPE_DR_ALL(7, 3, 9, 3, 9)),
A(ATTK(AT_LNCK, AD_DRST, 1, 6), ATTK(AT_HITS, AD_APCS, 0, 0),
A(ATTK(AT_LNCK, AD_SVPN, 1, 6), ATTK(AT_HITS, AD_APCS, 0, 0),
ATTK(AT_NONE, AD_FIRE, 0, 9)),
SIZ(WT_HUMAN, 400, MS_APOC, MZ_HUMAN),
MR_FIRE|MR_COLD|MR_ELEC|MR_SLEEP|MR_POISON|MR_MAGIC, 0,
@ -6712,8 +6783,8 @@ is a red right hand
MON("Avatar of Lolth", S_DEMON,//37 /*Needs encyc entry*//*Needs tile*/
LVL(66, 15, 10, -18), (G_UNIQ|G_NOGEN),
DEF(NAT_AC(2), SPE_AC(8), SPE_DR(8)),
A(ATTK(AT_BITE, AD_SSEX, 1,1), ATTK(AT_WEAP, AD_PHYS, 2,10),
ATTK(AT_WEAP, AD_PHYS, 2,10), ATTK(AT_TUCH, AD_CURS, 1, 1),
A(ATTK(AT_BITE, AD_SSEX, 1, 1), ATTK(AT_WEAP, AD_PHYS, 4, 8),
ATTK(AT_WEAP, AD_PHYS, 4, 8), ATTK(AT_TUCH, AD_CURS, 1, 1),
ATTK(AT_MAGC, AD_CLRC, 0, 8)),
SIZ(WT_MEDIUM, 500, MS_HUMANOID, MZ_MEDIUM), 0, 0,
0 /*MM*/, MT_OMNIVORE|MT_STALK|MT_HOSTILE|MT_GREEDY|MT_COLLECT|MT_WAITFORU|MT_WANTSAMUL|MT_TRAITOR /*MT*/, MF_MARTIAL_S /*MF*/,
@ -7423,7 +7494,7 @@ is a red right hand
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 6)),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
0 /*MM*/, MT_OMNIVORE|MT_COLLECT /*MT*/, MF_MARTIAL_B|MF_LEVEL_30 /*MF*/,
0 /*MM*/, MT_OMNIVORE|MT_COLLECT /*MT*/, MF_MARTIAL_B|MF_LEVEL_30|MF_PHYS_SCALING /*MF*/,
MB_HUMANOID|MB_STRONG|MB_MALE /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE|MG_TRACKER /*MG*/,
MA_HUMAN /*MA*/, MV_NORMAL /*MV*/, HI_DOMESTIC),
MON("cavewoman", S_HUMAN,//12
@ -7431,7 +7502,7 @@ is a red right hand
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 6)),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
0 /*MM*/, MT_OMNIVORE|MT_COLLECT /*MT*/, MF_MARTIAL_B|MF_LEVEL_30 /*MF*/,
0 /*MM*/, MT_OMNIVORE|MT_COLLECT /*MT*/, MF_MARTIAL_B|MF_LEVEL_30|MF_PHYS_SCALING /*MF*/,
MB_HUMANOID|MB_STRONG|MB_FEMALE /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE|MG_TRACKER /*MG*/,
MA_HUMAN /*MA*/, MV_NORMAL /*MV*/, HI_DOMESTIC),
#ifdef CONVICT
@ -7447,7 +7518,7 @@ is a red right hand
MON("healer", S_HUMAN,//12
LVL(10, 12, 1, 0), G_NOGEN,
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MMGC, AD_CLRC, 0, 0)),
SIZ(WT_HUMAN, 400, MS_NURSE, MZ_HUMAN), MR_POISON, 0,
0 /*MM*/, MT_OMNIVORE|MT_COLLECT /*MT*/, MF_MARTIAL_B|MF_BAB_HALF|MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE /*MG*/,
@ -7473,7 +7544,7 @@ is a red right hand
LVL(10, 12, 2, 0), G_NOGEN,
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_XWEP, AD_PHYS, 1, 8),
ATTK(AT_KICK, AD_PHYS, 1, 8)),
ATTK(AT_KICK, AD_PHYS, 1, 8), ATTK_LEV(AT_MMGC, AD_PSON, 0, 0, 20)),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
0 /*MM*/, 0 /*MT*/, MF_MARTIAL_B|MF_BAB_HALF|MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_STRONG|MB_MALE /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE /*MG*/,
@ -7482,7 +7553,7 @@ is a red right hand
LVL(10, 12, 2, 0), G_NOGEN,
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_XWEP, AD_PHYS, 1, 8),
ATTK(AT_KICK, AD_PHYS, 1, 8)),
ATTK(AT_KICK, AD_PHYS, 1, 8), ATTK_LEV(AT_MMGC, AD_PSON, 0, 0, 20)),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
0 /*MM*/, 0 /*MT*/, MF_MARTIAL_B|MF_BAB_HALF|MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_STRONG|MB_FEMALE /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE /*MG*/,
@ -7567,11 +7638,29 @@ is a red right hand
MON("valkyrie", S_HUMAN,//13
LVL(10, 12, 1, -1), G_NOGEN,
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8), OFFHND_ATTK(AT_TUCH, AD_COLD, 1, 8)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_TUCH, AD_COLD, 1, 8)),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), MR_COLD, 0,
0 /*MM*/, MT_OMNIVORE|MT_COLLECT /*MT*/, MF_MARTIAL_B|MF_BAB_FULL|MF_LEVEL_30 /*MF*/,
0 /*MM*/, MT_OMNIVORE|MT_COLLECT /*MT*/, MF_MARTIAL_B|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_STRONG|MB_FEMALE /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE /*MG*/,
MA_HUMAN /*MA*/, MV_NORMAL /*MV*/, HI_DOMESTIC),
MON("awakened valkyrie", S_HUMAN,//13
LVL(14, 14, 1, -1), G_NOGEN,
DEF(SPE_AC(3)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 8), ATTK(AT_XWEP, AD_PHYS, 1, 6),
ATTK(AT_TUCH, AD_COLD, 4, 8)),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), MR_COLD|MR_MAGIC, 0,
0 /*MM*/, MT_OMNIVORE|MT_COLLECT /*MT*/, MF_MARTIAL_S|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_STRONG|MB_FEMALE /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE /*MG*/,
MA_HUMAN|MA_MINION /*MA*/, MV_NORMAL|MV_SEE_INVIS /*MV*/, HI_DOMESTIC),
MON("transcendent valkyrie", S_HUMAN,//13
LVL(30, 18, 1, -1), G_NOGEN,
DEF(SPE_AC(10), SPE_DR(3)),
A(ATTK(AT_WEAP, AD_PHYS, 10, 8), ATTK(AT_XWEP, AD_PHYS, 2, 6),
ATTK(AT_TUCH, AD_COLD, 10, 8), ATTK(AT_TUCH, AD_DRLI, 5, 6)),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), MR_COLD|MR_MAGIC, 0,
0 /*MM*/, MT_OMNIVORE|MT_COLLECT /*MT*/, MF_MARTIAL_E|MF_BAB_FULL|MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_STRONG|MB_FEMALE /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE /*MG*/,
MA_MINION /*MA*/, MV_EXTRAMISSION|MV_DETECTION|MV_OMNI|MV_SEE_INVIS /*MV*/, HI_DOMESTIC),
MON("incantifier", S_HUMAN,//27 /*Needs tile?*/
LVL(20, 12, 0, 0), G_NOGEN,
DEF(NAT_AC(0)),
@ -7686,6 +7775,15 @@ is a red right hand
0 /*MM*/, MT_CLOSE|MT_OMNIVORE|MT_PEACEFUL|MT_COLLECT|MT_MAGIC /*MT*/, MF_MARTIAL_B|MF_BAB_HALF /*MF*/,
MB_HUMANOID|MB_STRONG|MB_MALE /*MB*/, MG_NOWISH|MG_NOTAME|MG_NOPOLY|MG_PNAME|MG_INFRAVISIBLE /*MG*/,
MA_HUMAN /*MA*/, MV_NORMAL|MV_SEE_INVIS /*MV*/, HI_LORD),
MON("Shuushar the Enlightened", S_HUMANOID, /*Needs encyc entry*/
LVL(30, 12, 125, 0), (G_NOGEN|G_UNIQ), //AC -29
DEF(SPE_AC(20), SPE_DR(8)),
A(ATTK(AT_MAGC, AD_CLRC, 0, 4)),
SIZ(WT_SMALL, CN_SMALL, MS_LEADER, MZ_SMALL),
MR_SLEEP|MR_POISON|MR_FIRE|MR_COLD|MR_ELEC|MR_ACID|MR_SICK|MR_DISINT|MR_STONE|MR_MAGIC|MR_DRAIN, 0,
MM_AMPHIBIOUS|MM_SWIM /*MM*/, MT_NOTAKE|MT_HERBIVORE|MT_PEACEFUL /*MT*/, MF_MARTIAL_E /*MF*/,
MB_HUMANOID|MB_MALE /*MB*/, MG_NOWISH|MG_NOTAME|MG_NOPOLY|MG_PNAME|MG_TRACKER|MG_PRINCE|MG_NOSPELLCOOLDOWN /*MG*/,
MA_AQUATIC /*MA*/, MV_DARKSIGHT|MV_DETECTION|MV_OMNI|MV_SEE_INVIS /*MV*/, HI_LORD),
MON("King Arthur", S_HUMAN,//23
LVL(20, 12, 40, 20), (G_NOGEN|G_UNIQ),
DEF(DEX_AC(3), SPE_AC(7), SPE_DR(3)),
@ -8166,6 +8264,32 @@ is a red right hand
MM_WEBRIP|MM_DOORBUST /*MM*/, MT_WANTSARTI|MT_WAITFORU|MT_OMNIVORE|MT_ROCKTHROW|MT_STALK|MT_HOSTILE|MT_JEWELS|MT_COLLECT /*MT*/, MF_MARTIAL_B /*MF*/,
MB_HUMANOID|MB_STRONG|MB_MALE /*MB*/, MG_NOTAME|MG_NOPOLY|MG_NASTY|MG_INFRAVISIBLE|MG_HATESIRON /*MG*/,
MA_GIANT|MA_MINION /*MA*/, MV_NORMAL|MV_INFRAVISION /*MV*/, CLR_GRAY),
MON("Blibdoolpoolp, graven-into-flesh", S_HUMAN,//
LVL(27, 8, 95, -20), (G_NOGEN|G_NOCORPSE|G_UNIQ), /*Spawn with blood bloaters*/
DEF(SPE_AC(10), DEX_AC(4), NAT_AC(4), NAT_DR_HEAD(10), NAT_DR_GLOV(10)),
A(POLYWEP_ATTK(AT_CLAW, AD_SQUE, 4, 8), OFFHND_ATTK(AT_CLAW, AD_SQUE, 4, 8),
ATTK(AT_HUGS, AD_PHYS, 2, 6),
/*magic-item-stealing tentacles (only work in a grapple)*/
ATTK(AT_HITS, AD_TSMI, 0, 0),
ATTK(AT_MAGC, AD_CLRC, 2, 8), /*Water, hot water, slime (blind and grease), blood rain*/
ATTK(AT_NONE, AD_MROT, 0, 0)
),
SIZ(WT_HUMAN, 450, MS_NEMESIS, MZ_HUMAN), MR_ALL, 0,
MM_WEBRIP|MM_SWIM|MM_AMPHIBIOUS /*MM*/, MT_WANTSARTI|MT_WAITFORU|MT_OMNIVORE|MT_STALK|MT_HOSTILE|MT_MAGIC|MT_COLLECT /*MT*/, MF_MARTIAL_E /*MF*/,
MB_HUMANOID|MB_STRONG|MB_FEMALE /*MB*/, MG_SANLOSS|MG_INSIGHT|MG_NOTAME|MG_NOPOLY|MG_NASTY|MG_INFRAVISIBLE|MG_HATESIRON|MG_PRINCE /*MG*/,
MA_DEMIHUMAN|MA_AQUATIC|MA_DROW|MA_ELF|MA_MINION /*MA*/, MV_NORMAL|MV_SEE_INVIS|MV_DETECTION /*MV*/, HI_LORD),
MON("Blibdoolpoolp's mindgraven champion", S_CENTAUR,//
LVL(6, 20, 50, -20), (G_NOGEN|G_UNIQ),
DEF(NAT_AC(4), NAT_DR_LEGS(4), NAT_DR_FEET(3)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_XWEP, AD_PHYS, 1, 4),
ATTK(AT_CLAW, AD_PHYS, 4, 8), ATTK(AT_CLAW, AD_PHYS, 4, 8),
ATTK(AT_HUGS, AD_PHYS, 2, 6),
ATTK(AT_TENT, AD_PLYS, 1, 6),
ATTK(AT_MAGC, AD_CLRC, 2, 8)),
SIZ(WT_LARGE, 450, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, 0,
MM_SWIM /*MM*/, MT_OMNIVORE|MT_STALK|MT_HOSTILE|MT_MAGIC|MT_COLLECT /*MT*/, MF_MARTIAL_E|MF_BAB_FULL|MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_ANIMAL|MB_HAS_FEET|MB_STRONG|MB_FEMALE /*MB*/, MG_NOPOLY|MG_NASTY|MG_INFRAVISIBLE|MG_HATESIRON|MG_INSIGHT|MG_SANLOSS /*MG*/,
MA_AQUATIC|MA_DROW|MA_ELF /*MA*/, MV_DARKSIGHT|MV_SEE_INVIS /*MV*/, HI_LORD),
MON("Ixoth", S_DRAGON,//24 /*Needs encyc entry*/
LVL(15, 12, 20, -14), (G_NOGEN|G_UNIQ),
DEF(NAT_AC(14), NAT_DR(5)),
@ -8208,8 +8332,8 @@ is a red right hand
MON("Rebel Ringleader", S_HUMAN,//20 /*Needs encyc entry*/
LVL(14, 16, 30, 10), (G_NOGEN|G_UNIQ),
DEF(SPE_AC(3)),
A(ATTK(AT_WEAP, AD_PHYS, 0, 8), ATTK(AT_WEAP, AD_PHYS, 0, 6),
ATTK(AT_CLAW, AD_SQUE, 1, 4)),
A(ATTK(AT_WEAP, AD_PHYS, 0, 8), ATTK_LEV(AT_WEAP, AD_PHYS, 0, 6, 20),
OFFHND_ATTK(AT_CLAW, AD_SQUE, 1, 4)),
SIZ(WT_HUMAN, 400, MS_NEMESIS, MZ_HUMAN), MR_STONE, 0,
0 /*MM*/, MT_WANTSARTI|MT_WAITFORU|MT_OMNIVORE|MT_COLLECT|MT_MAGIC|MT_HOSTILE /*MT*/, MF_MARTIAL_E|MF_BAB_FULL|MF_LEVEL_30|MF_PHYS_SCALING /*MF*/,
MB_HUMANOID|MB_STRONG|MB_FEMALE /*MB*/, MG_NOTAME|MG_NOPOLY|MG_INFRAVISIBLE /*MG*/,
@ -9327,7 +9451,7 @@ is a red right hand
MON("drow matron-mother", S_HUMAN,//18 /*Needs encyc entry*/
LVL(16, 12, 60, -9), G_NOGEN,
DEF(SPE_AC(4)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_MMGC, AD_CLRC, 0, 0)),
A(ATTK(AT_WEAP, AD_PHYS, 4, 4), ATTK(AT_MMGC, AD_CLRC, 0, 0)),
SIZ(WT_ELF, 350, MS_CUSS, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
0 /*MM*/, MT_OMNIVORE|MT_CLOSE|MT_PEACEFUL|MT_COLLECT|MT_TRAITOR /*MT*/, MF_MARTIAL_B|MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_FEMALE /*MB*/, MG_NOWISH|MG_NOPOLY|MG_PRINCE|MG_INFRAVISIBLE|MG_HATESIRON|MG_TRACKER /*MG*/,
@ -9378,15 +9502,15 @@ is a red right hand
MON("High-elf", S_HUMAN,//9 /*Needs encyc entry*//*Needs tile*/
LVL(7, 12, 10, -7), G_NOGEN,
DEF(DEX_AC(2), SPE_AC(2)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_MAGC, AD_CLRC, 0, 0)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK_LEV(AT_WEAP, AD_PHYS, 2, 4, 30), ATTK(AT_MAGC, AD_CLRC, 0, 0)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
0 /*MM*/, MT_OMNIVORE|MT_PEACEFUL|MT_COLLECT /*MT*/, MF_MARTIAL_E|MF_BAB_FULL|MF_LEVEL_30 /*MF*/,
MB_HUMANOID /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE|MG_HATESIRON|MG_TRACKER /*MG*/,
MA_ELF /*MA*/, MV_LOWLIGHT3|MV_SEE_INVIS /*MV*/, HI_DOMESTIC),
MON("stjarna-alfr", S_HUMAN,//9 /*Needs encyc entry*//*Needs tile*/
LVL(7, 12, 10, -7), G_NOGEN,
LVL(7, 12, 10, 7), G_NOGEN,
DEF(DEX_AC(2)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_MAGC, AD_CLRC, 0, 0)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK_LEV(AT_WEAP, AD_PHYS, 2, 4, 30), ATTK(AT_MAGC, AD_CLRC, 0, 0)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
0 /*MM*/, MT_OMNIVORE|MT_PEACEFUL|MT_COLLECT /*MT*/, MF_MARTIAL_E|MF_LEVEL_30 /*MF*/,
MB_HUMANOID /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE|MG_HATESIRON|MG_TRACKER /*MG*/,
@ -9399,6 +9523,192 @@ is a red right hand
0 /*MM*/, MT_OMNIVORE|MT_PEACEFUL|MT_COLLECT /*MT*/, MF_BAB_HALF /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE /*MG*/,
MA_HUMAN /*MA*/, MV_NORMAL /*MV*/, HI_DOMESTIC),
MON("Sister T'eirastra", S_HUMAN, // /*Needs encyc entry*/
LVL(25, 16, 50, 0), (G_NOGEN|G_UNIQ),
DEF(DEX_AC(4), SPE_AC(4)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_MAGC, AD_CLRC, 0, 8)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_POISON|MR_SICK|MR_SLEEP|MR_STONE|MR_DISINT, MR_SLEEP,
0 /*MM*/, MT_CLOSE|MT_OMNIVORE|MT_NOTAKE|MT_PEACEFUL /*MT*/, MF_BAB_HALF /*MF*/,
MB_HUMANOID|MB_FEMALE|MB_STRONG /*MB*/, MG_NOWISH|MG_NOTAME|MG_NOPOLY|MG_PNAME|MG_INFRAVISIBLE|MG_HATESIRON|MG_LORD /*MG*/,
MA_ELF|MA_DROW /*MA*/, 0 /*MV*/, HI_LORD),
MON("Pen'a mendicant", S_HUMAN,//
LVL(12, 12, 60, 0), G_NOGEN,
DEF(SPE_AC(2)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_CLRC, 0, 0)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_POISON|MR_SICK|MR_SLEEP, MR_SLEEP,
0 /*MM*/, MT_OMNIVORE|MT_PEACEFUL|MT_NOTAKE /*MT*/, MF_BAB_HALF|MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE|MG_HATESIRON /*MG*/,
MA_ELF|MA_DROW /*MA*/, MV_DARKSIGHT /*MV*/, HI_DOMESTIC),
MON("mendicant sprow", S_CENTAUR,// /*Need to look at tile*/
LVL(8, 15, 10, 0), (G_GENO|G_NOGEN),
DEF(NAT_AC(8)),
A(ATTK(AT_KICK, AD_WEBS, 1, 1), ATTK(AT_MAGC, AD_CLRC, 0, 0)),
SIZ(WT_MEDIUM, 500, MS_HUMANOID, MZ_MEDIUM), MR_POISON|MR_SICK|MR_SLEEP, MR_SLEEP,
0 /*MM*/, MT_OMNIVORE|MT_PEACEFUL|MT_NOTAKE /*MT*/, MF_BAB_HALF|MF_LEVEL_30 /*MF*/,
MB_HUMANOID|MB_FEMALE|MB_NOHANDS|MB_NOFEET /*MB*/, MG_INFRAVISIBLE|MG_HATESIRON /*MG*/,
MA_ARACHNID|MA_DEMIHUMAN|MA_DROW|MA_ELF /*MA*/, MV_DARKSIGHT /*MV*/, CLR_BLACK),
MON("mendicant drider", S_CENTAUR,//
LVL(16, 15, 10, 0), (G_GENO|G_NOGEN),
DEF(NAT_AC(8)),
A(ATTK(AT_WEAP, AD_PHYS, 1,10), ATTK(AT_XWEP, AD_PHYS, 1,10),
ATTK(AT_KICK, AD_WEBS, 1, 1), ATTK(AT_MAGC, AD_CLRC, 0, 0)),
SIZ(WT_LARGE, 500, MS_HUMANOID, MZ_MEDIUM), MR_POISON|MR_SICK|MR_SLEEP, MR_SLEEP,
0 /*MM*/, MT_OMNIVORE|MT_PEACEFUL|MT_NOTAKE /*MT*/, MF_BAB_HALF|MF_LEVEL_30 /*MF*/,
MB_STRONG|MB_HUMANOID|MB_ANIMAL|MB_FEMALE /*MB*/, MG_INFRAVISIBLE|MG_HATESIRON|MG_TRACKER /*MG*/,
MA_ARACHNID|MA_DEMIHUMAN|MA_DROW|MA_ELF /*MA*/, MV_DARKSIGHT /*MV*/, CLR_WHITE),
MON("Sir Aljanor", S_HUMAN,//
LVL(14, 10, 40, 20), (G_NOGEN|G_UNIQ),
DEF(DEX_AC(1)),
A(ATTK(AT_WEAP, AD_HOLY, 1, 6), ATTK(AT_WEAP, AD_HOLY, 1, 6)),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
0 /*MM*/, MT_CLOSE|MT_OMNIVORE|MT_PEACEFUL|MT_COLLECT|MT_MAGIC /*MT*/, MF_MARTIAL_E|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_STRONG|MB_MALE /*MB*/, MG_NOWISH|MG_NOTAME|MG_NOPOLY|MG_PNAME|MG_INFRAVISIBLE|MG_PRINCE /*MG*/,
MA_HUMAN /*MA*/, MV_NORMAL /*MV*/, HI_LORD),
MON("Alliance vanguard", S_HUMAN,//
LVL(7, 12, 10, 6), G_NOGEN,
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6)),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
0 /*MM*/, MT_OMNIVORE|MT_PEACEFUL|MT_COLLECT /*MT*/, MF_MARTIAL_E|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_NOWISH|MG_NOPOLY|MG_INFRAVISIBLE /*MG*/,
MA_HUMAN /*MA*/, MV_NORMAL /*MV*/, HI_DOMESTIC),
MON("Mad Grazi", S_HUMANOID,//
LVL(11, 12, 90, -10), (G_GENO|G_NOGEN),
DEF(SPE_AC(5)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 4), ATTK(AT_TENT, AD_DRIN, 1, 3),
ATTK(AT_MAGC, AD_SPEL, 0, 0)),
SIZ(WT_HUMAN, CN_HUMAN, MS_HISS, MZ_HUMAN), MR_POISON, 0,
MM_FLY /*MM*/, MT_HOSTILE|MT_GREEDY|MT_JEWELS|MT_COLLECT|MT_TRAITOR|MT_OMNIVORE /*MT*/, MF_MARTIAL_B /*MF*/,
MB_HUMANOID /*MB*/, MG_INFRAVISIBLE|MG_NASTY|MG_SANLOSS|MG_INSIGHT /*MG*/,
MA_DEMIHUMAN|MA_PRIMORDIAL /*MA*/, MV_TELEPATHIC|MV_DARKSIGHT|MV_RLYEHIAN|MV_SEE_INVIS /*MV*/, CLR_MAGENTA),
MON("kuo toa", S_HUMANOID,//
LVL(1, 12, 90, -10), (G_GENO|G_SGROUP|G_NOGEN),
DEF(SPE_AC(5)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 4), OFFHND_ATTK(AT_TUCH, AD_DREN, 4, 4),
ATTK(AT_BITE, AD_PHYS, 1, 6),
ATTK(AT_NONE, AD_MROT, 0, 0)),
SIZ(WT_SMALL, CN_SMALL, MS_RIBBIT, MZ_SMALL), MR_POISON, 0,
MM_SWIM|MM_AMORPHOUS|MM_AMPHIBIOUS /*MM*/, MT_HOSTILE|MT_TRAITOR|MT_OMNIVORE /*MT*/, MF_MARTIAL_B /*MF*/,
MB_HUMANOID /*MB*/, MG_SANLOSS|MG_INSIGHT /*MG*/,
MA_DEMIHUMAN|MA_AQUATIC /*MA*/, MV_DARKSIGHT|MV_SEE_INVIS|MV_SCENT /*MV*/, CLR_GREEN),
MON("kuo toa whip", S_HUMANOID,//
LVL(3, 12, 90, -10), (G_GENO|G_NOGEN),
DEF(SPE_AC(5)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 4), OFFHND_ATTK(AT_TUCH, AD_DREN, 4, 4),
ATTK(AT_BITE, AD_PHYS, 1, 6),
ATTK(AT_MAGC, AD_CLRC, 0, 0), ATTK(AT_NONE, AD_MROT, 0, 0)),
SIZ(WT_SMALL, CN_SMALL, MS_RIBBIT, MZ_SMALL), MR_POISON, 0,
MM_SWIM|MM_AMORPHOUS|MM_AMPHIBIOUS /*MM*/, MT_HOSTILE|MT_TRAITOR|MT_OMNIVORE /*MT*/, MF_MARTIAL_B /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_SANLOSS|MG_INSIGHT /*MG*/,
MA_DEMIHUMAN|MA_AQUATIC /*MA*/, MV_DARKSIGHT|MV_SEE_INVIS|MV_SCENT /*MV*/, CLR_BRIGHT_GREEN),
MON("duergar", S_HUMANOID,//
LVL(2, 6, 75, 4), (G_GENO|G_NOGEN|G_SGROUP),
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8)),
SIZ(WT_DWARF, CN_DWARF, MS_HUMANOID, MZ_HUMAN), 0, 0,
MM_TUNNEL|MM_NEEDPICK /*MM*/, MT_GREEDY|MT_JEWELS|MT_COLLECT|MT_OMNIVORE /*MT*/, MF_MARTIAL_B|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_INFRAVISIBLE /*MG*/,
MA_DWARF /*MA*/, MV_INFRAVISION|MV_DARKSIGHT /*MV*/, CLR_RED),
MON("giant duergar", S_GIANT,//
LVL(2, 6, 75, 4), (G_GENO|G_NOGEN),
DEF(NAT_AC(10)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 8)),
SIZ(WT_LARGE, CN_LARGE, MS_HUMANOID, MZ_HUGE), 0, 0,
MM_TUNNEL|MM_NEEDPICK /*MM*/, MT_GREEDY|MT_JEWELS|MT_COLLECT|MT_OMNIVORE /*MT*/, MF_MARTIAL_B|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_INFRAVISIBLE /*MG*/,
MA_DWARF /*MA*/, MV_INFRAVISION|MV_DARKSIGHT /*MV*/, CLR_RED),
MON("duergar stoneguard", S_HUMANOID,//
LVL(4, 6, 75, 5), (G_GENO|G_NOGEN|G_LGROUP),
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_XWEP, AD_PHYS, 2, 4)),
SIZ(WT_DWARF, CN_DWARF, MS_HUMANOID, MZ_HUMAN), 0, 0,
MM_TUNNEL|MM_NEEDPICK /*MM*/, MT_GREEDY|MT_JEWELS|MT_COLLECT|MT_OMNIVORE /*MT*/, MF_MARTIAL_S|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_INFRAVISIBLE /*MG*/,
MA_DWARF /*MA*/, MV_INFRAVISION|MV_DARKSIGHT /*MV*/, CLR_BROWN),
MON("giant stoneguard", S_GIANT,//
LVL(4, 6, 75, 5), (G_GENO|G_NOGEN),
DEF(NAT_AC(10)),
A(ATTK(AT_WEAP, AD_PHYS, 4, 4), ATTK(AT_XWEP, AD_PHYS, 4, 4)),
SIZ(WT_LARGE, CN_LARGE, MS_HUMANOID, MZ_HUGE), 0, 0,
MM_TUNNEL|MM_NEEDPICK /*MM*/, MT_GREEDY|MT_JEWELS|MT_COLLECT|MT_OMNIVORE /*MT*/, MF_MARTIAL_S|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_INFRAVISIBLE /*MG*/,
MA_DWARF /*MA*/, MV_INFRAVISION|MV_DARKSIGHT /*MV*/, CLR_BROWN),
MON("duergar debilitator", S_HUMANOID,//
LVL(4, 6, 75, 5), (G_GENO|G_NOGEN),
DEF(NAT_AC(0)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 4), ATTK(AT_MAGC, AD_CLRC, 0, 4)),
SIZ(WT_DWARF, CN_DWARF, MS_HUMANOID, MZ_HUMAN), 0, 0,
MM_TUNNEL|MM_NEEDPICK /*MM*/, MT_GREEDY|MT_JEWELS|MT_COLLECT|MT_OMNIVORE /*MT*/, MF_MARTIAL_B|MF_BAB_HALF /*MF*/,
MB_HUMANOID /*MB*/, MG_INFRAVISIBLE /*MG*/,
MA_DWARF /*MA*/, MV_INFRAVISION|MV_DARKSIGHT /*MV*/, CLR_ORANGE),
MON("duergar annihilator", S_GIANT,//
LVL(4, 6, 75, 5), (G_GENO|G_NOGEN),
DEF(NAT_AC(10)),
A(ATTK(AT_WEAP, AD_PHYS, 4, 4), ATTK(AT_MAGC, AD_CLRC, 0, 6)),
SIZ(WT_LARGE, CN_LARGE, MS_HUMANOID, MZ_HUGE), 0, 0,
MM_TUNNEL|MM_NEEDPICK /*MM*/, MT_GREEDY|MT_JEWELS|MT_COLLECT|MT_OMNIVORE /*MT*/, MF_MARTIAL_E|MF_BAB_FULL /*MF*/,
MB_HUMANOID|MB_STRONG /*MB*/, MG_INFRAVISIBLE /*MG*/,
MA_DWARF /*MA*/, MV_INFRAVISION|MV_DARKSIGHT /*MV*/, CLR_ORANGE),
MON("Y-cultist", S_HUMAN,//3
LVL(3, 14, 66, -13), G_NOGEN, /* for corpses */
DEF(DEX_AC(2), NAT_DR_HEAD(-2), NAT_DR_GLOV(-2)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), 0, 0,
0 /*MM*/, MT_COLLECT|MT_OMNIVORE /*MT*/, MF_MARTIAL_B /*MF*/,
MB_STRONG|MB_HUMANOID /*MB*/, MG_NOPOLY|MG_NOWISH|MG_INFRAVISIBLE|MG_HATESIRON|MG_TRACKER /*MG*/,
MA_ELF|MA_DROW /*MA*/, MV_DARKSIGHT /*MV*/, CLR_BLACK),
MON("Y-cultist fighter", S_HUMAN,//10 /*Needs encyc entry*/
LVL(6, 14, 66, -19), (G_NOGEN),
DEF(DEX_AC(2), NAT_DR_HEAD(-2), NAT_DR_GLOV(-2)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_XWEP, AD_PHYS, 1, 4),
ATTK(AT_MMGC, AD_SPEL, 0, 4)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
0 /*MM*/, MT_TRAITOR|MT_COLLECT|MT_HOSTILE|MT_OMNIVORE /*MT*/, MF_MARTIAL_S|MF_BAB_FULL /*MF*/,
MB_STRONG|MB_HUMANOID /*MB*/, MG_NOPOLY|MG_INFRAVISIBLE|MG_NASTY|MG_HATESIRON|MG_TRACKER /*MG*/,
MA_ELF|MA_DROW /*MA*/, MV_DARKSIGHT /*MV*/, CLR_BLACK),
MON("Y-cultist wizard", S_HUMAN,//12 /*Needs encyc entry*//*Needs tile*/
LVL(9, 14, 66, -16), (G_NOGEN),
DEF(DEX_AC(2), SPE_AC(4), NAT_DR_HEAD(-2), NAT_DR_GLOV(-2)),
A(ATTK(AT_WEAP, AD_PHYS, 1, 4), ATTK(AT_MMGC, AD_SPEL, 0, 6)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
0 /*MM*/, MT_COLLECT|MT_HOSTILE|MT_OMNIVORE|MT_TRAITOR /*MT*/, MF_BAB_HALF /*MF*/,
MB_HUMANOID|MB_STRONG|MB_MALE /*MB*/, MG_NOPOLY|MG_INFRAVISIBLE|MG_HATESIRON|MG_TRACKER /*MG*/,
MA_ELF|MA_DROW /*MA*/, MV_DARKSIGHT /*MV*/, CLR_GRAY),
MON("Y-cultist matron", S_HUMAN,//16 /*Needs encyc entry*/
LVL(12, 12, 66, -19), (G_NOGEN),
DEF(DEX_AC(2), SPE_AC(2), NAT_DR_HEAD(-2), NAT_DR_GLOV(-2)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_MMGC, AD_SPEL, 0, 0)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
MM_AMPHIBIOUS /*MM*/, MT_OMNIVORE|MT_COLLECT|MT_HOSTILE|MT_TRAITOR /*MT*/, MF_MARTIAL_S|MF_LEVEL_30 /*MF*/,
MB_NOGLOVES|MB_HUMANOID|MB_STRONG|MB_FEMALE /*MB*/, MG_NOPOLY|MG_INFRAVISIBLE|MG_PRINCE|MG_NASTY|MG_HATESIRON|MG_TRACKER /*MG*/,
MA_ELF|MA_DROW /*MA*/, MV_DARKSIGHT /*MV*/, CLR_BLACK),
MON("Y-cultist patron", S_HUMAN,//16 /*Needs encyc entry*/
LVL(14, 14, 66, -16), (G_NOGEN),
DEF(DEX_AC(4), SPE_AC(2), NAT_DR_HEAD(-2), NAT_DR_GLOV(-2)),
A(ATTK(AT_WEAP, AD_PHYS, 3, 4), ATTK(AT_XWEP, AD_PHYS, 3, 4),
ATTK(AT_MMGC, AD_SPEL, 0, 4)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
MM_AMPHIBIOUS /*MM*/, MT_OMNIVORE|MT_COLLECT|MT_HOSTILE|MT_TRAITOR /*MT*/, MF_MARTIAL_E|MF_BAB_FULL|MF_LEVEL_30 /*MF*/,
MB_NOGLOVES|MB_STRONG|MB_HUMANOID|MB_MALE /*MB*/, MG_NOPOLY|MG_INFRAVISIBLE|MG_HATESIRON|MG_TRACKER /*MG*/,
MA_ELF|MA_DROW /*MA*/, MV_DARKSIGHT /*MV*/, CLR_GRAY),
MON("anulo", S_HUMAN,//10 /*Needs encyc entry*/
LVL(6, 16, 60, -3), (G_GENO|G_SGROUP|G_NOGEN),
DEF(DEX_AC(3)),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_XWEP, AD_PHYS, 1, 4),
ATTK(AT_MMGC, AD_SPEL, 0, 6)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
MM_FLY /*MM*/, MT_TRAITOR|MT_COLLECT|MT_HOSTILE|MT_OMNIVORE /*MT*/, MF_LEVEL_30|MF_MARTIAL_S|MF_BAB_FULL /*MF*/,
MB_STRONG|MB_HUMANOID|MB_WINGS /*MB*/, MG_NOPOLY|MG_INFRAVISIBLE|MG_NASTY|MG_HATESIRON|MG_TRACKER /*MG*/,
MA_ELF|MA_DROW /*MA*/, MV_DARKSIGHT /*MV*/, CLR_BLACK),
MON("anulo dancer", S_HUMAN,//10 /*Needs encyc entry*/
LVL(12, 16, 60, 3), (G_GENO|G_SGROUP|G_NOGEN),
DEF(DEX_AC(6),SPE_AC(2)),
A(ATTK(AT_WEAP, AD_PHYS, 3, 4), ATTK(AT_XWEP, AD_PHYS, 3, 4),
ATTK(AT_MMGC, AD_SPEL, 0, 6), ATTK(AT_NONE, AD_MAGM, 4, 4)),
SIZ(WT_ELF, 350, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
MM_FLY /*MM*/, MT_TRAITOR|MT_COLLECT|MT_HOSTILE|MT_OMNIVORE /*MT*/, MF_LEVEL_30|MF_MARTIAL_S|MF_BAB_FULL /*MF*/,
MB_STRONG|MB_HUMANOID|MB_WINGS /*MB*/, MG_NOPOLY|MG_INFRAVISIBLE|MG_NASTY|MG_HATESIRON|MG_TRACKER /*MG*/,
MA_ELF|MA_DROW /*MA*/, MV_DARKSIGHT /*MV*/, CLR_BLACK),
MON("page", S_HUMAN,//8
LVL(6, 12, 10, 6), G_NOGEN,
DEF(NAT_AC(0)),

View file

@ -389,8 +389,10 @@ int *weapon, *secweapon, *rweapon, *rwammo, *armor, *shirt, *cloak, *helm, *boot
break;
#endif
case PM_VALKYRIE:
case PM_AWAKENED_VALKYRIE:
case PM_TRANSCENDENT_VALKYRIE:
if (rn2(2)) *weapon = WAR_HAMMER;
else *weapon = SPEAR;
else *weapon = ptr->mtyp == PM_VALKYRIE ? SPEAR : ATGEIR;
*rweapon = BOW;
*rwammo = ARROW;
if(special){

View file

@ -82,9 +82,10 @@ extern int monstr[];
/* Find a target for a ranged attack. */
/* needs to set tbx, tby */
struct monst *
mfind_target(magr, force_linedup)
mfind_target(magr, force_linedup, use_find_offensive)
struct monst *magr;
int force_linedup; /* if TRUE, we have some offensive item ready that will work if we are lined up */
boolean force_linedup; /* if TRUE, we have some offensive item ready that will work if we are lined up */
boolean use_find_offensive; /* if TRUE, we have some offensive item ready that will work if we are lined up */
{
struct monst * mdef = (struct monst *)0;
struct monst * best_target = (struct monst *)0;
@ -121,6 +122,7 @@ int force_linedup; /* if TRUE, we have some offensive item ready that will work
(mon_attacktype(magr, AT_MAGC) && !magr->mcan) ||
(mon_attacktype(magr, AT_MMGC) && !magr->mcan) ||
(mon_attacktype(magr, AT_GAZE) && !magr->mcan) ||
(mon_turn_undead(magr) && !magr->mspec_used && !magr->mcan && (!Inhell || mon_healing_turn(magr))) ||
(mon_attacktype(magr, AT_SPIT)) ||
(mon_attacktype(magr, AT_ARRW)) ||
(mon_attacktype(magr, AT_TNKR)) ||
@ -130,7 +132,7 @@ int force_linedup; /* if TRUE, we have some offensive item ready that will work
(mon_attacktype(magr, AT_5SQR)) ||
(mon_attacktype(magr, AT_5SBT)) ||
(is_commander(magr->data)) ||
(find_offensive(magr))
(use_find_offensive && find_offensive(magr))
))
return (struct monst *)0;
@ -226,7 +228,7 @@ int force_linedup; /* if TRUE, we have some offensive item ready that will work
(mon_attacktype(magr, AT_ARRW)) ||
(mon_attacktype(magr, AT_WEAP) && mrwep && !is_pole(mrwep)) ||
(mon_attacktype(magr, AT_DEVA) && mrwep && !is_pole(mrwep)) ||
(find_offensive(magr))
(use_find_offensive && find_offensive(magr))
))
||
/* attacks that are on a line that are ALWAYS SAFE */
@ -257,8 +259,10 @@ int force_linedup; /* if TRUE, we have some offensive item ready that will work
(distmin(magr->mx, magr->my, tarx, tary) <= 8 && (
(is_commander(magr->data) && !rn2(4)) || /* !rn2(4) -> reduce command frequency */
(mon_attacktype(magr, AT_GAZE) && !magr->mcan) ||
(mon_turn_undead(magr) && !magr->mspec_used && !magr->mcan) ||
(mon_get_attacktype(magr, AT_MAGC, &attkbuff) && !magr->mcan && real_spell_adtyp(attkbuff.adtyp)) ||
(mon_get_attacktype(magr, AT_MMGC, &attkbuff) && !magr->mcan && real_spell_adtyp(attkbuff.adtyp))
(mon_get_attacktype(magr, AT_MMGC, &attkbuff) && !magr->mcan && real_spell_adtyp(attkbuff.adtyp)) ||
(mon_turn_undead(magr) && !magr->mspec_used && !magr->mcan && (!Inhell || mon_healing_turn(magr)))
))
)){
/* mdef can be targeted by one of our attacks */

View file

@ -238,6 +238,7 @@ struct obj *otmp;
#define MUSE_POT_FULL_HEALING 18
#define MUSE_LIZARD_CORPSE 19
#define MUSE_LIFE_FLASK 20
#define MUSE_HEALING_SURGE 21
/*
#define MUSE_INNATE_TPT 9999
* We cannot use this. Since monsters get unlimited teleportation, if they
@ -254,6 +255,7 @@ find_defensive(mtmp)
struct monst *mtmp;
{
register struct obj *obj = 0;
struct monst *mtarg;
struct trap *t;
int x=mtmp->mx, y=mtmp->my;
boolean stuck = (mtmp == u.ustuck);
@ -325,6 +327,21 @@ struct monst *mtmp;
}
fraction = u.ulevel < 10 ? 5 : u.ulevel < 14 ? 4 : 3;
if(mon_healing_turn(mtmp) && !mtmp->mspec_used && !mtmp->mcan){
int range = BOLT_LIM + (mtmp->m_lev / 5);
range *= range;
for(mtarg = fmon; mtarg; mtarg = mtarg->nmon){
if(DEADMONSTER(mtarg)) continue;
if(is_undead(mtarg->data) || is_demon(mtarg->data)) continue;
if(!mtmp->mtame != !mtarg->mtame || mtmp->mpeaceful != mtarg->mpeaceful || mm_grudge(mtmp, mtarg)) continue;
if (!clear_path(mtmp->mx,mtmp->my, mtarg->mx,mtarg->my) ||
dist2(mtmp->mx,mtmp->my, mtarg->mx,mtarg->my) > range
) continue;
if(mtarg->mhp*fraction >= mtarg->mhpmax) continue;
m.has_defense = MUSE_HEALING_SURGE;
return TRUE;
}
}
if(mtmp->mhp >= mtmp->mhpmax
|| (mtmp->mhp >= 10 && mtmp->mhp*fraction >= mtmp->mhpmax)
){
@ -964,6 +981,10 @@ mon_tele:
/* not actually called for its unstoning effect */
mon_consume_unstone(mtmp, otmp, FALSE, FALSE);
return 2;
case MUSE_HEALING_SURGE:
mon_doturn(mtmp);
mtmp->mspec_used = 3;
return 2;
case 0: return 0; /* i.e. an exploded wand */
default: impossible("%s wanted to perform action %d?", Monnam(mtmp),
m.has_defense);
@ -1056,6 +1077,7 @@ struct monst *mtmp;
#define MUSE_WAN_CANCELLATION 22 /* Lethe */
#define MUSE_CRYSTAL_SKULL 23
#define MUSE_MON_TURN_UNDEAD 24
/* Find a mask.
*/
@ -1092,7 +1114,7 @@ struct monst *mtmp;
boolean reflection_skip = FALSE;
struct obj *helmet = which_armor(mtmp, W_ARMH);
struct monst *target = mfind_target(mtmp, TRUE);
struct monst *target = mfind_target(mtmp, TRUE, FALSE);
if(tbx == 0 && tby == 0) return FALSE; //Target is not lined up.
@ -1120,24 +1142,36 @@ struct monst *mtmp;
}
if (!ranged_stuff) return FALSE;
if(mon_turn_undead(mtmp) && !mtmp->mspec_used && !mtmp->mcan && (!Inhell || mon_healing_turn(mtmp))){
struct monst *target2 = mfind_target(mtmp, FALSE, FALSE);
if((target && is_undead(target->data))
|| (target2 && is_undead(target2->data))
) {
m.offensive = (struct obj *) 0;
m.has_offense = MUSE_MON_TURN_UNDEAD;
}
}
#define nomore(x) if(m.has_offense==x) continue;
for(obj=mtmp->minvent; obj; obj=obj->nobj) {
if(mtmp->mtyp == PM_VALKYRIE && obj->oartifact == ART_MJOLLNIR && !obj->cursed && mtmp->misc_worn_check & ARM_GLOVES) {
if(mon_valkyrie(mtmp) && obj->oartifact == ART_MJOLLNIR && !obj->cursed && mtmp->misc_worn_check & W_ARMG) {
struct obj *otmp;
for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
if (otmp->owornmask & ARM_GLOVES && otmp->otyp == GAUNTLETS_OF_POWER){
if (otmp->owornmask & W_ARMG && otmp->otyp == GAUNTLETS_OF_POWER){
m.offensive = obj;
m.has_offense = MUSE_MJOLLNIR;
break;
}
}
if(m.has_offense==MUSE_MJOLLNIR) break;
if(m.has_offense==MUSE_MJOLLNIR) break;
}
nomore(MUSE_CRYSTAL_SKULL);
if(obj->otyp == CRYSTAL_SKULL && obj->age < monstermoves && is_mind_flayer(mtmp->data) && !obj_summon_out(obj) && !get_ox(obj, OX_ESUM)) {
m.offensive = obj;
m.has_offense = MUSE_CRYSTAL_SKULL;
}
nomore(MUSE_MON_TURN_UNDEAD);
nomore(MUSE_WAN_DEATH);
if (!reflection_skip) {
if(obj->otyp == WAN_DEATH && obj->spe > 0) {
@ -1500,11 +1534,15 @@ struct monst *mtmp;
boolean oseen;
/* offensive potions are not drunk, they're thrown */
if (otmp->oclass != POTION_CLASS && (i = precheck(mtmp, otmp)) != 0)
if (otmp && otmp->oclass != POTION_CLASS && (i = precheck(mtmp, otmp)) != 0)
return i;
oseen = otmp && canseemon(mtmp);
switch(m.has_offense) {
case MUSE_MON_TURN_UNDEAD:{
mon_doturn(mtmp);
mtmp->mspec_used = 3;
}break;
case MUSE_CRYSTAL_SKULL:{
coord cc;
if(!enexto(&cc, mtmp->mx+sgn(tbx), mtmp->my+sgn(tby), (struct permonst *)0)){
@ -2592,13 +2630,13 @@ struct obj *obj;
else if(is_cloak(obj))
return abs(obj->objsize - mon->data->msize) <= 1;
else if(is_helmet(obj))
return ((!has_horns(mon->data) || obj->otyp == find_gcirclet()) && helm_match(mon->data,obj) && has_head_mon(mon) && obj->objsize == mon->data->msize) || is_flimsy(obj);
return helm_match(mon->data, obj) && helm_size_fits(mon->data,obj);
else if(is_shield(obj) && !mon_offhand_attack(mon))
return !noshield(mon->data);
else if(is_gloves(obj))
return obj->objsize == mon->data->msize && can_wear_gloves(mon->data);
else if(is_boots(obj))
return obj->objsize == mon->data->msize && can_wear_boots(mon->data);
return boots_size_fits(mon->data, obj) && can_wear_boots(mon->data);
else if(is_suit(obj))
return arm_match(mon->data, obj) && arm_size_fits(mon->data, obj);
return FALSE;

View file

@ -233,6 +233,9 @@ WEAPON(("javelin", "throwing spear"),
WEAPON(("trident"), /*Needs encyc entry*/
DMG(D(8), F(1)), DMG(D(3, 6)),
1, 0, MZ_LARGE, 8, 25, 5, 0, P, P_TRIDENT, IRON, FALSE, HI_METAL),
WEAPON(("pincer staff", "claw-ended staff"), /*Needs encyc entry*/
DMG(D(6), F(2)), DMG(D(2, 6), F(1)),
0, 0, MZ_HUGE, 0, 25, 800, 0, P, P_TRIDENT, SHELL_MAT, FALSE, CLR_BRIGHT_MAGENTA),
/* blades */
WEAPON(("dagger"),
@ -381,7 +384,7 @@ WEAPON(("katana", "samurai sword"),
/* special swords set up for artifacts and future weapons*/
WEAPON(("vibroblade", "gray short sword", "short sword"), /*Needs encyc entry*//*Needs tile*/
DMG(D(6)), DMG(D(8)),
1, 0, MZ_SMALL, 0, 5,1000, 0, P, P_SHORT_SWORD, PLASTIC, FALSE, CLR_GRAY, O_MAGIC(1)),
0, 0, MZ_SMALL, 0, 5,1000, 0, P, P_SHORT_SWORD, PLASTIC, FALSE, CLR_GRAY, O_MAGIC(1)),
WEAPON(("tsurugi", "long samurai sword"),
DMG(D(16)), DMG(D(8), D(2,6)),
0, 0, MZ_HUGE, 0, 60,500, 2, S, P_TWO_HANDED_SWORD, METAL, FALSE, HI_METAL),
@ -516,7 +519,7 @@ WEAPON(("macuahuitl", "obsidian-edged club"), /*Needs encyc entry*/
0, 0, MZ_MEDIUM, 0, 40, 10, 0, B|S, P_CLUB, WOOD, FALSE, HI_WOOD),
WEAPON(("breaking wheel", "wagon wheel"), /*Needs encyc entry*/
DMG(D(6)), DMG(D(3)),
0, 0, MZ_HUGE, 1, 150, 500, 0, B, P_NONE, WOOD, FALSE, HI_WOOD),
0, 0, MZ_HUGE, 1, 150, 500, 0, B, P_NONE, WOOD, FALSE, HI_WOOD),
WEAPON(("quarterstaff", "staff"),
DMG(D(6)), DMG(D(6)),
0, 0, MZ_HUGE, 9, 40, 5, 0, B, P_QUARTERSTAFF, WOOD, FALSE, HI_WOOD),
@ -772,6 +775,8 @@ DRGN_SCALES(("yellow dragon scales"), 1, 500, 9, 2, CLR_YELLOW, O_POWER(A
SUIT(("plate mail"), /*Needs encyc entry*/
1, 0, MZ_HUGE, ARMSZ_HEAVY, 44, 5, 225, 600, 4, 6, 3, IRON, HI_METAL),
SUIT(("lantern plate mail", "glass-set plate mail"),
0, 0, MZ_HUGE, ARMSZ_HEAVY, 0, 5, 225, 650, 5, 6, 3, IRON, HI_METAL),
SUIT(("high-elven plate", "runed plate mail"), /*Needs encyc entry*/
0, 0, MZ_HUGE, ARMSZ_MEDIUM, 0, 5, 110, 1200, 3, 7, 3, MITHRIL, HI_MITHRIL),
SUIT(("droven plate mail", "crested black plate", "crested plate mail"), /*Needs encyc entry*/
@ -881,7 +886,7 @@ CLOAK(("prayer-warded wrapping"),
CLOAK(("elven cloak", "faded pall"),
0, 1, 7, 0, 10, 60, 9, 0, 3, CLOTH, CLR_BLACK, O_POWER(STEALTH)),
CLOAK(("droven cloak", "cobwebbed cloak"), /*Needs encyc entry*/
0, 1, 1, 0, 10, 60, 10, 0, 3, CLOTH, CLR_GRAY),
0, 1, 1, 0, 10, 60, 10, 0, 3, CLOTH, CLR_GRAY, O_DRSLOT(HEAD_DR|CLOAK_DR)),
CLOAK(("orcish cloak", "coarse mantelet"),
0, 0, 8, 0, 10, 40, 10, 0, 2, CLOTH, CLR_BLACK),
CLOAK(("dwarvish cloak", "hooded cloak"),
@ -1156,8 +1161,8 @@ TOOL(("lock pick"), 1, MZ_TINY, 0, 0, 0, 60, 4, 20, IRON, HI
TOOL(("tallow candle", "candle"), 0, MZ_TINY, 1, 0, 0, 15, 2, 10, WAX, CLR_WHITE),
TOOL(("wax candle", "candle"), 0, MZ_TINY, 1, 0, 0, 5, 2, 20, WAX, CLR_WHITE),
TOOL(("candle of invocation", "runed candle"), /*Needs encyc entry*/
0, MZ_TINY, 0, 1, 0, 15, 2, 50, WAX, CLR_ORANGE, O_NOWISH(1)),
TOOL(("lantern"), 1, MZ_SMALL, 0, 0, 0, 20, 30, 12, COPPER, CLR_YELLOW, O_MATSPEC(IDED|UNIDED)),
0, MZ_TINY, 0, 1, 0, 15, 2, 50, WAX, CLR_ORANGE, O_NOWISH(1)),
TOOL(("lantern"), 1, MZ_SMALL, 0, 0, 0, 20, 30, 12, COPPER, CLR_YELLOW, O_MATSPEC(IDED|UNIDED)),
TOOL(("oil lamp", "lamp"), 0, MZ_SMALL, 0, 0, 0, 30, 20, 10, COPPER, CLR_YELLOW),
TOOL(("magic lamp", "lamp"), 0, MZ_SMALL, 0, 1, 0, 15, 20, 50, COPPER, CLR_YELLOW, O_NOWISH(1)),
// TOOL(("shadowlander's torch", "black torch"),
@ -1588,7 +1593,7 @@ SPELL(("invisibility", "dark brown"), P_ESCAPE_SPELL, 25, 4, 1, NODIR,
SPELL(("detect treasure", "gray"), P_DIVINATION_SPELL, 20, 4, 1, NODIR, CLR_GRAY),
SPELL(("remove curse", "wrinkled"), P_CLERIC_SPELL, 25, 3, 1, NODIR, HI_PAPER),
SPELL(("magic mapping", "dusty"), P_DIVINATION_SPELL, 18, 5, 1, NODIR, HI_PAPER),
SPELL(("identify", "bronze"), P_DIVINATION_SPELL, 20, 3, 1, NODIR, HI_COPPER),
SPELL(("identify", "bronze"), P_DIVINATION_SPELL, 20, 6, 1, NODIR, HI_COPPER),
// SPELL(("turn undead", "copper"), P_CLERIC_SPELL, 16, 6, 1, IMMEDIATE, HI_COPPER),
SPELL(("create monster", "turquoise"), P_CLERIC_SPELL, 16, 6, 1, NODIR, CLR_BRIGHT_CYAN),
SPELL(("polymorph", "silver"), P_MATTER_SPELL, 10, 7, 1, IMMEDIATE, HI_SILVER),

View file

@ -3754,6 +3754,7 @@ int wishflags;
dreprun = FALSE,
veioistafur = FALSE,
thjofastafur = FALSE,
lolth_symbol = FALSE,
sizewished = FALSE;
int objsize = (from_user ? youracedata->msize : MZ_MEDIUM);
long bodytype = 0L;
@ -3808,6 +3809,8 @@ int wishflags;
return mkhellvaultitem(VN_APOCALYPSE);
if(!strcmpi(bp, "lolth vault loot"))
return mklolthvaultitem();
if(!strcmpi(bp, "jewel"))
return mkjewel();
}
for(;;) {
@ -3886,6 +3889,8 @@ int wishflags;
veioistafur = TRUE;
} else if(!strncmpi(bp, "thjofastafur ", l=13)){
thjofastafur = TRUE;
} else if(!strncmpi(bp, "lolth_symbol ", l=13)){
lolth_symbol = TRUE;
} else if(!strncmpi(bp, "engraved ", l=9)){
/*This modifier does nothing, really, but people should be allowed to write it.*/;
} else if(!strncmpi(bp, "carved ", l=7)){
@ -5453,31 +5458,19 @@ typfnd:
if(otmp->oclass == ARMOR_CLASS && !Is_dragon_scales(otmp)){
if(bodytype == 0L){
if (from_user) {
if (is_suit(otmp) && (youracedata->mflagsb&MB_BODYTYPEMASK)) otmp->bodytypeflag = (youracedata->mflagsb&MB_BODYTYPEMASK);
else if (is_helmet(otmp)) otmp->bodytypeflag = (youracedata->mflagsb&MB_HEADMODIMASK);
else if (is_shirt(otmp) && (youracedata->mflagsb&MB_BODYTYPEMASK)) otmp->bodytypeflag = (youracedata->mflagsb&MB_HUMANOID) ? MB_HUMANOID : (youracedata->mflagsb&MB_BODYTYPEMASK);
else otmp->bodytypeflag = MB_HUMANOID;
set_obj_shape(otmp, youracedata->mflagsb);
}
else {
otmp->bodytypeflag = MB_HUMANOID;
set_obj_shape(otmp, MB_HUMANOID);
}
} else {
if(is_suit(otmp)){
if((bodytype&MB_BODYTYPEMASK) != 0L) otmp->bodytypeflag = (bodytype&MB_BODYTYPEMASK);
else otmp->bodytypeflag = (youracedata->mflagsb&MB_BODYTYPEMASK);
} else if(is_helmet(otmp)){
if((bodytype&MB_HEADMODIMASK) != 0L) otmp->bodytypeflag = (bodytype&MB_HEADMODIMASK);
else if((bodytype&MB_HUMANOID) != 0L) otmp->bodytypeflag = 0L; //Humanoid heads have no special modifier
else otmp->bodytypeflag = (youracedata->mflagsb&MB_HEADMODIMASK);
} else if(is_shirt(otmp)){
if((bodytype&MB_BODYTYPEMASK) != 0L) otmp->bodytypeflag = (bodytype&MB_HUMANOID) ? MB_HUMANOID : (bodytype&MB_BODYTYPEMASK);
else otmp->bodytypeflag = (youracedata->mflagsb&MB_HUMANOID) ? MB_HUMANOID : (youracedata->mflagsb&MB_BODYTYPEMASK);
}
set_obj_shape(otmp, youracedata->mflagsb);
set_obj_shape(otmp, bodytype);
}
}
if(otmp->oclass == RING_CLASS && isEngrRing((otmp)->otyp) && (wizwish || (otmp->oward && !(otmp->ohaluengr)))){
if(wizwish || (otmp->oclass == RING_CLASS && isEngrRing((otmp)->otyp) && otmp->oward && !otmp->ohaluengr)){
if(heptagram && wizwish) otmp->oward = HEPTAGRAM; /*can't be wished for*/
else if(gorgoneion && wizwish) otmp->oward = GORGONEION;/*can't be wished for*/
else if(acheron) otmp->oward = CIRCLE_OF_ACHERON;
@ -5493,6 +5486,10 @@ typfnd:
else if(dreprun && wizwish) otmp->oward = DREPRUN;/*can't be wished for*/
else if(veioistafur && wizwish) otmp->oward = VEIOISTAFUR;/*can't be wished for*/
else if(thjofastafur && wizwish) otmp->oward = THJOFASTAFUR; /*can't be wished for*/
else if(lolth_symbol && wizwish){/*can't be wished for*/
otmp->oward = LOLTH_SYMBOL;
otmp->ohaluengr = TRUE;
}
}
@ -5588,8 +5585,8 @@ typfnd:
/* set poisoned */
if (ispoisoned) {
if (is_poisonable(otmp))
otmp->opoisoned = (Luck >= 0) ? ispoisoned : 0;
if (is_poisonable(otmp) || wizwish)
otmp->opoisoned = (Luck >= 0 || wizwish) ? ispoisoned : 0;
else if (Is_box(otmp) || typ == TIN)
otmp->otrapped = 1;
else if (oclass == FOOD_CLASS)

View file

@ -2091,6 +2091,7 @@ get_description_of_damage_type(uchar id)
case AD_PERH: return "level-based damage";
case AD_SVPN: return "severe poison";
case AD_HLUH: return "corrupted holy energy";
case AD_TSMI: return "magic-item-stealing tentacles";
default:
impossible("bug in get_description_of_damage_type(%d)", id);
return "<MISSING DESCRIPTION, THIS IS A BUG>";

View file

@ -2174,6 +2174,11 @@ register struct obj *obj;
) {
pline("That combination is a little too explosive.");
return 0;
} else if (!(is_magic_obj(obj))
&& current_container->oartifact == ART_ESSCOOAHLIPBOOURRR
) {
pline("The artifact isn't interested in taking %s.", the(xname(obj)));
return 0;
} else if (obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) {
Norep("You cannot %s %s you are wearing.",
Icebox ? "refrigerate" : "stash", something);
@ -2556,6 +2561,97 @@ boolean past;
return;
}
void
open_giants_sack(box, past)
struct obj *box;
boolean past;
{
struct monst *victim;
xchar ox, oy;
pline(past ? "That %s was being used to haul a plague victim!" : "This %s is being used to haul a plague victim!", simple_typename(box->otyp));
box->spe = 0; /* box->owt will be updated below */
if (get_obj_location(box, &ox, &oy, 0))
box->ox = ox, box->oy = oy; /* in case it's being carried */
if(urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH){
int drow_plague_types[] = {
PM_DWARF_QUEEN, PM_DWARF_KING,
PM_ORC_CAPTAIN, PM_JUSTICE_ARCHON, PM_SHIELD_ARCHON, PM_SWORD_ARCHON,
PM_MOVANIC_DEVA, PM_MONADIC_DEVA, PM_ASTRAL_DEVA,
PM_LILLEND, PM_COURE_ELADRIN, PM_NOVIERE_ELADRIN, PM_BRALANI_ELADRIN, PM_FIRRE_ELADRIN, PM_SHIERE_ELADRIN,
PM_SPROW, PM_DRIDER, PM_PRIESTESS_OF_GHAUNADAUR,
PM_NURSE,
PM_ELF_LORD, PM_ELF_LADY, PM_ELVENKING, PM_ELVENQUEEN,
PM_ANULO, PM_ANULO,
PM_DROW_CAPTAIN, PM_HEDROW_WARRIOR, PM_HEDROW_WIZARD, PM_DROW_MATRON,
PM_DROW_CAPTAIN, PM_HEDROW_WARRIOR, PM_HEDROW_WIZARD, PM_DROW_MATRON, PM_UNEARTHLY_DROW, PM_HEDROW_BLADEMASTER,
PM_HEDROW_MASTER_WIZARD, PM_STJARNA_ALFR, PM_PEN_A_MENDICANT, PM_MENDICANT_SPROW, PM_MENDICANT_DRIDER,
PM_YOCHLOL, PM_LILITU, PM_MARILITH,
PM_ALLIANCE_VANGUARD, PM_PAGE, PM_DWARF_WARRIOR,
PM_BARBARIAN, PM_HALF_DRAGON, PM_BARD, PM_HEALER, PM_RANGER, PM_VALKYRIE
};
victim = makemon(&mons[ROLL_FROM(drow_plague_types)], box->ox, box->oy, NO_MM_FLAGS);
}
else {
int plague_types[] = {
PM_DWARF_LORD, PM_DWARF_CLERIC, PM_DWARF_QUEEN, PM_DWARF_KING,
PM_DEEP_ONE, PM_WINGED_KOBOLD,
PM_DEMINYMPH, PM_THRIAE,
PM_ORC_CAPTAIN, PM_JUSTICE_ARCHON, PM_SHIELD_ARCHON, PM_SWORD_ARCHON,
PM_MOVANIC_DEVA, PM_MONADIC_DEVA, PM_ASTRAL_DEVA,
PM_LILLEND, PM_COURE_ELADRIN, PM_NOVIERE_ELADRIN, PM_BRALANI_ELADRIN, PM_FIRRE_ELADRIN, PM_SHIERE_ELADRIN,
PM_CENTAUR_CHIEFTAIN,
PM_DRIDER, PM_FORMIAN_CRUSHER, PM_FORMIAN_TASKMASTER,
PM_MYRMIDON_YPOLOCHAGOS, PM_MYRMIDON_LOCHAGOS,
PM_GNOME_KING, PM_GNOME_QUEEN,
PM_HILL_GIANT, PM_MINOTAUR, PM_MINOTAUR_PRIESTESS,
PM_VAMPIRE, PM_VAMPIRE_LORD, PM_VAMPIRE_LADY,
PM_NURSE, PM_WATCH_CAPTAIN,
PM_GREY_ELF, PM_ELF_LORD, PM_ELF_LADY, PM_ELVENKING, PM_ELVENQUEEN,
PM_DROW_MATRON,
PM_HORNED_DEVIL, PM_SUCCUBUS, PM_INCUBUS, PM_ERINYS, PM_VROCK, PM_BARBED_DEVIL,
PM_LILITU,
PM_BARBARIAN, PM_HALF_DRAGON, PM_BARD, PM_HEALER, PM_RANGER, PM_VALKYRIE,
PM_GOAT_SPAWN, PM_GIANT_GOAT_SPAWN
};
victim = makemon(&mons[ROLL_FROM(plague_types)], box->ox, box->oy, NO_MM_FLAGS);
}
if(victim){
struct obj *nobj;
for(struct obj *obj = victim->minvent; obj; obj = nobj){
nobj = obj->nobj;
victim->misc_worn_check &= ~obj->owornmask;
update_mon_intrinsics(victim, obj, FALSE, FALSE);
if (obj->owornmask & W_WEP){
setmnotwielded(victim,obj);
MON_NOWEP(victim);
}
if (obj->owornmask & W_SWAPWEP){
setmnotwielded(victim,obj);
MON_NOSWEP(victim);
}
obj->owornmask = 0L;
obj_extract_self(obj);
if(past)
place_object(obj, victim->mx, victim->my);
else
add_to_container(box, obj);
}
(void)mongets(victim, SHACKLES, NO_MKOBJ_FLAGS);
victim->entangled = SHACKLES;
//Note: these are "fresh" so they don't take the 1/3rd penalty to level
set_template(victim, PLAGUE_TEMPLATE);
victim->mpeaceful = 1;
set_malign(victim);
} else {
pline(past ? "But the sack was now empty." : "But the sack is now empty.");
}
box->owt = weight(box);
return;
}
void
open_sarcophagus(box, past)
struct obj *box;
@ -2641,42 +2737,42 @@ boolean past;
continue;
obj_extract_self(otmp);
mpickobj(daughter, otmp);
break; //Found boots. Also, otmp->nobj should now be 0 anyway.
break; //Found gloves. Also, otmp->nobj should now be 0 anyway.
}
for(otmp = box->cobj; otmp; otmp = otmp->nobj){
if(!is_shirt(otmp))
continue;
obj_extract_self(otmp);
mpickobj(daughter, otmp);
break; //Found boots. Also, otmp->nobj should now be 0 anyway.
break; //Found shirt. Also, otmp->nobj should now be 0 anyway.
}
for(otmp = box->cobj; otmp; otmp = otmp->nobj){
if(!is_suit(otmp))
continue;
obj_extract_self(otmp);
mpickobj(daughter, otmp);
break; //Found boots. Also, otmp->nobj should now be 0 anyway.
break; //Found suit. Also, otmp->nobj should now be 0 anyway.
}
for(otmp = box->cobj; otmp; otmp = otmp->nobj){
if(!is_cloak(otmp))
continue;
obj_extract_self(otmp);
mpickobj(daughter, otmp);
break; //Found boots. Also, otmp->nobj should now be 0 anyway.
break; //Found cloak. Also, otmp->nobj should now be 0 anyway.
}
for(otmp = box->cobj; otmp; otmp = otmp->nobj){
if(!is_helmet(otmp))
continue;
obj_extract_self(otmp);
mpickobj(daughter, otmp);
break; //Found boots. Also, otmp->nobj should now be 0 anyway.
break; //Found helm. Also, otmp->nobj should now be 0 anyway.
}
for(otmp = box->cobj; otmp; otmp = otmp->nobj){
if(!is_shield(otmp))
continue;
obj_extract_self(otmp);
mpickobj(daughter, otmp);
break; //Found boots. Also, otmp->nobj should now be 0 anyway.
break; //Found shield. Also, otmp->nobj should now be 0 anyway.
}
m_dowear(daughter, TRUE);
m_level_up_intrinsic(daughter);
@ -3006,18 +3102,13 @@ struct monst *mon;
addArmorMenuOption
} else if(is_cloak(otmp) && !(mon->misc_worn_check&W_ARMC) && (abs(otmp->objsize - mon->data->msize) <= 1)){
addArmorMenuOption
} else if(is_helmet(otmp) && !(mon->misc_worn_check&W_ARMH) &&
((helm_match(mon->data,otmp) && has_head_mon(mon) && otmp->objsize == mon->data->msize && !has_horns(mon->data))
|| is_flimsy(otmp)
|| otmp->otyp == find_gcirclet()
)
){
} else if(is_helmet(otmp) && !(mon->misc_worn_check&W_ARMH) && helm_match(mon->data,otmp) && helm_size_fits(mon->data,otmp)){
addArmorMenuOption
} else if(is_shield(otmp) && !(mon->misc_worn_check&W_ARMS) && !noshield(mon->data)){
addArmorMenuOption
} else if(is_gloves(otmp) && !(mon->misc_worn_check&W_ARMG) && otmp->objsize == mon->data->msize && can_wear_gloves(mon->data)){
addArmorMenuOption
} else if(is_boots(otmp) && !(mon->misc_worn_check&W_ARMF) && otmp->objsize == mon->data->msize && can_wear_boots(mon->data)){
} else if(is_boots(otmp) && !(mon->misc_worn_check&W_ARMF) && boots_size_fits(mon->data, otmp) && can_wear_boots(mon->data)){
addArmorMenuOption
} else if(is_suit(otmp) && !(mon->misc_worn_check&W_ARM) && arm_match(mon->data, otmp) && arm_size_fits(mon->data, otmp)){
addArmorMenuOption
@ -3133,28 +3224,32 @@ register int held;
return MOVE_STANDARD;
}
current_container = obj; /* for use by in/out_container */
if (obj->spe == 1) {
observe_quantum_cat(obj, FALSE); //FALSE: the box was not destroyed. Use present tense.
used = 1;
quantum_cat = TRUE; /* for adjusting "it's empty" message */
}else if(obj->spe == 4){
open_coffin(obj, FALSE); //FALSE: the box was not destroyed. Use present tense.
return MOVE_STANDARD;
}else if(obj->spe == 5){
open_sarcophagus(obj, FALSE); //FALSE: the box was not destroyed. Use present tense.
return MOVE_STANDARD;
}else if(obj->spe == 6 && u.uinsight >= 10){
open_crazy_box(obj, FALSE); //FALSE: the box was not destroyed. Use present tense.
return MOVE_STANDARD;
}else if(obj->spe == 7){
// Madman reclaims their stuff. Contents handled by the level loader.
//FALSE: the box was not destroyed. Use present tense.
if(open_madstuff_box(obj, FALSE)){
if(Is_real_container(obj)){
if (obj->spe == 1) {
observe_quantum_cat(obj, FALSE); //FALSE: the box was not destroyed. Use present tense.
used = 1;
quantum_cat = TRUE; /* for adjusting "it's empty" message */
}else if(obj->spe == 4){
open_coffin(obj, FALSE); //FALSE: the box was not destroyed. Use present tense.
return MOVE_STANDARD;
}else if(obj->spe == 5){
open_sarcophagus(obj, FALSE); //FALSE: the box was not destroyed. Use present tense.
return MOVE_STANDARD;
}else if(obj->spe == 6 && u.uinsight >= 10){
open_crazy_box(obj, FALSE); //FALSE: the box was not destroyed. Use present tense.
return MOVE_STANDARD;
}else if(obj->spe == 7){
// Madman reclaims their stuff. Contents handled by the level loader.
//FALSE: the box was not destroyed. Use present tense.
if(open_madstuff_box(obj, FALSE)){
return MOVE_STANDARD;
}
}else if(obj->spe == 8){
// Nothing. Fulvous desk spawns monsters.
}else if(obj->spe == 9){
open_giants_sack(obj, FALSE); //FALSE: not destroyed
return MOVE_STANDARD;
}
}else if(obj->spe == 8){
// Nothing. Fulvous desk spawns monsters.
}
/* Count the number of contained objects. Sometimes toss objects if a cursed magic bag. */
if (cobj_is_magic_chest(obj))

View file

@ -583,6 +583,7 @@ register struct monst *mtmp;
if (mtmp->mconf) Strcat(info, ", confused");
if (mtmp->mcrazed) Strcat(info, ", crazed");
if (mtmp->mberserk) Strcat(info, ", berserk");
if (mon_healing_penalty(mtmp)) Strcat(info, ", itchy");
if (mtmp->mblinded || !mtmp->mcansee)
Strcat(info, ", blind");
else if(is_blind(mtmp)) Strcat(info, ", dazzled");

View file

@ -745,7 +745,7 @@ break_armor()
}
}
if ((otmp = uarmh) != 0){
if((!is_flimsy(otmp) && otmp->otyp != find_gcirclet() && (otmp->objsize != youracedata->msize || has_horns(youracedata) || !has_head_mon(&youmonst) || !helm_match(youracedata,otmp)))
if(!helm_match(youracedata, uarmh) || !helm_size_fits(youracedata, uarmh)
|| is_whirly(youracedata) || noncorporeal(youracedata)
) {
if (donning(otmp)) cancel_don();
@ -756,12 +756,12 @@ break_armor()
char hornbuf[BUFSZ], yourbuf[BUFSZ];
/* Future possiblities: This could damage/destroy helmet */
Sprintf(hornbuf, "horn%s", plur(num_horns(youracedata)));
Your("%s %s through %s %s.", hornbuf, vtense(hornbuf, "pierce"),
Your("%s %s through %s %s.", hornbuf, vtense(hornbuf, uarmh->otyp == find_gcirclet() ? "pass" : "pierce"),
shk_your(yourbuf, otmp), xname(otmp));
}
}
if ((otmp = uarmg) != 0) {
if(nogloves(youracedata) || nolimbs(youracedata) || otmp->objsize != youracedata->msize || is_whirly(youracedata) || noncorporeal(youracedata)){
if(nogloves(youracedata) || nolimbs(youracedata) || boots_size_fits(youracedata, otmp) || is_whirly(youracedata) || noncorporeal(youracedata)){
if (donning(otmp)) cancel_don();
/* Drop weapon along with gloves */
You("drop your gloves%s!", uwep ? " and weapon" : "");
@ -2048,7 +2048,7 @@ int part;
"spine", "toe", "hair", "blood",
"lung", "nose", "stomach", "heart",
"skin", "flesh", "beat", "bones",
"ear", "ears", "creak", "crack"},
"ear", "ears", "creak", "crack"},
*uvuudaum_parts[] = {
"arm", "eye", "headspike", "finger",
"fingertip", "hand", "hand", "handed",
@ -2095,14 +2095,14 @@ int part;
"cap", "ventral limb", "addled", "stalk",
"chassis", "needle-tip", "spores", "oil",
"gear", "gill", "hyphal network","eternal core",
"metal skin", "brass structure", "tick", "armature",
"armor", "brass structure", "tick", "armature",
"phonoreceptor horn","phonoreceptor horn","creak", "bend"},
*jelly_parts[] = {
"pseudopod", "dark spot", "front", "pseudopod extension",
"pseudopod extremity","pseudopod root", "grasp", "grasped",
"cerebral area", "lower pseudopod", "viscous", "middle",
"centriole", "pseudopod extremity","ripples", "juices",
"tiny cilia", "sensor", "stomach", "cytoskeletal structure",
"centriole", "pseudopod extremity","ripples", "plasm",
"tiny cilia", "chemosensor", "vacuoles", "cytoskeletal structure",
"membrane", "cortex", "shift", "cytoskeletal filaments",
"membrane", "membrane", "creak", "crack" },
*animal_parts[] = {
@ -2112,7 +2112,7 @@ int part;
"spine", "rear claw tip", "fur", "blood",
"lung", "nose", "stomach", "heart",
"skin", "flesh", "beat", "bones",
"ear", "ears", "creak", "crack" },
"ear", "ears", "creak", "crack" },
*insect_parts[] = {
"forelimb", "compound eye", "face", "foreclaw",
"claw tip", "rear claw", "foreclaw", "clawed",
@ -2157,7 +2157,7 @@ int part;
"mycelium", "visual area", "front", "hypha",
"hypha", "root", "strand", "stranded",
"cap area", "rhizome", "sporulated", "stalk",
"root", "rhizome tip", "spores", "juices",
"root", "rhizome tip", "spores", "juice",
"gill", "gill", "interior", "hyphal network",
"cuticle", "flesh", "...it doesn't sound like much","hyphae",
"tympanic area", "tympanic area", "stretch", "tear" },
@ -2253,10 +2253,18 @@ int part;
"arm", "eye", "face", "finger",
"fingertip", "serpentine lower body","hand", "handed",
"head", "rear region", "light headed", "neck",
"spine", "tail-tip", "scales", "blood",
"spine", "tail-tip", "hair", "blood",
"lung", "nose", "stomach", "heart",
"scales", "flesh", "beat", "bones",
"ear", "ears", "creak", "crack" },
*dracae_parts[] = {
"arm", "eye", "face", "finger",
"claw tip", "gooey proleg", "hand", "handed",
"head", "gooey caterpilloid lower body","light headed", "neck",
"notochord", "tentacle-tip", "tendrils", "sol",
"spongiform jelly", "chemopores", "vacuoles", "heart",
"mucous membrane", "protoplasm", "beat", "cytoskeletal filaments",
"tympanic membrane","tympanic membranes","creak", "crack" },
*centauroid_parts[] = {
"arm", "eye", "face", "finger",
"fingertip", "hoof", "hand", "handed",
@ -2357,6 +2365,8 @@ int part;
return android_parts[part];
if (mptr->mtyp == PM_UVUUDAUM)
return uvuudaum_parts[part];
if (mptr->mtyp == PM_DRACAE_ELADRIN)
return dracae_parts[part];
//S-based part lists
if (mptr->mlet == S_PLANT)

View file

@ -1067,7 +1067,7 @@ boolean force;
enhanced = uarmg && uarmg->oartifact == ART_GAUNTLETS_OF_THE_HEALING_H;
healup(d((enhanced ? 2 : 1) * (6 + 2 * bcsign(otmp)), 4),
!(get_ox(otmp, OX_ESUM)) * ((enhanced ? 2 : 1) * (!otmp->cursed ? 1 : 0)),
!!otmp->blessed, !otmp->cursed);
otmp->blessed, !otmp->cursed);
exercise(A_CON, TRUE);
break;
case POT_EXTRA_HEALING:

View file

@ -9,6 +9,7 @@
#include "artifact.h"
extern const int monstr[];
extern void you_aggravate(struct monst *);
STATIC_PTR int NDECL(prayer_done);
STATIC_DCL struct obj *NDECL(worst_cursed_item);
@ -2617,6 +2618,108 @@ doturn()
return MOVE_STANDARD;
}
int
mon_doturn(mon)
struct monst *mon;
{ /* Knights & Priest(esse)s only please */
struct monst *mtmp, *mtmp2;
int once, range, xlev;
short fast = 0;
if(mon_healing_turn(mon)){
if(canseemon(mon))
pline("%s shines with holy light!", Monnam(mon));
}
else
pline("%s chants holy scripture.", Monnam(mon));
if(Misotheism){
pline("But nothing happens!");
return MOVE_CANCELLED;
}
/* note: does not perform unturn_dead() on victims' inventories */
range = BOLT_LIM + (mon->m_lev / 5);
range *= range;
once = 0;
for(mtmp = fmon; mtmp; mtmp = mtmp2) {
mtmp2 = mtmp->nmon;
if (DEADMONSTER(mtmp)) continue;
if (mtmp == mon) continue;
if (!clear_path(mon->mx,mon->my, mtmp->mx,mtmp->my) ||
dist2(mon->mx,mon->my, mtmp->mx,mtmp->my) > range
) continue;
if (mm_grudge(mon, mtmp) &&
(is_undead(mtmp->data) ||
(is_demon(mtmp->data) && (mon->m_lev > (MAXULEV/2)))
)
){
mtmp->msleeping = 0;
if (mon->mconf) {
if (!once++){
pline("%s voice falters!", s_suffix(Monnam(mon)));
}
if(mtmp->mtyp != PM_BANDERSNATCH) mtmp->mflee = 0;
mtmp->mfrozen = 0;
mtmp->mcanmove = 1;
} else if (!resist(mtmp, '\0', 0, TELL)) {
if(is_undead(mtmp->data)){
xlev = turn_level(mtmp);
if (mon->m_lev >= xlev && !resist(mtmp, '\0', 0, NOTELL)) {
pline("%s is destroyed!", Monnam(mtmp));
grow_up(mon, mtmp);
monkilled(mtmp, (const char *)0, AD_SPEL);
}
}
/* else flee */
if(!DEADMONSTER(mtmp))
monflee(mtmp, 0, FALSE, TRUE);
}
}
else if (mon_healing_turn(mon) && mtmp->mhp < mtmp->mhpmax
&& !mon->mtame == !mtmp->mtame && mon->mpeaceful == mtmp->mpeaceful && !mm_grudge(mon, mtmp)
&& !(is_undead(mtmp->data) || is_demon(mtmp->data))
){
if(canseemon(mtmp))
pline("%s looks better!", Monnam(mtmp));
mtmp->mhp += d(10,6);
if(mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
}
}
if(distu(mon->mx,mon->my) <= range && !mon->mpeaceful){
if(is_undead(youracedata) || (is_demon(youracedata) && (mon->m_lev > (MAXULEV/2)))){
if(mon->mconf){
pline("%s faltering voice enrages you!", s_suffix(Monnam(mon)));
you_aggravate(mon);
}
else {
xlev = turn_level(&youmonst);
if(is_undead(youracedata) && mon->m_lev >= xlev && rnd(u.ulevel) <= xlev){
if(mon_healing_turn(mon)){
You("are burned by the holy light!");
losehp(d(10,6), "holy light", KILLED_BY);
}
else {
You("are burned by the holy words!");
losehp(d(6,6), "holy scripture", KILLED_BY);
}
}
You("panic!");
HPanicking += d(6,6);
}
}
else if(mon->mtame && mon_healing_turn(mon)
&& !(is_undead(youracedata) || (is_demon(youracedata) && (mon->m_lev > (MAXULEV/2))))
){
healup(d(10,6), 0, FALSE, FALSE);
}
}
return MOVE_STANDARD;
}
const char *
a_gname()
{
@ -4125,6 +4228,7 @@ int godnum;
case GOD_LOLTH: return LOLTH_SYMBOL;
case GOD_GHAUNADAUR: return GHAUNADAUR_SYMBOL;
case GOD_VER_TAS: return VER_TAS_SYMBOL;
case GOD_PEN_A: return PEN_A_SYMBOL;
case GOD_EILISTRAEE: return EILISTRAEE_SYMBOL;
case GOD_KIARANSALI: return KIARANSALEE_SYMBOL;
case GOD_THE_BLACK_MOTHER: return GOATMOM_FACTION;
@ -4460,16 +4564,30 @@ int x, y;
* Any attending priests will still get upset, though!
*/
boolean
gods_are_friendly(god1, god2)
int god1, god2;
gods_are_friendly(from_god, to_god)
int from_god, to_god;
{
/* elf-gods are friendly with each other */
/* NOTE: assumes order of elfgods in godlist.h */
if ((GOD_OROME <= god1 && god1 <= GOD_LORIEN)
&& (GOD_OROME <= god2 && god2 <= GOD_LORIEN))
if ((GOD_OROME <= from_god && from_god <= GOD_LORIEN)
&& (GOD_OROME <= to_god && to_god <= GOD_LORIEN))
{
return TRUE;
}
if(from_god == GOD_PEN_A || to_god == GOD_PEN_A){
if(from_god == GOD_ILMATER || to_god == GOD_ILMATER)
return TRUE;
if(from_god == GOD_EILISTRAEE || to_god == GOD_EILISTRAEE)
return TRUE;
}
if(from_god == GOD_VANDRIA || from_god == GOD_SEHANINE){
if(to_god == GOD_VANDRIA)
return TRUE;
if(to_god == GOD_SEHANINE)
return TRUE;
if(to_god == GOD_CORELLON)
return TRUE; /*Note: but not FROM Corellon*/
}
return FALSE;
}

View file

@ -203,7 +203,7 @@ boolean seal;
portal_flag = u.uevent.qexpelled ? 0 : /* returned via artifact? */
!seal ? 1 : -1;
}
schedule_goto(dest, FALSE, FALSE, portal_flag, (char *)0, (char *)0);
schedule_goto(dest, FALSE, FALSE, portal_flag, (char *)0, (char *)0,0);
if (seal) { /* remove the portal to the quest - sealing it off */
int reexpelled = u.uevent.qexpelled;
u.uevent.qexpelled = 1;

View file

@ -570,6 +570,41 @@ qt_montype()
return (&mons[qpm]);
//Should be impossible:
return (mkclass(S_YETI, G_NOHELL));
} else if(urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH){
int qpm;
int duergar[] = {PM_DUERGAR, PM_DUERGAR_STONEGUARD, PM_DUERGAR_DEBILITATOR};
int drow_etc[] = {PM_HOUSELESS_DROW, PM_HOUSELESS_DROW, PM_HOUSELESS_DROW, PM_HOUSELESS_DROW,
PM_SPROW, PM_SPROW, PM_DRIDER, PM_DROW_MUMMY,
PM_HEDROW_ZOMBIE, PM_DROW_CAPTAIN, PM_HEDROW_WARRIOR, PM_HEDROW_WIZARD,
PM_DROW_MATRON, PM_PEN_A_MENDICANT, PM_MENDICANT_SPROW, PM_MENDICANT_DRIDER,
PM_ALLIANCE_VANGUARD, PM_ANULO, PM_ANULO, PM_DWARF,
PM_DWARF, PM_WOODLAND_ELF, PM_WOODLAND_ELF, PM_GREEN_ELF,
PM_GREEN_ELF, PM_PEASANT, PM_PEASANT, PM_GOBLIN,
PM_HOBGOBLIN, PM_BUGBEAR, PM_BUGBEAR, PM_HOBBIT,
PM_GNOME, PM_GNOME, PM_HILL_GIANT, PM_HILL_GIANT,
PM_MINOTAUR, PM_MINOTAUR_PRIESTESS, PM_ETTIN,
PM_DEMINYMPH
};
if(!rn2(3)){
qpm = ROLL_FROM(duergar);
if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GONE && !In_quest(&u.uz)))
return (&mons[qpm]);
return (mkclass(S_HUMANOID, G_NOHELL));
}
if(rn2(2)){
if(u.uevent.qcompleted)
qpm = rn2(5) ? ROLL_FROM(duergar) : rn2(3) ? PM_CHUUL : PM_ELDER_CHUUL;
else
qpm = rn2(5) ? PM_KUO_TOA : rn2(3) ? PM_KUO_TOA_WHIP : rn2(3) ? PM_CHUUL : PM_ELDER_CHUUL;
if (qpm != NON_PM && !(mvitals[qpm].mvflags & G_GONE && !In_quest(&u.uz)))
return (&mons[qpm]);
//Fall through in this (impossible?) case
}
qpm = ROLL_FROM(drow_etc);
if (qpm != NON_PM && !(mvitals[qpm].mvflags & G_GONE && !In_quest(&u.uz)))
return (&mons[qpm]);
//Should be impossible:
return (mkclass(S_HUMAN, G_NOHELL));
} else if(Role_if(PM_NOBLEMAN) && Race_if(PM_HALF_DRAGON) && flags.initgend
&& ((Is_qlocate(&u.uz) && rn2(2)) || (u.uz.dlevel < qlocate_level.dlevel))
){

View file

@ -353,6 +353,34 @@ doread()
if (i == MAXSPELL) impossible("Too many spells memorized!");
return MOVE_READ;
}
} else if(scroll->oartifact == ART_ESSCOOAHLIPBOOURRR){
if (Blind) {
You_cant("see the staff!");
return MOVE_INSTANT;
} else {
int i;
You("read the still-visible traceries of healing magics inscribed on the shackles fusing the sword together.");
for (i = 0; i < MAXSPELL; i++) {
if (spellid(i) == SPE_MASS_HEALING) {
if (spellknow(i) <= 1000) {
Your("knowledge of Mass Healing is keener.");
spl_book[i].sp_know = 20000;
exercise(A_WIS,TRUE); /* extra study */
} else { /* 1000 < spellknow(i) <= MAX_SPELL_STUDY */
You("know Mass Healing quite well already.");
}
break;
} else if (spellid(i) == NO_SPELL) {
spl_book[i].sp_id = SPE_MASS_HEALING;
spl_book[i].sp_lev = objects[SPE_MASS_HEALING].oc_level;
spl_book[i].sp_know = 20000;
You("learn to cast Mass Healing!");
break;
}
}
if (i == MAXSPELL) impossible("Too many spells memorized!");
return MOVE_READ;
}
} else if(scroll->otyp == LIGHTSABER){
if (Blind) {
You_cant("see it!");
@ -480,11 +508,15 @@ doread()
return MOVE_READ;
#ifdef TOURIST
} else if(scroll->oclass == ARMOR_CLASS
&& scroll->ohaluengr
&& scroll->oward
&& is_readable_armor_otyp(scroll->otyp)
&& is_readable_armor(scroll)
){
pline("There is %s engraved on the armor.",fetchHaluWard((int)scroll->oward));
if(!scroll->ohaluengr){
if( !(u.wardsknown & get_wardID(scroll->oward)) ){
You("have learned a new warding sign!");
u.wardsknown |= get_wardID(scroll->oward);
}
}
return MOVE_READ;
}else if (scroll->otyp == T_SHIRT) {
static const char *shirt_msgs[] = { /* Scott Bigham */
@ -857,11 +889,14 @@ struct obj *scroll;
return 0;
}
else {
int objcount = 2 + rn2(3) + rn2(5);
You("can't understand what they say...");
pline("Suddenly, the glyphs glow in rainbow hues and escape from the fracturing disk!");
pline("Some of the glyphs get trapped in your %s!", (eyecount(youracedata) == 1) ? body_part(EYE) : makeplural(body_part(EYE)));
know_random_obj(2 + rn2(3) + rn2(5));
know_random_obj(objcount);
change_uinsight(1);
more_experienced(d(objcount+1, 100), 0);
newexplevel();
}
}
} else if(scroll->otyp == APHANACTONAN_ARCHIVE){
@ -878,24 +913,35 @@ struct obj *scroll;
else {
int i;
int rolls;
int effectcount;
int xp = 0;
boolean seals = FALSE, wards = FALSE, combat = FALSE;
You("can't understand what it says...");
pline("Suddenly, the glyphs glow in impossible hues and escape from the fracturing disk!");
pline("Some of the glyphs get trapped in your %s!", (eyecount(youracedata) == 1) ? body_part(EYE) : makeplural(body_part(EYE)));
know_random_obj(4 + rn2(5) + rn2(9));
change_uinsight(rnd(8));
//ID
effectcount = 4 + rn2(5) + rn2(9);
xp += d(effectcount,100);
know_random_obj(effectcount);
//Insight
effectcount = rnd(8);
xp += d(effectcount,100);
change_uinsight(effectcount);
change_usanity(-1*d(8,8),TRUE);
for(rolls = d(1,4); rolls > 0; rolls--){
switch(rnd(4)){
case 1:
for(i = rnd(4); i > 0; i--){
xp += d(1,200);
learn_spell_aphanactonan(rn1(SPE_BLANK_PAPER - SPE_DIG, SPE_DIG));
}
break;
case 2:
if(!Role_if(PM_EXILE)){
if(!seals){
xp += 625;
You("see circular seals!");
seals = TRUE;
}
@ -910,6 +956,7 @@ struct obj *scroll;
wards = TRUE;
}
for(i = d(2,4); i > 0; i--){
xp += d(1,50);
u.wardsknown |= 0x1L<<rnd(NUM_WARDS-1); //Note: Ward_Elbereth is 0x1L, and does nothing.
}
break;
@ -918,12 +965,15 @@ struct obj *scroll;
You("suddenly know secret combat techniques!");
combat = TRUE;
}
xp += 1000;
u.uhitinc = min_ints(100, u.uhitinc+d(1,2));
u.udaminc = min_ints(100, u.udaminc+d(1,2));
u.uacinc = min_ints(100, u.uacinc+d(1,2));
break;
}
}
more_experienced(xp, 0);
newexplevel();
}
}
} else if(scroll->otyp >= ANTI_CLOCKWISE_METAMORPHOSIS_G && scroll->otyp <= ORRERY_GLYPH) {
@ -1202,7 +1252,9 @@ int curse_bless;
}
} else if (obj->oclass == TOOL_CLASS || is_blaster(obj)
|| obj->otyp == DWARVISH_HELM || is_vibroweapon(obj)) {
|| obj->otyp == DWARVISH_HELM || obj->otyp == LANTERN_PLATE_MAIL
|| is_vibroweapon(obj)
) {
int rechrg = (int)obj->recharged;
if (objects[obj->otyp].oc_charged) {
@ -1260,8 +1312,9 @@ int curse_bless;
case DWARVISH_HELM:
case OIL_LAMP:
case LANTERN:
case LANTERN_PLATE_MAIL:
if (is_cursed) {
if (obj->otyp == DWARVISH_HELM) {
if (obj->otyp == DWARVISH_HELM && obj->otyp != LANTERN_PLATE_MAIL) {
/* Don't affect the +/- of the helm */
obj->age = 0;
}
@ -1273,7 +1326,7 @@ int curse_bless;
end_burn(obj, TRUE);
}
} else if (is_blessed) {
if (obj->otyp != DWARVISH_HELM) {
if (obj->otyp != DWARVISH_HELM && obj->otyp != LANTERN_PLATE_MAIL) {
obj->spe = 1;
}
obj->age = 1500;
@ -1908,7 +1961,7 @@ struct obj *sobj;
otmp->otyp - GRAY_DRAGON_SCALES;
otmp->objsize = youracedata->msize;
otmp->bodytypeflag = youracedata->mflagsb&MB_BODYTYPEMASK;
set_obj_shape(otmp, youracedata->mflagsb);
otmp->cursed = 0;
if (sobj->blessed) {
@ -3513,17 +3566,20 @@ boolean revival;
* than a mimic; this behavior quirk is useful so don't "fix" it...
*/
struct monst *
create_particular(specify_attitude, specify_derivation, allow_multi, ma_require, mg_restrict, gen_restrict)
create_particular(x, y, specify_attitude, specify_derivation, allow_multi, ma_require, mg_restrict, gen_restrict, in_buff)\
int x,y;
unsigned long specify_attitude; // -1 -> true; 0 -> false; >0 -> as given
int specify_derivation; // -1 -> true; 0 -> false; >0 -> as given
int allow_multi;
unsigned long ma_require;
unsigned long mg_restrict;
int gen_restrict;
char *in_buff;
{
char buf[BUFSZ], *bufp, *p, *q, monclass = MAXMCLASSES;
int which, tries, i;
int undeadtype = 0;
boolean mad_suicidal = FALSE;
struct permonst *whichpm;
struct monst *mtmp = (struct monst *)0;
boolean madeany = FALSE;
@ -3534,8 +3590,13 @@ int gen_restrict;
do {
which = urole.malenum; /* an arbitrary index into mons[] */
maketame = makeloyal = makepeaceful = makehostile = makesummoned = FALSE;
getlin("Create what kind of monster? [type the name or symbol]",
buf);
if(in_buff){
Sprintf(buf, "%s", in_buff);
}
else {
getlin("Create what kind of monster? [type the name or symbol]",
buf);
}
bufp = mungspaces(buf);
if (*bufp == '\033') return (struct monst *)0;
@ -3610,6 +3671,9 @@ int gen_restrict;
else if (!strncmpi(bufp, "moly-", l = 5)) {
undeadtype = MOLY_TEMPLATE;
}
else if (!strncmpi(bufp, "suicidal ", l = 9)) {
mad_suicidal = TRUE;
}
else
break;
@ -3662,6 +3726,12 @@ int gen_restrict;
undeadtype = WORLD_SHAPER;
else if (!strncmpi(p, "husk", 4))
undeadtype = MINDLESS;
else if (!strncmpi(p, "infectee", 8))
undeadtype = SPORE_ZOMBIE;
else if (!strncmpi(p, "cordyceps", 9))
undeadtype = CORDYCEPS;
else if (!strncmpi(p, "plague-victim", 13))
undeadtype = PLAGUE_TEMPLATE;
else
{
/* no suffix was used, undo the split made to search for suffixes */
@ -3699,6 +3769,11 @@ int gen_restrict;
if (monclass == MAXMCLASSES)
{
pline("I've never heard of such monsters.");
if(in_buff){
impossible("Bad parsed monster name in sp_lev");
tries = 5;
break;
}
continue; //try again
}
if (monclass == S_MIMIC_DEF && !(ma_require || mg_restrict || gen_restrict)) // bugfeature made feature
@ -3770,7 +3845,7 @@ createmon:
if (makesummoned)
mm_flags |= MM_ESUM;
mtmp = makemon_full(whichpm, u.ux, u.uy, mm_flags, undeadtype ? undeadtype : -1, -1);
mtmp = makemon_full(whichpm, x, y, mm_flags, undeadtype ? undeadtype : -1, -1);
if (mtmp) {
if (maketame){
@ -3787,6 +3862,9 @@ createmon:
if (makesummoned)
mark_mon_as_summoned(mtmp, (struct monst *)0, ESUMMON_PERMANENT, 0);
if (mad_suicidal)
mtmp->msuicide = TRUE;
madeany = TRUE;
newsym(mtmp->mx, mtmp->my);
}

View file

@ -1042,19 +1042,20 @@ boolean ghostly;
register struct monst *mtmp2;
for (mtmp = fmon; mtmp; mtmp = mtmp2) {
mtmp2 = mtmp->nmon;
if (ghostly) {
/* reset peaceful/malign relative to new character */
if(!mtmp->isshk)
/* shopkeepers will reset based on name */
mtmp->mpeaceful = peace_minded(mtmp->data);
set_malign(mtmp);
} else if (monstermoves > omoves)
mon_catchup_elapsed_time(mtmp, monstermoves - omoves);
mtmp2 = mtmp->nmon;
if (ghostly) {
/* reset peaceful/malign relative to new character */
if(!mtmp->isshk)
/* shopkeepers will reset based on name */
mtmp->mpeaceful = peace_minded(mtmp->data);
set_malign(mtmp);
} else if (monstermoves > omoves){
mon_catchup_elapsed_time(mtmp, monstermoves - omoves);
/* update shape-changers in case protection against
them is different now than when the level was saved */
restore_cham(mtmp);
/* update shape-changers in case protection against
them is different now than when the level was saved */
restore_cham(mtmp);
}
}
//Note: in case there's a bones file or other fail.
if(u.silver_flame_z.dnum == u.uz.dnum && u.silver_flame_z.dlevel == u.uz.dlevel

View file

@ -199,14 +199,14 @@ struct Role roles[] = {
PM_HIPPOCRATES, PM_ATTENDANT, PM_CYCLOPS,
PM_GIANT_RAT, PM_SNAKE, S_RODENT, S_YETI,
ART_STAFF_OF_AESCULAPIUS,
MA_HUMAN|MA_GNOME|MA_FEY, ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
MA_HUMAN|MA_ELF|MA_GNOME|MA_FEY, ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
/* Str Int Wis Dex Con Cha */
{ 7, 7, 13, 7, 11, 16 },
{ 15, 20, 20, 15, 25, 5 },
{ 7, 13, 11, 7, 11, 16 },
{ 5, 30, 20, 15, 25, 5 },
/* Init Lower Higher */
{ 11, 0, 0, 8, 1, 0 }, /* Hit points */
{ 1, 4, 1, 2, 0, 3 },20, /* Energy */
10, 3,-3, 2, 10, A_WIS, SPE_FULL_HEALING, -14
10, 3,-3, 2, 10, A_INT, SPE_FULL_HEALING, -14
},
{ {"Knight", 0}, {
{"Gallant", 0},
@ -1986,7 +1986,7 @@ int newgame;
}
if(flags.stag == 0){
urole.homebase = "Erelhei-Cinlu";
urole.homebase = "Menzoberranzan";
urole.intermed = "the drider caves";
urole.questarti = ART_SILVER_STARLIGHT;
@ -2000,7 +2000,7 @@ int newgame;
urole.enemy2sym = S_LAW_ANGEL;
} else {
urole.homebase = "the Grove of Eilistraee";
urole.intermed = "Erelhei-Cinlu";
urole.intermed = "Menzoberranzan";
urole.questarti = ART_TENTACLE_ROD;
urole.ldrnum = PM_SEYLL_AUZKOVYN;
@ -2068,6 +2068,27 @@ int newgame;
}
}
}
} else if(Race_if(PM_DROW) && Role_if(PM_HEALER)){
urole.filecode = "Dhl";
urole.lgod = GOD_ILMATER;
urole.ngod = GOD_PEN_A;
urole.cgod = GOD_GHAUNADAUR;
urole.homebase = "Ceiling District";/*Menzoberranzan*/
urole.intermed = "Floor District";
urole.questarti = ART_ESSCOOAHLIPBOOURRR; /*Steals items and stores them weightlessly, but can only be accessed via #invoke. Deals bonus damage with repeated hits.*/
urole.ldrnum = PM_SHUUSHAR_THE_ENLIGHTENED;
urole.guardnum = PM_ALLIANCE_VANGUARD; /*Also drow commoners*/
urole.neminum = PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH; /*Chuul/drow grab and steal magic items. Demogorgon cultists? Madness causes victims to imagine different natural attacks for themselves*/
urole.enemy1num = PM_DUERGAR;
urole.enemy2num = PM_KUO_TOA;
urole.enemy1sym = S_HUMANOID;
urole.enemy2sym = S_HUMANOID;
for(int i = 0; i<6; i++){
dungeons[quest_dnum].connect_side[i] = !rn2(3) ? CONNECT_LEFT : rn2(2) ? CONNECT_CENT : CONNECT_RGHT;
}
} else if((Race_if(PM_ELF) || Pantheon_if(PM_ELF)) && (Role_if(PM_RANGER) || Role_if(PM_WIZARD) || Role_if(PM_NOBLEMAN))){
flags.racial_pantheon = PM_ELF;
urole.filecode = "Elf";

View file

@ -77,7 +77,7 @@ struct attack *mattk;
)
return 0;
if(pagr->mtyp == PM_SMALL_GOAT_SPAWN || pagr->mtyp == PM_GOAT_SPAWN || pagr->mtyp == PM_GIANT_GOAT_SPAWN || has_template(magr, MISTWEAVER) || pagr->mtyp == PM_PHANTASM || pagr->mtyp == PM_BEAUTEOUS_ONE)
if(pagr->mtyp == PM_SMALL_GOAT_SPAWN || pagr->mtyp == PM_GOAT_SPAWN || pagr->mtyp == PM_GIANT_GOAT_SPAWN || pagr->mtyp == PM_BLESSED || has_template(magr, MISTWEAVER) || pagr->mtyp == PM_PHANTASM || pagr->mtyp == PM_BEAUTEOUS_ONE)
return 1;
if(pagr->mlet == S_NYMPH || pagr->mtyp == PM_INCUBUS || pagr->mtyp == PM_SUCCUBUS
@ -2327,15 +2327,16 @@ int *result;
int nitems = 0;
boolean goatspawn = (magr->data->mtyp == PM_SMALL_GOAT_SPAWN || magr->data->mtyp == PM_GOAT_SPAWN || magr->data->mtyp == PM_GIANT_GOAT_SPAWN || magr->data->mtyp == PM_BLESSED);
boolean noflee = (magr->isshk && magr->mpeaceful);
boolean mi_only = is_chuul(magr->data);
if(attk->adtyp == AD_SITM){
/* select item from defender's inventory */
for (otmp = mdef->minvent; otmp; otmp = otmp->nobj)
if ((!magr->mtame || !otmp->cursed) && !(otmp->owornmask&equipmentmask))
if ((!magr->mtame || !otmp->cursed) && !(otmp->owornmask&equipmentmask) && (!mi_only || is_magic_obj(otmp)))
nitems++;
if(nitems){
nitems = rnd(nitems);
for (otmp = mdef->minvent; otmp; otmp = otmp->nobj)
if ((!magr->mtame || !otmp->cursed) && !(otmp->owornmask&equipmentmask))
if ((!magr->mtame || !otmp->cursed) && !(otmp->owornmask&equipmentmask) && (!mi_only || is_magic_obj(otmp)))
if(--nitems <= 0)
break;
}

View file

@ -588,6 +588,9 @@ register struct monst *mtmp;
case MS_WAIL:
ret = "wail";
break;
case MS_RIBBIT:
ret = "croak";
break;
case MS_SILENT:
ret = "commotion";
break;
@ -622,9 +625,10 @@ register struct monst *mtmp;
/* the sounds of mistreated pets */
void
yelp(mtmp)
register struct monst *mtmp;
struct monst *mtmp;
{
register const char *yelp_verb = 0;
const char *yelp_verb = 0;
const char *yelp_modifier = 0;
if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->mnotlaugh || !mtmp->data->msound)
return;
@ -655,9 +659,16 @@ register struct monst *mtmp;
case MS_WAIL:
yelp_verb = "wail";
break;
case MS_RIBBIT:
yelp_verb = "peep";
break;
case MS_COUGH:
yelp_verb = "cough";
yelp_modifier = " paroxysmally";
break;
}
if (yelp_verb) {
pline("%s %s!", Monnam(mtmp), vtense((char *)0, yelp_verb));
pline("%s %s%s!", Monnam(mtmp), vtense((char *)0, yelp_verb), yelp_modifier ? yelp_modifier : "");
if(flags.run) nomul(0, NULL);
wake_nearto_noisy(mtmp->mx, mtmp->my, mtmp->data->mlevel * 12);
}
@ -796,17 +807,37 @@ boolean chatting;
}
}
}
switch (
is_silent_mon(mtmp) ? MS_SILENT :
(is_dollable(mtmp->data) && mtmp->m_insight_level) ? MS_STATS :
mtmp->ispriest ? MS_PRIEST :
mtmp->isshk ? MS_SELL :
(mtmp->mtyp == PM_RHYMER && !mtmp->mspec_used) ? MS_SONG :
mtmp->mfaction == QUEST_FACTION ? MS_GUARDIAN :
mtmp->mtyp == urole.guardnum ? MS_GUARDIAN :
(ptr->msound == MS_CUSS && mtmp->mpeaceful) ? MS_HUMANOID :
ptr->msound
) {
int soundtype = ptr->msound;
//Faction and special abilities adjustment
if(mtmp->mtyp == PM_RHYMER && !mtmp->mspec_used)
soundtype = MS_SONG;
else if(mtmp->mfaction == QUEST_FACTION)
soundtype = MS_GUARDIAN;
else if(mtmp->mtyp == urole.guardnum)
soundtype = MS_GUARDIAN;
else if(ptr->msound == MS_CUSS && mtmp->mpeaceful)
soundtype = MS_HUMANOID;
//Don't sing if chatted to.
if(chatting && (soundtype == MS_SONG || soundtype == MS_OONA)){
if(mtmp->mfaction == QUEST_FACTION)
soundtype = MS_GUARDIAN;
if(mtmp->mtyp == urole.guardnum)
soundtype = MS_GUARDIAN;
else soundtype = MS_HUMANOID;
}
//Template and profession adjustments
if(is_silent_mon(mtmp))
soundtype = MS_SILENT;
else if(is_dollable(mtmp->data) && mtmp->m_insight_level)
soundtype = MS_STATS;
else if(mtmp->ispriest)
soundtype = MS_PRIEST;
else if(mtmp->isshk)
soundtype = MS_SELL;
switch (soundtype) {
case MS_ORACLE:
return doconsult(mtmp);
case MS_PRIEST: /*Most (all?) things with this will have ispriest set*/
@ -1000,9 +1031,44 @@ asGuardian:
case MS_GURGLE:
pline_msg = "gurgles.";
break;
case MS_RIBBIT:
pline_msg = mtmp->mpeaceful ? "ribbits." : "croaks.";
break;
case MS_BURBLE:
pline_msg = "burbles.";
break;
case MS_COUGH:
if (mtmp->mflee)
pline_msg = "coughs frantically.";
else if ((get_mx(mtmp, MX_EDOG) && moves > EDOG(mtmp)->hungrytime) || mtmp->mhp*10 < mtmp->mhpmax)
pline_msg = "coughs weakly.";
else switch(rn2(10)){
default:
pline_msg = "coughs spasmodically.";
break;
case 0:
pline_msg = "coughs wetly.";
break;
case 1:
pline_msg = "groans weakly.";
break;
case 2:
pline_msg = "mumbles incoherently.";
break;
case 3:
pline_msg = "coughs.";
break;
case 4:
pline_msg = "coughs dryly.";
break;
case 5:
pline_msg = "coughs up blood.";
break;
case 6:
pline_msg = "vomits.";
break;
}
break;
case MS_JUBJUB:{
struct monst *tmpm;
if(!(mtmp->mspec_used || mtmp->mcan)){
@ -2357,6 +2423,8 @@ static const short command_chain[][2] = {
{ PM_JUSTICE_ARCHON, PM_RAZIEL }, { PM_SWORD_ARCHON, PM_RAZIEL }, { PM_SHIELD_ARCHON, PM_RAZIEL },
{ PM_PLAINS_CENTAUR, PM_CENTAUR_CHIEFTAIN }, { PM_FOREST_CENTAUR, PM_CENTAUR_CHIEFTAIN }, { PM_MOUNTAIN_CENTAUR, PM_CENTAUR_CHIEFTAIN },
{ PM_MIGO_WORKER, PM_MIGO_SOLDIER }, { PM_MIGO_SOLDIER, PM_MIGO_PHILOSOPHER }, { PM_MIGO_PHILOSOPHER, PM_MIGO_QUEEN },
{ PM_SOLDIER, PM_SERGEANT }, { PM_SERGEANT, PM_LIEUTENANT }, { PM_LIEUTENANT, PM_CAPTAIN },
@ -2499,7 +2567,7 @@ struct monst * commander;
if (!clear_path(mtmp->mx, mtmp->my, commander->mx, commander->my)
|| (mtmp == commander)
|| !mon_in_command_chain(mtmp, commander)
|| !(mtmp->mpeaceful == commander->mpeaceful && mtmp->mtame == commander->mtame))
|| !(mtmp->mpeaceful == commander->mpeaceful && !mtmp->mtame == !commander->mtame))
continue;
tmp = d(nd, sd);

View file

@ -843,78 +843,96 @@ struct mkroom *croom;
struct permonst *pm;
unsigned g_mvflags;
boolean parsed = m->class=='#';
if (rn2(100) < m->chance) {
if (m->class >= 0)
class = (char) def_char_to_monclass((char)m->class);
else if (m->class > -11)
class = (char) def_char_to_monclass(rmonst[- m->class - 1]);
else
class = 0;
if (class == MAXMCLASSES)
panic("create_monster: unknown monster class '%c'", m->class);
if(m->align == AM_SPLEV_CO)
alignment = galign(u.ugodbase[UGOD_ORIGINAL]);
else if(m->align == AM_SPLEV_NONCO){
alignment = noncoalignment(galign(u.ugodbase[UGOD_ORIGINAL]));
}
else if(m->align <= -11)
alignment = induced_align(80);
else if(m->align < 0)
alignment = Amask2align(ralign[-m->align-1]);
else
alignment = Amask2align(m->align);
if (!class)
pm = (struct permonst *) 0;
else if (m->id != NON_PM) {
pm = &mons[m->id];
g_mvflags = (unsigned) mvitals[monsndx(pm)].mvflags;
if ((pm->geno & G_UNIQ) && (g_mvflags & G_EXTINCT))
goto m_done;
else if (g_mvflags & G_GONE && !In_quest(&u.uz)) /* genocided or extinct */
pm = (struct permonst *) 0; /* make random monster */
} else {
pm = mkclass(class,Inhell ? G_HELL : G_NOHELL);
/* if we can't get a specific monster type (pm == 0) then the
class has been genocided, so settle for a random monster */
}
/* reduce quantity of peacefuls in the Mines */
if (In_mines(&u.uz) && pm && your_race(pm) &&
(Race_if(PM_DWARF) || Race_if(PM_GNOME)) && rn2(3))
pm = (struct permonst *) 0;
/* replace priests with angels on Binder's Astral */
if (Role_if(PM_EXILE) && on_level(&u.uz, &astral_level) && m->id == PM_ALIGNED_PRIEST) {
pm = &mons[PM_ANGEL];
}
x = m->x;
y = m->y;
if (croom)
get_room_loc(&x, &y, croom);
else {
if (!pm || !species_swims(pm))
if(parsed){
x = m->x;
y = m->y;
if (croom)
get_room_loc(&x, &y, croom);
else {
get_location(&x, &y, DRY);
else if (pm->mlet == S_EEL)
get_location(&x, &y, WET);
else
get_location(&x, &y, DRY|WET);
}
// /* try to find a close place if someone else is already there */
// if (MON_AT(x,y) && enexto(&cc, x, y, pm))
// x = cc.x, y = cc.y;
mtmp = create_particular(x, y, -1, -1, TRUE, 0, 0, 0, m->name.str);
if (mtmp)
pm = mtmp->data;
} else {
if (m->class >= 0)
class = (char) def_char_to_monclass((char)m->class);
else if (m->class > -11)
class = (char) def_char_to_monclass(rmonst[- m->class - 1]);
else
class = 0;
if (class == MAXMCLASSES)
panic("create_monster: unknown monster class '%c'", m->class);
if(m->align == AM_SPLEV_CO)
alignment = galign(u.ugodbase[UGOD_ORIGINAL]);
else if(m->align == AM_SPLEV_NONCO){
alignment = noncoalignment(galign(u.ugodbase[UGOD_ORIGINAL]));
}
else if(m->align <= -11)
alignment = induced_align(80);
else if(m->align < 0)
alignment = Amask2align(ralign[-m->align-1]);
else
alignment = Amask2align(m->align);
if (!class)
pm = (struct permonst *) 0;
else if (m->id != NON_PM) {
pm = &mons[m->id];
g_mvflags = (unsigned) mvitals[monsndx(pm)].mvflags;
if ((pm->geno & G_UNIQ) && (g_mvflags & G_EXTINCT))
goto m_done;
else if (g_mvflags & G_GONE && !In_quest(&u.uz)) /* genocided or extinct */
pm = (struct permonst *) 0; /* make random monster */
} else {
pm = mkclass(class,Inhell ? G_HELL : G_NOHELL);
/* if we can't get a specific monster type (pm == 0) then the
class has been genocided, so settle for a random monster */
}
/* reduce quantity of peacefuls in the Mines */
if (In_mines(&u.uz) && pm && your_race(pm) &&
(Race_if(PM_DWARF) || Race_if(PM_GNOME)) && rn2(3))
pm = (struct permonst *) 0;
/* replace priests with angels on Binder's Astral */
if (Role_if(PM_EXILE) && on_level(&u.uz, &astral_level) && m->id == PM_ALIGNED_PRIEST) {
pm = &mons[PM_ANGEL];
}
x = m->x;
y = m->y;
if (croom)
get_room_loc(&x, &y, croom);
else {
if (!pm || !species_swims(pm))
get_location(&x, &y, DRY);
else if (pm->mlet == S_EEL)
get_location(&x, &y, WET);
else
get_location(&x, &y, DRY|WET);
}
/* try to find a close place if someone else is already there */
if (MON_AT(x,y) && enexto(&cc, x, y, pm))
x = cc.x, y = cc.y;
if(m->align != -12)
mtmp = mk_roamer(pm, alignment, x, y, m->peaceful);
else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD)
mtmp = mk_mplayer(pm, x, y, FALSE);
else mtmp = makemon(pm, x, y, NO_MM_FLAGS);
}
/* try to find a close place if someone else is already there */
if (MON_AT(x,y) && enexto(&cc, x, y, pm))
x = cc.x, y = cc.y;
if(m->align != -12)
mtmp = mk_roamer(pm, alignment, x, y, m->peaceful);
else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD)
mtmp = mk_mplayer(pm, x, y, FALSE);
else mtmp = makemon(pm, x, y, NO_MM_FLAGS);
if (mtmp) {
/* handle specific attributes for some special monsters */
if (m->name.str) mtmp = christen_monst(mtmp, m->name.str);
if (m->name.str && !parsed) mtmp = christen_monst(mtmp, m->name.str);
/*
* This is currently hardwired for mimics only. It should
@ -1308,60 +1326,236 @@ default_case:
}
otmp->spe = 0;
}
if(otmp->otyp == CHAIN && otmp->where == OBJ_FLOOR && In_quest(&u.uz) && u.uz.dlevel == nemesis_level.dlevel && urole.neminum == PM_NECROMANCER){
int mtyp;
boolean polyps;
if(otmp->otyp == BEDROLL && otmp->spe == 2 && otmp->where == OBJ_FLOOR){
int plague_types[] = {PM_HOBBIT, PM_DWARF, PM_BUGBEAR, PM_DWARF_LORD, PM_DWARF_CLERIC,
PM_DWARF_QUEEN, PM_DWARF_KING, PM_DEEP_ONE, PM_IMP, PM_QUASIT, PM_WINGED_KOBOLD,
PM_DRYAD, PM_NAIAD, PM_OREAD, PM_DEMINYMPH, PM_THRIAE, PM_HILL_ORC, PM_ORC_SHAMAN,
PM_ORC_CAPTAIN, PM_JUSTICE_ARCHON, PM_SHIELD_ARCHON, PM_SWORD_ARCHON,
PM_MOVANIC_DEVA, PM_MONADIC_DEVA, PM_ASTRAL_DEVA, PM_LILLEND, PM_COURE_ELADRIN,
PM_NOVIERE_ELADRIN, PM_BRALANI_ELADRIN, PM_FIRRE_ELADRIN, PM_SHIERE_ELADRIN,
PM_CHIROPTERAN, PM_PLAINS_CENTAUR, PM_FOREST_CENTAUR, PM_MOUNTAIN_CENTAUR,
PM_DRIDER, PM_FORMIAN_CRUSHER, PM_FORMIAN_TASKMASTER, PM_MYRMIDON_HOPLITE,
PM_MYRMIDON_LOCHIAS, PM_MYRMIDON_YPOLOCHAGOS, PM_MYRMIDON_LOCHAGOS,
PM_GNOME, PM_GNOME_LORD, PM_GNOME_LADY, PM_TINKER_GNOME, PM_GNOME_KING, PM_GNOME_QUEEN,
PM_HILL_GIANT, PM_MINOTAUR, PM_MINOTAUR_PRIESTESS,
PM_VAMPIRE, PM_VAMPIRE_LORD, PM_VAMPIRE_LADY,
PM_PEASANT, PM_NURSE, PM_WATCHMAN, PM_WATCH_CAPTAIN,
PM_WOODLAND_ELF, PM_GREEN_ELF, PM_GREY_ELF, PM_ELF_LORD, PM_ELF_LADY, PM_ELVENKING, PM_ELVENQUEEN,
PM_DROW_CAPTAIN, PM_HEDROW_WIZARD,
PM_HORNED_DEVIL, PM_SUCCUBUS, PM_INCUBUS, PM_ERINYS, PM_VROCK, PM_BARBED_DEVIL,
PM_LILITU,
PM_BARBARIAN, PM_HALF_DRAGON, PM_BARD, PM_HEALER, PM_RANGER, PM_VALKYRIE,
PM_SMALL_GOAT_SPAWN, PM_GOAT_SPAWN, PM_GIANT_GOAT_SPAWN
};
struct monst *mon;
int prisoners[] = {
PM_ELF_LORD, PM_ELF_LADY, PM_GREY_ELF, PM_GREY_ELF,
PM_HEDROW_BLADEMASTER, PM_DROW_CAPTAIN, PM_DROW_MATRON, PM_UNEARTHLY_DROW,
PM_DWARF_CLERIC, PM_DWARF_LORD, PM_DWARF_QUEEN, PM_DWARF_KING,
PM_RANGER, PM_RANGER, PM_WIZARD, PM_KNIGHT, PM_KNIGHT, PM_VALKYRIE,
PM_DEMINYMPH, PM_DEMINYMPH,
PM_SWORD_ARCHON, PM_SHIELD_ARCHON, PM_TRUMPET_ARCHON,
PM_ASTRAL_DEVA, PM_GRAHA_DEVA,
PM_LILLEND, PM_ALEAX,
PM_COURE_ELADRIN, PM_NOVIERE_ELADRIN, PM_BRALANI_ELADRIN, PM_FIRRE_ELADRIN, PM_SHIERE_ELADRIN, PM_GHAELE_ELADRIN, PM_TULANI_ELADRIN, PM_DRACAE_ELADRIN,
PM_TITAN,
PM_ERINYS, PM_LILITU, PM_DAUGHTER_OF_BEDLAM, PM_ICE_DEVIL, PM_MARILITH, PM_PIT_FIEND, PM_FALLEN_ANGEL
};
mtyp = ROLL_FROM(prisoners);
if(mtyp == PM_DRACAE_ELADRIN){
if(dungeon_topology.eprecursor_typ != PRE_DRACAE){
mtyp = PM_TULANI_ELADRIN;
}
if(dungeon_topology.eprecursor_typ == PRE_POLYP){
polyps = TRUE;
}
}
if(mtyp == PM_TULANI_ELADRIN){
switch(dungeon_topology.alt_tulani){
case GAE_CASTE:
mtyp = PM_GAE_ELADRIN;
break;
case BRIGHID_CASTE:
mtyp = PM_BRIGHID_ELADRIN;
break;
case UISCERRE_CASTE:
mtyp = PM_UISCERRE_ELADRIN;
break;
case CAILLEA_CASTE:
mtyp = PM_CAILLEA_ELADRIN;
break;
}
}
mon = makemon(&mons[mtyp], otmp->ox, otmp->oy, MM_GOODEQUIP);
if(mon && polyps){
mon->ispolyp = TRUE;
mongets(mon, MASK, NO_MKOBJ_FLAGS);
mongets(mon, MASK, NO_MKOBJ_FLAGS);
mongets(mon, MASK, NO_MKOBJ_FLAGS);
mongets(mon, MASK, NO_MKOBJ_FLAGS);
mongets(mon, MASK, NO_MKOBJ_FLAGS);
}
mon = makemon_full(&mons[ROLL_FROM(plague_types)], otmp->ox, otmp->oy, NO_MINVENT, PLAGUE_TEMPLATE, -1);
if(mon){
(void)mongets(mon, SHACKLES, NO_MKOBJ_FLAGS);
mon->entangled = SHACKLES;
mon->mpeaceful = 1;
set_malign(mon);
}
otmp->spe = 0;
}
if(otmp->otyp == BEDROLL && otmp->spe == 3 && otmp->where == OBJ_FLOOR){
int drow_types[] = {
PM_SPROW, PM_DRIDER, PM_SPROW, PM_DRIDER,
PM_ANULO, PM_ANULO,
PM_DROW_CAPTAIN, PM_DROW_CAPTAIN, PM_DROW_CAPTAIN, PM_DROW_CAPTAIN,
PM_HEDROW_WARRIOR, PM_HEDROW_WIZARD, PM_HEDROW_WARRIOR, PM_HEDROW_WIZARD,
PM_DROW_MATRON, PM_DROW_MATRON,
PM_UNEARTHLY_DROW
};
int other_types[] = {PM_HOBBIT, PM_BUGBEAR, PM_GNOLL,
PM_HILL_ORC, PM_ORC_SHAMAN, PM_ORC_CAPTAIN,
PM_JUSTICE_ARCHON, PM_MOVANIC_DEVA, PM_LILLEND, PM_COURE_ELADRIN,
PM_CHIROPTERAN, PM_CHIROPTERAN,
PM_STONE_GIANT, PM_HILL_GIANT, PM_FIRE_GIANT, PM_FROST_GIANT,
PM_MINOTAUR, PM_MINOTAUR_PRIESTESS,
PM_WOODLAND_ELF, PM_GREEN_ELF, PM_ELF_LORD, PM_ELF_LADY,
PM_PRISONER, PM_PRISONER, PM_PRISONER,
PM_HORNED_DEVIL, PM_ERINYS, PM_BARBED_DEVIL,
PM_SUCCUBUS, PM_INCUBUS, PM_VROCK, PM_LILITU, PM_NALFESHNEE, PM_MARILITH,
PM_HALF_DRAGON, PM_BARD, PM_CONVICT, PM_KNIGHT, PM_TOURIST, PM_VALKYRIE
};
struct monst *mon;
if(rn2(3))
mon = makemon_full(&mons[ROLL_FROM(drow_types)], otmp->ox, otmp->oy, NO_MINVENT, PLAGUE_TEMPLATE, -1);
else
mon = makemon_full(&mons[ROLL_FROM(other_types)], otmp->ox, otmp->oy, NO_MINVENT, PLAGUE_TEMPLATE, -1);
if(mon){
mon->mpeaceful = 1;
set_malign(mon);
}
otmp->spe = 0;
}
if(otmp->otyp == CHAIN && otmp->where == OBJ_FLOOR && In_quest(&u.uz)){
if(urole.neminum == PM_CYCLOPS){
int plague_types[] = {
PM_DWARF_LORD, PM_DWARF_CLERIC, PM_DWARF_QUEEN, PM_DWARF_KING,
PM_DEEP_ONE, PM_WINGED_KOBOLD,
PM_DEMINYMPH, PM_THRIAE,
PM_ORC_CAPTAIN, PM_JUSTICE_ARCHON, PM_SHIELD_ARCHON, PM_SWORD_ARCHON,
PM_MOVANIC_DEVA, PM_MONADIC_DEVA, PM_ASTRAL_DEVA, PM_LILLEND, PM_COURE_ELADRIN,
PM_NOVIERE_ELADRIN, PM_BRALANI_ELADRIN, PM_FIRRE_ELADRIN, PM_SHIERE_ELADRIN,
PM_CENTAUR_CHIEFTAIN,
PM_DRIDER, PM_FORMIAN_CRUSHER, PM_FORMIAN_TASKMASTER,
PM_MYRMIDON_YPOLOCHAGOS, PM_MYRMIDON_LOCHAGOS,
PM_GNOME_KING, PM_GNOME_QUEEN,
PM_HILL_GIANT, PM_MINOTAUR, PM_MINOTAUR_PRIESTESS,
PM_VAMPIRE, PM_VAMPIRE_LORD, PM_VAMPIRE_LADY,
PM_NURSE, PM_WATCH_CAPTAIN,
PM_GREY_ELF, PM_ELF_LORD, PM_ELF_LADY, PM_ELVENKING, PM_ELVENQUEEN,
PM_DROW_MATRON,
PM_HORNED_DEVIL, PM_SUCCUBUS, PM_INCUBUS, PM_ERINYS, PM_VROCK, PM_BARBED_DEVIL,
PM_LILITU,
PM_BARBARIAN, PM_HALF_DRAGON, PM_BARD, PM_HEALER, PM_RANGER, PM_VALKYRIE,
PM_GOAT_SPAWN, PM_GIANT_GOAT_SPAWN
};
struct monst *mon;
mon = makemon(&mons[ROLL_FROM(plague_types)], otmp->ox, otmp->oy, NO_MINVENT);
if(mon){
//Note: these are "fresh" so they don't take the 1/3rd penalty to level
set_template(mon, PLAGUE_TEMPLATE);
mon->mpeaceful = 1;
set_malign(mon);
}
otmp->spe = 0;
}
else if(urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH){
if(otmp->spe == 0){
int sacc_types[] = {
PM_DWARF_LORD, PM_DWARF_CLERIC, PM_DWARF_QUEEN, PM_DWARF_KING,
PM_DEMINYMPH, PM_THRIAE,
PM_ELF_LORD, PM_ELF_LADY, PM_ELVENKING, PM_ELVENQUEEN,
PM_DROW_MATRON,
PM_BARBARIAN, PM_HALF_DRAGON, PM_VALKYRIE
};
struct monst *mon;
mon = makemon(&mons[ROLL_FROM(sacc_types)], otmp->ox, otmp->oy, NO_MM_FLAGS);
if(mon){
(void)mongets(mon, SHACKLES, NO_MKOBJ_FLAGS);
mon->entangled = SHACKLES;
//Note: these are "fresh" so they don't take the 1/3rd penalty to level
set_template(mon, PLAGUE_TEMPLATE);
mon->mpeaceful = 1;
set_malign(mon);
}
}
else if(otmp->spe == 1){
int prison2_types[] = {
PM_SWORD_ARCHON, PM_TRUMPET_ARCHON, PM_PANAKEIAN_ARCHON, PM_HYGIEIAN_ARCHON,
PM_ASTRAL_DEVA, PM_GRAHA_DEVA,
PM_LILLEND,
PM_COURE_ELADRIN, PM_NOVIERE_ELADRIN, PM_BRALANI_ELADRIN, PM_FIRRE_ELADRIN, PM_SHIELD_ARCHON, PM_GHAELE_ELADRIN, PM_TULANI_ELADRIN
};
struct monst *mon;
mon = makemon(&mons[ROLL_FROM(prison2_types)], otmp->ox, otmp->oy, MM_GOODEQUIP);
if(mon){
(void)mongets(mon, SHACKLES, NO_MKOBJ_FLAGS);
mon->entangled = SHACKLES;
//Note: these are "fresh" so they don't take the 1/3rd penalty to level
set_template(mon, PLAGUE_TEMPLATE);
mon->mpeaceful = 1;
set_malign(mon);
}
}
else if(otmp->spe == 2){
int drowplague3_types[] = {
PM_DROW_CAPTAIN, PM_DROW_CAPTAIN, PM_DROW_CAPTAIN, PM_DROW_CAPTAIN,
PM_HEDROW_WARRIOR, PM_HEDROW_WIZARD, PM_HEDROW_WARRIOR, PM_HEDROW_WIZARD,
PM_DROW_MATRON, PM_DROW_MATRON,
PM_UNEARTHLY_DROW
};
int plague3_types[] = {
PM_HOUSELESS_DROW, PM_HOUSELESS_DROW,
PM_HOUSELESS_DROW, PM_HOUSELESS_DROW,
PM_ANULO, PM_ANULO,
PM_SPROW, PM_DRIDER, PM_SPROW, PM_DRIDER,
PM_PRIESTESS_OF_GHAUNADAUR, PM_MENDICANT_DRIDER, PM_MENDICANT_SPROW,
PM_PEN_A_MENDICANT,
PM_DWARF_LORD, PM_DWARF_CLERIC, PM_DWARF_QUEEN, PM_DWARF_KING,
PM_DEMINYMPH, PM_ORC_CAPTAIN,
PM_DRIDER,
PM_GNOME_KING, PM_GNOME_QUEEN,
PM_HILL_GIANT, PM_MINOTAUR, PM_MINOTAUR_PRIESTESS,
PM_WOODLAND_ELF, PM_GREEN_ELF, PM_GREY_ELF, PM_ELF_LORD, PM_ELF_LADY, PM_ELVENKING, PM_ELVENQUEEN
};
struct monst *mon;
if(rn2(3)){
mon = makemon_full(&mons[ROLL_FROM(drowplague3_types)], otmp->ox, otmp->oy, NO_MM_FLAGS, PLAGUE_TEMPLATE, -1);
}
else {
mon = makemon_full(&mons[ROLL_FROM(plague3_types)], otmp->ox, otmp->oy, NO_MM_FLAGS, PLAGUE_TEMPLATE, -1);
}
if(mon){
(void)mongets(mon, SHACKLES, NO_MKOBJ_FLAGS);
mon->entangled = SHACKLES;
mon->mpeaceful = 1;
set_malign(mon);
}
}
otmp->spe = 0;
}
else if(u.uz.dlevel == nemesis_level.dlevel && urole.neminum == PM_NECROMANCER){
int mtyp;
boolean polyps;
struct monst *mon;
int prisoners[] = {
PM_ELF_LORD, PM_ELF_LADY, PM_GREY_ELF, PM_GREY_ELF,
PM_HEDROW_BLADEMASTER, PM_DROW_CAPTAIN, PM_DROW_MATRON, PM_UNEARTHLY_DROW,
PM_DWARF_CLERIC, PM_DWARF_LORD, PM_DWARF_QUEEN, PM_DWARF_KING,
PM_RANGER, PM_RANGER, PM_WIZARD, PM_KNIGHT, PM_KNIGHT, PM_VALKYRIE,
PM_DEMINYMPH, PM_DEMINYMPH,
PM_SWORD_ARCHON, PM_SHIELD_ARCHON, PM_TRUMPET_ARCHON,
PM_ASTRAL_DEVA, PM_GRAHA_DEVA,
PM_LILLEND, PM_ALEAX,
PM_COURE_ELADRIN, PM_NOVIERE_ELADRIN, PM_BRALANI_ELADRIN, PM_FIRRE_ELADRIN, PM_SHIERE_ELADRIN, PM_GHAELE_ELADRIN, PM_TULANI_ELADRIN, PM_DRACAE_ELADRIN,
PM_TITAN,
PM_ERINYS, PM_LILITU, PM_DAUGHTER_OF_BEDLAM, PM_ICE_DEVIL, PM_MARILITH, PM_PIT_FIEND, PM_FALLEN_ANGEL
};
mtyp = ROLL_FROM(prisoners);
if(mtyp == PM_DRACAE_ELADRIN){
if(dungeon_topology.eprecursor_typ != PRE_DRACAE){
mtyp = PM_TULANI_ELADRIN;
}
if(dungeon_topology.eprecursor_typ == PRE_POLYP){
polyps = TRUE;
}
}
if(mtyp == PM_TULANI_ELADRIN){
switch(dungeon_topology.alt_tulani){
case GAE_CASTE:
mtyp = PM_GAE_ELADRIN;
break;
case BRIGHID_CASTE:
mtyp = PM_BRIGHID_ELADRIN;
break;
case UISCERRE_CASTE:
mtyp = PM_UISCERRE_ELADRIN;
break;
case CAILLEA_CASTE:
mtyp = PM_CAILLEA_ELADRIN;
break;
}
}
mon = makemon(&mons[mtyp], otmp->ox, otmp->oy, MM_GOODEQUIP);
if(mon && polyps){
mon->ispolyp = TRUE;
mongets(mon, MASK, NO_MKOBJ_FLAGS);
mongets(mon, MASK, NO_MKOBJ_FLAGS);
mongets(mon, MASK, NO_MKOBJ_FLAGS);
mongets(mon, MASK, NO_MKOBJ_FLAGS);
mongets(mon, MASK, NO_MKOBJ_FLAGS);
}
if(mon){
(void)mongets(mon, SHACKLES, NO_MKOBJ_FLAGS);
mon->entangled = SHACKLES;
}
}
}
@ -1375,12 +1569,7 @@ default_case:
)\
stuff->objsize = (&mons[urace.malenum])->msize;\
if (stuff->oclass == ARMOR_CLASS){\
if (is_suit(stuff) || stuff->otyp == BODYGLOVE)\
stuff->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_BODYTYPEMASK);\
else if (is_helmet(stuff))\
stuff->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_HEADMODIMASK);\
else if (is_shirt(stuff))\
stuff->bodytypeflag = ((&mons[urace.malenum])->mflagsb&MB_HUMANOID) ? MB_HUMANOID : ((&mons[urace.malenum])->mflagsb&MB_BODYTYPEMASK);\
set_obj_shape(stuff, mons[urace.malenum].mflagsb);\
stuff->objsize = (&mons[urace.malenum])->msize;\
}
#define default_add(type) stuff = mksobj(type, MKOBJ_NOINIT);\
@ -3401,7 +3590,70 @@ dlb *fd;
prevstair.x = x;
prevstair.y = y;
}
if(Role_if(PM_HEALER) && Race_if(PM_DROW)){
//Up stair
if(u.uz.dlevel > 1 && u.uz.dlevel <= 4){
if(dungeons[u.uz.dnum].connect_side[u.uz.dlevel-2] == CON_UNSPECIFIED){
dungeons[u.uz.dnum].connect_side[u.uz.dlevel-2] = rnd(3);
}
int start_x, end_x;
switch(dungeons[u.uz.dnum].connect_side[u.uz.dlevel-2]){
case CONNECT_LEFT:
start_x = 0;
end_x = COLNO/3;
break;
case CONNECT_CENT:
start_x = COLNO/3;
end_x = COLNO*2/3;
break;
case CONNECT_RGHT:
start_x = COLNO*2/3;
end_x = COLNO;
break;
}
int x, y;
for(x = start_x; x < end_x; x++){
for(y = 0; y < ROWNO; y++){
if(levl[x][y].typ == STAIRS && levl[x][y].ladder == LA_UP){
xupstair = x;
yupstair = y;
}
}
}
}
//Down stair
if(u.uz.dlevel < 4){
if(dungeons[u.uz.dnum].connect_side[u.uz.dlevel-1] == CON_UNSPECIFIED){
dungeons[u.uz.dnum].connect_side[u.uz.dlevel-1] = rnd(3);
}
int start_x, end_x;
switch(dungeons[u.uz.dnum].connect_side[u.uz.dlevel-1]){
case CONNECT_LEFT:
start_x = 0;
end_x = COLNO/3;
break;
case CONNECT_CENT:
start_x = COLNO/3;
end_x = COLNO*2/3;
break;
case CONNECT_RGHT:
start_x = COLNO*2/3;
end_x = COLNO;
break;
}
int x, y;
for(x = start_x; x < end_x; x++){
for(y = 0; y < ROWNO; y++){
if(levl[x][y].typ == STAIRS && levl[x][y].ladder == LA_DOWN){
xdnstair = x;
ydnstair = y;
}
}
}
}
}
Fread((genericptr_t) &n, 1, sizeof(n), fd);
/* Number of altars */
while(n--) {

View file

@ -1773,7 +1773,7 @@ genericptr_t arg;
struct monst * mtmp = m_u_at(x, y);
if (mtmp == &youmonst)
zapyourself((struct obj *)arg, TRUE);
else if (mtmp && mtmp->mtame)
else if (mtmp && (mtmp->mtame || mtmp->mpeaceful))
bhitm(mtmp, (struct obj *)arg);
}
@ -3089,18 +3089,9 @@ spiriteffects(power, atme)
mon->m_lev += (u.ulevel - mon->m_lev)/3;
mon->mhpmax = (mon->m_lev * 8) - 4;
mon->mhp = mon->mhpmax;
for(curmon = fmon; curmon; curmon = curmon->nmon){
if(curmon->mspiritual && !get_timer(curmon->timed, DESUMMON_MON)){
numdogs++;
if(!weakdog) weakdog = curmon;
if(weakdog->m_lev > curmon->m_lev) weakdog = curmon;
else if(weakdog->mtame > curmon->mtame) weakdog = curmon;
else if(weakdog->mtame > curmon->mtame) weakdog = curmon;
else if(weakdog->mtame > curmon->mtame) weakdog = curmon;
}
}
if(weakdog && numdogs > dog_limit()) start_timer(5L, TIMER_MONSTER, DESUMMON_MON, (genericptr_t)mon);
mon->mspiritual = TRUE;
// May result in the new dog getting the vanish timer if it's weakest, but that's fine.
vanish_dogs();
}
}break;
case PWR_ROOT_SHOUT:{
@ -5897,7 +5888,10 @@ int spell;
splcaster -= urole.spelarmr * cast_bon / 3;
}
if (uwep->otyp == SCALPEL) { // a tool of healing
if (uwep->otyp == SCALPEL
|| uwep->oartifact == ART_STAFF_OF_AESCULAPIUS
|| uwep->oartifact == ART_ESSCOOAHLIPBOOURRR
) { // tools of healing
cast_bon = 0;
if(spell_skilltype(spellid(spell)) == P_HEALING_SPELL)
cast_bon += 2;
@ -5906,6 +5900,15 @@ int spell;
splcaster -= urole.spelarmr * cast_bon / 3;
}
if (uwep->oartifact == ART_ESSCOOAHLIPBOOURRR) { // mutation
cast_bon = 0;
if(spell_skilltype(spellid(spell)) == P_MATTER_SPELL)
cast_bon += 2;
if (uwep->oartifact)
cast_bon *= 2;
splcaster -= urole.spelarmr * cast_bon / 3;
}
if (uwep->otyp == CRYSTAL_BALL) { // a diviner's tool
cast_bon = 0;
if(spell_skilltype(spellid(spell)) == P_DIVINATION_SPELL)
@ -6203,6 +6206,90 @@ struct obj *obj;
return;
}
void
initialforgotwizardspells(num)
int num;
{
int spells[num];
int found = 0;
int i = 0, j;
int lim;
boolean ok;
while(num--){
lim = 500;
while(lim-- > 0){
spells[i] = rn2(SPE_STONE_TO_FLESH-SPE_DIG)+SPE_DIG;
if(objects[spells[i]].oc_level > 3)
continue;
ok = TRUE;
for(j = 0; j < found; j++)
if(spells[j] == spells[i])
ok = FALSE;
if(ok){
initialforgotspell(spells[i]);
found++;
i++;
break;
}
}
}
}
void
initialforgotpriestspells(num)
int num;
{
int candidatespells[] = {SPE_LIGHT, SPE_DETECT_MONSTERS, SPE_DETECT_UNSEEN,
SPE_CURE_BLINDNESS, SPE_EXTRA_HEALING,
SPE_TURN_UNDEAD, SPE_REMOVE_CURSE, SPE_PROTECTION};
int spells[num];
int found = 0;
int i = 0, j;
int lim;
boolean ok;
while(num--){
lim = 500;
while(lim-- > 0){
spells[i] = ROLL_FROM(candidatespells);
ok = TRUE;
for(j = 0; j < found; j++)
if(spells[j] == spells[i])
ok = FALSE;
if(ok){
initialforgotspell(spells[i]);
found++;
i++;
break;
}
}
}
}
/* Learn a forgotten spell during creation of the initial inventory */
void
initialforgotspell(otyp)
int otyp;
{
int i;
knows_object(otyp);
for (i = 0; i < MAXSPELL; i++) {
if (spellid(i) == otyp) {
pline("Error: Spell %s already known.",
OBJ_NAME(objects[otyp]));
return;
}
if (spellid(i) == NO_SPELL) {
spl_book[i].sp_id = otyp;
spl_book[i].sp_lev = objects[otyp].oc_level;
spl_book[i].sp_know = 0;
return;
}
}
impossible("Too many spells memorized!");
return;
}
/* Learn a ward during creation of the initial inventory */
void
initialward(obj)

View file

@ -242,6 +242,7 @@ int monkey_business; /* true iff an animal is doing the thievery */
struct obj *otmp;
int tmp, could_petrify, named = 0, armordelay;
boolean charms = (is_neuter(mtmp->data) || flags.female == mtmp->female);
boolean mi_only = is_chuul(mtmp->data);
if(mtmp->mtyp == PM_ALRUNES) charms = !charms;
else if(mtmp->mtyp == PM_FIERNA) charms = TRUE;
else if(mtmp->mtyp == PM_BEAUTEOUS_ONE) charms = FALSE;
@ -281,6 +282,7 @@ nothing_to_steal:
tmp = 0;
for(otmp = invent; otmp; otmp = otmp->nobj)
if ((!uarm || otmp != uarmc) && otmp != uskin
&& (!mi_only || is_magic_obj(otmp))
#ifdef INVISIBLE_OBJECTS
&& (!otmp->oinvis || mon_resistance(mtmp,SEE_INVIS))
#endif
@ -291,6 +293,7 @@ nothing_to_steal:
tmp = rn2(tmp);
for(otmp = invent; otmp; otmp = otmp->nobj)
if ((!uarm || otmp != uarmc) && otmp != uskin
&& (!mi_only || is_magic_obj(otmp))
#ifdef INVISIBLE_OBJECTS
&& (!otmp->oinvis || mon_resistance(mtmp,SEE_INVIS))
#endif

View file

@ -92,6 +92,12 @@ unsigned gpflags;
if (!ACCESSIBLE(levl[x][y].typ)) {
if (!(is_pool(x,y, FALSE) && ignorewater)) return FALSE;
}
if(In_quest(&u.uz) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && levl[x][y].typ == AIR){
if(mtmp){
return mon_resistance(mtmp,FLYING) || mon_resistance(mtmp,LEVITATION);
}
else return FALSE;
}
if (closed_door(x, y) && (!mdat || !amorphous(mdat)))
return FALSE;
@ -1045,7 +1051,7 @@ level_tele()
}
newlevel.dnum = u.uz.dnum;
newlevel.dlevel = llimit + newlev;
schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0);
schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0, 0);
return;
}
#endif
@ -1157,7 +1163,7 @@ level_tele()
#endif
get_level(&newlevel, newlev);
}
schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0);
schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0, 0);
/* in case player just read a scroll and is about to be asked to
call it something, we can't defer until the end of the turn */
if (u.utotype && !flags.mon_moving) deferred_goto();
@ -1211,12 +1217,12 @@ register struct trap *ttmp;
schedule_goto(&target_level, FALSE, FALSE, painting,
painting ? "You find yourself next to a scrap of canvas." :
"You feel dizzy for a moment, but the sensation passes.",
(char *)0);
(char *)0, 0);
} else {
target_level = ttmp->dst;
schedule_goto(&target_level, FALSE, FALSE, TRUE,
"You feel dizzy for a moment, but the sensation passes.",
(char *)0);
(char *)0, 0);
}
}

View file

@ -1521,6 +1521,7 @@ long timeout;
/* timeout while away */
if (timeout != monstermoves && (obj->where != OBJ_MINVENT || (
(!is_dwarf(obj->ocarry->data) || obj->otyp != DWARVISH_HELM)
&& obj->otyp != LANTERN_PLATE_MAIL
&& (!is_gnome(obj->ocarry->data) || obj->otyp != GNOMISH_POINTY_HAT)
&& (!is_szcultist(obj->ocarry->data) || !(obj->otyp == TORCH || obj->otyp == SHADOWLANDER_S_TORCH))
))) {
@ -1616,29 +1617,35 @@ long timeout;
case DWARVISH_HELM:
case LANTERN:
case LANTERN_PLATE_MAIL:
case OIL_LAMP:
switch((int)obj->age) {
case 150:
case 100:
case 50:
if (canseeit) {
if (obj->otyp == LANTERN
|| obj->otyp == DWARVISH_HELM)
lantern_message(obj);
if (obj->otyp == LANTERN
|| obj->otyp == DWARVISH_HELM
|| obj->otyp == LANTERN_PLATE_MAIL
)
lantern_message(obj);
else
see_lamp_flicker(obj,
obj->age == 50L ? " considerably" : "");
}
//Dwarvish lamps don't go out in monster inventories
if(obj->where == OBJ_MINVENT &&
is_dwarf(obj->ocarry->data) &&
obj->otyp == DWARVISH_HELM) obj->age = (long) rn1(250,250);
((is_dwarf(obj->ocarry->data) && obj->otyp == DWARVISH_HELM)
|| obj->otyp == LANTERN_PLATE_MAIL)
) obj->age = (long) rn1(250,250);
break;
case 25:
if (canseeit) {
if (obj->otyp == LANTERN
|| obj->otyp == DWARVISH_HELM)
|| obj->otyp == DWARVISH_HELM
|| obj->otyp == LANTERN_PLATE_MAIL
)
lantern_message(obj);
else {
switch (obj->where) {
@ -1656,8 +1663,9 @@ long timeout;
}
//Dwarvish lamps don't go out in monster inventories
if(obj->where == OBJ_MINVENT &&
is_dwarf(obj->ocarry->data) &&
obj->otyp == DWARVISH_HELM) obj->age = (long) rn1(50,25);
((is_dwarf(obj->ocarry->data) && obj->otyp == DWARVISH_HELM)
|| obj->otyp == LANTERN_PLATE_MAIL)
) obj->age = (long) rn1(50,25);
break;
case 0:
@ -1667,6 +1675,7 @@ long timeout;
case OBJ_INVENT:
case OBJ_MINVENT:
if (obj->otyp == LANTERN
|| obj->otyp == LANTERN_PLATE_MAIL
|| obj->otyp == DWARVISH_HELM)
pline("%s lantern has run out of power.",
whose);
@ -1676,6 +1685,7 @@ long timeout;
break;
case OBJ_FLOOR:
if (obj->otyp == LANTERN
|| obj->otyp == LANTERN_PLATE_MAIL
|| obj->otyp == DWARVISH_HELM)
You("see a lantern run out of power.");
else
@ -2140,6 +2150,7 @@ struct obj * obj;
case MAGIC_LAMP:
case DWARVISH_HELM:
case LANTERN:
case LANTERN_PLATE_MAIL:
case OIL_LAMP:
case CANDLE_OF_INVOCATION:
radius = 3;
@ -2232,6 +2243,7 @@ struct obj * obj;
case DWARVISH_HELM:
case LANTERN:
case LANTERN_PLATE_MAIL:
case OIL_LAMP:
/* magic times are 150, 100, 50, 25, and 0 */
if (obj->age > 150L)
@ -2295,6 +2307,7 @@ struct obj * obj;
(obj->otyp == GNOMISH_POINTY_HAT) ||
(obj->otyp == DWARVISH_HELM) ||
(obj->otyp == LANTERN) ||
(obj->otyp == LANTERN_PLATE_MAIL) ||
(obj->otyp == OIL_LAMP) ||
(obj->otyp == CANDELABRUM_OF_INVOCATION) ||
(obj->otyp == TALLOW_CANDLE) ||

View file

@ -536,7 +536,7 @@ boolean td; /* td == TRUE : trap door or hole */
Sprintf(msgbuf, "The hole in the %s above you closes up.",
ceiling(u.ux,u.uy));
schedule_goto(&dtmp, FALSE, TRUE, 0,
(char *)0, !td ? msgbuf : (char *)0);
(char *)0, !td ? msgbuf : (char *)0, 0);
}
/*
@ -621,14 +621,23 @@ int *fail_reason;
return (struct monst *)0;
}
if(mon && cause == ANIMATE_SPELL && rnd(!always_hostile(mon->data) ? 12 : 20) < ACURR(A_CHA) &&
!(is_animal(mon->data) || mindless_mon(mon))
if(mon && cause == ANIMATE_SPELL
&& ((In_quest(&u.uz) && Role_if(PM_HEALER) && (mon->mtyp == PM_IASOIAN_ARCHON || mon->mtyp == PM_PANAKEIAN_ARCHON || mon->mtyp == PM_HYGIEIAN_ARCHON))
|| rnd(!always_hostile(mon->data) ? 12 : 20) < ACURR(A_CHA)
) && !(is_animal(mon->data) || mindless_mon(mon))
){
struct monst *newmon;
newmon = tamedog(mon, (struct obj *)0);
if(newmon) mon = newmon;
if(canspotmon(mon) && mon->mtame)
grateful = TRUE;
if(In_quest(&u.uz) && Role_if(PM_HEALER) && (mon->mtyp == PM_IASOIAN_ARCHON || mon->mtyp == PM_PANAKEIAN_ARCHON || mon->mtyp == PM_HYGIEIAN_ARCHON)){
set_template(mon, PLAGUE_TEMPLATE);
if(get_mx(mon, MX_EDOG))
EDOG(mon)->loyal = TRUE;
}
}
/* in case statue is wielded and hero zaps stone-to-flesh at self */
@ -667,8 +676,11 @@ int *fail_reason;
canspotmon(mon) ? comes_to_life : "disappears");
} else if(cansee(x,y)) pline_The("statue %s!",
canspotmon(mon) ? comes_to_life : "disappears");
if(grateful)
pline("%s is incredibly grateful!", Monnam(mon));
if(grateful){
if(has_template(mon, PLAGUE_TEMPLATE))
pline("%s is glad to see you, but too sick to help!", Monnam(mon));
else pline("%s is incredibly grateful!", Monnam(mon));
}
if (historic) {
You_feel("guilty that the historic statue is now gone.");
adjalign(-1);
@ -2933,9 +2945,9 @@ long hmask, emask; /* might cancel timeout */
if (!trap) {
trap = t_at(u.ux,u.uy);
if(Weightless)
You("begin to tumble in place.");
You("begin to tumble in place.");
else if (Is_waterlevel(&u.uz) && !no_msg)
You_feel("heavier.");
You_feel("heavier.");
/* u.uinwater msgs already in spoteffects()/drown() */
else if (!u.uinwater && !no_msg) {
#ifdef STEED
@ -2976,7 +2988,18 @@ long hmask, emask; /* might cancel timeout */
it gets changed to reflect the new level before we can check it */
assign_level(&current_dungeon_level, &u.uz);
if(trap)
if(!Levitation && !Flying && In_quest(&u.uz) && urole.neminum == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && levl[u.ux][u.uy].typ == AIR){
if(on_level(&u.uz, &qstart_level) && !ok_to_quest()){
pline("A mysterious force prevents you from falling.");
} else {
struct d_level target_level;
target_level.dnum = u.uz.dnum;
target_level.dlevel = qlocate_level.dlevel+1;
int dist = qlocate_level.dlevel+1 - u.uz.dlevel;
schedule_goto(&target_level, FALSE, TRUE, FALSE, "You plummet through the cavern air!", "You slam into the rocky floor!", d(dist*5,6));
}
}
else if(trap)
switch(trap->ttyp) {
case STATUE_TRAP:
(void) activate_statue_trap(trap, trap->tx, trap->ty, FALSE);

View file

@ -21,6 +21,7 @@ STATIC_DCL boolean FDECL(restricted_spell_discipline, (int));
#define UNDEF_TYP 0
#define UNDEF_SPE '\177'
#define UNDEF_BLESS 2
#define OBJ_CURSED 3
/*
* Initial inventory for the various roles.
@ -322,6 +323,47 @@ static struct trobj Healer[] = {
{ EUCALYPTUS_LEAF, 0, FOOD_CLASS, 5, 1 },
{ 0, 0, 0, 0, 0 }
};
static struct trobj Healer_Drow[] = {
{ SCALPEL, 0, WEAPON_CLASS, 1, 1 },
{ KHAKKHARA, 0, WEAPON_CLASS, 1, 1 },
{ GLOVES, 1, ARMOR_CLASS, 1, UNDEF_BLESS },
{ BLINDFOLD, 0, ARMOR_CLASS, 1, OBJ_CURSED },
{ HEALER_UNIFORM, 1, ARMOR_CLASS, 1, 1 },
{ DROVEN_CLOAK, 1, ARMOR_CLASS, 1, 1 },
{ SHOES, 1, ARMOR_CLASS, 1, 1 },
{ STETHOSCOPE, 0, TOOL_CLASS, 1, 0 },
/* always blessed, so it's guaranteed readable */
{ SPE_HEALING, 0, SPBOOK_CLASS, 1, 1 },
{ SPE_DETECT_FOOD, 0, SPBOOK_CLASS, 1, 1 },
{ SPE_CLAIRVOYANCE, 0, SPBOOK_CLASS, 1, 1 },
{ SPE_STONE_TO_FLESH, 0, SPBOOK_CLASS, 1, 1 },
{ SLIME_MOLD, UNDEF_SPE, FOOD_CLASS, 5, 0 },
{ LEMBAS_WAFER, UNDEF_SPE, FOOD_CLASS, 1, 0 },
{ EUCALYPTUS_LEAF, 0, FOOD_CLASS, 5, 1 },
{ 0, 0, 0, 0, 0 }
};
static struct trobj Healer_Hedrow[] = {
{ SCALPEL, 0, WEAPON_CLASS, 1, 1 },
{ QUARTERSTAFF, 0, WEAPON_CLASS, 1, 1 },
{ GLOVES, 1, ARMOR_CLASS, 1, UNDEF_BLESS },
{ BLINDFOLD, 0, ARMOR_CLASS, 1, OBJ_CURSED },
{ HEALER_UNIFORM, 1, ARMOR_CLASS, 1, 1 },
{ DROVEN_CLOAK, 1, ARMOR_CLASS, 1, 1 },
{ SHOES, 1, ARMOR_CLASS, 1, 1 },
{ STETHOSCOPE, 0, TOOL_CLASS, 1, 0 },
/* always blessed, so it's guaranteed readable */
{ SPE_HEALING, 0, SPBOOK_CLASS, 1, 1 },
{ SPE_DETECT_FOOD, 0, SPBOOK_CLASS, 1, 1 },
{ SPE_CLAIRVOYANCE, 0, SPBOOK_CLASS, 1, 1 },
{ SPE_STONE_TO_FLESH, 0, SPBOOK_CLASS, 1, 1 },
{ SLIME_MOLD, UNDEF_SPE, FOOD_CLASS, 5, 0 },
{ LEMBAS_WAFER, UNDEF_SPE, FOOD_CLASS, 1, 0 },
{ EUCALYPTUS_LEAF, 0, FOOD_CLASS, 5, 1 },
{ 0, 0, 0, 0, 0 }
};
static struct trobj Knight[] = {
{ LONG_SWORD, 1, WEAPON_CLASS, 1, UNDEF_BLESS },
{ LANCE, 1, WEAPON_CLASS, 1, UNDEF_BLESS },
@ -1046,6 +1088,48 @@ static const struct def_skill Skill_H[] = {
{ P_NONE, 0 }
};
static const struct def_skill Skill_Dro_M_H[] = {
{ P_DAGGER, P_SKILLED }, { P_KNIFE, P_EXPERT },
{ P_SHORT_SWORD, P_SKILLED }, { P_SCIMITAR, P_BASIC },
{ P_SABER, P_BASIC }, { P_CLUB, P_SKILLED },
{ P_MACE, P_BASIC }, { P_QUARTERSTAFF, P_EXPERT },
{ P_POLEARMS, P_BASIC }, { P_SPEAR, P_BASIC },
{ P_HARVEST, P_EXPERT }, { P_TRIDENT, P_BASIC },
{ P_SLING, P_SKILLED }, { P_DART, P_EXPERT },
{ P_SHURIKEN, P_SKILLED }, { P_UNICORN_HORN, P_EXPERT },
{ P_ATTACK_SPELL, P_EXPERT }, { P_HEALING_SPELL, P_EXPERT },
{ P_DIVINATION_SPELL, P_EXPERT }, { P_ENCHANTMENT_SPELL, P_SKILLED },
{ P_CLERIC_SPELL, P_BASIC }, { P_ESCAPE_SPELL, P_SKILLED },
{ P_MATTER_SPELL, P_SKILLED },
{ P_WAND_POWER, P_BASIC },
{ P_BARE_HANDED_COMBAT, P_BASIC },
#ifdef STEED
{ P_RIDING, P_BASIC },
#endif
{ P_BEAST_MASTERY, P_EXPERT },
{ P_NONE, 0 }
};
static const struct def_skill Skill_Dro_F_H[] = {
{ P_DAGGER, P_SKILLED }, { P_KNIFE, P_EXPERT },
{ P_WHIP, P_SKILLED }, { P_SCIMITAR, P_BASIC },
{ P_SABER, P_BASIC }, { P_CLUB, P_SKILLED },
{ P_MACE, P_BASIC }, { P_QUARTERSTAFF, P_EXPERT },
{ P_POLEARMS, P_BASIC }, { P_SPEAR, P_BASIC },
{ P_HARVEST, P_EXPERT }, { P_TRIDENT, P_BASIC },
{ P_SLING, P_SKILLED }, { P_DART, P_EXPERT },
{ P_SHURIKEN, P_SKILLED }, { P_UNICORN_HORN, P_EXPERT },
{ P_HEALING_SPELL, P_EXPERT }, { P_DIVINATION_SPELL, P_EXPERT },
{ P_CLERIC_SPELL, P_EXPERT },
{ P_WAND_POWER, P_BASIC },
{ P_BARE_HANDED_COMBAT, P_BASIC },
#ifdef STEED
{ P_RIDING, P_BASIC },
#endif
{ P_BEAST_MASTERY, P_EXPERT },
{ P_NONE, 0 }
};
static const struct def_skill Skill_I[] = {
{ P_ATTACK_SPELL, P_EXPERT }, { P_HEALING_SPELL, P_EXPERT },
{ P_DIVINATION_SPELL, P_EXPERT }, { P_ENCHANTMENT_SPELL, P_EXPERT },
@ -2093,15 +2177,53 @@ u_init()
urace.lovemask = 0; /* Madmen are pariahs of their race */
break;
case PM_HEALER:
if(Race_if(PM_DROW)){
if(flags.initgend){
#ifndef GOLDOBJ
u.ugold = u.ugold0 = rn1(1000, 1001);
// u.ugold = u.ugold0 = rn1(500, 501);
// u.ugold = u.ugold0 = rn1(100, 101);
u.ugold = u.ugold0 = 0;
#else
u.umoney0 = rn1(1000, 1001);
// u.umoney0 = rn1(500, 5001);
// u.umoney0 = rn1(100, 1001);
u.umoney0 = 0;
#endif
ini_inv(Healer);
ini_inv(Lamp);
Blinded |= TIMEOUT_INF;
// HTelepat |= FROMOUTSIDE;
ini_inv(Healer_Drow);
initialforgotspell(SPE_DRAIN_LIFE);
initialforgotspell(SPE_CREATE_FAMILIAR);
initialforgotpriestspells(2);
skill_init(Skill_Dro_F_H);
}
else {
#ifndef GOLDOBJ
// u.ugold = u.ugold0 = rn1(100, 101);
u.ugold = u.ugold0 = 0;
#else
// u.umoney0 = rn1(100, 101);
u.umoney0 = 0;
#endif
Blinded |= TIMEOUT_INF;
// HTelepat |= FROMOUTSIDE;
ini_inv(Healer_Hedrow);
initialforgotspell(SPE_FORCE_BOLT);
initialforgotwizardspells(3);
skill_init(Skill_Dro_M_H);
}
knows_object(POT_HEALING);
knows_object(POT_EXTRA_HEALING);
} else {
#ifndef GOLDOBJ
u.ugold = u.ugold0 = rn1(1000, 1001);
#else
u.umoney0 = rn1(1000, 1001);
#endif
ini_inv(Healer);
ini_inv(Lamp);
skill_init(Skill_H);
}
knows_object(POT_FULL_HEALING);
skill_init(Skill_H);
break;
case PM_KNIGHT:
if(Race_if(PM_DWARF)) ini_inv(DwarfNoble);
@ -2409,6 +2531,11 @@ u_init()
}
} else if(Role_if(PM_ANACHRONONAUT)){
u.umartial = TRUE;
} else if(Role_if(PM_HEALER)){
u.ualign.type = A_NEUTRAL;
u.ualign.god = u.ugodbase[UGOD_CURRENT] = u.ugodbase[UGOD_ORIGINAL] = align_to_god(u.ualign.type);
flags.initalign = 1; // 1 == neutral
change_luck(-10);
} else if(!Role_if(PM_EXILE) && !Role_if(PM_CONVICT)){
if(!Role_if(PM_MADMAN))
ini_inv(DrovenCloak);
@ -2436,7 +2563,10 @@ u_init()
knows_object(find_signet_ring());
}
if(Role_if(PM_ANACHRONONAUT)) u.uhouse = LAST_BASTION_SYMBOL;
if(Role_if(PM_ANACHRONONAUT))
u.uhouse = LAST_BASTION_SYMBOL;
else if(Role_if(PM_HEALER))
u.uhouse = PEN_A_SYMBOL;
else u.uhouse = !(Role_if(PM_EXILE) || (Role_if(PM_NOBLEMAN) && !flags.initgend) || Role_if(PM_CONVICT) || Role_if(PM_MADMAN) || Role_if(PM_PIRATE)) ?
rn2(LAST_HOUSE+1-FIRST_HOUSE)+FIRST_HOUSE :
rn2(LAST_FALLEN_HOUSE+1-FIRST_FALLEN_HOUSE)+FIRST_FALLEN_HOUSE;
@ -2811,15 +2941,31 @@ register struct trobj *trop;
if(obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
set_obj_size(obj, youracedata->msize);
if(obj->oclass == ARMOR_CLASS){
if(is_suit(obj)) obj->bodytypeflag = (youracedata->mflagsb&MB_BODYTYPEMASK);
else if(is_helmet(obj)) obj->bodytypeflag = (youracedata->mflagsb&MB_HEADMODIMASK);
else if(is_shirt(obj)) obj->bodytypeflag = (youracedata->mflagsb&MB_HUMANOID) ? MB_HUMANOID : (youracedata->mflagsb&MB_BODYTYPEMASK);
set_obj_shape(obj, youracedata->mflagsb);
}
if(obj->otyp == BULLWHIP && Race_if(PM_DROW) && flags.initgend){
obj->otyp = VIPERWHIP;
set_material_gm(obj, SILVER);
obj->ovar1 = 1;
}
if(Role_if(PM_HEALER) && Race_if(PM_DROW)){
if(obj->otyp == SCALPEL){
set_material_gm(obj, OBSIDIAN_MT);
}
else if(obj->otyp == BLINDFOLD){
obj->obj_color = CLR_BRIGHT_BLUE;
}
else if(obj->otyp == HEALER_UNIFORM){
obj->obj_color = CLR_WHITE;
}
else if(obj->otyp == SHOES){
set_material_gm(obj, CLOTH);
obj->obj_color = CLR_BLUE;
}
else if(obj->otyp == DROVEN_CLOAK){
obj->obj_color = CLR_BLUE;
}
}
if(obj->otyp == SLIME_MOLD && Race_if(PM_DROW)){
obj->spe = fruitadd("mushroom cake");
}
@ -3065,7 +3211,11 @@ register struct trobj *trop;
}
if (trop->trspe != UNDEF_SPE)
obj->spe = trop->trspe;
if (trop->trbless != UNDEF_BLESS)
if (trop->trbless == OBJ_CURSED){
obj->blessed = 0;
obj->cursed = 1;
}
else if (trop->trbless != UNDEF_BLESS)
obj->blessed = trop->trbless;
if(hates_holy(youracedata)){
@ -3117,6 +3267,10 @@ register struct trobj *trop;
setworn(obj, W_TOOL);
}
if(obj->otyp == BLINDFOLD && obj->cursed && !ublindf){
setworn(obj, W_TOOL);
}
if(obj->otyp == ANDROID_VISOR && !ublindf){
setworn(obj, W_TOOL);
}

View file

@ -657,6 +657,21 @@ int otyp;
bonn = 2;
bond = 4;
}
else if (obj->oartifact == ART_ESSCOOAHLIPBOOURRR)
{
if (large)
{
ocn = 2;
ocd = max(6 + 2 * dmod, 2);
flat += 1;
}
else
{
ocn = 1;
ocd = max(6 + 2 * dmod, 2);
flat += 2;
}
}
}
@ -3975,6 +3990,18 @@ const struct def_skill *class_skill;
OLD_P_SKILL(P_DART) = P_BASIC;
OLD_P_SKILL(P_DAGGER) = P_BASIC;
}
if (Role_if(PM_HEALER) && Race_if(PM_DROW)){
OLD_P_SKILL(P_BARE_HANDED_COMBAT) = P_BASIC;
OLD_P_SKILL(P_BEAST_MASTERY) = P_BASIC;
OLD_P_SKILL(P_DIVINATION_SPELL) = P_BASIC;
if(flags.initgend){
OLD_P_SKILL(P_CLERIC_SPELL) = P_BASIC;
}
else {
OLD_P_SKILL(P_ATTACK_SPELL) = P_BASIC;
OLD_P_SKILL(P_ENCHANTMENT_SPELL) = P_BASIC;
}
}
if (u.specialSealsActive&SEAL_BLACK_WEB) {
OLD_P_SKILL(P_CROSSBOW) = P_BASIC;
}

View file

@ -16,6 +16,7 @@ register struct monst *mon;
&& !(is_yochlol(mon->data) && mon->mhp < .5*mon->mhpmax)
&& !(mon->mtyp == PM_SELKIE || mon->mtyp == PM_SEAL)
&& !(mon->mtyp == PM_INCUBUS || mon->mtyp == PM_SUCCUBUS)
&& !(is_duergar(mon))
) return;
if(mon->mtyp == PM_NOVIERE_ELADRIN && !is_pool(mon->mx, mon->my, FALSE)) return;
@ -41,6 +42,27 @@ register struct monst *mon;
}
} else if (is_heladrin(mon->data)){
if(!Protection_from_shape_changers) new_were(mon);
} else if (is_duergar(mon)){
if(mon->data->mlet == S_HUMANOID){
if(Protection_from_shape_changers)
;//Do nothing
else if(!mon->mpeaceful && mon_can_see_you(mon)){
if(rn2(2)) new_were(mon);
}
else if(nearby_targets(mon)){
if(!rn2(4)) new_were(mon);
}
}
else {
if(Protection_from_shape_changers)
new_were(mon); //Revert
else if(!mon->mpeaceful && !mon_can_see_you(mon)){
if(!rn2(20)) new_were(mon);
}
else if(!nearby_targets(mon)){
if(!rn2(20)) new_were(mon);
}
}
} else if (
!rn2(night() ? (flags.moonphase == FULL_MOON ? 3 : 30)
: (flags.moonphase == FULL_MOON ? 10 : 50))
@ -135,6 +157,13 @@ int pm;
case PM_SELKIE: return(PM_SEAL);
case PM_SEAL: return(PM_SELKIE);
case PM_DUERGAR: return(PM_GIANT_DUERGAR);
case PM_GIANT_DUERGAR: return(PM_DUERGAR);
case PM_DUERGAR_STONEGUARD: return(PM_GIANT_STONEGUARD);
case PM_GIANT_STONEGUARD: return(PM_DUERGAR_STONEGUARD);
case PM_DUERGAR_DEBILITATOR: return(PM_DUERGAR_ANNIHILATOR);
case PM_DUERGAR_ANNIHILATOR: return(PM_DUERGAR_DEBILITATOR);
case PM_YOCHLOL:
switch(rnd(3)){
case 1: return(PM_UNEARTHLY_DROW);
@ -215,6 +244,7 @@ struct monst *mon;
&& !is_eladrin(mon->data) && !is_yochlol(mon->data)
&& !(mon->mtyp == PM_SELKIE || mon->mtyp == PM_SEAL)
&& !(mon->mtyp == PM_INCUBUS || mon->mtyp == PM_SUCCUBUS)
&& !is_duergar(mon)
) pline("%s changes into %s.", Monnam(mon),
is_human(&mons[pm]) ? "a human" :
an(mons[pm].mname+4));
@ -273,6 +303,13 @@ struct monst *mon;
} else if(is_heladrin(mon->data)){
m_dowear(mon, TRUE);
init_mon_wield_item(mon);
} else if(is_duergar(mon)){
for(otmp = mon->minvent; otmp; otmp = otmp->nobj){
if(otmp->owornmask && !otmp->oartifact && !((is_weptool(otmp) || otmp->oclass == WEAPON_CLASS) && !check_oprop(otmp, OPROP_NONE))){
size_and_shape_to_fit(otmp, mon);
}
}
mon_break_armor(mon, FALSE);
} else mon_break_armor(mon, FALSE);
possibly_unwield(mon, FALSE);
}

View file

@ -970,12 +970,7 @@ struct permonst * ptr;
}
/* Some creatures are specifically always able to wield any weapon in one hand */
if (ptr && (
ptr->mtyp == PM_THRONE_ARCHON ||
ptr->mtyp == PM_OCCULTIST ||
ptr->mtyp == PM_LUNGORTHIN ||
ptr->mtyp == PM_BASTARD_OF_THE_BOREAL_VALLEY
))
if (ptr && always_one_hand_mtyp(ptr))
return FALSE;
/* get object size */

View file

@ -17,7 +17,6 @@ extern const int monstr[];
#ifdef OVLB
STATIC_DCL short FDECL(which_arti, (long int));
STATIC_DCL boolean FDECL(mon_has_arti, (struct monst *,SHORT_P));
STATIC_DCL struct monst *FDECL(other_mon_has_arti, (struct monst *,SHORT_P));
STATIC_DCL boolean FDECL(rightful_owner, (struct monst *,SHORT_P, struct monst *));
STATIC_DCL struct obj *FDECL(on_ground, (SHORT_P));
@ -174,7 +173,7 @@ which_arti(mask)
* since bell, book, candle, and amulet are all objects, not really
* artifacts right now. [MRS]
*/
STATIC_OVL boolean
boolean
mon_has_arti(mtmp, otyp)
register struct monst *mtmp;
register short otyp;
@ -183,10 +182,11 @@ mon_has_arti(mtmp, otyp)
for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
if(otyp) {
if(otmp->otyp == otyp)
return(1);
if(otmp->otyp == otyp)
return(1);
}
else if(is_quest_artifact(otmp)) return(1);
else if(is_quest_artifact(otmp))
return(1);
}
return(0);
@ -194,8 +194,8 @@ mon_has_arti(mtmp, otyp)
STATIC_OVL struct monst *
other_mon_has_arti(mtmp, otyp)
register struct monst *mtmp;
register short otyp;
struct monst *mtmp;
int otyp;
{
register struct monst *mtmp2;
@ -275,9 +275,9 @@ target_on(mask, mtmp)
register long int mask;
register struct monst *mtmp;
{
register short otyp;
register struct obj *otmp;
register struct monst *mtmp2;
int otyp;
struct obj *otmp;
struct monst *mtmp2;
if(!M_Wants(mask)) return(STRAT_NONE);

View file

@ -1158,6 +1158,7 @@ int depth;
int bas_mdr; /* base DR: magical-ish */
int nat_mdr; /* natural DR: (poly)form */
int arm_mdr; /* armor DR: worn armor */
boolean blip_humanoid_armor = FALSE;
bas_mdr = base_mdr(mon);
nat_mdr = base_nat_mdr(mon);
@ -1193,6 +1194,14 @@ int depth;
slot = LOWER_TORSO_DR;
if (slot == ARM_DR && !can_wear_gloves(mon->data))
slot = UPPER_TORSO_DR;
if(mon->mtyp == PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION && magr && !depth){
if(slot != LEG_DR && rn2(3)){
slot = LOWER_TORSO_DR;
}
else {
blip_humanoid_armor = TRUE;
}
}
/* DR of worn armor */
int marmor[] = { W_ARM, W_ARMC, W_ARMF, W_ARMH, W_ARMG, W_ARMS, W_ARMU };
@ -1205,6 +1214,10 @@ int depth;
if (curarm && ((objects[curarm->otyp].oc_dtyp & slot) || (!objects[curarm->otyp].oc_dtyp && (slot&adfalt[i])))) {
if(depth && higher_depth(objects[curarm->otyp].oc_armcat, depth))
continue;
if(marmor[i] == W_ARM && slot == LOWER_TORSO_DR && mon->mtyp == PM_BLIBDOOLPOOLP_S_MINDGRAVEN_CHAMPION && !blip_humanoid_armor && magr && !depth){
if(!full_body_match(mon->data, curarm))
continue;
}
arm_mdr += arm_dr_bonus(curarm);
if (magr) arm_mdr += properties_dr(curarm, agralign, agrmoral);
}
@ -1378,6 +1391,8 @@ boolean creation;
*/
if(mad_no_armor(mon))
return;
if(mon->mtyp == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH)
return;
if ((is_animal(mon->data) || mindless_mon(mon)) && !creation)
return;
@ -1452,9 +1467,7 @@ boolean racialexception;
case W_ARMH:
if(mon->mtyp == PM_CATHEZAR && obj->otyp == CHAIN)
break;
if (!is_helmet(obj) || ((!helm_match(mon->data,obj) || !has_head_mon(mon) || obj->objsize != mon->data->msize) && !is_flimsy(obj))) continue;
/* (flimsy exception matches polyself handling) */
if (has_horns(mon->data) && obj->otyp != find_gcirclet() && !is_flimsy(obj)) continue;
if (!is_helmet(obj) || !helm_match(mon->data,obj) || !helm_size_fits(mon->data,obj)) continue;
break;
case W_ARMS:
if (noshield(mon->data) || (mon_offhand_attack(mon) && !creation) || !is_shield(obj)) continue;
@ -1467,7 +1480,7 @@ boolean racialexception;
case W_ARMF:
if((mon->mtyp == PM_WARDEN_ARIANNA) && obj->otyp == CHAIN)
break;
if (!is_boots(obj) || obj->objsize != mon->data->msize || !can_wear_boots(mon->data)) continue;
if (!is_boots(obj) || !boots_size_fits(mon->data, obj) || !can_wear_boots(mon->data)) continue;
break;
case W_ARM:
if((mon->mtyp == PM_CATHEZAR || mon->mtyp == PM_WARDEN_ARIANNA) && obj->otyp == CHAIN)
@ -1839,22 +1852,18 @@ boolean polyspot;
}
if ((otmp = which_armor(mon, W_ARMH)) != 0 &&
/* flimsy test for horns matches polyself handling */
(!(is_flimsy(otmp) || otmp->otyp == find_gcirclet()) || is_whirly(mon->data) || noncorporeal(mon->data))
(!helm_match(mon->data, otmp) || !helm_size_fits(mon->data, otmp) || is_whirly(mon->data) || noncorporeal(mon->data) )
) {
if(!has_head_mon(mon) || mon->data->msize != otmp->objsize || !helm_match(mon->data,otmp) || has_horns(mon->data)
|| is_whirly(mon->data) || noncorporeal(mon->data)
){
if (vis)
pline("%s helmet falls to the %s!",
s_suffix(Monnam(mon)), surface(mon->mx, mon->my));
else
You_hear("a clank.");
if (polyspot) bypass_obj(otmp);
m_lose_armor(mon, otmp);
}
if (vis)
pline("%s helmet falls to the %s!",
s_suffix(Monnam(mon)), surface(mon->mx, mon->my));
else
You_hear("a clank.");
if (polyspot) bypass_obj(otmp);
m_lose_armor(mon, otmp);
}
if ((otmp = which_armor(mon, W_ARMF)) != 0) {
if(((noboots(mon->data) || !humanoid(mon->data)) && !can_wear_boots(mon->data)) || mon->data->msize != otmp->objsize || is_whirly(mon->data) || noncorporeal(mon->data)){
if(((noboots(mon->data) || !humanoid(mon->data)) && !can_wear_boots(mon->data)) || !boots_size_fits(mon->data, otmp) || is_whirly(mon->data) || noncorporeal(mon->data)){
if (vis) {
if (is_whirly(mon->data) || noncorporeal(mon->data))
pline("%s %s falls, unsupported!",

View file

@ -1647,6 +1647,7 @@ int * subout; /* records what attacks have been subbed out */
#define SUBOUT_GOATSPWN 0x0100 /* Goat spawn: seduction */
#define SUBOUT_GRAPPLE 0x0200 /* Grappler's Grasp crushing damage */
#define SUBOUT_SCORPION 0x0400 /* Scorpion Carapace's sting */
#define SUBOUT_LOLTH1 0x0800 /* Lolth's 8 arm attack chain */
int * tohitmod; /* some attacks are made with decreased accuracy */
{
struct attack * attk;
@ -1975,6 +1976,15 @@ int * tohitmod; /* some attacks are made with decreased accuracy */
else if(!youdef && !mdef->mdoubt)
GETNEXT
}
/*Skip chuul tentacles unless the target is grappled*/
if(!by_the_book && (attk->adtyp == AD_TSMI ||
(is_chuul(pa) && attk->aatyp == AT_TENT)
)){
if(!mdef)
GETNEXT
else if(youdef && magr != u.ustuck)
GETNEXT
}
/* Nitocris uses clerical spells while wearing their Wrappings */
if(!by_the_book && pa->mtyp == PM_NITOCRIS){
if (attk->aatyp == AT_MAGC){
@ -2001,7 +2011,7 @@ int * tohitmod; /* some attacks are made with decreased accuracy */
if(pd && (!(dmgtype(pd, AD_SEDU)
|| dmgtype(pd, AD_SSEX)
|| dmgtype(pd, AD_LSEX)
|| !could_seduce(magr,mdef,attk)
|| !could_seduce(magr,mdef,0)
|| !(uarm || uarmu || uarmh || uarmg || uarmf || uarmc || uwep || uswapwep)
))){
*subout |= SUBOUT_GOATSPWN;
@ -2017,7 +2027,7 @@ int * tohitmod; /* some attacks are made with decreased accuracy */
|| dmgtype(pd, AD_SSEX)
|| dmgtype(pd, AD_LSEX)
|| magr->mcan
|| !(mdef && could_seduce(magr,mdef,attk))
|| !(mdef && could_seduce(magr,mdef,0))
|| (mdef && !(which_armor(mdef, W_ARM) || which_armor(mdef, W_ARMU) || which_armor(mdef, W_ARMH) ||
which_armor(mdef, W_ARMG) || which_armor(mdef, W_ARMF) || which_armor(mdef, W_ARMC) ||
MON_WEP(mdef) || MON_SWEP(mdef)
@ -2084,7 +2094,7 @@ int * tohitmod; /* some attacks are made with decreased accuracy */
}
/* Bael has alternate attack routines -- not shown in pokedex */
if (pa->mtyp == PM_BAEL && *indexnum < NATTK && !by_the_book) {
static const struct attack marilithHands[6] = {
static const struct attack marilithHands[NATTK] = {
{ AT_MARI, AD_PHYS, 1, 15 },
{ AT_MARI, AD_PHYS, 1, 15 },
{ AT_MARI, AD_PHYS, 1, 15 },
@ -2092,7 +2102,7 @@ int * tohitmod; /* some attacks are made with decreased accuracy */
{ AT_MARI, AD_PHYS, 1, 15 },
{ AT_MARI, AD_PHYS, 1, 15 }
};
static const struct attack swordArchon[6] = {
static const struct attack swordArchon[NATTK] = {
{ AT_CLAW, AD_ACFR, 3, 7 },
{ AT_CLAW, AD_ACFR, 3, 7 },
{ AT_REND, AD_DISN, 7, 1 },
@ -2118,6 +2128,42 @@ int * tohitmod; /* some attacks are made with decreased accuracy */
*attk = marilithHands[*indexnum];
}
}
/* Blibdoolpoolp switches to a worse attack routine at high insight -- shown in pokedex */
if (pa->mtyp == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH && *indexnum < NATTK && u.uinsight >= 54) {
static const struct attack blib_alternate[NATTK] = {
{ AT_CLAW, AD_SQUE, 4, 8, 0, 0, 1 },
{ AT_CLAW, AD_SQUE, 4, 8, 0, 1, 0 },
{ AT_REND, AD_SHRD, 3, 12 },
{ AT_HITS, AD_TSMI, 0, 0 },
{ AT_MAGC, AD_CLRC, 2, 8 },
{ AT_NONE, AD_MROT, 0, 0 }
};
*attk = blib_alternate[*indexnum];
}
/* Lolth has alternate attack routines -- not shown in pokedex */
if (pa->mtyp == PM_AVATAR_OF_LOLTH && *indexnum < NATTK && !by_the_book) {
static const struct attack lolthHands[NATTK] = {
{ AT_WEAP, AD_PHYS, 4, 8 },
{ AT_XWEP, AD_PHYS, 4, 8 },
{ AT_MARI, AD_PHYS, 2, 8 },
{ AT_MARI, AD_PHYS, 2, 8 },
{ AT_MARI, AD_PHYS, 1, 8 },
{ AT_MARI, AD_PHYS, 1, 8 },
{ AT_MARI, AD_PHYS, 1, 8 },
{ AT_MARI, AD_PHYS, 1, 8 }
};
// first index -- determine which attack form
if (*indexnum == 0){
if (rn2(2)){ // 1/2 of marilith-hands
*subout |= SUBOUT_LOLTH1;
}
//else; // 1/2 of normal
}
// If using marilith-hands sub out entire attack chain
if (*subout & SUBOUT_LOLTH1){
*attk = lolthHands[*indexnum];
}
}
/* Various weapons can cause an additional full attack to be made */
/* This only works if it is wielded in the mainhand, and a weapon attack is being made with it (AT_WEAP, AT_DEVA) */
/* not shown in pokedex */
@ -3366,6 +3412,8 @@ int *shield_margin;
/* these guys are extra accurate */
if (is_uvuudaum(pa) || pa->mtyp == PM_CLAIRVOYANT_CHANGED || pa->mtyp == PM_NORN)
bons_acc += 20;
if (pa->mtyp == PM_DRACAE_ELADRIN)
bons_acc += rnd(12);
if (pa->mtyp == PM_GROTESQUE_PEEPER){
if((youdef && mon_can_see_you(magr))
||(!youdef && mon_can_see_mon(magr,mdef) && !mindless_mon(mdef))
@ -4811,6 +4859,8 @@ boolean ranged;
pline("%s is afflicted by disease!",
Monnam(mdef));
}
if(!youagr && ((magr->mspores && !rn2(20)) || has_template(magr, SPORE_ZOMBIE) || has_template(magr, CORDYCEPS)))
mdef->mspores = TRUE;
}
}
return xdamagey(magr, mdef, attk, dmg);
@ -5027,13 +5077,19 @@ boolean ranged;
return result;
case AD_PLYS:
if(cantmove(mdef) && is_chuul(pa)){
/*Steal items instead in this case*/
alt_attk.aatyp = AT_TUCH;
alt_attk.adtyp = AD_SITM;
return xmeleehurty(magr, mdef, &alt_attk, originalattk, weapon_p, dohitmsg, dmg, dieroll, vis, ranged);
}
/* make physical attack */
alt_attk.adtyp = AD_PHYS;
result = xmeleehurty(magr, mdef, &alt_attk, originalattk, weapon_p, dohitmsg, dmg, dieroll, vis, ranged);
/* return early if cannot continue the attack */
if (result&(MM_DEF_DIED|MM_DEF_LSVD))
return result;
if (uncancelled && !cantmove(mdef) && !rn2(3)) {
if (youdef){
if (Free_action) {
@ -5159,11 +5215,11 @@ boolean ranged;
if (result&(MM_DEF_DIED|MM_DEF_LSVD))
return result;
if ((uncancelled && !rn2(4)) || pa->mtyp == PM_PALE_NIGHT) {
if ((uncancelled) || pa->mtyp == PM_PALE_NIGHT) {
if (youdef)
drain_en(dmg);
else
/* Missing an equivalent for monsters. Perhaps this damage type should be skipped vs monsters. */;
mdef->mspec_used += (dmg+9)/10;
}
return result;
@ -6321,7 +6377,7 @@ boolean ranged;
pline("But, no harm is done!");
} else {
int i = 1;
if (pa->mtyp == PM_DEMOGORGON)
if (pa->mtyp == PM_DEMOGORGON || pa->mtyp == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH)
i += rnd(4);
for (; i>0; i--){
@ -6345,7 +6401,7 @@ boolean ranged;
/* no armor */
else {
/* Demogorgon tries to kill */
if (pa->mtyp == PM_DEMOGORGON) {
if (pa->mtyp == PM_DEMOGORGON || pa->mtyp == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH) {
if (noncorporeal(pd) || amorphous(pd)) {
/* custom hit message */
if (vis && dohitmsg) {
@ -6896,6 +6952,34 @@ boolean ranged;
alt_attk.adtyp = AD_PHYS;
return xmeleehurty(magr, mdef, &alt_attk, originalattk, weapon_p, FALSE, dmg, dieroll, vis, ranged);
case AD_TSMI:{
struct obj *inventory = youdef ? invent : mdef->minvent;
if(!inventory)
return MM_MISS;
//Note: with no inventory return silently.
if (vis && dohitmsg) {
if(youdef){
if(canseemon(magr)){
pline("A fan of strange tentacles unfolds from %s %s!", !youagr ? mon_nam(magr) : "your", !youagr ? mbodypart(magr, HEAD) : body_part(HEAD));
pline("The tentacles investigate your belongings!");
}
else pline("Strange tentacles investigate your belongings!");
}
else if(youagr){
pline("A fan of strange tentacles unfolds from your %s!", body_part(HEAD));
pline("Your tentacles investigate %s belongings!", s_suffix(mon_nam(mdef)));
}
else {
if(canseemon(magr)){
pline("A fan of strange tentacles unfolds from %s %s!", mon_nam(magr), mbodypart(magr, HEAD));
pline("The tentacles investigate %s belongings!", s_suffix(mon_nam(mdef)));
}
}
}
dotsmi_theft(magr, mdef, inventory, (struct obj *)0);
return MM_MISS;
}
case AD_WEBS:
/* print a basic hit message */
if (vis && dohitmsg) {
@ -7013,9 +7097,14 @@ boolean ranged;
{
boolean goatspawn = (pa->mtyp == PM_SMALL_GOAT_SPAWN || pa->mtyp == PM_GOAT_SPAWN || pa->mtyp == PM_GIANT_GOAT_SPAWN || pa->mtyp == PM_BLESSED || pa->mtyp == PM_XUENU_MONK);
boolean noflee = (magr->isshk && magr->mpeaceful);
/* make physical attack */
alt_attk.adtyp = AD_PHYS;
result = xmeleehurty(magr, mdef, &alt_attk, originalattk, weapon_p, dohitmsg, dmg, dieroll, vis, ranged);
if(attk->damn > 0 || attk->damd > 0){
/* make physical attack */
alt_attk.adtyp = AD_PHYS;
result = xmeleehurty(magr, mdef, &alt_attk, originalattk, weapon_p, dohitmsg, dmg, dieroll, vis, ranged);
}
else if (vis && dohitmsg) {
xyhitmsg(magr, mdef, originalattk);
}
/* return early if cannot continue the attack */
if (result&(MM_DEF_DIED|MM_DEF_LSVD))
return result;
@ -9443,6 +9532,7 @@ int vis;
result = xdamagey(magr, mdef, attk, FATAL_DAMAGE_MODIFIER);
}
else {
*hp(mdef) -= *hp(mdef)/(u.uswldtim+1); //Floored and current HP, so never fatal.
pline("%s%s digests you!", Monnam(magr),
(u.uswldtim == 2) ? " thoroughly" :
(u.uswldtim == 1) ? " utterly" : "");
@ -9595,7 +9685,12 @@ int vis;
if(thick_skinned(pd))
resist += 2;
if(resist > 0){
if(rnd(20) < resist){
if(resist >= 20)
dmg = 0;
else
dmg = mdef->mhpmax*(20-resist)/20;
if(dmg < mdef->mhp){
mdef->mhp -= dmg;//Will not kill defender
if(canspotmon(magr) || canspotmon(mdef)){
pline("%s regurgitates %s.", Monnam(magr), mon_nam(mdef));
}
@ -9974,6 +10069,18 @@ int vis;
/* deal damage */
result = xdamagey(magr, mdef, attk, dmg);
break;
case AD_DREN:
/* message */
if (vis&VIS_MDEF) {
pline_The("air around %s flashes with multicolored sparks.",
(youdef ? "you" : mon_nam(mdef))
);
}
if (youdef)
drain_en(dmg);
else
mdef->mspec_used += (dmg+9)/10;
break;
case AD_COLD:
case AD_ECLD:
/* apply resistance */
@ -10599,7 +10706,13 @@ expl_common:
else if (vis) {
pline("%s gets blasted!", Monnam(mdef));
}
/* spores */
if(magr->mtyp == PM_BALLISTOSPORE && !Sick_res(mdef)){
if(youdef)
diseasemu(pa);
else
mdef->mspores = TRUE;
}
/* deal damage */
result = xdamagey(magr, mdef, attk, dmg);
}
@ -10877,7 +10990,6 @@ int vis;
/* these gazes are actually hacks and only work vs the player */
if (!youdef && (adtyp == AD_WTCH || adtyp == AD_MIST))
return MM_MISS;
if (/* needs_magr_eyes: magr must have eyes and can actively see mdef */
(needs_magr_eyes && !(
(haseyes(pa)) &&
@ -11567,7 +11679,8 @@ int vis;
(magr->mtyp == PM_AXUS) ? "partially " : "",
(magr->mtyp == PM_AXUS) ? "!" : ".");
if (magr->data->mlet == S_EYE && attk->aatyp == AT_WDGZ &&
mon_reflects(magr, canseemon(magr) ? buf : (char *)0)) {
mon_reflects(magr, canseemon(magr) ? buf : (char *)0)
) {
/* mon_reflects() prints message */
if (magr->mtyp == PM_AXUS)
dmg = dmg/2 + 1;
@ -12228,13 +12341,17 @@ int vis;
break;
case AD_SPOR:
/* release a spore */
if (is_fern(pa) && !magr->mcan &&
if (!magr->mcan &&
!is_fern_sprout(pa) ? !rn2(2) : !rn2(4)) {
coord mm;
int typ;
switch (pa->mtyp) {
if(has_template(magr, CORDYCEPS)){
typ = PM_BALLISTOSPORE;
}
else switch (pa->mtyp) {
case PM_DUNGEON_FERN:
case PM_DUNGEON_FERN_SPROUT:
case PM_BAELNORN:
typ = PM_DUNGEON_FERN_SPORE;
break;
case PM_SWAMP_FERN:
@ -12307,10 +12424,15 @@ int vis;
int mid;
struct monst *mtmp;
int maketame = ((magr->mtame || youagr) ? MM_EDOG : 0);
if(pa->mtyp == PM_CANDLE_TREE || pa->mtyp == PM_FLAMING_ORB){
int makesum = MM_ESUM;
if(has_template(magr, CORDYCEPS)){
mid = PM_BALLISTOSPORE;
makesum = 0;
}
else if(pa->mtyp == PM_CANDLE_TREE || pa->mtyp == PM_FLAMING_ORB){
mid = PM_FLAMING_SPHERE;
// if (cansee(magr->mx, magr->my)) You("see fog billow out from around %s.", mon_nam(magr));
} else {
}
else {
switch(rnd(3)){
case 1:
mid = PM_FLAMING_SPHERE;
@ -12324,10 +12446,11 @@ int vis;
}
}
for(n = dmg; n > 0; n--){
mtmp = makemon(&mons[mid], x(magr), y(magr), MM_ADJACENTOK|MM_ADJACENTSTRICT|maketame|MM_ESUM);
mtmp = makemon(&mons[mid], x(magr), y(magr), MM_ADJACENTOK|MM_ADJACENTSTRICT|maketame|makesum);
if (mtmp) {
/* time out */
mark_mon_as_summoned(mtmp, magr, mlev(magr) + rnd(mlev(magr)), 0);
if(makesum)
mark_mon_as_summoned(mtmp, magr, mlev(magr) + rnd(mlev(magr)), 0);
/* can be peaceful */
if(magr->mpeaceful)
mtmp->mpeaceful = TRUE;
@ -12539,6 +12662,7 @@ int vis; /* True if action is at all visible to the player */
#define SNEAK_TRAPPED 0x08
#define SNEAK_HELPLESS 0x10
#define SNEAK_JUYO 0x20
#define SNEAK_SUICIDAL 0x40
long silverobj = 0L,
jadeobj = 0L,
ironobj = 0L,
@ -12903,6 +13027,8 @@ int vis; /* True if action is at all visible to the player */
if (!mdef->mcanmove || !mdef->mnotlaugh ||
mdef->mstun || mdef->mconf || mdef->msleeping)
sneak_attack |= SNEAK_HELPLESS;
if (mdef->msuicide)
sneak_attack |= SNEAK_SUICIDAL;
if (is_blind(mdef))
sneak_attack |= SNEAK_BLINDED;
if (mdef->mtrapped)
@ -12930,6 +13056,8 @@ int vis; /* True if action is at all visible to the player */
}
if (multi || Stunned || Confusion || Sleeping)
sneak_attack |= SNEAK_HELPLESS;
if (mad_turn(MAD_SUICIDAL))
sneak_attack |= SNEAK_SUICIDAL;
}
else {
if (mdef->mflee && pd->mtyp != PM_BANDERSNATCH)
@ -12941,6 +13069,8 @@ int vis; /* True if action is at all visible to the player */
if (!mdef->mcanmove || !mdef->mnotlaugh ||
mdef->mstun || mdef->mconf || mdef->msleeping)
sneak_attack |= SNEAK_HELPLESS;
if (mdef->msuicide)
sneak_attack |= SNEAK_SUICIDAL;
}
}
/* if we have both a method (attack) and ability (dice) and this isn't a multihit, do the bonus */
@ -14494,9 +14624,11 @@ int vis; /* True if action is at all visible to the player */
}
/* unarmed punches proc effects of worn gloves */
if (unarmed_punch) {
//Monsters have extra damage for their attacks, it makes sense to treat it as part of the unarmed damage.
int unarmed_basedmg = basedmg + ((youagr && !natural_strike) ? 0 : monsdmg);
otmp = (youagr ? uarmg : which_armor(magr, W_ARMG));
if (otmp) {
returnvalue = apply_hit_effects(magr, mdef, otmp, (struct obj *)0, basedmg, &artidmg, &elemdmg, dieroll, &hittxt, TRUE);
returnvalue = apply_hit_effects(magr, mdef, otmp, (struct obj *)0, unarmed_basedmg, &artidmg, &elemdmg, dieroll, &hittxt, TRUE);
if (returnvalue == MM_MISS || (returnvalue & (MM_DEF_DIED | MM_DEF_LSVD)))
return returnvalue;
if (otmp->oartifact)
@ -14505,9 +14637,11 @@ int vis; /* True if action is at all visible to the player */
}
/* unarmed kicks proc effects of worn boots */
if (unarmed_kick) {
//Monsters have extra damage for their attacks, it makes sense to treat it as part of the unarmed damage.
int unarmed_basedmg = basedmg + ((youagr && !natural_strike) ? 0 : monsdmg);
otmp = (youagr ? uarmf : which_armor(magr, W_ARMF));
if (otmp) {
returnvalue = apply_hit_effects(magr, mdef, otmp, (struct obj *)0, basedmg, &artidmg, &elemdmg, dieroll, &hittxt, TRUE);
returnvalue = apply_hit_effects(magr, mdef, otmp, (struct obj *)0, unarmed_basedmg, &artidmg, &elemdmg, dieroll, &hittxt, TRUE);
if (returnvalue == MM_MISS || (returnvalue & (MM_DEF_DIED | MM_DEF_LSVD)))
return returnvalue;
if (otmp->oartifact)
@ -14864,6 +14998,7 @@ int vis; /* True if action is at all visible to the player */
else if (sneak_attack & SNEAK_BLINDED) You("rain blows on the blinded %s%s", l_monnam(mdef), exclam(subtotl));
else if (sneak_attack & SNEAK_TRAPPED) You("rain blows on the trapped %s%s", l_monnam(mdef), exclam(subtotl));
else if (sneak_attack & SNEAK_HELPLESS) You("rain blows on the helpless %s%s", l_monnam(mdef), exclam(subtotl));
else if (sneak_attack & SNEAK_SUICIDAL) You("rain blows on the suicidal %s%s", l_monnam(mdef), exclam(subtotl));
else You("rain blows on %s%s", mon_nam(mdef), exclam(subtotl));
/* ...player gets bonus movement points! */
switch (min(P_SKILL(P_JUYO), P_SKILL(weapon_type(weapon)))){
@ -14881,6 +15016,7 @@ int vis; /* True if action is at all visible to the player */
else if (sneak_attack & SNEAK_BLINDED) You("strike the blinded %s%s", l_monnam(mdef), exclam(subtotl));
else if (sneak_attack & SNEAK_TRAPPED) You("strike the trapped %s%s", l_monnam(mdef), exclam(subtotl));
else if (sneak_attack & SNEAK_HELPLESS) You("strike the helpless %s%s", l_monnam(mdef), exclam(subtotl));
else if (sneak_attack & SNEAK_SUICIDAL) You("strike the suicidal %s%s", l_monnam(mdef), exclam(subtotl));
else You("strike %s%s", mon_nam(mdef), exclam(subtotl));
}
}
@ -16369,12 +16505,11 @@ boolean endofchain; /* if the passive is occuring at the end of aggressor's at
switch (passive->adtyp)
{
case AD_MROT:
// Does nothing, this effect is handled in the experience gain functions xkilled and grow_up.
// // This effect *only* happens if the defender has died!
// if(DEADMONSTER(mdef)){
// //This function's defender is the one doing the cursing, so they are passed in as the agressor.
// result |= mummy_curses_x(mdef, magr);
// }
// Usually does nothing, this effect is handled in the experience gain functions xkilled and grow_up.
if(!DEADMONSTER(mdef) && mdef->mtyp == PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH){
//This function's defender is the one doing the cursing, so they are passed in as the agressor.
result |= mummy_curses_x(mdef, magr);
}
break;
case AD_MAGM:
/* wrath of gods for attacking Oracle */
@ -16684,7 +16819,7 @@ boolean endofchain; /* if the passive is occuring at the end of aggressor's at
if (pd->mlet == S_EYE) { /* assumed to be gaze */
/* the eye can't be blinded */
if (youdef ? Blind : is_blind(mdef)) {
if (youagr) {
if (youagr && pd->mtyp == PM_FLOATING_EYE) {
pline("%s cannot defend itself.",
Adjmonnam(mdef, "blind"));
if (!rn2(500))
@ -17991,6 +18126,15 @@ struct monst * mdef;
else
cnum = 8;
break;
case PM_KUO_TOA:
cnum = 9;
break;
case PM_KUO_TOA_WHIP:
cnum = rn2(20) ? 9 : 10;
break;
case PM_BLIBDOOLPOOLP__GRAVEN_INTO_FLESH:
cnum = 10;
break;
default:
cnum = 0;
break;
@ -18204,6 +18348,121 @@ struct monst * mdef;
}
}
break;
//Liquid Sparks
case 9:{
struct obj *armh = youdef ? uarmh : which_armor(mdef, W_ARMH);
int dmg;
if(armh && is_wide_helm(armh) && !is_metallic(uarmh)){
if(youdef){
if(!Blind)
pline("Bright liquid sparks rain down on your %s.", xname(armh));
}
else {
if(canseemon(mdef))
pline("Bright liquid sparks rain down on %s %s.", s_suffix(mon_nam(mdef)), xname(armh));
}
break;
}
else if(Water_res(mdef) || Shock_res(mdef)){
shieldeff(x(mdef), y(mdef));
if(youdef){
pline("Bright liquid sparks bounce off your %s.", body_part(HEAD));
}
else {
if(canseemon(mdef))
pline("Bright liquid sparks bounce off %s %s.", s_suffix(mon_nam(mdef)) , mbodypart(mdef, HEAD));
}
break;
}
//else
if(youdef){
pline("Bright liquid sparks smite your %s!", body_part(HEAD));
}
else {
if(canseemon(mdef))
pline("Bright liquid sparks smite %s %s!", s_suffix(mon_nam(mdef)) , mbodypart(mdef, HEAD));
}
dmg = d(min((mlev(magr)+2)/3, MAX_BONUS_DICE), 6);
if (Half_spel(mdef))
dmg = (dmg + 1) / 2;
if (youdef && u.uvaul_duration)
dmg = (dmg + 1) / 2;
/* damage inventory */
if (!UseInvShock_res(mdef)){
destroy_item(mdef, WAND_CLASS, AD_ELEC);
}
water_damage(youdef ? invent : mdef->minvent, FALSE, FALSE, FALSE, mdef);
if(youdef)
losehp(dmg, "lightning sparks", KILLED_BY);
else
m_losehp(mdef, dmg, youagr, "lightning sparks");
}break;
//Liquid Bolt
case 10:{
struct obj *armh = youdef ? uarmh : which_armor(mdef, W_ARMH);
int dmg;
int resistances = 0;
if(armh && is_wide_helm(armh) && !is_metallic(uarmh)){
if(youdef){
if(!Blind)
pline("A bright surging torrent pours down on your %s!", xname(armh));
}
else {
if(canseemon(mdef))
pline("A bright surging torrent pours down on %s %s!", s_suffix(mon_nam(mdef)), xname(armh));
}
resistances++;
}
else {
if(youdef){
pline("A bright surging torrent pours down on your %s!", body_part(HEAD));
}
else {
if(canseemon(mdef))
pline("A bright surging torrent pours down on %s %s!", s_suffix(mon_nam(mdef)) , mbodypart(mdef, HEAD));
}
}
if(Water_res(mdef)){
resistances++;
}
if(Shock_res(mdef)){
resistances++;
}
if(resistances > 2){
shieldeff(x(mdef), y(mdef));
if(youdef){
You("seem unharmed.");
}
else {
if(canseemon(mdef))
pline("%s seems unharmed.", Monnam(mdef));
}
break;
}
//else
dmg = d(min((mlev(magr)+2)/3, MAX_BONUS_DICE), 12);
if (resistances == 2)
dmg = (dmg + 3) / 4;
else if (resistances == 1)
dmg = (dmg + 1) / 2;
if (Half_spel(mdef))
dmg = (dmg + 1) / 2;
if (youdef && u.uvaul_duration)
dmg = (dmg + 1) / 2;
/* damage inventory */
if (!UseInvShock_res(mdef)){
destroy_item(mdef, WAND_CLASS, AD_ELEC);
}
if(!Water_res(mdef) && !(armh && is_wide_helm(armh)))
water_damage(youdef ? invent : mdef->minvent, FALSE, FALSE, FALSE, mdef);
if(youdef)
losehp(dmg, "liquid lightning", KILLED_BY);
else
m_losehp(mdef, dmg, youagr, "liquid lightning");
}break;
}
return MM_MISS;
}

View file

@ -467,6 +467,7 @@ struct attack *mattk;
long unwornmask;
int petrifies = FALSE;
char kbuf[BUFSZ];
boolean mi_only = is_chuul(youracedata);
if (!mdef->minvent) return; /* nothing to take */
@ -501,6 +502,8 @@ struct attack *mattk;
mon_nam(mdef), mhe(mdef), mhis(mdef));
}
while ((otmp = mdef->minvent) != 0) {
if(mi_only && !is_magic_obj(otmp) && otmp != stealoid)
continue;
/* take the object away from the monster */
obj_extract_self(otmp);
if ((unwornmask = otmp->owornmask) != 0L) {

View file

@ -405,8 +405,22 @@ struct obj *otmp;
case SPE_FULL_HEALING:
case SPE_MASS_HEALING:{
int delta = mtmp->mhp;
const char *starting_word_ptr = injury_desc_word(mtmp);
int health = otyp == SPE_FULL_HEALING ? (50*P_SKILL(P_HEALING_SPELL)) : (d(6, otyp != SPE_HEALING ? 8 : 4) + 6*(P_SKILL(P_HEALING_SPELL)-1));
reveal_invis = TRUE;
if(has_template(mtmp, PLAGUE_TEMPLATE) && otyp == SPE_FULL_HEALING){
if(canseemon(mtmp))
pline("%s is no longer sick!", Monnam(mtmp));
set_template(mtmp, 0);
if(rnd(!always_hostile(mtmp->data) ? 12 : 20) < ACURR(A_CHA)){
struct monst *newmon = tamedog_core(mtmp, (struct obj *)0, TRUE);
if(newmon){
mtmp = newmon;
newsym(mtmp->mx, mtmp->my);
pline("%s is very grateful!", Monnam(mtmp));
}
}
}
if (mtmp->mtyp != PM_PESTILENCE) {
char hurtmonbuf[BUFSZ];
Strcpy(hurtmonbuf, Monnam(mtmp));
@ -435,10 +449,20 @@ struct obj *otmp;
otyp != SPE_HEALING ? " much" : "" );
}
else {
pline("%s %s %s.",
hurtmonbuf,
(delta != 0 && mtmp->mhp < mtmp->mhpmax) ? "now looks only" : "looks",
injury_desc_word(mtmp));
const char * ending_word_ptr = injury_desc_word(mtmp);
// Note: this compares the string pointers recieved from injury_desc_word. They should be the same if the level is unchanged, and different otherwise.
if(starting_word_ptr != ending_word_ptr){
pline("%s %s %s.",
hurtmonbuf,
(mtmp->mhp < mtmp->mhpmax) ? "now looks only" : "looks",
ending_word_ptr);
}
else if(delta != 0){
pline("%s looks better, but still %s.", hurtmonbuf, ending_word_ptr);
}
// else {
// pline("%s is still %s.", hurtmonbuf, ending_word_ptr);
// }
}
}
}
@ -1860,6 +1884,10 @@ int id;
gem->owt = weight(gem);
add_to_container(otmp, gem);
}
//Transfer body type flags. A non-armor item that becomes armor SHOULD end up MB_HUMANOID
if(is_suit(otmp) || is_shirt(otmp) || is_helmet(otmp)){
set_obj_shape(otmp, obj->bodytypeflag);
}
/* update the weight */
otmp->owt = weight(otmp);
@ -2028,7 +2056,7 @@ struct obj *obj, *otmp;
case SCR_LIGHT:
case SPE_LIGHT:
if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
obj->otyp == LANTERN || obj->otyp == POT_OIL ||
obj->otyp == LANTERN || obj->otyp == LANTERN_PLATE_MAIL || obj->otyp == POT_OIL ||
obj->otyp == DWARVISH_HELM || obj->otyp == GNOMISH_POINTY_HAT ||
obj->otyp == TALLOW_CANDLE || obj->otyp == WAX_CANDLE) &&
!((!Is_candle(obj) && obj->age == 0) || (obj->otyp == MAGIC_LAMP && obj->spe == 0))
@ -2038,7 +2066,9 @@ struct obj *obj, *otmp;
// Assumes the player is the only cause of this effect for purposes of shk billing
if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
obj->otyp == LANTERN || obj->otyp == DWARVISH_HELM) {
obj->otyp == LANTERN || obj->otyp == LANTERN_PLATE_MAIL ||
obj->otyp == DWARVISH_HELM
) {
check_unpaid(obj);
}
else {

View file

@ -850,13 +850,19 @@ monster_detail : MONSTER_ID chance ':' monster_c ',' m_name ',' coordinate '[' S
check_coord(current_coord.x, current_coord.y,
"Monster");
if ($6) {
int token = get_monster_id($6, (char) $<i>4);
if (token == ERR)
yywarning(
"Invalid monster name! Making random monster.");
else
tmpmonst[nmons]->id = token;
Free($6);
if($4=='#')
{
tmpmonst[nmons]->name.str = $6;
}
else {
int token = get_monster_id($6, (char) $<i>4);
if (token == ERR)
yywarning(
"Invalid monster name! Making random monster.");
else
tmpmonst[nmons]->id = token;
Free($6);
}
}
}
monster_infos
@ -884,13 +890,19 @@ monster_detail : MONSTER_ID chance ':' monster_c ',' m_name ',' coordinate '[' S
check_coord(current_coord.x, current_coord.y,
"Monster");
if ($6) {
int token = get_monster_id($6, (char) $<i>4);
if (token == ERR)
yywarning(
"Invalid monster name! Making random monster.");
else
tmpmonst[nmons]->id = token;
Free($6);
if($4=='#')
{
tmpmonst[nmons]->name.str = $6;
}
else {
int token = get_monster_id($6, (char) $<i>4);
if (token == ERR)
yywarning(
"Invalid monster name! Making random monster.");
else
tmpmonst[nmons]->id = token;
Free($6);
}
}
}
monster_infos
@ -958,13 +970,13 @@ object_desc : chance ':' object_c ',' o_name
tmpobj[nobj]->class = '#';
}
else{
int token = get_object_id($5, $<i>3);
if (token == ERR)
yywarning(
"Illegal object name! Making random object.");
else
tmpobj[nobj]->id = token;
Free($5);
int token = get_object_id($5, $<i>3);
if (token == ERR)
yywarning(
"Illegal object name! Making random object.");
else
tmpobj[nobj]->id = token;
Free($5);
}
}
@ -1719,7 +1731,8 @@ place : coord
monster : CHAR
{
if (check_monster_char((char) $1))
char c = (char) $1;
if (check_monster_char(c)||c=='#')
$<i>$ = $1 ;
else {
yyerror("Unknown monster class!");