- [+] issues with drawing off edge of map.

- [+] should ALWAYS be blank (' ')
- [+] The fire giant forgecaller incinerates you with a flaming
      morningstar.--More-- HP:-115193/139
- [+] barbarian should start with a heavy weapon (to do heavy blow with)
- [+] chang epegasus symbol to Q
- [+] stop sprinting when you open a door, attack, etc
- [+] "the darkmantle vanishes" "the darkmantle appearS" "the
      darkmantle steps though the shadows"
- [+] when generating humanoid monsters on dark levels without
      seeindark, high chance of them having a torch/candle
- [+] all undead should seeindark
- [+] major healing pot doesn't work
- [+] crossbow should do more damage
* [+] aiming skill - determines accuracy of firearms
* [+] change spellbooks to be a single object ("spellbook")
- [+] call wind spell
- [+] make plants boost power of druid spells
- [+] secret iron door showing up as '.'
- [+] table shoudl be misc, not dfeature
* [+] implement sound volume.  1 - xx
* [+] some monsers have f_varlevel. v0 = max.
- [+] implement 'say'
* [+] bandits should demand a bribe (based on their hit dice)
* [+] replace graph paper with cartography skill
- [+] lightning bolt (air, goes THROUGH all lfs until the target one.
      less damage than fireball though.)
- [+] no casting spells while prone
Initial world map implemention.
- [+] maps need flags.
* [+] when in world map, calculate rarity differently based on distance
      from 0,0
* [+] allow walking off edge of forest to new map areas
This commit is contained in:
Rob Pearce 2011-05-19 20:30:58 +00:00
parent 300f1637b3
commit a763c3c4b1
20 changed files with 1979 additions and 416 deletions

25
ai.c
View File

@ -828,6 +828,24 @@ void aiturn(lifeform_t *lf) {
}
}
///////////////////////////////////////////////
// generic pre-movement actions.
///////////////////////////////////////////////
if (!haslos(lf, lf->cell)) {
object_t *lamp;
lamp = hasobwithflagval(lf->pack, F_ACTIVATECONFER, F_PRODUCESLIGHT, NA, NA, NULL);
if (lamp && !isactivated(lamp)) {
if (db) dblog(".oO { it's dark and i have an inactive light source (%s) }", lamp->type->name);
if (!operate(lf, lamp, NULL)) {
if (db) dblog(".oO { successfully turned it on. }");
return;
} else {
if (db) dblog(".oO { failed to turn it on. }");
}
}
}
///////////////////////////////////////////////
// movement
///////////////////////////////////////////////
@ -1581,6 +1599,13 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
if (gothere) {
// cast a spell?
if (cancast(lf, OT_S_CALLWIND, NULL) && haslof(lf->cell, c, LOF_NEED, NULL)) {
if (!castspell(lf, OT_S_CALLWIND, NULL, o, c)) {
// successful
return B_TRUE;
}
}
// start walking towards target cell
if (aigoto(lf, c, MR_OB, o, AI_FOLLOWTIME)) {
return B_FALSE;

View File

@ -125,6 +125,7 @@ int attackcell(lifeform_t *lf, cell_t *c) {
int gotweapon = B_FALSE;
int maxattacks = ALL;
int lastweaponidx = -1;
flag_t *sf;
// anyone there? if so just attack.
if (c->lf) {
@ -166,6 +167,23 @@ int attackcell(lifeform_t *lf, cell_t *c) {
}
}
// stop sprinting
sf = lfhasflag(lf, F_SPRINTING);
if (sf && sf->val[0]) {
killflag(sf);
}
// ai code...
if (lfhasflag(lf, F_DEMANDSBRIBE)) {
if (!isplayer(lf) && (attacktype == AT_LF) && isplayer((lifeform_t *)attacktarget)) {
if (demandbribe(lf)) {
// ie. player paid.
taketime(lf, getactspeed(lf));
return B_FALSE;
}
}
}
// first use our weapon...
nweps = 0;
wep[nweps] = getweapon(lf);
@ -622,7 +640,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
needses(attackverb) ? "es" : "s",
victimname,withwep, nodamstr);
}
noise(lf->cell, lf, "sounds of fighting.", NULL);
noise(lf->cell, lf, 3, "sounds of fighting.", NULL);
}
@ -938,7 +956,7 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
msg("%s %ss %s%s.", attackername,
getattackverb(lf, wep, damtype[i],dam[i],maxhp), obname,withwep);
} else {
noise(lf->cell, NULL, "sounds of fighting.", NULL);
noise(lf->cell, NULL, 3, "sounds of fighting.", NULL);
}
if ((i == 0) && (wep->type->id == OT_FISTS) && hasflag(o->flags, F_HARD)) {
@ -1236,7 +1254,7 @@ int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) {
flag_t *f;
for (f = wep->flags->first ; f ; f = f->next) {
if (f->id == F_ONFIRE) {
if (f->text) {
if (strlen(f->text)) {
*(dam + *ndam) = roll(f->text);
} else {
*(dam + *ndam) = rolldie(2,6);

43
defs.h
View File

@ -39,11 +39,13 @@ enum SKILL {
SK_ARMOUR = 1,
SK_ATHLETICS,
SK_BACKSTAB,
SK_CARTOGRAPHY,
SK_CHANNELING,
SK_COOKING,
SK_FIRSTAID,
SK_LISTEN,
SK_LOCKPICKING,
SK_CHANNELING,
SK_RANGED,
SK_SHIELDS,
SK_SPELLCASTING,
SK_SPOTHIDDEN,
@ -81,7 +83,7 @@ enum SKILL {
SK_SS_TRANSLOCATION,
SK_SS_WILD,
};
#define MAXSKILLS 42
#define MAXSKILLS 44
// proficiency levels
enum SKILLLEVEL {
@ -248,6 +250,9 @@ enum LFCONDITION {
#define MAX_MAPH 20
#define MINCLEARINGRADIUS 2
#define MAXCLEARINGRADIUS 5
//#define MAX_MAPROOMS 10
#define MIN_ROOMH 4
@ -574,6 +579,8 @@ enum RACECLASS {
enum RACE {
R_NONE, R_RANDOM,
R_HUMAN,
// human monsters
R_BANDIT,
// monsters
R_BEHOLDER,
R_BUGBEAR,
@ -794,6 +801,7 @@ enum OBTYPE {
OT_POT_RESTORATION,
OT_POT_RUM,
OT_POT_SANCTUARY,
OT_POT_SLEEP,
OT_POT_SPEED,
OT_POT_WATER,
OT_POT_JUICE,
@ -821,6 +829,9 @@ enum OBTYPE {
OT_SCR_TURNUNDEAD,
OT_SCR_WISH,
// BOOKS
OT_MANUAL,
OT_SPELLBOOK,
/*
OT_MAN_ARMOUR,
OT_MAN_ATHLETICS,
OT_MAN_BACKSTAB,
@ -829,6 +840,7 @@ enum OBTYPE {
OT_MAN_LISTEN,
OT_MAN_LOCKPICKING,
OT_MAN_MAGITEMUSAGE,
OT_MAN_RANGED,
OT_MAN_SHIELDS,
OT_MAN_SPELLCASTING,
OT_MAN_SPOTHIDDEN,
@ -959,6 +971,7 @@ enum OBTYPE {
OT_SB_TELEPORT,
OT_SB_TWIDDLE,
// -- wild can't be learned from books
*/
// spells
// -- allomancy
OT_S_ABSORBMETAL,
@ -1052,6 +1065,7 @@ enum OBTYPE {
// nature
OT_S_BARKSKIN,
OT_S_CALLLIGHTNING,
OT_S_CALLWIND,
OT_S_CALMANIMALS,
OT_S_CALMINGSCENT,
OT_S_CHARMANIMAL,
@ -1062,6 +1076,7 @@ enum OBTYPE {
OT_S_ENDUREELEMENTS,
OT_S_ENTANGLE,
OT_S_HAILSTORM,
OT_S_LIGHTNINGBOLT,
OT_S_LIGHTNINGSTORM,
OT_S_PURIFYFOOD,
OT_S_QUENCH,
@ -1306,6 +1321,7 @@ enum OBTYPE {
OT_HANDAXE,
OT_BATTLEAXE,
OT_GREATAXE,
OT_WARAXE,
// short blades
OT_COMBATKNIFE,
OT_DAGGER,
@ -1423,6 +1439,8 @@ enum POISONTYPE {
enum FLAG {
F_NONE, // dummy flag
// map flags
F_MAPCOORDS, // v0+v1 are x/y coords for this map area
// object flags
F_DEAD, // object will be removed
F_CREATEDBY, // object was made by lf id v0, text=real lfname
@ -1737,11 +1755,17 @@ enum FLAG {
F_LOSLOF, // v0 = whether this spell needs line of sight
// v1 = whether this spell needs line of fire
// MONSTER AI FLAGS
F_DEMANDSBRIBE, // lf will demand gold from the player.
F_VARLEVEL, // lf is generated with random level between
// 1 and its map dificulty/depth.
// if v0 is set, this is the max level.
F_MINION, // v0=lfid of minion
F_XPVAL, // force xp val for killing this lf to v0
// ...OR if applied to an ability...
// monsters with this abil/spell are worth
// v0 more xp.
F_XPMULTIPLY, // multiply xp val for killing this lf by v0
F_NOJOBTEXT, // this lf's name is 'a xxx', not 'a xxx wizard' etc
F_LASTDIR, // this is the last direction we moved.
F_OWNERLASTDIR, // for pets, this it the last dir our owner moved
// when we could see them.
@ -1779,6 +1803,7 @@ enum FLAG {
F_KILLEDBYPLAYER, // did the player kill this lf?
// monster noise flags
F_NOISETEXT, // val0 is a enum NOISETYPE
// val1 is the volume of the noise
// text is "verb^noun"
// eg. "shouts^a shout"
F_SPELLCASTTEXT, // text is announcement for spellcast
@ -2138,6 +2163,7 @@ enum ERROR {
E_CARNIVORE = 51,
E_NOOB = 52,
E_LEVITATING = 53,
E_PRONE = 54,
};
@ -2204,9 +2230,16 @@ typedef struct map_s {
struct lifeform_s *lf,*lastlf;
struct flagpile_s *flags;
struct map_s *next, *prev;
} map_t; //////////////// remember to modify save/load for new props!!
typedef struct glyph_s {
int ch;
int colour;
} glyph_t;
typedef struct cell_s {
map_t *map; // pointer back to map
int x,y; // map coords
@ -2225,16 +2258,12 @@ typedef struct cell_s {
struct lifeform_s *lf;
// known to player?
int known;
struct glyph_s knownglyph;
// FOR CONSTRUCTION
int visited;
} cell_t;
typedef struct glyph_s {
int ch;
int colour;
} glyph_t;
typedef struct celltype_s {
int id; // eg. dungeonfloor, wall, door
struct glyph_s glyph;

View File

@ -8,7 +8,6 @@ objects.c:
remember to have spelllevel
(optional) add a scroll to do the same effect, use F_LINKSPELL
(optional) add a potion to do the same effect
(optional) add a spellbook to learn it
assign AI hint flags so it knows how to cast it
spell.c:

7
doc/volumes.txt Normal file
View File

@ -0,0 +1,7 @@
0 = tiny/mini walking
1 = light footsteps
2 = footsteps, door opening
3 = heavy footsteps, shout, instruments, fighting
4 = extremely loud thumping, war cry
5 = footsteps of SZ_ENORMOUS, explosion
6 = footsteps of SZ_MAX, big explosion

168
io.c
View File

@ -234,6 +234,55 @@ void anim(cell_t *src, cell_t *dst, char ch, int colour) {
needredraw = B_TRUE;
}
void animcells(cell_t *src, cell_t **dst, int ndst, int gradual, char ch, char ch2, int colour) {
glyph_t gl;
int i;
gl.ch = ch;
gl.colour = colour;
// hide cursor
curs_set(0);
for (i = 0; i < ndst; i++) {
int n;
if ((i % 2) == 0) {
gl.ch = ch;
} else {
gl.ch = ch2;
}
if (gradual) {
// update screen each time
updateviewfor(src);
drawlevelfor(player);
}
if (gradual) {
// draw one at a time
for (n = 0; n <= i; n++) {
drawglyph(&gl, dst[n]->x - viewx, dst[n]->y - viewy);
}
} else {
drawglyph(&gl, dst[i]->x - viewx, dst[i]->y - viewy);
}
if (gradual) {
wrefresh(gamewin);
usleep(ANIMDELAY);
}
}
if (!gradual) {
wrefresh(gamewin);
usleep(ANIMDELAY);
}
// show cursor
curs_set(1);
needredraw = B_TRUE;
}
void animradial(cell_t *src, int radius, char ch, int colour) {
glyph_t gl;
int i;
@ -399,7 +448,7 @@ char askchar(char *prompt, char *validchars, char *def, int showchars) {
return ch;
}
cell_t *askcoords(char *prompt, int targettype) {
cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange) {
static int startlf = -1;
int finished = B_FALSE;
int moved = B_FALSE;
@ -721,6 +770,11 @@ cell_t *askcoords(char *prompt, int targettype) {
}
// dont use msg() to avoid 'more's
capitalise(buf);
if (srclf && (maxrange != UNLIMITED)) {
if (getcelldist(srclf->cell, c) > maxrange) {
strcat(buf, " [outofrange]");
}
}
wclear(msgwin);
mvwprintw(msgwin, 0, 0, "%s",buf);
wrefresh(msgwin);
@ -810,6 +864,20 @@ void announceob(enum OBTYPE oid) {
}
*/
void announcearrival(lifeform_t *lf, map_t *newmap) {
if (isplayer(lf)) {
if (newmap->region == RG_WORLDMAP) {
if (lf->cell->map->region == RG_WORLDMAP) {
msg("You arrive in a new area.");
} else {
msg("You arrive at the surface.");
}
} else if (newmap->habitat == H_DUNGEON) {
msg("You arrive at dungeon level %d.", newmap->depth);
}
}
}
int announceflaggain(lifeform_t *lf, flag_t *f) {
int donesomething = B_FALSE;
lifeform_t *lf2;
@ -2018,9 +2086,7 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
centre(mainwin, getmaxy(mainwin)-1, "[Press any key]");
getch();
needredraw = B_TRUE;
clearmsg();
drawscreen();
restoregamewindows();
return NULL;
}
@ -2056,22 +2122,6 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
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);
@ -2162,18 +2212,14 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
*count = o->amt;
}
// display game windows again
needredraw = B_TRUE;
clearmsg();
drawscreen();
restoregamewindows();
return o;
}
} else if ((ch == '-') && (opts & AO_INCLUDENOTHING)) { // select nothing
reason = E_SELNOTHING;
// display game windows again
needredraw = B_TRUE;
clearmsg();
drawscreen();
restoregamewindows();
return NULL;
} else if (isdigit(ch) && count) {
char temp[2];
@ -3329,7 +3375,7 @@ void docomms(void) {
char ch;
flag_t *f;
where = askcoords("Talk to who?", TT_MONSTER);
where = askcoords("Talk to who?", TT_MONSTER, player, UNLIMITED);
if (where && where->lf && cansee(player, where->lf)) {
lf = where->lf;
}
@ -3370,7 +3416,7 @@ void docomms(void) {
char lfname2[BUFLEN];
case 'a':
sprintf(buf, "Tell %s to attack who?",lfname);
c = askcoords(buf, TT_MONSTER);
c = askcoords(buf, TT_MONSTER, player, UNLIMITED);
if (c && c->lf && cansee(player, c->lf)) {
lf2 = c->lf;
@ -3445,7 +3491,7 @@ void docomms(void) {
break;
case 'y':
msg("You shout at %s!", lfname);
noise(where, player, "someone shouting!", NULL);
noise(where, player, 3, "someone shouting!", NULL);
break;
}
taketime(player, getactspeed(player));
@ -3746,6 +3792,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm) {
}
killobpile(op);
restoregamewindows();
}
@ -4288,7 +4335,7 @@ void doexplain(char *question) {
while (!done) {
//sprintf(buf, "Select glyph to explain (ESC to cancel):");
where = askcoords(question, TT_NONE);
where = askcoords(question, TT_NONE, player, UNLIMITED);
if (!where) {
clearmsg();
break;
@ -4668,7 +4715,7 @@ void doselguntarget(void) {
getobname(gun, gunname, 1);
sprintf(buf, "Aim %s where?",gunname);
where = askcoords(buf, TT_MONSTER);
where = askcoords(buf, TT_MONSTER, player, UNLIMITED);
if (where) {
if (where->lf && haslof(player->cell, where, LOF_NEED, NULL)) {
setguntarget(player, where->lf);
@ -4740,7 +4787,7 @@ void dothrow(obpile_t *op) {
// ask where to throw it
sprintf(buf2, "Throw %s where?",buf);
where = askcoords(buf2, TT_MONSTER);
where = askcoords(buf2, TT_MONSTER, player, UNLIMITED);
if (where) {
cell_t *newwhere = NULL;
@ -4913,39 +4960,36 @@ void drawlevelfor(lifeform_t *lf) {
}
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
glyph_t glyph,screenglyph;
int needdraw = B_FALSE;
cell = getcellat(map, x + viewx, y + viewy);
if (cell) {
glyph_t glyph,screenglyph;
int needdraw = B_FALSE;
getcellglyph(&glyph, cell, player);
//drawglyph(&glyph, x - viewx, y - viewy);
} else {
glyph.ch = ' ';
glyph.colour = C_GREY;
}
// only draw if screen char/colour is different
/*
if (cell == player->cell) {
dblog("test");
}
*/
screenglyph.ch = mvwinch(gamewin, y, x) & A_CHARTEXT;
if (screenglyph.ch != glyph.ch) {
// only draw if screen char/colour is different
screenglyph.ch = mvwinch(gamewin, y, x) & A_CHARTEXT;
if (screenglyph.ch != glyph.ch) {
needdraw = B_TRUE;
} else {
screenglyph.colour = PAIR_NUMBER(mvwinch(gamewin, y, x) & A_COLOR);
if (screenglyph.colour != glyph.colour) {
needdraw = B_TRUE;
} else {
screenglyph.colour = PAIR_NUMBER(mvwinch(gamewin, y, x) & A_COLOR);
if (screenglyph.colour != glyph.colour) {
needdraw = B_TRUE;
}
}
if (needdraw) {
drawglyph(&glyph, x, y);
if (db) {
dblog(" drawing char '%lc'/%d at %d,%d (screenglyph was '%lc'/%d)\n\n",
glyph.ch, glyph.ch,
x,y,
screenglyph.ch, screenglyph.ch);
}
ndrawn++;
}
if (needdraw) {
drawglyph(&glyph, x, y);
if (db) {
dblog(" drawing char '%lc'/%d at %d,%d (screenglyph was '%lc'/%d)\n\n",
glyph.ch, glyph.ch,
x,y,
screenglyph.ch, screenglyph.ch);
}
ndrawn++;
}
}
}
@ -7637,6 +7681,10 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s %s missing one eye.", you(lf), is(lf));
y++;
}
if (hasjob(lf, J_DRUID)) {
mvwprintw(mainwin, y, 0, "%s spells are boosted by nearby plants.", isplayer(lf) ? "Your" : "Its");
y++;
}
// flags which aren't really intrinsics
if (lfhasflag(lf, F_VEGETARIAN)) {
@ -8092,7 +8140,11 @@ void tombstone(lifeform_t *lf) {
centre(mainwin, y, "R.I.P."); y++;
//printf("%s\n",lf->name);
centre(mainwin, y, "%s (%ld points)",pname, calcscore(lf)); y++;
centre(mainwin, y, "Died on level %d of the dungeon.", lf->cell->map->depth); y++;
if (lf->cell->map->region == RG_WORLDMAP) {
centre(mainwin, y, "Died in the forest.");
} else {
centre(mainwin, y, "Died on level %d of the dungeon.", lf->cell->map->depth); y++;
}
p = strtok_r(lf->lastdam,"^", &dummy);
if (p) {

4
io.h
View File

@ -5,10 +5,12 @@ void addheading(prompt_t *p, char *text);
void addmsghist(char *text);
void addpromptq(prompt_t *p, char *q);
void anim(cell_t *src, cell_t *dst, char ch, int colour);
void animcells(cell_t *src, cell_t **dst, int ndst, int gradual, char ch, char ch2, int colour);
void animradial(cell_t *src, int radius, char ch, int colour);
void animradialorth(cell_t *src, int radius, char ch, int colour);
void animsky(cell_t *src, char ch, int colour);
//void announceob(enum OBTYPE oid);
void announcearrival(lifeform_t *lf, map_t *newmap);
int announceflaggain(lifeform_t *lf, flag_t *f);
int announceflagloss(lifeform_t *lf, flag_t *f);
int announceobflaggain(object_t *o, flag_t *f);
@ -18,7 +20,7 @@ object_t *askobjectwithflag(obpile_t *op, char *title, int *count, long opts, en
object_t *doaskobject(obpile_t *op, char *title, int *count, int forpickup, int showpoints, long opts, ...);
int askobjectmulti(obpile_t *op, char *prompt, long opts);
char askchar(char *prompt, char *validchars, char *def, int showchars);
cell_t *askcoords(char *prompt, int targettype);
cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange);
char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def);
void centre(WINDOW *win, int y, char *format, ... );
int chartodir(char ch);

565
lf.c

File diff suppressed because it is too large Load Diff

9
lf.h
View File

@ -42,6 +42,7 @@ int countmoney(lifeform_t *lf);
int countnearbyallies(lifeform_t *lf);
int countnearbyhurtallies(lifeform_t *lf);
void debug(lifeform_t *lf);
int demandbribe(lifeform_t *lf);
void die(lifeform_t *lf);
void dumplev(void);
void dumplf(void);
@ -70,6 +71,7 @@ void gainmp(lifeform_t *lf, int amt);
void gainxp(lifeform_t *lf, long amt);
void genxplist(void);
int getactspeed(lifeform_t *lf);
void getadjallies(lifeform_t *lf, lifeform_t **adjally, int *nadjallies);
enum ALLEGIENCE getallegiance(lifeform_t *lf);
int getallouterarmour(lifeform_t *lf, object_t **ob, int *nobs);
object_t *getarmour(lifeform_t *lf, enum BODYPART bp);
@ -103,6 +105,7 @@ job_t *getjob(lifeform_t *lf);
int getlastdir(lifeform_t *lf);
int getlfaccuracy(lifeform_t *lf, object_t *wep);
enum LFCONDITION getlfcondition(lifeform_t *lf);
int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions);
int getnightvisrange(lifeform_t *lf);
char *getlfconditionname(enum LFCONDITION cond);
object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp);
@ -140,9 +143,10 @@ char *getpoisonname(enum POISONTYPE ptype);
int getraceclass(lifeform_t *lf);
int getracerarity(map_t *map, enum RACE rid);
object_t *getrandomarmour(lifeform_t *lf);
//int getrandommonlevel(int depth);
int getrandommonlevel(race_t *r, map_t *m);
race_t *getrandomrace(map_t *map, int forcedepth);
race_t *getreallyrandomrace(void);
enum SKILL getrandomskill(void);
object_t *getrestob(lifeform_t *lf);
enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id);
char *getspeedname(int speed, char *buf);
@ -230,7 +234,7 @@ int modattr(lifeform_t *lf, enum ATTRIB attr, int amt);
void modhunger(lifeform_t *lf, int amt);
float modifybystat(float num, lifeform_t *lf, enum ATTRIB att);
int needstorest(lifeform_t *lf, char *validchars);
void noise(cell_t *c, lifeform_t *noisemaker, char *text, char *seetext);
int noise(cell_t *c, lifeform_t *noisemaker, int volume, char *text, char *seetext);
void outfitlf(lifeform_t *lf);
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground);
void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char *fromwhat);
@ -250,6 +254,7 @@ int rolliq(enum IQBRACKET bracket);
int rollstr(enum STRBRACKET bracket);
int rollstat(lifeform_t *lf, enum ATTRIB attr);
int safetorest(lifeform_t *lf);
int say(lifeform_t *lf, char *text, int volume);
int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus);
int setammo(lifeform_t *lf, object_t *o);
void setattr(lifeform_t *lf, enum ATTRIB attr, int val);

359
log.txt
View File

@ -4,3 +4,362 @@
====== NEW LOGFILE ====
givejob() starting.
xxx
xxx
xxx
xxx
lfid 175 (kobold) spending 20 time
lfid 180 (kobold) spending 20 time
xxx
xxx
lfid 181 (kobold) spending 20 time
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 175 (kobold) spending 20 time
xxx
lfid 180 (kobold) spending 20 time
fireat(): dam = throwdam(3) * speed(2)/2 = 3
lfid 181 (kobold) spending 20 time
fireat(): dam = throwdam(2) * speed(3)/2 = 2
xxx
xxx
xxx
lfid 195 (kobold) spending 20 time
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
lfid 175 (kobold) spending 20 time
xxx
lfid 178 (kobold) spending 20 time
xxx
lfid 180 (kobold) spending 20 time
fireat(): dam = throwdam(3) * speed(2)/2 = 3
xxx
lfid 181 (kobold) spending 20 time
xxx
xxx
xxx
lfid 195 (kobold) spending 20 time
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
lfid 175 (kobold) spending 20 time
xxx
lfid 178 (kobold) spending 20 time
xxx
xxx
xxx
lfid 195 (kobold) spending 15 time
xxx
xxx
lfid 198 (human) spending 20 time
lfid 170 (giant rat) spending 15 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 178 (kobold) spending 15 time
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
lfid 167 (xat) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 40 time
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
lfid 198 (human) spending 20 time
xxx
xxx
xxx
lfid 175 (kobold) spending 20 time
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx

465
map.c
View File

@ -15,6 +15,7 @@
extern map_t *firstmap,*lastmap;
extern celltype_t *firstcelltype, *lastcelltype;
extern objecttype_t *objecttype,*lastobjecttype;
extern int viewx,viewy,vieww,viewh;
extern lifeform_t *player;
@ -46,6 +47,8 @@ cell_t *addcell(map_t *m, int x, int y) {
cell->origlittimer = 0;
cell->writing = NULL;
cell->known = B_FALSE;
cell->knownglyph.ch = ' ';
cell->knownglyph.colour = C_GREY;
return cell;
}
@ -102,6 +105,7 @@ map_t *addmap(void) {
for (i = 0; i < MAXDIR_ORTH; i++) {
a->nextmap[i] = -1;
}
a->flags = addflagpile(NULL, NULL);
a->beingcreated = B_TRUE;
return a;
}
@ -132,23 +136,23 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
if (db) dblog("adding rand lf %s to cell %d,%d",r->name,c->x,c->y);
if (r) {
//lf = addlf(c, r->id, getrandommonlevel(c->map->depth));
lf = addlf(c, r->id, 1);
lf = addlf(c, r->id, getrandommonlevel(r, c->map));
if (lf) {
flag_t *f;
lf->born = B_FALSE;
if (jobok) {
// has a job?
f = hasflag(lf->flags, F_STARTJOB);
if (f) {
if (rnd(1,100) <= f->val[0]) {
givejob(lf, f->val[1]);
for (f = lf->flags->first ; f ; f = f->next) {
// has a job?
if (f->id == F_STARTJOB) {
if (rnd(1,100) <= f->val[0]) {
givejob(lf, f->val[1]);
break;
}
}
}
}
//if (lf->cell->map->beingcreated) {
if (autogen) {
// sometimes start off asleep in new maps
if (!lfhasflag(lf, F_DEAF) && cansleep(lf)) {
@ -188,12 +192,23 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
// did we find one?
if (!adjcell) break;
newlf = addlf(adjcell, r->id, 1);
newlf = addlf(c, r->id, getrandommonlevel(r, adjcell->map));
if (!newlf) {
break;
}
newlf->born = B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
// initial monster shoudl remember its minions
addflag(lf->flags, F_MINION, newlf->id, NA, NA, NULL);
// if master is asleep, minions will also be asleep
if (lfhasflag(lf, F_ASLEEP)) {
addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
}
// minions never have certain flags.
killflagsofid(newlf->flags, F_DEMANDSBRIBE);
newlf->born = B_TRUE;
}
}
@ -220,7 +235,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
newr = findracebyname(f->text);
if (!newr) break;
newlf = addlf(adjcell, newr->id, 1);
newlf = addlf(adjcell, newr->id, getrandommonlevel(newr, adjcell->map));
if (!newlf) break;
newlf->born = B_FALSE;
@ -250,6 +265,31 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
}
}
}
// humanoids on dark levels which can't see will probably have some
// kind of light producing device
if (!islit(c) && !hasflag(lf->flags, F_SEEINDARK) && !hasflag(lf->flags, F_TREMORSENSE)) {
if (lfhasflag(lf, F_HUMANOID)) {
objecttype_t *ot, *poss[MAXCANDIDATES];
int nposs = 0;
// get a random light-producing object
for (ot = objecttype ; ot ; ot = ot->next) {
if (hasflag(ot->flags, F_OPERABLE) &&
hasflagval(ot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, NA, NA, NULL)) {
poss[nposs++] = ot;
}
}
if (nposs > 0) {
ot = poss[rnd(0,nposs-1)];
} else {
ot = NULL;
}
if (ot) {
addob(lf->pack, ot->name);
}
}
}
lf->born = B_TRUE;
} // end if lf
}
@ -257,30 +297,38 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
return lf;
}
void addrandomob(cell_t *c) {
object_t *addrandomob(cell_t *c) {
char buf[BUFLEN];
int db = B_FALSE;
object_t *o = NULL;
if (c->type->solid) {
return;
return NULL;
}
if (getrandomob(c->map, buf)) {
if (db) dblog("adding rand obj %s to cell %d,%d",buf,c->x,c->y);
addob(c->obpile, buf);
o = addob(c->obpile, buf);
}
return o;
}
void addrandomthing(cell_t *c, int obchance) {
int addrandomthing(cell_t *c, int obchance) {
int rv = TT_NONE;
// if there's already someone there,
// then add an object.
if (c->lf || (rnd(1,100) <= obchance)) {
// object
addrandomob(c);
if (addrandomob(c)) {
rv = TT_OBJECT;
}
} else {
// monster
addmonster(c, R_RANDOM, B_TRUE, 1, B_TRUE);
if (addmonster(c, R_RANDOM, B_TRUE, 1, B_TRUE)) {
rv = TT_MONSTER;
}
}
return rv;
}
int cellhaslos(cell_t *c1, cell_t *dest) {
@ -493,28 +541,14 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
break;
default:
if (c->known) {
//drawunviscell(cell, x-viewx, y-viewy);
object_t *o;
// copy from cell
/*
*g = c->type->glyph;
*/
*g = c->knownglyph;
if (g->ch == '.') {
g->ch = ' ';
}
// show staircases...
o = hasobwithflag(c->obpile, F_CLIMBABLE);
if (o) {
*g = *(getglyph(o));
}
// show dungeon features
for (o = c->obpile->first ; o ; o = o->next) {
if (o->type->obclass->id == OC_DFEATURE) {
if (!issecretdoor(o)) {
*g = *(getglyph(o));
}
}
}
}
break;
}
@ -543,18 +577,58 @@ enum CELLTYPE getwallcelltype(enum HABITAT hab) {
return CT_WALL;
}
flag_t *getmapcoords(map_t *m, int *x, int *y) {
flag_t *f;
f = hasflag(m->flags, F_MAPCOORDS);
if (f) {
if (x) *x = f->val[0];
if (y) *y = f->val[1];
return f;
}
if (x) *x = -999;
if (y) *y = -999;
return NULL;
}
int getmapdifficulty(map_t *m) {
int diff = 1;
if (m) {
if (m->region == RG_WORLDMAP) {
int x,y;
// depth is distance from 0,0
getmapcoords(m, &x, &y);
diff = (abs(x) + abs(y))+1;
} else {
diff = m->depth;
}
} else {
diff = rnd(1,MAXDEPTH);
}
return diff;
}
object_t *gettopobject(cell_t *where) {
object_t *o;
object_t *o,*oo = NULL;
enum LFSIZE largest = SZ_MINI;
int c;
// draw impassable objects first...
o = hasobwithflag(where->obpile, F_IMPASSABLE);
if (o) {
// get largest known impassable object first
for (o = where->obpile->first ; o ; o = o->next) {
flag_t *f;
// ignore hidden traps, but not secret doors
if (hasflag(o->flags, F_SECRET) && !isdoor(o, NULL)) {
} else {
return o;
f = hasflag(o->flags, F_IMPASSABLE);
if (f && (f->val[0] > largest)) {
largest = f->val[0];
oo = o;
}
}
}
if (oo) {
return oo;
}
// otherwise draw highest object in sort order
c = 0;
@ -1074,14 +1148,26 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
if (db) dblog("--> Will add %d objects to room %d (of %d)",numobs,i,numrooms);
for (n = 0 ; n < numobs; n++) {
int ntries = 0;
int nmonsters = 0;
cell_t *c;
done = B_FALSE;
while (!done) {
c = getrandomroomcell(map, i);
// if nothing there
if (c && isempty(c) && !countobs(c->obpile)) {
// slightly more chance of objects in rooms
addrandomthing(c,60);
int obchance;
// limit # monster per room to depth+1
if (nmonsters >= (depth+1)) {
obchance = 100;
} else {
// slightly more chance of objects in rooms
obchance = getobchance(map->habitat) + 10;
}
if (addrandomthing(c,obchance) == TT_MONSTER) {
nmonsters++;
}
done = B_TRUE;
} else {
ntries++;
@ -1106,6 +1192,8 @@ void createforest(map_t *map, int depth, map_t *parentmap, int exitdir) {
int ntrees;
int density;
cell_t *c;
char buf[BUFLEN];
int nclearings;
//object_t *o;
// what kind of cells will 'empty' ones be?
@ -1118,7 +1206,6 @@ void createforest(map_t *map, int depth, map_t *parentmap, int exitdir) {
}
}
// determine density
density = rnd(40,70);
// add a plant to density percent of cells
@ -1128,7 +1215,44 @@ void createforest(map_t *map, int depth, map_t *parentmap, int exitdir) {
while (c->lf) {
c = getrandomcell(map);
}
addob(c->obpile, "tree");
switch (rnd(0,1)) {
default: case 0: strcpy(buf, "tree"); break;
case 1: strcpy(buf, "shrub"); break;
}
addob(c->obpile, buf);
}
// clearings
nclearings = rnd(0,5);
for (i = 0; i < nclearings; i++) {
int w;
c = getrandomcell(map);
w = rnd(MINCLEARINGRADIUS,MAXCLEARINGRADIUS);
for (y = c->y - w; y <= c->y + w; y++) {
for (x = c->x - w; x <= c->x + w; x++) {
cell_t *newc;
int dist = 999;
newc = getcellat(map, x, y);
if (newc) {
dist = getcelldistorth(newc, c);
if (dist <= w) {
int dirtchance;
// kill all obs here
while (newc->obpile->first) killob(newc->obpile->first);
// change it into dirt.
// ie. at centre (dist=0) dirt chance is 100%
// ie. at max distance, dirt chance is 30%
dirtchance = 100 - (((float)dist / (float)w) * 70);
if (rnd(1,100) <= dirtchance) {
setcelltype(newc, CT_DIRT);
}
}
}
}
}
}
// add monsters
@ -1143,8 +1267,10 @@ void createforest(map_t *map, int depth, map_t *parentmap, int exitdir) {
*/
void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap, int exitdir) {
lifeform_t *lf;
map_t *m;
char buf[BUFLEN];
int i,x,y;
int firstworldmap = B_FALSE;
// determine habitat?
if (habitat == AUTO) {
if (depth > 0) {
@ -1154,6 +1280,21 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
}
}
if (region == RG_WORLDMAP) {
int found = B_FALSE;
for (m = firstmap ; m ; m = m->next) {
if ((m != map) && (m->region == RG_WORLDMAP)) {
found = B_TRUE;
break;
}
}
if (!found) {
firstworldmap = B_TRUE;
}
}
map->beingcreated = B_TRUE;
map->depth = depth;
@ -1169,7 +1310,7 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
map->nextmap[i] = -1;
}
// look for adjacent maps in this region
// look for adjacent maps above/below this one
for (i = depth-1; i <= depth+1; i += 2) {
map_t *othermap;
othermap = findregionmap(map->region, i);
@ -1204,6 +1345,62 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
map->seed = rand() % 65535;
srand(map->seed);
// set map coords
if (firstworldmap) {
addflag(map->flags, F_MAPCOORDS, 0, 0, NA, NULL);
} else {
// set mapcoords if not already done.
if (!hasflag(map->flags, F_MAPCOORDS)) {
x = -999;
y = -999;
if (parentmap) {
getmapcoords(parentmap, &x, &y);
assert((x != -999) && (y != -999));
switch (exitdir) {
case D_N:
y--;
break;
case D_E:
x++;
break;
case D_S:
y++;
break;
case D_W:
x--;
break;
default:
// no change
break;
}
addflag(map->flags, F_MAPCOORDS, x, y, NA, NULL);
} else {
// set it based on something else...
if (region == RG_FIRSTDUNGEON) {
x = 0;
y = 0;
} else {
// find another map of this region and set it.
for (m = firstmap ; m ; m = m->next) {
if ((m != map) && (m->region == region)) {
flag_t *ff;
ff = hasflag(m->flags, F_MAPCOORDS);
if (ff) {
x = ff->val[0];
y = ff->val[1];
break;
}
}
}
}
}
assert(x != -999);
assert(y != -999);
addflag(map->flags, F_MAPCOORDS, x, y, NA, NULL);
}
}
// build it...
if (habitat == H_DUNGEON) {
createdungeon(map, depth, parentmap, exitdir);
@ -1216,36 +1413,28 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
addhomeobs(lf);
}
// if this is the first world map, add stairs to the dungeon
if (region == RG_WORLDMAP) {
map_t *m;
int found = B_FALSE;
if (firstworldmap) {
// ie. this is the first forest map
map_t *firstdungeon;
for (m = firstmap ; m ; m = m->next) {
if ((m != map) && (m->region == 0)) {
found = B_TRUE;
break;
}
}
if (!found) {
map_t *firstdungeon;
// link to first dungeon map
firstdungeon = findregionmap(RG_FIRSTDUNGEON, 1);
assert(firstdungeon);
map->nextmap[D_DOWN] = firstdungeon->id;
// add stairs going down to dungeon
for (i = 0; i < 3; i++) {
cell_t *c;
object_t *o;
c = NULL;
while (!c || !cellwalkable(NULL, c, NULL)) {
c = getrandomcell(map);
}
o = addob(c->obpile, "staircase going down");
linkstairs(o);
// link to first dungeon map
firstdungeon = findregionmap(RG_FIRSTDUNGEON, 1);
assert(firstdungeon);
map->nextmap[D_DOWN] = firstdungeon->id;
// add stairs going down to dungeon
for (i = 0; i < 3; i++) {
cell_t *c;
object_t *o;
c = NULL;
while (!c || !cellwalkable(NULL, c, NULL)) {
c = getrandomcell(map);
}
o = addob(c->obpile, "staircase going down");
linkstairs(o);
}
}
@ -1275,6 +1464,29 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
}
}
// look for adjacent maps
getmapcoords(map, &x, &y);
assert(x != -999);
assert(y != -999);
for (m = firstmap ; m ; m = m->next) {
if ((m != map) && (m->region == map->region)) {
int thisx,thisy;
getmapcoords(m, &thisx, &thisy);
if (map->nextmap[D_N] == -1) {
if (thisy == (y - 1)) map->nextmap[D_N] = m->id;
}
if (map->nextmap[D_E] == -1) {
if (thisx == (x + 1)) map->nextmap[D_E] = m->id;
}
if (map->nextmap[D_S] == -1) {
if (thisy == (y + 1)) map->nextmap[D_S] = m->id;
}
if (map->nextmap[D_W] == -1) {
if (thisx == (x - 1)) map->nextmap[D_W] = m->id;
}
}
}
map->beingcreated = B_FALSE;
}
@ -1522,7 +1734,7 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int
msg("You see %s explosion!", (range > 0) ? "a huge" : "an");
}
} else {
noise(c, NULL, "an explosion!", NULL);
noise(c, NULL, (range > 0) ? 6 : 5, "an explosion!", NULL);
}
for (y = c->y - range ; y <= c->y + range ; y++) {
@ -1615,6 +1827,63 @@ map_t *findmapofdepth(int depth) {
return NULL;
}
cell_t *findmapentrypoint(map_t *m, int side, lifeform_t *lf) {
int x,y,xinc,yinc;
cell_t *selection = NULL;
cell_t *bestcell = NULL;
int closest = 999;
switch (side) {
case D_N:
x = 0;
y = 0;
xinc = 1;
yinc = 0;
bestcell = getcellat(m, lf->cell->x, 0);
break;
case D_E:
x = m->w-1;
y = 0;
xinc = 0;
yinc = 1;
bestcell = getcellat(m, m->w - 1, lf->cell->y);
break;
case D_S:
x = 0;
y = m->h - 1;
xinc = 1;
yinc = 0;
bestcell = getcellat(m, lf->cell->x, m->h - 1);
break;
case D_W:
x = 0;
y = 0;
xinc = 0;
yinc = 1;
bestcell = getcellat(m, 0, lf->cell->y);
break;
}
for (;(x < m->w) && (y < m->h);) {
cell_t *c;
// check cell
c = getcellat(m, x, y);
if (c && cellwalkable(lf, c, NULL)) {
int dist;
dist = getcelldist(c, bestcell);
if (dist < closest) {
selection = c;
closest = dist;
}
}
// go to next one
x += xinc;
y += yinc;
}
return selection;
}
// find the object with id 'id' in map 'm'
object_t *findobidinmap(map_t *m, long id) {
cell_t *c;
@ -1844,7 +2113,7 @@ int getthingchance(int habitat) {
case H_DUNGEON:
return 3;
case H_FOREST:
return 5;
return 3;
}
// default of no objects
return 0;
@ -2503,6 +2772,52 @@ void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong) {
}
}
void setcellknown(cell_t *cell, int forcelev) {
enum SKILLLEVEL slev;
object_t *o;
if (forcelev > 0) {
slev = forcelev;
} else {
slev = getskill(player, SK_CARTOGRAPHY);
}
// photographic memory counts as novice level
if ((slev == PR_INEPT) && lfhasflag(player, F_PHOTOMEM)) {
slev = PR_NOVICE;
}
if (slev >= PR_NOVICE) {
cell->known = B_TRUE;
// default to remembering the cell's glyph
cell->knownglyph = cell->type->glyph;
// high cartography skill lets us remember certain objects...
if (slev >= PR_EXPERT) {
o = gettopobject(cell);
if (o) {
cell->knownglyph = *(getglyph(o));
}
}
if (slev >= PR_ADEPT) {
for (o = cell->obpile->first ; o ; o = o->next) {
if (o->type->obclass->id == OC_DFEATURE) {
if (!issecretdoor(o)) {
cell->knownglyph = *(getglyph(o));
}
}
}
}
if (slev >= PR_BEGINNER) {
o = hasobwithflag(cell->obpile, F_CLIMBABLE);
if (o) {
cell->knownglyph = *(getglyph(o));
}
}
}
//getcellglyph(&(cell->knownglyph), cell, player);
}
void setcelltype(cell_t *cell, int id) {
assert(cell);
cell->type = findcelltype(id);
@ -2528,9 +2843,7 @@ void updateknowncells(void) {
if (cell) {
//if ((player->cell == cell) || haslos(player, cell)) {
if (haslos(player, cell)) {
if (!cell->known) {
cell->known = B_TRUE;
}
setcellknown(cell, B_FALSE);
if (cell->lf && lfhasflag(cell->lf, F_UNDEAD)) {
seenundead = B_TRUE;
}

8
map.h
View File

@ -4,8 +4,8 @@ cell_t *addcell(map_t *map, int x, int y);
void addhomeobs(lifeform_t *lf);
map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen);
void addrandomob(cell_t *c);
void addrandomthing(cell_t *c, int obchance);
object_t *addrandomob(cell_t *c);
int addrandomthing(cell_t *c, int obchance);
int cellhaslos(cell_t *c1, cell_t *dest);
cell_t *getcellat(map_t *map, int x, int y);
int getcelldist(cell_t *src, cell_t *dst);
@ -13,6 +13,8 @@ int getcelldistorth(cell_t *src, cell_t *dst);
void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer);
enum CELLTYPE getemptycelltype(enum HABITAT hab);
enum CELLTYPE getwallcelltype(enum HABITAT hab);
flag_t *getmapcoords(map_t *m, int *x, int *y);
int getmapdifficulty(map_t *m);
object_t *gettopobject(cell_t *where);
void calclight(map_t *map);
int calcroompos(map_t *map, int w, int h, int *bx, int *by);
@ -31,6 +33,7 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int
celltype_t *findcelltype(enum CELLTYPE cid);
map_t *findmap(int mid);
map_t *findmapofdepth(int depth);
cell_t *findmapentrypoint(map_t *m, int side, lifeform_t *lf);
object_t *findobidinmap(map_t *m, long id);
cell_t *findobinmap(map_t *m, enum OBCLASS oid);
map_t *findregionmap(int region, int depth);
@ -68,5 +71,6 @@ int linkstairs(object_t *o);
void makedoor(cell_t *cell);
void makelit(cell_t *c, enum LIGHTLEV how, int howlong);
void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong);
void setcellknown(cell_t *cell, int forcelev);
void setcelltype(cell_t *cell, int id);
void updateknowncells(void);

162
move.c
View File

@ -1,4 +1,5 @@
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -24,7 +25,7 @@ extern enum GAMEMODE gamemode;
extern enum ERROR reason;
extern void *rdata;
extern WINDOW *gamewin;
extern WINDOW *gamewin, *msgwin;
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) {
if (isplayer(lf)) {
@ -544,8 +545,15 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
if (reason != E_OK) {
// failed to move
switch (reason) {
case E_WALLINWAY:
case E_OFFMAP:
if (lf->cell->map->region == RG_WORLDMAP) {
if (!walkoffmap(lf, dir, B_FALSE)) {
// successful
break;
}
}
// fall through
case E_WALLINWAY:
if (seen) msg("%s slam%s into a wall!",lfname,isplayer(lf) ? "" : "s");
losehp(lf, rnd(1,6), DT_BASH, pusher, "slamming into a wall");
// stop moving
@ -830,29 +838,32 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// haslos() code to handle looking along walls
// instead.
// if you walked into a new fully lit room, reveal it
if ((postroom > 0) && (postroom != preroom)) {
cell_t *c[MAX_MAPW*MAX_MAPH];
int ncells;
int i,alllit = B_TRUE,allknown = B_TRUE;
// is the whole room lit?
getroomcells(lf->cell->map, postroom, c, &ncells);
for (i = 0; i < ncells; i++) {
if (!islit(c[i])) {
alllit = B_FALSE;
}
if (!c[i]->known) {
allknown = B_FALSE;
}
}
if (getskill(lf, SK_CARTOGRAPHY) >= PR_NOVICE) {
if ((postroom > 0) && (postroom != preroom)) {
cell_t *c[MAX_MAPW*MAX_MAPH];
int ncells;
int i,alllit = B_TRUE,allknown = B_TRUE;
if (alllit && !allknown) {
// make the all known
// is the whole room lit?
getroomcells(lf->cell->map, postroom, c, &ncells);
for (i = 0; i < ncells; i++) {
c[i]->known = B_TRUE;
if (!islit(c[i])) {
alllit = B_FALSE;
}
if (!c[i]->known) {
allknown = B_FALSE;
}
}
}
if (alllit && !allknown) {
// make the all known
for (i = 0; i < ncells; i++) {
setcellknown(c[i], B_FALSE);
}
}
}
}
}
@ -1116,8 +1127,15 @@ int opendoor(lifeform_t *lf, object_t *o) {
return B_TRUE;
} else {
if (lf) {
flag_t *sf;
taketime(lf, getactspeed(lf));
touch(lf, o);
// stop sprinting
sf = lfhasflag(lf, F_SPRINTING);
if (sf && sf->val[0]) {
killflag(sf);
}
}
// locked?
@ -1180,7 +1198,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
// checking if we have LOS to the lifeform making
// sound, but in this case it's the door making
// the sound, not the lf.
noise(where, NULL, "a door opening.", NULL);
noise(where, NULL, 2, "a door opening.", NULL);
}
if (player && haslos(player, where)) {
needredraw = B_TRUE;
@ -1657,11 +1675,9 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
reason = errcode;
switch (errcode) {
case E_OFFMAP:
if (isplayer(lf)) {
msg("You can't go any further in that direction.");
} else if (cansee(player, lf)) {
getlfname(lf, buf);
msg("%s %ss around randomly.", buf, getmoveverb(lf));
if (lf->cell->map->region == RG_WORLDMAP) {
// we are allowed to walk off the edge
walkoffmap(lf, dir, B_TRUE);
}
break;
case E_WALLINWAY:
@ -1679,7 +1695,8 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
sprintf(buf, "%sing into a wall", getmoveverb(lf));
losehp(lf, 1, DT_BASH, NULL, buf);
// we now know there is a wall there.
cell->known = B_TRUE;
setcellknown(cell, B_FALSE);
if (onpurpose) taketime(lf, getmovespeed(lf));
}
} else {
@ -1701,7 +1718,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
opendoor(lf, inway);
} else {
msg("Ouch! You %s into a door.", getmoveverb(lf));
cell->known = B_TRUE;
setcellknown(cell, B_FALSE);
sprintf(buf, "%sing into a door", getmoveverb(lf));
losehp(lf, 1, DT_BASH, NULL, buf);
if (onpurpose) taketime(lf, getmovespeed(lf));
@ -1829,6 +1846,95 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
return B_FALSE;
}
int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
map_t *adjmap = NULL, *thismap;
cell_t *dst = NULL;
lifeform_t *adjally[8];
int nadjallies = 0;
int n;
// announce
if (isplayer(lf)) {
char dirname[BUFLEN];
curs_set(1);
strcpy(dirname, getdirname(dir));
dirname[0] = tolower(dirname[0]);
msg("You %s to the %s...", getmoveverb(lf), getdirname(dir));
// move cursor to msgwindow while we create the new level...
wrefresh(msgwin);
} else if (cansee(player, lf)) {
char dirname[BUFLEN];
char lfname[BUFLEN];
getlfname(lf, lfname);
curs_set(1);
strcpy(dirname, getdirname(dir));
dirname[0] = tolower(dirname[0]);
msg("%s %s to the %s...", lfname, getmoveverbother(lf), getdirname(dir));
wrefresh(msgwin);
}
// is there a map in that direction ?
thismap = lf->cell->map;
adjmap = findmap(lf->cell->map->nextmap[dir]);
if (!adjmap) {
// make one
adjmap = addmap();
createmap(adjmap, thismap->depth, thismap->region, AUTO, thismap, dir);
}
if (adjmap) {
// find an empty cell in the next map
dst = findmapentrypoint(adjmap, diropposite(dir), lf);
}
if (!dst) {
// failed
if (isplayer(lf)) {
msg("Your path seems to be blocked.");
}
return B_TRUE;
}
if (onpurpose) {
// get list of adjacent allies
if (isplayer(lf)) {
getadjallies(lf, adjally, &nadjallies);
}
}
// announce
announcearrival(lf, dst->map);
// move there
moveto(lf, dst, onpurpose, B_TRUE);
if (onpurpose) {
taketime(lf, getmovespeed(lf));
}
// move adjacent allies
if (onpurpose) {
for (n = 0; n < nadjallies; n++) {
cell_t *c;
c = getrandomadjcell(dst, WE_WALKABLE, B_ALLOWEXPAND);
if (c) {
if (!initiatemove(adjally[n], NULL, NULL)) {
movelf(adjally[n], c);
taketime(adjally[n], getmovespeed(adjally[n]));
}
}
}
}
if (isplayer(lf)) {
statdirty = B_TRUE;
needredraw = B_TRUE;
calclight(player->cell->map);
precalclos(lf);
drawscreen();
}
return B_FALSE;
}
int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
cell_t *cell;

1
move.h
View File

@ -25,4 +25,5 @@ void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int onpurpose);
int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke);
int trymove(lifeform_t *lf, int dir, int onpurpose);
int tryrun(lifeform_t *lf, int dir);
int walkoffmap(lifeform_t *lf, int dir, int onpurpose);
int willmove(lifeform_t *lf, int dir, enum ERROR *error);

14
nexus.c
View File

@ -264,7 +264,6 @@ int main(int argc, char **argv) {
// start game - this will cause debug messages to now
// go to the log file instead of stdout.
gamemode = GM_GAMESTARTED;
timeleft = 0; // reset game timer
// calculate initial light
@ -287,6 +286,13 @@ int main(int argc, char **argv) {
needredraw = B_TRUE;
statdirty = B_TRUE;
// start game
gamemode = GM_GAMESTARTED;
// redo light and player los
calclight(player->cell->map);
precalclos(player);
// show level
drawscreen();
@ -541,7 +547,8 @@ void donextturn(map_t *map) {
} else {
if (isplayer(who)) {
if (++who->turnsskipped >= 10) {
msg("Time passes...");
//msg("Time passes...");
msg(".");
who->turnsskipped = 0;
}
}
@ -557,7 +564,8 @@ void donextturn(map_t *map) {
if (isimmobile(who)) {
if (isplayer(who)) {
if (++who->turnsskipped >= 10) {
msg("Time passes...");
//msg("Time passes...");
msg(".");
who->turnsskipped = 0;
}
}

281
objects.c
View File

@ -404,6 +404,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
obmod_t *wantom[MAXOBMODS];
int nom = 0;
int n;
int bookcontents = -1;
localname = strdup(name);
@ -530,6 +531,28 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
corpserace = findracebyname(racename);
ot = findot(OT_HEAD);
} else if (strstr(p, "spellbook of ")) {
char *pp;
pp = p + 13;
if (*pp) {
objecttype_t *spelltype = NULL;
spelltype = findspelln(pp);
if (spelltype) {
bookcontents = spelltype->id;
}
}
ot = findot(OT_SPELLBOOK);
} else if (strstr(p, "manual of ")) {
char *pp;
pp = p + 10;
if (*pp) {
skill_t *sk;
sk = findskillbyname(pp);
if (sk) {
bookcontents = sk->id;
}
}
ot = findot(OT_MANUAL);
} else {
// make sure we can find the requested object type
if (db) dblog("DB: Looking for object name '%s'", p );
@ -564,7 +587,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
canstack = B_FALSE;
}
// special checks for unique objects
if (hasflag(ot->flags, F_UNIQUE)) {
// does this unique ob already exist?
@ -579,6 +601,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
if (db) dblog("DB: '%s' -> adding %d x %s",name, howmany, ot->name);
for (i = 0; i < howmany; i++) {
int added = B_FALSE;
if (canstack) {
@ -694,6 +717,52 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
}
}
// fill in book types
if (o && (o->type->obclass->id == OC_BOOK)) {
hiddenname_t *hn,*selhn = NULL;
int numhiddennames;
int n,sel;
if (bookcontents == -1) {
if (o->type->id == OT_SPELLBOOK) {
bookcontents = getrandomspell();
while (!schoolappearsinbooks(getspellschool(bookcontents))) {
bookcontents = getrandomspell();
}
} else { // ie. manual
bookcontents = getrandomskill();
}
}
// link
if (o->type->id == OT_SPELLBOOK) {
addflag(o->flags, F_LINKSPELL, bookcontents, NA, NA, NULL);
} else {
addflag(o->flags, F_MANUALOF, bookcontents, NA, NA, NULL);
}
// count hidden names
numhiddennames = 0;
for (hn = firsthiddenname ; hn ; hn = hn->next) {
if (hn->obclass == o->type->obclass->id) {
numhiddennames++;
}
}
// assign hidden name
sel = rnd(0,numhiddennames-1);
n = 0;
for (hn = firsthiddenname ; hn ; hn = hn->next) {
if (hn->obclass == o->type->obclass->id) {
if (n == sel) {
selhn = hn;
break;
}
n++;
}
}
addflag(o->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, selhn->text);
}
// other special changes we need to make based on what was
// asked for
@ -3134,6 +3203,28 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
strcpy(basename,gethiddenname(o));
}
if (o->type->obclass->id == OC_BOOK) {
if (!strcmp(basename, o->type->name)) {
if (o->type->id == OT_SPELLBOOK) {
f = hasflag(o->flags, F_LINKSPELL);
if (f) {
objecttype_t *st;
st = findot(f->val[0]);
strcat(basename, " of ");
strcat(basename, st->name);
}
} else {
f = hasflag(o->flags, F_MANUALOF);
if (f) {
skill_t *sk;
sk = findskill(f->val[0]);
strcat(basename, " of ");
strcat(basename, sk->name);
}
}
}
}
if (!showall) {
if ((gamemode == GM_GAMESTARTED) && adjustforblind && !haslos(player, where) ) {
// override with obclass names
@ -3600,10 +3691,8 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
if (forcedepth != NA) {
depth = forcedepth;
} else if (map) {
depth = map->depth;
} else {
depth = rnd(1,MAXDEPTH);
depth = getmapdifficulty(map);
}
getrarity(depth, &raritymin, &raritymax, RARITYVARIANCEOB, B_TRUE);
@ -3811,7 +3900,8 @@ char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf) {
}
char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod) {
return real_getrandomob(map, buf, RO_OBCLASS, cid, map->depth + depthmod);
//return real_getrandomob(map, buf, RO_OBCLASS, cid, map->depth + depthmod);
return real_getrandomob(map, buf, RO_OBCLASS, cid, getmapdifficulty(map) + depthmod);
}
int getobrarity(object_t *o) {
@ -4090,7 +4180,7 @@ object_t *hasobid(obpile_t *op, int id) {
// fully identify a single object.
void identify(object_t *o) {
flag_t *f;
if (!isknown(o)) {
if (!isknown(o) && (o->type->obclass->id != OC_BOOK)) {
makeknown(o->type->id);
}
addflag(o->flags, F_IDENTIFIED, B_TRUE, -1, -1, NULL);
@ -4151,7 +4241,6 @@ void ignite(object_t *o) {
void initobjects(void) {
//int ch;
int i,n;
objecttype_t *ot;
// generate hidden names
for (n = 0; strlen(colour[n].name); n++) {
@ -4503,18 +4592,6 @@ void initobjects(void) {
addflag(lastot->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL);
addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL);
addot(OT_WOODENTABLE, "wooden table", "A waist-height wooden table.", MT_WOOD, 25, OC_DFEATURE);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "\\");
addflag(lastot->flags, F_IMPASSABLE, SZ_HUMAN, NA, NA, NULL);
addflag(lastot->flags, F_CRUSHABLE, SZ_LARGE, NA, NA, NULL);
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
//addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL);
addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 80, OC_ROCK);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, "");
@ -4564,13 +4641,13 @@ void initobjects(void) {
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_MISC);
addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_DFEATURE);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, "");
addflag(lastot->flags, F_GLYPH, C_WHITE, NA, NA, "_");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_MISC);
addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_DFEATURE);
addflag(lastot->flags, F_GLYPH, C_BOLDGREEN, NA, NA, "&");
addflag(lastot->flags, F_CLIMBABLE, D_IN, NA, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -4579,7 +4656,7 @@ void initobjects(void) {
// traps
addot(OT_TRAPTRIP, "tripwire", "A thin wire at ankle height.", MT_NOTHING, 0, OC_MISC);
addflag(lastot->flags, F_TRAP, 10, B_FALSE, 20, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -4587,7 +4664,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SECRET, 25, NA, NA, NULL);
addot(OT_TRAPROCK, "falling rock trap", "A pressure plate which causes heavy rocks to drop from the ceiling.", MT_NOTHING, 0, OC_MISC);
addflag(lastot->flags, F_TRAP, 20, B_TRUE, 22, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -4596,7 +4673,7 @@ void initobjects(void) {
addot(OT_TRAPARROW, "arrow trap", "A pressure plate which causes arrows to shoot at you.", MT_NOTHING, 0, OC_MISC);
addflag(lastot->flags, F_TRAP, 25, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 76, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 76, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -4605,7 +4682,7 @@ void initobjects(void) {
addot(OT_TRAPARROWP, "poison arrow trap", "A pressure plate which causes poisoned arrows to shoot at you.", MT_NOTHING, 0, OC_MISC);
addflag(lastot->flags, F_TRAP, 25, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 69, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 69, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -4614,7 +4691,7 @@ void initobjects(void) {
addot(OT_TRAPGAS, "gas trap", "A pressure plate which releases poisonous gas.", MT_NOTHING, 0, OC_MISC);
addflag(lastot->flags, F_TRAP, 27, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 69, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 69, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -4623,7 +4700,7 @@ void initobjects(void) {
addot(OT_TRAPFIRE, "fire trap", "A pressure plate which fires a pillar of flame.", MT_NOTHING, 0, OC_MISC);
addflag(lastot->flags, F_TRAP, 30, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 59, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 59, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -4632,7 +4709,8 @@ void initobjects(void) {
addot(OT_TRAPMINE, "landmine trap", "A buried, pressure-sensitive explosive device.", MT_NOTHING, 0, OC_MISC);
addflag(lastot->flags, F_TRAP, 30, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 50, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 20, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -4707,6 +4785,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, "");
addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "%");
addflag(lastot->flags, F_IMPASSABLE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastot->flags, F_REDUCEMOVEMENT, 1, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
@ -4831,6 +4910,9 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, NA, NULL);
addot(OT_POT_RESTORATION, "potion of restoration", "Restores lost abilities to the drinker.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addot(OT_POT_SLEEP, "potion of sleep", "Puts the drinker into a deep sleep.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addot(OT_POT_SPEED, "potion of haste", "Temporarily increasees the drinker's speed.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
@ -5144,6 +5226,11 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_ADJSELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_CALLWIND, "call wind", "Conjures a friendly wind, carrying a single object to the caster's hands.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
// l2
addot(OT_S_GUSTOFWIND, "gust of wind", "Causes a gust of wind to blow the target's objects away.", MT_NOTHING, 0, OC_SPELL);
@ -5332,6 +5419,11 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_LIGHTNINGBOLT, "lightning bolt", "Fires electricity through multiple enemies.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL);
addot(OT_S_ENDUREELEMENTS, "endure elements", "Provides resistance to fire and cold.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
@ -5521,7 +5613,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_LIGHT, "light", "Creates a temporary light source centred on the caster.\nAt Power III, you can control where the light appears.\nAt Power VIII, the light becomes permenant.", MT_NOTHING, 0, OC_SPELL);
addot(OT_S_LIGHT, "light area", "Creates a temporary light source centred on the caster.\nAt Power III, you can control where the light appears.\nAt Power VIII, the light becomes permenant.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
@ -5738,7 +5830,12 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
// manuals
// books
addot(OT_MANUAL, "manual", "Teaches you one level of its subject matter.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 48, NA, NULL);
addot(OT_SPELLBOOK, "spellbook", "Teaches you the spell contained within.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
/*
addot(OT_MAN_ARMOUR, "manual of armour", "Teaches you the skill 'armour'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_ARMOUR, NA, NA, NULL);
addot(OT_MAN_ATHLETICS, "manual of athletics", "Teaches you the skill 'athletics'.", MT_PAPER, 3, OC_BOOK);
@ -5755,6 +5852,8 @@ void initobjects(void) {
addflag(lastot->flags, F_MANUALOF, SK_LOCKPICKING, NA, NA, NULL);
addot(OT_MAN_MAGITEMUSAGE, "manual of channeling", "Teaches you the skill 'channeling'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_CHANNELING, NA, NA, NULL);
addot(OT_MAN_RANGED, "manual of ranged weapons", "Teaches you the skill 'ranged weapons'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_RANGED, NA, NA, NULL);
addot(OT_MAN_SHIELDS, "manual of shields", "Teaches you the skill 'shields'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SHIELDS, NA, NA, NULL);
addot(OT_MAN_SPELLCASTING, "manual of sorcery", "Teaches you the skill 'sorcery'.", MT_PAPER, 3, OC_BOOK);
@ -5824,8 +5923,10 @@ void initobjects(void) {
addflag(lastot->flags, F_MANUALOF, SK_SS_TRANSLOCATION, NA, NA, NULL);
addot(OT_MAN_SS_WILD, "manual of wild magic", "Teaches you the skill 'wild magic'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SS_WILD, NA, NA, NULL);
*/
// spellbooks
/*
addot(OT_SB_ANIMATEDEAD, "spellbook of animate dead", "Teaches the spell 'animate dead'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_ANIMATEDEAD, NA, NA, NULL);
addot(OT_SB_DRAINLIFE, "spellbook of drain life", "Teaches the spell 'drain life'.", MT_PAPER, 1.5, OC_BOOK);
@ -5993,9 +6094,11 @@ void initobjects(void) {
addflag(lastot->flags, F_LINKSPELL, OT_S_TELEPORT, NA, NA, NULL);
addot(OT_SB_TWIDDLE, "spellbook of twiddle", "Teaches the spell 'twiddle'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_TWIDDLE, NA, NA, NULL);
*/
// assign rarity to books
/*
for (ot = objecttype ; ot ; ot = ot->next) {
if ((ot->obclass->id == OC_BOOK) && !hasflag(ot->flags, F_RARITY)) {
flag_t *f;
@ -6025,6 +6128,7 @@ void initobjects(void) {
}
}
*/
// wands
@ -6614,6 +6718,19 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 6, 6, NA, NULL);
addot(OT_WOODENTABLE, "wooden table", "A waist-height wooden table.", MT_WOOD, 25, OC_MISC);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "\\");
addflag(lastot->flags, F_IMPASSABLE, SZ_HUMAN, NA, NA, NULL);
addflag(lastot->flags, F_CRUSHABLE, SZ_LARGE, NA, NA, NULL);
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
//addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL);
addot(OT_WOODENSTOOL, "wooden footstool", "A small, wooden footstool.", MT_WOOD, 5, OC_MISC);
addflag(lastot->flags, F_RARITY, H_ALL, 83, NA, NULL);
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "\\");
@ -7331,10 +7448,10 @@ void initobjects(void) {
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 9, NA, NULL);
addot(OT_BATTLEAXE, "battleaxe", "An axe specifically designed for combat.", MT_METAL, 5, OC_WEAPON);
addot(OT_BATTLEAXE, "battleaxe", "An large axe specifically designed for combat.", MT_METAL, 5, OC_WEAPON);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL);
addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d9");
addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d8+1");
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
@ -7342,19 +7459,26 @@ void initobjects(void) {
addot(OT_GREATAXE, "greataxe", "An enormous axe made designed for combat.", MT_METAL, 8, OC_WEAPON);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL);
addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d10");
addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d9+1");
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 16, NA, NULL);
addot(OT_HANDAXE, "hand axe", "A fast one-handed axe made for combat.", MT_METAL, 2, OC_WEAPON);
addot(OT_HANDAXE, "hand axe", "A fast one-handed axe, ideal for throwing.", MT_METAL, 2, OC_WEAPON);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL);
addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d6+1");
addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d7");
addflag(lastot->flags, F_ACCURACY, 85, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 7, NA, NULL);
addot(OT_WARAXE, "war axe", "An axe made for combat.", MT_METAL, 4, OC_WEAPON);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL);
addflag(lastot->flags, F_DAM, DT_CHOP, NA, NA, "1d7+1");
addflag(lastot->flags, F_ACCURACY, 85, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 11, NA, NULL);
// short blades
addot(OT_COMBATKNIFE, "combat knife", "A sharp knife designed for military use.", MT_METAL, 1, OC_WEAPON);
@ -7551,7 +7675,7 @@ void initobjects(void) {
// staves
addot(OT_QUARTERSTAFF, "quarterstaff", "A long, stout pole.", MT_WOOD, 2, OC_WEAPON);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d8");
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
@ -7582,7 +7706,7 @@ void initobjects(void) {
addot(OT_IRONSTAFF, "iron staff", "A long, stout metal pole.", MT_METAL, 4, OC_WEAPON);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 135, NA, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "3d4+1");
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
@ -7667,7 +7791,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 5, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 8, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL);
addflag(lastot->flags, F_AMMOOB, OT_ARROW, NA, NA, NULL);
@ -7678,7 +7802,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 9, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 12, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL);
addflag(lastot->flags, F_AMMOOB, OT_BOLT, NA, NA, NULL);
@ -7688,7 +7812,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 5, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 6, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL);
addflag(lastot->flags, F_AMMOOB, OT_BOLT, NA, NA, NULL);
@ -7697,7 +7821,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 7, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 12, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL);
addflag(lastot->flags, F_AMMOOB, OT_ARROW, NA, NA, NULL);
@ -7709,7 +7833,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
//addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
//addflag(lastot->flags, F_DAM, 3, 4, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 10, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 20, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL);
addflag(lastot->flags, F_AMMOOB, OT_BULLET, NA, NA, NULL);
@ -7719,7 +7843,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 3, NA, NA, NULL);
addflag(lastot->flags, F_FIRESPEED, 6, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL);
addflag(lastot->flags, F_AMMOOB, OT_STONE, NA, NA, NULL);
@ -8161,6 +8285,8 @@ int istried(object_t *o) {
int istriedot(objecttype_t *ot) {
knowledge_t *k;
if (ot->obclass->id == OC_BOOK) return B_FALSE;
for (k = knowledge; k ; k = k->next) {
if (k->id == ot->id) {
// it DOES have a hidden name.
@ -9030,6 +9156,20 @@ int obmatchescondition(object_t *o, long opts) {
if ((opts & AO_POURABLE) && ispourable(o)) ok = B_TRUE;
if ((opts & AO_NOTIDENTIFIED) && !isidentified(o)) ok = B_TRUE;
if ((opts & AO_NOTKNOWN) && !isknown(o)) ok = B_TRUE;
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_TRUE;
}
}
return ok;
}
@ -9139,10 +9279,10 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
if (isplayer(lf)) {
if (strlen(f->text) > 0) {
where = askcoords(f->text, ttype);
where = askcoords(f->text, ttype, lf, UNLIMITED);
} else {
sprintf(buf, "Where will you aim %s?",obname);
where = askcoords(buf, ttype);
where = askcoords(buf, ttype, lf, UNLIMITED);
if (!haslos(lf, where)) {
// exception - wand of digging doesn't need los
if (isknown(o) && (o->type->id == OT_WAND_DIGGING)) {
@ -9424,7 +9564,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
// announce
if (!seen) {
noise(where, NULL, "something spraying.", NULL);
noise(where, NULL, 0, "something spraying.", NULL);
}
} else if ((o->type->id == OT_EMPTYFLASK) || (o->type->id == OT_EMPTYVIAL)) {
object_t *oo,*nextoo;
@ -9610,7 +9750,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
if (isplayer(lf)) {
msg("You play a few notes on your panpipes.");
} else {
noise(lf->cell, lf, "the sound of panpipes.", "plays a tune on its panpipes.");
noise(lf->cell, lf, 3, "the sound of panpipes.", "plays a tune on its panpipes.");
}
} else if (o->type->id == OT_PICKAXE) {
int ch,dir;
@ -10279,6 +10419,9 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i
case OT_POT_HEALINGMIN:
dospelleffects(lf, OT_S_HEALINGMIN,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen);
break;
case OT_POT_HEALINGMAJ:
dospelleffects(lf, OT_S_HEALINGMAJ,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen);
break;
case OT_POT_INVIS:
dospelleffects(lf, OT_S_INVISIBILITY,potblessed ? 6 : 3, lf, NULL, lf->cell, potblessed, seen);
break;
@ -10409,17 +10552,20 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i
}
}
break;
case OT_POT_SLEEP:
dospelleffects(lf, OT_S_SLEEP, 8, lf, NULL, lf->cell, B_UNCURSED, NULL);
if (seen) *seen = B_TRUE;
break;
case OT_POT_SPEED:
if (potblessed == B_BLESSED) {
dospelleffects(lf, OT_S_HASTE, 1, lf, NULL, lf->cell, B_BLESSED, NULL);
dospelleffects(lf, OT_S_HASTE, 5, lf, NULL, lf->cell, B_BLESSED, NULL);
} else if (potblessed == B_CURSED) {
dospelleffects(lf, OT_S_SLOW, 1, lf, NULL, lf->cell, B_UNCURSED, NULL);
dospelleffects(lf, OT_S_SLOW, 5, lf, NULL, lf->cell, B_UNCURSED, NULL);
} else { // uncursed
dospelleffects(lf, OT_S_HASTE, 1, lf, NULL, lf->cell, B_UNCURSED, NULL);
dospelleffects(lf, OT_S_HASTE, 5, lf, NULL, lf->cell, B_UNCURSED, NULL);
}
if (seen) *seen = B_TRUE;
break;
case OT_POT_WATER:
switch (potblessed) {
case B_BLESSED:
@ -10585,8 +10731,12 @@ int readsomething(lifeform_t *lf, object_t *o) {
}
if (!isknown(o) && willid) {
// id the scroll
makeknown(o->type->id);
// id the object
if (o->type->obclass->id == OC_BOOK) {
identify(o);
} else {
makeknown(o->type->id);
}
real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE, B_FALSE); // don't adjust for blindness
if (isplayer(lf)) {
// tell the player
@ -10911,7 +11061,7 @@ void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
seen = B_TRUE;
} else {
noise(where, NULL, "shattering glass.", NULL);
noise(where, NULL, 3, "shattering glass.", NULL);
}
if (target) {
@ -11256,7 +11406,7 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno
real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_FALSE, B_FALSE);
real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE);
getobconditionname(o, predamname);
hpflag = hasflag(o->flags, F_OBHP);
if (hpflag) {
@ -11342,7 +11492,7 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno
return damtaken;
}
// throw speed is the damage multiplier
// throw speed/2 is the damage multiplier
int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm) {
char throwername[BUFLEN];
char throwernamea[BUFLEN];
@ -11661,7 +11811,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (shield) {
// block chance based on shield skill
// ie. ST_AVERAGE = speed3 = 18
// ie. gun = speed10 = 60 = basically impossible
// ie. gun = speed20 = 120 = impossible
if (skillcheck(target, SC_SHIELDBLOCK, speed*6, 0)) {
int throwdam,dam;
if (seen) {
@ -12453,7 +12603,6 @@ int usecharge(object_t *o) {
int validateobs(void) {
objecttype_t *ot;
skill_t *sk;
int foundspells = B_FALSE;
int goterror = B_FALSE;
flag_t *f;
@ -12553,6 +12702,7 @@ int validateobs(void) {
}
}
/*
for (sk = firstskill ; sk ; sk = sk->next) {
int found = B_FALSE;
// make sure every skill have an object providing it
@ -12567,6 +12717,7 @@ int validateobs(void) {
goterror = B_TRUE;
}
}
*/
return goterror;
}
@ -12670,21 +12821,27 @@ enum MATSTATE getmaterialstate(enum MATERIAL mat) {
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt) {
int acc,maxrange,howfar;
enum SKILLLEVEL slev;
// figure out if you miss or not, based on distance and
// dexterity
// base:
// if throwing, 50%
// if firing, gun accuracy
// if firing, gun accuracy modified by sk_ranged
// adjust for range:
// pointblank = +30%
// max = -30%
// then modify using dexterity/int/whatever
// then penalise for throwing non-missiles
// base accuracy
if (firearm) {
slev = getskill(thrower, SK_RANGED);
acc = getobaccuracy(firearm, thrower);
// ie. inept = -30%, adept = 0%, master = +30%
acc += ((slev - PR_ADEPT) * 10);
} else {
slev = PR_INEPT;
acc = 50;
}
@ -12700,14 +12857,14 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
}
howfar = getcelldist(thrower->cell, where);
if (howfar == 1) {
acc += 30;
} else if (howfar == maxrange) {
acc -= 30;
if (slev != PR_MASTER) {
acc -= 30;
}
}
// modify for dexterity
if (whichatt != A_NONE) {
acc += getstatmod(thrower, whichatt);

14
save.c
View File

@ -332,8 +332,8 @@ map_t *loadmap(char *basefile) {
*/
// cell info
fscanf(f, "%d,%d,%d,%d,%d,%d,%d\n",
&c->roomid, &celltypeid, &c->known, &c->visited, &c->lit, &c->origlit, &c->littimer);
fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
&c->roomid, &celltypeid, &c->known, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer);
ct = findcelltype(celltypeid);
@ -445,6 +445,10 @@ map_t *loadmap(char *basefile) {
}
}
// load flags
loadflagpile(f, m->flags);
fclose(f);
// move lifeforms to their proper locations
@ -745,8 +749,8 @@ int savemap(map_t *m) {
cell_t *c;
c = getcellat(m, x, y);
// cell info
fprintf(f, "%d,%d,%d,%d,%d,%d,%d\n",
c->roomid, c->type->id, c->known, c->visited,c->lit,c->origlit,c->littimer);
fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
c->roomid, c->type->id, c->known, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer);
// cell objects
for (o = c->obpile->first ; o ; o = o->next) {
fprintf(f, "ob:%ld\n",o->id);
@ -769,6 +773,8 @@ int savemap(map_t *m) {
}
}
saveflagpile(f, m->flags);
fclose(f);
return B_FALSE;

238
spell.c
View File

@ -27,6 +27,7 @@ extern prompt_t prompt;
extern WINDOW *msgwin;
extern job_t *firstjob;
extern objecttype_t *objecttype;
extern map_t *firstmap;
@ -106,7 +107,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user)) {
sprintf(buf, "Charge who (max range %d)?",range);
// TODO: ask for direction
targcell = askcoords(buf, TT_MONSTER);
targcell = askcoords(buf, TT_MONSTER, user, range);
if (!targcell) {
msg("Cancelled.");
return TRUE;
@ -253,7 +254,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else {
sprintf(buf, "Darkwalk to where?");
}
targcell = askcoords(buf, TT_NONE);
targcell = askcoords(buf, TT_NONE, user, range);
} else {
return B_TRUE;
}
@ -537,7 +538,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
sprintf(buf, "Jump where (max distance 2)?");
while (!targcell) {
// ask where
targcell = askcoords(buf, TT_NONE);
targcell = askcoords(buf, TT_NONE, user, 2);
if (!targcell) {
return B_TRUE;
} else if (getcelldist(user->cell, targcell) > 2) {
@ -800,7 +801,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user)) {
sprintf(buf, "Swoop who (max range %d)?",srange);
// TODO: ask for direction
targcell = askcoords(buf, TT_MONSTER);
targcell = askcoords(buf, TT_MONSTER, user, srange);
if (!targcell) {
msg("Cancelled.");
return TRUE;
@ -934,13 +935,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
return B_FALSE;
} else if (abilid == OT_A_DEBUG) {
cell_t *where;
where = askcoords("Debug who?", TT_MONSTER);
where = askcoords("Debug who?", TT_MONSTER, user, UNLIMITED);
if (where && where->lf) {
debug(where->lf);
}
} else if (abilid == OT_A_EMPLOY) {
cell_t *where;
where = askcoords("Assign job to who?", TT_MONSTER);
where = askcoords("Assign job to who?", TT_MONSTER, user, UNLIMITED);
if (where && where->lf) {
char question[BUFLEN];
char lfname[BUFLEN];
@ -964,7 +965,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
}
} else if (abilid == OT_A_ENHANCE) {
cell_t *where;
where = askcoords("Enhance stats of who?", TT_MONSTER);
where = askcoords("Enhance stats of who?", TT_MONSTER, user, UNLIMITED);
if (where && where->lf) {
char ch;
enum ATTRIB att;
@ -1039,8 +1040,9 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
}
makenoise(user, N_WARCRY);
// take a lot of time
taketime(user, getactspeed(user)*4);
// take a lot of time, so that there is a danger in just
// using it all the time.
taketime(user, getactspeed(user)*2);
// all in range must pass a morale check or flee
for (target = user->cell->map->lf ; target ; target = target->next) {
@ -1601,6 +1603,67 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
failed = B_TRUE;
}
if (failed) {
fizzle(caster);
}
} else if (spellid == OT_S_CALLWIND) {
int failed = B_FALSE;
float maxweight;
// if no target object...
if (!targob) {
// ask for a target cell (to take objects from)
if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power)) return B_TRUE;
if (targcell->obpile->first) {
// select object from cell...
if (countobs(targcell->obpile) == 1) {
targob = targcell->obpile->first;
} else {
targob = askobject(targcell->obpile, "Target which object", NULL, AO_NONE);
if (!targob) {
failed = B_TRUE;
}
}
} else {
failed = B_TRUE;
}
}
if (!failed) {
targcell = caster->cell;
// not liftable?
if (hasflag(targob->flags, F_NOPICKUP)) {
if (isplayer(caster)) {
nothinghappens();
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
return B_FALSE;
}
// too heavy? max weight is now based on our race's weight and intelligence
maxweight = getlfweight(caster, B_NOOBS) +
(getlfweight(caster, B_NOOBS) * (getstatmod(caster, A_IQ) / 100));
// modify by power
maxweight += (10*power);
if (getobweight(targob) > maxweight) {
cell_t *obloc;
char obname[BUFLEN];
obloc = getoblocation(targob);
getobname(targob, obname, targob->amt);
if (haslos(player, obloc)) {
msg("%s lifts slightly, then drops again.",obname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
return B_FALSE;
}
pullobto(targob, caster);
}
if (failed) {
fizzle(caster);
}
@ -2253,7 +2316,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!targcell) {
if (isplayer(caster)) {
sprintf(buf, "Where will you target your dispersal?");
targcell = askcoords(buf, TT_MONSTER|TT_OBJECT);
targcell = askcoords(buf, TT_MONSTER|TT_OBJECT, caster, UNLIMITED);
if (!targcell) { // no cell
fizzle(caster);
return B_TRUE;
@ -2962,6 +3025,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_HAILSTORM) {
int failed = B_FALSE;
if (isoutdoors(caster->cell->map)) {
power += 3;
limit(&power, NA, 10);
}
// ask for a target cell
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (targcell) {
@ -3371,9 +3438,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
c = getcellat(m, x, y);
if (c) {
if (range == UNLIMITED) {
c->known = B_TRUE;
setcellknown(c, PR_ADEPT);
} else if (getcelldist(caster->cell, c) <= range) {
c->known = B_TRUE;
setcellknown(c, PR_ADEPT);
}
}
}
@ -3467,7 +3534,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster)) {
// ask for a target cell
sprintf(buf, "Whose mind will you scan?");
where = askcoords(buf, TT_MONSTER);
where = askcoords(buf, TT_MONSTER, caster, UNLIMITED);
if (where && haslos(caster, where) && haslf(where)) {
char targname[BUFLEN];
lifeform_t *oldplayer;
@ -4150,6 +4217,34 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
calclight(targcell->map);
needredraw = B_TRUE;
drawscreen();
} else if (spellid == OT_S_LIGHTNINGBOLT) {
cell_t *retcell[MAXRETCELLS];
int nretcells;
int i;
int nhits = power;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
// create a line of fire towards the target cell
calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, targcell->x, targcell->y, retcell, &nretcells);
animcells(caster->cell, &retcell[1], nretcells-1, B_FALSE, '/', '\\', C_WHITE);
if (cansee(player, caster)) {
msg("%s shoot%s a bolt of lightning!",castername, isplayer(caster) ? "" : "s");
}
// don't hit the caster cell on fire!
for (i = 1; (i < nretcells) && (nhits > 0); i++) {
cell_t *c;
c = retcell[i];
if (c->lf) {
// hit with lightning
losehp(c->lf, roll("2d6"), DT_ELECTRIC, caster, "a lightning bolt");
nhits--;
}
if (haslos(player, c)) {
needredraw = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
}
} else if (spellid == OT_S_LIGHTNINGSTORM) {
char targname[BUFLEN];
lifeform_t *poss[MAXCANDIDATES], *targ[MAXCANDIDATES];
@ -4196,7 +4291,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
getlfname(targ[i],targname);
msg("%s %s struck by a bolt of lightning!",targname, is(targ[i]));
}
if (isoutdoors(target->cell->map)) {
if (isoutdoors(targ[i]->cell->map)) {
losehp(targ[i], rolldie(4,6), DT_ELECTRIC, caster, "a bolt of lightning");
} else {
losehp(targ[i], rolldie(3,6), DT_ELECTRIC, caster, "a bolt of lightning");
@ -4331,7 +4426,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster)) {
cell_t *where;
sprintf(buf, "Where will you target your spell?");
where = askcoords(buf, TT_MONSTER);
where = askcoords(buf, TT_MONSTER, caster, UNLIMITED);
if (where && haslos(caster, where) && haslf(where)) {
target = haslf(where);
} else {
@ -4376,6 +4471,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int i;
char targname[BUFLEN];
if (isoutdoors(caster->cell->map)) {
power += 5;
limit(&power, NA, 10);
}
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_OBJECT, spellid, power)) return B_TRUE;
target = targcell->lf;
@ -4552,7 +4652,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// ask for target if required
if (!target && isplayer(caster)) {
cell_t *where;
where = askcoords("Who will you polymorph?", TT_MONSTER);
where = askcoords("Who will you polymorph?", TT_MONSTER, caster, UNLIMITED);
if (haslos(caster, where)) {
target = where->lf;
} else {
@ -4676,6 +4776,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster)) {
char obname[BUFLEN];
flag_t *f;
int donesomething = B_FALSE;
getobname(o, obname, o->amt);
@ -4684,27 +4785,37 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
makeknown(o->type->id); // you now know that it was poison.
o->type = findot(OT_POT_WATER);
makeknown(o->type->id); // you now know what water is too.
donesomething = B_TRUE;
} else {
f = hasflag(o->flags, F_OBHP);
if (!f) {
nothinghappens();
return B_TRUE;
} else {
if (f) {
f->val[0] = f->val[1];
if (isdrinkable(o)) {
msg("Your %s looks more clean now.", noprefix(obname));
} else {
msg("Your %s looks more fresh now.", noprefix(obname));
}
f = hasflagval(o->flags, F_OBHPDRAIN, NA, DT_DECAY, NA, NULL);
if (f) {
killflag(f);
}
if (seenbyplayer) *seenbyplayer = B_TRUE;
donesomething = B_TRUE;
}
f = hasflag(o->flags, F_TAINTED);
if (f) {
killflag(f);
donesomething = B_TRUE;
}
}
if (donesomething) {
if (isdrinkable(o)) {
msg("Your %s looks more clean now.", noprefix(obname));
} else {
msg("Your %s looks more fresh now.", noprefix(obname));
}
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else {
nothinghappens();
return B_TRUE;
}
} else {
// monsters can't purify things!
@ -4882,6 +4993,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_SLEETSTORM) {
int failed = B_FALSE;
if (isoutdoors(caster->cell->map)) {
power += 3;
limit(&power, NA, 10);
}
// ask for a target cell
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (targcell) {
@ -5181,7 +5296,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
sprintf(buf, "Where will you teleport to?");
while (!c) {
int ch;
c = askcoords(buf, TT_NONE);
c = askcoords(buf, TT_NONE, caster, UNLIMITED);
if (!c->known) {
// confirm
ch = askchar("Are you sure to want to teleport into the unknown?", "yn", "n", B_TRUE);
@ -5337,7 +5452,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!targob) {
// ask for a target cell (to take objects from)
sprintf(buf, "Where will you focus your telekinetic power?");
where = askcoords(buf, TT_OBJECT | TT_DOOR);
where = askcoords(buf, TT_OBJECT | TT_DOOR, caster, UNLIMITED);
if (where && haslos(caster, where)) {
if (where->obpile->first) {
// select object from cell...
@ -5374,7 +5489,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char obname[BUFLEN];
getobname(targob, obname, 1);
sprintf(buf, "Where will you move %s to?", obname);
targcell = askcoords(buf, TT_MONSTER | TT_PLAYER);
targcell = askcoords(buf, TT_MONSTER | TT_PLAYER, caster, UNLIMITED);
}
// not liftable?
@ -5888,7 +6003,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
o = relinkob(o, newloc->obpile);
}
if (o) {
noise(caster->cell, NULL, "something hitting the ground.", NULL);
noise(caster->cell, NULL, 1, "something hitting the ground.", NULL);
if (!isblind(caster)) {
msg("%s appear%s on the ground!", obname, (o->amt == 1) ? "s" : "");
}
@ -5909,6 +6024,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return rv;
}
objecttype_t *findspelln(char *buf) {
objecttype_t *ot;
for (ot = objecttype ; ot ; ot = ot->next) {
if (ot->obclass->id == OC_SPELL) {
if (!strcasecmp(ot->name, buf)) {
return ot;
}
}
}
return NULL;
}
void fizzle(lifeform_t *caster) {
if (isplayer(caster)) {
if (lfhasflag(caster, F_CASTINGSPELL)) {
@ -5925,6 +6052,30 @@ void fizzle(lifeform_t *caster) {
}
}
enum OBTYPE getrandomspell(void) {
int wantlev;
objecttype_t *ot,*poss[MAXCANDIDATES];
int nposs = 0;
wantlev = 1;
while (rnd(1,2) == 1) {
wantlev++;
}
// get list of all spells of this level
for (ot = objecttype ; ot ; ot = ot->next) {
if ((ot->obclass->id == OC_SPELL) && (getspelllevel(ot->id) == wantlev) ) {
poss[nposs++] = ot;
}
}
if (nposs <= 0) {
return OT_NONE;
}
ot = poss[rnd(0,nposs-1)];
return ot->id;
}
enum SKILL getschoolskill(enum SPELLSCHOOL ss) {
switch (ss) {
case SS_ALLOMANCY:
@ -6252,6 +6403,12 @@ int getspellrange(enum OBTYPE spellid, int power) {
// base range for this spell is 3
range += (power/3);
break;
case OT_S_CALLWIND:
range = (power*2);
break;
case OT_S_LIGHTNINGBOLT:
range = (power*3);
break;
default:
break;
}
@ -6345,6 +6502,19 @@ void stopallspells(lifeform_t *lf) {
}
}
int schoolappearsinbooks(enum SPELLSCHOOL ss) {
switch (ss) {
case SS_DIVINE:
case SS_ABILITY:
case SS_ALLOMANCY:
case SS_MENTAL:
return B_FALSE;
default:
break;
}
return B_TRUE;
}
void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power) {
int x,y;
if (ch != '\0') {
@ -6480,7 +6650,7 @@ lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **targe
cell_t *where;
char buf[BUFLEN];
sprintf(buf, "Where will you target your %s?",ot->name);
where = askcoords(buf, TT_MONSTER);
where = askcoords(buf, TT_MONSTER, user, maxrange);
if (where) {
if (!haslf(where)) {
msg("There is nobody there!");
@ -6611,7 +6781,7 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e
} else {
sprintf(buf, "Where will you target your spell [max range %d]?",maxrange);
}
where = askcoords(buf, targtype);
where = askcoords(buf, targtype, caster, maxrange);
if (!where) {
int ch;
ch = askchar("Abandon your spell?","yn","n", B_TRUE);
@ -6704,7 +6874,7 @@ lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **target) {
cell_t *where;
char buf[BUFLEN];
sprintf(buf, "Where will you target your spell?");
where = askcoords(buf, TT_MONSTER);
where = askcoords(buf, TT_MONSTER, caster, UNLIMITED);
if (where && haslos(caster, where) && haslf(where)) {
*target = haslf(where);
} else {

View File

@ -4,9 +4,11 @@
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target, flag_t *cwflag);
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer);
objecttype_t *findspelln(char *buf);
void fizzle(lifeform_t *caster);
//int getiqreq(enum OBTYPE oid);
int getmpcost(lifeform_t *lf, enum OBTYPE oid);
enum OBTYPE getrandomspell(void);
enum SKILL getschoolskill(enum SPELLSCHOOL ss);
char *getspellcosttext(lifeform_t *lf, enum OBTYPE spellid, int power, char *buf);
int getspellduration(int min,int max,int blessed);
@ -19,6 +21,7 @@ enum SPELLSCHOOL getspellschoolknown(lifeform_t *lf, enum OBTYPE spellid);
int getspellrange(enum OBTYPE spellid, int power);
char *getvarpowerspelldesc(enum OBTYPE spellid, int power, char *buf);
void pullobto(object_t *o, lifeform_t *lf);
int schoolappearsinbooks(enum SPELLSCHOOL ss);
void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power);
void stopspell(lifeform_t *caster, enum OBTYPE spellid);
void stopallspells(lifeform_t *lf);

2
text.c
View File

@ -328,7 +328,7 @@ char *makeplural(char *text) {
if (rv) return newtext;
newtext = strrep(newtext, "gem ", "gems ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "leaf ", "leaves ", &rv);
newtext = strrep(newtext, "leaf", "leaves", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "loaf ", "loaves ", &rv);
if (rv) return newtext;