Unlock your quest by killing your quest leader

Allow killing your quest leader, just to make games winnable if you
converted before doing the quest.
Boost the quest leaders and give them some equipment. King Arthur
gets Excalibur. Killing quest leader gives really bad luck and
makes your god angry at you, and killing quest guardians gives
smaller penalties.

This is based on both the EvilHack implementation by
k21971 <keith.simpson1971@gmail.com>, and xNetHack
implementation by copperwater <aosdict@gmail.com>.
This commit is contained in:
Pasi Kallinen
2021-05-23 08:55:58 +03:00
parent 882efdcf58
commit 20cbadcf85
21 changed files with 135 additions and 68 deletions

View File

@@ -70,7 +70,10 @@ des.door("locked",24,14)
des.door("closed",31,14)
des.door("locked",49,14)
-- Lord Carnarvon
des.monster("Lord Carnarvon", 25, 10)
des.monster({ id = "Lord Carnarvon", coord = {25, 10}, inventory = function()
des.object({ id = "fedora", spe = 5 });
des.object({ id = "bullwhip", spe = 4 });
end })
-- The treasure of Lord Carnarvon
des.object("chest", 25, 10)
-- student guards for the audience chamber

View File

@@ -69,7 +69,10 @@ des.door("open",23,13)
des.door("open",25,10)
des.door("open",28,05)
-- Elder
des.monster("Pelias", 10, 07)
des.monster({ id = "Pelias", coord = {10, 07}, inventory = function()
des.object({ id = "runesword", spe = 5 });
des.object({ id = "chain mail", spe = 5 });
end })
-- The treasure of Pelias
des.object("chest", 09, 05)
-- chieftain guards for the audience chamber

View File

@@ -54,7 +54,10 @@ des.door("locked",19,06)
-- The temple altar (this will force a priest(ess) to be created)
des.altar({ x=36,y=02, align="coaligned", type="shrine" })
-- Shaman Karnov
des.monster("Shaman Karnov", 35, 02)
des.monster({ id = "Shaman Karnov", coord = {35, 02}, inventory = function()
des.object({ id = "leather armor", spe = 5 });
des.object({ id = "club", spe = 5 });
end })
-- The treasure of Shaman Karnov
des.object("chest", 34, 02)
-- neanderthal guards for the audience chamber

View File

@@ -60,7 +60,9 @@ des.door("closed",47,08)
des.door("closed",48,12)
des.door("locked",50,10)
-- Hippocrates
des.monster("Hippocrates", 37, 10)
des.monster({ id = "Hippocrates", coord = {37, 10}, inventory = function()
des.object({ id = "silver dagger", spe = 5 });
end })
-- The treasure of Hippocrates
des.object("chest", 37, 10)
-- intern guards for the audience chamber

View File

@@ -62,7 +62,10 @@ des.door("closed",45,03)
des.door("closed",04,12)
des.door("closed",45,12)
-- King Arthur
des.monster("King Arthur", 09, 07)
des.monster({ id = "King Arthur", coord = {09, 07}, inventory = function()
des.object({ id = "long sword", spe = 4, buc = "blessed", name = "Excalibur" });
des.object({ id = "plate mail", spe = 4 });
end })
-- The treasure of King Arthur
des.object("chest", 09, 07)
-- knight guards for the watchrooms

View File

@@ -71,7 +71,9 @@ des.door("closed",52,14)
-- Unattended Altar - unaligned due to conflict - player must align it.
des.altar({ x=28,y=09, align="noalign", type="altar" })
-- The Grand Master
des.monster("Grand Master", 28, 10)
des.monster({ id = "Grand Master", coord = {28, 10}, inventory = function()
des.object({ id = "robe", spe = 6 });
end })
-- No treasure chest!
-- guards for the audience chamber
des.monster("abbot", 32, 07)

View File

@@ -71,7 +71,10 @@ des.door("closed",52,14)
-- Unattended Altar - unaligned due to conflict - player must align it.
des.altar({ x=28, y=09, align="noalign", type="altar" })
-- High Priest
des.monster("Arch Priest", 28, 10)
des.monster({ id = "Arch Priest", coord = {28, 10}, inventory = function()
des.object({ id = "robe", spe = 4 });
des.object({ id = "mace", spe = 4 });
end })
-- The treasure of High Priest
des.object("chest", 27, 10)
-- knight guards for the audience chamber

View File

@@ -46,7 +46,11 @@ des.stair("down", 10,10)
-- Portal arrival point; just about anywhere on the right hand side of the map
des.levregion({ region = {51,2,77,18}, region_islev = 1, type="branch" })
-- Orion
des.monster("Orion", 20, 10)
des.monster({ id = "Orion", coord = {20, 10}, inventory = function()
des.object({ id = "leather armor", spe = 4 });
des.object({ id = "yumi", spe = 4 });
des.object({ id = "arrow", spe = 4, quantity = 50 });
end })
-- The treasure of Orion
des.object("chest", 20, 10)
-- Guards for the audience chamber

View File

@@ -103,7 +103,11 @@ des.door("closed", 6,18)
des.door("closed", 65,18)
des.door("closed", 68,18)
-- Master of Thieves
des.monster("Master of Thieves", 36, 11)
des.monster({ id = "Master of Thieves", coord = {36, 11}, inventory = function()
des.object({ id = "leather armor", spe = 5 });
des.object({ id = "silver dagger", spe = 4 });
des.object({ id = "dagger", spe = 2, quantity = d(2,4), buc = "not-cursed" });
end })
-- The treasure of Master of Thieves
des.object("chest", 36, 11)
-- thug guards, room #1

View File

@@ -54,7 +54,10 @@ des.door("locked",39,08)
des.door("closed",50,04)
des.door("closed",50,06)
-- Lord Sato
des.monster("Lord Sato", 20, 04)
des.monster({ id = "Lord Sato", coord = {20, 04}, inventory = function()
des.object({ id = "splint mail", spe = 5 });
des.object({ id = "katana", spe = 4 });
end })
-- The treasure of Lord Sato
des.object("chest", 20, 04)
-- roshi guards for the audience chamber

View File

@@ -95,7 +95,10 @@ des.monster("forest centaur")
des.monster("forest centaur")
des.monster("C")
-- Twoflower
des.monster("Twoflower", 64, 03)
des.monster({ id = "Twoflower", coord = {64, 03}, inventory = function()
des.object({ id = "walking shoes", spe = 3 });
des.object({ id = "hawaiian shirt", spe = 3 });
end })
-- The treasure of Twoflower
des.object("chest", 64, 03)
-- guides for the audience chamber

View File

@@ -61,7 +61,10 @@ des.feature("fountain", 53,02)
des.door("locked",26,10)
des.door("locked",43,10)
-- Norn
des.monster("Norn", 35, 10)
des.monster({ id = "Norn", coord = {35, 10}, inventory = function()
des.object({ id = "banded mail", spe = 5 });
des.object({ id = "long sword", spe = 4 });
end })
-- The treasure of the Norn
des.object("chest", 36, 10)
-- valkyrie guards for the audience chamber

View File

@@ -61,7 +61,10 @@ des.door("closed",15,10)
des.door("locked",19,10)
des.door("locked",20,10)
-- Neferet the Green, the quest leader
des.monster("Neferet the Green", 23, 05)
des.monster({ id = "Neferet the Green", coord = {23, 05}, inventory = function()
des.object({ id = "elven cloak", spe = 5 });
des.object({ id = "quarterstaff", spe = 5 });
end })
-- The treasure of the quest leader
des.object("chest", 24, 05)
-- apprentice guards for the audience chamber

View File

@@ -532,6 +532,8 @@ make anti-magic fields drain more energy and prevent them from showing up
eating magical monsters such as wizards or shamans may give a mild buzz
make exploding spheres create an actual explosion
pets are more careful about attacking monsters at low health
allow killing your quest leader to open the quest
give King Arthur Excalibur
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -2064,6 +2064,7 @@ extern void free_epri(struct monst *);
extern void onquest(void);
extern void nemdead(void);
extern void leaddead(void);
extern void artitouch(struct obj *);
extern boolean ok_to_quest(void);
extern void leader_speaks(struct monst *);

View File

@@ -17,7 +17,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
#define EDITLEVEL 33
#define EDITLEVEL 34
/*
* Development status possibilities.

View File

@@ -11,6 +11,7 @@ struct q_score { /* Quest "scorecard" */
Bitfield(not_ready, 3); /* rejected due to alignment, etc. */
Bitfield(pissed_off, 1); /* got the leader angry */
Bitfield(got_quest, 1); /* got the quest assignment */
Bitfield(killed_leader, 1); /* killed the quest leader */
Bitfield(first_locate, 1); /* only set the first time */
Bitfield(met_intermed, 1); /* used if the locate is a person. */
@@ -39,7 +40,6 @@ struct q_score { /* Quest "scorecard" */
unsigned leader_m_id;
};
#define MAX_QUEST_TRIES 7 /* exceed this and you "fail" */
#define MIN_QUEST_ALIGN 20 /* at least this align.record to start */
/* note: align 20 matches "pious" as reported by enlightenment (cmd.c) */
#define MIN_QUEST_LEVEL 14 /* at least this u.ulevel to start */

View File

@@ -2205,6 +2205,8 @@ m_detach(
wizdead();
if (mtmp->data->msound == MS_NEMESIS)
nemdead();
if (mtmp->data->msound == MS_LEADER)
leaddead();
if (mtmp->m_id == g.stealmid)
thiefdead();
relobj(mtmp, 0, FALSE);
@@ -2926,12 +2928,17 @@ xkilled(
/* adjust alignment points */
if (mtmp->m_id == g.quest_status.leader_m_id) { /* REAL BAD! */
adjalign(-(u.ualign.record + (int) ALIGNLIM / 2));
u.ugangr += 7; /* instantly become "extremely" angry */
change_luck(-20);
pline("That was %sa bad idea...",
u.uevent.qcompleted ? "probably " : "");
} else if (mdat->msound == MS_NEMESIS) { /* Real good! */
if (!g.quest_status.killed_leader)
adjalign((int) (ALIGNLIM / 4));
} else if (mdat->msound == MS_GUARDIAN) { /* Bad */
adjalign(-(int) (ALIGNLIM / 8));
u.ugangr++;
change_luck(-4);
if (!Hallucination)
pline("That was probably a bad idea...");
else
@@ -3368,8 +3375,7 @@ setmangry(struct monst* mtmp, boolean via_attack)
}
/* attacking your own quest leader will anger his or her guardians */
if (!g.context.mon_moving /* should always be the case here */
&& mtmp->data == &mons[quest_info(MS_LEADER)]) {
if (mtmp->data == &mons[quest_info(MS_LEADER)]) {
struct monst *mon;
struct permonst *q_guardian = &mons[quest_info(MS_GUARDIAN)];
int got_mad = 0;

View File

@@ -2854,25 +2854,25 @@ struct permonst _mons2[] = {
/*
* quest leaders
*/
MON("Lord Carnarvon", S_HUMAN, LVL(20, 12, 0, 30, 20), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
NO_ATTK),
MON("Lord Carnarvon", S_HUMAN, LVL(20, 15, 0, 90, 20), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_SPEL, 4, 8),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
M1_TUNNEL | M1_NEEDPICK | M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
| M2_COLLECT | M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 22, HI_LORD),
MON("Pelias", S_HUMAN, LVL(20, 12, 0, 30, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
NO_ATTK),
MON("Pelias", S_HUMAN, LVL(20, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), MR_POISON, 0,
M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
| M2_COLLECT | M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 22, HI_LORD),
MON("Shaman Karnov", S_HUMAN, LVL(20, 12, 0, 30, 20), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
NO_ATTK),
MON("Shaman Karnov", S_HUMAN, LVL(20, 15, 0, 90, 20), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_CLRC, 2, 8),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
@@ -2900,23 +2900,23 @@ struct permonst _mons2[] = {
| M2_FEMALE | M2_COLLECT | M2_MAGIC,
M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, 22, HI_LORD),
#endif
MON("Hippocrates", S_HUMAN, LVL(20, 12, 0, 40, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
NO_ATTK),
MON("Hippocrates", S_HUMAN, LVL(20, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_CLRC, 3, 8),
ATTK(AT_MAGC, AD_CLRC, 3, 8), NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), MR_POISON, 0,
M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
| M2_COLLECT | M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 22, HI_LORD),
MON("King Arthur", S_HUMAN, LVL(20, 12, 0, 40, 20), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
MON("King Arthur", S_HUMAN, LVL(20, 15, 0, 90, 20), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10), NO_ATTK,
NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
| M2_COLLECT | M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 23, HI_LORD),
MON("Grand Master", S_HUMAN, LVL(25, 12, 0, 70, 0), (G_NOGEN | G_UNIQ),
MON("Grand Master", S_HUMAN, LVL(25, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_CLAW, AD_PHYS, 4, 10), ATTK(AT_KICK, AD_PHYS, 2, 8),
ATTK(AT_MAGC, AD_CLRC, 2, 8), ATTK(AT_MAGC, AD_CLRC, 2, 8), NO_ATTK,
NO_ATTK),
@@ -2926,7 +2926,7 @@ struct permonst _mons2[] = {
M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_MALE | M2_NASTY
| M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 30, CLR_BLACK),
MON("Arch Priest", S_HUMAN, LVL(25, 12, 7, 70, 0), (G_NOGEN | G_UNIQ),
MON("Arch Priest", S_HUMAN, LVL(25, 15, 7, 90, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_KICK, AD_PHYS, 2, 8),
ATTK(AT_MAGC, AD_CLRC, 2, 8), ATTK(AT_MAGC, AD_CLRC, 2, 8), NO_ATTK,
NO_ATTK),
@@ -2936,9 +2936,9 @@ struct permonst _mons2[] = {
M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_MALE | M2_COLLECT
| M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 30, CLR_WHITE),
MON("Orion", S_HUMAN, LVL(20, 12, 0, 30, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
NO_ATTK),
MON("Orion", S_HUMAN, LVL(20, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_SPEL, 4, 8),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(2200, 700, MS_LEADER, MZ_HUGE), 0, 0,
M1_HUMANOID | M1_OMNIVORE | M1_SEE_INVIS | M1_SWIM | M1_AMPHIBIOUS,
M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
@@ -2946,43 +2946,43 @@ struct permonst _mons2[] = {
M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, 22, HI_LORD),
/* Note: Master of Thieves is also the Tourist's nemesis.
*/
MON("Master of Thieves", S_HUMAN, LVL(20, 12, 0, 30, -20),
MON("Master of Thieves", S_HUMAN, LVL(20, 15, 0, 90, -20),
(G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 2, 6),
ATTK(AT_CLAW, AD_SAMU, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), MR_STONE, 0,
M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_MALE | M2_GREEDY
| M2_JEWELS | M2_COLLECT | M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 24, HI_LORD),
MON("Lord Sato", S_HUMAN, LVL(20, 12, 0, 30, 20), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
MON("Lord Sato", S_HUMAN, LVL(20, 15, 0, 90, 20), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10), NO_ATTK,
NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
| M2_COLLECT | M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 23, HI_LORD),
MON("Twoflower", S_HUMAN, LVL(20, 12, 10, 20, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
MON("Twoflower", S_HUMAN, LVL(20, 15, 10, 90, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), NO_ATTK, NO_ATTK,
NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
| M2_COLLECT | M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 22, HI_DOMESTIC),
MON("Norn", S_HUMAN, LVL(20, 12, 0, 80, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
MON("Norn", S_HUMAN, LVL(20, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10), NO_ATTK,
NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1800, 550, MS_LEADER, MZ_HUGE), MR_COLD, 0,
M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_FEMALE
| M2_COLLECT | M2_MAGIC,
M3_CLOSE | M3_INFRAVISIBLE, 23, HI_LORD),
MON("Neferet the Green", S_HUMAN, LVL(20, 12, 0, 60, 0),
MON("Neferet the Green", S_HUMAN, LVL(20, 15, 0, 90, 0),
(G_NOGEN | G_UNIQ),
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_SPEL, 2, 8), NO_ATTK,
NO_ATTK, NO_ATTK, NO_ATTK),
A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_SPEL, 2, 8),
ATTK(AT_MAGC, AD_SPEL, 2, 8), NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_FEMALE | M2_PNAME | M2_PEACEFUL | M2_STRONG

View File

@@ -17,7 +17,7 @@ static void on_goal(void);
static boolean not_capable(void);
static int is_pure(boolean);
static void expulsion(boolean);
static void chat_with_leader(void);
static void chat_with_leader(struct monst *);
static void chat_with_nemesis(void);
static void chat_with_guardian(void);
static void prisoner_speaks(struct monst *);
@@ -112,6 +112,15 @@ nemdead(void)
}
}
void
leaddead(void)
{
if (!Qstat(killed_leader)) {
Qstat(killed_leader) = TRUE;
/* TODO: qt_pager("killed_leader"); ? */
}
}
void
artitouch(struct obj *obj)
{
@@ -130,8 +139,8 @@ artitouch(struct obj *obj)
boolean
ok_to_quest(void)
{
return (boolean) ((Qstat(got_quest) || Qstat(got_thanks))
&& is_pure(FALSE) > 0);
return (boolean) (((Qstat(got_quest) || Qstat(got_thanks))
&& is_pure(FALSE) > 0) || Qstat(killed_leader));
}
static boolean
@@ -240,8 +249,11 @@ finish_quest(struct obj *obj) /* quest artifact; possibly null if carrying
}
static void
chat_with_leader(void)
chat_with_leader(struct monst *mtmp)
{
if (!mtmp->mpeaceful || Qstat(pissed_off))
return;
/* Rule 0: Cheater checks. */
if (u.uhave.questart && !Qstat(met_nemesis))
Qstat(cheater) = TRUE;
@@ -293,18 +305,16 @@ chat_with_leader(void)
exercise(A_WIS, TRUE);
expulsion(FALSE);
} else if ((purity = is_pure(TRUE)) < 0) {
if (!Qstat(pissed_off)) {
com_pager("banished");
expulsion(TRUE);
} else if (purity == 0) {
qt_pager("badalign");
if (Qstat(not_ready) == MAX_QUEST_TRIES) {
qt_pager("leader_last");
expulsion(TRUE);
} else {
Qstat(not_ready)++;
exercise(A_WIS, TRUE);
Qstat(pissed_off) = TRUE;
expulsion(FALSE);
}
} else if (purity == 0) {
qt_pager("badalign");
Qstat(not_ready) = 1;
exercise(A_WIS, TRUE);
expulsion(FALSE);
} else { /* You are worthy! */
qt_pager("assignquest");
exercise(A_WIS, TRUE);
@@ -318,6 +328,12 @@ leader_speaks(struct monst *mtmp)
{
/* maybe you attacked leader? */
if (!mtmp->mpeaceful) {
if (!Qstat(pissed_off)) {
/* again, don't end it permanently if the leader gets angry
* since you're going to have to kill him to go questing... :)
* ...but do only show this crap once. */
qt_pager("leader_last");
}
Qstat(pissed_off) = TRUE;
mtmp->mstrategy &= ~STRAT_WAITMASK; /* end the inaction */
}
@@ -326,11 +342,8 @@ leader_speaks(struct monst *mtmp)
if (!on_level(&u.uz, &qstart_level))
return;
if (Qstat(pissed_off)) {
qt_pager("leader_last");
expulsion(TRUE);
} else
chat_with_leader();
if (!Qstat(pissed_off))
chat_with_leader(mtmp);
}
static void
@@ -399,7 +412,10 @@ void
quest_chat(struct monst *mtmp)
{
if (mtmp->m_id == Qstat(leader_m_id)) {
chat_with_leader();
chat_with_leader(mtmp);
/* leader might have become pissed during the chat */
if (Qstat(pissed_off))
setmangry(mtmp, FALSE);
return;
}
switch (mtmp->data->msound) {

View File

@@ -499,6 +499,9 @@ nh_timeout(void)
if (flags.friday13)
baseluck -= 1;
if (g.quest_status.killed_leader)
baseluck -= 4;
if (u.uluck != baseluck
&& g.moves % ((u.uhave.amulet || u.ugangr) ? 300 : 600) == 0) {
/* Cursed luckstones stop bad luck from timing out; blessed luckstones