From: Pasi Kallinen Date: Sun, 23 May 2021 05:55:58 +0000 (+0300) Subject: Unlock your quest by killing your quest leader X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=20cbadcf85544cf9d0c3f4e4200b2800bab49c8e;p=nethack 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 , and xNetHack implementation by copperwater . --- diff --git a/dat/Arc-strt.lua b/dat/Arc-strt.lua index 5f759b575..4bccd8441 100644 --- a/dat/Arc-strt.lua +++ b/dat/Arc-strt.lua @@ -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 diff --git a/dat/Bar-strt.lua b/dat/Bar-strt.lua index 79df053e7..57297b73a 100644 --- a/dat/Bar-strt.lua +++ b/dat/Bar-strt.lua @@ -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 diff --git a/dat/Cav-strt.lua b/dat/Cav-strt.lua index 83c071d0c..d4b974bd2 100644 --- a/dat/Cav-strt.lua +++ b/dat/Cav-strt.lua @@ -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 diff --git a/dat/Hea-strt.lua b/dat/Hea-strt.lua index 1a2f64acc..a936f0212 100644 --- a/dat/Hea-strt.lua +++ b/dat/Hea-strt.lua @@ -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 diff --git a/dat/Kni-strt.lua b/dat/Kni-strt.lua index 4442d93a7..d7f9284c5 100644 --- a/dat/Kni-strt.lua +++ b/dat/Kni-strt.lua @@ -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 diff --git a/dat/Mon-strt.lua b/dat/Mon-strt.lua index ae1ad77d0..0ae685a69 100644 --- a/dat/Mon-strt.lua +++ b/dat/Mon-strt.lua @@ -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) diff --git a/dat/Pri-strt.lua b/dat/Pri-strt.lua index 480a6276d..fb66e6492 100644 --- a/dat/Pri-strt.lua +++ b/dat/Pri-strt.lua @@ -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 diff --git a/dat/Ran-strt.lua b/dat/Ran-strt.lua index 69004ebb6..388dd7e9c 100644 --- a/dat/Ran-strt.lua +++ b/dat/Ran-strt.lua @@ -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 diff --git a/dat/Rog-strt.lua b/dat/Rog-strt.lua index 58f27f696..b2fd32a79 100644 --- a/dat/Rog-strt.lua +++ b/dat/Rog-strt.lua @@ -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 diff --git a/dat/Sam-strt.lua b/dat/Sam-strt.lua index 8186c3cb4..e7c930bee 100644 --- a/dat/Sam-strt.lua +++ b/dat/Sam-strt.lua @@ -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 diff --git a/dat/Tou-strt.lua b/dat/Tou-strt.lua index c5efa0d29..e7a4f7812 100644 --- a/dat/Tou-strt.lua +++ b/dat/Tou-strt.lua @@ -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 diff --git a/dat/Val-strt.lua b/dat/Val-strt.lua index dbce2280d..545dbce6c 100644 --- a/dat/Val-strt.lua +++ b/dat/Val-strt.lua @@ -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 diff --git a/dat/Wiz-strt.lua b/dat/Wiz-strt.lua index 715cb5744..69172039e 100644 --- a/dat/Wiz-strt.lua +++ b/dat/Wiz-strt.lua @@ -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 diff --git a/doc/fixes37.0 b/doc/fixes37.0 index a06c27ea4..5eadb3ae3 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index 548280a50..c9d666210 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *); diff --git a/include/patchlevel.h b/include/patchlevel.h index 700a80582..9b4b90091 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -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. diff --git a/include/quest.h b/include/quest.h index 710af02d9..88fd47eca 100644 --- a/include/quest.h +++ b/include/quest.h @@ -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 */ diff --git a/src/mon.c b/src/mon.c index 423ff0317..b63a3ec91 100644 --- a/src/mon.c +++ b/src/mon.c @@ -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! */ - adjalign((int) (ALIGNLIM / 4)); + 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; diff --git a/src/monst.c b/src/monst.c index 1da91df09..4f837d1b3 100644 --- a/src/monst.c +++ b/src/monst.c @@ -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 diff --git a/src/quest.c b/src/quest.c index 575f4fef8..23d7037ac 100644 --- a/src/quest.c +++ b/src/quest.c @@ -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) { - 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); + if (!Qstat(pissed_off)) { + com_pager("banished"); + 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) { diff --git a/src/timeout.c b/src/timeout.c index 47434ad7a..bacf359d7 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -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