7065 lines
163 KiB
C
7065 lines
163 KiB
C
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ncurses.h>
|
|
#include <unistd.h>
|
|
#include "ai.h"
|
|
#include "attack.h"
|
|
#include "defs.h"
|
|
#include "flag.h"
|
|
#include "io.h"
|
|
#include "lf.h"
|
|
#include "map.h"
|
|
#include "move.h"
|
|
#include "nexus.h"
|
|
#include "objects.h"
|
|
#include "text.h"
|
|
#include "save.h"
|
|
#include "spell.h"
|
|
|
|
WINDOW *mainwin;
|
|
WINDOW *gamewin;
|
|
WINDOW *msgwin;
|
|
WINDOW *statwin;
|
|
|
|
int statdirty = B_TRUE;
|
|
|
|
int hascolour = B_TRUE;
|
|
|
|
extern int needredraw;
|
|
extern int numdraws;
|
|
|
|
extern int SCREENW, SCREENH;
|
|
|
|
extern enum ERROR reason;
|
|
|
|
extern char msghist[MAXHISTORY][BUFLEN];
|
|
extern int nmsghist;
|
|
|
|
extern prompt_t prompt;
|
|
|
|
extern object_t *retobs[MAXPILEOBS+1];
|
|
extern int retobscount[MAXPILEOBS+1];
|
|
extern int nretobs;
|
|
|
|
extern FILE *logfile;
|
|
extern enum OBCLASS sortorder[];
|
|
extern knowledge_t *knowledge;
|
|
extern objecttype_t *objecttype;
|
|
extern command_t *firstcommand;
|
|
extern skill_t *firstskill;
|
|
|
|
extern enum GAMEMODE gamemode;
|
|
extern long curtime;
|
|
|
|
char msgbuf[HUGEBUFLEN];
|
|
char lastmsgbuf[HUGEBUFLEN];
|
|
|
|
extern lifeform_t *player;
|
|
|
|
extern map_t *firstmap;
|
|
|
|
int viewx = -9999,viewy = -9999;
|
|
|
|
int vieww,viewh;
|
|
|
|
int msgmod = B_FALSE;
|
|
|
|
|
|
void addchoice(prompt_t *p, char ch, char *text, char *desc, void *data) {
|
|
p->choice[p->nchoices].ch = ch;
|
|
p->choice[p->nchoices].text = strdup(text);
|
|
if (desc) {
|
|
p->choice[p->nchoices].desc = strdup(desc);
|
|
} else {
|
|
p->choice[p->nchoices].desc = strdup(text);
|
|
}
|
|
p->choice[p->nchoices].data = data;
|
|
p->choice[p->nchoices].heading = B_FALSE;
|
|
p->nchoices++;
|
|
}
|
|
|
|
void addheading(prompt_t *p, char *text) {
|
|
p->choice[p->nchoices].ch = '\0';
|
|
p->choice[p->nchoices].text = strdup(text);
|
|
p->choice[p->nchoices].desc = strdup(text);
|
|
p->choice[p->nchoices].data = NULL;
|
|
p->choice[p->nchoices].heading = B_TRUE;
|
|
p->nchoices++;
|
|
}
|
|
|
|
void addmsghist(char *text) {
|
|
char *localtext;
|
|
int db = B_FALSE;
|
|
localtext = strdup(text);
|
|
localtext = strrep(localtext, MORESTRING, "", NULL);
|
|
if (nmsghist < MAXHISTORY) {
|
|
strcpy(msghist[nmsghist], localtext);
|
|
nmsghist++;
|
|
if (db) dblog("adding to msg hist: %s",localtext);
|
|
} else {
|
|
int i;
|
|
// shuffle everything up then replace last one
|
|
for (i = 0; i < (MAXHISTORY-1); i++) {
|
|
strcpy(msghist[i], msghist[i+1]);
|
|
}
|
|
strcpy(msghist[MAXHISTORY-1], localtext);
|
|
if (db) dblog("replacing last msg hist: %s",localtext);
|
|
}
|
|
free(localtext);
|
|
}
|
|
|
|
void addpromptq(prompt_t *p, char *q) {
|
|
if (p->q[p->nqs]) {
|
|
free(p->q[p->nqs]);
|
|
}
|
|
p->q[p->nqs] = strdup(q);
|
|
p->nqs++;
|
|
}
|
|
|
|
void anim(cell_t *src, cell_t *dst, char ch, int colour) {
|
|
int deltax, deltay;
|
|
int numpixels;
|
|
int d;
|
|
int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2;
|
|
int xinc,yinc,dinc;
|
|
int i;
|
|
int x1,y1;
|
|
int x;
|
|
int y;
|
|
glyph_t gl;
|
|
//int maxvisrange;
|
|
//int modmaxvisrange;
|
|
//int xray = B_FALSE;
|
|
//int wentuphill = B_FALSE;
|
|
|
|
int x2,y2;
|
|
|
|
// just in case
|
|
if (src->map != dst->map) return;
|
|
|
|
x1 = src->x;
|
|
y1 = src->y;
|
|
x2 = dst->x;
|
|
y2 = dst->y;
|
|
|
|
deltax = (x2 - x1);
|
|
if (deltax < 0) deltax = -deltax;
|
|
deltay = (y2 - y1);
|
|
if (deltay < 0) deltay = -deltay;
|
|
|
|
// going nowhere
|
|
if ((deltax == 0) && (deltay == 0)) {
|
|
return;
|
|
}
|
|
|
|
if (deltax >= deltay) {
|
|
numpixels = deltax + 1;
|
|
d = (deltay*2) - deltax;
|
|
dinc1 = deltay << 1;
|
|
dinc2 = (deltay-deltax) << 1;
|
|
xinc1 = 1;
|
|
xinc2 = 1;
|
|
yinc1 = 0;
|
|
yinc2 = 1;
|
|
} else {
|
|
numpixels = deltay + 1;
|
|
d = (deltax*2) - deltay;
|
|
dinc1 = deltax << 1;
|
|
dinc2 = (deltax - deltay) << 1;
|
|
xinc1 = 0;
|
|
xinc2 = 1;
|
|
yinc1 = 1;
|
|
yinc2 = 1;
|
|
}
|
|
|
|
if (x1 > x2) {
|
|
xinc1 = - xinc1;
|
|
xinc2 = - xinc2;
|
|
}
|
|
if (y1 > y2) {
|
|
yinc1 = - yinc1;
|
|
yinc2 = - yinc2;
|
|
}
|
|
|
|
|
|
x = x1; y = y1;
|
|
|
|
gl.ch = ch;
|
|
gl.colour = colour;
|
|
// hide cursor
|
|
curs_set(0);
|
|
for (i = 0; i < numpixels ; i++) {
|
|
cell_t *cell;
|
|
|
|
// get current cell
|
|
cell = getcellat(src->map, x, y);
|
|
|
|
// update screen
|
|
if (haslos(player, cell)) {
|
|
updateviewfor(cell);
|
|
drawlevelfor(player);
|
|
// draw char & cursor at its current pos...
|
|
drawglyph(&gl, cell->x - viewx, cell->y - viewy);
|
|
//mvwprintw(gamewin, cell->y - viewy, cell->x - viewx, "%c", gl.ch);
|
|
wmove(gamewin, cell->y - viewy, cell->x - viewx);
|
|
wrefresh(gamewin);
|
|
usleep(ANIMDELAY);
|
|
}
|
|
|
|
// move to next cell
|
|
if (d < 0) {
|
|
xinc = xinc1;
|
|
yinc = yinc1;
|
|
dinc = dinc1;
|
|
} else {
|
|
xinc = xinc2;
|
|
yinc = yinc2;
|
|
dinc = dinc2;
|
|
}
|
|
|
|
d += dinc;
|
|
x += xinc;
|
|
y += yinc;
|
|
}
|
|
// show cursor
|
|
curs_set(1);
|
|
}
|
|
|
|
void animradial(cell_t *src, int radius, char ch, int colour) {
|
|
glyph_t gl;
|
|
int i;
|
|
int x,y;
|
|
cell_t *c;
|
|
|
|
gl.ch = ch;
|
|
gl.colour = colour;
|
|
// hide cursor
|
|
curs_set(0);
|
|
for (i = 0; i <= radius; i++) {
|
|
int drawn = B_FALSE;
|
|
|
|
// update screen
|
|
updateviewfor(src);
|
|
drawlevelfor(player);
|
|
|
|
for (y = src->y - radius ; y <= src->y + radius ; y++) {
|
|
for (x = src->x - radius ; x <= src->x + radius ; x++) {
|
|
c = getcellat(src->map, x, y);
|
|
if (c && haslos(player, c) && (getcelldistorth(src, c) <= i)) {
|
|
// draw char & cursor at its current pos...
|
|
//mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch);
|
|
drawglyph(&gl, c->x - viewx, c->y - viewy);
|
|
drawn = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
wrefresh(gamewin);
|
|
if (drawn) {
|
|
usleep(ANIMDELAY);
|
|
}
|
|
}
|
|
// show cursor
|
|
curs_set(1);
|
|
|
|
}
|
|
|
|
void animradialorth(cell_t *src, int radius, char ch,int colour) {
|
|
glyph_t gl;
|
|
int i;
|
|
int x,y;
|
|
cell_t *c;
|
|
|
|
gl.ch = ch;
|
|
gl.colour = colour;
|
|
// hide cursor
|
|
curs_set(0);
|
|
for (i = 0; i <= radius; i++) {
|
|
int drawn = B_FALSE;
|
|
|
|
// update screen
|
|
updateviewfor(src);
|
|
drawlevelfor(player);
|
|
|
|
for (y = src->y - radius ; y <= src->y + radius ; y++) {
|
|
for (x = src->x - radius ; x <= src->x + radius ; x++) {
|
|
c = getcellat(src->map, x, y);
|
|
if (c && haslos(player, c) && (getcelldist(src, c) <= i)) {
|
|
// draw char & cursor at its current pos...
|
|
//mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch);
|
|
drawglyph(&gl, c->x - viewx, c->y - viewy);
|
|
drawn = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
wrefresh(gamewin);
|
|
if (drawn) {
|
|
usleep(ANIMDELAY);
|
|
}
|
|
}
|
|
// show cursor
|
|
curs_set(1);
|
|
}
|
|
|
|
char askchar(char *prompt, char *validchars, char *def, int showchars) {
|
|
char buf[BUFLEN];
|
|
char *p;
|
|
char temp[2];
|
|
char ch;
|
|
int valid = B_FALSE;
|
|
|
|
wclear(msgwin);
|
|
if (showchars) {
|
|
sprintf(buf, "%s (",prompt);
|
|
for (p = validchars ; *p ; ) {
|
|
temp[0] = *p;
|
|
temp[1] = '\0';
|
|
strcat(buf, temp);
|
|
p++;
|
|
if (*p) {
|
|
strcat(buf, "/");
|
|
}
|
|
}
|
|
strcat(buf, ")");
|
|
} else {
|
|
sprintf(buf, "%s",prompt);
|
|
}
|
|
if (def) {
|
|
strcat(buf, " [");
|
|
strcat(buf, def);
|
|
strcat(buf, "]");
|
|
}
|
|
strcat(buf, "? ");
|
|
|
|
mvwprintw(msgwin, 0, 0, buf);
|
|
wrefresh(msgwin);
|
|
|
|
valid = B_FALSE;
|
|
while (!valid) {
|
|
ch = getkey();
|
|
if (strchr(validchars, ch)) {
|
|
valid = B_TRUE;
|
|
} else if ((ch == 10) && def) { // enter = default
|
|
valid = B_TRUE;
|
|
} else {
|
|
valid = B_FALSE;
|
|
}
|
|
}
|
|
clearmsg();
|
|
if ((ch == 13) && def) {
|
|
return def[0];
|
|
}
|
|
return ch;
|
|
}
|
|
|
|
cell_t *askcoords(char *prompt, int targettype) {
|
|
static int startlf = -1;
|
|
int finished = B_FALSE;
|
|
int moved = B_FALSE;
|
|
cell_t *c,*newcell;
|
|
char buf[BUFLEN];
|
|
cell_t *target[MAX_MAPW*MAX_MAPH];
|
|
int ntargets = 0,curtarget = -1;
|
|
int x,y;
|
|
|
|
// remember previously targetted lifeforms
|
|
if (startlf > 0) {
|
|
if (!findlf(player->cell->map, startlf)) {
|
|
startlf = -1;
|
|
}
|
|
}
|
|
|
|
// build list of targets if required
|
|
if (targettype != TT_NONE) {
|
|
for (y = 0; y < player->cell->map->h; y++) {
|
|
for (x = 0; x < player->cell->map->w; x++) {
|
|
c = getcellat(player->cell->map, x, y);
|
|
if (c && haslos(player, c)) {
|
|
int valid = B_FALSE;
|
|
if ((targettype & TT_MONSTER) && haslf(c) && cansee(player, c->lf) && (c->lf->controller != C_PLAYER)) {
|
|
valid = B_TRUE;
|
|
} else if ((targettype & TT_PLAYER) && haslf(c) && cansee(player, c->lf) && (c->lf->controller == C_PLAYER)) {
|
|
valid = B_TRUE;
|
|
} else if ((targettype & TT_OBJECT) && hasobject(c)) {
|
|
valid = B_TRUE;
|
|
} else if ((targettype & TT_DOOR) && hasobwithflag(c->obpile, F_DOOR)) {
|
|
valid = B_TRUE;
|
|
}
|
|
|
|
if (valid) {
|
|
target[ntargets] = c;
|
|
if (curtarget == -1) curtarget = ntargets;
|
|
ntargets++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// start prompting
|
|
|
|
if (curtarget == -1) {
|
|
c = player->cell;
|
|
} else {
|
|
int i;
|
|
// override curtarget based on previous target
|
|
for (i = 0; i < ntargets; i++) {
|
|
if (target[i]->lf && (target[i]->lf->id == startlf)) {
|
|
curtarget = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
c = target[curtarget];
|
|
}
|
|
|
|
|
|
wclear(msgwin);
|
|
mvwprintw(msgwin, 0, 0, "%s", prompt);
|
|
wrefresh(msgwin);
|
|
|
|
while (!finished) {
|
|
int dir;
|
|
char ch;
|
|
|
|
drawstatus();
|
|
updateviewfor(c);
|
|
drawlevelfor(player);
|
|
|
|
if (moved) {
|
|
// show what we are over in msg bar
|
|
strcpy(buf, "");
|
|
if (haslos(player, c)) {
|
|
// can see the cell...
|
|
if (c->lf) {
|
|
if (cansee(player, c->lf)) {
|
|
flag_t *f;
|
|
object_t *wep;
|
|
char extrainfo[BUFLEN];
|
|
strcpy(extrainfo, "");
|
|
getlfnamea(c->lf, buf);
|
|
// level
|
|
/*
|
|
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) {
|
|
sprintf(extrainfo, "level %d, ",c->lf->level);
|
|
}
|
|
*/
|
|
switch (getallegiance(c->lf)) {
|
|
case AL_FRIENDLY:
|
|
if (!isplayer(c->lf)) {
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
strcat(extrainfo, "ally");
|
|
}
|
|
break;
|
|
case AL_PEACEFUL:
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
strcat(extrainfo, "peaceful");
|
|
break;
|
|
case AL_HOSTILE:
|
|
break;
|
|
}
|
|
|
|
if (isfleeing(c->lf)) {
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
strcat(extrainfo, "fleeing");
|
|
}
|
|
if (lfhasflag(c->lf, F_ASLEEP)) {
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
strcat(extrainfo, "asleep");
|
|
}
|
|
// hp
|
|
if (isgenius(player)) {
|
|
char buf2[BUFLEN];
|
|
// show actual hp
|
|
sprintf(buf2, "hp %d/%d",c->lf->hp, c->lf->maxhp);
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
strcat(extrainfo, buf2);
|
|
} else {
|
|
char buf2[BUFLEN];
|
|
// show condition name
|
|
sprintf(buf2, "%s",getseenlfconditionname(c->lf, player));
|
|
if (strlen(buf2)) {
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
strcat(extrainfo, buf2);
|
|
}
|
|
}
|
|
|
|
wep = getweapon(c->lf);
|
|
if (wep) {
|
|
object_t *secwep;
|
|
char obname[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
getobname(wep, obname, wep->amt);
|
|
sprintf(buf2, "weilding %s",obname);
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
|
|
secwep = getequippedob(c->lf->pack, BP_SECWEAPON);
|
|
if (secwep && (secwep != wep)) {
|
|
getobname(secwep, obname, secwep->amt);
|
|
strcat(buf2, " and ");
|
|
strcat(buf2, obname);
|
|
}
|
|
strcat(extrainfo, buf2);
|
|
} else {
|
|
wep = getequippedob(c->lf->pack, BP_SECWEAPON);
|
|
if (wep) {
|
|
char obname[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
getobname(wep, obname, wep->amt);
|
|
sprintf(buf2, "weilding %s",obname);
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
strcat(extrainfo, buf2);
|
|
}
|
|
}
|
|
|
|
f = lfhasflag(c->lf, F_GRABBING);
|
|
if (f) {
|
|
lifeform_t *lf2;
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
char lfname2[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
getlfname(lf2, lfname2);
|
|
sprintf(buf2, "holding %s",lfname2);
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
strcat(extrainfo, buf2);
|
|
}
|
|
}
|
|
|
|
f = lfhasflag(c->lf, F_GRABBEDBY);
|
|
if (f) {
|
|
lifeform_t *lf2;
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
char lfname2[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
getlfname(lf2, lfname2);
|
|
sprintf(buf2, "held by %s",lfname2);
|
|
if (strlen(extrainfo)) strcat(extrainfo, ", ");
|
|
strcat(extrainfo, buf2);
|
|
}
|
|
}
|
|
|
|
if (strlen(extrainfo)) {
|
|
char buf2[BUFLEN];
|
|
sprintf(buf2, " [%s]",extrainfo);
|
|
strcat(buf, buf2);
|
|
}
|
|
} else {
|
|
void *thing;
|
|
// lf there but can't see it
|
|
if (isinscanrange(c, &thing, buf, NULL) == TT_MONSTER) {
|
|
// if scanned, show it.
|
|
} else {
|
|
// otherwise, show objects
|
|
object_t *o;
|
|
// find top object name
|
|
o = gettopobject(c);
|
|
if (o) {
|
|
getobname(o, buf, o->amt);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
object_t *o;
|
|
// find top object name
|
|
o = gettopobject(c);
|
|
if (o) {
|
|
getobname(o, buf, o->amt);
|
|
}
|
|
}
|
|
} else {
|
|
// can't see objects or lf there
|
|
void *thing;
|
|
char desc[BUFLEN];
|
|
switch (isinscanrange(c, &thing, desc, NULL)) {
|
|
case TT_MONSTER:
|
|
case TT_OBJECT:
|
|
strcpy(buf, desc);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
// dont use msg() to avoid 'more's
|
|
capitalise(buf);
|
|
wclear(msgwin);
|
|
mvwprintw(msgwin, 0, 0, "%s",buf);
|
|
wrefresh(msgwin);
|
|
}
|
|
|
|
|
|
// move cursor selected position
|
|
wmove(gamewin, c->y - viewy, c->x - viewx);
|
|
redraw();
|
|
|
|
// get input
|
|
ch = getch();
|
|
if (ch == '.') {
|
|
clearmsg();
|
|
|
|
// remember this target
|
|
if (c->lf) {
|
|
startlf = c->lf->id;
|
|
}
|
|
return c;
|
|
} else if (ch == 27) { // ESC - cancel
|
|
finished = B_TRUE;
|
|
} else if ((ch == '\'') && (ntargets > 0)) { // cycle targets
|
|
if (curtarget != -1) { // -1 means no targets
|
|
curtarget++;
|
|
if (curtarget >= ntargets) curtarget = 0;
|
|
c = target[curtarget];
|
|
moved = B_TRUE;
|
|
}
|
|
} else {
|
|
dir = chartodir(ch);
|
|
if (dir != D_NONE) {
|
|
newcell = getcellindir(c, dir);
|
|
if (newcell) {
|
|
c = newcell;
|
|
moved = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
clearmsg();
|
|
return NULL;
|
|
}
|
|
|
|
// retbuf must already be allocated
|
|
// "def" is optional
|
|
char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def) {
|
|
char buf[BUFLEN];
|
|
char *ending;
|
|
|
|
wclear(msgwin);
|
|
sprintf(buf, "%s",prompt);
|
|
if (def) {
|
|
strcat(buf, " [");
|
|
strcat(buf, def);
|
|
strcat(buf, "]");
|
|
}
|
|
|
|
asprintf(&ending, "%c ",punc);
|
|
strcat(buf, ending);
|
|
free(ending);
|
|
mvwprintw(msgwin, 0, 0, buf);
|
|
wrefresh(msgwin);
|
|
echo();
|
|
wgetnstr(msgwin, retbuf, retbuflen);
|
|
noecho();
|
|
clearmsg();
|
|
if (def && (strlen(retbuf) == 0)) {
|
|
strcpy(retbuf, def);
|
|
}
|
|
return retbuf;
|
|
}
|
|
|
|
/*
|
|
void announceob(enum OBTYPE oid) {
|
|
switch (oid) {
|
|
case OT_RING_INVULN:
|
|
msg("You feel indestructable!");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
|
|
int announceflaggain(lifeform_t *lf, flag_t *f) {
|
|
int donesomething = B_FALSE;
|
|
lifeform_t *lf2;
|
|
char lfname[BUFLEN];
|
|
char buf[BUFLEN];
|
|
char *buf2;
|
|
|
|
if (!lf->born) {
|
|
return B_FALSE;
|
|
}
|
|
|
|
if (lf->race->id == R_DANCINGWEAPON) {
|
|
return B_FALSE;
|
|
}
|
|
|
|
getlfname(lf, lfname);
|
|
|
|
if (isdead(player)) return B_FALSE;
|
|
|
|
// player can't see this?
|
|
// We need to check "!isplayer(lf)" as well, otherwise
|
|
// we'll get no announcement when the player turns
|
|
// invisible and doesn't have see invisible.
|
|
if (!isplayer(lf) && !cansee(player, lf)) {
|
|
return B_FALSE;
|
|
}
|
|
|
|
switch (f->id) {
|
|
case F_ATTRMOD:
|
|
switch (f->val[0]) {
|
|
case A_STR:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "weaker" : "stronger");
|
|
break;
|
|
case A_IQ:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "foolish" : "smarter");
|
|
break;
|
|
case A_DEX:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "sluggish" : "agile");
|
|
break;
|
|
case A_CON:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "frail" : "healthier");
|
|
break;
|
|
}
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_ATTRSET:
|
|
if (f->val[1] != getattr(lf, f->val[0])) {
|
|
int myatt;
|
|
myatt = getattr(lf, f->val[0]);
|
|
switch (f->val[0]) {
|
|
case A_STR:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < myatt) ? "weak" : "strong");
|
|
break;
|
|
case A_IQ:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < myatt) ? "foolish" : "smart");
|
|
break;
|
|
case A_DEX:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < myatt) ? "sluggish" : "agile");
|
|
break;
|
|
case A_CON:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] < 0) ? "frail" : "healthier");
|
|
break;
|
|
}
|
|
}
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_MAGICARMOUR:
|
|
msg("%s %s appears around %s!",needan(f->text) ? "An" : "A", f->text, lfname);
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_ASLEEP:
|
|
msg("%s fall%s asleep.",lfname, isplayer(lf) ? "" : "s");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_BEINGSTONED:
|
|
msg("%s begin%s to turn to stone!",lfname, isplayer(lf) ? "" : "s");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_BLIND:
|
|
if (isplayer(lf)) {
|
|
msg("%s cannot see!",lfname);
|
|
} else {
|
|
msg("%s is blinded!",lfname);
|
|
}
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_CANCAST:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
objecttype_t *ot;
|
|
ot = findot(f->val[0]);
|
|
if (ot) {
|
|
msg("You have learned the spell '%s'.", ot->name);
|
|
donesomething = B_TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case F_CANWILL:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
objecttype_t *ot;
|
|
ot = findot(f->val[0]);
|
|
if (ot && (!hasflag(ot->flags, F_NOANNOUNCE))) {
|
|
msg("You have learned the ability '%s'.", ot->name);
|
|
donesomething = B_TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case F_CHARMEDBY:
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
getlfname(lf2, buf);
|
|
msg("%s %s now under %s%s power!",lfname, isplayer(lf) ? "are" : "is", buf,getpossessive(buf));
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_CONTROL:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel very in control of yourself.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DTIMMUNE:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel immune to %s!", getdamnamenoun(f->val[0]));
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DTRESIST:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel resistant to %s!", getdamnamenoun(f->val[0]));
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DTVULN:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel vulnerable to %s!", getdamnamenoun(f->val[0]));
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTAURAS:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel aware of spiritual auras around you.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTLIFE:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You can now detect nearby lifeforms.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTOBS:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You can now detect nearby objects.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTMAGIC:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel sensitive to magical enchantments.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTMETAL:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You can now detect nearby metal.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DODGES:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You can now dodge attacks.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_INVISIBLE:
|
|
if (isplayer(lf)) {
|
|
if (lfhasflag(player, F_SEEINVIS)) {
|
|
msg("Your body turns transparent!");
|
|
} else {
|
|
msg("Your body turns invisible!");
|
|
}
|
|
donesomething = B_TRUE;
|
|
} else {
|
|
if (lfhasflag(player, F_SEEINVIS)) {
|
|
msg("%s turns transparent!", lfname);
|
|
donesomething = B_TRUE;
|
|
} else {
|
|
msg("%s vanishes!", lfname);
|
|
}
|
|
}
|
|
break;
|
|
case F_INVULNERABLE:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel invulnerable!");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_FLEEFROM:
|
|
// who are they fleeing from?
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
getlfname(lf2, buf);
|
|
msg("%s turn%s to flee from %s!", lfname, isplayer(lf) ? "" : "s",
|
|
(cansee(player, lf2) || isplayer(lf2)) ? buf : "something");
|
|
}
|
|
break;
|
|
case F_POISONED:
|
|
msg("%s %s very sick.", lfname, isplayer(lf) ? "feel" : "looks");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_EXTRADAM:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel more dangerous!");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_EXTRAMP:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("Your magical power feels boosted!");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_EXTRALUCK:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel lucky!");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_FASTACT:
|
|
msg("%s %s",lfname, isplayer(lf) ? "feel accelerated!" : "looks accelerated!");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_FASTMOVE:
|
|
msg("%s %s faster.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_FLYING:
|
|
msg("%s begin%s to fly!",lfname, isplayer(lf) ? "" : "s");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_FROZEN:
|
|
// strip "frozen" out...
|
|
buf2 = strdup(lfname);
|
|
buf2 = strrep(buf2, "frozen ","",NULL);
|
|
msg("%s %s to ice!",lfname, isplayer(lf) ? "turn" : "turns");
|
|
donesomething = B_TRUE;
|
|
free(buf2);
|
|
break;
|
|
case F_GRABBEDBY:
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
getlfname(lf2, buf);
|
|
msg("%s %s %s!",buf, isplayer(lf2) ? "grab" : "grabs", lfname);
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
// don't announce grabbing.
|
|
case F_GRAVBOOSTED:
|
|
msg("%s %s stuck to the floor!",lfname, isplayer(lf) ? "are" : "is");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_LEVITATING:
|
|
msg("%s begin%s to levitate in the air!",lfname, isplayer(lf) ? "" : "s");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_MAGSHIELD:
|
|
msg("%s %s surrounded by a magnetic shield!",lfname, isplayer(lf) ? "are" : "is");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_NAUSEATED:
|
|
if (isplayer(lf)) {
|
|
msg("You are nauseated by a disgusting stench!");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_NONCORPOREAL:
|
|
msg("%s%s body becomes transparent!",lfname, getpossessive(lfname));
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_PAIN:
|
|
msg("%s%s skin erupts in stings and burns!",lfname, getpossessive(lfname));
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_PARALYZED:
|
|
if (isplayer(lf)) {
|
|
msg("You cannot move!");
|
|
} else {
|
|
msg("%s stops moving!",lfname);
|
|
}
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_PHOTOMEM:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You will no longer forget your surroundings.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_PRODUCESLIGHT:
|
|
msg("%s start%s producing light!", lfname, isplayer(lf) ? "" : "s");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_REGENERATES:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("Your body's healing rate is enhanced!");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_RESISTMAG:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel %simmune to magic.", hasflag_real(lf->flags, F_RESISTMAG, NA, f) ? "more " : "");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_SEEINVIS:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You vision seems enhanced.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_SEEINDARK:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You can now see in the dark.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_SLOWACT:
|
|
msg("%s %s",lfname, isplayer(lf) ? "feel sluggish." : "looks sluggish.");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_SLOWMOVE:
|
|
msg("%s %s slower.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_SPRINTING:
|
|
msg("%s %s sprinting!",lfname, isplayer(lf) ? "start" : "starts");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
|
|
case F_TIRED:
|
|
if (isplayer(lf)) {
|
|
msg("You are exhausted.");
|
|
} else if (cansee(player, lf)) {
|
|
msg("%s looks exhausted.",lfname);
|
|
}
|
|
break;
|
|
case F_WINDSHIELD:
|
|
if (isplayer(lf)) {
|
|
msg("You are surrounded by a whirling cyclone!");
|
|
} else if (cansee(player, lf)) {
|
|
msg("%s is surrounded by a whirling cyclone!",lfname);
|
|
}
|
|
break;
|
|
case F_VISRANGEMOD:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
char fartext[BUFLEN];
|
|
if (f->val[0] > 0) {
|
|
int amt;
|
|
amt = abs(f->val[0]);
|
|
if (amt >= 7) {
|
|
strcpy(fartext, "a lot ");
|
|
} else if (amt >= 5) {
|
|
strcpy(fartext, "");
|
|
} else {
|
|
strcpy(fartext, "a little ");
|
|
}
|
|
msg("You can see %sfurther.", fartext);
|
|
} else {
|
|
int amt;
|
|
amt = abs(f->val[0]);
|
|
if (amt >= 7) {
|
|
msg("Your vision is dramatically reduced.");
|
|
} else if (amt >= 5) {
|
|
msg("Your vision is reduced.");
|
|
} else {
|
|
msg("Your vision is slightly reduced.");
|
|
}
|
|
}
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_XRAYVIS:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("The walls around you suddenly turn transparent!");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
default: // no message
|
|
break;
|
|
}
|
|
|
|
if (donesomething) statdirty = B_TRUE;
|
|
|
|
return donesomething;
|
|
}
|
|
|
|
int announceflagloss(lifeform_t *lf, flag_t *f) {
|
|
char lfname[BUFLEN];
|
|
lifeform_t *lf2;
|
|
int donesomething = B_FALSE;
|
|
|
|
if (lf->race->id == R_DANCINGWEAPON) {
|
|
return B_FALSE;
|
|
}
|
|
|
|
if (isdead(lf) || isdead(player)) return B_FALSE;
|
|
getlfname(lf, lfname);
|
|
|
|
// player can't see?
|
|
if (!cansee(player, lf)) {
|
|
return B_FALSE;
|
|
}
|
|
switch (f->id) {
|
|
case F_ATTRMOD:
|
|
switch (f->val[0]) {
|
|
case A_STR:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less strong" : "less weak");
|
|
break;
|
|
case A_IQ:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less smart" : "less foolish");
|
|
break;
|
|
case A_DEX:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less agile" : "less sluggish");
|
|
break;
|
|
case A_CON:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less healthy" : "less frail");
|
|
break;
|
|
}
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_ATTRSET:
|
|
if (f->val[1] != getattr(lf, f->val[0])) {
|
|
int myatt;
|
|
myatt = getattr(lf, f->val[0]);
|
|
switch (f->val[0]) {
|
|
case A_STR:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > myatt) ? "less strong" : "less weak");
|
|
break;
|
|
case A_IQ:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > myatt) ? "less smart" : "less foolish");
|
|
break;
|
|
case A_DEX:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > myatt) ? "less agile" : "less sluggish");
|
|
break;
|
|
case A_CON:
|
|
msg("%s %s %s!",lfname, isplayer(lf) ? "feel" : "seems", (f->val[1] > 0) ? "less healthy" : "less frail");
|
|
break;
|
|
}
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_MAGICARMOUR:
|
|
msg("%s%s %s vanishes.",lfname,getpossessive(lfname), f->text);
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_ASLEEP:
|
|
msg("%s wake%s up.",lfname, isplayer(lf) ? "" : "s");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_BEINGSTONED:
|
|
msg("The fragments of stone around %s%s body drop%s away.",lfname, getpossessive(lfname), isplayer(lf) ? "" : "s");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_BLIND:
|
|
msg("%s can see again.",lfname);
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_CANCAST:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
objecttype_t *ot;
|
|
ot = findot(f->val[0]);
|
|
if (ot) {
|
|
msg("You have forgotten how to cast '%s'.", ot->name);
|
|
donesomething = B_TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case F_CANWILL:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
objecttype_t *ot;
|
|
ot = findot(f->val[0]);
|
|
if (ot && (!hasflag(ot->flags, F_NOANNOUNCE))) {
|
|
msg("You can no longer use the ability '%s'.", ot->name);
|
|
donesomething = B_TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case F_CHARMEDBY:
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
char buf[BUFLEN];
|
|
getlfname(lf2, buf);
|
|
msg("%s break%s free of %s%s control!",lfname, isplayer(lf) ? "" : "s", buf,getpossessive(buf));
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_CONTROL:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You feel less controlled.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DTIMMUNE:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You are no longer immune to %s.", getdamnamenoun(f->val[0]));
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DTRESIST:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You are no longer resistant to %s.", getdamnamenoun(f->val[0]));
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DTVULN:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You are no longer vulnerable to %s.", getdamnamenoun(f->val[0]));
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_EXTRADAM:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You no longer feel more dangerous.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_EXTRALUCK:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You feel less lucky.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_EXTRAMP:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("Your magical power no longer feels boosted.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_FASTACT:
|
|
msg("%s %s",lfname, isplayer(lf) ? "are no longer accelerated." : "is no longer accelerated.");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_FASTMOVE:
|
|
msg("%s %s slower.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_FLEEFROM:
|
|
msg("%s stop%s fleeing.", lfname, isplayer(lf) ? "" : "s");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_FRIENDLY:
|
|
msg("%s no longer looks quite so friendly!", lfname);
|
|
break;
|
|
case F_POISONED:
|
|
msg("%s %s less sick now.", lfname, isplayer(lf) ? "feel" : "looks");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_DODGES:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You can no longer dodge attacks.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_INVISIBLE:
|
|
if (isplayer(lf)) {
|
|
msg("Your are no longer invisible.");
|
|
donesomething = B_TRUE;
|
|
} else {
|
|
if (lfhasflag(player, F_SEEINVIS)) {
|
|
msg("%s is no longer transparent.", lfname);
|
|
donesomething = B_TRUE;
|
|
} else {
|
|
msg("%s appears out of nowhere!", lfname);
|
|
}
|
|
}
|
|
break;
|
|
case F_INVULNERABLE:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You no longer feel invulnerable.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTAURAS:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You can no longer detect auras.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTLIFE:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You can no longer detect nearby lifeforms.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTOBS:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You can no longer detect nearby objects.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTMAGIC:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You can no longer detect magical enchantments.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_DETECTMETAL:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You can no longer detect nearby metal.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_FLYING:
|
|
msg("%s %s flying.", lfname, isplayer(lf) ? "cease" : "stops");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_FROZEN:
|
|
if (isplayer(lf)) {
|
|
msg("You thaw out.");
|
|
} else {
|
|
msg("%s thaws out.", lfname);
|
|
}
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_GRABBEDBY:
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2 && !isdead(lf2)) {
|
|
char buf[BUFLEN];
|
|
getlfname(lf2, buf);
|
|
msg("%s break%s free from %s!",lfname, isplayer(lf) ? "" : "s", buf);
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_GRAVBOOSTED:
|
|
msg("%s %s no longer stuck to the floor.",lfname, isplayer(lf) ? "are" : "is");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_LEVITATING:
|
|
msg("%s %s down to the ground.", lfname, isplayer(lf) ? "float" : "floats");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_MAGSHIELD:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("Your magnetic shield vanishes.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_NAUSEATED:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You no longer feel nauseated.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_NONCORPOREAL:
|
|
msg("%s%s body solidifies.",lfname, getpossessive(lfname));
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_PAIN:
|
|
if (isplayer(lf)) { // don't konw if it expires for monsters
|
|
msg("Your skin stops hurting.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_PARALYZED:
|
|
if (isplayer(lf)) { // don't konw if it expires for monsters
|
|
msg("You can move again.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_PHOTOMEM:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("Your feel like you might forget your surroundings.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_PRODUCESLIGHT:
|
|
msg("%s %s no longer producing light.", lfname, isplayer(lf) ? "are" : "is");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_REGENERATES:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("Your healing rate is no longer enhanced.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_RESISTMAG:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
if (hasflag_real(lf->flags, F_RESISTMAG, NA, f)) {
|
|
msg("You feel less immune to magic.");
|
|
} else {
|
|
msg("You are no longer immune to magic.");
|
|
}
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
/*
|
|
case F_RESTCOUNT:
|
|
if (isplayer(lf)) {
|
|
msg("Restcount expired.");
|
|
}
|
|
break;
|
|
*/
|
|
case F_SEEINVIS:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You vision returns to normal.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_SEEINDARK:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("You can no longer see in the dark.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_SLOWACT:
|
|
msg("%s %s",lfname, isplayer(lf) ? "no longer feel sluggish." : "no longer looks sluggish.");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_SLOWMOVE:
|
|
msg("%s %s faster.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_SPRINTING:
|
|
if (f->val[0]) {
|
|
if (isplayer(lf)) { // don't know if monsters lose it (but you'll see them get exhausted)
|
|
msg("You stop sprinting.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
} else {
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You are no longer exhausted.");
|
|
} else {
|
|
msg("%s looks less exhausted.",lfname);
|
|
}
|
|
}
|
|
break;
|
|
case F_TIRED:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
msg("You are no longer exhausted.");
|
|
} else {
|
|
msg("%s looks less exhausted.",lfname);
|
|
}
|
|
donesomething = B_TRUE;
|
|
break;
|
|
case F_WINDSHIELD:
|
|
if (isplayer(lf) || cansee(player, lf)) {
|
|
msg("%s%s cyclonic shield vanishes.", lfname, getpossessive(lfname));
|
|
}
|
|
break;
|
|
case F_VISRANGEMOD:
|
|
if (isplayer(lf)) { // don't know if monsters get it
|
|
char fartext[BUFLEN];
|
|
if (f->val[0] < 0) {
|
|
int amt;
|
|
amt = abs(f->val[0]);
|
|
if (amt >= 7) {
|
|
strcpy(fartext, "a lot ");
|
|
} else if (amt >= 5) {
|
|
strcpy(fartext, "");
|
|
} else {
|
|
strcpy(fartext, "a little ");
|
|
}
|
|
msg("You can see %sfurther.", fartext);
|
|
} else {
|
|
int amt;
|
|
amt = abs(f->val[0]);
|
|
if (amt >= 7) {
|
|
msg("Your vision is dramatically reduced.");
|
|
} else if (amt >= 5) {
|
|
msg("Your vision is reduced.");
|
|
} else {
|
|
msg("Your vision is slightly reduced.");
|
|
}
|
|
}
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
case F_XRAYVIS:
|
|
if (isplayer(lf)) { // don't know if monsters lose it
|
|
msg("The walls around you are no longer transparent.");
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
default: // no message
|
|
break;
|
|
}
|
|
|
|
if (donesomething) statdirty = B_TRUE;
|
|
|
|
return donesomething;
|
|
}
|
|
|
|
|
|
|
|
int announceobflaggain(object_t *o, flag_t *f) {
|
|
int donesomething = B_FALSE;
|
|
char obname[BUFLEN];
|
|
char prefix[BUFLEN];
|
|
cell_t *loc;
|
|
|
|
loc = getoblocation(o);
|
|
|
|
if (isdead(player)) return B_FALSE;
|
|
// player can't see?
|
|
if (!haslos(player, loc)) {
|
|
return B_FALSE;
|
|
}
|
|
real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE);
|
|
|
|
if (o->pile->owner) {
|
|
if (isplayer(o->pile->owner)) {
|
|
sprintf(prefix, "Your %s",noprefix(obname));
|
|
} else {
|
|
char lfname[BUFLEN];
|
|
getlfname(o->pile->owner, lfname);
|
|
sprintf(prefix, "%s%s %s",lfname, getpossessive(lfname), noprefix(obname));
|
|
}
|
|
} else {
|
|
sprintf(prefix, "%s",obname);
|
|
}
|
|
|
|
|
|
switch (f->id) {
|
|
case F_ONFIRE:
|
|
donesomething = B_TRUE;
|
|
// don't want "the flaming sword catches on fire"
|
|
real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_TRUE, B_TRUE);
|
|
if (o->birthtime != curtime) msg("%s catch%s on fire.",prefix, (o->amt == 1) ? "es" : "");
|
|
break;
|
|
case F_PRODUCESLIGHT:
|
|
donesomething = B_TRUE;
|
|
if (o->birthtime != curtime) msg("%s start%s glowing!",prefix, (o->amt == 1) ? "s" : "");
|
|
break;
|
|
default: // no message
|
|
break;
|
|
}
|
|
return donesomething;
|
|
}
|
|
|
|
void announceobflagloss(object_t *o, flag_t *f) {
|
|
char obname[BUFLEN];
|
|
char prefix[BUFLEN];
|
|
char isare[BUFLEN];
|
|
cell_t *loc;
|
|
|
|
loc = getoblocation(o);
|
|
|
|
if (isdead(player)) return;
|
|
// player can't see?
|
|
if (!haslos(player, loc)) {
|
|
return;
|
|
}
|
|
real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE);
|
|
|
|
if (o->pile->owner) {
|
|
if (isplayer(o->pile->owner)) {
|
|
sprintf(prefix, "Your %s",noprefix(obname));
|
|
} else {
|
|
char lfname[BUFLEN];
|
|
getlfname(o->pile->owner, lfname);
|
|
sprintf(prefix, "%s%s %s",lfname, getpossessive(lfname), noprefix(obname));
|
|
}
|
|
} else {
|
|
sprintf(prefix, "%s",obname);
|
|
}
|
|
|
|
if (o->amt == 1) {
|
|
strcpy(isare, "is");
|
|
} else {
|
|
strcpy(isare, "are");
|
|
}
|
|
|
|
switch (f->id) {
|
|
case F_ONFIRE:
|
|
msg("%s %s no longer on fire.",prefix,isare);
|
|
break;
|
|
case F_PRODUCESLIGHT:
|
|
msg("%s %s no longer glowing.",prefix,isare);
|
|
break;
|
|
case F_WET:
|
|
msg("%s %s out.",prefix, (o->amt == 1) ? "dries" : "dry");
|
|
break;
|
|
default: // no message
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
object_t *askobject(obpile_t *op, char *prompt, int *count, long opts) {
|
|
return doaskobject(op, prompt, count, opts, F_NONE);
|
|
}
|
|
|
|
object_t *askobjectwithflag(obpile_t *op, char *prompt, int *count, long opts, enum FLAG withflag) {
|
|
return doaskobject(op, prompt, count, opts, withflag, F_NONE);
|
|
}
|
|
|
|
/*
|
|
object_t *askobjectofclass(obpile_t *op, char *prompt, int *count, long opts, enum OBCLASS obclass) {
|
|
return doaskobject(op, prompt, count, opts, F_NONE, obclass, OC_NULL);
|
|
}
|
|
*/
|
|
|
|
|
|
int contains(enum OBCLASS *array, int nargs, enum OBCLASS want) {
|
|
int i;
|
|
for (i = 0; i < nargs; i++) {
|
|
if (array[i] == want) {
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters) {
|
|
int lastclass = OC_NULL;
|
|
int i;
|
|
int useobletters = B_TRUE;
|
|
if (myletters) {
|
|
useobletters = B_FALSE;
|
|
}
|
|
for (i = firstob ; (mylist[i] != NULL) && (*y < lastline); i++) {
|
|
char selchar;
|
|
char buf[BUFLEN];
|
|
char obname[BUFLEN];
|
|
char infobuf[BUFLEN];
|
|
char equipbuf[BUFLEN];
|
|
if (mylist[i]->type->obclass->id != lastclass) {
|
|
// print class heading
|
|
wattron(win, A_STANDOUT);
|
|
mvwprintw(win, *y, 0, "%s", mylist[i]->type->obclass->name);
|
|
(*y)++;
|
|
wattroff(win, A_STANDOUT);
|
|
|
|
lastclass = mylist[i]->type->obclass->id;
|
|
|
|
}
|
|
// print object name
|
|
getobname(mylist[i], obname,mylist[i]->amt);
|
|
|
|
if (sellist && sellist[i]) {
|
|
if ((selcount[i] == ALL) || (selcount[i] == mylist[i]->amt)) {
|
|
selchar = '*';
|
|
} else {
|
|
selchar = '#';
|
|
}
|
|
} else {
|
|
selchar = ' ';
|
|
}
|
|
|
|
sprintf(buf, "%c %c - %s", selchar, useobletters ? mylist[i]->letter : myletters[i],
|
|
obname);
|
|
|
|
if (mylist[i]->blessknown) {
|
|
if (iscursed(mylist[i])) {
|
|
setcol(win, C_RED);
|
|
} else if (isblessed(mylist[i])) {
|
|
setcol(win, C_CYAN);
|
|
}
|
|
}
|
|
getobextrainfo(mylist[i], infobuf);
|
|
getobequipinfo(mylist[i], equipbuf);
|
|
|
|
mvwprintw(win, *y, 0, "%s%s", buf, infobuf);
|
|
|
|
if (mylist[i]->blessknown) {
|
|
if (iscursed(mylist[i])) {
|
|
unsetcol(win, C_RED);
|
|
} else if (isblessed(mylist[i])) {
|
|
unsetcol(win, C_CYAN);
|
|
}
|
|
}
|
|
|
|
if (strlen(equipbuf)) {
|
|
setcol(win, C_BROWN);
|
|
wprintw(win, "%s", equipbuf);
|
|
unsetcol(win, C_BROWN);
|
|
}
|
|
(*y)++;
|
|
|
|
}
|
|
*counter = i;
|
|
}
|
|
|
|
object_t *doaskobject(obpile_t *op, char *prompt, int *count, long opts, ...) {
|
|
int c,i;
|
|
object_t *mylist[MAXPILEOBS+1];
|
|
char myletters[MAXPILEOBS+1];
|
|
char numstring[BUFLEN];
|
|
int firstob = 0;
|
|
int nextpage = -1;
|
|
int lastline = SCREENH-4;
|
|
int finished;
|
|
char nextlet = 'a';
|
|
int useobletters;
|
|
//flag_t *f;
|
|
object_t *ammo;
|
|
enum FLAG wantflag[MAXCANDIDATES];
|
|
va_list flags;
|
|
int nwantflags;
|
|
|
|
// construct list of valid obclasses
|
|
va_start(flags, opts);
|
|
nwantflags = 0;
|
|
wantflag[nwantflags] = va_arg(flags, enum FLAG);
|
|
while (wantflag[nwantflags] != F_NONE) {
|
|
nwantflags++;
|
|
wantflag[nwantflags] = va_arg(flags, enum FLAG);
|
|
}
|
|
va_end(flags);
|
|
dblog("nwantflags is %d",nwantflags);
|
|
|
|
// remember player's current ammo
|
|
if (op->owner) {
|
|
ammo = getammo(op->owner);
|
|
}
|
|
|
|
if (countobs(op) <= 0) {
|
|
// no objects in pack
|
|
cls();
|
|
mvwprintw(mainwin, 2, 0, "You have no possessions.");
|
|
// wait for key
|
|
centre(mainwin, getmaxy(mainwin)-1, "[Press any key]");
|
|
getch();
|
|
|
|
clearmsg();
|
|
drawscreen();
|
|
return NULL;
|
|
}
|
|
|
|
reason = E_OK;
|
|
|
|
// if picking form a player's pack, use the object's letters.
|
|
// otherwise just label them a, b, c, etc.
|
|
if (op->owner && (op->owner->controller == C_PLAYER)) {
|
|
useobletters = B_TRUE;
|
|
} else {
|
|
useobletters = B_FALSE;
|
|
}
|
|
|
|
// construct a list of objects
|
|
c = 0;
|
|
i = 0;
|
|
while (sortorder[c] != OC_NULL) {
|
|
object_t *o;
|
|
//if (!wantoc || (sortorder[c] == wantoc->id)) {
|
|
//if (!nwantflags || contains(wantflag, nwantflags, sortorder[c])) {
|
|
// add all objects of this class
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o->type->obclass->id == sortorder[c]) {
|
|
int ok;
|
|
int n;
|
|
// can we include this object?
|
|
ok = B_TRUE;
|
|
|
|
// check for wanted flags
|
|
for (n = 0; n < nwantflags; n++) {
|
|
if (!hasflag(o->flags, wantflag[n])) {
|
|
ok = B_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (ok) {
|
|
if (opts & AO_SPECIFIED) {
|
|
int n;
|
|
int found = B_FALSE;
|
|
// does retlist contain this?
|
|
for (n = 0; n < nretobs; n++) {
|
|
if (retobs[n] == o) {
|
|
found = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
ok = B_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ok) {
|
|
ok = obmatchescondition(o, opts);
|
|
}
|
|
|
|
if (ok) {
|
|
mylist[i] = o;
|
|
myletters[i] = nextlet;
|
|
if (++nextlet > 'z') nextlet = 'A';
|
|
i++;
|
|
}
|
|
} // end if ob matches sortorder
|
|
} // end for each ob
|
|
c++;
|
|
}
|
|
mylist[i] = NULL;
|
|
|
|
// start displaying from the first one
|
|
firstob = 0;
|
|
nextpage = -1;
|
|
finished = B_FALSE;
|
|
strcpy(numstring, "");
|
|
while (!finished) {
|
|
int y;
|
|
int ch;
|
|
|
|
cls();
|
|
|
|
// list the objects
|
|
y = 2;
|
|
|
|
listobs(mainwin, mylist, NULL, NULL, firstob, &i, lastline, &y, useobletters ? NULL : myletters );
|
|
|
|
if (mylist[i] == NULL) {
|
|
nextpage = -1;
|
|
} else {
|
|
nextpage = i;
|
|
}
|
|
// draw prompt
|
|
if (strlen(numstring) > 0) {
|
|
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit) [%s]: ",prompt,
|
|
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "",
|
|
numstring);
|
|
} else {
|
|
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit): ", prompt,
|
|
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "");
|
|
}
|
|
if (nextpage != -1) {
|
|
mvwprintw(mainwin, y, 0, MORESTRING);
|
|
}
|
|
// update screen
|
|
wrefresh(mainwin);
|
|
// wait for keypess
|
|
ch = getch();
|
|
if (ch == 27) { // ESCAPE
|
|
finished = B_TRUE;
|
|
break;
|
|
}
|
|
// otherwise look for shift key etc..
|
|
ch = keycodetokey(ch);
|
|
// then handle input
|
|
if (ch == ' ') { // next page
|
|
if (nextpage == -1) { // go to first page
|
|
firstob = 0;
|
|
} else {
|
|
firstob = nextpage;
|
|
}
|
|
} else if (isalpha(ch) || (ch == '$')) {
|
|
object_t *o;
|
|
// describe that object
|
|
if (useobletters) {
|
|
o = findobl(op, ch);
|
|
} else {
|
|
o = NULL;
|
|
for (i = firstob ; (mylist[i] != NULL) && (y < lastline); i++) {
|
|
if (myletters[i] == ch) {
|
|
o = mylist[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (o) {
|
|
// make sure count is okay...
|
|
if (count && *count > o->amt) {
|
|
*count = o->amt;
|
|
}
|
|
if (count && (*count == ALL)) {
|
|
*count = o->amt;
|
|
}
|
|
// display game windows again
|
|
clearmsg();
|
|
drawscreen();
|
|
return o;
|
|
}
|
|
} else if ((ch == '-') && (opts & AO_INCLUDENOTHING)) { // select nothing
|
|
reason = E_SELNOTHING;
|
|
// display game windows again
|
|
clearmsg();
|
|
drawscreen();
|
|
return NULL;
|
|
} else if (isdigit(ch) && count) {
|
|
char temp[2];
|
|
temp[0] = ch;
|
|
temp[1] = '\0';
|
|
strcat(numstring, temp);
|
|
if (count) *count = atoi(numstring);
|
|
} else if ((ch == 8) && count) { // backspace
|
|
if (strlen(numstring) > 0) {
|
|
// remove last letter of number string
|
|
numstring[strlen(numstring)-1] = '\0';
|
|
if (count) *count = atoi(numstring);
|
|
}
|
|
}
|
|
|
|
// sanity check count...
|
|
if (count && (*count == 0)) {
|
|
strcpy(numstring, "");
|
|
}
|
|
}
|
|
|
|
// clear msg bar
|
|
clearmsg();
|
|
|
|
// display game windows again
|
|
drawscreen();
|
|
return NULL;
|
|
}
|
|
|
|
int askobjectmulti(obpile_t *op, char *prompt, long opts) {
|
|
int c,i;
|
|
object_t *mylist[MAXPILEOBS+1];
|
|
int selected[MAXPILEOBS+1];
|
|
int selcount[MAXPILEOBS+1];
|
|
char myletters[MAXPILEOBS+1];
|
|
char numstring[BUFLEN];
|
|
int firstob = 0;
|
|
int nextpage = -1;
|
|
int lastline = SCREENH-4;
|
|
int finished;
|
|
int count = ALL;
|
|
char nextlet = 'a';
|
|
int useobletters;
|
|
objectclass_t *wantoc = NULL;
|
|
object_t *ammo;
|
|
|
|
// remember player's current ammo
|
|
if (op->owner) {
|
|
ammo = getammo(op->owner);
|
|
}
|
|
|
|
clearretobs();
|
|
|
|
if (countobs(op) <= 0) {
|
|
// no objects in pack
|
|
cls();
|
|
mvwprintw(mainwin, 2, 0, "You have no possessions.");
|
|
// wait for key
|
|
centre(mainwin, getmaxy(mainwin)-1, "[Press any key]");
|
|
getch();
|
|
|
|
clearmsg();
|
|
drawscreen();
|
|
return B_TRUE;
|
|
}
|
|
|
|
reason = E_OK;
|
|
|
|
// if picking form a player's pack, use the object's letters.
|
|
// otherwise just label them a, b, c, etc.
|
|
if (op->owner && (op->owner->controller == C_PLAYER)) {
|
|
useobletters = B_TRUE;
|
|
} else {
|
|
useobletters = B_FALSE;
|
|
}
|
|
|
|
|
|
|
|
// construct a list of objects
|
|
c = 0;
|
|
i = 0;
|
|
while (sortorder[c] != OC_NULL) {
|
|
object_t *o;
|
|
if (!wantoc || (sortorder[c] == wantoc->id)) {
|
|
// add all objects of this class
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o->type->obclass->id == sortorder[c]) {
|
|
int ok;
|
|
// can we include this object?
|
|
ok = obmatchescondition(o, opts);
|
|
|
|
if (ok) {
|
|
mylist[i] = o;
|
|
myletters[i] = nextlet;
|
|
selected[i] = B_FALSE;
|
|
selcount[i] = 0;
|
|
if (++nextlet > 'z') nextlet = 'A';
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
c++;
|
|
}
|
|
mylist[i] = NULL;
|
|
|
|
// start displaying from the first one
|
|
firstob = 0;
|
|
nextpage = -1;
|
|
finished = B_FALSE;
|
|
strcpy(numstring, "");
|
|
while (!finished) {
|
|
int y;
|
|
int ch;
|
|
|
|
cls();
|
|
|
|
// list the objects
|
|
y = 2;
|
|
|
|
listobs(mainwin, mylist, selected, selcount, firstob, &i, lastline, &y, useobletters ? NULL : myletters );
|
|
|
|
if (mylist[i] == NULL) {
|
|
nextpage = -1;
|
|
} else {
|
|
nextpage = i;
|
|
}
|
|
// draw prompt
|
|
if (nextpage != -1) {
|
|
mvwprintw(mainwin, y, 0, MORESTRING);
|
|
}
|
|
if (strlen(numstring) > 0) {
|
|
mvwprintw(mainwin, 0, 0, "%s (%s','=all, ESC to quit) [%s]: ",prompt,
|
|
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "",
|
|
numstring);
|
|
} else {
|
|
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit): ", prompt,
|
|
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "");
|
|
}
|
|
// update screen
|
|
wrefresh(mainwin);
|
|
// wait for keypess
|
|
ch = getch();
|
|
if (ch == 27) { // ESCAPE
|
|
finished = B_TRUE;
|
|
break;
|
|
}
|
|
// otherwise look for shift key etc..
|
|
ch = keycodetokey(ch);
|
|
// then handle input
|
|
if (ch == ' ') { // next page
|
|
if (nextpage == -1) { // go to first page
|
|
firstob = 0;
|
|
} else {
|
|
firstob = nextpage;
|
|
}
|
|
} else if (isalpha(ch) || (ch == '$')) {
|
|
int which = -1;
|
|
// select it
|
|
if (useobletters) {
|
|
object_t *o;
|
|
o = findobl(op, ch);
|
|
// find ob in list
|
|
for (i = 0 ; (mylist[i] != NULL) ; i++) {
|
|
if (mylist[i] == o) {
|
|
which = i;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0 ; (mylist[i] != NULL) ; i++) {
|
|
if (myletters[i] == ch) {
|
|
which = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (which != -1) {
|
|
int val;
|
|
if (selected[i]) val = B_FALSE;
|
|
else val = B_TRUE;
|
|
|
|
selected[i] = val;
|
|
if (val == B_TRUE) {
|
|
selcount[i] = count;
|
|
if (selcount[i] > mylist[i]->amt) selcount[i] = ALL;
|
|
} else {
|
|
selcount[i] = 0;
|
|
}
|
|
// reset count
|
|
strcpy(numstring, "");
|
|
count = ALL;
|
|
}
|
|
} else if ((ch == '-') && (opts & AO_INCLUDENOTHING)) { // select nothing
|
|
reason = E_SELNOTHING;
|
|
nretobs = 0;
|
|
// display game windows again
|
|
clearmsg();
|
|
drawscreen();
|
|
return B_TRUE;
|
|
} else if (ch == ',') { // toggle all/none
|
|
int val;
|
|
if (selected[0]) { // deselect all
|
|
val = B_FALSE;
|
|
} else { // select all
|
|
val = B_TRUE;
|
|
}
|
|
for (i = 0 ; (mylist[i] != NULL) ; i++) {
|
|
selected[i] = val;
|
|
selcount[i] = mylist[i]->amt;
|
|
}
|
|
} else if (ch == 10) { // enter
|
|
// construct list to return
|
|
nretobs = 0;
|
|
for (i = 0 ; (mylist[i] != NULL); i++) {
|
|
if (selected[i]) {
|
|
retobs[nretobs] = mylist[i];
|
|
retobscount[nretobs] = selcount[i];
|
|
nretobs++;
|
|
}
|
|
}
|
|
finished = B_TRUE;
|
|
} else if (isdigit(ch) && count) {
|
|
char temp[2];
|
|
temp[0] = ch;
|
|
temp[1] = '\0';
|
|
strcat(numstring, temp);
|
|
count = atoi(numstring);
|
|
} else if ((ch == 8) && count) { // backspace
|
|
if (strlen(numstring) > 0) {
|
|
// remove last letter of number string
|
|
numstring[strlen(numstring)-1] = '\0';
|
|
count = atoi(numstring);
|
|
}
|
|
}
|
|
|
|
/*
|
|
// sanity check count...
|
|
if (count && (*count == 0)) {
|
|
strcpy(numstring, "");
|
|
}
|
|
*/
|
|
}
|
|
|
|
// clear msg bar
|
|
clearmsg();
|
|
|
|
// display game windows again
|
|
drawscreen();
|
|
if (nretobs <= 0) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
void centre(WINDOW *win, int y, char *format, ... ) {
|
|
int w;
|
|
char buf[BUFLEN];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsprintf( buf, format, args );
|
|
va_end(args);
|
|
|
|
w = getmaxx(win);
|
|
mvwprintw(win, y, (w/2) - (strlen(buf)/2), buf);
|
|
}
|
|
|
|
|
|
int chartodir(char c) {
|
|
switch (tolower(c)) {
|
|
case 'h': return D_W;
|
|
case 'j': return D_S;
|
|
case 'k': return D_N;
|
|
case 'l': return D_E;
|
|
case 'y': return DC_NW;
|
|
case 'u': return DC_NE;
|
|
case 'b': return DC_SW;
|
|
case 'n': return DC_SE;
|
|
}
|
|
return D_NONE;
|
|
}
|
|
|
|
char checkforkey(void) {
|
|
char ch;
|
|
nodelay(mainwin, TRUE);
|
|
ch = getch();
|
|
nodelay(mainwin, FALSE);
|
|
if (ch == ERR) ch = '\0';
|
|
|
|
return ch;
|
|
}
|
|
|
|
void clearmsg(void) {
|
|
real_clearmsg(B_FALSE);
|
|
}
|
|
|
|
// use forced clear msg when we have
|
|
// drawn over the whole screen, eg.
|
|
void real_clearmsg(int force) {
|
|
// remember message history
|
|
if (force || strcmp(msgbuf, "")) {
|
|
char *p;
|
|
int ok = B_FALSE;
|
|
// make sure msg contains non-whitespace characters
|
|
for (p = msgbuf; p ; p++) {
|
|
if (*p != ' ') {
|
|
ok = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (ok) {
|
|
addmsghist(msgbuf);
|
|
}
|
|
|
|
strcpy(msgbuf, "");
|
|
wclear(msgwin);
|
|
wrefresh(msgwin);
|
|
}
|
|
}
|
|
|
|
int cleanupgfx(void) {
|
|
curs_set(1);
|
|
endwin();
|
|
return B_FALSE;
|
|
}
|
|
|
|
void updatestatus(void) {
|
|
wrefresh(statwin);
|
|
}
|
|
|
|
void updateviewfor(cell_t *cell) {
|
|
// calculate viewport if required
|
|
if ((viewx == -9999) || (viewy == -9999)) {
|
|
// try to centre player
|
|
viewx = cell->x - (SCREENW/2);
|
|
viewy = cell->y - (SCREENH/2);
|
|
}
|
|
|
|
while ((cell->x - viewx) >= ((SCREENW / 3)*2)) {
|
|
viewx++;
|
|
}
|
|
while ((cell->y - viewy) >= ((SCREENH / 3)*2)) {
|
|
viewy++;
|
|
}
|
|
while ((cell->x - viewx) <= (SCREENW/3)) {
|
|
viewx--;
|
|
}
|
|
while ((cell->y - viewy) <= (SCREENH/3)) {
|
|
viewy--;
|
|
}
|
|
}
|
|
|
|
|
|
void drawscreen(void) {
|
|
if (gamemode < GM_GAMESTARTED) {
|
|
return;
|
|
}
|
|
|
|
if (statdirty) {
|
|
drawstatus();
|
|
wrefresh(statwin);
|
|
statdirty = B_FALSE;
|
|
}
|
|
|
|
if (needredraw) {
|
|
updateviewfor(player->cell);
|
|
drawlevelfor(player);
|
|
drawcursor(); // this will call redraw gamewin
|
|
}
|
|
}
|
|
|
|
void clearretobs(void) {
|
|
int i;
|
|
for (i = 0; i < MAXPILEOBS+1; i++) {
|
|
retobs[i] = NULL;
|
|
retobscount[i] = ALL;
|
|
}
|
|
nretobs = 0;
|
|
}
|
|
|
|
// clears the screen
|
|
void cls(void) {
|
|
wclear(mainwin);
|
|
statdirty = B_TRUE;
|
|
}
|
|
|
|
void describeob(object_t *o) {
|
|
char buf[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
int y;
|
|
flag_t *f;
|
|
int obknown;
|
|
int i;
|
|
|
|
cls();
|
|
|
|
obknown = isknown(o);
|
|
// title
|
|
getobname(o, buf,o->amt);
|
|
mvwprintw(mainwin, 0, 0, buf);
|
|
|
|
getobdesc(o, buf);
|
|
mvwprintw(mainwin, 2, 0, buf);
|
|
|
|
|
|
// properties
|
|
y = 4;
|
|
if (o->material->id != MT_FOOD) {
|
|
mvwprintw(mainwin, y, 0, "%s made from %s.",(o->amt == 1) ? "It is" : "They are", o->material->name); y++;
|
|
}
|
|
|
|
if (isedible(o)) {
|
|
int basenutr;
|
|
basenutr = getnutritionbase(o);
|
|
mvwprintw(mainwin, y, 0, "%s edible.",(o->amt == 1) ? "It is" : "They are"); y++;
|
|
mvwprintw(mainwin, y, 0, "%s %s.",(o->amt == 1) ? "It is" : "They are each", getfillingname(basenutr)); y++;
|
|
}
|
|
|
|
|
|
if (o->amt == 1) {
|
|
getweighttext(getobweight(o), buf);
|
|
mvwprintw(mainwin, y, 0, "It weighs %s.",buf);
|
|
} else {
|
|
getweighttext(getobweight(o), buf);
|
|
getweighttext(getobunitweight(o), buf2);
|
|
mvwprintw(mainwin, y, 0, "They weigh %s (%s each).",buf, buf2);
|
|
}
|
|
y++;
|
|
|
|
// weapons?
|
|
if (o->type->obclass->id == OC_WEAPON) {
|
|
int delay;
|
|
f = hasflag(o->flags, F_DAMTYPE);
|
|
if (f) {
|
|
int bonus = 0;
|
|
int damtype;
|
|
damtype = f->val[0];
|
|
|
|
f = hasflag(o->flags, F_BONUS);
|
|
if (f && f->known) {
|
|
// only tell player about bonuses if they are known.!
|
|
bonus = f->val[0];
|
|
}
|
|
|
|
f = hasflag(o->flags, F_DAM);
|
|
if (f) {
|
|
char buf[BUFLEN];
|
|
char dicebuf[BUFLEN];
|
|
int mindam,maxdam;
|
|
getdamrange(o->flags, &mindam, &maxdam);
|
|
mindam += bonus;
|
|
maxdam += bonus;
|
|
if (mindam < 0) mindam = 0;
|
|
if (maxdam < 0) maxdam = 0;
|
|
|
|
if (mindam == maxdam) {
|
|
sprintf(buf, "It inflicts %d %s damage",maxdam, getdamname(damtype));
|
|
} else {
|
|
sprintf(buf, "It inflicts %d-%d %s damage",mindam,maxdam, getdamname(damtype));
|
|
}
|
|
|
|
dicetotext(f->val[0], f->val[1], f->val[2], NULL, NULL, dicebuf, NULL);
|
|
|
|
strcat(buf, " (");
|
|
strcat(buf, dicebuf);
|
|
strcat(buf, ").");
|
|
|
|
/*
|
|
if (f->val[2] == NA) {
|
|
sprintf(dicebuf, " (%dd%d).", f->val[0], f->val[1]);
|
|
} else {
|
|
sprintf(dicebuf, " (%dd%d%c%d).", f->val[0], f->val[1],
|
|
(f->val[2] > 0) ? '+' : '-',
|
|
abs(f->val[2]));
|
|
}
|
|
strcat(buf,dicebuf);
|
|
*/
|
|
mvwprintw(mainwin, y, 0, "%s",buf);
|
|
y++;
|
|
} else {
|
|
mvwprintw(mainwin, y, 0, "It inflicts %s damage.",getdamname(damtype));
|
|
y++;
|
|
}
|
|
}
|
|
|
|
// other extra damage or effects?
|
|
f = hasflag(o->flags, F_ONFIRE);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, " It also inflicts extra burning damage.");
|
|
y++;
|
|
}
|
|
|
|
delay = 100;
|
|
f = hasflag(o->flags, F_OBATTACKDELAY);
|
|
if (f) {
|
|
delay = f->val[0];
|
|
}
|
|
mvwprintw(mainwin, y, 0, "Its attack delay is %d%%.",delay - 100);
|
|
y++;
|
|
|
|
f = hasflag(o->flags, F_ACCURACY);
|
|
if (f) {
|
|
int acc;
|
|
acc = getobaccuracy(o, NULL);
|
|
mvwprintw(mainwin, y, 0, "It has %s accuracy.",getaccuracyname(acc));
|
|
y++;
|
|
}
|
|
f = hasflag(o->flags, F_DISARMATTACK);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "A skilled weilder can disarm opponents with it.");
|
|
y++;
|
|
}
|
|
f = hasflag(o->flags, F_TRIPATTACK);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "A skilled weilder can trip opponents with it.");
|
|
y++;
|
|
}
|
|
|
|
}
|
|
// damage
|
|
if (isarmour(o)) {
|
|
f = hasflag(o->flags, F_GOESON);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "It is worn %s your %s.",getbodypartequipname(f->val[0]), getbodypartname(f->val[0]));
|
|
y++;
|
|
}
|
|
f = hasflag(o->flags, F_ARMOURRATING);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "It has an Armour Rating of %d.",f->val[0] + getobbonus(o));
|
|
y++;
|
|
}
|
|
}
|
|
|
|
|
|
f = hasflag(o->flags, F_THROWMISSILE);
|
|
if (f) {
|
|
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) {
|
|
int dam;
|
|
dam = getthrowdam(o);
|
|
mvwprintw(mainwin, y, 0, "%s good for throwing [base damage %d].",(o->amt == 1) ? "It is" : "They are", dam);
|
|
} else {
|
|
mvwprintw(mainwin, y, 0, "%s good for throwing.", (o->amt == 1) ? "It is" : "They are");
|
|
}
|
|
y++;
|
|
}
|
|
|
|
f = hasflag(o->flags, F_ARMOURPIERCE);
|
|
if (f && f->known) {
|
|
mvwprintw(mainwin, y, 0, "Armour will not reduce %s damage.",(o->amt == 1) ? "its" : "their");
|
|
y++;
|
|
}
|
|
|
|
|
|
|
|
f = hasflag(o->flags, F_PICKLOCKS);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "You can use it to pick locks.");
|
|
y++;
|
|
}
|
|
|
|
// immunities
|
|
for (i = 0; i < MAXDAMTYPE; i++) {
|
|
if (isimmuneto(o->flags, i)) {
|
|
mvwprintw(mainwin, y, 0, "It is immune to %s.",getdamnamenoun(i));
|
|
y++;
|
|
}
|
|
if (isresistantto(o->flags, i)) {
|
|
mvwprintw(mainwin, y, 0, "It is resistant to %s.",getdamnamenoun(i));
|
|
y++;
|
|
}
|
|
if (isvulnto(o->flags, i)) {
|
|
mvwprintw(mainwin, y, 0, "It is vulnerable to %s.",getdamnamenoun(i));
|
|
y++;
|
|
}
|
|
}
|
|
|
|
// been made invulnerable ?
|
|
if (hasflag(o->type->flags, F_DAMAGABLE) && !hasflag(o->flags, F_DAMAGABLE)) {
|
|
mvwprintw(mainwin, y, 0, "It has been rendered invulnerable to most damage.");
|
|
y++;
|
|
}
|
|
|
|
for (f = o->flags->first ; f ; f = f->next) {
|
|
if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) {
|
|
mvwprintw(mainwin, y, 0, "It has been coated with poison.");
|
|
y++;
|
|
}
|
|
}
|
|
|
|
|
|
// now special flags...
|
|
y++;
|
|
|
|
f = hasflag(o->flags, F_MASTERWORK);
|
|
if (f && f->known) {
|
|
mvwprintw(mainwin, y, 0, "It is extremely well crafted.");
|
|
y++;
|
|
}
|
|
f = hasflag(o->flags, F_SHODDY);
|
|
if (f && f->known) {
|
|
mvwprintw(mainwin, y, 0, "It is very poorly crafted.");
|
|
y++;
|
|
}
|
|
|
|
f = hasflag(o->flags, F_ONFIRE);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "It is on fire.");
|
|
y++;
|
|
}
|
|
|
|
if (obproduceslight(o)) {
|
|
mvwprintw(mainwin, y, 0, "It is producing light.");
|
|
y++;
|
|
}
|
|
|
|
f = hasflag(o->flags, F_WET);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "It is wet.");
|
|
y++;
|
|
}
|
|
f = hasflag(o->flags, F_RUSTED);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "It is rusty.");
|
|
y++;
|
|
}
|
|
|
|
|
|
f = hasflag(o->flags, F_ACTIVATED);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "It is activated.");
|
|
y++;
|
|
}
|
|
|
|
|
|
// if known, show what it confers
|
|
y++;
|
|
for (f = o->flags->first ; f ; f = f->next) {
|
|
if ((f->id == F_HOLDCONFER) || (f->id == F_EQUIPCONFER) || (f->id == F_ACTIVATECONFER)) {
|
|
if (obknown) {
|
|
objecttype_t *ot;
|
|
if (f->id == F_HOLDCONFER) strcpy(buf, "When held, it");
|
|
else if (f->id == F_ACTIVATECONFER) strcpy(buf, "When activated, it");
|
|
else if (f->id == F_HITCONFER) strcpy(buf, "When hit by it, it");
|
|
else strcpy(buf, "When equipped, it");
|
|
|
|
// conferred intrinsics
|
|
switch (f->val[0]) {
|
|
int amt;
|
|
case F_SHIELDPENALTY:
|
|
amt = adjustshieldpenalty(player, f->val[1]);
|
|
mvwprintw(mainwin, y, 0, "%s lowers your attack accuracy by %d%%.", buf, amt); y++;
|
|
break;
|
|
case F_ATTRMOD:
|
|
mvwprintw(mainwin, y, 0, "%s %s your %s.", buf, (f->val[2] > 0) ? "increases" : "decreases", getattrname(f->val[1])); y++;
|
|
break;
|
|
case F_ATTRSET:
|
|
mvwprintw(mainwin, y, 0, "%s modifies your %s.", buf, getattrname(f->val[1])); y++;
|
|
break;
|
|
case F_BLIND:
|
|
mvwprintw(mainwin, y, 0, "%s prevents you from seeing.", buf); y++;
|
|
break;
|
|
case F_CONTROL:
|
|
mvwprintw(mainwin, y, 0, "%s lets you control teleportation and polymorphic effects.", buf); y++;
|
|
break;
|
|
case F_DETECTLIFE:
|
|
mvwprintw(mainwin, y, 0, "%s will detect nearby lifeforms.", buf); y++;
|
|
break;
|
|
case F_DETECTOBS:
|
|
mvwprintw(mainwin, y, 0, "%s will detect nearby objects.", buf); y++;
|
|
break;
|
|
case F_DETECTMAGIC:
|
|
mvwprintw(mainwin, y, 0, "%s will detect magical enchantments on objects.", buf); y++;
|
|
break;
|
|
case F_DETECTMETAL:
|
|
mvwprintw(mainwin, y, 0, "%s will detect nearby metal.", buf); y++;
|
|
break;
|
|
case F_EXTRAINFO:
|
|
mvwprintw(mainwin, y, 0, "%s provides enhanced knowledge to you.", buf); y++;
|
|
break;
|
|
case F_EXTRADAM:
|
|
mvwprintw(mainwin, y, 0, "%s will cause you to deal more damage.", buf); y++;
|
|
break;
|
|
case F_EXTRALUCK:
|
|
mvwprintw(mainwin, y, 0, "%s will give you a bonus to all skill checks.", buf); y++;
|
|
break;
|
|
case F_EXTRAMP:
|
|
mvwprintw(mainwin, y, 0, "%s will increase your mana pool by %d%%.", buf, f->val[0]); y++;
|
|
break;
|
|
case F_FASTACT:
|
|
mvwprintw(mainwin, y, 0, "%s will speed up your actions.", buf); y++;
|
|
break;
|
|
case F_FASTMOVE:
|
|
mvwprintw(mainwin, y, 0, "%s will speed up your movement.", buf); y++;
|
|
break;
|
|
case F_FLYING:
|
|
mvwprintw(mainwin, y, 0, "%s will allow you to fly.", buf); y++;
|
|
break;
|
|
case F_FREEZINGTOUCH:
|
|
mvwprintw(mainwin, y, 0, "%s will cause objects you touch to turn to ice.", buf); y++;
|
|
break;
|
|
case F_FROZEN:
|
|
mvwprintw(mainwin, y, 0, "%s turns you to ice.", buf); y++;
|
|
break;
|
|
case F_GRAVBOOSTED:
|
|
mvwprintw(mainwin, y, 0, "%s increases gravity around you.", buf); y++;
|
|
break;
|
|
case F_DODGES:
|
|
mvwprintw(mainwin, y, 0, "%s allows you to dodge attacks.", buf); y++;
|
|
break;
|
|
case F_INVISIBLE:
|
|
mvwprintw(mainwin, y, 0, "%s renders you invisible to normal sight.", buf); y++;
|
|
break;
|
|
case F_INVULNERABLE:
|
|
mvwprintw(mainwin, y, 0, "%s protects you from all physical harm.", buf); y++;
|
|
break;
|
|
case F_CANWILL:
|
|
ot = findot(f->val[1]);
|
|
if (ot) {
|
|
strcpy(buf2, ot->name);
|
|
capitalise(buf2);
|
|
mvwprintw(mainwin, y, 0, "%s allows you to cast '%s' at will.", buf, buf2); y++;
|
|
}
|
|
break;
|
|
case F_CANCAST:
|
|
ot = findot(f->val[1]);
|
|
if (ot) {
|
|
strcpy(buf2, ot->name);
|
|
capitalise(buf2);
|
|
mvwprintw(mainwin, y, 0, "%s allows you to cast '%s'.", buf, buf2); y++;
|
|
}
|
|
break;
|
|
case F_DETECTAURAS:
|
|
mvwprintw(mainwin, y, 0, "%s allows you to detect blessings or curses.", buf); y++;
|
|
break;
|
|
case F_LEVITATING:
|
|
mvwprintw(mainwin, y, 0, "%s causes you to levitate.", buf); y++;
|
|
break;
|
|
case F_MAGSHIELD:
|
|
mvwprintw(mainwin, y, 0, "%s surrounds you with a magnetic shield.", buf); y++;
|
|
break;
|
|
case F_NAUSEATED:
|
|
mvwprintw(mainwin, y, 0, "%s causes you to feel nauseated.", buf); y++;
|
|
break;
|
|
case F_NONCORPOREAL:
|
|
mvwprintw(mainwin, y, 0, "%s makes you non-corporeal.", buf); y++;
|
|
break;
|
|
case F_PAIN:
|
|
mvwprintw(mainwin, y, 0, "%s causes you intense pain.", buf); y++;
|
|
break;
|
|
case F_PARALYZED:
|
|
mvwprintw(mainwin, y, 0, "%s paralyzes you.", buf); y++;
|
|
break;
|
|
case F_PHOTOMEM:
|
|
mvwprintw(mainwin, y, 0, "%s prevents you from forgetting your surroundings.", buf); y++;
|
|
break;
|
|
case F_STABILITY:
|
|
mvwprintw(mainwin, y, 0, "%s prevents you from slipping over.", buf); y++;
|
|
break;
|
|
case F_STENCH:
|
|
mvwprintw(mainwin, y, 0, "%s makes you smell bad.", buf); y++;
|
|
break;
|
|
case F_PRODUCESLIGHT:
|
|
mvwprintw(mainwin, y, 0, "%s produces light.", buf); y++;
|
|
break;
|
|
case F_REGENERATES:
|
|
if (f->val[1] == 1) {
|
|
strcpy(buf2, "");
|
|
} else if (f->val[1] == 2) {
|
|
strcpy(buf2, "quickly");
|
|
} else if (f->val[1] == 3) {
|
|
strcpy(buf2, "very quickly");
|
|
} else { // >= 4
|
|
strcpy(buf2, "extremely quickly");
|
|
}
|
|
mvwprintw(mainwin, y, 0, "%s allows you to regenerate health%s.", buf,buf2); y++;
|
|
break;
|
|
case F_RESISTMAG:
|
|
mvwprintw(mainwin, y, 0, "%s grants you %s immunity to magic.", buf,
|
|
(f->val[0] >= 10) ? "strong" : "minor"); y++;
|
|
break;
|
|
case F_SEEINVIS:
|
|
mvwprintw(mainwin, y, 0, "%s allows you to see invisible things.", buf); y++;
|
|
break;
|
|
case F_SEEINDARK:
|
|
mvwprintw(mainwin, y, 0, "%s allows you to see in the dark.", buf); y++;
|
|
break;
|
|
case F_SLOWACT:
|
|
mvwprintw(mainwin, y, 0, "%s will slow down your actions.", buf); y++;
|
|
break;
|
|
case F_SLOWMOVE:
|
|
mvwprintw(mainwin, y, 0, "%s will slow down your movement.", buf); y++;
|
|
break;
|
|
case F_WINDSHIELD:
|
|
mvwprintw(mainwin, y, 0, "%s will surround you with a cyclonic shield.", buf); y++;
|
|
break;
|
|
case F_TIRED:
|
|
mvwprintw(mainwin, y, 0, "%s make you tired.", buf); y++;
|
|
break;
|
|
case F_VISRANGEMOD:
|
|
mvwprintw(mainwin, y, 0, "%s %s your vision range.", buf, (f->val[1] > 0) ? "increases" : "descreases"); y++;
|
|
break;
|
|
case F_XRAYVIS:
|
|
mvwprintw(mainwin, y, 0, "%s allows you to see through walls.", buf); y++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// show special properties where known
|
|
f = hasflag(o->flags, F_BALANCE);
|
|
if (f && f->known) {
|
|
mvwprintw(mainwin, y, 0, "It heals weaker enemies, and does extra damage to stronger ones.");
|
|
y++;
|
|
}
|
|
f = hasflag(o->flags, F_FLAMESTRIKE);
|
|
if (f && f->known) {
|
|
mvwprintw(mainwin, y, 0, "It ignites fires wherever it hits.");
|
|
y++;
|
|
}
|
|
f = hasflag(o->flags, F_HEAVYBLOW);
|
|
if (f && f->known) {
|
|
mvwprintw(mainwin, y, 0, "Its powerful blows knock enemies backwards.");
|
|
y++;
|
|
}
|
|
f = hasflag(o->flags, F_REVENGE);
|
|
if (f && f->known) {
|
|
mvwprintw(mainwin, y, 0, "It does more damage as your HP are lowered.");
|
|
y++;
|
|
}
|
|
|
|
y++;
|
|
|
|
// skill type?
|
|
f = hasflag(o->flags, F_USESSKILL);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "It falls into the '%s' category of weapons.",getskillname(f->val[0]));
|
|
y++;
|
|
}
|
|
|
|
if (hasflag(o->flags, F_NOBLESS)) {
|
|
mvwprintw(mainwin, y, 0, "%s cannot be blessed or cursed.", (o->amt == 1) ? "It" : "They" );
|
|
y++;
|
|
} else {
|
|
if (isblessknown(o)) {
|
|
if (o->blessed == B_BLESSED) {
|
|
mvwprintw(mainwin, y, 0, "%s a blessing bestowed upon %s.",
|
|
(o->amt == 1) ? "It has" : "They have",
|
|
(o->amt == 1) ? "it" : "them");
|
|
y++;
|
|
} else if (o->blessed == B_CURSED) {
|
|
mvwprintw(mainwin, y, 0, "%s cursed.",
|
|
(o->amt == 1) ? "It is" : "They are");
|
|
y++;
|
|
}
|
|
} else {
|
|
mvwprintw(mainwin, y, 0, "%s might be blessed or cursed.",
|
|
(o->amt == 1) ? "It" : "They");
|
|
y++;
|
|
}
|
|
}
|
|
|
|
|
|
wrefresh(mainwin);
|
|
|
|
// wait for key
|
|
getch();
|
|
real_clearmsg(B_TRUE);
|
|
drawscreen();
|
|
}
|
|
|
|
void describespell(objecttype_t *ot) {
|
|
char buf[BUFLEN];
|
|
int y;
|
|
flag_t *f;
|
|
int i;
|
|
int power;
|
|
|
|
cls();
|
|
|
|
// title
|
|
sprintf(buf, "%s",ot->name);
|
|
capitalise(buf);
|
|
mvwprintw(mainwin, 0, 0, buf);
|
|
|
|
sprintf(buf, "%s",ot->desc);
|
|
mvwprintw(mainwin, 2, 0, buf);
|
|
|
|
|
|
// properties
|
|
y = 5;
|
|
f = hasflag(ot->flags, F_SPELLLEVEL);
|
|
if (f) {
|
|
flag_t *sf;
|
|
sf = hasflag(ot->flags, F_SPELLSCHOOL);
|
|
assert(sf);
|
|
mvwprintw(mainwin, y, 0, "It is a level %d %s spell.",f->val[0], getschoolname(sf->val[0]));
|
|
y++;
|
|
}
|
|
|
|
i = getmpcost(NULL, ot->id);
|
|
if (i > 0) {
|
|
if (hasflag(ot->flags, F_ONGOING)) {
|
|
mvwprintw(mainwin, y, 0, "It takes %d MP to keep active - this is an ongoing cost.",i);
|
|
} else {
|
|
mvwprintw(mainwin, y, 0, "It costs %d MP to cast.",i);
|
|
}
|
|
y++;
|
|
}
|
|
|
|
y++;
|
|
|
|
power = getspellpower(player, ot->id);
|
|
mvwprintw(mainwin, y, 0, "You can cast it at power level %d (maximum %d).",power, getspellmaxpower(ot->id));
|
|
y++;
|
|
|
|
wrefresh(mainwin);
|
|
|
|
// wait for key
|
|
getch();
|
|
real_clearmsg(B_TRUE);
|
|
drawscreen();
|
|
}
|
|
|
|
void doattackcell(char dirch) {
|
|
int dir;
|
|
flag_t *f;
|
|
cell_t *c;
|
|
|
|
if (dirch == '\0') {
|
|
dirch = askchar("Attack in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE);
|
|
}
|
|
|
|
|
|
if (dirch == '.') {
|
|
// yourself!
|
|
c = player->cell;
|
|
} else {
|
|
dir = chartodir(dirch);
|
|
if (dir == D_NONE) {
|
|
clearmsg();
|
|
return;
|
|
} else {
|
|
c = getcellindir(player->cell, dir);
|
|
}
|
|
}
|
|
|
|
if (c) {
|
|
// update last cmd
|
|
f = hasflag(player->flags, F_LASTCMD);
|
|
if (f) {
|
|
f->val[2] = dirch;
|
|
}
|
|
|
|
if (attackcell(player, c)) {
|
|
// failed
|
|
msg("There is nothing there to attack!");
|
|
}
|
|
}
|
|
}
|
|
|
|
void doclose(void) {
|
|
char ch;
|
|
int failed = B_TRUE; // default is to fail
|
|
int dir;
|
|
int adjdoors;
|
|
int forcedir;
|
|
|
|
|
|
// how many doors are nearby?
|
|
adjdoors = 0;
|
|
for (dir = DC_N; dir <= DC_NW; dir++) {
|
|
cell_t *c;
|
|
c = getcellindir(player->cell, dir);
|
|
if (c) {
|
|
object_t *door;
|
|
door = hasobwithflag(c->obpile, F_DOOR);
|
|
if (door) {
|
|
int open;
|
|
isdoor(door, &open);
|
|
if (open) {
|
|
forcedir = dir;
|
|
adjdoors++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (adjdoors == 0) {
|
|
msg("There are no open doors nearby!");
|
|
return;
|
|
} else if (adjdoors == 1) {
|
|
dir = forcedir;
|
|
} else {
|
|
ch = askchar("Close door in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
|
|
dir = chartodir(ch);
|
|
}
|
|
|
|
if (dir == D_NONE) {
|
|
clearmsg();
|
|
return;
|
|
} else {
|
|
cell_t *c;
|
|
c = getcellindir(player->cell, dir);
|
|
if (c) {
|
|
failed = closedoorat(player, c);
|
|
}
|
|
}
|
|
}
|
|
|
|
void docomms(void) {
|
|
lifeform_t *lf = NULL;
|
|
cell_t *where;
|
|
char buf[BUFLEN];
|
|
char lfname[BUFLEN];
|
|
char ch;
|
|
|
|
where = askcoords("Talk to who?", TT_MONSTER);
|
|
if (where && where->lf && cansee(player, where->lf)) {
|
|
lf = where->lf;
|
|
}
|
|
if (!lf) {
|
|
msg("Cancelled.");
|
|
return;
|
|
}
|
|
getlfname(lf, lfname);
|
|
|
|
sprintf(buf, "What will you say to %s?",lfname);
|
|
initprompt(&prompt, buf);
|
|
prompt.maycancel = B_TRUE;
|
|
// are they friendly?
|
|
if (areallies(player, lf)) {
|
|
addchoice(&prompt, 'a', "Attack something", NULL, NULL);
|
|
if (!isadjacent(lf->cell, player->cell)) {
|
|
addchoice(&prompt, 'c', "Come here", NULL, NULL);
|
|
}
|
|
if (isadjacent(lf->cell, player->cell)) {
|
|
addchoice(&prompt, 't', "Trade items with me", NULL, NULL);
|
|
}
|
|
} else {
|
|
addchoice(&prompt, 'y', "Yeeeeeaaaargh!", NULL, NULL);
|
|
}
|
|
addchoice(&prompt, 'n', "(nothing)", NULL, NULL);
|
|
|
|
ch = getchoice(&prompt);
|
|
switch (ch) {
|
|
cell_t *c;
|
|
lifeform_t *lf2 = NULL;
|
|
char lfname2[BUFLEN];
|
|
case 'a':
|
|
sprintf(buf, "Tell %s to attack who?",lfname);
|
|
c = askcoords(buf, TT_MONSTER);
|
|
if (c && c->lf && cansee(player, c->lf)) {
|
|
lf2 = c->lf;
|
|
|
|
}
|
|
if (!lf2) {
|
|
msg("Cancelled.");
|
|
return;
|
|
}
|
|
getlfname(lf2, lfname2);
|
|
msg("You say \"Attack %s!\" to %s.",lfname2, lfname);
|
|
aiattack(lf, lf2, AI_FOLLOWTIME);
|
|
break;
|
|
case 'c':
|
|
msg("You say \"Come here!\" to %s.",lfname);
|
|
// find adjacent cell
|
|
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
|
if (c) {
|
|
aigoto(lf, c, AI_FOLLOWTIME);
|
|
}
|
|
break;
|
|
case 'n':
|
|
msg("Cancelled.");
|
|
return;
|
|
case 't':
|
|
// ask whtehr to give/take
|
|
initprompt(&prompt, "How will you trade?");
|
|
sprintf(buf, "Give items to %s",lfname);
|
|
addchoice(&prompt, 'i', buf, NULL, NULL);
|
|
sprintf(buf, "Take items from %s",lfname);
|
|
addchoice(&prompt, 'o', buf, NULL, NULL);
|
|
sprintf(buf, "Both");
|
|
addchoice(&prompt, 'b', buf, NULL, NULL);
|
|
sprintf(buf, "Neither");
|
|
addchoice(&prompt, 'n', buf, NULL, NULL);
|
|
ch = getchoice(&prompt);
|
|
switch (ch) {
|
|
case 'i':
|
|
dodrop(player->pack, B_MULTIPLE, lf->pack);
|
|
break;
|
|
case 'o':
|
|
dopickup(lf->pack);
|
|
break;
|
|
case 'b':
|
|
dodrop(player->pack, B_MULTIPLE, lf->pack);
|
|
dopickup(lf->pack);
|
|
break;
|
|
case 'n':
|
|
msg("Cancelled.");
|
|
return;
|
|
}
|
|
break;
|
|
case 'y':
|
|
msg("You shout at %s!", lfname);
|
|
noise(where, player, "someone shouting!", NULL);
|
|
break;
|
|
}
|
|
taketime(player, getactspeed(player));
|
|
}
|
|
|
|
void dodrop(obpile_t *op, int wantmulti, obpile_t *dst) {
|
|
object_t *o;
|
|
char buf[BUFLEN];
|
|
int count = ALL;
|
|
int i;
|
|
lifeform_t *tolf = NULL;
|
|
char lfname[BUFLEN];
|
|
|
|
|
|
// where is destination?
|
|
if (dst->owner) {
|
|
tolf = dst->owner;
|
|
getlfname(tolf, lfname);
|
|
} else {
|
|
// on ground
|
|
}
|
|
|
|
if (tolf) {
|
|
sprintf(buf, "Give what to %s",lfname);
|
|
} else {
|
|
strcpy(buf, "Drop what");
|
|
}
|
|
|
|
if (wantmulti) {
|
|
askobjectmulti(op, buf, AO_NONE);
|
|
} else {
|
|
o = askobject(op, buf, &count, AO_NONE);
|
|
if (o) {
|
|
retobs[0] = o;
|
|
retobscount[0] = count;
|
|
nretobs = 1;
|
|
} else {
|
|
nretobs = 0;
|
|
}
|
|
|
|
}
|
|
if (nretobs <= 0) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < nretobs; i++) {
|
|
flag_t *f;
|
|
//pickup(player, retobs[i],retobscount[i]);
|
|
|
|
o = retobs[i];
|
|
count = retobscount[i];
|
|
|
|
getobname(o, buf, count);
|
|
|
|
f = hasflag(o->flags, F_EQUIPPED);
|
|
if (f) {
|
|
if (f->val[0] == BP_WEAPON) {
|
|
// first try to unweild it
|
|
if (unweild(player, o)) {
|
|
if (nretobs > 1) {
|
|
if (tolf) {
|
|
msg("Not giving %s to %s.",buf, lfname); more();
|
|
} else {
|
|
msg("Not dropping %s.",buf); more();
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
} else { // armour
|
|
int ch;
|
|
char buf2[BUFLEN];
|
|
// take it off first - this takes time.
|
|
sprintf(buf2, "Remove %s",buf);
|
|
ch = askchar(buf2, "yn","y", B_TRUE);
|
|
if (ch == 'y') {
|
|
if (takeoff(player, o)) {
|
|
// failed to take it off - can't drop it.
|
|
if (nretobs > 1) {
|
|
if (tolf) {
|
|
msg("Not giving %s to %s.",buf, lfname); more();
|
|
} else {
|
|
msg("Not dropping %s.",buf); more();
|
|
}
|
|
}
|
|
continue;
|
|
|
|
}
|
|
} else {
|
|
if (nretobs > 1) {
|
|
if (tolf) {
|
|
msg("Not giving %s to %s.",buf, lfname); more();
|
|
} else {
|
|
msg("Not dropping %s.",buf); more();
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (count == ALL) count = o->amt;
|
|
|
|
if (tolf) {
|
|
o = moveob(o, dst, count);
|
|
if (o) {
|
|
getobname(o, buf, o->amt);
|
|
msg("%s takes %s from you.",lfname, buf);
|
|
} else {
|
|
msg("%s can't carry that.",lfname);
|
|
}
|
|
} else {
|
|
drop(o, count);
|
|
}
|
|
}
|
|
}
|
|
|
|
void doeat(obpile_t *op) {
|
|
object_t *o;
|
|
char ch;
|
|
char buf[BUFLEN];
|
|
char obname[BUFLEN];
|
|
|
|
// stuffed?
|
|
if (gethungerlevel(gethungerval(player)) <= H_STUFFED) {
|
|
msg("You couldn't eat another bite!");
|
|
return;
|
|
}
|
|
|
|
// edible objects here?
|
|
for (o = player->cell->obpile->first; o ; o = o->next) {
|
|
if (isedible(o)) {
|
|
getobname(o, obname, o->amt);
|
|
sprintf(buf, "There %s %s here. Eat %s",
|
|
(o->amt == 1) ? "is" : "are",
|
|
obname,
|
|
(o->amt == 1) ? "it" : "one");
|
|
ch = askchar(buf, "yn","n", B_TRUE);
|
|
if (ch == 'y') {
|
|
eat(player, o);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!hasedibleob(player->pack)) {
|
|
msg("You have nothing to eat!");
|
|
return;
|
|
}
|
|
|
|
o = askobject(op, "Eat what", NULL, AO_EDIBLE);
|
|
if (o) {
|
|
eat(player, o);
|
|
}
|
|
}
|
|
|
|
void dovendingmachine(lifeform_t *lf, object_t *vm) {
|
|
int y;
|
|
flag_t *f;
|
|
//int i;
|
|
int done;
|
|
char ch;
|
|
char choices[BUFLEN];
|
|
char buf[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
char toptext[BUFLEN];
|
|
obpile_t *op;
|
|
|
|
strcpy(toptext, "");
|
|
|
|
op = addobpile(NULL, NULL);
|
|
|
|
// populate machine with items
|
|
strcpy(choices, "");
|
|
for (f = vm->flags->first ; f ; f = f->next) {
|
|
if (f->id == F_CONTAINSOB) {
|
|
object_t *o;
|
|
|
|
ch = f->val[0];
|
|
if (strlen(f->text)) {
|
|
o = addobject(op, f->text, B_FALSE); // no stacking!
|
|
// remember letter
|
|
o->letter = ch;
|
|
// make object fully known
|
|
addflag(o->flags, F_SHOPITEM, B_TRUE, NA, NA, NULL);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// list objects for sale and ask for input
|
|
done = B_FALSE;
|
|
while (!done) {
|
|
cls();
|
|
mvwprintw(mainwin, 0, 0, toptext);
|
|
y = 2;
|
|
centre(mainwin, y, "VENDING MACINE");
|
|
y += 2;
|
|
|
|
// list objects for sale
|
|
strcpy(choices, "");
|
|
for (f = vm->flags->first ; f ; f = f->next) {
|
|
if (f->id == F_CONTAINSOB) {
|
|
char temp[2];
|
|
char obname[BUFLEN];
|
|
object_t *o;
|
|
|
|
ch = f->val[0];
|
|
sprintf(temp, "%c",ch);
|
|
|
|
if (strlen(f->text)) {
|
|
// add this as a valid choice
|
|
strcat(choices, temp);
|
|
// construct string
|
|
o = hasobletter(op, ch);
|
|
// get the name of the object
|
|
getobname(o, obname, o->amt);
|
|
sprintf(buf, "%c - %s", ch, obname);
|
|
sprintf(buf2, "%-60s$%d",buf,getobvalue(o));
|
|
mvwprintw(mainwin, y, 0, "%s", buf2);
|
|
y++;
|
|
} else {
|
|
// construct string
|
|
sprintf(buf, " %s", SOLDOUTSTRING);
|
|
sprintf(buf2, "%-60s",buf);
|
|
mvwprintw(mainwin, y, 0, "%s", buf2);
|
|
y++;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
y++;
|
|
|
|
|
|
mvwprintw(mainwin, y, 0, "You have $%d.", countmoney(player));
|
|
y++;
|
|
y++;
|
|
|
|
// ask what to do
|
|
mvwprintw(mainwin, y, 0, "What will you buy (ESC to exit)? ");
|
|
|
|
ch = getch();
|
|
if (ch == 27) {
|
|
done = B_TRUE;
|
|
} else {
|
|
object_t *o;
|
|
// try to find that object...
|
|
o = hasobletter(op, ch);
|
|
if (o) {
|
|
// do you have enough money?
|
|
if (countmoney(player) >= getobvalue(o)) {
|
|
object_t *gold;
|
|
// if so, buy it
|
|
// lose money (do this first to avoid potential weight issues)
|
|
gold = hasob(player->pack, OT_GOLD);
|
|
if (gold) {
|
|
char obname[BUFLEN];
|
|
char answer;
|
|
// confirm
|
|
getobname(o, obname, o->amt);
|
|
sprintf(buf, "Buy %s for $%d?",obname, getobvalue(o));
|
|
answer = askchar(buf, "yn","n", B_TRUE);
|
|
if (answer == 'y') {
|
|
gold->amt -= getobvalue(o);
|
|
// clear o->letter
|
|
o->letter = '\0';
|
|
// give object
|
|
o = moveob(o, player->pack, ALL);
|
|
getobname(o, obname, o->amt);
|
|
sprintf(toptext, "Purchased: %c - %s", o->letter, obname);
|
|
// set F_CONTAINSOB text to "" - ie. sold out
|
|
for (f = vm->flags->first ; f ; f = f->next) {
|
|
if (f->val[0] == ch) {
|
|
strcpy(f->text, "");
|
|
}
|
|
}
|
|
} else {
|
|
// cancelled
|
|
strcpy(toptext, "");
|
|
}
|
|
} else {
|
|
// error
|
|
sprintf(toptext,"You don't seem to have any gold...");
|
|
}
|
|
} else {
|
|
sprintf(toptext, "You cannot afford that!");
|
|
}
|
|
} else {
|
|
sprintf(toptext, "That item is sold out!");
|
|
} // end if o
|
|
} // end if ch
|
|
} // end while not done
|
|
|
|
// free mem
|
|
while (op->first) {
|
|
killob(op->first);
|
|
}
|
|
killobpile(op);
|
|
|
|
|
|
drawscreen();
|
|
real_clearmsg(B_TRUE);
|
|
}
|
|
|
|
|
|
int dowear(obpile_t *op) {
|
|
object_t *o;
|
|
int rv;
|
|
o = askobject(op, "Wear what", NULL, AO_WEARABLE);
|
|
if (o) {
|
|
wear(player, o);
|
|
} else {
|
|
msg("Cancelled.");
|
|
rv = B_TRUE;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
int doweild(obpile_t *op) {
|
|
object_t *o;
|
|
int count = ALL;
|
|
int rv;
|
|
o = askobject(op, "Weild what", &count, AO_WEILDABLE | AO_INCLUDENOTHING);
|
|
if (o) {
|
|
rv = weild(player, o);
|
|
} else if (reason == E_SELNOTHING) {
|
|
// ie. unweild
|
|
rv = weild(player, NULL);
|
|
} else {
|
|
rv = B_TRUE;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
void doknowledgelist(void) {
|
|
knowledge_t *k;
|
|
int y = 0;
|
|
int numfound = 0;
|
|
int c;
|
|
|
|
cls();
|
|
mvwprintw(mainwin, 0, 0, "Current Knowledge");
|
|
y = 2;
|
|
for (c = 0; sortorder[c] != OC_NULL ; c++) {
|
|
int first = B_TRUE;
|
|
for (k = knowledge ; k ; k = k->next) {
|
|
if (k->known) {
|
|
objecttype_t *ot;
|
|
ot = findot(k->id);
|
|
if (ot->obclass->id == c) {
|
|
if (first) {
|
|
mvwprintw(mainwin, y, 0, "%s", ot->obclass->name);
|
|
y++;
|
|
|
|
first = B_FALSE;
|
|
}
|
|
|
|
mvwprintw(mainwin, y, 0, " %-25s (%s)",ot->name, k->hiddenname);
|
|
y++;
|
|
|
|
numfound++;
|
|
|
|
if (y >= (SCREENH-3)) {
|
|
mvwprintw(mainwin, (SCREENH-2), 0, MORESTRING);
|
|
wrefresh(mainwin);
|
|
getch();
|
|
cls();
|
|
mvwprintw(mainwin, 0, 0, "Current Knowledge");
|
|
y = 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (numfound == 0) {
|
|
mvwprintw(mainwin, y, 0, "You don't know much.");
|
|
}
|
|
wrefresh(mainwin);
|
|
getch();
|
|
|
|
clearmsg();
|
|
drawscreen();
|
|
}
|
|
|
|
void dolook(cell_t *where) {
|
|
int numobs;
|
|
char buf[BUFLEN];
|
|
char seeverb[BUFLEN];
|
|
int seensomething = B_FALSE;
|
|
|
|
//if (isblind(player)) {
|
|
if (!haslos(player, player->cell)) {
|
|
strcpy(seeverb, "feel");
|
|
} else {
|
|
strcpy(seeverb, "see");
|
|
}
|
|
|
|
numobs = countobs(where->obpile);
|
|
if (numobs > 0) {
|
|
if (numobs == 1) {
|
|
getobname(where->obpile->first, buf, where->obpile->first->amt);
|
|
msg("You %s %s here.", seeverb, buf);
|
|
} else if ((numobs > 1) && (numobs <= 3)) {
|
|
msg("You %s a few objects here.", seeverb);
|
|
} else if ((numobs > 3) && (numobs <= 6)) {
|
|
msg("You %s some objects here.", seeverb);
|
|
} else if (numobs > 6) {
|
|
msg("You %s many objects here.", seeverb);
|
|
}
|
|
seensomething = B_TRUE;
|
|
}
|
|
|
|
|
|
|
|
// writing here?
|
|
if (where->writing && !isblind(player)) {
|
|
msg("There is a magical inscription here:");
|
|
msg("\"%s\"", where->writing);
|
|
seensomething = B_TRUE;
|
|
}
|
|
|
|
|
|
if (!seensomething) {
|
|
// just clear the message buffer
|
|
//clearmsg();
|
|
if (isblind(player)) {
|
|
msg("There does not seem to be anything here.");
|
|
} else {
|
|
msg("There is nothing here.");
|
|
}
|
|
}
|
|
}
|
|
|
|
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2) {
|
|
char ch;
|
|
flag_t *f;
|
|
char buf[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
char costbuf[BUFLEN];
|
|
enum OBTYPE poss[MAXCANDIDATES];
|
|
int mpcost[MAXCANDIDATES];
|
|
char mpdesc[MAXCANDIDATES][BUFLEN];
|
|
int validspell[MAXCANDIDATES];
|
|
int deactspell[MAXCANDIDATES];
|
|
int nposs = 0;
|
|
int i,n;
|
|
enum SPELLSCHOOL lastschool;
|
|
objecttype_t *ot;
|
|
|
|
nposs = 0;
|
|
for (i = SS_NONE+1; i < SS_LAST; i++) {
|
|
// get list of spells/abilities we can cast at will
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) {
|
|
f = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
|
|
if (f) {
|
|
if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) {
|
|
poss[nposs] = ot->id;
|
|
deactspell[nposs] = B_FALSE; // default
|
|
mpcost[nposs] = -1;
|
|
if (f->val[2] == NA) {
|
|
sprintf(mpdesc[nposs], "(ready)");
|
|
validspell[nposs] = B_TRUE;
|
|
} else {
|
|
if (f->val[1] == f->val[2]) {
|
|
sprintf(mpdesc[nposs], "(ready)");
|
|
validspell[nposs] = B_TRUE;
|
|
} else {
|
|
sprintf(mpdesc[nposs], "(%d/%d)",f->val[1],f->val[2]);
|
|
validspell[nposs] = B_FALSE;
|
|
}
|
|
}
|
|
|
|
nposs++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (!lfhasflag(lf, F_NOSPELLS)) {
|
|
// get list of spells we can cast using mp
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if (ot->obclass->id == OC_SPELL) {
|
|
if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) {
|
|
// not using 'cancast' here because we want to list spells
|
|
// even if we don't have enough mp
|
|
if (lfhasflagval(lf, F_CANCAST, ot->id, NA, NA, NULL)) {
|
|
int cost;
|
|
int found = B_FALSE;
|
|
cost = getmpcost(lf, ot->id);
|
|
for (n = 0; n < nposs; n++) {
|
|
if (poss[n] == ot->id) {
|
|
found = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
int power;
|
|
// add to list
|
|
poss[nposs] = ot->id;
|
|
mpcost[nposs] = cost;
|
|
deactspell[nposs] = B_FALSE; // default
|
|
power = getspellpower(lf, ot->id);
|
|
if (power > 0) {
|
|
if (hasactivespell(lf, ot->id)) {
|
|
cost = 0;
|
|
mpcost[nposs] = 0;
|
|
strcpy(mpdesc[nposs], "(Deactivate, at will)");
|
|
deactspell[nposs] = B_TRUE;
|
|
} else {
|
|
int ongoing = B_FALSE;
|
|
if (hasflag(ot->flags, F_ONGOING)) ongoing = B_TRUE;
|
|
|
|
if (hasflag(ot->flags, F_VARPOWER)) {
|
|
|
|
sprintf(mpdesc[nposs], "(%d-%d MP%s)", mpcost[nposs],
|
|
mpcost[nposs] * power,
|
|
ongoing ? ", ongoing" : "");
|
|
} else {
|
|
sprintf(mpdesc[nposs], "(%d MP%s)", mpcost[nposs],
|
|
ongoing ? ", ongoing" : "");
|
|
}
|
|
}
|
|
if (lf->mp >= mpcost[nposs]) {
|
|
validspell[nposs] = B_TRUE;
|
|
} else {
|
|
validspell[nposs] = B_FALSE;
|
|
}
|
|
} else {
|
|
sprintf(mpdesc[nposs], "(too hard)");
|
|
validspell[nposs] = B_FALSE;
|
|
}
|
|
nposs++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // end foreach spell school
|
|
|
|
|
|
if (lfhasflag(lf, F_NOSPELLS) && (nposs == 0)) {
|
|
msg("%ss cannot use magic!", lf->race->name);
|
|
return;
|
|
}
|
|
|
|
// list player's magic...
|
|
ch = 'a';
|
|
initprompt(pr, ques);
|
|
prompt.maycancel = B_TRUE;
|
|
addpromptq(pr, ques2);
|
|
|
|
lastschool = SS_LAST;
|
|
for (i = 0; i < nposs; i++) {
|
|
int power;
|
|
ot = findot(poss[i]);
|
|
assert(ot);
|
|
|
|
power = getspellpower(lf, poss[i]);
|
|
|
|
// heading
|
|
f = hasflag(ot->flags, F_SPELLSCHOOL);
|
|
assert(f);
|
|
if (f->val[0] != lastschool) {
|
|
lastschool = f->val[0];
|
|
addheading(pr, getschoolname(lastschool));
|
|
}
|
|
|
|
getspellname(ot->id, player, buf2);
|
|
if (deactspell[i]) {
|
|
strcat(buf2, "/deact");
|
|
}
|
|
|
|
|
|
if (validspell[i]) {
|
|
strcpy(costbuf, "");
|
|
} else {
|
|
strcpy(costbuf, "(NOT CASTABLE) ");
|
|
}
|
|
|
|
strcat(costbuf, mpdesc[i]);
|
|
sprintf(buf, "%-30s%s", buf2, costbuf);
|
|
// we don't want spell letters to change
|
|
// every time you get a new spell, so the
|
|
// choice letter always comes from spell letter
|
|
|
|
/*
|
|
f = hasflag(ot->flags, F_SPELLLETTER);
|
|
assert(f);
|
|
*/
|
|
// letter doesn't matter
|
|
addchoice(pr, 'a', buf2, buf, ot);
|
|
}
|
|
}
|
|
|
|
void domagic(enum OBTYPE spellid, int cellx, int celly) {
|
|
flag_t *f;
|
|
objecttype_t *ot;
|
|
int finished;
|
|
|
|
// init the prompt if required.
|
|
if (spellid == OT_NONE) {
|
|
makespellchoicelist(&prompt, player, "Use which spell/ability:","Describe which spell/ability:");
|
|
}
|
|
|
|
finished = B_FALSE;
|
|
while (!finished) {
|
|
// ask for spell if required
|
|
if (spellid == OT_NONE) {
|
|
if (prompt.nchoices > 0) {
|
|
getchoicestr(&prompt, B_TRUE, B_FALSE);
|
|
|
|
ot = prompt.result;
|
|
if (ot) {
|
|
spellid = ot->id;
|
|
}
|
|
} else {
|
|
msg("You don't have any spells or abilities!");
|
|
return;
|
|
}
|
|
} // end if spellid == NONE
|
|
|
|
// if still no spell, finish.
|
|
if (spellid == OT_NONE) {
|
|
clearmsg();
|
|
msg("Cancelled.");
|
|
return;
|
|
} else { // otherwise either cast the spell or describe it
|
|
cell_t *targcell = NULL;
|
|
lifeform_t *targlf = NULL;
|
|
|
|
if (prompt.whichq == 0) { // cast the spell
|
|
// update lastcmd
|
|
f = hasflag(player->flags, F_LASTCMD);
|
|
if (f) {
|
|
f->val[2] = spellid;
|
|
}
|
|
|
|
// try to cast it
|
|
ot = findot(spellid);
|
|
|
|
// specified x/y coords from a repeated cmd?
|
|
if (cellx == NA) {
|
|
targcell = NULL;
|
|
targlf = NULL;
|
|
} else {
|
|
targcell = getcellat(player->cell->map, cellx, celly);
|
|
targlf = haslf(targcell);
|
|
}
|
|
|
|
// should always work...
|
|
if (ot->obclass->id == OC_SPELL) {
|
|
castspell(player, spellid, targlf, NULL, targcell);
|
|
} else {
|
|
useability(player, spellid, targlf, targcell);
|
|
}
|
|
finished = B_TRUE;
|
|
} else { // describe it
|
|
describespell(ot);
|
|
// prompt again!
|
|
spellid = OT_NONE;
|
|
}
|
|
} // end cast/describe test
|
|
} // end while not finished
|
|
}
|
|
|
|
void domemmagic(void) {
|
|
char ch;
|
|
int slot;
|
|
objecttype_t *ot;
|
|
makespellchoicelist(&prompt, player, "Memorise which spell/ability:","Describe which spell/ability");
|
|
if (prompt.nchoices <= 0) {
|
|
msg("You don't have any spells or abilities!");
|
|
return;
|
|
}
|
|
ch = askchar("Memorise in which slot (1-9)", "1234567890","", B_FALSE);
|
|
slot = ch - '0';
|
|
|
|
getchoicestr(&prompt, B_FALSE, B_FALSE);
|
|
|
|
ot = (objecttype_t *)prompt.result;
|
|
if (ot) {
|
|
flag_t *f;
|
|
f = lfhasflagval(player, F_SHORTCUT, slot, NA, NA, NULL);
|
|
if (f) {
|
|
killflag(f);
|
|
}
|
|
addflag(player->flags, F_SHORTCUT, slot, NA, NA, ot->name);
|
|
msg("Shortcut %d set to '%s'",slot,ot->name);
|
|
}
|
|
}
|
|
|
|
void domsghist(void) {
|
|
int i;
|
|
int y;
|
|
cls();
|
|
mvwprintw(mainwin, 0, 0, "MESSAGE HISTORY:");
|
|
y = 1;
|
|
for (i = 0; i < nmsghist; i++) {
|
|
mvwprintw(mainwin, y, 0, msghist[i]);
|
|
y++;
|
|
}
|
|
wrefresh(mainwin);
|
|
getch();
|
|
// restore screen
|
|
//cls();
|
|
drawscreen();
|
|
real_clearmsg(B_TRUE);
|
|
}
|
|
|
|
void dooperate(obpile_t *op) {
|
|
object_t *o;
|
|
|
|
// ask which object to read
|
|
o = askobject(op, "Operate what", NULL, AO_OPERABLE);
|
|
if (o) {
|
|
if (isoperable(o)) {
|
|
operate(player, o, NULL);
|
|
} else {
|
|
msg("You can't operate that!");
|
|
}
|
|
}
|
|
}
|
|
|
|
int dopickup(obpile_t *op) {
|
|
int obcount;
|
|
//object_t *o = NULL;
|
|
int howmany = ALL;
|
|
int i;
|
|
lifeform_t *fromlf = NULL;
|
|
char lfname[BUFLEN];
|
|
char buf[BUFLEN];
|
|
|
|
if (op->owner) {
|
|
fromlf = op->owner;
|
|
getlfname(fromlf, lfname);
|
|
}
|
|
|
|
|
|
obcount = countobs(op);
|
|
// anything here?
|
|
if (obcount == 0) {
|
|
if (fromlf) {
|
|
msg("%s is not carrying anything!", lfname);
|
|
} else {
|
|
msg("There is nothing here to pick up!");
|
|
}
|
|
return B_TRUE;
|
|
} else if (!fromlf && (obcount == 1) && (op->first->amt == 1)) {
|
|
// just get it
|
|
howmany = ALL;
|
|
retobs[0] = op->first;
|
|
retobscount[0] = op->first->amt;
|
|
nretobs = 1;
|
|
} else {
|
|
if (fromlf) {
|
|
sprintf(buf, "Take what from %s",lfname);
|
|
} else {
|
|
strcpy(buf, "Pick up what");
|
|
}
|
|
// prompt which one to pick up
|
|
askobjectmulti(op, buf, AO_NONE);
|
|
}
|
|
|
|
if (nretobs <= 0) {
|
|
return B_TRUE;
|
|
} else if (lfhasflag(player, F_NOPACK)) {
|
|
msg("You lack the ability to carry things!");
|
|
return B_TRUE;
|
|
}
|
|
|
|
for (i = 0; i < nretobs; i++) {
|
|
pickup(player, retobs[i],retobscount[i], B_TRUE);
|
|
}
|
|
|
|
/*
|
|
if (o) {
|
|
pickup(player, o, howmany);
|
|
} else {
|
|
return B_TRUE;
|
|
}
|
|
*/
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
void doenter(lifeform_t *lf) {
|
|
object_t *enterob;
|
|
if (isplayer(lf)) {
|
|
enterob = hasob(lf->cell->obpile, OT_VENDINGMACHINE);
|
|
if (enterob) {
|
|
dovendingmachine(lf, enterob);
|
|
return;
|
|
}
|
|
enterob = hasob(lf->cell->obpile, OT_PORTAL);
|
|
if (enterob) {
|
|
usestairs(lf, enterob);
|
|
return;
|
|
}
|
|
|
|
// try to go down
|
|
dostairs(D_DOWN);
|
|
}
|
|
}
|
|
|
|
void doexplain(char *question) {
|
|
char buf[BUFLEN];
|
|
cell_t *where;
|
|
int done = B_FALSE;
|
|
|
|
while (!done) {
|
|
//sprintf(buf, "Select glyph to explain (ESC to cancel):");
|
|
where = askcoords(question, TT_NONE);
|
|
if (!where) {
|
|
clearmsg();
|
|
return;
|
|
}
|
|
|
|
// explain it
|
|
if (where->lf && cansee(player, where->lf)) {
|
|
showlfstats(where->lf, B_FALSE);
|
|
} else {
|
|
object_t *o;
|
|
// object description
|
|
o = gettopobject(where);
|
|
if (o) {
|
|
getobdesc(o, buf);
|
|
}
|
|
msg("%s", buf);
|
|
}
|
|
}
|
|
msg("Done.");
|
|
}
|
|
|
|
void dofinaloblist(obpile_t *op) {
|
|
object_t *o;
|
|
o = askobject(op, "Your final possessions were", NULL, AO_NONE);
|
|
while (o) {
|
|
// describe it
|
|
describeob(o);
|
|
// ask for another one
|
|
o = askobject(op, "Your final possessions were", NULL, AO_NONE);
|
|
}
|
|
real_clearmsg(B_TRUE);
|
|
}
|
|
|
|
void dofire(void) {
|
|
if (shoot(player)) {
|
|
// why not?
|
|
switch (reason) {
|
|
case E_NOTEQUIPPED:
|
|
msg("You have no firearm equipped!");
|
|
break;
|
|
case E_NOTARGET:
|
|
msg("You have no target selected!");
|
|
break;
|
|
case E_NOAMMO:
|
|
msg("You are out of ammo!");
|
|
break;
|
|
default:
|
|
msg("You cannot fire for some reason!");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void dohelp(void) {
|
|
int h;
|
|
int y;
|
|
command_t *c;
|
|
char *ftext= "%c %s";
|
|
|
|
h = getmaxy(mainwin);
|
|
|
|
cls();
|
|
centre(mainwin, 0, "COMMAND REFERENCE");
|
|
y = 2;
|
|
|
|
|
|
for (c = firstcommand ; c ; c = c->next) {
|
|
mvwprintw(mainwin, y, 0, ftext, c->ch, c->desc); y++;
|
|
if (y >= (h-2)) {
|
|
centre(mainwin, h-1, "[Press any key]");
|
|
getch();
|
|
cls();
|
|
y = 2;
|
|
}
|
|
}
|
|
centre(mainwin, h-1, "[Press any key]");
|
|
getch();
|
|
|
|
drawscreen();
|
|
real_clearmsg(B_TRUE);
|
|
}
|
|
|
|
void doinventory(obpile_t *op) {
|
|
object_t *o;
|
|
char buf[BUFLEN];
|
|
float packweight,maxweight,pct;
|
|
packweight = getobpileweight(player->pack);
|
|
maxweight = getmaxcarryweight(player);
|
|
pct = (packweight / maxweight) * 100;
|
|
sprintf(buf, "Inventory (%0.0f/%0.0f kg, %0.0f%%)", packweight, maxweight, pct);
|
|
o = askobject(op, buf, NULL, AO_NONE);
|
|
while (o) {
|
|
// describe it
|
|
describeob(o);
|
|
// ask for another one
|
|
o = askobject(op, buf, NULL, AO_NONE);
|
|
}
|
|
real_clearmsg(B_TRUE);
|
|
}
|
|
|
|
|
|
void doquaff(obpile_t *op) {
|
|
object_t *o,*liquid = NULL;
|
|
|
|
// quaffable objects here?
|
|
for (o = player->cell->obpile->first; o ; o = o->next) {
|
|
if (isdrinkable(o) && canquaff(player, o)) {
|
|
char obname[BUFLEN];
|
|
char buf[BUFLEN];
|
|
char ch;
|
|
getobname(o, obname, o->amt);
|
|
sprintf(buf, "There %s %s here. Drink %s",
|
|
(o->amt == 1) ? "is" : "are",
|
|
obname,
|
|
(o->amt == 1) ? "it" : "one");
|
|
ch = askchar(buf, "yn","n", B_TRUE);
|
|
if (ch == 'y') {
|
|
liquid = o;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ask which object to quaff
|
|
if (!liquid) {
|
|
liquid = askobjectwithflag(op, "Quaff what", NULL, AO_NONE, F_DRINKABLE);
|
|
}
|
|
if (liquid) {
|
|
if (canquaff(player, liquid)) {
|
|
quaff(player, liquid);
|
|
} else {
|
|
switch (reason) {
|
|
case E_INSUBSTANTIAL:
|
|
msg("You need a physical body to do that!");
|
|
break;
|
|
case E_WRONGOBTYPE:
|
|
default:
|
|
msg("You can't drink that!");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void dolockpick(obpile_t *op) {
|
|
object_t *o;
|
|
char ch;
|
|
int dir;
|
|
|
|
if (!hasobwithflag(player->pack, F_PICKLOCKS)) {
|
|
msg("You have nothing to use for lockpicking!");
|
|
return;
|
|
}
|
|
|
|
// ask direction
|
|
ch = askchar("Lockpick in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
|
|
dir = chartodir(ch);
|
|
if (dir == D_NONE) {
|
|
clearmsg();
|
|
return;
|
|
} else {
|
|
cell_t *c;
|
|
c = getcellindir(player->cell, dir);
|
|
if (c) {
|
|
object_t *targ;
|
|
// something to lockpick there?
|
|
targ = hasobwithflag(c->obpile, F_LOCKED);
|
|
if (targ) {
|
|
// ask which object to use
|
|
o = askobjectwithflag(op, "Lockpick using what", NULL, AO_NONE, F_PICKLOCKS);
|
|
if (o) {
|
|
if (hasflag(o->flags, F_PICKLOCKS)) {
|
|
lockpick(player, targ, o);
|
|
} else {
|
|
msg("That can't be used to pick locks!");
|
|
}
|
|
} else {
|
|
msg("Cancelled.");
|
|
return;
|
|
}
|
|
} else {
|
|
// fail
|
|
msg("There is nothing locked there!");
|
|
}
|
|
} else {
|
|
clearmsg();
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void donextguntarget(void) {
|
|
object_t *gun;
|
|
char gunname[BUFLEN];
|
|
int i,startpos;
|
|
int done;
|
|
lifeform_t *targ;
|
|
|
|
gun = getfirearm(player);
|
|
if (!gun) {
|
|
msg("You have no firearm equipped!");
|
|
return;
|
|
}
|
|
getobname(gun, gunname, 1);
|
|
|
|
// get current target
|
|
targ = getguntarget(player);
|
|
|
|
// find current target cell
|
|
startpos = 0; // default
|
|
for (i = 0; i < player->nlos; i++) {
|
|
cell_t *c;
|
|
c = player->los[i];
|
|
if (c->lf && (c->lf == targ)) {
|
|
startpos = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
i = startpos;
|
|
done = B_FALSE;
|
|
while (!done) {
|
|
cell_t *c;
|
|
c = player->los[i];
|
|
if (c->lf && (c->lf != player) && (c->lf != targ)) {
|
|
if (haslof(player->cell, c, LOF_NEED, NULL) && isingunrange(player, c)) {
|
|
// found one!
|
|
setguntarget(player, c->lf);
|
|
done = B_TRUE;
|
|
}
|
|
}
|
|
i++;
|
|
if (i >= player->nlos) {
|
|
i = 0;
|
|
}
|
|
if (i == startpos) {
|
|
// no new targets found - keep current one.
|
|
setguntarget(player, targ);
|
|
done = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
void dopour(obpile_t *op) {
|
|
object_t *o;
|
|
|
|
// ask which object to read
|
|
o = askobject(op, "Pour what", NULL, AO_POURABLE);
|
|
if (o) {
|
|
if (ispourable(o)) {
|
|
pour(player, o);
|
|
} else {
|
|
msg("That isn't pourable!");
|
|
}
|
|
}
|
|
}
|
|
|
|
void doquit(void) {
|
|
char ch;
|
|
ch = askchar("Really quit", "yn","n", B_TRUE);
|
|
if (ch == 'y') {
|
|
setlastdam(player, "quitting");
|
|
player->alive = B_FALSE;
|
|
}
|
|
}
|
|
|
|
void doread(obpile_t *op) {
|
|
object_t *o;
|
|
|
|
if (isblind(player)) {
|
|
msg("You can't read while blind!");
|
|
return;
|
|
}
|
|
|
|
// ask which object to read
|
|
o = askobject(op, "Read what", NULL, AO_READABLE);
|
|
if (o) {
|
|
if (isreadable(o)) {
|
|
readsomething(player, o);
|
|
} else {
|
|
msg("You can't read that!");
|
|
}
|
|
}
|
|
}
|
|
|
|
void dorest(void) {
|
|
// can we rest?
|
|
if (canrest(player)) {
|
|
int willtrain = B_FALSE;
|
|
if (player->skillpoints || lfhasflag(player, F_STATGAINREADY)) {
|
|
int ch;
|
|
ch = askchar("Would you like to train your skills?","yn","y", B_TRUE);
|
|
if (ch == 'y') {
|
|
willtrain = B_TRUE;
|
|
}
|
|
}
|
|
// if not training, only rest if we need to.
|
|
if (!willtrain) {
|
|
char validchars[BUFLEN];
|
|
char ques[BUFLEN];
|
|
char ch;
|
|
strcpy(validchars, "");
|
|
if (player->hp < player->maxhp) {
|
|
strcat(validchars, "h");
|
|
}
|
|
if ((getmaxmp(player) > 0) && (player->mp < getmaxmp(player))) {
|
|
strcat(validchars, "m");
|
|
}
|
|
|
|
if (strchr(validchars, 'h') && strchr(validchars, 'm')) {
|
|
strcat(validchars, "bn");
|
|
strcpy(ques, "Rest until full HP, Mana, Both or none");
|
|
ch = askchar(ques, validchars, "b", B_TRUE);
|
|
if (ch == 'b') {
|
|
addflag(player->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
|
|
addflag(player->flags, F_RESTUNTILMP, B_TRUE, NA, NA, NULL);
|
|
} else if (ch == 'h') {
|
|
addflag(player->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
|
|
} else if (ch == 'm') {
|
|
addflag(player->flags, F_RESTUNTILMP, B_TRUE, NA, NA, NULL);
|
|
}
|
|
} else if (strchr(validchars, 'h')) {
|
|
strcpy(ques, "Rest until full HP");
|
|
ch = askchar(ques, "yn", "y", B_TRUE);
|
|
if (ch == 'y') {
|
|
addflag(player->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
|
|
}
|
|
} else if (strchr(validchars, 'm')) {
|
|
strcpy(ques, "Rest until full Mana");
|
|
ch = askchar(ques, "yn", "y", B_TRUE);
|
|
if (ch == 'y') {
|
|
addflag(player->flags, F_RESTUNTILMP, B_TRUE, NA, NA, NULL);
|
|
}
|
|
} else {
|
|
msg("You don't need to rest at the moment.");
|
|
return;
|
|
}
|
|
|
|
if (!lfhasflag(player, F_RESTUNTILHP) && !lfhasflag(player, F_RESTUNTILMP)) {
|
|
msg("Cancelled.");
|
|
return;
|
|
}
|
|
}
|
|
startresting(player, willtrain);
|
|
// do the first one right away
|
|
rest(player, B_TRUE);
|
|
} else {
|
|
switch (reason) {
|
|
case E_MONSTERNEARBY:
|
|
msg("You cannot rest - there are monsters nearby!");
|
|
break;
|
|
default:
|
|
msg("You cannot rest for some reason.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void doselguntarget(void) {
|
|
object_t *gun;
|
|
cell_t *where;
|
|
char buf[BUFLEN];
|
|
char gunname[BUFLEN];
|
|
gun = getfirearm(player);
|
|
if (!gun) {
|
|
msg("You have no firearm equipped!");
|
|
return;
|
|
}
|
|
getobname(gun, gunname, 1);
|
|
|
|
sprintf(buf, "Aim %s where?",gunname);
|
|
where = askcoords(buf, TT_MONSTER);
|
|
if (where) {
|
|
if (where->lf && haslof(player->cell, where, LOF_NEED, NULL)) {
|
|
setguntarget(player, where->lf);
|
|
} else {
|
|
setguntarget(player, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void dostairs(int dir) {
|
|
object_t *o;
|
|
o = hasobwithflagval(player->cell->obpile, F_CLIMBABLE, dir, NA, NA, NULL);
|
|
if (o) {
|
|
usestairs(player, o);
|
|
} else {
|
|
msg("There are no stairs going %s here!", getdirname(dir));
|
|
}
|
|
}
|
|
|
|
int dotakeoff(obpile_t *op) {
|
|
object_t *o;
|
|
flag_t *f;
|
|
int rv = B_TRUE;
|
|
|
|
// ask which object to read
|
|
o = askobject(op, "Take off what", NULL, AO_EQUIPPEDARMOUR );
|
|
if (o) {
|
|
if (isarmour(o)) {
|
|
f = hasflag(o->flags, F_EQUIPPED);
|
|
if (f) {
|
|
rv = takeoff(player, o);
|
|
} else {
|
|
msg("You are not wearing that!");
|
|
rv = B_TRUE;
|
|
}
|
|
} else {
|
|
//rv = unweild(player, o);
|
|
rv = takeoff(player, o);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
void dothrow(obpile_t *op) {
|
|
object_t *o;
|
|
char buf[BUFLEN],buf2[BUFLEN];
|
|
|
|
if (!hasbp(player, BP_HANDS)) {
|
|
msg("You have no hands to throw with!");
|
|
return;
|
|
}
|
|
|
|
// ask which object to throw
|
|
o = askobject(op, "Throw what", NULL, AO_NONE);
|
|
if (o) {
|
|
int maxdist;
|
|
cell_t *where;
|
|
flag_t *f;
|
|
getobname(o, buf, 1);
|
|
|
|
f = hasflag(o->flags, F_EQUIPPED);
|
|
if (f && (f->val[0] != BP_WEAPON)) {
|
|
msg("You'll need to take it off first.");
|
|
return;
|
|
}
|
|
|
|
// calculate throw range
|
|
maxdist = getmaxthrowrange(player, o);
|
|
|
|
// ask where to throw it
|
|
sprintf(buf2, "Throw %s where?",buf);
|
|
where = askcoords(buf2, TT_MONSTER);
|
|
|
|
if (where) {
|
|
cell_t *newwhere = NULL;
|
|
if (!haslof(player->cell, where, LOF_WALLSTOP, &newwhere)) {
|
|
if (newwhere) {
|
|
// update destination cell.
|
|
where = newwhere;
|
|
} else {
|
|
if (reason == E_NOLOS) {
|
|
msg("You can't see there!");
|
|
} else { // ie. E_NOLOF
|
|
msg("You don't have a clear line of fire to there.");
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (getcelldist(player->cell, where) > maxdist) {
|
|
msg("You can't throw %s that far!",buf);
|
|
} else {
|
|
throwat(player, o, where);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
void drawscannedcell(cell_t *cell, int x, int y) {
|
|
if (cell->lf) {
|
|
char glyph;
|
|
// draw glyph based on size
|
|
switch(getlfsize(cell->lf)) {
|
|
case SZ_ENORMOUS:
|
|
glyph = '6';
|
|
break;
|
|
case SZ_HUGE:
|
|
glyph = '5';
|
|
break;
|
|
case SZ_LARGE:
|
|
glyph = '4';
|
|
break;
|
|
case SZ_HUMAN:
|
|
glyph = '3';
|
|
break;
|
|
case SZ_MEDIUM:
|
|
glyph = '2';
|
|
break;
|
|
case SZ_SMALL:
|
|
glyph = '1';
|
|
break;
|
|
case SZ_MINI:
|
|
case SZ_TINY:
|
|
default:
|
|
glyph = '0';
|
|
break;
|
|
}
|
|
mvwprintw(gamewin, y, x, "%c", glyph);
|
|
}
|
|
}
|
|
*/
|
|
|
|
// returns TRUE if escape pressed
|
|
int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar) {
|
|
char headbuf[BUFLEN];
|
|
int ch;
|
|
sprintf(headbuf, "%s (continued)", heading);
|
|
(*y)++;
|
|
if (*y >= (h-3)) {
|
|
centre(mainwin, h-2, MORESTRING);
|
|
if (bottomstring) {
|
|
centre(mainwin, h-1, bottomstring);
|
|
}
|
|
ch = getch();
|
|
if (cmdchars && strchr(cmdchars, ch)) {
|
|
if (retchar) *retchar = ch;
|
|
return B_TRUE;
|
|
} else if (ch == 27) { // ESC
|
|
if (retchar) *retchar = ch;
|
|
return B_TRUE;
|
|
}
|
|
|
|
cls(); *y = 0;
|
|
centre(mainwin, *y, headbuf);
|
|
*y += 2;
|
|
wmove(mainwin, *y, 0);
|
|
if (subheading) {
|
|
doheading(mainwin, y, 0, subheading);
|
|
}
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
// draw a cell which we remember, but can't see
|
|
/*
|
|
void drawunviscell(cell_t *cell, int x, int y) {
|
|
glyph_t glyph;
|
|
object_t *o;
|
|
|
|
// copy from cell
|
|
glyph = cell->type->glyph;
|
|
|
|
if (glyph.ch == '.') {
|
|
glyph.ch = ' ';
|
|
}
|
|
|
|
// show staircases...
|
|
o = hasobwithflag(cell->obpile, F_CLIMBABLE);
|
|
if (o) {
|
|
glyph = *(getglyph(o));
|
|
}
|
|
// show dungeon features
|
|
o = hasobofclass(cell->obpile, OC_DFEATURE);
|
|
if (o) {
|
|
glyph = *(getglyph(o));
|
|
}
|
|
|
|
//mvwprintw(gamewin, y, x, "%c", glyph);
|
|
drawglyph(&glyph, x, y);
|
|
}
|
|
*/
|
|
|
|
void drawglyph(glyph_t *g, int x, int y) {
|
|
int col;
|
|
col = g->colour;
|
|
setcol(gamewin, g->colour);
|
|
mvwprintw(gamewin, y, x, "%c", g->ch);
|
|
unsetcol(gamewin, g->colour);
|
|
}
|
|
|
|
/*
|
|
void drawcell(cell_t *cell, int x, int y) {
|
|
drawglyph(&cell->type->glyph, x, y);
|
|
}
|
|
*/
|
|
|
|
// draw a cell that we have LOS to.
|
|
/*
|
|
void drawcellwithcontents(cell_t *cell, int x, int y) {
|
|
if (cell->lf && cansee(player, cell->lf)) { // lifeform here that we can see
|
|
glyph_t *gl;
|
|
// draw the lf's race glyph
|
|
gl = getlfglyph(cell->lf);
|
|
drawglyph(gl, x, y);
|
|
return;
|
|
} else {
|
|
void *thing;
|
|
glyph_t glyph;
|
|
// scanned lf here?
|
|
if (isinscanrange(cell, &thing, NULL, &glyph) == TT_MONSTER) {
|
|
//mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph);
|
|
drawglyph(&glyph, x, y);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ((countobs(cell->obpile) > 0)) {
|
|
object_t *o;
|
|
|
|
// draw highest object in sort order
|
|
o = gettopobject(cell);
|
|
if (o) {
|
|
drawglyph(getglyph(o), x, y);
|
|
} else {
|
|
// should never happen. if it does, just show the
|
|
// first object
|
|
dblog("Warn: sorted object glyph drawing matching nothing!");
|
|
//mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph);
|
|
drawglyph(&cell->obpile->first->type->obclass->glyph, x, y);
|
|
}
|
|
} else {
|
|
// draw cell normally
|
|
drawcell(cell, x, y);
|
|
}
|
|
}
|
|
*/
|
|
|
|
void drawcursor(void) {
|
|
// move cursor to player position
|
|
wmove(gamewin, player->cell->y - viewy, player->cell->x - viewx);
|
|
wrefresh(gamewin);
|
|
}
|
|
|
|
void drawlevelfor(lifeform_t *lf) {
|
|
int x,y;
|
|
cell_t *cell;
|
|
map_t *map;
|
|
map = lf->cell->map;
|
|
|
|
numdraws++;
|
|
|
|
// turn off cursor
|
|
curs_set(0);
|
|
|
|
// TODO: draw to buffer here...
|
|
// buffer is an array of 'glyph_t's
|
|
wclear(gamewin);
|
|
for (y = viewy; y < viewy + viewh; y++) {
|
|
for (x = viewx; x < viewx + vieww; x++) {
|
|
cell = getcellat(map, x, y);
|
|
if (cell) {
|
|
glyph_t glyph,screenglyph;
|
|
getcellglyph(&glyph, cell, lf);
|
|
//drawglyph(&glyph, x - viewx, y - viewy);
|
|
|
|
// only draw if screen char/colour is different
|
|
screenglyph.ch = mvwinch(gamewin, y - viewy, x - viewx) & A_CHARTEXT;
|
|
if (screenglyph.ch != glyph.ch) {
|
|
drawglyph(&glyph, x - viewx, y - viewy);
|
|
} else {
|
|
screenglyph.colour = mvwinch(gamewin, y - viewy, x - viewx) & A_COLOR;
|
|
if (screenglyph.colour != glyph.colour) {
|
|
drawglyph(&glyph, x - viewx, y - viewy);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
// turn on cursor
|
|
curs_set(1);
|
|
// move it to the player's position
|
|
wmove(gamewin, lf->y - viewy, lf->x - viewx);
|
|
}
|
|
|
|
void doheading(WINDOW *win, int *y, int x, char *what) {
|
|
int len;
|
|
char *buf;
|
|
len = strlen(what) + 1;
|
|
buf = malloc(len * sizeof(char));
|
|
memset(buf, '-', (size_t)len);
|
|
mvwprintw(win, *y, x, what); (*y)++;
|
|
mvwprintw(win, *y, x, buf); (*y)++;
|
|
free(buf);
|
|
}
|
|
|
|
void initgfx(void) {
|
|
int msgwinh = 2;
|
|
int statwinh = 2;
|
|
mainwin = initscr();
|
|
|
|
// colour setup
|
|
if (!has_colors()) {
|
|
printf("Terminal does not support colour.\n");
|
|
hascolour = B_FALSE;
|
|
exit(1);
|
|
}
|
|
start_color();
|
|
|
|
init_pair(C_BLACK, COLOR_BLACK, COLOR_BLACK);
|
|
init_pair(C_RED, COLOR_RED, COLOR_BLACK);
|
|
init_pair(C_GREEN, COLOR_GREEN, COLOR_BLACK);
|
|
init_pair(C_BROWN, COLOR_YELLOW, COLOR_BLACK);
|
|
init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK);
|
|
init_pair(C_BLUE, COLOR_BLUE, COLOR_BLACK);
|
|
init_pair(C_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
|
|
init_pair(C_CYAN, COLOR_CYAN, COLOR_BLACK);
|
|
init_pair(C_GREY, COLOR_WHITE, COLOR_BLACK);
|
|
|
|
init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK);
|
|
init_pair(C_WHITE, COLOR_WHITE, COLOR_BLACK);
|
|
init_pair(C_BOLDCYAN, COLOR_CYAN, COLOR_BLACK);
|
|
init_pair(C_BOLDBLUE, COLOR_BLUE, COLOR_BLACK);
|
|
init_pair(C_BOLDMAGENTA, COLOR_MAGENTA, COLOR_BLACK);
|
|
init_pair(C_BOLDGREEN, COLOR_GREEN, COLOR_BLACK);
|
|
init_pair(C_ORANGE, COLOR_RED, COLOR_BLACK);
|
|
|
|
noecho();
|
|
cbreak();
|
|
nodelay(mainwin, FALSE);
|
|
|
|
getmaxyx(mainwin, SCREENH, SCREENW);
|
|
|
|
// determine window sizes
|
|
vieww = SCREENW;
|
|
//viewh = SCREENH - 4;
|
|
//viewh = SCREENH - statwinh - msgwinh - 1;
|
|
viewh = SCREENH - statwinh - msgwinh;
|
|
|
|
// create windows
|
|
//msgwin = newwin(1, vieww, 0, 0);
|
|
msgwin = newwin(msgwinh, vieww, 0, 0);
|
|
gamewin = newwin(viewh, vieww, msgwinh, 0);
|
|
//statwin = newwin(statwinh, vieww, msgwinh + viewh + statwinh - 2 ,0);
|
|
statwin = newwin(statwinh, vieww, SCREENH - statwinh,0);
|
|
statdirty = B_TRUE;
|
|
|
|
redraw();
|
|
refresh();
|
|
|
|
// init message buffer
|
|
strcpy(msgbuf, "");
|
|
strcpy(lastmsgbuf, "xxx");
|
|
}
|
|
|
|
int drop(object_t *o, int count) {
|
|
object_t *newob;
|
|
obpile_t *op;
|
|
char obname[BUFLEN];
|
|
enum OBTYPE origid;
|
|
|
|
op = o->pile;
|
|
assert(op->owner);
|
|
|
|
getobname(o, obname, count);
|
|
|
|
origid = o->type->id;
|
|
newob = moveob(o, op->owner->cell->obpile, count);
|
|
if (newob) { // if drop was successful...
|
|
//taketime(op->owner, (SPEED_DROP * count));
|
|
taketime(op->owner, SPEED_DROP);
|
|
// if object wasn't changed...
|
|
if (newob->type->id == origid) {
|
|
if (op->owner) {
|
|
if (isplayer(op->owner)) {
|
|
msg("You drop %s.",obname);
|
|
} else if (cansee(player, op->owner)) {
|
|
char ownername[BUFLEN];
|
|
getlfname(op->owner, ownername);
|
|
msg("%s drops %s.",ownername, obname);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// tell the player why!
|
|
if (isplayer(op->owner)) {
|
|
switch (reason) {
|
|
case E_NOSPACE:
|
|
msg("There is no space here for any more objects!");
|
|
break;
|
|
default:
|
|
msg("For some reason, you cannot drop %s!");
|
|
break;
|
|
}
|
|
}
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
char getchoice(prompt_t *prompt) {
|
|
int i;
|
|
int y;
|
|
char ch;
|
|
int sel;
|
|
int gotheadings;
|
|
int first= 0;
|
|
int nextpage = -1;
|
|
int lastline = SCREENH - 4;
|
|
|
|
gotheadings = B_FALSE;
|
|
for (i = 0; i < prompt->nchoices; i++) {
|
|
if (prompt->choice[i].heading) {
|
|
gotheadings = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// loop until result is valid
|
|
sel = -1;
|
|
while (sel == -1) {
|
|
// show choices
|
|
cls();
|
|
y = 2;
|
|
nextpage = -1;
|
|
for (i = first; i < prompt->nchoices; i++) {
|
|
int atbottom;
|
|
|
|
atbottom = B_FALSE;
|
|
if (y > lastline) { // if we're at the bottom of the screen
|
|
atbottom = B_TRUE;
|
|
} else if (prompt->choice[i].heading && (y+1 > lastline)) {
|
|
// on a heading, and next line is at the bottom
|
|
atbottom = B_TRUE;
|
|
}
|
|
if (atbottom) {
|
|
nextpage = i;
|
|
mvwprintw(mainwin, y, 0, "--More--");
|
|
break;
|
|
}
|
|
|
|
// heading?
|
|
if (prompt->choice[i].heading) {
|
|
mvwprintw(mainwin, y, 0, "%s", prompt->choice[i].desc);
|
|
} else {
|
|
mvwprintw(mainwin, y, 0, "%s%c - %s", gotheadings ? " " : "", prompt->choice[i].ch, prompt->choice[i].desc);
|
|
}
|
|
y++;
|
|
}
|
|
|
|
// display prompt question
|
|
mvwprintw(mainwin, 0, 0, "%s %s", prompt->q[prompt->whichq],
|
|
prompt->maycancel ? "[ESC to cancel] " : "");
|
|
wrefresh(mainwin);
|
|
|
|
// ask for choice...
|
|
ch = getch();
|
|
if ((ch == 27) && (prompt->maycancel)) { // ESC - cancel
|
|
prompt->result = NULL;
|
|
sel = -1;
|
|
break;
|
|
} else if (ch == ' ') {
|
|
if (nextpage == -1) {
|
|
first = 0;
|
|
} else {
|
|
first = nextpage;
|
|
}
|
|
} else {
|
|
sel = -1;
|
|
for (i = 0 ; i < prompt->nchoices; i++) {
|
|
if (prompt->choice[i].ch == ch) {
|
|
sel = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ch != 27) {
|
|
// set result pointer
|
|
prompt->result = prompt->choice[i].data;
|
|
prompt->selection = i;
|
|
}
|
|
|
|
if ((gamemode == GM_GAMESTARTED)) {
|
|
drawscreen();
|
|
} else {
|
|
cls();
|
|
wrefresh(mainwin);
|
|
}
|
|
// return NUL or result char
|
|
if (ch == 27) {
|
|
return '\0';
|
|
}
|
|
return prompt->choice[i].ch;
|
|
}
|
|
|
|
char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
|
|
int i;
|
|
int y;
|
|
char ch;
|
|
int sel;
|
|
int gotheadings;
|
|
int first= 0;
|
|
int nextpage = -1;
|
|
int lastline = SCREENH - 4;
|
|
char inpstring[BUFLEN];
|
|
char curheading[BUFLEN];
|
|
int doneheading;
|
|
int nvalid;
|
|
char promptstr[BUFLEN];
|
|
int showall;
|
|
int autochar = 0;
|
|
|
|
showall = showallatstart;
|
|
|
|
strcpy(inpstring, "");
|
|
|
|
// mark valid choices, and determine whether we have
|
|
// headings
|
|
gotheadings = B_FALSE;
|
|
for (i = 0; i < prompt->nchoices; i++) {
|
|
if (prompt->choice[i].heading) {
|
|
gotheadings = B_TRUE;
|
|
prompt->choice[i].valid = B_FALSE;
|
|
} else {
|
|
prompt->choice[i].valid = B_TRUE;
|
|
}
|
|
}
|
|
|
|
strcpy(curheading, "");
|
|
doneheading = B_FALSE;
|
|
|
|
// loop until result is valid
|
|
sel = -1;
|
|
while (sel == -1) {
|
|
int atbottom;
|
|
// show choices which match our input string
|
|
if (showall) {
|
|
cls();
|
|
}
|
|
y = 2;
|
|
nextpage = -1;
|
|
nvalid = 0;
|
|
|
|
atbottom = B_FALSE;
|
|
for (i = 0; i < prompt->nchoices; i++) {
|
|
if (showall) {
|
|
if (!atbottom) {
|
|
if (y > lastline) { // if we're at the bottom of the screen
|
|
atbottom = B_TRUE;
|
|
} else if (prompt->choice[i].heading && (y+1 >= (SCREENH-2))) {
|
|
// on a heading, and next line is at the bottom
|
|
atbottom = B_TRUE;
|
|
}
|
|
if (atbottom) {
|
|
nextpage = i;
|
|
mvwprintw(mainwin, y, 0, "--' for next page--");
|
|
}
|
|
}
|
|
}
|
|
|
|
// heading?
|
|
if (prompt->choice[i].heading) {
|
|
strcpy(curheading, prompt->choice[i].desc);
|
|
doneheading = B_FALSE;
|
|
//mvwprintw(mainwin, y, 0, "%s", prompt->choice[i].text);
|
|
prompt->choice[i].valid = B_FALSE;
|
|
} else if (strlen(inpstring)) {
|
|
int matched = B_FALSE;
|
|
// does this choice match? use ->text, not ->desc
|
|
matched = strpixmatch(prompt->choice[i].text, inpstring);
|
|
|
|
if (matched) {
|
|
if (showall) {
|
|
// if we haven't printed the heading yet...
|
|
if (gotheadings && !doneheading) {
|
|
// only print if on the page
|
|
if ((i >= first) && !atbottom) {
|
|
// show heading first
|
|
mvwprintw(mainwin, y, 0, "%s", curheading);
|
|
y++;
|
|
}
|
|
doneheading = B_TRUE;
|
|
}
|
|
// only print if we're not off the bottom
|
|
if ((i >= first) && !atbottom) {
|
|
mvwprintw(mainwin, y, 0, "%s%s", gotheadings ? " " : "", prompt->choice[i].desc);
|
|
y++;
|
|
}
|
|
}
|
|
prompt->choice[i].valid = B_TRUE;
|
|
nvalid++;
|
|
} else {
|
|
prompt->choice[i].valid = B_FALSE;
|
|
}
|
|
} else {
|
|
// if we haven't printed the heading yet...
|
|
if (showall) {
|
|
if (gotheadings && !doneheading) {
|
|
// only print if on the page
|
|
if ((i >= first) && !atbottom) {
|
|
// show heading first
|
|
mvwprintw(mainwin, y, 0, "%s", curheading);
|
|
y++;
|
|
}
|
|
doneheading = B_TRUE;
|
|
}
|
|
// only print if we're not off the bottom
|
|
if ((i >= first) && !atbottom) {
|
|
mvwprintw(mainwin, y, 0, "%s%s", gotheadings ? " " : "", prompt->choice[i].desc);
|
|
y++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// display prompt question
|
|
sprintf(promptstr, "%s [%s%s] %s",
|
|
prompt->q[prompt->whichq],
|
|
prompt->maycancel ? "ESC," : "",
|
|
showall ? "'=next page,?=toggle" : "?=list",
|
|
inpstring);
|
|
mvwprintw(mainwin, 0, 0, "%s", promptstr);
|
|
wclrtoeol(mainwin);
|
|
|
|
// if there's only one match, complete it
|
|
if (nvalid == 1) {
|
|
int cx,cy;
|
|
int validone = -1;
|
|
// remember cursor pos
|
|
getyx(mainwin, cy, cx);
|
|
|
|
// find the valid one
|
|
for (i = 0; i < prompt->nchoices; i++) {
|
|
if (prompt->choice[i].valid) {
|
|
validone = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// fill in the name of the completed choice
|
|
/*
|
|
sprintf(promptstr, "%s %s %s",
|
|
prompt->q[prompt->whichq], prompt->maycancel ? "[ESC=cancel, '=next page] " : "",
|
|
prompt->choice[validone].text);
|
|
*/
|
|
sprintf(promptstr, "%s [%s%s] %s",
|
|
prompt->q[prompt->whichq],
|
|
prompt->maycancel ? "ESC," : "",
|
|
showall ? "'=next page,?=toggle" : "?=list",
|
|
prompt->choice[validone].text);
|
|
mvwprintw(mainwin, 0, 0, "%s", promptstr);
|
|
|
|
// move the cursor back
|
|
wmove(mainwin, cy, cx);
|
|
}
|
|
wrefresh(mainwin);
|
|
|
|
|
|
// ask for choice...
|
|
if (autochar) {
|
|
ch = autochar;
|
|
autochar = 0;
|
|
} else {
|
|
ch = getch();
|
|
}
|
|
|
|
if ((ch >= '0') && (ch <= '9')) { // shortcut
|
|
flag_t *f;
|
|
// autofill from the shortcut
|
|
f = lfhasflagval(player, F_SHORTCUT, ch - '0', NA, NA, NULL);
|
|
if (f) {
|
|
strcpy(inpstring, f->text);
|
|
// now press enter
|
|
autochar = 10;
|
|
}
|
|
} else if ((ch == 27) && (prompt->maycancel)) { // ESC - cancel
|
|
sel = -1;
|
|
break;
|
|
} else if (ch == '\'') {
|
|
if (nextpage == -1) {
|
|
first = 0;
|
|
} else {
|
|
first = nextpage;
|
|
}
|
|
} else if ((ch == '!') || (ch == '?')) { // toggle prompts
|
|
if (showall) {
|
|
prompt->whichq++;
|
|
if (prompt->whichq >= prompt->nqs) prompt->whichq = 0;
|
|
} else {
|
|
showall = B_TRUE;
|
|
}
|
|
} else if ((ch == 8) || (ch == 127)) { // backspace
|
|
if (strlen(inpstring) > 0) {
|
|
inpstring[strlen(inpstring)-1] = '\0';
|
|
}
|
|
} else if (ch == 10) { // enter
|
|
// exactly one valid choice?
|
|
if (nvalid == 1) {
|
|
for (i = 0; i < prompt->nchoices; i++) {
|
|
if (prompt->choice[i].valid) {
|
|
sel = i;
|
|
break;
|
|
}
|
|
}
|
|
} else if (nvalid == 0) {
|
|
// cancel
|
|
sel = -1;
|
|
break;
|
|
}
|
|
} else {
|
|
char temp[2];
|
|
// append to input string
|
|
temp[0] = ch;
|
|
temp[1] = '\0';
|
|
strcat(inpstring, temp);
|
|
/*
|
|
sel = -1;
|
|
for (i = 0 ; i < prompt->nchoices; i++) {
|
|
if (prompt->choice[i].ch == ch) {
|
|
sel = i;
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
// set result pointer
|
|
if (sel == -1) {
|
|
prompt->result = NULL;
|
|
prompt->selection = -1;
|
|
} else {
|
|
prompt->result = prompt->choice[i].data;
|
|
prompt->selection = i;
|
|
}
|
|
|
|
if ((gamemode == GM_GAMESTARTED)) {
|
|
drawscreen();
|
|
} else {
|
|
cls();
|
|
wrefresh(mainwin);
|
|
}
|
|
// return NUL or result char
|
|
if (ch == 27) {
|
|
return '\0';
|
|
}
|
|
return prompt->choice[i].ch;
|
|
}
|
|
|
|
int getkey(void) {
|
|
int key_code=0;
|
|
|
|
|
|
key_code = getch();
|
|
|
|
// XXX NEW CODE:
|
|
if (strcmp(msgbuf, "")) {
|
|
clearmsg();
|
|
//strcpy(msgbuf, "");
|
|
//drawmsg();
|
|
//drawcursor();
|
|
}
|
|
|
|
return keycodetokey(key_code);
|
|
}
|
|
|
|
void handleinput(void) {
|
|
int ch;
|
|
//char buf[BUFLEN];
|
|
flag_t *f;
|
|
int gotcmd = B_FALSE;
|
|
char numstring[BUFLEN];
|
|
int count = 1;
|
|
|
|
// if running, automatically do move
|
|
f = hasflag(player->flags, F_RUNNING);
|
|
if (f) {
|
|
int dir;
|
|
int hasgettableobs = B_FALSE;
|
|
dir = f->val[0];
|
|
object_t *o;
|
|
|
|
|
|
for (o = player->cell->obpile->first ; o ; o = o->next) {
|
|
if (!hasflag(o->flags, F_NOPICKUP)) {
|
|
hasgettableobs = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// something here?
|
|
if (hasgettableobs) {
|
|
stoprunning(player);
|
|
} else if (!canmove(player, dir, NULL)) { // can't move anymore?
|
|
stoprunning(player);
|
|
} else {
|
|
if (trymove(player, dir, B_TRUE)) {
|
|
stoprunning(player);
|
|
} else {
|
|
// moved ok - dont wait for input
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
drawmsg();
|
|
|
|
strcpy(numstring, "");
|
|
gotcmd = B_FALSE;
|
|
while (!gotcmd) {
|
|
char temp[2];
|
|
flag_t repeatflag;
|
|
int wantrepeat = B_FALSE;
|
|
|
|
repeatflag.text = NULL;
|
|
|
|
drawcursor();
|
|
|
|
// repeated commands?
|
|
f = hasflag(player->flags, F_AUTOCMD);
|
|
if (f) {
|
|
ch = f->text[0];
|
|
if (f->val[0] <= 0) {
|
|
killflag(f);
|
|
msg("Finished repeating '%c'.",ch);
|
|
} else {
|
|
count = 1;
|
|
f->val[0]--;
|
|
}
|
|
} else {
|
|
ch = getkey();
|
|
}
|
|
gotcmd = B_TRUE;
|
|
|
|
|
|
switch (ch) {
|
|
// count
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
temp[0] = ch;
|
|
temp[1] = '\0';
|
|
strcat(numstring, temp);
|
|
count = atoi(numstring);
|
|
if (count < 1) count = 1;
|
|
if (count > 1) {
|
|
mvwprintw(msgwin, 0, 0, "count = %d", count);
|
|
} else {
|
|
wclear(msgwin);
|
|
}
|
|
wrefresh(msgwin);
|
|
gotcmd = B_FALSE;
|
|
break;
|
|
case 127:
|
|
case 8: // ie. backspace
|
|
if (strlen(numstring) > 0) {
|
|
// remove last letter of number string
|
|
numstring[strlen(numstring)-1] = '\0';
|
|
count = atoi(numstring);
|
|
if (count < 1) count = 1;
|
|
if (count > 1) {
|
|
mvwprintw(msgwin, 0, 0, "count = %d", count);
|
|
} else {
|
|
wclear(msgwin);
|
|
}
|
|
wrefresh(msgwin);
|
|
}
|
|
gotcmd = B_FALSE;
|
|
break;
|
|
case 'g': // repeat last command
|
|
f = hasflag(player->flags, F_LASTCMD);
|
|
if (f) {
|
|
ch = f->text[0];
|
|
repeatflag.id = f->id;
|
|
repeatflag.val[0] = f->val[0];
|
|
repeatflag.val[1] = f->val[1];
|
|
repeatflag.val[2] = f->val[2];
|
|
repeatflag.text = strdup(f->text);
|
|
wantrepeat = B_TRUE;
|
|
} else {
|
|
msg("Cannot repeat last command.");
|
|
}
|
|
break;
|
|
}
|
|
|
|
// now handle actual commands
|
|
f = hasflag(player->flags, F_LASTCMD);
|
|
if (f) {
|
|
killflag(f);
|
|
}
|
|
temp[0] = ch;
|
|
temp[1] = '\0';
|
|
|
|
switch (ch) {
|
|
// movement
|
|
case 'h':
|
|
case 'j':
|
|
case 'k':
|
|
case 'l':
|
|
case 'y':
|
|
case 'u':
|
|
case 'b':
|
|
case 'n':
|
|
trymove(player, chartodir(ch), B_TRUE);
|
|
break;
|
|
case 'H':
|
|
case 'J':
|
|
case 'K':
|
|
case 'L':
|
|
case 'Y':
|
|
case 'U':
|
|
case 'B':
|
|
case 'N':
|
|
tryrun(player, chartodir(ch));
|
|
break;
|
|
case '.': // wait
|
|
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
|
|
if (count > 1) {
|
|
addflag(player->flags, F_AUTOCMD, count, NA, NA, ".");
|
|
} else {
|
|
rest(player, B_TRUE);
|
|
}
|
|
break;
|
|
// testing
|
|
/*
|
|
case '1':
|
|
gettimetext(buf);
|
|
msg("The current time is %s",buf);
|
|
break;
|
|
case '2':
|
|
msg("Something happens.");
|
|
msg("Something else happens.");
|
|
msg("Another thing is about to happen now.");
|
|
msg("Too many things are happening!");
|
|
break;
|
|
*/
|
|
// player commands
|
|
case 'A': // attack
|
|
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
|
|
if (wantrepeat) {
|
|
doattackcell(repeatflag.val[2]);
|
|
} else {
|
|
doattackcell('\0');
|
|
}
|
|
break;
|
|
case 'i': // inventory
|
|
doinventory(player->pack);
|
|
break;
|
|
case '?': // help
|
|
dohelp();
|
|
break;
|
|
case '@': // display player stats
|
|
showlfstats(player, B_FALSE);
|
|
break;
|
|
case ']': // display armour
|
|
showlfarmour(player);
|
|
break;
|
|
case ':': // look at what's here
|
|
dolook(player->cell);
|
|
break;
|
|
case '|': // msg history - TODO: replace with ctrl-p
|
|
domsghist();
|
|
break;
|
|
case '/': // explain object
|
|
doexplain("Select glyph to explain (ESC to cancel):");
|
|
break;
|
|
case '\\': // list knowledge
|
|
doknowledgelist();
|
|
break;
|
|
case 'R': // rest
|
|
dorest();
|
|
break;
|
|
case 'm': // 'm'agic/abilities (magic)
|
|
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
|
|
if (wantrepeat) {
|
|
//domagic(repeatflag.val[2], repeatflag.val[0], repeatflag.val[1]);
|
|
// don't repeat the target cell!
|
|
domagic(repeatflag.val[2], NA, NA);
|
|
} else {
|
|
domagic(OT_NONE, NA, NA);
|
|
}
|
|
break;
|
|
case 'M': // 'M'emorise magic/ability shortcut
|
|
domemmagic();
|
|
break;
|
|
case '<': // go up
|
|
dostairs(D_UP);
|
|
break;
|
|
case '>': // go down
|
|
doenter(player);
|
|
break;
|
|
// firearm functions
|
|
case 'f': // fire gun
|
|
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
|
|
dofire();
|
|
break;
|
|
case 'a': // aim
|
|
doselguntarget();
|
|
break;
|
|
case 'F': // aim then fire
|
|
doselguntarget();
|
|
dofire();
|
|
break;
|
|
case '\'':
|
|
donextguntarget();
|
|
break;
|
|
// object functions
|
|
case 'c': // close
|
|
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
|
|
doclose();
|
|
break;
|
|
case 'C': // communicate
|
|
docomms();
|
|
break;
|
|
case 'e': // eat
|
|
doeat(player->pack);
|
|
break;
|
|
case 'd': // drop
|
|
dodrop(player->pack, B_SINGLE, player->cell->obpile);
|
|
break;
|
|
case 'D': // drop multiple things
|
|
dodrop(player->pack, B_MULTIPLE, player->cell->obpile);
|
|
break;
|
|
case 'W': // wear
|
|
dowear(player->pack);
|
|
break;
|
|
case 'w': // weild
|
|
doweild(player->pack);
|
|
break;
|
|
case 'T': // takeoff
|
|
dotakeoff(player->pack);
|
|
break;
|
|
case ',': // pickup
|
|
dopickup(player->cell->obpile);
|
|
break;
|
|
case 'r': // read
|
|
doread(player->pack);
|
|
break;
|
|
case 'q': // quaff
|
|
doquaff(player->pack);
|
|
break;
|
|
case 't': // throw
|
|
dothrow(player->pack);
|
|
break;
|
|
case 'p': // pick lock
|
|
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
|
|
dolockpick(player->pack);
|
|
break;
|
|
case 'P': // Pour
|
|
dopour(player->pack);
|
|
break;
|
|
case 'o': // operate
|
|
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
|
|
dooperate(player->pack);
|
|
break;
|
|
// GAME FUNCTIONS
|
|
case 'Q': // quit
|
|
doquit();
|
|
break;
|
|
case 'S': // save + quit
|
|
if (savegame()) {
|
|
msg("Save failed.");
|
|
} else {
|
|
msg("Saved successfully. See you later...");
|
|
more();
|
|
exit(0);
|
|
}
|
|
break;
|
|
default:
|
|
gotcmd = B_FALSE;
|
|
break;
|
|
}
|
|
if (repeatflag.text) {
|
|
free(repeatflag.text);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void initprompt(prompt_t *p, char *q1) {
|
|
int i;
|
|
for (i = 0; i < MAXPROMPTQUESTIONS; i++) {
|
|
if (p->q[i]) {
|
|
free(p->q[i]);
|
|
p->q[i] = NULL;
|
|
}
|
|
}
|
|
p->q[0] = strdup(q1);
|
|
p->nqs = 1;
|
|
p->whichq = 0;
|
|
p->maycancel = B_FALSE;
|
|
p->result = NULL;
|
|
p->nchoices = 0;
|
|
|
|
for (i = 0; i < MAXCHOICES; i++) {
|
|
choice_t *c;
|
|
c = &p->choice[i];
|
|
if (c->text) {
|
|
free(c->text);
|
|
c->text = NULL;
|
|
}
|
|
if (c->desc) {
|
|
free(c->desc);
|
|
c->desc = NULL;
|
|
}
|
|
c->data = NULL;
|
|
}
|
|
}
|
|
|
|
int keycodetokey(int keycode) {
|
|
int keystroke = 0;
|
|
|
|
if (keycode == -1) return -1;
|
|
|
|
if (keycode == 27) { // an esc sequence
|
|
keycode=getch();
|
|
keystroke=keycode;
|
|
keycode=getch();
|
|
keystroke=keystroke | (keycode<<8);
|
|
keycode=getch();
|
|
keystroke=keystroke | (keycode<<16);
|
|
} else {
|
|
// regular keypress
|
|
return (int)keycode;
|
|
}
|
|
|
|
return keystroke;
|
|
}
|
|
|
|
|
|
void dblog(char *format, ... ) {
|
|
char buf[HUGEBUFLEN];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsprintf( buf, format, args );
|
|
va_end(args);
|
|
|
|
/*
|
|
if (gamestarted) {
|
|
fprintf(logfile, "%s\n", buf);
|
|
fflush(logfile);
|
|
} else {
|
|
printf("%s\n", buf);
|
|
fflush(stdout);
|
|
}
|
|
*/
|
|
if (logfile) {
|
|
fprintf(logfile, "%s\n", buf);
|
|
fflush(logfile);
|
|
} else {
|
|
fprintf(stdout, "%s\n", buf);
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
|
|
// force a '--more--' prompt
|
|
void more(void) {
|
|
//msg("^");
|
|
strcat(msgbuf, MORESTRING);
|
|
//mvwprintw(msgwin, 0, 0, msgbuf);
|
|
drawmsg();
|
|
// wait for space
|
|
while (getch() != ' ');
|
|
// clear msg
|
|
clearmsg();
|
|
}
|
|
|
|
|
|
void warn(char *format, ... ) {
|
|
char buf[BUFLEN];
|
|
va_list args;
|
|
|
|
// like msg, but interrupts rest ect
|
|
interrupt(player);
|
|
|
|
|
|
va_start(args, format);
|
|
vsprintf( buf, format, args );
|
|
va_end(args);
|
|
msg_real("%s", buf);
|
|
}
|
|
|
|
void msgnocap(char *format, ... ) {
|
|
char buf[BUFLEN];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsprintf( buf, format, args );
|
|
va_end(args);
|
|
// like msg, but don't capitalise
|
|
msg_real("%s", buf);
|
|
}
|
|
|
|
void msg(char *format, ... ) {
|
|
char buf[BUFLEN];
|
|
va_list args;
|
|
|
|
|
|
va_start(args, format);
|
|
vsprintf( buf, format, args );
|
|
va_end(args);
|
|
|
|
capitalise(buf);
|
|
msg_real("%s", buf);
|
|
}
|
|
|
|
void msg_real(char *format, ... ) {
|
|
char buf[BUFLEN];
|
|
va_list args;
|
|
//char *p;
|
|
int db = B_FALSE;
|
|
|
|
// any msg will interrupt the player
|
|
//interrupt(player);
|
|
|
|
//msgmod = B_TRUE;
|
|
|
|
va_start(args, format);
|
|
vsprintf( buf, format, args );
|
|
va_end(args);
|
|
|
|
if (db) dblog("adding to msgbuf: [%s]",buf);
|
|
|
|
|
|
assert(!strchr(buf, '#'));
|
|
// ie. can the message buffer fit:
|
|
// what is already there + 2 spaces + the new text + '--more--' ?
|
|
//if (strlen(msgbuf) + 2 + strlen(buf) + strlen(MORESTRING) >= SCREENW) {
|
|
if (strlen(msgbuf) + 2 + strlen(buf) >= SCREENW) {
|
|
// do more
|
|
more();
|
|
} else {
|
|
if (strlen(msgbuf) > 0) {
|
|
strcat(msgbuf, " ");
|
|
}
|
|
}
|
|
strcat(msgbuf, buf);
|
|
|
|
|
|
if (db) dblog(" msgbuf is now: [%s]",msgbuf);
|
|
|
|
|
|
msgmod = B_TRUE;
|
|
|
|
// update msg window
|
|
drawmsg();
|
|
drawcursor();
|
|
|
|
}
|
|
|
|
int needsbold(enum COLOUR col) {
|
|
switch (col) {
|
|
case C_YELLOW:
|
|
case C_WHITE:
|
|
case C_BOLDCYAN:
|
|
case C_BOLDBLUE:
|
|
case C_BOLDMAGENTA:
|
|
case C_BOLDGREEN:
|
|
case C_ORANGE:
|
|
return B_TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
void nothinghappens(void) {
|
|
msg("Nothing seems to happen.");
|
|
}
|
|
|
|
void drawstatus(void) {
|
|
char buf[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
//char mpbuf[BUFLEN];
|
|
char waitbuf[BUFLEN];
|
|
char pname[BUFLEN];
|
|
char maxmpstr[BUFLEN];
|
|
flag_t *f;
|
|
enum ATTRIB a;
|
|
int myatt[MAXATTS];
|
|
long xpleft;
|
|
|
|
getplayernamefull(pname);
|
|
|
|
wclear(statwin);
|
|
xpleft = getxpforlev(player->level + 1) - player->xp;
|
|
|
|
sprintf(buf, "[%-26s] Lv:%d", pname,
|
|
player->level);
|
|
mvwprintw(statwin, 0, 0, buf);
|
|
|
|
if ((player->skillpoints == 0) && (getattpoints(player) == 0)) {
|
|
wprintw(statwin, " Next:%ld",xpleft);
|
|
} else {
|
|
setcol(statwin, C_BOLDGREEN);
|
|
wprintw(statwin, " LevUp",xpleft);
|
|
unsetcol(statwin, C_BOLDGREEN);
|
|
}
|
|
// blinded?
|
|
if (isblind(player)) {
|
|
setcol(statwin, C_RED);
|
|
wprintw(statwin, " Blind");
|
|
unsetcol(statwin, C_RED);
|
|
}
|
|
|
|
// paralysed somehow?
|
|
if (isimmobile(player)) {
|
|
setcol(statwin, C_RED);
|
|
wprintw(statwin, " Immobile");
|
|
unsetcol(statwin, C_RED);
|
|
} else {
|
|
// show player action speed
|
|
getspeedname(getactspeed(player), buf2);
|
|
if (strcmp(buf2, "normal")) {
|
|
enum COLOUR col;
|
|
if (getactspeed(player) < SP_NORMAL) {
|
|
col = C_GREEN;
|
|
} else {
|
|
col = C_RED;
|
|
}
|
|
setcol(statwin, col);
|
|
wprintw(statwin, " Act:");
|
|
capitaliseall(buf2);
|
|
wprintw(statwin, "%s", buf2);
|
|
unsetcol(statwin, col);
|
|
}
|
|
// show player movement speed
|
|
getspeedname(getmovespeed(player), buf2);
|
|
if (strcmp(buf2, "normal")) {
|
|
enum COLOUR col;
|
|
if (getmovespeed(player) < SP_NORMAL) {
|
|
col = C_GREEN;
|
|
} else {
|
|
col = C_RED;
|
|
}
|
|
setcol(statwin, col);
|
|
wprintw(statwin, " Mv:");
|
|
capitaliseall(buf2);
|
|
wprintw(statwin, "%s", buf2);
|
|
unsetcol(statwin, col);
|
|
}
|
|
}
|
|
|
|
// burdened somehow?
|
|
switch (isburdened(player)) {
|
|
case BR_BURDENED:
|
|
setcol(statwin, C_BROWN);
|
|
wprintw(statwin, " Burdened");
|
|
unsetcol(statwin, C_BROWN);
|
|
break;
|
|
case BR_STRAINED:
|
|
setcol(statwin, C_RED);
|
|
wprintw(statwin, " Strained");
|
|
unsetcol(statwin, C_RED);
|
|
break;
|
|
case BR_OVERLOADED:
|
|
setcol(statwin, C_YELLOW);
|
|
wprintw(statwin, " Overloaded");
|
|
unsetcol(statwin, C_YELLOW);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// show certain flags
|
|
if (lfhasflag(player, F_POISONED)) {
|
|
if (getskill(player, SK_FIRSTAID) >= PR_ADEPT) {
|
|
if (poisonthreatenslife(player)) {
|
|
setcol(statwin, C_GREEN);
|
|
wprintw(statwin, " Poison(bad)");
|
|
unsetcol(statwin, C_GREEN);
|
|
} else {
|
|
setcol(statwin, C_BROWN);
|
|
wprintw(statwin, " Poisoned(mild)");
|
|
unsetcol(statwin, C_BROWN);
|
|
}
|
|
} else {
|
|
setcol(statwin, C_GREEN);
|
|
wprintw(statwin, " Poisoned");
|
|
unsetcol(statwin, C_GREEN);
|
|
}
|
|
}
|
|
|
|
//mvwprintw(statwin, 0, 0, buf);
|
|
|
|
f = hasflag(player->flags, F_HUNGER);
|
|
if (f) {
|
|
int hlev;
|
|
hlev = gethungerlevel(f->val[0]);
|
|
if (hlev == H_NONE) {
|
|
strcpy(buf2, "");
|
|
} else {
|
|
gethungername(gethungerlevel(f->val[0]), buf2);
|
|
capitalise(buf2);
|
|
}
|
|
} else {
|
|
strcpy(buf2, "");
|
|
}
|
|
|
|
if (strlen(buf2) > 0) {
|
|
setcol(statwin, C_BROWN);
|
|
wprintw(statwin, " %s", buf2);
|
|
unsetcol(statwin, C_BROWN);
|
|
}
|
|
|
|
// construct waiting string
|
|
strcpy(waitbuf, "");
|
|
/*
|
|
// timespent > 0?
|
|
if (player->timespent) {
|
|
sprintf(buf, "busy: %d", player->timespent);
|
|
strcat(waitbuf, buf);
|
|
}
|
|
*/
|
|
|
|
|
|
f = hasflag(player->flags, F_AUTOCMD);
|
|
if (f) {
|
|
if (strlen(waitbuf)) strcat(waitbuf, ", ");
|
|
sprintf(buf, "'%c' x %d", f->text[0], f->val[0]);
|
|
strcat(waitbuf, buf);
|
|
}
|
|
|
|
if (strlen(waitbuf)) {
|
|
wprintw(statwin, " (%s)",waitbuf);
|
|
}
|
|
|
|
// SECOND LINE
|
|
|
|
for (a = 0; a < MAXATTS; a++) {
|
|
myatt[a] = getattr(player, a);
|
|
}
|
|
//redraw();
|
|
|
|
if (getmaxmp(player) == player->maxmp) {
|
|
strcpy(maxmpstr, "");
|
|
} else {
|
|
sprintf(maxmpstr, "(%d)",player->maxmp);
|
|
}
|
|
|
|
|
|
// HP
|
|
mvwprintw(statwin, 1, 0, "HP:");
|
|
setcol(statwin, getpctcol(player->hp, player->maxhp));
|
|
wprintw(statwin, "%d",player->hp);
|
|
unsetcol(statwin, getpctcol(player->hp, player->maxhp));
|
|
wprintw(statwin, "/%d ",player->maxhp);
|
|
|
|
// MP
|
|
if (getmaxmp(player) > 0) {
|
|
wprintw(statwin, "MP:");
|
|
setcol(statwin, getpctcol(player->mp, getmaxmp(player)));
|
|
wprintw(statwin, "%d",player->mp);
|
|
unsetcol(statwin, getpctcol(player->mp, getmaxmp(player)));
|
|
wprintw(statwin, "/%d%s ",getmaxmp(player),maxmpstr);
|
|
} else {
|
|
wprintw(statwin, "MP:- ");
|
|
}
|
|
|
|
sprintf(buf, "$:%d AR:%d ", countmoney(player), getarmourrating(player));
|
|
wprintw(statwin, buf);
|
|
|
|
|
|
for (a = 0; a < MAXATTS; a++) {
|
|
wprintw(statwin, "%s:", getattrabbrev(a));
|
|
if (myatt[a] == player->baseatt[a]) {
|
|
wprintw(statwin, "%d ",myatt[a]);
|
|
} else {
|
|
if (myatt[a] > player->baseatt[a]) {
|
|
setcol(statwin, C_GREEN);
|
|
wprintw(statwin, "%d*",myatt[a]);
|
|
unsetcol(statwin, C_GREEN);
|
|
} else {
|
|
setcol(statwin, C_RED);
|
|
wprintw(statwin, "%d*",myatt[a]);
|
|
unsetcol(statwin, C_RED);
|
|
}
|
|
}
|
|
}
|
|
|
|
wprintw(statwin, "DLev:%d", player->cell->map->depth);
|
|
}
|
|
|
|
void drawmsg(void) {
|
|
//char *nexttok;
|
|
int db = B_FALSE;
|
|
|
|
if (db) dblog("drawmsg called");
|
|
|
|
/*
|
|
if ( !strcmp(msgbuf, "") ) {
|
|
return;
|
|
}
|
|
|
|
if (!isplayerturn() && !msgmod) {
|
|
return;
|
|
}
|
|
*/
|
|
|
|
//dblog("calling drawmsg");
|
|
|
|
|
|
// is msgbuf has changed...
|
|
if (strcmp(msgbuf, lastmsgbuf) || msgmod) {
|
|
wclear(msgwin);
|
|
wmove(msgwin, 0, 0);
|
|
wprintw(msgwin, "%s", msgbuf);
|
|
//mvwprintw(msgwin, 0, 0, msgbuf);
|
|
wrefresh(msgwin);
|
|
strcpy(lastmsgbuf, msgbuf);
|
|
}
|
|
|
|
// drawcursor();
|
|
/*
|
|
// TODO: if it's a monster's turn, always do a more?
|
|
nexttok = strstr(msgbuf, "^");
|
|
if (!nexttok) {
|
|
// just update msg with current text
|
|
wclear(msgwin);
|
|
mvwprintw(msgwin, 0, 0, "%s", msgbuf);
|
|
wrefresh(msgwin);
|
|
} else {
|
|
while (nexttok) {
|
|
char thistok[BUFLEN];
|
|
int thistoklen;
|
|
// print up to just before the "^" current token
|
|
|
|
// remember this token
|
|
|
|
thistoklen = nexttok - msgbuf;
|
|
strncpy(thistok, msgbuf, thistoklen);
|
|
thistok[thistoklen] = '\0';
|
|
if (db) dblog("drawmsg: thistok is [%s]",thistok);
|
|
|
|
// is there another token?
|
|
nexttok = strstr(msgbuf, "^");
|
|
|
|
if (nexttok) {
|
|
nexttok++; // go forward past the ^
|
|
if (db) dblog("drawmsg: nexttok is [%s]",nexttok);
|
|
// print with '--more--' added to the end
|
|
if (db) dblog("drawmsg: displaying thistok [%s]",thistok);
|
|
wclear(msgwin);
|
|
mvwprintw(msgwin, 0, 0, "%s%s", thistok,MORESTRING);
|
|
wrefresh(msgwin);
|
|
|
|
// ...wait for spacebar before showing next bit...
|
|
while (getch() != ' ');
|
|
|
|
// we now know the player has read this
|
|
|
|
if (db) dblog("prompting for --more--");
|
|
|
|
// now clear msgstring up to end of where
|
|
// 'thistok' appears!
|
|
strcpy(msgbuf, nexttok);
|
|
if (db) dblog(" reduced msgbuf to: [%s]",msgbuf);
|
|
} else {
|
|
if (db) dblog("drawmsg: no nexttok");
|
|
// just print this bit
|
|
wclear(msgwin);
|
|
mvwprintw(msgwin, 0, 0, "%s", thistok);
|
|
wrefresh(msgwin);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// clear message buffer
|
|
if (isplayerturn()) {
|
|
strcpy(msgbuf, "");
|
|
if (db) dblog("clearing msg buf");
|
|
}
|
|
*/
|
|
//msgmod = B_FALSE;
|
|
|
|
}
|
|
|
|
void redraw(void) {
|
|
//dblog("redraw");
|
|
//wrefresh(msgwin);
|
|
wrefresh(statwin);
|
|
wrefresh(gamewin);
|
|
}
|
|
|
|
void setcol(WINDOW *win, enum COLOUR col) {
|
|
if (needsbold(col)) {
|
|
wattron(win, A_BOLD);
|
|
}
|
|
wattron(win, COLOR_PAIR(col));
|
|
}
|
|
void unsetcol(WINDOW *win, enum COLOUR col) {
|
|
wattroff(win, COLOR_PAIR(col));
|
|
if (needsbold(col)) {
|
|
wattroff(win, A_BOLD);
|
|
}
|
|
}
|
|
|
|
void showlfarmour(lifeform_t *lf) {
|
|
enum BODYPART bp;
|
|
object_t *o;
|
|
int y;
|
|
char buf[BUFLEN];
|
|
|
|
cls();
|
|
if (isplayer(lf)) {
|
|
centre(mainwin, 0, "CHARACTER EQUIPMENT");
|
|
} else{
|
|
centre(mainwin, 0, "MONSTER EQUIPMENT");
|
|
}
|
|
y = 2;
|
|
|
|
for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) {
|
|
sprintf(buf, "%15s:%3s",getbodypartname(bp), " ");
|
|
o = hasobwithflagval(lf->pack, F_EQUIPPED, bp, NA, NA, NULL);
|
|
if (o) {
|
|
char obname[BUFLEN];
|
|
getobname(o, obname, o->amt);
|
|
strcat(buf, obname);
|
|
} else {
|
|
strcat(buf, "-");
|
|
}
|
|
mvwprintw(mainwin, y, 0, "%s", buf);
|
|
y++;
|
|
}
|
|
y = getmaxy(mainwin);
|
|
centre(mainwin, y-1, "[Press any key]");
|
|
|
|
|
|
/*
|
|
|
|
|
|
f = hasflag(mylist[i]->flags,F_EQUIPPED);
|
|
if (f) {
|
|
if (f->val[0] == BP_WEAPON) {
|
|
if (hasflag(mylist[i]->flags, F_TWOHANDED)) {
|
|
strcat(buf2, " (two-handed weapon)");
|
|
} else {
|
|
strcat(buf2, " (weapon)");
|
|
}
|
|
} else {
|
|
strcat(buf2, " (");
|
|
strcat(buf2, getbodypartequipname(f->val[0]));
|
|
strcat(buf2, " ");
|
|
strcat(buf2, getbodypartname(f->val[0]));
|
|
strcat(buf2, ")");
|
|
}
|
|
}
|
|
*/
|
|
getch();
|
|
|
|
drawscreen();
|
|
real_clearmsg(B_TRUE);
|
|
}
|
|
|
|
void showlfstats(lifeform_t *lf, int showall) {
|
|
int y = 0, y2 = 0, x2 = 40;
|
|
int x;
|
|
int arating, evasion;
|
|
int speed,acc;
|
|
int h;
|
|
char buf[BUFLEN],buf2[BUFLEN];
|
|
job_t *j;
|
|
flag_t *f;
|
|
char *ftext= "%12s: ";
|
|
long xpneeded;
|
|
object_t *w;
|
|
objecttype_t *ot;
|
|
int first;
|
|
int i;
|
|
int unarmed = B_FALSE;
|
|
flag_t *uflag = NULL;
|
|
float dammod;
|
|
int accmod;
|
|
enum BODYPART bp;
|
|
enum BODYPART missingbp[MAXBODYPARTS];
|
|
int nmissingbp;
|
|
|
|
char ch;
|
|
char mode = '@';
|
|
char prompt[BUFLEN];
|
|
char cmdchars[BUFLEN];
|
|
int done = B_FALSE;
|
|
|
|
h = getmaxy(mainwin);
|
|
|
|
// override showall sometimes...
|
|
// need 'player == lf' to cope with mind scans
|
|
// where we update the player pointer, but don't
|
|
// change the target's '->controller' setting (meaning
|
|
// that isplayer(target) still returns false).
|
|
if (isplayer(lf) || isgenius(player) || (player == lf)) {
|
|
showall = B_TRUE;
|
|
}
|
|
|
|
if (showall) {
|
|
sprintf(prompt, "[@=stats S=skills/abilities M=magic E=effects %sESC=quit]", isplayer(lf) ? "" : "I=items " );
|
|
sprintf(cmdchars, "@ase%s",isplayer(lf) ? "" : "i");
|
|
} else {
|
|
sprintf(prompt, "%s", "[ESC=quit]");
|
|
sprintf(cmdchars, "%s", "@");
|
|
}
|
|
|
|
while (!done) {
|
|
cls();
|
|
y = 0;
|
|
ch = '\0';
|
|
if (mode == '@') {
|
|
if (isplayer(lf)) {
|
|
centre(mainwin, 0, "CHARACTER DETAILS");
|
|
} else{
|
|
centre(mainwin, 0, "MONSTER DETAILS");
|
|
}
|
|
y = 2;
|
|
y2 = 2;
|
|
|
|
dammod = getstrdammod(lf);
|
|
accmod = getstatmod(lf, A_DEX);
|
|
|
|
if (isplayer(lf)) {
|
|
getplayername(buf);
|
|
} else {
|
|
getlfnamea(lf, buf);
|
|
}
|
|
mvwprintw(mainwin, y, 0, ftext, "Name");
|
|
wprintw(mainwin, "%-20s", buf); y++;
|
|
|
|
if (isplayer(lf)) {
|
|
mvwprintw(mainwin, y, 0, ftext, "Race");
|
|
wprintw(mainwin, "%-20s", lf->race->name); y++;
|
|
}
|
|
|
|
j = getjob(lf);
|
|
if (j) {
|
|
mvwprintw(mainwin, y, 0, ftext, "Job");
|
|
wprintw(mainwin, "%-20s", j->name); y++;
|
|
}
|
|
|
|
if (showall) {
|
|
float w;
|
|
w = getlfweight(lf, B_NOOBS);
|
|
mvwprintw(mainwin, y, 0, ftext, "Weight");
|
|
getweighttext(w, buf);
|
|
wprintw(mainwin, buf, w); y++;
|
|
}
|
|
|
|
|
|
|
|
if (showall) {
|
|
mvwprintw(mainwin, y, 0, ftext, "Hit Points");
|
|
wprintw(mainwin, "%d / %d", lf->hp , lf->maxhp); y++;
|
|
} else {
|
|
char hpinfo[BUFLEN];
|
|
sprintf(hpinfo, "%s",getseenlfconditionname(lf, player));
|
|
if (strlen(hpinfo) > 0) {
|
|
mvwprintw(mainwin, y, 0, ftext, "Hit Points");
|
|
wprintw(mainwin, "%s", hpinfo); y++;
|
|
}
|
|
}
|
|
if (showall) {
|
|
char maxmpstr[BUFLEN];
|
|
|
|
if (getmaxmp(lf) == lf->maxmp) {
|
|
strcpy(maxmpstr, "");
|
|
} else {
|
|
sprintf(maxmpstr, "(%d)",lf->maxmp);
|
|
}
|
|
|
|
mvwprintw(mainwin, y, 0, ftext, "Mana");
|
|
wprintw(mainwin, "%d / %d%s", lf->mp , lf->maxmp,maxmpstr); y++;
|
|
}
|
|
if (showall) {
|
|
mvwprintw(mainwin, y, 0, ftext, "Exp Level");
|
|
if (isplayer(lf)) {
|
|
xpneeded = getxpforlev(lf->level + 1) - lf->xp;
|
|
wprintw(mainwin, "%d (%ld XP, %ld for next)", lf->level, lf->xp, xpneeded); y++;
|
|
} else {
|
|
wprintw(mainwin, "%d", lf->level); y++;
|
|
}
|
|
if (isplayer(lf)) {
|
|
int attpoints;
|
|
attpoints = getattpoints(lf);
|
|
mvwprintw(mainwin, y, 0, ftext, "Training");
|
|
if ((lf->skillpoints == 0) && (attpoints == 0)) {
|
|
wprintw(mainwin, "n/a");
|
|
} else {
|
|
wprintw(mainwin, "%d skill%s, %d attrib%s", lf->skillpoints,
|
|
(lf->skillpoints == 1) ? "" : "s",
|
|
attpoints,
|
|
(attpoints == 1) ? "" : "s");
|
|
}
|
|
y++;
|
|
}
|
|
}
|
|
y++; // skip line
|
|
|
|
if (showall) {
|
|
char buf2[BUFLEN];
|
|
int str;
|
|
str = getattr(lf, A_STR);
|
|
getstrname(str, buf2);
|
|
if (dammod == 1) {
|
|
sprintf(buf, "%d (%s)",str, buf2);
|
|
} else if (dammod > 1) {
|
|
sprintf(buf, "%d (%s, +%d%% dmg)",str, buf2, (int)((dammod * 100) - 100) );
|
|
} else { // ie. dammod < 1
|
|
sprintf(buf, "%d (%s, -%d%% dmg)",str, buf2, (int)(100 - (dammod * 100)) );
|
|
}
|
|
if (str != lf->baseatt[A_STR]) strcat(buf, "*");
|
|
mvwprintw(mainwin, y, 0, ftext, "STR");
|
|
wprintw(mainwin, "%s", buf); y++;
|
|
} else if (!isplayer(lf)) {
|
|
int str;
|
|
// just show name
|
|
str = getattr(lf, A_STR);
|
|
getstrname(str, buf);
|
|
if (str != lf->baseatt[A_STR]) strcat(buf, "*");
|
|
mvwprintw(mainwin, y, 0, ftext, "STR");
|
|
wprintw(mainwin, "%s", buf); y++;
|
|
}
|
|
|
|
if (showall) {
|
|
char buf2[BUFLEN];
|
|
int dex;
|
|
dex = getattr(lf, A_DEX);
|
|
getdexname(dex, buf2);
|
|
|
|
if (accmod == 0) {
|
|
sprintf(buf, "%d (%s)",dex, buf2);
|
|
} else if (accmod > 0) {
|
|
sprintf(buf, "%d (%s, +%d%% bonus)",dex, buf2, accmod );
|
|
} else { // ie. accmod < 0
|
|
sprintf(buf, "%d (%s, %d%% bonus)",dex, buf2, accmod );
|
|
}
|
|
|
|
if (dex != lf->baseatt[A_DEX]) strcat(buf, "*");
|
|
mvwprintw(mainwin, y, 0, ftext, "DEX");
|
|
wprintw(mainwin, "%s", buf); y++;
|
|
} else if (!isplayer(lf)) {
|
|
int dex;
|
|
// just show name
|
|
dex = getattr(lf, A_DEX);
|
|
getdexname(dex, buf);
|
|
if (dex != lf->baseatt[A_DEX]) strcat(buf, "*");
|
|
mvwprintw(mainwin, y, 0, ftext, "DEX");
|
|
wprintw(mainwin, "%s", buf); y++;
|
|
}
|
|
|
|
if (showall) {
|
|
char buf2[BUFLEN];
|
|
int iq;
|
|
iq = getattr(lf, A_IQ);
|
|
getiqname(iq, buf2);
|
|
sprintf(buf, "%d (%s)",iq, buf2);
|
|
if (iq != lf->baseatt[A_IQ]) strcat(buf, "*");
|
|
mvwprintw(mainwin, y, 0, ftext, "IQ");
|
|
wprintw(mainwin, "%s", buf); y++;
|
|
} else if (!isplayer(lf)) {
|
|
int iq;
|
|
// just show name
|
|
iq = getattr(lf, A_IQ);
|
|
getiqname(iq, buf);
|
|
if (iq != lf->baseatt[A_IQ]) strcat(buf, "*");
|
|
mvwprintw(mainwin, y, 0, ftext, "IQ");
|
|
wprintw(mainwin, "%s", buf); y++;
|
|
}
|
|
|
|
if (showall) {
|
|
char buf2[BUFLEN];
|
|
int con;
|
|
con = getattr(lf, A_CON);
|
|
getconname(con, buf2);
|
|
sprintf(buf, "%d (%s)",con, buf2);
|
|
if (con != lf->baseatt[A_CON]) strcat(buf, "*");
|
|
mvwprintw(mainwin, y, 0, ftext, "CON");
|
|
wprintw(mainwin, "%s", buf); y++;
|
|
} else if (!isplayer(lf)) {
|
|
int con;
|
|
// just show name
|
|
con = getattr(lf, A_CON);
|
|
getconname(con, buf);
|
|
if (con != lf->baseatt[A_CON]) strcat(buf, "*");
|
|
mvwprintw(mainwin, y, 0, ftext, "CON");
|
|
wprintw(mainwin, "%s", buf); y++;
|
|
}
|
|
|
|
//mvwprintw(mainwin, y, 0, ftext, "XP");
|
|
//wprintw(mainwin, "%ld (%ld more for next level)", lf->xp, xpneeded); y++;
|
|
|
|
y++; // skip line
|
|
|
|
|
|
// now go to second column
|
|
// WEAPON STUFF
|
|
|
|
w = getweapon(lf);
|
|
if (w) {
|
|
sprintf(buf, "%s", w->type->name);
|
|
} else {
|
|
obpile_t *op = NULL;
|
|
op = getunarmedweapon(lf, &uflag); // will return a random weapon. TODO: show all?
|
|
if (op->first) {
|
|
w = op->first;
|
|
sprintf(buf, "%s (unarmed)", w->type->name);
|
|
unarmed = B_TRUE;
|
|
} else {
|
|
sprintf(buf, "N/A");
|
|
}
|
|
killobpile(op);
|
|
}
|
|
mvwprintw(mainwin, y2, x2, ftext, "Current Weapon");
|
|
wprintw(mainwin, "%-20s", buf); y2++;
|
|
|
|
|
|
if (showall) {
|
|
if (w) {
|
|
// chance to hit
|
|
acc = getlfaccuracy(lf);
|
|
mvwprintw(mainwin, y2, x2, ftext, "Accuracy");
|
|
wprintw(mainwin, "%d%%", acc); y2++;
|
|
}
|
|
}
|
|
|
|
// attack speed
|
|
if (w) {
|
|
speed = getattackspeed(lf);
|
|
getspeedname(speed, buf);
|
|
capitalise(buf);
|
|
mvwprintw(mainwin, y2, x2, ftext, "Attack Speed");
|
|
wprintw(mainwin, "%-20s", buf); y2++;
|
|
}
|
|
|
|
|
|
// damage
|
|
if (w) {
|
|
int mindam,maxdam;
|
|
int bonus;
|
|
f = hasflag(w->flags, F_BONUS);
|
|
if (f && f->known) {
|
|
// only tell player about bonuses if they are known.!
|
|
bonus = f->val[0];
|
|
} else {
|
|
bonus = 0;
|
|
}
|
|
|
|
if (uflag) {
|
|
getdamrangeunarmed(uflag, &mindam, &maxdam);
|
|
} else {
|
|
f = hasflag(w->flags, F_DAM);
|
|
if (f) {
|
|
getdamrange(w->flags, &mindam, &maxdam);
|
|
} else {
|
|
mindam = 0;
|
|
maxdam = 0;
|
|
}
|
|
}
|
|
|
|
mindam += bonus;
|
|
maxdam += bonus;
|
|
|
|
// apply damage mod for strength
|
|
if (!hasflag(w->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
|
|
mindam = (int)((float)mindam * dammod);
|
|
maxdam = (int)((float)maxdam * dammod);
|
|
}
|
|
|
|
if (mindam < 0) mindam = 0;
|
|
if (maxdam < 0) maxdam = 0;
|
|
|
|
sprintf(buf, "%d-%d",(int)mindam,(int)maxdam);
|
|
} else {
|
|
// no damage
|
|
sprintf(buf, "N/A");
|
|
}
|
|
|
|
if (showall) {
|
|
mvwprintw(mainwin, y2, x2, ftext, "Attack Dmg");
|
|
wprintw(mainwin, "%-20s", buf); y2++;
|
|
}
|
|
|
|
|
|
|
|
y2++; // skip line
|
|
|
|
// ARMOUR STUFF
|
|
if (showall) {
|
|
arating = getarmourrating(lf);
|
|
mvwprintw(mainwin, y2, x2, ftext, "Armour");
|
|
if (arating > 0) {
|
|
wprintw(mainwin, "%d (-%0.0f%% dmg)", arating, getdamreducepct(arating)); y2++;
|
|
} else {
|
|
wprintw(mainwin, "%d", arating); y2++;
|
|
}
|
|
evasion = getevasion(lf);
|
|
mvwprintw(mainwin, y2, x2, ftext, "Evasion");
|
|
wprintw(mainwin, "%d%%", evasion); y2++;
|
|
|
|
y2++; // skip line
|
|
}
|
|
|
|
speed = getactspeed(lf);
|
|
getspeedname(speed, buf);
|
|
capitalise(buf);
|
|
mvwprintw(mainwin, y2, x2, ftext, "Action Speed");
|
|
wprintw(mainwin, "%-20s", buf); y2++;
|
|
|
|
speed = getmovespeed(lf);
|
|
getspeedname(speed, buf);
|
|
capitalise(buf);
|
|
mvwprintw(mainwin, y2, x2, ftext, "Move Speed");
|
|
wprintw(mainwin, "%-20s", buf); y2++;
|
|
|
|
|
|
y2++; // skip line
|
|
|
|
|
|
if (showall) {
|
|
f = hasflag(lf->flags, F_HUNGER);
|
|
if (f) {
|
|
gethungername(gethungerlevel(f->val[0]), buf);
|
|
capitalise(buf);
|
|
mvwprintw(mainwin, y2, x2, ftext, "Hunger");
|
|
|
|
wprintw(mainwin, "%-14s", buf); y++;
|
|
/*
|
|
if (showall) {
|
|
wprintw(mainwin, "%-14s (%d)", buf, f->val[0]); y++;
|
|
} else {
|
|
wprintw(mainwin, "%-14s", buf); y++;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
y++; // skip line
|
|
|
|
|
|
|
|
// back to first column
|
|
|
|
|
|
f = lfhasknownflag(lf, F_UNDEAD);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s %s undead.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
|
|
// non-intrinsic effecst like polymorph, eye shading
|
|
f = lfhasknownflag(lf, F_POLYMORPHED);
|
|
if (f && (f->known)) {
|
|
sprintf(buf, "%s have been polymorphed into a %s.",you(lf), lf->race->name);
|
|
//if (lfhasflag(lf, F_OMNIPOTENT) || lfhasflag(lf, F_EXTRAINFO)) {
|
|
sprintf(buf2, " [%d left]", f->lifetime);
|
|
strcat(buf, buf2);
|
|
// }
|
|
mvwprintw(mainwin, y, 0, "%s", buf);
|
|
y++;
|
|
}
|
|
|
|
// missing body parts?
|
|
if (lfhasflagval(lf, F_NOBODYPART, BP_WEAPON, NA, NA, NULL)) {
|
|
mvwprintw(mainwin, y, 0, "%s cannot use weapons.", you(lf));
|
|
y++;
|
|
}
|
|
|
|
nmissingbp = 0;
|
|
for (bp = BP_RIGHTHAND; bp < MAXBODYPARTS; bp++) {
|
|
if (lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) {
|
|
if (bp == BP_RIGHTHAND) {
|
|
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
|
|
missingbp[nmissingbp] = bp;
|
|
nmissingbp++;
|
|
}
|
|
} else if (bp == BP_LEFTHAND) {
|
|
if (!lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
|
|
missingbp[nmissingbp] = bp;
|
|
nmissingbp++;
|
|
}
|
|
} else {
|
|
missingbp[nmissingbp] = bp;
|
|
nmissingbp++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nmissingbp) {
|
|
sprintf(buf, "%s have no %s",you(lf),getbodypartname(missingbp[0]));
|
|
if (nmissingbp > 1) {
|
|
// construct list of missing body parts
|
|
for (i = 1; i < nmissingbp ; i++) {
|
|
if (i == nmissingbp - 1) { // last
|
|
strcat(buf, " or ");
|
|
strcat(buf, getbodypartname(missingbp[i]));
|
|
} else {
|
|
strcat(buf, ", ");
|
|
strcat(buf, getbodypartname(missingbp[i]));
|
|
}
|
|
}
|
|
}
|
|
strcat(buf, ".");
|
|
mvwprintw(mainwin, y, 0, "%s", buf);
|
|
y++;
|
|
}
|
|
|
|
if (eyesshaded(lf)) {
|
|
mvwprintw(mainwin, y, 0, "%s eyes are shaded.", your(lf), buf);
|
|
y++;
|
|
}
|
|
|
|
// fleeing?
|
|
if (showall) {
|
|
for (f = lf->flags->first ; f ; f = f->next) {
|
|
if (f->id == F_FLEEFROM) {
|
|
lifeform_t *lf2;
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
getlfname(lf2, buf);
|
|
mvwprintw(mainwin, y, 0, "%s %s fleeing from %s.",
|
|
you(lf), isplayer(lf) ? "are" : "is", buf);
|
|
y++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// diff materials?
|
|
if (lf->race->material->id != MT_FLESH) {
|
|
mvwprintw(mainwin, y, 0, "%s %s made out of %s.",you(lf), isplayer(lf) ? "are" : "is", lf->race->material->name);
|
|
y++;
|
|
}
|
|
|
|
if (showall) {
|
|
// resistances
|
|
strcpy(buf, "");
|
|
f = lfhasflagval(lf, F_DTRESIST, DT_ALL, NA, NA, NULL);
|
|
if (f && (showall || f->known)) {
|
|
sprintf(buf, "%s %s resistant to %s", you(lf), isplayer(lf) ? "are" : "is", getdamname(DT_ALL));
|
|
} else {
|
|
first = B_TRUE;
|
|
for (i = 0; i < MAXDAMTYPE; i++) {
|
|
f = isresistantto(lf->flags, i);
|
|
if (f && (showall || f->known)) {
|
|
if (first) {
|
|
sprintf(buf2, "%s %s resistant to: %s", you(lf), isplayer(lf) ? "are" : "is",getdamnamenoun(i));
|
|
first = B_FALSE;
|
|
} else {
|
|
sprintf(buf2, ", %s", getdamnamenoun(i));
|
|
}
|
|
|
|
|
|
if (lfhasknownflag(lf, F_EXTRAINFO) || lfhasflag(lf, F_OMNIPOTENT)) {
|
|
if (f->lifetime != PERMENANT) {
|
|
char buf3[BUFLEN];
|
|
sprintf(buf3, "[%dt]",f->lifetime);
|
|
strcat(buf2, buf3);
|
|
}
|
|
}
|
|
strcat(buf, buf2);
|
|
}
|
|
}
|
|
}
|
|
if (strlen(buf) > 0) {
|
|
strcat(buf, ".");
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
|
|
// immunities
|
|
strcpy(buf, "");
|
|
f = lfhasflagval(lf, F_DTIMMUNE, DT_ALL, NA, NA, NULL);
|
|
if (f && (showall || f->known)) {
|
|
sprintf(buf, "%s %s immune to %s", you(lf), isplayer(lf) ? "are" : "is", getdamname(DT_ALL));
|
|
} else {
|
|
first = B_TRUE;
|
|
for (i = 0; i < MAXDAMTYPE; i++) {
|
|
f = isimmuneto(lf->flags, i);
|
|
if (f && (showall || f->known)) {
|
|
if (first) {
|
|
sprintf(buf2, "%s %s immune to: %s", you(lf), isplayer(lf) ? "are" : "is", getdamname(i));
|
|
first = B_FALSE;
|
|
} else {
|
|
sprintf(buf2, ", %s", getdamname(i));
|
|
}
|
|
strcat(buf, buf2);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (strlen(buf) > 0) {
|
|
strcat(buf, ".");
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
|
|
// vulnerabilities
|
|
strcpy(buf, "");
|
|
f = lfhasflagval(lf, F_DTVULN, DT_ALL, NA, NA, NULL);
|
|
if (f && (showall || f->known)) {
|
|
sprintf(buf, "%s %s vulnerable to %s", you(lf), isplayer(lf) ? "are" : "is", getdamname(DT_ALL));
|
|
} else {
|
|
first = B_TRUE;
|
|
for (i = 0; i < MAXDAMTYPE; i++) {
|
|
f = isvulnto(lf->flags, i);
|
|
if (f && (showall || f->known)) {
|
|
if (first) {
|
|
sprintf(buf2, "%s %s vulnerable to: %s", you(lf), isplayer(lf) ? "are" : "is", getdamnamenoun(i));
|
|
first = B_FALSE;
|
|
} else {
|
|
sprintf(buf2, ", %s", getdamnamenoun(i));
|
|
}
|
|
|
|
|
|
if (lfhasknownflag(lf, F_EXTRAINFO) || lfhasflag(lf, F_OMNIPOTENT)) {
|
|
if (f->lifetime != PERMENANT) {
|
|
char buf3[BUFLEN];
|
|
sprintf(buf3, "[%dt]",f->lifetime);
|
|
strcat(buf2, buf3);
|
|
}
|
|
}
|
|
strcat(buf, buf2);
|
|
}
|
|
}
|
|
}
|
|
if (strlen(buf) > 0) {
|
|
strcat(buf, ".");
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
}
|
|
|
|
// obvious physical effects
|
|
// (NON-obvious intrinsics etc go on next page)
|
|
f = lfhasknownflag(lf, F_ASLEEP);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s %s sleeping.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_BEINGSTONED);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s %s being turning to stone.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
|
|
f = lfhasknownflag(lf, F_FLYING);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s flying.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
f = lfhasflag(lf, F_FROZEN);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s been turned to ice, and %s slowly melting.", you(lf), isplayer(lf) ? "have" : "has",
|
|
isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_GRABBEDBY);
|
|
if (f && (f->known)) {
|
|
lifeform_t *lf2;
|
|
char grabbername[BUFLEN];
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
getlfname(lf2, grabbername);
|
|
} else {
|
|
strcpy(grabbername, "something");
|
|
}
|
|
sprintf(buf,"%s %s being held by %s.",you(lf), isplayer(lf) ? "are" : "is", grabbername);
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_GRABBING);
|
|
if (f && (f->known)) {
|
|
lifeform_t *lf2;
|
|
char grabeename[BUFLEN];
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
getlfname(lf2, grabeename);
|
|
} else {
|
|
strcpy(grabeename, "something");
|
|
}
|
|
sprintf(buf,"%s %s holding on to %s.",you(lf), isplayer(lf) ? "are" : "is", grabeename);
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_INVISIBLE);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s invisible.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_LEVITATING);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s levitating.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
f = lfhasflag(lf, F_NONCORPOREAL);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s noncorporeal and can walk through walls.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
f = lfhasflag(lf, F_PRODUCESLIGHT);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s produce%s light.", you(lf), isplayer(lf) ? "" : "s");
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_SPRINTING);
|
|
if (f) {
|
|
if (f->val[0]) {
|
|
mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
} else {
|
|
mvwprintw(mainwin, y, 0, "%s %s exhausted.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
}
|
|
|
|
|
|
} else if (mode == 's') {
|
|
int exitnow = B_FALSE;
|
|
|
|
// now show intrinsics on next page
|
|
centre(mainwin, 0, "ABILITIES");
|
|
y = 2;
|
|
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if (ot->obclass->id == OC_ABILITY) {
|
|
f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
|
|
if (f && (f->known)) {
|
|
char expirebuf[BUFLEN];
|
|
char eb2[BUFLEN];
|
|
int needgrab = B_FALSE;
|
|
|
|
if (f->val[2] == NA) {
|
|
sprintf(expirebuf, "at will");
|
|
} else {
|
|
sprintf(expirebuf, "every %d turn%s",f->val[2],
|
|
(f->val[2] == 1) ? "" : "s");
|
|
}
|
|
|
|
// extra options?
|
|
texttospellopts(f->text, NULL, NULL, &needgrab);
|
|
if (needgrab) {
|
|
strcat(expirebuf, ",after grab");
|
|
}
|
|
|
|
if (strlen(expirebuf)) {
|
|
sprintf(eb2,"(%s)",expirebuf);
|
|
} else {
|
|
strcpy(eb2, "");
|
|
}
|
|
sprintf(buf, "%-12s%s%s", ot->name, ot->desc, eb2);
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
if (downline(&y, h, "ABILITIES", NULL, prompt, cmdchars, &ch)) {
|
|
exitnow = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
y++;
|
|
|
|
if (!exitnow) {
|
|
if (hasflag(lf->flags, F_HASSKILL)) {
|
|
centre(mainwin, y, "SKILLS"); y += 2;
|
|
for (f = lf->flags->first ; f ; f = f->next) {
|
|
if (f->id == F_HASSKILL) {
|
|
mvwprintw(mainwin, y, 0, "%c %s (%s%s)",
|
|
ismaxedskill(lf, f->val[0]) ? '*' : '-',
|
|
getskillname(f->val[0]),
|
|
getskilllevelname(f->val[1]),
|
|
ismaxedskill(lf, f->val[0]) ? "/MAX" : "");
|
|
if (downline(&y, h, "SKILLS", NULL, prompt, cmdchars, &ch)) {
|
|
exitnow = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (mode == 'm') {
|
|
char subheading[BUFLEN];
|
|
int lev;
|
|
int anyfound;
|
|
int exitnow = B_FALSE;
|
|
|
|
sprintf(subheading, " %-4s%-25s%-22s%s","Lv","Spell", "School", "Cost");
|
|
|
|
centre(mainwin, y, "SPELLS"); y += 2;
|
|
doheading(mainwin, &y, 0, subheading);
|
|
//if (!isplayer(lf)) {
|
|
// show spells monster can cast using mp
|
|
for (lev = 0; (lev <= 9) && !exitnow; lev++) {
|
|
for (ot = objecttype ; ot && !exitnow ; ot = ot->next) {
|
|
if (ot->obclass->id == OC_SPELL) {
|
|
int thislev;
|
|
thislev = getspelllevel(ot->id);
|
|
if (thislev == lev) {
|
|
f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
|
|
if (!f) {
|
|
f = lfhasknownflagval(lf, F_CANCAST, ot->id, NA, NA, NULL);
|
|
}
|
|
if (f && (f->known)) {
|
|
char spellname[BUFLEN];
|
|
char mpbuf[BUFLEN];
|
|
int power;
|
|
int mpcost;
|
|
if (f->id == F_CANWILL) {
|
|
mpcost = 0;
|
|
|
|
if (f->val[2] == NA) {
|
|
sprintf(mpbuf, "At will");
|
|
} else {
|
|
sprintf(mpbuf, "At will, every %d turn%s",f->val[2],
|
|
(f->val[2] == 1) ? "" : "s");
|
|
}
|
|
} else {
|
|
|
|
mpcost = getmpcost(lf, ot->id);
|
|
if (mpcost) {
|
|
if (hasflag(ot->flags, F_ONGOING)) {
|
|
sprintf(mpbuf, "%d MP ongoing", mpcost);
|
|
} else {
|
|
sprintf(mpbuf, "%d MP", mpcost);
|
|
}
|
|
} else {
|
|
sprintf(mpbuf, "At will");
|
|
}
|
|
}
|
|
|
|
power = getspellpower(lf, ot->id);
|
|
|
|
getspellname(ot->id, lf, spellname);
|
|
sprintf(buf, " %-4d%-25s%-22s%s",thislev, spellname, getschoolname(getspellschool(ot->id)), mpbuf);
|
|
mvwprintw(mainwin, y, 0, "%s\n", buf);
|
|
anyfound = B_TRUE;
|
|
if (downline(&y, h, "SPELLS", subheading, prompt, cmdchars, &ch)) {
|
|
exitnow = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!anyfound) {
|
|
mvwprintw(mainwin, y, 0, "%s cannot cast any spells.", you(lf));
|
|
}
|
|
} else if (mode == 'e') {
|
|
x = 0; // override
|
|
// down a line.
|
|
centre(mainwin, y, "EFFECTS");
|
|
y += 2;
|
|
|
|
|
|
// ready to gain a level?
|
|
if (lfhasflag(lf, F_STATGAINREADY)) {
|
|
mvwprintw(mainwin, y, 0, "%s are ready for training.", you(lf));
|
|
y++;
|
|
}
|
|
if (lf->skillpoints >= 2) {
|
|
mvwprintw(mainwin, y, 0, "%s are ready to learn a new skill.", you(lf));
|
|
y++;
|
|
} else if (lf->skillpoints) {
|
|
mvwprintw(mainwin, y, 0, "%s are ready to enhance %s existing skills.", you(lf),
|
|
isplayer(lf) ? "your" : "its");
|
|
y++;
|
|
}
|
|
|
|
// show intrinsics
|
|
f = lfhasknownflag(lf, F_ATTRSET);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s has been modified.", your(lf), getattrname(f->val[0]));
|
|
y++;
|
|
} else {
|
|
f = lfhasknownflag(lf, F_ATTRMOD);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s has been %s.", your(lf), getattrname(f->val[0]), (f->val[2] > 0) ? "increased" : "decreased");
|
|
y++;
|
|
}
|
|
}
|
|
|
|
f = lfhasknownflag(lf, F_MAGICARMOUR);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s protected by %s %s", you(lf), isplayer(lf) ? "are" : "is",
|
|
needan(f->text) ? "an" : "a", f->text);
|
|
if (isplayer(lf)) {
|
|
wprintw(mainwin, " (+%d AR).",f->val[0]);
|
|
} else {
|
|
wprintw(mainwin, ".");
|
|
}
|
|
y++;
|
|
}
|
|
|
|
f = lfhasknownflag(lf, F_NOPACK);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s cannot carry objects.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasflag(lf, F_OMNIPOTENT);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s are omnipotent.", you(lf));
|
|
y++;
|
|
}
|
|
if (isblind(lf)) {
|
|
mvwprintw(mainwin, y, 0, "%s cannot see.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_CHARMEDBY);
|
|
if (f) {
|
|
lifeform_t *lf2;
|
|
char charmername[BUFLEN];
|
|
lf2 = findlf(NULL, f->val[0]);
|
|
if (lf2) {
|
|
getlfnamea(lf2, charmername);
|
|
} else {
|
|
strcpy(charmername, "something");
|
|
}
|
|
sprintf(buf,"%s %s been charmed by %s.",you(lf), isplayer(lf) ? "have" : "has", charmername);
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_CONTROL);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s can control teleportation and polymorphic effects.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_DETECTAURAS);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s automatically detect blessings or curses.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_DETECTLIFE);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s automatically detect %snearby lifeforms.", you(lf),
|
|
(f->val[1] == B_TRUE) ? "" : "the size of ");
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_DETECTMAGIC);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s automatically detect magical enchantments on objects.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_DETECTMETAL);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s automatically detect nearby metal.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_DETECTOBS);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s automatically detect nearby objects.", you(lf));
|
|
y++;
|
|
}
|
|
|
|
|
|
// extra dam - can have it multiple times
|
|
for (f = lf->flags->first ; f; f = f->next) {
|
|
if (f->id == F_EXTRADAM) {
|
|
int ndice,nsides,bonus;
|
|
char dicebuf[BUFLEN];
|
|
char mmbuf[BUFLEN];
|
|
char damtypebuf[BUFLEN];
|
|
int min = 0,max = 0;
|
|
texttodice(f->text, &ndice,&nsides,&bonus);
|
|
|
|
if ((f->lifetime == FROMOBEQUIP) ||
|
|
(f->lifetime == FROMOBHOLD) ||
|
|
(f->lifetime == FROMOBACTIVATE) ) {
|
|
object_t *obfrom;
|
|
obfrom = findobbyid(lf->pack, f->obfrom);
|
|
if (obfrom) {
|
|
int bonusdam;
|
|
sumflags(obfrom->flags, F_BONUS, &bonusdam, NULL, NULL);
|
|
bonus += bonusdam;
|
|
}
|
|
}
|
|
|
|
if (f->val[0] == NA) {
|
|
strcpy(damtypebuf, "damage");
|
|
} else {
|
|
sprintf(damtypebuf, "%s damage", getdamname(f->val[0]));
|
|
}
|
|
|
|
dicetotext(ndice, nsides, bonus, &min, &max, dicebuf, mmbuf);
|
|
if (strcmp(dicebuf, mmbuf)) {
|
|
mvwprintw(mainwin, y, 0, "%s deal%s %s (%s) extra %s each hit.", you(lf),
|
|
isplayer(lf) ? "" : "s", dicebuf, mmbuf, damtypebuf);
|
|
} else {
|
|
mvwprintw(mainwin, y, 0, "%s deal%s %s extra %s each hit.", you(lf),
|
|
isplayer(lf) ? "" : "s", dicebuf, damtypebuf);
|
|
}
|
|
y++;
|
|
|
|
}
|
|
}
|
|
|
|
f = lfhasknownflag(lf, F_EXTRALUCK);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "Your luck is being boosted.", you(lf));
|
|
y++;
|
|
}
|
|
|
|
f = lfhasknownflag(lf, F_EXTRAMP);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "Your mana pool is being boosted.", you(lf));
|
|
y++;
|
|
}
|
|
|
|
f = lfhasknownflag(lf, F_EXTRAINFO);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_POISONED);
|
|
if (f && (f->known)) {
|
|
sprintf(buf, "%s %s poisoned.", you(lf), isplayer(lf) ? "are" : "is");
|
|
if (lfhasflag(lf, F_EXTRAINFO) || lfhasflag(lf, F_OMNIPOTENT) ||
|
|
(getskill(lf, SK_FIRSTAID) >= PR_ADEPT) ) {
|
|
char buf2[BUFLEN];
|
|
sprintf(buf2, " [max %d turns left]", f->lifetime);
|
|
strcat(buf, buf2);
|
|
}
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
f = lfhasflag(lf, F_NAUSEATED);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s nauseated.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_PACKATTACK);
|
|
if (f && (f->known)) {
|
|
sprintf(buf,"%s deal%s extra damage when in a %s pack.", you(lf), isplayer(lf) ? "" : "s",
|
|
f->text);
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_PHALANX);
|
|
if (f && (f->known)) {
|
|
sprintf(buf,"%s gain%s %d extra armour rating when in a %s pack.", you(lf), isplayer(lf) ? "" : "s",
|
|
f->val[0], f->text);
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_HEAVYBLOW);
|
|
if (f && (f->known)) {
|
|
sprintf(buf,"%s%s attacks knock enemies back.", you(lf), getpossessive(you(lf)));
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_QUICKBITE);
|
|
if (f && (f->known)) {
|
|
sprintf(buf,"%s can bite wounded enemies for extra damage.", you(lf));
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_FREEZINGTOUCH);
|
|
if (f && (f->known)) {
|
|
strcpy(buf,"The next object you touch will turn to solid ice.");
|
|
if (lfhasflag(lf, F_OMNIPOTENT)) {
|
|
char buf2[BUFLEN];
|
|
sprintf(buf2, " [%d uses left]", f->val[0]);
|
|
strcat(buf, buf2);
|
|
}
|
|
mvwprintw(mainwin, y, 0, buf);
|
|
y++;
|
|
}
|
|
f = lfhasflag(lf, F_GRAVBOOSTED);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "Gravity is increased around %s.", you_l(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_DODGES);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s can dodge attacks.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_INVULNERABLE);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s are protected from all physical harm.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasflag(lf, F_MAGSHIELD);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s surrounded by a magnetic shield.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
|
|
f = lfhasflag(lf, F_PAIN);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s in extreme pain, and movement will cause %s damage.", you(lf), isplayer(lf) ? "are" : "is", isplayer(lf) ? "you" : "it");
|
|
y++;
|
|
}
|
|
|
|
f = lfhasflag(lf, F_PARALYZED);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s %s paralyzed.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
f = lfhasflag(lf, F_PHOTOMEM);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s do not forget your surroundings.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_REGENERATES);
|
|
if (f) {
|
|
char regenspeed[BUFLEN];
|
|
if (f->val[0] == 1) {
|
|
strcpy(regenspeed, "");
|
|
} else if (f->val[0] == 2) {
|
|
strcpy(regenspeed, " quickly");
|
|
} else if (f->val[0] == 3) {
|
|
strcpy(regenspeed, " very quickly");
|
|
} else { // >= 4
|
|
strcpy(regenspeed, " extremely quickly");
|
|
}
|
|
mvwprintw(mainwin, y, 0, "%s regenerate%s health%s.", you(lf),isplayer(lf) ? "" : "s", regenspeed);
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_RESISTMAG);
|
|
if (f) {
|
|
int mr;
|
|
char adjective[BUFLEN];
|
|
mr = getmr(lf);
|
|
if (mr <= 5) {
|
|
strcpy(adjective, "slightly");
|
|
} else if (mr <= 10) {
|
|
strcpy(adjective, "quite");
|
|
} else if (mr <= 15) {
|
|
strcpy(adjective, "very");
|
|
} else if (mr <= 20) {
|
|
strcpy(adjective, "extremely");
|
|
} else { // ie. 21 upwards
|
|
strcpy(adjective, "incredibly");
|
|
}
|
|
mvwprintw(mainwin, y, 0, "%s %s %s resistant to magic.", you(lf), isplayer(lf) ? "are" : "is", adjective);
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_WINDSHIELD);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s %s protected from missiles by a cyclonic shield", you(lf), isplayer(lf) ? "are" : "is");
|
|
|
|
if (isplayer(lf)) {
|
|
wprintw(mainwin, " (power %d).",roman(f->val[0]));
|
|
} else {
|
|
wprintw(mainwin, ".");
|
|
}
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_TIRED);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s %s tired.", you(lf), isplayer(lf) ? "are" : "is");
|
|
y++;
|
|
}
|
|
|
|
|
|
f = lfhasflag(lf, F_STABILITY);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s will not fall on slippery ground.", you(lf));
|
|
y++;
|
|
}
|
|
|
|
f = lfhasflag(lf, F_STENCH);
|
|
if (f && (f->known)) {
|
|
mvwprintw(mainwin, y, 0, "%s smell%s terrible.", you(lf), isplayer(lf) ? "" : "s");
|
|
y++;
|
|
}
|
|
|
|
if (!isblind(lf)) {
|
|
f = lfhasknownflag(lf, F_SEEINDARK);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s can see in the dark.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_SEEINVIS);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s can see invisible things.", you(lf));
|
|
y++;
|
|
}
|
|
f = lfhasknownflag(lf, F_XRAYVIS);
|
|
if (f) {
|
|
mvwprintw(mainwin, y, 0, "%s can see through walls.", you(lf));
|
|
y++;
|
|
}
|
|
}
|
|
} else if (mode == 'i') {
|
|
object_t *o;
|
|
cls();
|
|
centre(mainwin, 0, "INVENTORY");
|
|
y = 2;
|
|
if (countobs(lf->pack)) {
|
|
mvwprintw(mainwin, y, 0, "It is carrying:");
|
|
y += 2;
|
|
for (o = lf->pack->first ; o ; o = o->next) {
|
|
getobname(o, buf,o->amt);
|
|
getobextrainfo(o, buf2);
|
|
|
|
mvwprintw(mainwin, y, 0, "%s%s", buf,buf2);
|
|
|
|
if (o->next && downline(&y, h, "INVENTORY", NULL, prompt, cmdchars, &ch)) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
mvwprintw(mainwin, y, 0, "It is not carrying anything.");
|
|
}
|
|
}
|
|
|
|
// wait for key
|
|
centre(mainwin, h-1, prompt);
|
|
if (ch == '\0') {
|
|
ch = getch();
|
|
}
|
|
switch (ch) {
|
|
case 27: // ESC
|
|
done = B_TRUE;
|
|
break;
|
|
case '@':
|
|
mode = ch;
|
|
break;
|
|
case 's':
|
|
case 'm':
|
|
case 'e':
|
|
if (showall) mode = ch;
|
|
break;
|
|
case 'i':
|
|
if (showall && !isplayer(lf)) mode = ch;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} // end while !done
|
|
|
|
drawscreen();
|
|
real_clearmsg(B_TRUE);
|
|
//redraw();
|
|
}
|
|
|
|
void tombstone(lifeform_t *lf) {
|
|
char pname[BUFLEN];
|
|
int y;
|
|
char *p, *dummy;
|
|
|
|
|
|
gamemode = GM_GAMEOVER;
|
|
|
|
getplayernamefull(pname);
|
|
|
|
// clear screen
|
|
cls();
|
|
|
|
y = 1;
|
|
centre(mainwin, y, "R.I.P."); y++;
|
|
//printf("%s\n",lf->name);
|
|
centre(mainwin, y, "%s",pname); y++;
|
|
|
|
p = strtok_r(lf->lastdam,"^", &dummy);
|
|
if (p) {
|
|
if (!strcmp(p, "you")) {
|
|
centre(mainwin, y, "Committed suicide.",p); y++;
|
|
} else {
|
|
centre(mainwin, y, "Killed by %s.",p); y++;
|
|
}
|
|
p = strtok_r(NULL, "^", &dummy);
|
|
while (p) {
|
|
centre(mainwin, y, "(%s)",p); y++;
|
|
p = strtok_r(NULL, "^", &dummy);
|
|
}
|
|
|
|
} else {
|
|
centre(mainwin, y, "Killed by something unknown."); y++;
|
|
}
|
|
|
|
|
|
wrefresh(mainwin);
|
|
// wait for key...
|
|
getch();
|
|
|
|
// close down graphics ready to quit
|
|
// clear windows
|
|
delwin(gamewin);
|
|
delwin(statwin);
|
|
delwin(msgwin);
|
|
// clear screen
|
|
cls();
|
|
// close down curses
|
|
curs_set(1);
|
|
endwin();
|
|
|
|
}
|
|
|
|
|
|
|