fix #H2195 - late discovery for teleport scrolls (trunk only)
From a bug report, when reading an unknown
scroll which turns out to be teleportation, if you happened to land on
another scroll of teleportation it wouldn't be discovered yet, even
though you ought to know that type of scroll by then. Fixing it required
moving handling of that scroll into the teleport code, since discovery
depends upon where you arrive and by then it's too late for seffects() to
do anything that affects feedback for any objects you land on.
Also fixes a post-3.4.3 bug where seffects() was making decisions
based on Teleport_control without being aware that Stunned now negates it
during teleportation.
This commit is contained in:
@@ -1870,6 +1870,7 @@ E long NDECL(random);
|
||||
|
||||
/* ### read.c ### */
|
||||
|
||||
E void FDECL(learnscroll, (struct obj *));
|
||||
E int NDECL(doread);
|
||||
E boolean FDECL(is_chargeable, (struct obj *));
|
||||
E void FDECL(recharge, (struct obj *,int));
|
||||
@@ -2201,6 +2202,7 @@ E void FDECL(teleds, (int,int,BOOLEAN_P));
|
||||
E boolean FDECL(safe_teleds, (BOOLEAN_P));
|
||||
E boolean FDECL(teleport_pet, (struct monst *,BOOLEAN_P));
|
||||
E void NDECL(tele);
|
||||
E boolean FDECL(scrolltele, (struct obj *));
|
||||
E int NDECL(dotele);
|
||||
E void NDECL(level_tele);
|
||||
E void FDECL(domagicportal, (struct trap *));
|
||||
|
||||
20
src/read.c
20
src/read.c
@@ -18,7 +18,6 @@ static NEARDATA const char readable[] =
|
||||
static const char all_count[] = { ALLOW_COUNT, ALL_CLASSES, 0 };
|
||||
|
||||
STATIC_DCL boolean FDECL(learnscrolltyp, (SHORT_P));
|
||||
STATIC_DCL void FDECL(learnscroll, (struct obj *));
|
||||
STATIC_DCL void NDECL(do_class_genocide);
|
||||
STATIC_DCL void FDECL(stripspe,(struct obj *));
|
||||
STATIC_DCL void FDECL(p_glow1,(struct obj *));
|
||||
@@ -35,17 +34,20 @@ learnscrolltyp(scrolltyp)
|
||||
short scrolltyp;
|
||||
{
|
||||
if (!objects[scrolltyp].oc_name_known) {
|
||||
makeknown(scrolltyp);
|
||||
makeknown(scrolltyp);
|
||||
more_experienced(0, 10);
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
/* also called from teleport.c for scroll of teleportation */
|
||||
void
|
||||
learnscroll(sobj)
|
||||
struct obj *sobj;
|
||||
{
|
||||
/* it's implied that sobj->dknown is set;
|
||||
we couldn't be reading this scroll otherwise */
|
||||
if (sobj->oclass != SPBOOK_CLASS)
|
||||
(void) learnscrolltyp(sobj->otyp);
|
||||
}
|
||||
@@ -1178,15 +1180,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
|
||||
if (confused || scursed) {
|
||||
level_tele();
|
||||
} else {
|
||||
if (sblessed && !Teleport_control) {
|
||||
known = TRUE;
|
||||
if (yn("Do you wish to teleport?") == 'n')
|
||||
break;
|
||||
}
|
||||
tele();
|
||||
if (Teleport_control || !couldsee(u.ux0, u.uy0) ||
|
||||
distu(u.ux0, u.uy0) >= 16)
|
||||
known = TRUE;
|
||||
known = scrolltele(sobj);
|
||||
}
|
||||
break;
|
||||
case SCR_GOLD_DETECTION:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/* NetHack 3.5 teleport.c $Date$ $Revision$ */
|
||||
/* SCCS Id: @(#)teleport.c 3.5 2006/12/13 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -11,6 +10,9 @@ STATIC_DCL void NDECL(vault_tele);
|
||||
STATIC_DCL boolean FDECL(rloc_pos_ok, (int,int,struct monst *));
|
||||
STATIC_DCL void FDECL(mvault_tele, (struct monst *));
|
||||
|
||||
/* non-null when teleporting via having read this scroll */
|
||||
STATIC_VAR struct obj *telescroll = 0;
|
||||
|
||||
/*
|
||||
* Is (x,y) a good position of mtmp? If mtmp is NULL, then is (x,y) good
|
||||
* for an object?
|
||||
@@ -328,6 +330,15 @@ boolean allow_drag;
|
||||
vision_full_recalc = 1;
|
||||
nomul(0);
|
||||
vision_recalc(0); /* vision before effects */
|
||||
if (telescroll) {
|
||||
/* when teleporting by scroll, we need to handle discovery
|
||||
now before getting feedback about any objects at our
|
||||
destination since we might land on another such scroll */
|
||||
if (distu(u.ux0, u.uy0) >= 16 || !couldsee(u.ux0, u.uy0))
|
||||
learnscroll(telescroll);
|
||||
else
|
||||
telescroll = 0; /* no discovery by scrolltele()'s caller */
|
||||
}
|
||||
spoteffects(TRUE);
|
||||
invocation_message();
|
||||
}
|
||||
@@ -394,10 +405,23 @@ boolean force_it;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* teleport the hero via some method other than scroll of teleport */
|
||||
void
|
||||
tele()
|
||||
{
|
||||
(void)scrolltele((struct obj *)0);
|
||||
}
|
||||
|
||||
/* teleport the hero; return true if scroll of teleportation should become
|
||||
discovered; teleds() will usually do the actual discovery, since the
|
||||
outcome sometimes depends upon destination and discovery needs to be
|
||||
performed before arrival, in case we land on another teleport scroll */
|
||||
boolean
|
||||
scrolltele(scroll)
|
||||
struct obj *scroll;
|
||||
{
|
||||
coord cc;
|
||||
boolean result = FALSE; /* don't learn scroll */
|
||||
|
||||
/* Disable teleportation in stronghold && Vlad's Tower */
|
||||
if (level.flags.noteleport) {
|
||||
@@ -405,7 +429,7 @@ tele()
|
||||
if (!wizard) {
|
||||
#endif
|
||||
pline("A mysterious force prevents you from teleporting!");
|
||||
return;
|
||||
return TRUE;
|
||||
#ifdef WIZARD
|
||||
}
|
||||
#endif
|
||||
@@ -419,7 +443,7 @@ tele()
|
||||
#ifdef WIZARD
|
||||
if (wizard && yn("Override?") != 'y')
|
||||
#endif
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
if ((Teleport_control && !Stunned)
|
||||
#ifdef WIZARD
|
||||
@@ -429,30 +453,43 @@ tele()
|
||||
if (unconscious()) {
|
||||
pline("Being unconscious, you cannot control your teleport.");
|
||||
} else {
|
||||
char whobuf[BUFSZ];
|
||||
|
||||
Strcpy(whobuf, "you");
|
||||
#ifdef STEED
|
||||
char buf[BUFSZ];
|
||||
if (u.usteed) Sprintf(buf," and %s", mon_nam(u.usteed));
|
||||
if (u.usteed)
|
||||
Sprintf(eos(whobuf), " and %s", mon_nam(u.usteed));
|
||||
#endif
|
||||
pline("To what position do you%s want to be teleported?",
|
||||
#ifdef STEED
|
||||
u.usteed ? buf :
|
||||
#endif
|
||||
"");
|
||||
pline("To what position do %s want to be teleported?",
|
||||
whobuf);
|
||||
cc.x = u.ux;
|
||||
cc.y = u.uy;
|
||||
if (getpos(&cc, TRUE, "the desired position") < 0)
|
||||
return; /* abort */
|
||||
return TRUE; /* abort */
|
||||
/* possible extensions: introduce a small error if
|
||||
magic power is low; allow transfer to solid rock */
|
||||
if (teleok(cc.x, cc.y, FALSE)) {
|
||||
/* for scroll, discover it regardless of destination */
|
||||
if (scroll) learnscroll(scroll);
|
||||
teleds(cc.x, cc.y, FALSE);
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
pline("Sorry...");
|
||||
result = TRUE;
|
||||
}
|
||||
} else if (scroll && scroll->blessed) {
|
||||
/* (this used to be handled in seffects()) */
|
||||
if (yn("Do you wish to teleport?") == 'n') return TRUE;
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
telescroll = scroll;
|
||||
(void) safe_teleds(FALSE);
|
||||
/* teleds() will leave telescroll intact iff random destination
|
||||
is far enough away for scroll discovery to be warranted */
|
||||
if (telescroll) result = TRUE;
|
||||
telescroll = 0; /* reset */
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
Reference in New Issue
Block a user