Tutorial level
Add a tutorial level to teach commands to new players. Very much a WIP. Breaks save and bones compat.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
static void moveloop_preamble(boolean);
|
||||
static void u_calc_moveamt(int);
|
||||
static void maybe_do_tutorial(void);
|
||||
#ifdef POSITIONBAR
|
||||
static void do_positionbar(void);
|
||||
#endif
|
||||
@@ -303,7 +304,7 @@ moveloop_core(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (Searching && gm.multi >= 0)
|
||||
if (!gl.level.flags.noautosearch && Searching && gm.multi >= 0)
|
||||
(void) dosearch0(1);
|
||||
if (Warning)
|
||||
warnreveal();
|
||||
@@ -498,12 +499,41 @@ moveloop_core(void)
|
||||
/* [should this be flush_screen() instead?] */
|
||||
display_nhwindow(WIN_MAP, FALSE);
|
||||
}
|
||||
|
||||
if (gl.luacore && nhcb_counts[NHCB_END_TURN]) {
|
||||
lua_getglobal(gl.luacore, "nh_callback_run");
|
||||
lua_pushstring(gl.luacore, nhcb_name[NHCB_END_TURN]);
|
||||
nhl_pcall(gl.luacore, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_do_tutorial(void)
|
||||
{
|
||||
s_level *sp = find_level("tut-1");
|
||||
|
||||
if (!sp)
|
||||
return;
|
||||
|
||||
if (ask_do_tutorial()) {
|
||||
assign_level(&u.ucamefrom, &u.uz);
|
||||
u.nofollowers = TRUE;
|
||||
schedule_goto(&sp->dlevel, UTOTYPE_NONE, (char *) 0, (char *) 0);
|
||||
deferred_goto();
|
||||
vision_recalc(0);
|
||||
docrt();
|
||||
u.nofollowers = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
moveloop(boolean resuming)
|
||||
{
|
||||
moveloop_preamble(resuming);
|
||||
|
||||
if (!resuming)
|
||||
maybe_do_tutorial();
|
||||
|
||||
for (;;) {
|
||||
moveloop_core();
|
||||
}
|
||||
|
||||
32
src/cmd.c
32
src/cmd.c
@@ -482,6 +482,15 @@ can_do_extcmd(const struct ext_func_tab *extcmd)
|
||||
{
|
||||
int ecflags = extcmd->flags;
|
||||
|
||||
if (gl.luacore && nhcb_counts[NHCB_CMD_BEFORE]) {
|
||||
lua_getglobal(gl.luacore, "nh_callback_run");
|
||||
lua_pushstring(gl.luacore, nhcb_name[NHCB_CMD_BEFORE]);
|
||||
lua_pushstring(gl.luacore, extcmd->ef_txt);
|
||||
nhl_pcall(gl.luacore, 2, 1);
|
||||
if (!lua_toboolean(gl.luacore, -1))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!wizard && (ecflags & WIZMODECMD)) {
|
||||
pline(unavailcmd, extcmd->ef_txt);
|
||||
return FALSE;
|
||||
@@ -3607,6 +3616,29 @@ cmd_from_func(int (*fn)(void))
|
||||
return '\0';
|
||||
}
|
||||
|
||||
/* return visual interpretation of the key bound to extended command,
|
||||
or the ext cmd name if not bound to any key. */
|
||||
char *
|
||||
cmd_from_ecname(const char *ecname)
|
||||
{
|
||||
static char cmdnamebuf[QBUFSZ];
|
||||
const struct ext_func_tab *extcmd;
|
||||
|
||||
for (extcmd = extcmdlist; extcmd->ef_txt; ++extcmd)
|
||||
if (!strcmp(extcmd->ef_txt, ecname)) {
|
||||
char key = cmd_from_func(extcmd->ef_funct);
|
||||
|
||||
if (key)
|
||||
Sprintf(cmdnamebuf, "%s", visctrl(key));
|
||||
else
|
||||
Sprintf(cmdnamebuf, "#%s", ecname);
|
||||
return cmdnamebuf;
|
||||
}
|
||||
|
||||
cmdnamebuf[0] = '\0';
|
||||
return cmdnamebuf;
|
||||
}
|
||||
|
||||
static const char *
|
||||
ecname_from_fn(int (*fn)(void))
|
||||
{
|
||||
|
||||
@@ -45,6 +45,14 @@ const int shield_static[SHIELD_COUNT] = {
|
||||
S_ss1, S_ss2, S_ss3, S_ss2, S_ss1, S_ss2, S_ss4,
|
||||
};
|
||||
|
||||
const char * const nhcb_name[NUM_NHCB] = {
|
||||
"cmd_before",
|
||||
"level_enter",
|
||||
"level_leave",
|
||||
"end_turn",
|
||||
};
|
||||
|
||||
int nhcb_counts[NUM_NHCB] = DUMMY;
|
||||
|
||||
NEARDATA const struct c_color_names c_color_names = {
|
||||
"black", "amber", "golden", "light blue", "red", "green",
|
||||
|
||||
13
src/do.c
13
src/do.c
@@ -1481,6 +1481,12 @@ goto_level(
|
||||
if (on_level(newlevel, &u.uz))
|
||||
return; /* this can happen */
|
||||
|
||||
if (gl.luacore && nhcb_counts[NHCB_LVL_LEAVE]) {
|
||||
lua_getglobal(gl.luacore, "nh_callback_run");
|
||||
lua_pushstring(gl.luacore, nhcb_name[NHCB_LVL_LEAVE]);
|
||||
nhl_pcall(gl.luacore, 1, 0);
|
||||
}
|
||||
|
||||
/* tethered movement makes level change while trapped feasible */
|
||||
if (u.utrap && u.utraptype == TT_BURIEDBALL)
|
||||
buried_ball_to_punishment(); /* (before we save/leave old level) */
|
||||
@@ -1511,7 +1517,8 @@ goto_level(
|
||||
set_ustuck((struct monst *) 0); /* clear u.ustuck and u.uswallow */
|
||||
set_uinwater(0); /* u.uinwater = 0 */
|
||||
u.uundetected = 0; /* not hidden, even if means are available */
|
||||
keepdogs(FALSE);
|
||||
if (!u.nofollowers)
|
||||
keepdogs(FALSE);
|
||||
recalc_mapseen(); /* recalculate map overview before we leave the level */
|
||||
/*
|
||||
* We no longer see anything on the level. Make sure that this
|
||||
@@ -1611,6 +1618,7 @@ goto_level(
|
||||
if (portal && !In_endgame(&u.uz)) {
|
||||
/* find the portal on the new level */
|
||||
register struct trap *ttrap;
|
||||
struct stairway *stway;
|
||||
|
||||
for (ttrap = gf.ftrap; ttrap; ttrap = ttrap->ntrap)
|
||||
if (ttrap->ttyp == MAGIC_PORTAL)
|
||||
@@ -1623,6 +1631,9 @@ goto_level(
|
||||
after already getting expelled once. The portal back
|
||||
doesn't exist anymore - see expulsion(). */
|
||||
u_on_rndspot(0);
|
||||
} else if ((stway = stairway_find_dir(TRUE)) != 0) {
|
||||
/* returning from tutorial via portal */
|
||||
u_on_newpos(stway->sx, stway->sy);
|
||||
} else {
|
||||
panic("goto_level: no corresponding portal!");
|
||||
}
|
||||
|
||||
@@ -714,9 +714,10 @@ get_dgn_flags(lua_State *L)
|
||||
{
|
||||
int dgn_flags = 0;
|
||||
static const char *const flagstrs[] = {
|
||||
"town", "hellish", "mazelike", "roguelike", NULL
|
||||
"town", "hellish", "mazelike", "roguelike", "unconnected", NULL
|
||||
};
|
||||
static const int flagstrs2i[] = { TOWN, HELLISH, MAZELIKE, ROGUELIKE, 0 };
|
||||
static const int flagstrs2i[] = { TOWN, HELLISH, MAZELIKE, ROGUELIKE,
|
||||
UNCONNECTED, 0 };
|
||||
|
||||
lua_getfield(L, -1, "flags");
|
||||
if (lua_type(L, -1) == LUA_TTABLE) {
|
||||
@@ -1040,6 +1041,7 @@ init_dungeons(void)
|
||||
gd.dungeons[i].flags.maze_like = !!(dgn_flags & MAZELIKE);
|
||||
gd.dungeons[i].flags.rogue_like = !!(dgn_flags & ROGUELIKE);
|
||||
gd.dungeons[i].flags.align = dgn_align;
|
||||
gd.dungeons[i].flags.unconnected = !!(dgn_flags & UNCONNECTED);
|
||||
|
||||
/*
|
||||
* Set the entry level for this dungeon. The entry value means:
|
||||
@@ -1063,7 +1065,9 @@ init_dungeons(void)
|
||||
gd.dungeons[i].entry_lev = 1; /* defaults to top level */
|
||||
}
|
||||
|
||||
if (i) { /* set depth */
|
||||
if (gd.dungeons[i].flags.unconnected) {
|
||||
gd.dungeons[i].depth_start = 1;
|
||||
} else if (i) { /* set depth */
|
||||
branch *br;
|
||||
schar from_depth;
|
||||
boolean from_up;
|
||||
|
||||
@@ -296,8 +296,8 @@ wipe_engr_at(coordxy x, coordxy y, xint16 cnt, boolean magical)
|
||||
{
|
||||
register struct engr *ep = engr_at(x, y);
|
||||
|
||||
/* Headstones are indelible */
|
||||
if (ep && ep->engr_type != HEADSTONE) {
|
||||
/* Headstones and some specially marked engravings are indelible */
|
||||
if (ep && ep->engr_type != HEADSTONE && !ep->nowipeout) {
|
||||
debugpline1("asked to erode %d characters", cnt);
|
||||
if (ep->engr_type != BURN || is_ice(x, y) || (magical && !rn2(2))) {
|
||||
if (ep->engr_type != DUST && ep->engr_type != ENGR_BLOOD) {
|
||||
|
||||
@@ -1141,7 +1141,7 @@ makemon(
|
||||
fakemon = cg.zeromonst;
|
||||
cc.x = cc.y = 0;
|
||||
|
||||
if (iflags.debug_mongen)
|
||||
if (iflags.debug_mongen || (!gl.level.flags.rndmongen && !ptr))
|
||||
return (struct monst *) 0;
|
||||
|
||||
/* if caller wants random location, do it here */
|
||||
|
||||
@@ -1016,6 +1016,12 @@ makelevel(void)
|
||||
for (i = 0; i < gn.nroom; ++i) {
|
||||
fill_special_room(&gr.rooms[i]);
|
||||
}
|
||||
|
||||
if (gl.luacore && nhcb_counts[NHCB_LVL_ENTER]) {
|
||||
lua_getglobal(gl.luacore, "nh_callback_run");
|
||||
lua_pushstring(gl.luacore, nhcb_name[NHCB_LVL_ENTER]);
|
||||
nhl_pcall(gl.luacore, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1518,6 +1524,9 @@ mktrap(
|
||||
(void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y, NO_MM_FLAGS);
|
||||
if (t && (mktrapflags & MKTRAP_SEEN))
|
||||
t->tseen = TRUE;
|
||||
if (kind == MAGIC_PORTAL && (u.ucamefrom.dnum || u.ucamefrom.dlevel)) {
|
||||
assign_level(&t->dst, &u.ucamefrom);
|
||||
}
|
||||
|
||||
/* The hero isn't the only person who's entered the dungeon in
|
||||
search of treasure. On the very shallowest levels, there's a
|
||||
|
||||
@@ -34,6 +34,7 @@ static void pacify_guard(struct monst *);
|
||||
|
||||
#define LEVEL_SPECIFIC_NOCORPSE(mdat) \
|
||||
(Is_rogue_level(&u.uz) \
|
||||
|| !gl.level.flags.deathdrops \
|
||||
|| (gl.level.flags.graveyard && is_undead(mdat) && rn2(3)))
|
||||
|
||||
/* A specific combination of x_monnam flags for livelogging. The livelog
|
||||
|
||||
140
src/nhlua.c
140
src/nhlua.c
@@ -36,6 +36,9 @@ static int nhl_timer_has_at(lua_State *);
|
||||
static int nhl_timer_peek_at(lua_State *);
|
||||
static int nhl_timer_stop_at(lua_State *);
|
||||
static int nhl_timer_start_at(lua_State *);
|
||||
static int nhl_get_cmd_key(lua_State *);
|
||||
static int nhl_callback(lua_State *);
|
||||
static int nhl_gamestate(lua_State *);
|
||||
static int nhl_test(lua_State *);
|
||||
static int nhl_getmap(lua_State *);
|
||||
static char splev_typ2chr(schar);
|
||||
@@ -1474,6 +1477,140 @@ nhl_timer_start_at(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns the visual interpretation of the key bound to an extended command,
|
||||
or the ext cmd name if not bound to any key */
|
||||
/* local helpkey = eckey("help"); */
|
||||
static int
|
||||
nhl_get_cmd_key(lua_State *L)
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1) {
|
||||
const char *cmd = luaL_checkstring(L, 1);
|
||||
char *key = cmd_from_ecname(cmd);
|
||||
|
||||
lua_pushstring(L, key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* add or remove a lua function callback */
|
||||
/* callback("level_enter", "function_name"); */
|
||||
/* callback("level_enter", "function_name", true); */
|
||||
/* level_enter, level_leave, cmd_before */
|
||||
static int
|
||||
nhl_callback(lua_State *L)
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
int i;
|
||||
|
||||
if (argc == 2) {
|
||||
const char *fn = luaL_checkstring(L, -1);
|
||||
const char *cb = luaL_checkstring(L, -2);
|
||||
|
||||
if (!gl.luacore) {
|
||||
nhl_error(L, "nh luacore not inited");
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_NHCB; i++)
|
||||
if (!strcmp(cb, nhcb_name[i]))
|
||||
break;
|
||||
|
||||
if (i >= NUM_NHCB)
|
||||
return 0;
|
||||
|
||||
nhcb_counts[i]++;
|
||||
|
||||
lua_getglobal(gl.luacore, "nh_callback_set");
|
||||
lua_pushstring(gl.luacore, cb);
|
||||
lua_pushstring(gl.luacore, fn);
|
||||
nhl_pcall(gl.luacore, 2, 0);
|
||||
} else if (argc == 3) {
|
||||
boolean rm = lua_toboolean(L, -1);
|
||||
const char *fn = luaL_checkstring(L, -2);
|
||||
const char *cb = luaL_checkstring(L, -3);
|
||||
|
||||
if (!gl.luacore) {
|
||||
nhl_error(L, "nh luacore not inited");
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_NHCB; i++)
|
||||
if (!strcmp(cb, nhcb_name[i]))
|
||||
break;
|
||||
|
||||
if (i >= NUM_NHCB)
|
||||
return 0;
|
||||
|
||||
if (rm) {
|
||||
nhcb_counts[i]--;
|
||||
if (nhcb_counts[i] < 0)
|
||||
impossible("nh.callback counts are wrong");
|
||||
} else {
|
||||
nhcb_counts[i]++;
|
||||
}
|
||||
|
||||
lua_getglobal(gl.luacore, rm ? "nh_callback_rm" : "nh_callback_set");
|
||||
lua_pushstring(gl.luacore, cb);
|
||||
lua_pushstring(gl.luacore, fn);
|
||||
nhl_pcall(gl.luacore, 2, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* store or restore game state */
|
||||
/* NOTE: doesn't work when saving/restoring the game */
|
||||
/* currently handles inventory and turns. */
|
||||
/* gamestate(); -- save state */
|
||||
/* gamestate(true); -- restore state */
|
||||
static int
|
||||
nhl_gamestate(lua_State *L)
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
boolean reststate = argc > 0 ? lua_toboolean(L, -1) : FALSE;
|
||||
static struct obj *invent = NULL;
|
||||
static long moves = 0;
|
||||
static boolean stored = FALSE;
|
||||
|
||||
if (reststate && stored) {
|
||||
/* restore game state */
|
||||
gm.moves = moves;
|
||||
while (gi.invent)
|
||||
useupall(gi.invent);
|
||||
while (invent) {
|
||||
struct obj *otmp = invent;
|
||||
long wornmask = otmp->owornmask;
|
||||
otmp->owornmask = 0L;
|
||||
extract_nobj(otmp, &invent);
|
||||
addinv(otmp);
|
||||
if (wornmask)
|
||||
setworn(otmp, wornmask);
|
||||
}
|
||||
stored = FALSE;
|
||||
} else {
|
||||
/* store game state */
|
||||
while (gi.invent) {
|
||||
struct obj *otmp = gi.invent;
|
||||
long wornmask = otmp->owornmask;
|
||||
setnotworn(otmp);
|
||||
freeinv(otmp);
|
||||
otmp->nobj = invent;
|
||||
otmp->owornmask = wornmask;
|
||||
invent = otmp;
|
||||
}
|
||||
moves = gm.moves;
|
||||
stored = TRUE;
|
||||
}
|
||||
update_inventory();
|
||||
return 0;
|
||||
}
|
||||
|
||||
RESTORE_WARNING_UNREACHABLE_CODE
|
||||
|
||||
static const struct luaL_Reg nhl_functions[] = {
|
||||
@@ -1499,6 +1636,9 @@ static const struct luaL_Reg nhl_functions[] = {
|
||||
{"menu", nhl_menu},
|
||||
{"text", nhl_text},
|
||||
{"getlin", nhl_getlin},
|
||||
{"eckey", nhl_get_cmd_key},
|
||||
{"callback", nhl_callback},
|
||||
{"gamestate", nhl_gamestate},
|
||||
|
||||
{"makeplural", nhl_makeplural},
|
||||
{"makesingular", nhl_makesingular},
|
||||
|
||||
@@ -368,6 +368,52 @@ extern int curses_read_attrs(const char *attrs);
|
||||
extern char *curses_fmt_attrs(char *);
|
||||
#endif
|
||||
|
||||
/* ask user if they want a tutorial, except if tutorial boolean option has been
|
||||
set in config - either on or off - in which case just obey that setting
|
||||
without asking. */
|
||||
boolean
|
||||
ask_do_tutorial(void)
|
||||
{
|
||||
boolean dotut = flags.tutorial;
|
||||
|
||||
if (!opt_set_in_config[opt_tutorial]) {
|
||||
winid win;
|
||||
menu_item *sel;
|
||||
anything any;
|
||||
int n;
|
||||
|
||||
do {
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany;
|
||||
any.a_char = 'y';
|
||||
add_menu(win, &nul_glyphinfo, &any, any.a_char, 0,
|
||||
ATR_NONE, 0, "Yes, do a tutorial", MENU_ITEMFLAGS_NONE);
|
||||
any.a_char = 'n';
|
||||
add_menu(win, &nul_glyphinfo, &any, any.a_char, 0,
|
||||
ATR_NONE, 0, "No", MENU_ITEMFLAGS_NONE);
|
||||
|
||||
any = cg.zeroany;
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, 0, "", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, 0, "", MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, 0, "Put \"OPTIONS=notutorial\" in the config file to skip this query.", MENU_ITEMFLAGS_NONE);
|
||||
|
||||
end_menu(win, "Do you want a tutorial?");
|
||||
|
||||
n = select_menu(win, PICK_ONE, &sel);
|
||||
destroy_nhwindow(win);
|
||||
} while (n <= 0 && !gp.program_state.done_hup);
|
||||
if (n > 0) {
|
||||
dotut = (sel[0].item.a_char == 'y');
|
||||
free((genericptr_t) sel);
|
||||
}
|
||||
}
|
||||
return dotut;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************
|
||||
*
|
||||
|
||||
18
src/sp_lev.c
18
src/sp_lev.c
@@ -3712,6 +3712,12 @@ lspo_level_flags(lua_State *L)
|
||||
gl.level.flags.temperature = 1;
|
||||
else if (!strcmpi(s, "cold"))
|
||||
gl.level.flags.temperature = -1;
|
||||
else if (!strcmpi(s, "nomongen"))
|
||||
gl.level.flags.rndmongen = 0;
|
||||
else if (!strcmpi(s, "nodeathdrops"))
|
||||
gl.level.flags.deathdrops = 0;
|
||||
else if (!strcmpi(s, "noautosearch"))
|
||||
gl.level.flags.noautosearch = 1;
|
||||
else {
|
||||
char buf[BUFSZ];
|
||||
Sprintf(buf, "Unknown level flag %s", s);
|
||||
@@ -3783,6 +3789,9 @@ lspo_engraving(lua_State *L)
|
||||
long ecoord;
|
||||
coordxy x = -1, y = -1;
|
||||
int argc = lua_gettop(L);
|
||||
boolean guardobjs = FALSE;
|
||||
boolean wipeout = TRUE;
|
||||
struct engr *ep;
|
||||
|
||||
create_des_coder();
|
||||
|
||||
@@ -3795,6 +3804,8 @@ lspo_engraving(lua_State *L)
|
||||
y = ey;
|
||||
etyp = engrtypes2i[get_table_option(L, "type", "engrave", engrtypes)];
|
||||
txt = get_table_str(L, "text");
|
||||
wipeout = get_table_boolean_opt(L, "degrade", TRUE);
|
||||
guardobjs = get_table_boolean_opt(L, "guardobjects", FALSE);
|
||||
} else if (argc == 3) {
|
||||
lua_Integer ex, ey;
|
||||
(void) get_coord(L, 1, &ex, &ey);
|
||||
@@ -3814,6 +3825,11 @@ lspo_engraving(lua_State *L)
|
||||
get_location_coord(&x, &y, DRY, gc.coder->croom, ecoord);
|
||||
make_engr_at(x, y, txt, 0L, etyp);
|
||||
Free(txt);
|
||||
ep = engr_at(x, y);
|
||||
if (ep) {
|
||||
ep->guardobjects = guardobjs;
|
||||
ep->nowipeout = !wipeout;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6826,6 +6842,8 @@ sp_level_coder_init(void)
|
||||
|
||||
gl.level.flags.is_maze_lev = 0;
|
||||
gl.level.flags.temperature = In_hell(&u.uz) ? 1 : 0;
|
||||
gl.level.flags.rndmongen = 1;
|
||||
gl.level.flags.deathdrops = 1;
|
||||
|
||||
reset_xystart_size();
|
||||
|
||||
|
||||
@@ -1128,7 +1128,8 @@ void
|
||||
domagicportal(struct trap *ttmp)
|
||||
{
|
||||
struct d_level target_level;
|
||||
boolean already_stunned;
|
||||
s_level *tutlvl = find_level("tut-1");
|
||||
const char *stunmsg = (char *) 0;
|
||||
|
||||
if (u.utrap && u.utraptype == TT_BURIEDBALL)
|
||||
buried_ball_to_punishment();
|
||||
@@ -1154,13 +1155,16 @@ domagicportal(struct trap *ttmp)
|
||||
return;
|
||||
}
|
||||
|
||||
already_stunned = !!Stunned;
|
||||
make_stunned((HStun & TIMEOUT) + 3L, FALSE);
|
||||
target_level = ttmp->dst;
|
||||
schedule_goto(&target_level, UTOTYPE_PORTAL,
|
||||
!already_stunned ? "You feel slightly dizzy."
|
||||
: "You feel dizzier.",
|
||||
(char *) 0);
|
||||
|
||||
/* coming back from tutorial doesn't trigger stunning */
|
||||
if (!(tutlvl && tutlvl->dlevel.dnum == u.uz.dnum)) {
|
||||
stunmsg = !Stunned ? "You feel slightly dizzy."
|
||||
: "You feel dizzier.";
|
||||
make_stunned((HStun & TIMEOUT) + 3L, FALSE);
|
||||
}
|
||||
|
||||
schedule_goto(&target_level, UTOTYPE_PORTAL, stunmsg, (char *) 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user