- [+] monster which is horrific - penalties if you can see it! (or you
just can't attack?) - [+] glow bug corpse in empty flask * [+] auto hit if paralyzed/frozen - [+] allomancer has permenant detect metal - [+] remove detect metal spell - [+] make detect magic last way longer (at least triple) * [+] change scrolls to wands: * [+] on "behead", leave head? - [+] allomancer way to heal using metal? like absorb metal but costs more. * [+] way to see spell descriptions * [+] replace most occurensces of getmovespeed() with getactionspeed() * [+] "sprint" ability - [+] remove curse scroll! - [+] need average IQ to know if something is rotting! - [+] make mosnters rest. - [+] create monster needs to cope with 'xxx wizard' - [+] ie. if no match on name, look for job suffixes - [+] if found, strip it, make the monsters (force no job!), then apply the job - [+] rotting corpses turn into bones * [+] Monster wizards start with a _random_ book, not flamedart. - [+] 'R'esting bug. - [+] waited forever. NEver gained any hp! - [+] need to somehow check when resting that we _ARE_ actually gaining hp... ?
This commit is contained in:
parent
86ee482ce3
commit
4f89ab33f8
255
ai.c
255
ai.c
|
@ -16,8 +16,105 @@
|
|||
extern lifeform_t *player;
|
||||
extern enum ERROR reason;
|
||||
|
||||
void aimove(lifeform_t *lf) {
|
||||
int wantdb = B_TRUE;
|
||||
|
||||
enum OBTYPE aigetattackspell(lifeform_t *lf) {
|
||||
flag_t *f;
|
||||
enum OBTYPE poss[MAXPILEOBS];
|
||||
int nposs = 0;
|
||||
int db = B_FALSE;
|
||||
|
||||
if (lfhasflag(lf, F_DEBUG)) {
|
||||
db = B_TRUE;
|
||||
}
|
||||
|
||||
for (f = lf->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_CANWILL) {
|
||||
poss[nposs] = f->val[0];
|
||||
nposs++;
|
||||
} else if (f->id == F_CANCAST) {
|
||||
objecttype_t *ot;
|
||||
ot = findot(f->val[0]);
|
||||
if (cancast(lf, f->val[0], NULL)) {
|
||||
if (hasflag(ot->flags, F_AICASTATVICTIM) || hasflag(ot->flags, F_AICASTATSELF) || hasflag(ot->flags, F_AICASTANYWHERE)) {
|
||||
if (db) {
|
||||
dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?");
|
||||
}
|
||||
//TODO :ooo only add if we have an AICAST flag!
|
||||
poss[nposs] = f->val[0];
|
||||
nposs++;
|
||||
} else {
|
||||
if (db) {
|
||||
dblog(".oO { cant cast %s - dont know where to target it }", ot ? ot->name : "?unkownspell?");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (db) {
|
||||
if (ot) {
|
||||
dblog(".oO { can't cast %s right now (mpcost=%d, i have %d) }",
|
||||
ot ? ot->name : "?unkownspell?",
|
||||
getmpcost(ot->id), lf->mp);
|
||||
} else {
|
||||
dblog(".oO { can't cast ?unknownspell? right now }");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// select a random one
|
||||
if (nposs > 0) {
|
||||
int sel;
|
||||
sel = rnd(0,nposs-1);
|
||||
return poss[sel];
|
||||
}
|
||||
|
||||
return OT_NONE;
|
||||
}
|
||||
|
||||
void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob) {
|
||||
if (hasflag(spelltype->flags, F_AICASTATVICTIM)) {
|
||||
if (spelllf) *spelllf = victim;
|
||||
if (spellcell) *spellcell = victim->cell;
|
||||
if (spellob) *spellob = NULL;
|
||||
} else if (hasflag(spelltype->flags, F_AICASTATSELF)) {
|
||||
if (spelllf) *spelllf = lf;
|
||||
if (spellcell) *spellcell = lf->cell;
|
||||
if (spellob) *spellob = NULL;
|
||||
} else if (hasflag(spelltype->flags, F_AICASTANYWHERE)) {
|
||||
if (spelllf) *spelllf = NULL;
|
||||
if (spellcell) *spellcell = NULL;
|
||||
if (spellob) *spellob = NULL;
|
||||
} else {
|
||||
// default - at victim.
|
||||
if (spelllf) *spelllf = victim;
|
||||
if (spellcell) *spellcell = victim->cell;
|
||||
if (spellob) *spellob = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
object_t * aigetwand(lifeform_t *lf) {
|
||||
object_t *o;
|
||||
object_t *poss[MAXPILEOBS];
|
||||
int nposs = 0;
|
||||
for (o = lf->pack->first ; o ; o = o->next) {
|
||||
// wand with charges left?
|
||||
if ((o->type->obclass->id == OC_WAND) && (getcharges(o) > 0)) {
|
||||
// do we know how to use it?
|
||||
if (hasflag(o->flags, F_AICASTATVICTIM) || hasflag(o->flags, F_AICASTATSELF) || hasflag(o->flags, F_AICASTANYWHERE)) {
|
||||
// TODO: if castatself, check whether we actually need to (ie. healing etc)
|
||||
poss[nposs] = o;
|
||||
nposs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nposs > 0) {
|
||||
return poss[rnd(0,nposs-1)];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void aimove(lifeform_t *lf) {
|
||||
int db = B_FALSE;
|
||||
object_t *curwep,*bestwep, *o;
|
||||
object_t *curgun,*bestgun;
|
||||
|
@ -33,11 +130,19 @@ void aimove(lifeform_t *lf) {
|
|||
|
||||
|
||||
|
||||
/*
|
||||
if (wantdb && haslos(player, lf->cell)) {
|
||||
db = B_TRUE;
|
||||
} else {
|
||||
db = B_FALSE;
|
||||
}
|
||||
*/
|
||||
|
||||
if (wantdb && lfhasflag(lf, F_DEBUG)) {
|
||||
db = B_TRUE;
|
||||
} else {
|
||||
db = B_FALSE;
|
||||
}
|
||||
|
||||
if (db) {
|
||||
char lfname[BUFLEN];
|
||||
|
@ -132,15 +237,15 @@ void aimove(lifeform_t *lf) {
|
|||
|
||||
|
||||
// can we attack with spells (ie. ones which target the victim)?
|
||||
spell = getattackspell(lf);
|
||||
spell = aigetattackspell(lf);
|
||||
if (spell != OT_NONE) {
|
||||
int spellfailed = B_FALSE;
|
||||
lifeform_t *spelllf = NULL;
|
||||
cell_t *spellcell = NULL;
|
||||
object_t *spellob = NULL;
|
||||
if (db) {
|
||||
objecttype_t *st;
|
||||
st = findot(spell);
|
||||
if (db) {
|
||||
dblog(".oO { will cast attack spell: %s }", st->name);
|
||||
}
|
||||
|
||||
|
@ -179,9 +284,8 @@ void aimove(lifeform_t *lf) {
|
|||
spelllf = target;
|
||||
spellcell = target->cell;
|
||||
} else {
|
||||
spelllf = target;
|
||||
spellcell = target->cell;
|
||||
spellob = NULL;
|
||||
// pick targets based on spell flags
|
||||
aigetspelltarget(lf, st, target, &spelllf, &spellcell, &spellob);
|
||||
}
|
||||
|
||||
|
||||
|
@ -193,6 +297,8 @@ void aimove(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
|
||||
// if not adjacent, check for guns, wands, throwing
|
||||
if (goingtomove && (getcelldist(lf->cell, target->cell) > 1)) {
|
||||
// can we attack by firing something?
|
||||
gun = getfirearm(lf);
|
||||
if (goingtomove && gun && getammo(lf)) {
|
||||
|
@ -206,7 +312,7 @@ void aimove(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
// can we attack by throwing something?
|
||||
if (goingtomove && getcelldist(lf->cell, target->cell) > 1) {
|
||||
if (goingtomove) {
|
||||
// TODO: or firing! check if we have a firearm first.
|
||||
o = getbestmissile(lf);
|
||||
if (o) {
|
||||
|
@ -221,6 +327,32 @@ void aimove(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
|
||||
// do we have a wand we can zap?
|
||||
o = aigetwand(lf);
|
||||
if (o) {
|
||||
objecttype_t *st;
|
||||
cell_t *zapcell = NULL;
|
||||
|
||||
st = getlinkspell(o);
|
||||
if (st) {
|
||||
aigetspelltarget(lf, st, target, NULL, &zapcell, NULL);
|
||||
} else {
|
||||
// no linkspell - just zap it.
|
||||
zapcell = NULL;
|
||||
}
|
||||
|
||||
// zap it
|
||||
if (db) dblog(".oO { will zap %s instead of moving }", o->type->name);
|
||||
|
||||
if (!operate(lf, o, zapcell)) {
|
||||
// succesful
|
||||
goingtomove = B_FALSE;
|
||||
} else {
|
||||
if (db) dblog(".oO { zap failed! }");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do we have a valid melee attack?
|
||||
if (!curwep) {
|
||||
if (db) dblog(".oO { won't move towards target - i have no weapon. }");
|
||||
|
@ -256,15 +388,6 @@ void aimove(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
if (lookforobs(lf, B_COVETS)) {
|
||||
if (db) dblog(".oO { found covetted object. returning. }");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// do we have a target cell?
|
||||
f = hasflag(lf->flags, F_TARGETCELL);
|
||||
if (f) {
|
||||
|
@ -316,20 +439,19 @@ void aimove(lifeform_t *lf) {
|
|||
// are we hostile? if so, look for a target
|
||||
f = hasflag(lf->flags, F_HOSTILE);
|
||||
if (f) {
|
||||
int x,y;
|
||||
int i;
|
||||
if (db) dblog(".oO { i am hostile. looking for a target. }");
|
||||
|
||||
// look around for a target
|
||||
// TODO: use our vis rang einstead of 10!
|
||||
for (y = lf->cell->y - 10; y <= lf->cell->y + 10; y++) {
|
||||
for (x = lf->cell->x - 10; x <= lf->cell->x + 10; x++) {
|
||||
c = getcellat(lf->cell->map, x, y);
|
||||
// cell exists and we can see it?
|
||||
if (c && haslos(lf, c)) {
|
||||
// player there?
|
||||
if (c->lf && (c->lf != lf) && isplayer(c->lf)) {
|
||||
for (i = 0; i < lf->nlos; i++) {
|
||||
cell_t *c;
|
||||
c = lf->los[i];
|
||||
|
||||
if (c->lf) {
|
||||
if (isplayer(c->lf)) { // TODO: change to if isenemy ?
|
||||
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
|
||||
// target them!
|
||||
addtempflag(lf->flags, F_TARGET, c->lf->id, NA, NA, NULL, AI_FOLLOWTIME);
|
||||
addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME);
|
||||
// tell the player
|
||||
if (haslos(player, lf->cell)) {
|
||||
makenoise(lf, N_GETANGRY);
|
||||
|
@ -342,7 +464,7 @@ void aimove(lifeform_t *lf) {
|
|||
} else {
|
||||
if (db) dblog(".oO { won't move towards target - i have no weapon. }");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -364,7 +486,7 @@ void aimove(lifeform_t *lf) {
|
|||
if (c->lf && (c->lf != lf) && !isplayer(c->lf)) {
|
||||
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
|
||||
// target them!
|
||||
addtempflag(lf->flags, F_TARGET, c->lf->id, NA, NA, NULL, AI_FOLLOWTIME);
|
||||
addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME);
|
||||
// then move towards them...
|
||||
if (db) dblog(".oO { moving towards my new target }");
|
||||
if (!movetowards(lf, c)) return;
|
||||
|
@ -375,6 +497,13 @@ void aimove(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
|
||||
// need to heal?
|
||||
if ((lf->hp < lf->maxhp) ||
|
||||
((lf->mp < lf->maxmp) && lfhasflag(lf, F_RESTHEALMPAMT)) ) {
|
||||
if (db) dblog(".oO { resting }");
|
||||
rest(lf, B_TRUE);
|
||||
}
|
||||
|
||||
// just try to move in a random direction
|
||||
if (db) dblog(".oO { default - moving randomly }");
|
||||
dorandommove(lf, B_NOBADMOVES);
|
||||
|
@ -388,54 +517,11 @@ int aipickup(lifeform_t *lf, object_t *o) {
|
|||
if (isedible(o)) {
|
||||
return eat(lf, o);
|
||||
} else {
|
||||
return pickup(lf, o, o->amt);
|
||||
return pickup(lf, o, o->amt, B_TRUE);
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
enum OBTYPE getattackspell(lifeform_t *lf) {
|
||||
flag_t *f;
|
||||
enum OBTYPE poss[MAXPILEOBS];
|
||||
int nposs = 0;
|
||||
int db = B_TRUE;
|
||||
for (f = lf->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_CANWILL) {
|
||||
poss[nposs] = f->val[0];
|
||||
nposs++;
|
||||
} else if (f->id == F_CANCAST) {
|
||||
objecttype_t *ot;
|
||||
ot = findot(f->val[0]);
|
||||
if (cancast(lf, f->val[0], NULL)) {
|
||||
if (db) {
|
||||
dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?");
|
||||
|
||||
}
|
||||
poss[nposs] = f->val[0];
|
||||
nposs++;
|
||||
} else {
|
||||
if (db) {
|
||||
if (ot) {
|
||||
dblog(".oO { can't cast %s right now (mpcost=%d, i have %d) }",
|
||||
ot ? ot->name : "?unkownspell?",
|
||||
getmpcost(ot->id), lf->mp);
|
||||
} else {
|
||||
dblog(".oO { can't cast ?unknownspell? right now }");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// select a random one
|
||||
if (nposs > 0) {
|
||||
int sel;
|
||||
sel = rnd(0,nposs-1);
|
||||
return poss[sel];
|
||||
}
|
||||
|
||||
return OT_NONE;
|
||||
}
|
||||
|
||||
|
||||
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op) {
|
||||
object_t *o;
|
||||
|
@ -478,11 +564,17 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
int noids = 0;
|
||||
enum FLAG wantflag[MAXPILEOBS];
|
||||
int nwantflags = 0;
|
||||
int db = B_TRUE;
|
||||
flag_t *f;
|
||||
cell_t *c;
|
||||
int n;
|
||||
int i;
|
||||
int db = B_FALSE;
|
||||
|
||||
if (wantdb && lfhasflag(lf, F_DEBUG)) {
|
||||
db = B_TRUE;
|
||||
} else {
|
||||
db = B_FALSE;
|
||||
}
|
||||
|
||||
// construct a list of objects which we want
|
||||
noids = 0;
|
||||
|
@ -502,7 +594,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
|
||||
// current cell has an object we want?
|
||||
o = hasobmulti(lf->cell->obpile, oid, noids);
|
||||
if (o && (canpickup(lf, o) || caneat(lf,o)) ) {
|
||||
if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf,o)) ) {
|
||||
if (db) dblog(".oO { current cell has ob i want (%s) }",o->type->name);
|
||||
// try to pick it up
|
||||
if (!aipickup(lf, o)) return B_TRUE;
|
||||
|
@ -513,7 +605,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
// has an object with a flag we want?
|
||||
for (n = 0; n < nwantflags; n++) {
|
||||
o = hasobwithflag(lf->cell->obpile, wantflag[n]);
|
||||
if (o && (canpickup(lf, o) || caneat(lf,o)) ) {
|
||||
if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf,o)) ) {
|
||||
if (db) dblog(".oO { current cell has ob with flag i want (%s) }",o->type->name);
|
||||
// try to pick it up
|
||||
if (!aipickup(lf, o)) return B_TRUE;
|
||||
|
@ -528,7 +620,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
if (f ) {
|
||||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
o = hasbetterweapon(lf, lf->cell->obpile);
|
||||
if (o && canpickup(lf, o)) {
|
||||
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
|
||||
if (db) dblog(".oO { current cell has better weapon (%s) }",o->type->name);
|
||||
// try to pick it up
|
||||
if (!aipickup(lf, o)) return B_TRUE;
|
||||
|
@ -541,7 +633,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
if (f ) {
|
||||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
o = hasbetterarmour(lf, lf->cell->obpile);
|
||||
if (o && canpickup(lf, o)) {
|
||||
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
|
||||
if (db) dblog(".oO { current cell has better armour (%s) }",o->type->name);
|
||||
// try to pick it up
|
||||
if (!aipickup(lf, o)) return B_TRUE;
|
||||
|
@ -559,7 +651,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
c = lf->los[i];
|
||||
if (c != lf->ignorecell) {
|
||||
o = hasobmulti(c->obpile, oid, noids);
|
||||
if (o && (canpickup(lf, o) || caneat(lf,o)) ) {
|
||||
if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf,o)) ) {
|
||||
if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name);
|
||||
gothere = B_TRUE;
|
||||
}
|
||||
|
@ -567,7 +659,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
// has an object with a flag we want?
|
||||
for (n = 0; n < nwantflags; n++) {
|
||||
o = hasobwithflag(c->obpile, wantflag[n]);
|
||||
if (o && (canpickup(lf, o) || caneat(lf, o)) ) {
|
||||
if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf, o)) ) {
|
||||
if (db) dblog(".oO { remote cell has ob with flag i want (%s) }", o->type->name);
|
||||
gothere = B_TRUE;
|
||||
}
|
||||
|
@ -580,7 +672,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
|
||||
o = hasbetterweapon(lf, c->obpile);
|
||||
if (o && canpickup(lf, o)) {
|
||||
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
|
||||
if (db) dblog(".oO { remote cell has better weapon (%s). setting f_targetcell }",o->type->name);
|
||||
gothere = B_TRUE;
|
||||
}
|
||||
|
@ -594,7 +686,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
if (!covetsonly || (f->val[1] == B_COVETS)) {
|
||||
|
||||
o = hasbetterarmour(lf, c->obpile);
|
||||
if (o && canpickup(lf, o)) {
|
||||
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
|
||||
if (db) dblog(".oO { remote cell has better armour (%s). setting f_targetcell }",o->type->name);
|
||||
gothere = B_TRUE;
|
||||
}
|
||||
|
@ -613,6 +705,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (db) dblog(".oO { didn't find any obs i want }");
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
|
4
ai.h
4
ai.h
|
@ -1,8 +1,10 @@
|
|||
#include "defs.h"
|
||||
|
||||
enum OBTYPE aigetattackspell(lifeform_t *lf);
|
||||
void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob);
|
||||
object_t * aigetwand(lifeform_t *lf);
|
||||
void aimove(lifeform_t *lf);
|
||||
int aipickup(lifeform_t *lf, object_t *o);
|
||||
enum OBTYPE getattackspell(lifeform_t *lf);
|
||||
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op);
|
||||
object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op);
|
||||
int lookforobs(lifeform_t *lf, int covetsonly);
|
||||
|
|
218
attack.c
218
attack.c
|
@ -34,7 +34,7 @@ int attackcell(lifeform_t *lf, cell_t *c) {
|
|||
}
|
||||
|
||||
int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
||||
unsigned int dam[100];
|
||||
int dam[100];
|
||||
enum DAMTYPE damtype[100];
|
||||
int ndam = 0;
|
||||
char buf[BUFLEN];
|
||||
|
@ -50,16 +50,13 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
char wepname[BUFLEN];
|
||||
int ev;
|
||||
int i;
|
||||
int willheal = B_FALSE;
|
||||
|
||||
int aidb = B_TRUE;
|
||||
int aidb = B_FALSE;
|
||||
|
||||
|
||||
if (aidb) {
|
||||
if (isplayer(lf)) {
|
||||
aidb = B_FALSE;
|
||||
} else if (!haslos(player, lf->cell)) {
|
||||
aidb = B_FALSE;
|
||||
}
|
||||
if (lfhasflag(lf, F_DEBUG)) {
|
||||
aidb = B_TRUE;
|
||||
}
|
||||
|
||||
// get names
|
||||
|
@ -78,12 +75,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
} else if (haslos(player, lf->cell)) {
|
||||
//msg("%s looks like it wants to attack!",attackername);
|
||||
}
|
||||
/*
|
||||
if (!isplayer(lf)) {
|
||||
// if ai, take some time to avoid infinite loops!
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
*/
|
||||
if (op) killobpile(op);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -157,19 +148,27 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
// override normal damage calculation
|
||||
dam[ndam] = getdamrollfromflag(unarmedflag);
|
||||
} else {
|
||||
dam[ndam] = getdamroll(wep);
|
||||
dam[ndam] = getdamroll(wep, victim);
|
||||
}
|
||||
dblog("rolled dam[%d] = %d",ndam,dam[ndam]);
|
||||
if (aidb) dblog("rolled dam[%d] = %d",ndam,dam[ndam]);
|
||||
|
||||
if (dam[ndam] < 0) {
|
||||
willheal = B_TRUE;
|
||||
}
|
||||
|
||||
if (!willheal) {
|
||||
// modify for strength
|
||||
dam[ndam] = (int)((float)dam[ndam] * getstrdammod(lf));
|
||||
}
|
||||
|
||||
// damtype?
|
||||
damtype[ndam] = getdamtype(wep);
|
||||
if (aidb) dblog(".oO { dealing %d %s damage }", dam[ndam], getdamname(damtype[ndam]));
|
||||
ndam++;
|
||||
|
||||
|
||||
// blessed vs undead etc?
|
||||
if (!willheal) {
|
||||
if (isblessed(wep) && lfhasflagval(victim, F_DTVULN, DT_HOLY, NA, NA, NULL)) {
|
||||
// a little extra damage
|
||||
dam[ndam] = (int) ( (float)dam[ndam] * 1.25 );
|
||||
|
@ -177,6 +176,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
|
||||
// determine extra damage
|
||||
getextradam(wep, &dam[ndam], &damtype[ndam]);
|
||||
}
|
||||
} else {
|
||||
hit = B_FALSE;
|
||||
ndam = 0;
|
||||
|
@ -213,6 +213,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
// announce it
|
||||
if (isplayer(lf)) {
|
||||
char extradambuf[BUFLEN];
|
||||
char *verb;
|
||||
if (dam[i] == 0) {
|
||||
strcpy(extradambuf, " but do no damage");
|
||||
} else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
|
||||
|
@ -220,11 +221,21 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
} else {
|
||||
strcpy(extradambuf, "");
|
||||
}
|
||||
|
||||
if (fatal) {
|
||||
verb = getkillverb(victim, damtype[i], dam[i], victim->maxhp);
|
||||
} else {
|
||||
verb = getattackverb(damtype[i], dam[i], victim->maxhp);
|
||||
}
|
||||
warn("You %s %s%s%s",
|
||||
fatal ? getkillverb(damtype[i], dam[i], victim->maxhp) : getattackverb(damtype[i], dam[i], victim->maxhp),
|
||||
verb,
|
||||
victimname, extradambuf,
|
||||
fatal ? "!" : ".");
|
||||
|
||||
if (fatal && strstr(verb, "behead")) {
|
||||
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
|
||||
if (fatal && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
|
||||
// don't also say "the xx dies"
|
||||
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
|
||||
|
@ -259,6 +270,18 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (willheal) {
|
||||
if (haslos(player, victim->cell)) {
|
||||
flag_t *f;
|
||||
msg("%s is healed!",victimname);
|
||||
f = hasflag(wep->flags, F_BALANCE);
|
||||
if (f) {
|
||||
f->known = B_TRUE;
|
||||
}
|
||||
gainhp(victim, dam[i]);
|
||||
}
|
||||
} else {
|
||||
// victim loses hp
|
||||
// don't adjust damage - we've already done that
|
||||
if (wep && !unarmedflag) {
|
||||
|
@ -268,14 +291,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
} else {
|
||||
strcpy(buf, attackername);
|
||||
}
|
||||
// check
|
||||
/*
|
||||
if (dam[i] >= 120) {
|
||||
// potential bug
|
||||
msg("DB: potential bug: huge dam=%d",dam[i]);
|
||||
assert(1 == 2);
|
||||
}
|
||||
*/
|
||||
|
||||
losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE);
|
||||
|
||||
|
@ -283,18 +298,36 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
if (reduceamt) {
|
||||
object_t *armour;
|
||||
int adam;
|
||||
// damage reduction goes towards armour
|
||||
if (damtype[i] == DT_ACID) {
|
||||
// ALL of damage reduction goes towards armour
|
||||
adam = reduceamt;
|
||||
} else {
|
||||
// some of damage reduction goes towards armour
|
||||
adam = (reduceamt / 2);
|
||||
}
|
||||
// pick a random piece of armour
|
||||
armour = getrandomarmour(victim);
|
||||
if (armour) {
|
||||
takedamage(armour,adam, damtype[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end foreach damtype
|
||||
|
||||
// special weapon effects
|
||||
wepeffects(wep, victim->cell);
|
||||
|
||||
if (!isdead(victim)) {
|
||||
if (unarmedflag) {
|
||||
flag_t *f;
|
||||
f = lfhasflag(lf, F_FREEZINGTOUCH);
|
||||
if (f) {
|
||||
// victim turns to ice for a while!
|
||||
freezelf(victim, lf, rnd(5,10));
|
||||
killflag(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // miss!
|
||||
if (aidb) dblog(".oO { i missed! }");
|
||||
// announce it
|
||||
|
@ -338,7 +371,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
}
|
||||
|
||||
int attackob(lifeform_t *lf, object_t *o) {
|
||||
unsigned int dam[100];
|
||||
int dam[100];
|
||||
enum DAMTYPE damtype[100];
|
||||
int ndam = 0;
|
||||
char attackername[BUFLEN];
|
||||
|
@ -379,7 +412,7 @@ int attackob(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
if (!isplayer(lf)) {
|
||||
// if ai, take some time to avoid infinite loops!
|
||||
taketime(lf, getmovespeed(lf));
|
||||
taketime(lf, getactspeed(lf));
|
||||
}
|
||||
if (op) killobpile(op);
|
||||
return B_TRUE;
|
||||
|
@ -402,7 +435,7 @@ int attackob(lifeform_t *lf, object_t *o) {
|
|||
// override normal damage calculation
|
||||
dam[ndam] = getdamrollfromflag(unarmedflag);
|
||||
} else {
|
||||
dam[ndam] = getdamroll(wep);
|
||||
dam[ndam] = getdamroll(wep, NULL);
|
||||
}
|
||||
|
||||
// damtype?
|
||||
|
@ -458,7 +491,7 @@ int attackob(lifeform_t *lf, object_t *o) {
|
|||
|
||||
|
||||
// returns a const char *
|
||||
const char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
float pct;
|
||||
pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
if (damtype == DT_PROJECTILE) {
|
||||
|
@ -502,6 +535,8 @@ const char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) {
|
|||
} else if (pct <= 15) {
|
||||
return "claw";
|
||||
} else if (pct <= 30) {
|
||||
return "tear";
|
||||
} else if (pct <= 40) {
|
||||
return "rake";
|
||||
} else if (pct <= 50) {
|
||||
return "gouge";
|
||||
|
@ -600,7 +635,7 @@ enum DAMTYPE getdamtype(object_t *wep) {
|
|||
return dt;
|
||||
}
|
||||
|
||||
int getextradam(object_t *wep, unsigned int *dam, enum DAMTYPE *damtype) {
|
||||
int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype) {
|
||||
flag_t *f;
|
||||
for (f = wep->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_ONFIRE) {
|
||||
|
@ -611,10 +646,14 @@ int getextradam(object_t *wep, unsigned int *dam, enum DAMTYPE *damtype) {
|
|||
return *dam;
|
||||
}
|
||||
|
||||
char *getkillverb(enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
float pct;
|
||||
pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
|
||||
if ((damtype == DT_BASH) && lfhasflag(victim, F_FROZEN)) {
|
||||
return "shatter";
|
||||
}
|
||||
|
||||
if (damtype == DT_HOLY) {
|
||||
return "smite";
|
||||
}
|
||||
|
@ -624,7 +663,17 @@ char *getkillverb(enum DAMTYPE damtype, int dam, int maxhp) {
|
|||
if (damtype == DT_BASH) return "flatten";
|
||||
if (damtype == DT_BITE) return "gore";
|
||||
if (damtype == DT_CLAW) return "disembowel";
|
||||
if (damtype == DT_SLASH) return "behead"; // TODO: only if they have a head! otherwise "bisect"
|
||||
if (damtype == DT_SLASH) {
|
||||
if (lfhasflagval(victim, F_NOBODYPART, BP_HEAD, NA, NA, NULL)) {
|
||||
return "bisect";
|
||||
} else {
|
||||
if (rnd(1,3)) {
|
||||
return "behead";
|
||||
} else {
|
||||
return "bisect";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "kill";
|
||||
|
@ -659,9 +708,51 @@ void getdamrange(flagpile_t *fp, int *min, int *max) {
|
|||
if (max) *max = maxdam;
|
||||
}
|
||||
|
||||
void getdamrangeunarmed(flag_t *f, int *min, int *max) {
|
||||
obpile_t *op;
|
||||
object_t *o;
|
||||
op = addobpile(NULL, NULL);
|
||||
o = addob(op, f->text);
|
||||
if (o) {
|
||||
int ndice,nsides,mod;
|
||||
flag_t *damflag;
|
||||
|
||||
damflag = hasflag(o->flags, F_DAM);
|
||||
|
||||
if (f->val[0] == NA) {
|
||||
ndice = damflag->val[0];
|
||||
} else {
|
||||
ndice = f->val[0];
|
||||
}
|
||||
if (f->val[1] == NA) {
|
||||
nsides = damflag->val[1];
|
||||
} else {
|
||||
nsides = f->val[1];
|
||||
}
|
||||
if (f->val[2] == NA) {
|
||||
if (damflag->val[2] != NA) {
|
||||
mod = damflag->val[2];
|
||||
} else {
|
||||
mod = 0;
|
||||
}
|
||||
} else {
|
||||
mod = f->val[2];
|
||||
}
|
||||
|
||||
if (min) *min = (ndice * 1) + mod;
|
||||
if (max) *max = (ndice * nsides) + mod;
|
||||
|
||||
killob(o);
|
||||
} else {
|
||||
if (min) *min = 0;
|
||||
if (max) *max = 0;
|
||||
}
|
||||
free(op);
|
||||
}
|
||||
|
||||
|
||||
// roll for damage
|
||||
int getdamroll(object_t *o) {
|
||||
int getdamroll(object_t *o, lifeform_t *victim) {
|
||||
int dam;
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_DAM);
|
||||
|
@ -693,6 +784,25 @@ int getdamroll(object_t *o) {
|
|||
|
||||
if (dam < 0) dam = 0;
|
||||
|
||||
// special effects ?
|
||||
f = hasflag(o->flags, F_BALANCE);
|
||||
if (f) {
|
||||
lifeform_t *owner;
|
||||
owner = o->pile->owner;
|
||||
if (owner && victim) {
|
||||
float ratio;
|
||||
ratio = (float)owner->maxhp / (float)victim->maxhp;
|
||||
|
||||
if (ratio >= 1.25) {
|
||||
// heals instead!
|
||||
dam = -dam;
|
||||
} else if (ratio <= 0.75) {
|
||||
// extra dam!
|
||||
dam = (int) ((float)dam * ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dam;
|
||||
}
|
||||
|
||||
|
@ -846,7 +956,7 @@ void wepeffects(object_t *wep, cell_t *where) {
|
|||
f->known = B_KNOWN;
|
||||
}
|
||||
}
|
||||
} else if ((f->id == F_HITCONFER) && victim) {
|
||||
} else if ((f->id == F_HITCONFER) && victim && !isdead(victim)) {
|
||||
enum FLAG fid;
|
||||
int val0,val1;
|
||||
int min,max,howlong;
|
||||
|
@ -876,6 +986,44 @@ void wepeffects(object_t *wep, cell_t *where) {
|
|||
}
|
||||
addtempflag(victim->flags, fid, val0, val1, NA, NULL, howlong);
|
||||
}
|
||||
} else if ((f->id == F_REVENGE) && victim && !isdead(victim)) {
|
||||
lifeform_t *owner;
|
||||
owner = wep->pile->owner;
|
||||
if (owner && victim) {
|
||||
float ratio;
|
||||
float dampct;
|
||||
int maxdam;
|
||||
int extradam;
|
||||
// figure out hp percentage
|
||||
ratio = 1.0 - ((float)owner->hp / (float)owner->maxhp);
|
||||
dampct = (ratio * 100); // ie. lower hp% = higher dampct
|
||||
|
||||
if (dampct >= 50) {
|
||||
getdamrange(wep->flags, NULL, &maxdam);
|
||||
extradam = (int)(dampct * (float)maxdam);
|
||||
if (extradam > 0) {
|
||||
char buf[BUFLEN];
|
||||
char obname[BUFLEN];
|
||||
char damstring[BUFLEN];
|
||||
char victimname[BUFLEN];
|
||||
getlfname(owner, buf);
|
||||
getlfname(victim, victimname);
|
||||
getobname(wep, obname, 1);
|
||||
|
||||
// announce
|
||||
if (isplayer(owner)) {
|
||||
msg("Your %s blasts %s!",noprefix(obname),victimname);
|
||||
f->known = B_TRUE;
|
||||
} else if (haslos(player, owner->cell)) {
|
||||
msg("%s%s %s blasts %s!",buf, getpossessive(buf),noprefix(obname),victimname);
|
||||
f->known = B_TRUE;
|
||||
}
|
||||
|
||||
sprintf(damstring, "%s%s blast of revenge",buf, getpossessive(buf));
|
||||
losehp(victim, extradam, DT_DIRECT, owner, damstring);
|
||||
}
|
||||
} // end if dampct > 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
9
attack.h
9
attack.h
|
@ -3,14 +3,15 @@
|
|||
int attackcell(lifeform_t *lf, cell_t *c);
|
||||
int attacklf(lifeform_t *lf, lifeform_t *victim);
|
||||
int attackob(lifeform_t *lf, object_t *o);
|
||||
const char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp);
|
||||
char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp);
|
||||
object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag);
|
||||
enum DAMTYPE getdamtype(object_t *wep);
|
||||
int getextradam(object_t *wep, unsigned int *dam, enum DAMTYPE *damtype);
|
||||
char *getkillverb(enum DAMTYPE damtype, int dam, int maxhp);
|
||||
int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype);
|
||||
char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp);
|
||||
void getdamrange(flagpile_t *fp, int *min, int *max);
|
||||
void getdamrangeunarmed(flag_t *f, int *min, int *max);
|
||||
float getdamreducepct(float armourrating);
|
||||
int getdamroll(object_t *o);
|
||||
int getdamroll(object_t *o, lifeform_t *victim);
|
||||
int getdamrollfromflag(flag_t *f);
|
||||
float getstrdammod(lifeform_t *lf);
|
||||
obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag);
|
||||
|
|
207
defs.h
207
defs.h
|
@ -28,7 +28,8 @@ enum ATTRIB {
|
|||
enum BURDENED {
|
||||
BR_NONE = 0,
|
||||
BR_BURDENED = 1,
|
||||
BR_OVERLOADED = 2,
|
||||
BR_STRAINED = 2,
|
||||
BR_OVERLOADED = 3,
|
||||
};
|
||||
|
||||
|
||||
|
@ -61,11 +62,15 @@ enum LFCONDITION {
|
|||
#define FROMOBACTIVATE (-9868)
|
||||
#define FROMMAT (-9867)
|
||||
#define FROMBLESSING (-9866)
|
||||
#define FROMOBMOD (-9865)
|
||||
|
||||
|
||||
#define IFKNOWN (-9772) // used by f_xxconfer. only confer a flag if item is known.
|
||||
#define IFACTIVE (-9771) // used by f_prodeuceslight. only does so if object is activated
|
||||
|
||||
#define IFMONSTER (-9769) // used in v2 of f_ifpct job flags
|
||||
#define IFPLAYER (-9768) // used in v2 of f_ifpct job flags
|
||||
|
||||
#define ANYROOM (-9770)
|
||||
|
||||
#define TICK_INTERVAL (20)
|
||||
|
@ -97,6 +102,7 @@ enum LFCONDITION {
|
|||
|
||||
#define MAXRANDOMOBCANDIDATES 100
|
||||
#define MAXRANDOMLFCANDIDATES 100
|
||||
#define MAXCANDIDATES 50
|
||||
|
||||
//#define MAX_MAPW 80
|
||||
//#define MAX_MAPH 50
|
||||
|
@ -121,7 +127,8 @@ enum LFCONDITION {
|
|||
//#define DEF_SPARSENESS 14
|
||||
#define DEF_SPARSENESS 20
|
||||
//#define DEF_SPARSENESS 0
|
||||
#define DEF_LOOPPCT 70
|
||||
//#define DEF_LOOPPCT 70
|
||||
#define DEF_LOOPPCT 85
|
||||
//#define DEF_LOOPPCT 0
|
||||
#define MINROOMS 5
|
||||
#define MAXROOMS 10
|
||||
|
@ -145,6 +152,8 @@ enum LFCONDITION {
|
|||
#define AO_EQUIPPEDARMOUR 128
|
||||
#define AO_WEILDABLE 256
|
||||
#define AO_SPECIFIED 512
|
||||
#define AO_READABLE 1024
|
||||
#define AO_ARMOUR 2048
|
||||
|
||||
// askcoords target types
|
||||
#define TT_NONE 0
|
||||
|
@ -179,6 +188,7 @@ enum LFCONDITION {
|
|||
// speed settings (lower is faster)
|
||||
#define SPEED_ATTACK SP_NORMAL
|
||||
#define SPEED_DEAD 50
|
||||
#define SPEED_ACTION SP_NORMAL
|
||||
#define SPEED_MOVE SP_NORMAL
|
||||
#define SPEED_DROP SP_FAST
|
||||
#define SPEED_PICKUP SP_FAST
|
||||
|
@ -217,6 +227,7 @@ enum LFCONDITION {
|
|||
// altitude directions
|
||||
#define D_UP 12
|
||||
#define D_DOWN 13
|
||||
#define D_IN 14
|
||||
|
||||
|
||||
|
||||
|
@ -286,6 +297,7 @@ enum IQBRACKET {
|
|||
|
||||
// damage type
|
||||
enum DAMTYPE {
|
||||
DT_ALL = -1,
|
||||
DT_PIERCE = 0,
|
||||
DT_SLASH = 1,
|
||||
DT_FIRE = 2,
|
||||
|
@ -318,6 +330,7 @@ enum OBCLASS {
|
|||
OC_RING,
|
||||
OC_SCROLL,
|
||||
OC_POTION,
|
||||
OC_WAND,
|
||||
OC_FOOD,
|
||||
OC_CORPSE,
|
||||
OC_ROCK,
|
||||
|
@ -327,6 +340,7 @@ enum OBCLASS {
|
|||
OC_ABILITY,
|
||||
OC_EFFECT,
|
||||
OC_DFEATURE,
|
||||
OC_BOOK,
|
||||
OC_NULL = -999
|
||||
};
|
||||
|
||||
|
@ -358,18 +372,25 @@ enum RACE {
|
|||
R_NONE, R_RANDOM,
|
||||
R_HUMAN,
|
||||
// monsters
|
||||
R_BUGBEAR,
|
||||
R_EYEBAT,
|
||||
R_GIANT,
|
||||
R_GNOLL,
|
||||
R_GOBLIN,
|
||||
R_GOBLINGUARD,
|
||||
R_GOBLINCHAMP,
|
||||
R_HOBGOBLIN,
|
||||
R_LIZARDMAN,
|
||||
R_LURKINGHORROR,
|
||||
R_OGRE,
|
||||
R_ORC,
|
||||
R_ORK,
|
||||
R_POLTERGEIST,
|
||||
R_SHADOWCAT,
|
||||
R_SLIME,
|
||||
R_SPRITEFIRE,
|
||||
R_TROLL,
|
||||
R_LURKINGHORROR,
|
||||
R_XAT,
|
||||
// small animals
|
||||
R_BAT,
|
||||
R_NEWT,
|
||||
|
@ -397,6 +418,7 @@ enum JOB {
|
|||
J_COMMANDO,
|
||||
J_PLUMBER,
|
||||
J_PRINCE,
|
||||
J_WIZARD,
|
||||
};
|
||||
|
||||
// Object Materials
|
||||
|
@ -437,6 +459,7 @@ enum OBTYPE {
|
|||
OT_STAIRSDOWN,
|
||||
OT_STAIRSUP,
|
||||
OT_VENDINGMACHINE,
|
||||
OT_PORTAL,
|
||||
// rocks
|
||||
OT_GOLD,
|
||||
OT_STONE,
|
||||
|
@ -454,6 +477,9 @@ enum OBTYPE {
|
|||
OT_BREADFRESH,
|
||||
OT_CHOCOLATE,
|
||||
// corpses
|
||||
OT_CORPSE,
|
||||
OT_HEAD,
|
||||
/*
|
||||
OT_CORPSEEYEBAT,
|
||||
OT_CORPSEBAT,
|
||||
OT_CORPSEFLY,
|
||||
|
@ -466,6 +492,7 @@ enum OBTYPE {
|
|||
OT_CORPSERODENT,
|
||||
OT_CORPSETROLL,
|
||||
OT_CORPSEWOLF,
|
||||
*/
|
||||
// potions
|
||||
OT_POT_ACID,
|
||||
OT_POT_ACROBATICS,
|
||||
|
@ -473,6 +500,7 @@ enum OBTYPE {
|
|||
OT_POT_COMPETENCE,
|
||||
OT_POT_ELEMENTENDURE,
|
||||
OT_POT_ELEMENTIMMUNE,
|
||||
OT_POT_ETHEREALNESS,
|
||||
OT_POT_GASEOUSFORM,
|
||||
OT_POT_HEALING,
|
||||
OT_POT_HEALINGMIN,
|
||||
|
@ -491,30 +519,79 @@ enum OBTYPE {
|
|||
OT_SCR_CREATEMONSTER,
|
||||
OT_SCR_DETECTAURA,
|
||||
OT_SCR_DETECTLIFE,
|
||||
OT_SCR_FIREBALL,
|
||||
OT_SCR_DETECTMAGIC,
|
||||
OT_SCR_FLAMEPILLAR,
|
||||
OT_SCR_IDENTIFY,
|
||||
OT_SCR_KNOCK,
|
||||
OT_SCR_LIGHT,
|
||||
OT_SCR_MAPPING,
|
||||
OT_SCR_MINDSCAN,
|
||||
OT_SCR_ENCHANT,
|
||||
OT_SCR_FREEZEOB,
|
||||
OT_SCR_REMOVECURSE,
|
||||
OT_SCR_TELEPORTRND,
|
||||
OT_SCR_TURNUNDEAD,
|
||||
OT_SCR_WISH,
|
||||
// SPELLBOOKS
|
||||
// allomancy can't be learned from books
|
||||
// -- death
|
||||
OT_SB_INFINITEDEATH,
|
||||
OT_SB_WEAKEN,
|
||||
// -- divination
|
||||
OT_SB_DETECTAURA,
|
||||
OT_SB_DETECTLIFE,
|
||||
OT_SB_IDENTIFY,
|
||||
OT_SB_MAPPING,
|
||||
// -- elemental
|
||||
OT_SB_FIREDART,
|
||||
OT_SB_CONECOLD,
|
||||
OT_SB_FIREBALL,
|
||||
OT_SB_FLAMEPILLAR,
|
||||
// -- gravity
|
||||
OT_SB_GRAVBOOST,
|
||||
OT_SB_HASTE,
|
||||
OT_SB_SLOW,
|
||||
// -- life
|
||||
OT_SB_HEALING,
|
||||
OT_SB_HEALINGMIN,
|
||||
OT_SB_TURNUNDEAD,
|
||||
// -- mental
|
||||
OT_SB_MINDSCAN,
|
||||
OT_SB_TELEKINESIS,
|
||||
// -- modification
|
||||
OT_SB_FREEZEOB,
|
||||
OT_SB_GASEOUSFORM,
|
||||
OT_SB_KNOCK,
|
||||
OT_SB_INSCRIBE,
|
||||
OT_SB_LIGHT,
|
||||
OT_SB_PASSWALL,
|
||||
OT_SB_POLYMORPH,
|
||||
OT_SB_POLYMORPHRND,
|
||||
// -- summoning
|
||||
OT_SB_CREATEMONSTER,
|
||||
// -- translocation
|
||||
OT_SB_BLINK,
|
||||
OT_SB_DISPERSAL,
|
||||
OT_SB_GATE,
|
||||
OT_SB_TELEPORT,
|
||||
OT_SB_TELEPORTRND,
|
||||
// -- wild can't be learned from books
|
||||
// spells
|
||||
// -- allomancy
|
||||
OT_S_ABSORBMETAL,
|
||||
OT_S_ACCELMETAL,
|
||||
OT_S_ANIMATEMETAL,
|
||||
OT_S_DETECTMETAL,
|
||||
OT_S_DETONATE,
|
||||
OT_S_EXPLODEMETAL,
|
||||
OT_S_PULLMETAL,
|
||||
OT_S_MAGSHIELD,
|
||||
OT_S_METALHEAL,
|
||||
// -- death
|
||||
OT_S_INFINITEDEATH,
|
||||
OT_S_WEAKEN,
|
||||
// -- divination
|
||||
OT_S_DETECTAURA,
|
||||
OT_S_DETECTLIFE,
|
||||
OT_S_DETECTMAGIC,
|
||||
OT_S_IDENTIFY,
|
||||
OT_S_MAPPING,
|
||||
// -- elemental
|
||||
|
@ -534,28 +611,48 @@ enum OBTYPE {
|
|||
OT_S_MINDSCAN,
|
||||
OT_S_TELEKINESIS,
|
||||
// -- modification
|
||||
OT_S_ENCHANT,
|
||||
OT_S_FREEZEOB,
|
||||
OT_S_GASEOUSFORM,
|
||||
OT_S_INSCRIBE,
|
||||
OT_S_KNOCK,
|
||||
OT_S_LIGHT,
|
||||
OT_S_PASSWALL,
|
||||
OT_S_POLYMORPH,
|
||||
OT_S_POLYMORPHRND,
|
||||
// -- summoning
|
||||
OT_S_CREATEMONSTER,
|
||||
// -- translocation
|
||||
OT_S_BLINK,
|
||||
OT_S_DISPERSAL,
|
||||
OT_S_LEVTELEPORT,
|
||||
OT_S_GATE,
|
||||
OT_S_TELEPORT,
|
||||
OT_S_TELEPORTRND,
|
||||
// -- wild
|
||||
OT_S_MANASPIKE,
|
||||
OT_S_DETONATE,
|
||||
OT_S_ENERGYBOLT,
|
||||
OT_S_ENERGYBLAST,
|
||||
OT_S_FLASH,
|
||||
// -- divine powers
|
||||
OT_S_WISH,
|
||||
OT_S_GIFT,
|
||||
// abilities
|
||||
OT_A_JUMP,
|
||||
OT_A_SPRINT,
|
||||
OT_A_DEBUG,
|
||||
OT_A_EMPLOY,
|
||||
// wands
|
||||
OT_WAND_COLD,
|
||||
OT_WAND_DETONATION,
|
||||
OT_WAND_FIRE,
|
||||
OT_WAND_FIREBALL,
|
||||
OT_WAND_HASTE,
|
||||
OT_WAND_KNOCK,
|
||||
OT_WAND_LIGHT,
|
||||
OT_WAND_POLYMORPH,
|
||||
OT_WAND_SLOW,
|
||||
OT_WAND_WEAKNESS,
|
||||
// tech/tools
|
||||
OT_BLINDFOLD,
|
||||
OT_POCKETWATCH,
|
||||
|
@ -586,6 +683,7 @@ enum OBTYPE {
|
|||
OT_BROKENGLASS,
|
||||
OT_ICECHUNK,
|
||||
OT_PUDDLEWATER,
|
||||
OT_PUDDLEWATERL,
|
||||
OT_SLIMEPOOL,
|
||||
OT_VOMITPOOL,
|
||||
OT_BLOODSTAIN,
|
||||
|
@ -607,9 +705,12 @@ enum OBTYPE {
|
|||
OT_OVERALLS,
|
||||
OT_COTTONSHIRT,
|
||||
OT_SILKSHIRT,
|
||||
OT_ROBE,
|
||||
OT_VELVETROBE,
|
||||
// armour - shoulders
|
||||
OT_CLOAK,
|
||||
OT_VELVETROBE,
|
||||
// armour - waist
|
||||
OT_BELTLEATHER,
|
||||
// armour - legs
|
||||
OT_CLOTHTROUSERS,
|
||||
OT_RIDINGTROUSERS,
|
||||
|
@ -689,6 +790,8 @@ enum OBTYPE {
|
|||
OT_RUBBERBULLET,
|
||||
// holy weapons
|
||||
OT_HANDOFGOD,
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -701,16 +804,18 @@ enum BODYPART {
|
|||
BP_SHOULDERS,
|
||||
BP_BODY,
|
||||
BP_HANDS,
|
||||
BP_WAIST,
|
||||
BP_LEGS,
|
||||
BP_FEET,
|
||||
BP_RIGHTHAND,
|
||||
BP_LEFTHAND,
|
||||
};
|
||||
#define MAXBODYPARTS (11)
|
||||
#define MAXBODYPARTS (12)
|
||||
|
||||
// empty types
|
||||
#define WE_NOTSOLID 1
|
||||
#define WE_EMPTY 2
|
||||
#define WE_PORTAL 3
|
||||
|
||||
enum NOISETYPE {
|
||||
N_GETANGRY,
|
||||
|
@ -732,6 +837,7 @@ enum FLAG {
|
|||
F_NONE, // dummy flag
|
||||
// object flags
|
||||
F_DEAD, // object will be removed
|
||||
F_ENCHANTABLE, // object can get +1/-1 ect
|
||||
F_STACKABLE, // can stack multiple objects togethr
|
||||
F_NO_PLURAL, // this obname doesn't need an 's' for plurals (eg. gold, money)
|
||||
F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold)
|
||||
|
@ -767,6 +873,7 @@ enum FLAG {
|
|||
F_MATIMMUNE, // immune to damage from obs with material 'mat'
|
||||
F_DAMAGABLE, // this ob can be damaged via takedamage()
|
||||
F_TINTED, // when worn on eyes, protects against bright lights
|
||||
F_HASOBMOD, // has the object mod v0 (ie. OM_FLAMESTRIKE)
|
||||
F_HOLDCONFER, // gives flag v0+v1 when carried. v2 specifies if it must be id'd.
|
||||
F_EQUIPCONFER, // gives flag v0+v1 when weilded/worn. v2 specifies if it must be id'd.
|
||||
F_ACTIVATECONFER, // gives flag v0+v1 when activated. v2 specifies if it must be id'd.
|
||||
|
@ -789,8 +896,9 @@ enum FLAG {
|
|||
F_OPERONOFF, // operating this will just turn it on/off
|
||||
F_OPERUSECHARGE, // operating this will use 1 charge
|
||||
F_OPERNEEDTARGET, // need to ask for a target of type val0 when opering
|
||||
// v1 is target requirements (los/lof)
|
||||
// v0 is target requirements (los/lof)
|
||||
// text is prompt
|
||||
F_OPERNEEDDIR, // need to ask a direction when operating this. text is prompt
|
||||
// what can ou do with this object?
|
||||
F_EDIBLE, // you can eat this. val2 = nutrition. 100 = a meal
|
||||
// -1 means "nutrition is weight x abs(val1)"
|
||||
|
@ -804,17 +912,18 @@ enum FLAG {
|
|||
F_DOOR, // this object is a door - ie. can open it
|
||||
F_OPEN, // is this door open?
|
||||
F_LOCKED,// door is locked
|
||||
F_JAMMED, // is this door jammed?
|
||||
// stairs / teleporters / portals
|
||||
F_CLIMBABLE, // this is a stiarcase
|
||||
F_STAIRDIR, // val0 = direcion
|
||||
F_OPPOSITESTAIRS, // val0 = opposite kind of stairs
|
||||
F_MAPLINK, // val0 = map to link to
|
||||
F_MAPLINK, // val0 = map to link to. optional v1/v2 = x/y
|
||||
F_FLAMMABLE, // object will catch alight if burnt
|
||||
|
||||
// object mods/effects
|
||||
F_ONFIRE, // burning, also deals extra fire damage
|
||||
F_HEADLESS, // for corpses
|
||||
// weapon flags
|
||||
F_OBATTACKSPEED, // how long weapon takes to attack
|
||||
F_OBATTACKDELAY, // how long weapon takes to attack
|
||||
F_DAMTYPE, // val0 = damage type
|
||||
F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod
|
||||
F_ACCURACY, // 100 - val0 = penalty to tohit% (ie. higher is better)
|
||||
|
@ -824,6 +933,8 @@ enum FLAG {
|
|||
F_AMMOOB, // what object this weapon fires
|
||||
F_RANGE, // range of projectile firing weapon
|
||||
F_FLAMESTRIKE, // causes fires where you hit
|
||||
F_BALANCE, // heals target if their maxhp < your maxhp
|
||||
F_REVENGE, // causes damage based on your max hp
|
||||
// tech flags
|
||||
F_RNDCHARGES, // ob starts with between val0 and val1 charges
|
||||
// this will cause F_CHARGES to be filled in
|
||||
|
@ -842,6 +953,7 @@ enum FLAG {
|
|||
// if no damtype specified, it will be DT_DIRECT
|
||||
F_NOOBDAMTEXT, // don't anounce damage to this object
|
||||
F_NOOBDIETEXT, // don't anounce destruction of this object
|
||||
F_NODIECONVERTTEXT, // don't anounce when this object changes
|
||||
// scroll flags
|
||||
F_LINKSPELL, // val0 = spell this scroll will cast when read
|
||||
// ob identification flags
|
||||
|
@ -858,26 +970,31 @@ enum FLAG {
|
|||
F_AICASTATSELF, // hints for AI to cast spells
|
||||
F_AICASTANYWHERE, // hints for AI to cast spells
|
||||
// lifeform flags
|
||||
F_DEBUG, // debugging enabled
|
||||
F_ATTRMOD, // modify attribute val0 by val1. ie. 0=A_STR,1=-3
|
||||
F_ATTRSET, // forces attribute val0 to be val1. ie. 0=A_STR,1=18
|
||||
F_SIZE, // val0 = lf size (enum LFSIZE)
|
||||
F_RESTCOUNT, // val0 = how long you've been resting for
|
||||
F_RESTHEALTIME, // val0 = how long to rest before healing hp
|
||||
F_RESTHEALAMT, // val0 = how many hp to gain after resting x turns
|
||||
F_RESTHEALMPAMT, // val0 = how many MP to gain after resting x turns
|
||||
F_AUTOCMD, // val0 = how many times to repeat this
|
||||
F_LASTCMD, // text[0] = last command performed, v0/1 = x/y of cell, v2=various
|
||||
F_STARTOB, // val0 = %chance of starting with it, text = ob name
|
||||
// val1,2 = min/max amounts. if NA, min=max=1.
|
||||
F_STARTOBDT, // val0 = %chance of starting with damtype val1
|
||||
F_STARTOBCLASS, // val0 = %chance of starting with obclass val1
|
||||
F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid
|
||||
F_STARTIQ, // val0 = start iq bracket (ie. IQ_GENIUS)
|
||||
F_STARTDEX, // val0 = start dex bracket (ie. DEX_xxx)
|
||||
F_STARTSTR, // val0 = start str bracket (ie. STR_STRONG)
|
||||
F_CORPSETYPE, // text field specifies what corpse obtype to leave
|
||||
F_NOCORPSE, // monster's body crumbles to dust after death
|
||||
F_UNARMEDSPEED, // how long this race takes to attack
|
||||
F_VISRANGE, // how far you can see (in the light)
|
||||
F_VISRANGEMOD, // modifications to visrange
|
||||
F_GUNTARGET, // current projectile weapon target
|
||||
F_CASTINGSPELL, // set while the player is casting a spell
|
||||
// v0 is spell id
|
||||
// MONSTER AI FLAGS
|
||||
F_HOSTILE, // lf will attack the player if in sight
|
||||
F_FRIENDLY, // lf will attack all non-players if in sight
|
||||
|
@ -900,7 +1017,9 @@ enum FLAG {
|
|||
// eg. "shouts^a shout"
|
||||
F_SPELLCASTTEXT, // text is announcement for spellcast
|
||||
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
|
||||
F_BEHEADED, // use special corpse drop code
|
||||
F_MOVESPEED, // override default move speed
|
||||
F_ACTIONSPEED, // override default action speed
|
||||
F_SPELLSPEED, // override default spellcast speed (ie. movespeed)
|
||||
F_RARITY, // val[0] = habitat, val[1] = rarity
|
||||
F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max
|
||||
|
@ -908,7 +1027,7 @@ enum FLAG {
|
|||
F_MPDICE, // val0: # d4 to roll for maxmp per level. val1: +xx
|
||||
F_JOB, // val0 = player's class/job
|
||||
F_NAME, // text = player's name
|
||||
F_XPVAL, // how much xp this is worth
|
||||
F_XPMOD, // add/subtract this much from calculated xpval
|
||||
F_BLOODOB, // text = type of object to drop for blood
|
||||
F_OBESE, // double base weight for race!
|
||||
F_ORIGRACE, // original player race (if you polymorphed)
|
||||
|
@ -923,22 +1042,29 @@ enum FLAG {
|
|||
F_NOPACK, // this race cannot hold objects
|
||||
F_NOSPELLS, // this race cannot cast spells
|
||||
F_INDUCEFEAR, // causes fear when you attack it
|
||||
F_AUTOCREATEOB, // produces obtype 'text' wherever it walks, v0=radius
|
||||
// (only if ob of that type not already there)
|
||||
// INTRINSICS
|
||||
F_BLIND, // cannot see anything
|
||||
F_CANCAST, // can cast the spell val0 (need MP)
|
||||
F_CANWILL, // can cast the spell val0 without using MP
|
||||
F_DETECTAURAS, // autodetect bless/curse
|
||||
F_DETECTLIFE, // autodetect nearby lifeforms
|
||||
F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0
|
||||
F_DETECTMAGIC, // autodetect magic/special objects
|
||||
F_DETECTMETAL, // autodetect nearby metal
|
||||
F_EXTRAINFO, // knows extra info
|
||||
F_FLYING, // lf is flying
|
||||
F_FASTACT, // modifier for action speed
|
||||
F_FASTMOVE, // modifier for move speed
|
||||
F_FOODPOISONED, // has food poisoning
|
||||
F_FREEZINGTOUCH,// next thing touched turns to ice!
|
||||
F_GRAVBOOSTED,// cannot walk or throw stuff
|
||||
F_PARALYZED,// cannot do anything
|
||||
F_FROZEN, // made of ice
|
||||
F_INVULNERABLE,// immune to most damage
|
||||
F_LEVITATING, // like flying but uncontrolled
|
||||
F_MAGSHIELD,// magnetic shield
|
||||
F_NONCORPOREAL,// can walk through walls
|
||||
F_OMNIPOTENT, // knows extra info
|
||||
F_PHOTOMEM, // you don't forget your surroundings
|
||||
F_REGENERATES, // regenerate HP at val0 per turn
|
||||
|
@ -949,8 +1075,12 @@ enum FLAG {
|
|||
// (but not for obs in pack)
|
||||
// if val2 is true, will only make light if ob
|
||||
// is activated!
|
||||
F_SLOWACT, // modifier for action speed
|
||||
F_SLOWMOVE, // modifier for move speed
|
||||
F_XRAYVIS, //val0=num of walls we can see through
|
||||
F_CANSEETHROUGHMAT, //val0=kind of material you can see through
|
||||
F_SPRINTING, // you are sprinting
|
||||
F_TIRED, // you are too tired to sprint
|
||||
// COMBAT
|
||||
F_HASATTACK, // objecttype id to use when attacking unarmed
|
||||
// if val0-3 are filled in, they override the object's
|
||||
|
@ -964,6 +1094,11 @@ enum FLAG {
|
|||
// nutrition
|
||||
F_HUNGER, // val0 = hunger, higher = hungrier
|
||||
|
||||
// for jobs
|
||||
F_IFPCT, // only add the NEXT job flag if rnd(1,100) <= v0.
|
||||
// if v2=IFMONSTER, also only add the next one for non-players
|
||||
// if v2=IFPLAYER, also only add the next one for players
|
||||
|
||||
//
|
||||
F_NULL = -1
|
||||
};
|
||||
|
@ -1063,6 +1198,8 @@ enum ERROR {
|
|||
E_NOAMMO = 25,
|
||||
E_GRAVBOOSTED = 26,
|
||||
E_NOMP = 27,
|
||||
E_AVOIDOB = 28,
|
||||
E_FROZEN = 29,
|
||||
};
|
||||
|
||||
typedef struct map_s {
|
||||
|
@ -1160,6 +1297,9 @@ typedef struct lifeform_s {
|
|||
int nlos;
|
||||
cell_t **los;
|
||||
|
||||
// set to TRUE after lf has being created
|
||||
int born;
|
||||
|
||||
// for ai movement - don't need to save.
|
||||
struct cell_s *ignorecell;
|
||||
|
||||
|
@ -1263,6 +1403,36 @@ typedef struct object_s {
|
|||
struct object_s *next, *prev;
|
||||
} object_t;
|
||||
|
||||
enum OBMOD {
|
||||
OM_BALANCE,
|
||||
OM_DEXTERITY,
|
||||
OM_FEEBLENESS,
|
||||
OM_FLIGHT,
|
||||
OM_GIANTSTRENGTH,
|
||||
OM_INTELLIGENCE,
|
||||
OM_KNOWLEDGE,
|
||||
OM_LEVITATION,
|
||||
OM_MAGRESIST,
|
||||
OM_PYROMANIA,
|
||||
OM_REVENGE,
|
||||
OM_SLOTH,
|
||||
OM_SPEED,
|
||||
OM_STRENGTH,
|
||||
OM_SWIFTNESS,
|
||||
OM_TELEKINESIS,
|
||||
OM_TELEPATHY,
|
||||
OM_WEAKNESS,
|
||||
};
|
||||
|
||||
typedef struct obmod_s {
|
||||
enum OBMOD id;
|
||||
char *description;
|
||||
char *suffix;
|
||||
flagpile_t *flags;
|
||||
enum BODYPART bp;
|
||||
struct obmod_s *next, *prev;
|
||||
} obmod_t;
|
||||
|
||||
typedef struct choice_s {
|
||||
char ch;
|
||||
char *text;
|
||||
|
@ -1273,8 +1443,11 @@ typedef struct choice_s {
|
|||
} choice_t;
|
||||
|
||||
|
||||
#define MAXPROMPTQUESTIONS 5
|
||||
typedef struct prompt_s {
|
||||
char *q1;
|
||||
char *q[MAXPROMPTQUESTIONS];
|
||||
int nqs;
|
||||
int whichq;
|
||||
void *result;
|
||||
choice_t choice[MAXCHOICES];
|
||||
int selection;
|
||||
|
|
|
@ -8,6 +8,7 @@ objects.c:
|
|||
remember to have spelllevle
|
||||
(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
|
||||
|
||||
spell.c:
|
||||
implement the effects
|
||||
|
|
81
flag.c
81
flag.c
|
@ -9,23 +9,27 @@
|
|||
#include "text.h"
|
||||
|
||||
extern int gamestarted;
|
||||
extern int needredraw;
|
||||
extern int statdirty;
|
||||
|
||||
flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text) {
|
||||
return addflag_real(fp, id, val1, val2, val3, text, PERMENANT, B_KNOWN);
|
||||
return addflag_real(fp, id, val1, val2, val3, text, PERMENANT, B_KNOWN, -1);
|
||||
}
|
||||
flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft) {
|
||||
return addflag_real(fp, id, val1, val2, val3, text, timeleft, B_KNOWN);
|
||||
return addflag_real(fp, id, val1, val2, val3, text, timeleft, B_KNOWN, -1);
|
||||
}
|
||||
|
||||
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known) {
|
||||
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid) {
|
||||
flag_t *f;
|
||||
int i;
|
||||
int doredraw = B_FALSE;
|
||||
|
||||
// identified things mean all new flags are autmaticlaly known.
|
||||
if (hasflag(fp, F_IDENTIFIED)) {
|
||||
known = B_KNOWN;
|
||||
}
|
||||
|
||||
|
||||
// certain flags stack...
|
||||
if (flagstacks(id)) {
|
||||
f = hasflag(fp, id);
|
||||
|
@ -58,7 +62,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
f->id = id;
|
||||
f->lifetime = lifetime;
|
||||
f->known = known;
|
||||
f->obfrom = -1;
|
||||
f->obfrom = obfromid;
|
||||
|
||||
// first blank values
|
||||
for (i = 0; i < 3; i++) {
|
||||
|
@ -89,12 +93,38 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
if (f->pile->owner) {
|
||||
if (announceflaggain(f->pile->owner, f)) {
|
||||
f->known = B_TRUE;
|
||||
if (f->obfrom) { // ooooooo it's getting -1 ?!?!?!?
|
||||
object_t *ob;
|
||||
|
||||
ob = findobbyid(f->pile->owner->pack, f->obfrom);
|
||||
if (ob) {
|
||||
flag_t *f2;
|
||||
switch (f->lifetime) {
|
||||
case FROMOBEQUIP:
|
||||
f2 = hasflagval(ob->flags, F_EQUIPCONFER, f->id, NA, NA, NULL);
|
||||
break;
|
||||
case FROMOBHOLD:
|
||||
f2 = hasflagval(ob->flags, F_HOLDCONFER, f->id, NA, NA, NULL);
|
||||
break;
|
||||
case FROMOBACTIVATE:
|
||||
f2 = hasflagval(ob->flags, F_ACTIVATECONFER, f->id, NA, NA, NULL);
|
||||
break;
|
||||
}
|
||||
if (f2) {
|
||||
f2->known = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isplayer(f->pile->owner)) {
|
||||
switch (f->id) {
|
||||
case F_BLIND:
|
||||
case F_SEEINDARK:
|
||||
drawscreen();
|
||||
case F_SPRINTING:
|
||||
case F_TIRED:
|
||||
case F_FASTMOVE:
|
||||
case F_SLOWMOVE:
|
||||
doredraw = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -107,6 +137,11 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
}
|
||||
}
|
||||
|
||||
if (gamestarted && doredraw) {
|
||||
statdirty = B_TRUE;
|
||||
needredraw = B_TRUE;
|
||||
drawscreen();
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
|
@ -125,7 +160,7 @@ void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) {
|
|||
flag_t *f;
|
||||
for (f = src->first ; f ; f = f->next) {
|
||||
addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text,
|
||||
(lifetime == NA) ? f->lifetime : lifetime, f->known);
|
||||
(lifetime == NA) ? f->lifetime : lifetime, f->known, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +168,6 @@ int flagstacks(enum FLAG fid) {
|
|||
int res = B_FALSE;
|
||||
switch (fid) {
|
||||
case F_EVASION:
|
||||
case F_BONUS:
|
||||
res = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
|
@ -217,7 +251,7 @@ void killflagsofid(flagpile_t *fp, enum FLAG fid) {
|
|||
void killflag(flag_t *f) {
|
||||
flag_t *nextone, *lastone;
|
||||
lifeform_t *lf;
|
||||
int needredraw = B_FALSE;
|
||||
int doredraw = B_FALSE;
|
||||
|
||||
lf = f->pile->owner;
|
||||
|
||||
|
@ -225,7 +259,11 @@ void killflag(flag_t *f) {
|
|||
switch (f->id) {
|
||||
case F_BLIND:
|
||||
case F_SEEINDARK:
|
||||
needredraw = B_TRUE;
|
||||
case F_SPRINTING:
|
||||
case F_TIRED:
|
||||
case F_FASTMOVE:
|
||||
case F_SLOWMOVE:
|
||||
doredraw = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -246,6 +284,17 @@ void killflag(flag_t *f) {
|
|||
lf->polyrevert = B_TRUE;
|
||||
}
|
||||
|
||||
if (lf && (f->id == F_SPRINTING)) {
|
||||
int howlong;
|
||||
// you get tired when you finish sprinting
|
||||
|
||||
// TODO: change this based on
|
||||
// constitution
|
||||
// running skill
|
||||
howlong = 5;
|
||||
addtempflag(f->pile, F_TIRED, B_TRUE, NA, NA, NULL, howlong);
|
||||
}
|
||||
|
||||
// free mem
|
||||
|
||||
// remove from list
|
||||
|
@ -267,7 +316,9 @@ void killflag(flag_t *f) {
|
|||
lastone->next = nextone;
|
||||
}
|
||||
|
||||
if (gamestarted && needredraw) {
|
||||
if (gamestarted && doredraw) {
|
||||
statdirty = B_TRUE;
|
||||
needredraw = B_TRUE;
|
||||
drawscreen();
|
||||
}
|
||||
}
|
||||
|
@ -317,6 +368,16 @@ void timeeffectsflag(flag_t *f) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else if (f->lifetime == 2) {
|
||||
if (isplayer(f->pile->owner)) {
|
||||
switch (f->id) {
|
||||
case F_NONCORPOREAL:
|
||||
warn("You feel your body solidifying...");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (f->lifetime == 1) {
|
||||
// warn about certain flags......
|
||||
if (isplayer(f->pile->owner)) {
|
||||
|
|
2
flag.h
2
flag.h
|
@ -4,7 +4,7 @@
|
|||
// functions
|
||||
flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text);
|
||||
flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft);
|
||||
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known);
|
||||
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid);
|
||||
flagpile_t *addflagpile(lifeform_t *owner, object_t *o);
|
||||
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
|
||||
int flagstacks(enum FLAG fid);
|
||||
|
|
4
io.h
4
io.h
|
@ -3,6 +3,7 @@
|
|||
void addchoice(prompt_t *p, char ch, char *text, char *desc, void *data);
|
||||
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);
|
||||
void animradial(cell_t *src, int radius, char ch);
|
||||
//void announceob(enum OBTYPE oid);
|
||||
|
@ -13,7 +14,7 @@ void announceobflagloss(object_t *o, flag_t *f);
|
|||
object_t *askobject(obpile_t *op, char *title, int *count, int opts);
|
||||
object_t *askobjectwithflag(obpile_t *op, char *title, int *count, int opts, enum FLAG withflag);
|
||||
object_t *askobjectofclass(obpile_t *op, char *title, int *count, int opts, enum OBCLASS obclass);
|
||||
object_t *doaskobject(obpile_t *op, char *title, int *count, int opts, enum OBCLASS obclass, enum FLAG withflag);
|
||||
object_t *doaskobject(obpile_t *op, char *title, int *count, int opts, enum FLAG withflag, ...);
|
||||
int askobjectmulti(obpile_t *op, char *prompt, int opts);
|
||||
char askchar(char *prompt, char *validchars, char *def, int showchars);
|
||||
cell_t *askcoords(char *prompt, int targettype);
|
||||
|
@ -25,6 +26,7 @@ void clearmsg(void);
|
|||
void real_clearmsg(int force);
|
||||
void clearretobs(void);
|
||||
void cls(void);
|
||||
int contains(enum OBCLASS *array, int nargs, enum OBCLASS want);
|
||||
void describeob(object_t *o);
|
||||
void doattackcell(char dirch);
|
||||
void doclose(void);
|
||||
|
|
31
lf.h
31
lf.h
|
@ -4,15 +4,18 @@ lifeform_t *addlf(cell_t *cell, enum RACE rid, int level);
|
|||
lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller);
|
||||
job_t *addjob(enum JOB id, char *name);
|
||||
race_t *addrace(enum RACE id, char *name, float weight, char glyph, enum MATERIAL mat);
|
||||
void adjustdamlf(lifeform_t *lf, unsigned int *amt, enum DAMTYPE damtype);
|
||||
void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype);
|
||||
void autotarget(lifeform_t *lf);
|
||||
void autoweild(lifeform_t *lf);
|
||||
int appearsrandomly(enum RACE rid);
|
||||
void bleed(lifeform_t *lf);
|
||||
int calcxp(lifeform_t *lf);
|
||||
int calcxprace(enum RACE rid);
|
||||
int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost);
|
||||
int caneat(lifeform_t *lf, object_t *o);
|
||||
int canhear(lifeform_t *lf, cell_t *c);
|
||||
int canpickup(lifeform_t *lf, object_t *o);
|
||||
int cannotmove(lifeform_t *lf);
|
||||
int canpickup(lifeform_t *lf, object_t *o, int amt);
|
||||
int canpush(lifeform_t *lf, object_t *o, int dir);
|
||||
int canquaff(lifeform_t *lf, object_t *o);
|
||||
int canrest(lifeform_t *lf);
|
||||
|
@ -22,18 +25,22 @@ int cantakeoff(lifeform_t *lf, object_t *o);
|
|||
int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell);
|
||||
void die(lifeform_t *lf);
|
||||
void dumplf(void);
|
||||
void dumpxp(void);
|
||||
int eat(lifeform_t *lf, object_t *o);
|
||||
object_t *eyesshaded(lifeform_t *lf);
|
||||
void fightback(lifeform_t *lf, lifeform_t *attacker);
|
||||
job_t *findjob(enum JOB jobid);
|
||||
job_t *findjobbyname(char *name);
|
||||
lifeform_t *findlf(map_t *m, int lfid);
|
||||
race_t *findrace(enum RACE id);
|
||||
race_t *findracebyname(char *name);
|
||||
int flee(lifeform_t *lf);
|
||||
int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong);
|
||||
void gainhp(lifeform_t *lf, int amt);
|
||||
void gainlevel(lifeform_t *lf);
|
||||
void gainmp(lifeform_t *lf, int amt);
|
||||
void gainxp(lifeform_t *lf, long amt);
|
||||
int getactspeed(lifeform_t *lf);
|
||||
object_t *getarmour(lifeform_t *lf, enum BODYPART bp);
|
||||
int getarmourrating(lifeform_t *lf);
|
||||
int getattackspeed(lifeform_t *lf);
|
||||
|
@ -68,6 +75,7 @@ float getmaxpushweight(lifeform_t *lf);
|
|||
int getvisrange(lifeform_t *lf);
|
||||
int getmovespeed(lifeform_t *lf);
|
||||
char *getmoveverb(lifeform_t *lf);
|
||||
char *getmoveverbother(lifeform_t *lf);
|
||||
char *getlfname(lifeform_t *lf, char *buf);
|
||||
char *getlfnamea(lifeform_t *lf, char *buf);
|
||||
enum LFSIZE getlfsize(lifeform_t *lf);
|
||||
|
@ -85,7 +93,6 @@ enum STRBRACKET getstrname(int str, char *buf);
|
|||
enum DEXBRACKET getdexname(int dex, char *buf);
|
||||
enum IQBRACKET getiqname(int iq, char *buf);
|
||||
int getthrowspeed(int str);
|
||||
int getunarmedattackspeed(lifeform_t *lf);
|
||||
object_t *getweapon(lifeform_t *lf);
|
||||
long getxpforlev(int level);
|
||||
void givejob(lifeform_t *lf, enum JOB jobid);
|
||||
|
@ -105,6 +112,7 @@ int hasmr(lifeform_t *lf);
|
|||
void initjobs(void);
|
||||
void initrace(void);
|
||||
void interrupt(lifeform_t *lf);
|
||||
int isairborne(lifeform_t *lf);
|
||||
int isbleeding(lifeform_t *lf);
|
||||
int isblind(lifeform_t *lf);
|
||||
enum BURDENED isburdened(lifeform_t *lf);
|
||||
|
@ -112,22 +120,25 @@ int isdead(lifeform_t *lf);
|
|||
int isfleeing(lifeform_t *lf);
|
||||
int isfreebp(lifeform_t *lf, enum BODYPART bp);
|
||||
int isgenius(lifeform_t *lf);
|
||||
int isingunrange(lifeform_t *lf, cell_t *where);
|
||||
int isimmobile(lifeform_t *lf);
|
||||
flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt);
|
||||
int isingunrange(lifeform_t *lf, cell_t *where);
|
||||
int ispeaceful(lifeform_t *lf);
|
||||
int isplayer(lifeform_t *lf);
|
||||
int ispolymorphed(lifeform_t *lf);
|
||||
flag_t *isresistantto(flagpile_t *fp, enum DAMTYPE dt);
|
||||
flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt);
|
||||
void killjob(job_t *job);
|
||||
void killlf(lifeform_t *lf);
|
||||
void killrace(race_t *race);
|
||||
int losehp(lifeform_t *lf, unsigned int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc);
|
||||
int losehp_real(lifeform_t *lf, unsigned int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam);
|
||||
int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc);
|
||||
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam);
|
||||
void makenoise(lifeform_t *lf, enum NOISETYPE nid);
|
||||
void maycastspellschool(flagpile_t *fp, enum SPELLSCHOOL ss);
|
||||
void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how);
|
||||
int modattr(lifeform_t *lf, enum ATTRIB attr, int amt);
|
||||
void modhunger(lifeform_t *lf, int amt);
|
||||
void outfitlf(lifeform_t *lf);
|
||||
int pickup(lifeform_t *lf, object_t *what, int howmany);
|
||||
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground);
|
||||
void precalclos(lifeform_t *lf);
|
||||
int push(lifeform_t *lf, object_t *o, int dir);
|
||||
void relinklf(lifeform_t *src, map_t *dst);
|
||||
|
@ -136,7 +147,8 @@ void startresting(lifeform_t *lf);
|
|||
int rolldex(enum DEXBRACKET bracket);
|
||||
int rolliq(enum IQBRACKET bracket);
|
||||
int rollstr(enum STRBRACKET bracket);
|
||||
int savingthrow(lifeform_t *lf, enum ATTRIB attr);
|
||||
int rollstat(lifeform_t *lf, enum ATTRIB attr);
|
||||
int savingthrow(lifeform_t *lf, enum ATTRIB attr, int mod);
|
||||
int scare(lifeform_t *lf, lifeform_t *scarer, int howlong);
|
||||
int setammo(lifeform_t *lf, object_t *o);
|
||||
void setattr(lifeform_t *lf, enum ATTRIB attr, int val);
|
||||
|
@ -147,6 +159,7 @@ int shoot(lifeform_t *lf);
|
|||
void sortlf(map_t *map, lifeform_t *lf);
|
||||
void stopresting(lifeform_t *lf);
|
||||
void stoprunning(lifeform_t *lf);
|
||||
int testammo(lifeform_t *lf, object_t *o);
|
||||
int takeoff(lifeform_t *lf, object_t *o);
|
||||
void taketime(lifeform_t *lf, long howlong);
|
||||
int throwat(lifeform_t *thrower, object_t *o, cell_t *where);
|
||||
|
|
51
map.c
51
map.c
|
@ -33,6 +33,7 @@ cell_t *addcell(map_t *m, int x, int y) {
|
|||
cell->roomid = -1;
|
||||
cell->lit = B_FALSE;
|
||||
cell->writing = NULL;
|
||||
cell->known = B_FALSE;
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
@ -72,9 +73,10 @@ map_t *addmap(void) {
|
|||
}
|
||||
|
||||
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid) {
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok) {
|
||||
lifeform_t *lf = NULL;
|
||||
race_t *r;
|
||||
int db = B_FALSE;
|
||||
|
||||
// ie. don't create mosnters on closed doors!
|
||||
if (!cellwalkable(NULL, c, NULL)) {
|
||||
|
@ -88,7 +90,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid) {
|
|||
}
|
||||
assert(r);
|
||||
|
||||
dblog("adding rand lf %s to cell %d,%d",r->name,c->x,c->y);
|
||||
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));
|
||||
|
@ -96,6 +98,17 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid) {
|
|||
if (lf) {
|
||||
int amt;
|
||||
flag_t *f;
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// appears in groups?
|
||||
f = hasflag(lf->flags, F_NUMAPPEAR);
|
||||
if (f) {
|
||||
|
@ -124,13 +137,14 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid) {
|
|||
|
||||
void addrandomob(cell_t *c) {
|
||||
char buf[BUFLEN];
|
||||
int db = B_FALSE;
|
||||
|
||||
if (c->type->solid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getrandomob(c->map, buf)) {
|
||||
dblog("adding rand obj %s to cell %d,%d",buf,c->x,c->y);
|
||||
if (db) dblog("adding rand obj %s to cell %d,%d",buf,c->x,c->y);
|
||||
addob(c->obpile, buf);
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +157,7 @@ void addrandomthing(cell_t *c) {
|
|||
addrandomob(c);
|
||||
} else {
|
||||
// monster
|
||||
addmonster(c, R_RANDOM);
|
||||
addmonster(c, R_RANDOM, B_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,6 +513,7 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
|
|||
//int startdir,forcex,forcey,ntries;
|
||||
cell_t *cell, *c;
|
||||
object_t *o;
|
||||
int db = B_FALSE;
|
||||
|
||||
// parameters
|
||||
int turnpct = DEF_TURNPCT;
|
||||
|
@ -758,7 +773,14 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
|
|||
|
||||
o = addob(c->obpile, returnstairtype->name);
|
||||
if (parentmap) {
|
||||
addflag(o->flags, F_MAPLINK, parentmap->id, NA, NA, NULL);
|
||||
cell_t *parentstairs;
|
||||
objecttype_t *ot;
|
||||
ot = getoppositestairs(returnstairtype);
|
||||
// find stairs in parent map
|
||||
parentstairs = findobinmap(parentmap, ot->id);
|
||||
assert(parentstairs);
|
||||
// link stairs on new map to stairs on parent map
|
||||
addflag_real(o->flags, F_MAPLINK, parentmap->id, parentstairs->x, parentstairs->y, NULL, PERMENANT, B_UNKNOWN, -1);
|
||||
}
|
||||
|
||||
// add staircase continuing on (normally this will be down)
|
||||
|
@ -771,6 +793,7 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
|
|||
}
|
||||
ot = getoppositestairs(returnstairtype);
|
||||
addob(c->obpile, ot->name);
|
||||
// don't add F_MAPLINK yet - this will cocur when we use the stairs
|
||||
}
|
||||
|
||||
|
||||
|
@ -968,7 +991,7 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
|
|||
int n;
|
||||
int numpillars;
|
||||
numpillars = rnd(1,maxpillars);
|
||||
dblog("--> Will add %d pillars",numpillars);
|
||||
if (db) dblog("--> Will add %d pillars",numpillars);
|
||||
for (n = 0; n < numpillars;n++ ) {
|
||||
//dblog("----> Adding pillar %d/%d",n+1,numpillars);
|
||||
cell_t *c;
|
||||
|
@ -998,7 +1021,7 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
|
|||
} else {
|
||||
numobs = rnd(numobsmin,numobsmax);
|
||||
}
|
||||
dblog("--> Will add %d objects to room %d (of %d)",numobs,i,numrooms);
|
||||
if (db) dblog("--> Will add %d objects to room %d (of %d)",numobs,i,numrooms);
|
||||
for (n = 0 ; n < numobs; n++) {
|
||||
int ntries = 0;
|
||||
cell_t *c;
|
||||
|
@ -1044,7 +1067,7 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
|
|||
}
|
||||
}
|
||||
|
||||
dblog("Finished adding objects.");
|
||||
if (db) dblog("Finished adding objects.");
|
||||
|
||||
/*
|
||||
// some extra monsters in corridors
|
||||
|
@ -1681,6 +1704,12 @@ cell_t *getrandomadjcell(cell_t *c, int wantempty) {
|
|||
if (cellwalkable(NULL, new, NULL)) {
|
||||
return new;
|
||||
}
|
||||
} else if (wantempty == WE_PORTAL) {
|
||||
if (cellwalkable(NULL, new, NULL) && !hasenterableobject(new) ) {
|
||||
if (!hasobwithflag(new->obpile, F_DOOR)) {
|
||||
return new;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// always ok
|
||||
return new;
|
||||
|
@ -1764,6 +1793,11 @@ cell_t *getrandomroomcell(map_t *map, int roomid) {
|
|||
return c;
|
||||
}
|
||||
|
||||
object_t *hasenterableobject(cell_t *c) {
|
||||
return hasobwithflag(c->obpile, F_CLIMBABLE);
|
||||
}
|
||||
|
||||
|
||||
lifeform_t *haslf(cell_t *c) {
|
||||
if (c->lf && !isdead(c->lf)) {
|
||||
return c->lf;
|
||||
|
@ -1981,6 +2015,7 @@ void makelit(cell_t *c, int how) {
|
|||
} else if (c->lit != B_PERM) { // don't override permenant light with temp light!
|
||||
c->lit = how;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void makelitradius(cell_t *c, int radius, int how) {
|
||||
|
|
3
map.h
3
map.h
|
@ -2,7 +2,7 @@
|
|||
|
||||
cell_t *addcell(map_t *map, int x, int y);
|
||||
map_t *addmap(void);
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid);
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok);
|
||||
void addrandomob(cell_t *c);
|
||||
void addrandomthing(cell_t *c);
|
||||
int cellhaslos(cell_t *c1, cell_t *dest);
|
||||
|
@ -35,6 +35,7 @@ cell_t *getrandomcell(map_t *map);
|
|||
cell_t *getrandomcelloftype(map_t *map, int id);
|
||||
int getrandomdir(int dirtype);
|
||||
cell_t *getrandomroomcell(map_t *map, int roomid);
|
||||
object_t *hasenterableobject(cell_t *c);
|
||||
lifeform_t *haslf(cell_t *c);
|
||||
int hasobject(cell_t *c);
|
||||
int isadjacent(cell_t *src, cell_t *dst);
|
||||
|
|
196
move.c
196
move.c
|
@ -16,6 +16,7 @@
|
|||
extern lifeform_t *player;
|
||||
|
||||
extern int statdirty;
|
||||
extern int needredraw;
|
||||
|
||||
extern enum ERROR reason;
|
||||
extern void *rdata;
|
||||
|
@ -47,6 +48,11 @@ int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
if (isburdened(lf) >= BR_OVERLOADED) {
|
||||
if (error) *error = E_TOOHEAVY;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// TODO: check if we are burdened, paralyzed, etc
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
|
||||
|
@ -54,6 +60,47 @@ int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
|||
}
|
||||
|
||||
|
||||
// will populate rdata
|
||||
int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
|
||||
enum IQBRACKET iq;
|
||||
// default
|
||||
if (error) {
|
||||
*error = E_OK;
|
||||
rdata = NULL;
|
||||
}
|
||||
|
||||
// check for dangerous objects
|
||||
iq = getiqname(getattr(lf, A_IQ), NULL);
|
||||
if (iq >= IQ_AVERAGE) {
|
||||
flag_t *f;
|
||||
object_t *o;
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
// don't walk on sharp objects without boots
|
||||
if (hasflag(o->flags, F_SHARP)) {
|
||||
if (!getequippedob(lf->pack, BP_FEET)) {
|
||||
if (error) {
|
||||
*error = E_AVOIDOB;
|
||||
rdata = o;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
f = hasflag(o->flags, F_WALKDAM);
|
||||
if (f) {
|
||||
// are we immune to this?
|
||||
if (!lfhasflagval(lf, F_DTIMMUNE, f->val[1], NA, NA, NULL)) {
|
||||
if (error) {
|
||||
*error = E_AVOIDOB;
|
||||
rdata = o;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
|
||||
object_t *o;
|
||||
// default
|
||||
|
@ -61,16 +108,28 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
|
|||
*error = E_OK;
|
||||
rdata = NULL;
|
||||
}
|
||||
if (!cell || cell->type->solid) {
|
||||
if (!cell) {
|
||||
if (error) *error = E_WALLINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
if (cell->type->solid) {
|
||||
if (lf && lfhasflag(lf, F_NONCORPOREAL)) {
|
||||
// ok
|
||||
} else {
|
||||
if (error) *error = E_WALLINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
if (lf) {
|
||||
if ((lf->race->material->id != MT_GAS) &&
|
||||
(lf->race->material->id != MT_SLIME)) {
|
||||
if ((lf->race->material->id == MT_GAS) ||
|
||||
(lf->race->material->id == MT_SLIME)) {
|
||||
// ok
|
||||
} else if (lfhasflag(lf, F_NONCORPOREAL)) {
|
||||
// ok
|
||||
} else {
|
||||
rdata = o;
|
||||
if (error) *error = E_OBINWAY;
|
||||
return B_FALSE;
|
||||
|
@ -90,8 +149,6 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dorandommove(lifeform_t *lf, int badmovesok) {
|
||||
int dir;
|
||||
int tries = 0;
|
||||
|
@ -139,6 +196,7 @@ void dorandommove(lifeform_t *lf, int badmovesok) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
int getdiraway(cell_t *src, cell_t *dst, int wantcheck) {
|
||||
int d;
|
||||
cell_t *c;
|
||||
|
@ -280,7 +338,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
|
||||
|
||||
// check ground objects
|
||||
if (!lfhasflag(lf, F_FLYING)) {
|
||||
if (!isairborne(lf)) {
|
||||
for (o = newcell->obpile->first ; o ; o = nexto ) {
|
||||
nexto = o->next;
|
||||
f = hasflag(o->flags, F_SHARP);
|
||||
|
@ -341,10 +399,19 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
for (l = newcell->map->lf ; l ; l = l->next) {
|
||||
if (l != lf) {
|
||||
if (haslos(l, newcell)) {
|
||||
interrupt(lf);
|
||||
interrupt(l);
|
||||
if (isplayer(l)) {
|
||||
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_RESTING)) {
|
||||
char lfname2[BUFLEN];
|
||||
getlfname(lf, lfname);
|
||||
sprintf(lfname2, "%s",noprefix(lfname));
|
||||
msg("%s %s comes into view.",isvowel(lfname2[0]) ? "An" : "A", lfname2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return didmsg;
|
||||
}
|
||||
|
||||
|
@ -459,6 +526,11 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
return B_TRUE;
|
||||
} else {
|
||||
if (lf) {
|
||||
taketime(lf, getactspeed(lf));
|
||||
touch(lf, o);
|
||||
}
|
||||
|
||||
// locked?
|
||||
if (hasflag(o->flags, F_LOCKED)) {
|
||||
if (lf && isplayer(lf)) {
|
||||
|
@ -466,6 +538,22 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
return B_TRUE;
|
||||
} else {
|
||||
int openit = B_TRUE;
|
||||
f = hasflag(o->flags, F_JAMMED);
|
||||
if (f) {
|
||||
|
||||
f->val[0] --;
|
||||
// loosen a bit
|
||||
if (lf && isplayer(lf)) {
|
||||
msg("You yank on the door but it holds fast.");
|
||||
}
|
||||
if (f->val[0] <= 0) {
|
||||
killflag(f);
|
||||
}
|
||||
openit = B_FALSE; // don't open the door
|
||||
}
|
||||
if (openit) {
|
||||
cell_t *where;
|
||||
// open it
|
||||
addflag(o->flags, F_OPEN, B_TRUE, NA, NA, NULL);
|
||||
|
||||
|
@ -487,10 +575,15 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
msg("%s opens.",obname);
|
||||
}
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
|
||||
touch(lf, o);
|
||||
}
|
||||
where = getoblocation(o);
|
||||
if (player && haslos(player, where)) {
|
||||
needredraw = B_TRUE;
|
||||
drawscreen();
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,7 +649,7 @@ int closedoor(lifeform_t *lf, object_t *o) {
|
|||
msg("%s closes.",obname);
|
||||
}
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
taketime(lf, getactspeed(lf));
|
||||
touch(lf, o);
|
||||
}
|
||||
}
|
||||
|
@ -598,7 +691,7 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
|
|||
char buf[BUFLEN];
|
||||
getlfname(lf, buf);
|
||||
msg("%s %s pulled %s!", buf, isplayer(lf) ? "are" : "is",
|
||||
lfhasflag(lf, F_FLYING) ? "through the air" :
|
||||
isairborne(lf) ? "through the air" :
|
||||
"along the ground");
|
||||
}
|
||||
movelf(lf, dst);
|
||||
|
@ -610,16 +703,16 @@ int teleportto(lifeform_t *lf, cell_t *c) {
|
|||
char buf[BUFLEN];
|
||||
if (!isplayer(lf) && haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
msg("%s disappears in a puff of smoke!", buf);
|
||||
msg("%s disappears in a cloud of smoke!", buf);
|
||||
}
|
||||
addob(lf->cell->obpile, "puff of smoke");
|
||||
movelf(lf, c);
|
||||
addob(lf->cell->obpile, "cloud of smoke");
|
||||
movelf(lf, c);
|
||||
// addob(lf->cell->obpile, "cloud of smoke");
|
||||
if (isplayer(lf)) {
|
||||
msg("Suddenly, your surroundings appear different!");
|
||||
} else if (haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
msg("%s appears in a cloud of smoke!", buf);
|
||||
msg("%s appears!", buf);
|
||||
}
|
||||
// show any objects here, just like if we moved.
|
||||
// BUT don't let dolook() clear the msg bar if there are
|
||||
|
@ -638,6 +731,31 @@ int trymove(lifeform_t *lf, int dir) {
|
|||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
if (canandwillmove(lf, dir, &errcode)) {
|
||||
object_t *o;
|
||||
|
||||
// check for cursed objects + animals
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
if (!isplayer(lf)) {
|
||||
if (o->blessed == B_CURSED) {
|
||||
if (lfhasflag(lf, F_ANIMAL)) {
|
||||
if (!isairborne(lf)) {
|
||||
if (haslos(player, lf->cell)) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(lf,lfname);
|
||||
getobname(o, buf, o->amt);
|
||||
msg("%s shies away from %s!", lfname, buf);
|
||||
o->blessknown = B_TRUE;
|
||||
|
||||
taketime(lf, getmovespeed(lf));
|
||||
reason = E_OK;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reason = E_OK;
|
||||
moveto(lf, cell);
|
||||
taketime(lf, getmovespeed(lf));
|
||||
|
@ -697,7 +815,10 @@ int trymove(lifeform_t *lf, int dir) {
|
|||
}
|
||||
} else {
|
||||
// try to open it
|
||||
opendoor(lf, inway);
|
||||
if (!opendoor(lf, inway)) {
|
||||
// opening a door counts as a successful move.
|
||||
reason = E_OK;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// can we push this?
|
||||
|
@ -741,6 +862,12 @@ int trymove(lifeform_t *lf, int dir) {
|
|||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
break;
|
||||
case E_TOOHEAVY:
|
||||
if (isplayer(lf)) {
|
||||
msg("Your load is too heavy to move with!");
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -756,8 +883,7 @@ int trymove(lifeform_t *lf, int dir) {
|
|||
|
||||
int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
cell_t *cell;
|
||||
object_t *o;
|
||||
enum IQBRACKET iq;
|
||||
//object_t *o;
|
||||
|
||||
// default
|
||||
if (error) {
|
||||
|
@ -766,41 +892,9 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
|||
}
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
// check for cursed objects + animals
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
if (!isplayer(lf)) {
|
||||
if (o->blessed == B_CURSED) {
|
||||
if (lfhasflag(lf, F_ANIMAL)) {
|
||||
if (!lfhasflag(lf, F_FLYING)) {
|
||||
if (celldangerous(lf, cell, error)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for dangerous objects
|
||||
iq = getiqname(getattr(lf, A_IQ), NULL);
|
||||
if (iq >= IQ_AVERAGE) {
|
||||
flag_t *f;
|
||||
object_t *o;
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
// don't walk on sharp objects without boots
|
||||
if (hasflag(o->flags, F_SHARP)) {
|
||||
if (!getequippedob(lf->pack, BP_FEET)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
f = hasflag(o->flags, F_WALKDAM);
|
||||
if (f) {
|
||||
// are we immune to this?
|
||||
if (!lfhasflagval(lf, F_DTIMMUNE, f->val[1], NA, NA, NULL)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
|
1
move.h
1
move.h
|
@ -2,6 +2,7 @@
|
|||
|
||||
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
int canmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error);
|
||||
int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error);
|
||||
int closedoorat(lifeform_t *lf, cell_t *c);
|
||||
int closedoor(lifeform_t *lf, object_t *o);
|
||||
|
|
40
nexus.c
40
nexus.c
|
@ -19,6 +19,7 @@
|
|||
material_t *material = NULL,*lastmaterial = NULL;
|
||||
objectclass_t *objectclass = NULL,*lastobjectclass = NULL;
|
||||
objecttype_t *objecttype = NULL,*lastobjecttype = NULL;
|
||||
obmod_t *firstobmod = NULL,*lastobmod = NULL;
|
||||
celltype_t *firstcelltype = NULL,*lastcelltype = NULL;
|
||||
race_t *firstrace = NULL,*lastrace = NULL;
|
||||
job_t *firstjob = NULL,*lastjob = NULL;
|
||||
|
@ -281,14 +282,23 @@ void checkendgame(void) {
|
|||
void cleanup(void) {
|
||||
fclose(logfile);
|
||||
cleanupgfx();
|
||||
|
||||
// free maps
|
||||
// free knowledge
|
||||
// free obmods
|
||||
// free obtypes
|
||||
// free objects
|
||||
// free materials
|
||||
// free races
|
||||
}
|
||||
|
||||
|
||||
void donextturn(map_t *map) {
|
||||
lifeform_t *who;
|
||||
int db = B_FALSE;
|
||||
|
||||
who = map->lf;
|
||||
dblog("**** donextturn for: id %d %s", who->id, who->race->name);
|
||||
if (db) dblog("**** donextturn for: id %d %s", who->id, who->race->name);
|
||||
|
||||
|
||||
turneffectslf(who);
|
||||
|
@ -319,9 +329,8 @@ dblog("**** donextturn for: id %d %s", who->id, who->race->name);
|
|||
flag_t *f;
|
||||
|
||||
if (donormalmove) {
|
||||
// paralyzed?
|
||||
f = hasflag(who->flags, F_PARALYZED);
|
||||
if (f) {
|
||||
// paralyzed etc?
|
||||
if (cannotmove(who)) {
|
||||
rest(who, B_FALSE);
|
||||
donormalmove = B_FALSE;
|
||||
}
|
||||
|
@ -331,13 +340,8 @@ dblog("**** donextturn for: id %d %s", who->id, who->race->name);
|
|||
if (donormalmove) {
|
||||
f = hasflag(who->flags, F_RESTING);
|
||||
if (f) {
|
||||
if (who->hp < who->maxhp) {
|
||||
rest(who, B_TRUE);
|
||||
donormalmove = B_FALSE;
|
||||
} else {
|
||||
killflag(f);
|
||||
if (isplayer(who)) msg("You finish resting.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,12 +370,12 @@ dblog("**** donextturn for: id %d %s", who->id, who->race->name);
|
|||
// effects which happen every GAME TICK
|
||||
// ie. object hp drain etc
|
||||
//////////////////////////////////
|
||||
timeeffectsworld(map);
|
||||
|
||||
// everyone else's time goes down by 1
|
||||
//for (who = map->lf->next ; who ; who = who->next ){
|
||||
// if (who->timespent > 0) who->timespent--;
|
||||
//}
|
||||
// note: can't use 'who->' below since 'who' might have died
|
||||
// and been de-alloced during checkdeath() above.
|
||||
timeeffectsworld(player->cell->map); // in case the player changed levels!
|
||||
|
||||
|
||||
}
|
||||
|
||||
celltype_t *findcelltype(int id) {
|
||||
|
@ -617,7 +621,7 @@ dblog("doing sort...");
|
|||
|
||||
void timeeffectsworld(map_t *map) {
|
||||
lifeform_t *l;
|
||||
int db = B_TRUE;
|
||||
int db = B_FALSE;
|
||||
object_t *o,*nexto;
|
||||
int x,y;
|
||||
long firstlftime;
|
||||
|
@ -636,10 +640,10 @@ void timeeffectsworld(map_t *map) {
|
|||
}
|
||||
|
||||
//if (db) dblog("timespent = %d\n", timespent);
|
||||
dblog("firstlftime = %d\n", firstlftime);
|
||||
if (db) dblog("firstlftime = %d\n", firstlftime);
|
||||
|
||||
if (firstlftime > 0) {
|
||||
dblog("making firstlf timespent = 0 (currently %d):", firstlftime);
|
||||
if (db) dblog("making firstlf timespent = 0 (currently %d):", firstlftime);
|
||||
//dumplf();
|
||||
for (l = map->lf ; l ; l = l->next) {
|
||||
//dblog("shuffling id %d %s timespent=%d -> %d",l->id,l->race->name, l->timespent, l->timespent - firstlftime);
|
||||
|
@ -653,7 +657,7 @@ void timeeffectsworld(map_t *map) {
|
|||
//dblog("after shuffle:");
|
||||
//dumplf();
|
||||
} else {
|
||||
dblog("firstlf timespent is not greater than 0. no shuffle.");
|
||||
if (db) dblog("firstlf timespent is not greater than 0. no shuffle.");
|
||||
}
|
||||
|
||||
timeleft += firstlftime;
|
||||
|
|
14
objects.h
14
objects.h
|
@ -8,6 +8,7 @@ material_t *addmaterial(enum MATERIAL id, char *name, float weightrating);
|
|||
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph);
|
||||
object_t *addob(obpile_t *where, char *name);
|
||||
object_t *addobject(obpile_t *where, char *name, int canstack);
|
||||
obmod_t *addobmod(enum OBMOD id, char *suffix, enum BODYPART bp);
|
||||
obpile_t *addobpile(lifeform_t *owner, cell_t *where);
|
||||
objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid);
|
||||
void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat);
|
||||
|
@ -28,12 +29,16 @@ void explodeob(object_t *o, flag_t *f, int bigness);
|
|||
void extinguish(object_t *o);
|
||||
material_t *findmaterial(int id);
|
||||
objectclass_t *findoc(int id);
|
||||
object_t *findobbyid(obpile_t *op, long oid);
|
||||
object_t *findobl(obpile_t *op, char let); // find object by letter
|
||||
obmod_t *findobmod(enum OBMOD id);
|
||||
objecttype_t *findot(enum OBTYPE id);
|
||||
objecttype_t *findotn(char *name); // find objecttype by name
|
||||
void fragments(cell_t *centre, char *what, int speed);
|
||||
void genhiddennames(void);
|
||||
int getcharges(object_t *o);
|
||||
int geteffecttime(int min, int max, enum BLESSTYPE isblessed);
|
||||
objecttype_t *getlinkspell(object_t *o);
|
||||
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt);
|
||||
int getobaccuracy(object_t *wep);
|
||||
int getobvalue(object_t *o);
|
||||
|
@ -49,7 +54,7 @@ int getfirearmspeed(object_t *o);
|
|||
char getglyph(object_t *o);
|
||||
char *genhiddenname(enum OBCLASS id);
|
||||
char *gethiddenname(object_t *o);
|
||||
int getobattackspeed(object_t *o);
|
||||
int getobattackdelay(object_t *o);
|
||||
int getletindex(char let);
|
||||
int getmaterialvalue(enum MATERIAL mat );
|
||||
int getmaxthrowrange(lifeform_t *lf, object_t *o);
|
||||
|
@ -93,6 +98,7 @@ int isblessed(object_t *o);
|
|||
int isblessknown(object_t *o);
|
||||
int iscorpse(object_t *o);
|
||||
int iscursed(object_t *o);
|
||||
int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown);
|
||||
int isdrinkable(object_t *o);
|
||||
int isedible(object_t *o);
|
||||
flag_t *isequipped(object_t *o);
|
||||
|
@ -119,16 +125,18 @@ void killot(objecttype_t *ot);
|
|||
lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level);
|
||||
void makeknown(enum OBTYPE otid);
|
||||
object_t *moveob(object_t *src, obpile_t *dst, int howmany);
|
||||
object_t *newobeffects(object_t *o);
|
||||
void modbonus(object_t *o, int amt);
|
||||
//object_t *newobeffects(object_t *o);
|
||||
void obaction(object_t *o, char *text);
|
||||
object_t *obexists(enum OBTYPE obid);
|
||||
void obdie(object_t *o);
|
||||
int obfits(object_t *o, obpile_t *op);
|
||||
enum DAMTYPE oblastdamtype(object_t *o);
|
||||
int obmodappliesto(obmod_t *om, objecttype_t *ot);
|
||||
flag_t *obproduceslight(object_t *o);
|
||||
int obpropsmatch(object_t *a, object_t *b);
|
||||
int obotpropsmatch(object_t *a, objecttype_t *b);
|
||||
int operate(lifeform_t *lf, object_t *o);
|
||||
int operate(lifeform_t *lf, object_t *o, cell_t *where);
|
||||
int pilehasletter(obpile_t *op, char let);
|
||||
void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, int *seen);
|
||||
int pour(lifeform_t *lf, object_t *o);
|
||||
|
|
3
save.c
3
save.c
|
@ -74,9 +74,8 @@ int loadflagpile(FILE *f, flagpile_t *fp) {
|
|||
fl = addflag_real(fp, tempflag.id,
|
||||
tempflag.val[0],
|
||||
tempflag.val[1],
|
||||
tempflag.val[2], strcmp(buf, "^^^") ? buf : NULL, tempflag.lifetime, tempflag.known);
|
||||
tempflag.val[2], strcmp(buf, "^^^") ? buf : NULL, tempflag.lifetime, tempflag.known, tempflag.obfrom);
|
||||
|
||||
fl->obfrom = tempflag.obfrom;
|
||||
|
||||
if (db) {
|
||||
dblog("--> added flag id=%d. v0=%d, v1=%d, v2=%d, text=%s, lifetime=%d, known=%d, obfrom=%ld\n",fl->id,
|
||||
|
|
631
spell.c
631
spell.c
|
@ -1,4 +1,5 @@
|
|||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -18,6 +19,8 @@ extern lifeform_t *player;
|
|||
|
||||
extern WINDOW *msgwin;
|
||||
|
||||
extern job_t *firstjob;
|
||||
|
||||
int abilityeffects(lifeform_t *user, enum OBTYPE abilid) {
|
||||
char username[BUFLEN];
|
||||
char buf[BUFLEN];
|
||||
|
@ -43,8 +46,20 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) {
|
|||
}
|
||||
}
|
||||
|
||||
if (isburdened(user)) {
|
||||
if (isplayer(user)) {
|
||||
msg("Your load is too heavy to jump!");
|
||||
}
|
||||
return B_TRUE;
|
||||
} else if (lfhasflag(user, F_GRAVBOOSTED)) {
|
||||
if (isplayer(user)) {
|
||||
msg("Gravity around you is too strong to jump in!");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// we now have a cell - go there!
|
||||
taketime(user, getmovespeed(user));
|
||||
taketime(user, getactspeed(user));
|
||||
origcell = user->cell;
|
||||
|
||||
// did you land on anyone?
|
||||
|
@ -118,7 +133,64 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (abilid == OT_A_SPRINT) {
|
||||
int howlong;
|
||||
if (lfhasflag(user, F_TIRED)) {
|
||||
if (isplayer(user)) {
|
||||
msg("You are too tired to sprint right now.");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
// TODO: calculate time based on:
|
||||
// constitution (or max hp?)
|
||||
// running speed
|
||||
howlong = 3;
|
||||
addtempflag(user->flags, F_SPRINTING, B_TRUE, NA, NA, NULL, howlong);
|
||||
} else if (abilid == OT_A_DEBUG) {
|
||||
cell_t *where;
|
||||
where = askcoords("Debug who?", TT_MONSTER);
|
||||
if (where) {
|
||||
lifeform_t *victim;
|
||||
victim = where->lf;
|
||||
if (victim) {
|
||||
char lfname[BUFLEN];
|
||||
flag_t *f;
|
||||
getlfname(victim, lfname);
|
||||
|
||||
f = hasflag(victim->flags, F_DEBUG);
|
||||
if (f) {
|
||||
killflag(f);
|
||||
msg("%s - debugging is DISABLED.", lfname);
|
||||
} else {
|
||||
addflag(victim->flags, F_DEBUG, B_TRUE, NA, NA, NULL);
|
||||
msg("%s - debugging is ON.", lfname);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (abilid == OT_A_EMPLOY) {
|
||||
cell_t *where;
|
||||
where = askcoords("Assign job to who?", TT_MONSTER);
|
||||
if (where && where->lf) {
|
||||
char question[BUFLEN];
|
||||
char lfname[BUFLEN];
|
||||
char buf[BUFLEN];
|
||||
job_t *j;
|
||||
lifeform_t *target;
|
||||
|
||||
target = where->lf;
|
||||
getlfname(target, lfname);
|
||||
sprintf(question, "What job will you assign to %s",lfname);
|
||||
askstring(question, '?', buf, BUFLEN, NULL);
|
||||
j = findjobbyname(buf);
|
||||
if (j) {
|
||||
givejob(target, j->id);
|
||||
msg("%s is now a %s.", lfname, j->name);
|
||||
} else {
|
||||
fizzle(user);
|
||||
}
|
||||
} else {
|
||||
msg("There is nobody there!");
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -132,6 +204,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
|
||||
getlfname(caster, castername);
|
||||
|
||||
// default to unseen
|
||||
if (seenbyplayer) *seenbyplayer = B_FALSE;
|
||||
|
||||
if (spellid == OT_S_ABSORBMETAL) {
|
||||
|
@ -163,6 +236,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
removedeadobs(caster->pack);
|
||||
}
|
||||
|
||||
// handle cell under the caster
|
||||
for (o = caster->cell->obpile->first ; o ; o = o->next) {
|
||||
// destroy metal items on the ground
|
||||
if (ismetal(o->material->id)) {
|
||||
takedamage(o, 9999, DT_DIRECT);
|
||||
if (hasflag(o->flags, F_DEAD)) {
|
||||
totalmass += getobweight(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
// destroy objects right away
|
||||
removedeadobs(caster->cell->obpile);
|
||||
|
||||
for (i = 0; i < caster->nlos; i++) {
|
||||
targcell = caster->los[i];
|
||||
for (o = targcell->obpile->first ; o ; o = o->next) {
|
||||
|
@ -222,7 +308,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
return B_FALSE;
|
||||
} else if (o->amt != 1) {
|
||||
if (isplayer(caster)) {
|
||||
msg("Your %s wobble a little.", obname);
|
||||
msg("Your %s wobbles a little.", obname);
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
|
@ -245,6 +331,31 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_BLINK) {
|
||||
if (hasmr(caster)) {
|
||||
if (isplayer(caster)) {
|
||||
msg("You feel a momentary tug.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if (!caster->nlos) {
|
||||
// can't see anywhere
|
||||
fizzle(caster);
|
||||
} else {
|
||||
int tries = 0,maxtries = 10;
|
||||
// pick a random location
|
||||
targcell = NULL;
|
||||
while (!targcell || !cellwalkable(caster, targcell, NULL) || celldangerous(caster, targcell, NULL)) {
|
||||
int i;
|
||||
i = rnd(0,caster->nlos-1);
|
||||
targcell = caster->los[i];
|
||||
tries++;
|
||||
if (tries >= maxtries) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
teleportto(caster, targcell);
|
||||
}
|
||||
} else if (spellid == OT_S_CONECOLD) {
|
||||
char lfname[BUFLEN];
|
||||
int acc;
|
||||
|
@ -278,13 +389,36 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else if (spellid == OT_S_CREATEMONSTER) {
|
||||
cell_t *where;
|
||||
lifeform_t *newlf;
|
||||
job_t *forcejob = NULL;
|
||||
race_t *r = NULL;
|
||||
int randomjobsok = B_TRUE;
|
||||
// create a monster nearby
|
||||
|
||||
if (blessed) {
|
||||
// ask what kind of monster
|
||||
askstring("Create what kind of monster", '?', buf, BUFLEN, NULL);
|
||||
r = findracebyname(buf);
|
||||
// not found - are we asking for a job with the monster?
|
||||
if (!r) {
|
||||
job_t *j;
|
||||
// try removing suffixes
|
||||
for (j = firstjob ; j ; j = j->next) {
|
||||
char *p;
|
||||
char jobname[BUFLEN];
|
||||
strcpy(jobname, j->name);
|
||||
jobname[0] = tolower(jobname[0]);
|
||||
p = strstr(buf, jobname);
|
||||
if (p) {
|
||||
char newbuf[BUFLEN];
|
||||
strncpy(newbuf, buf, (p - buf) - 1);
|
||||
r = findracebyname(newbuf);
|
||||
if (r) {
|
||||
forcejob = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!r) {
|
||||
if (caster->controller == C_PLAYER) {
|
||||
nothinghappens();
|
||||
|
@ -302,13 +436,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
return B_TRUE;
|
||||
}
|
||||
// create random monster in cell
|
||||
|
||||
if (forcejob) {
|
||||
randomjobsok = B_FALSE;
|
||||
} else {
|
||||
randomjobsok = B_TRUE;
|
||||
}
|
||||
|
||||
if (blessed) {
|
||||
//newlf = addlf(where, r->id, getrandommonlevel(where->map->depth));
|
||||
newlf = addmonster(where, r->id);
|
||||
newlf = addmonster(where, r->id, randomjobsok);
|
||||
} else {
|
||||
newlf = addmonster(where, R_RANDOM);
|
||||
newlf = addmonster(where, R_RANDOM, randomjobsok);
|
||||
}
|
||||
if (newlf) {
|
||||
// assign job if required
|
||||
if (forcejob) {
|
||||
givejob(newlf, forcejob->id);
|
||||
}
|
||||
if (haslos(player, where)) {
|
||||
char *newbuf;
|
||||
getlfname(newlf, buf);
|
||||
|
@ -379,47 +524,49 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else if (spellid == OT_S_DETECTLIFE) {
|
||||
target = caster;
|
||||
if (isplayer(caster)) {
|
||||
int howlong = 15;
|
||||
switch (blessed) {
|
||||
case B_BLESSED:
|
||||
howlong = 20; break;
|
||||
case B_UNCURSED:
|
||||
howlong = rnd(10,20); break;
|
||||
case B_CURSED:
|
||||
howlong = 2; break;
|
||||
}
|
||||
int howlong;
|
||||
howlong = getspellduration(10,20,blessed);
|
||||
addtempflag(target->flags, F_DETECTLIFE, 10, NA, NA, NULL, howlong);
|
||||
} else {
|
||||
// monsters can't use this
|
||||
}
|
||||
} else if (spellid == OT_S_DETECTMAGIC) {
|
||||
target = caster;
|
||||
if (isplayer(caster)) {
|
||||
int howlong;
|
||||
howlong = getspellduration(40,90,blessed);
|
||||
addtempflag(target->flags, F_DETECTMAGIC, B_TRUE, NA, NA, NULL, howlong);
|
||||
} else {
|
||||
// monsters can't use this
|
||||
}
|
||||
/*
|
||||
} else if (spellid == OT_S_DETECTMETAL) {
|
||||
target = caster;
|
||||
if (isplayer(caster)) {
|
||||
int howlong = 15;
|
||||
switch (blessed) {
|
||||
case B_BLESSED:
|
||||
howlong = 20; break;
|
||||
case B_UNCURSED:
|
||||
howlong = rnd(10,20); break;
|
||||
case B_CURSED:
|
||||
howlong = 2; break;
|
||||
}
|
||||
howlong = getspellduration(10,20,blessed);
|
||||
addtempflag(target->flags, F_DETECTMETAL, 10, NA, NA, NULL, howlong);
|
||||
} else {
|
||||
// monsters can't use this
|
||||
}
|
||||
*/
|
||||
} else if (spellid == OT_S_DETONATE) {
|
||||
// don't need line of fire!
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, B_FALSE)) return B_TRUE;
|
||||
|
||||
explodecells(targcell, 20, B_TRUE, NULL, 0, B_TRUE);
|
||||
|
||||
if (haslos(player, targcell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_EXPLODEMETAL) {
|
||||
float totalmass = 0;
|
||||
object_t *o, *nexto;
|
||||
int i;
|
||||
|
||||
if (!validatespellcell(caster, &targcell, TT_OBJECT, B_FALSE)) return B_TRUE;
|
||||
|
||||
// how much metal is there?
|
||||
for (i = 0; i < caster->nlos; i++) {
|
||||
cell_t *c;
|
||||
c = caster->los[i];
|
||||
for (o = c->obpile->first ; o ; o = nexto) {
|
||||
for (o = targcell->obpile->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
// destroy metal items on the ground
|
||||
if (ismetal(o->material->id)) {
|
||||
|
@ -427,7 +574,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
removeob(o, o->amt);
|
||||
}
|
||||
}
|
||||
}
|
||||
// destroy objects right away
|
||||
removedeadobs(targcell->lf->pack);
|
||||
|
||||
// explosion, based on size...
|
||||
if (totalmass > 0) {
|
||||
|
@ -566,27 +714,25 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
}
|
||||
}
|
||||
} else if (spellid == OT_S_FIREBALL) {
|
||||
cell_t *where;
|
||||
int failed = B_FALSE;
|
||||
// ask for a target cell
|
||||
sprintf(buf, "Where will you target your fireball?");
|
||||
where = askcoords(buf, TT_MONSTER);
|
||||
if (where && haslof(caster, where)) { // need line of FIRE for this, not just sight
|
||||
if (!where->type->solid || hasflag(where->type->material->flags, F_FLAMMABLE)) {
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (targcell && haslof(caster, targcell)) { // need line of FIRE for this, not just sight
|
||||
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
|
||||
int dir;
|
||||
cell_t *c;
|
||||
// centre fireball here...
|
||||
if (caster->controller == C_PLAYER) {
|
||||
if (isplayer(caster)) {
|
||||
msg("You launch an enormous ball of fire!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, caster->cell)) {
|
||||
msg("%s launches an enormous ball of fire!",castername);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, where)) {
|
||||
} else if (haslos(player, targcell)) {
|
||||
msg("An enormous ball of fire explodes!");
|
||||
}
|
||||
|
||||
anim(caster->cell, where, '^');
|
||||
anim(caster->cell, targcell, '^');
|
||||
|
||||
// add fires as follows (3 = large, 2 = medium, 1 = smell)
|
||||
//
|
||||
|
@ -596,23 +742,23 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
// 232
|
||||
// 1
|
||||
// add large fires to surrounding cells
|
||||
addob(where->obpile, "large fire");
|
||||
addob(targcell->obpile, "large fire");
|
||||
for (dir = D_N; dir <= D_W; dir++) {
|
||||
c = getcellindir(where, dir);
|
||||
c = getcellindir(targcell, dir);
|
||||
if (c && (!c->type->solid || hasflag(c->type->material->flags, F_FLAMMABLE)) ) {
|
||||
addob(c->obpile, "large fire");
|
||||
}
|
||||
}
|
||||
for (dir = DC_NE; dir <= DC_NW; dir += 2) {
|
||||
cell_t *c;
|
||||
c = getcellindir(where, dir);
|
||||
c = getcellindir(targcell, dir);
|
||||
if (c && (!c->type->solid || hasflag(c->type->material->flags, F_FLAMMABLE)) ) {
|
||||
addob(c->obpile, "medium fire");
|
||||
}
|
||||
}
|
||||
for (dir = D_N; dir <= D_W; dir++) {
|
||||
cell_t *c;
|
||||
c = getcellindir(where, dir);
|
||||
c = getcellindir(targcell, dir);
|
||||
if (c) {
|
||||
c = getcellindir(c, dir);
|
||||
if (c && (!c->type->solid || hasflag(c->type->material->flags, F_FLAMMABLE)) ) {
|
||||
|
@ -665,19 +811,17 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
}
|
||||
}
|
||||
} else if (spellid == OT_S_FLAMEPILLAR) {
|
||||
cell_t *where;
|
||||
int failed = B_FALSE;
|
||||
// ask for a target cell
|
||||
sprintf(buf, "Where will you create a flame pillar?");
|
||||
where = askcoords(buf, TT_MONSTER);
|
||||
if (where && haslos(caster, where)) {
|
||||
if (!where->type->solid || hasflag(where->type->material->flags, F_FLAMMABLE)) {
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (targcell && haslos(caster, targcell)) {
|
||||
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
|
||||
// create flame there
|
||||
if (haslos(player, where)) {
|
||||
if (haslos(player, targcell)) {
|
||||
msg("A raging pillar of flame appears!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
addob(where->obpile, "large fire");
|
||||
addob(targcell->obpile, "large fire");
|
||||
} else {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
|
@ -688,6 +832,39 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
if (failed) {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_ENCHANT) {
|
||||
object_t *o;
|
||||
|
||||
if (targob) {
|
||||
o = targob;
|
||||
} else {
|
||||
// ask for an object
|
||||
o = askobjectwithflag(caster->pack, "Enchant which object", NULL, AO_NONE, F_ENCHANTABLE);
|
||||
}
|
||||
if (!o) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (isplayer(caster)) {
|
||||
if (!hasflag(o->flags, F_ENCHANTABLE)) {
|
||||
nothinghappens();
|
||||
return B_TRUE;
|
||||
} else {
|
||||
int amt;
|
||||
char obname[BUFLEN];
|
||||
if (blessed == B_CURSED) {
|
||||
amt = -1;
|
||||
} else {
|
||||
amt = 1;
|
||||
}
|
||||
modbonus(o, amt);
|
||||
getobname(o, obname, o->amt);
|
||||
msg("Your %s glows %s for a moment.", noprefix(obname), (blessed == B_CURSED) ? "black" : "green");
|
||||
}
|
||||
} else {
|
||||
// monsters can't id things!
|
||||
}
|
||||
} else if (spellid == OT_S_FREEZEOB) {
|
||||
object_t *o;
|
||||
|
||||
|
@ -799,9 +976,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
}
|
||||
} else if (spellid == OT_S_HASTE) {
|
||||
int howlong = 15;
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
|
||||
if (!isplayer(target) && haslos(player, target->cell)) {
|
||||
target = targcell->lf;
|
||||
|
||||
if (!target) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
if (haslos(player, target->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
|
||||
|
@ -812,17 +996,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
switch (blessed) {
|
||||
case B_BLESSED:
|
||||
howlong = 25;
|
||||
break;
|
||||
case B_UNCURSED:
|
||||
howlong = rnd(5,25);
|
||||
break;
|
||||
case B_CURSED:
|
||||
howlong = 5;
|
||||
break;
|
||||
}
|
||||
howlong = getspellduration(5,25,blessed);
|
||||
addtempflag(target->flags, F_FASTACT, 5, NA, NA, NULL, howlong);
|
||||
addtempflag(target->flags, F_FASTMOVE, 5, NA, NA, NULL, howlong);
|
||||
}
|
||||
} else if (spellid == OT_S_HEALING) {
|
||||
|
@ -1045,6 +1220,89 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
rv = B_FALSE;
|
||||
} else if (spellid == OT_S_METALHEAL) {
|
||||
int i;
|
||||
float totalmass = 0;
|
||||
object_t *o;
|
||||
int howmuch;
|
||||
// works on all metal in sight
|
||||
if (isplayer(caster)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_FALSE;
|
||||
msg("You draw health from nearby metal!");
|
||||
} else if (haslos(player, caster->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_FALSE;
|
||||
msg("%s draws health from nearby metal!",castername);
|
||||
}
|
||||
totalmass = 0;
|
||||
|
||||
// destroy WORN metal objects by the caster (not CARRIED ones)
|
||||
if (!hasmr(caster)) {
|
||||
for (o = caster->pack->first ; o ; o = o->next) {
|
||||
if (isequipped(o) && ismetal(o->material->id)) {
|
||||
takedamage(o, 9999, DT_DIRECT);
|
||||
if (hasflag(o->flags, F_DEAD)) {
|
||||
totalmass += getobweight(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
// destroy objects right away
|
||||
removedeadobs(caster->pack);
|
||||
}
|
||||
|
||||
// handle cell under the caster
|
||||
for (o = caster->cell->obpile->first ; o ; o = o->next) {
|
||||
// destroy metal items on the ground
|
||||
if (ismetal(o->material->id)) {
|
||||
takedamage(o, 9999, DT_DIRECT);
|
||||
if (hasflag(o->flags, F_DEAD)) {
|
||||
totalmass += getobweight(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
// destroy objects right away
|
||||
removedeadobs(caster->cell->obpile);
|
||||
|
||||
for (i = 0; i < caster->nlos; i++) {
|
||||
targcell = caster->los[i];
|
||||
for (o = targcell->obpile->first ; o ; o = o->next) {
|
||||
// destroy metal items on the ground
|
||||
if (ismetal(o->material->id)) {
|
||||
takedamage(o, 9999, DT_DIRECT);
|
||||
if (hasflag(o->flags, F_DEAD)) {
|
||||
totalmass += getobweight(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
// destroy objects right away
|
||||
removedeadobs(targcell->obpile);
|
||||
if (targcell->lf && !hasmr(targcell->lf)) {
|
||||
// destroy only WORN metal objects, not CARRIED ones
|
||||
for (o = targcell->lf->pack->first ; o ; o = o->next) {
|
||||
if (isequipped(o) && ismetal(o->material->id)) {
|
||||
takedamage(o, 9999, DT_DIRECT);
|
||||
if (hasflag(o->flags, F_DEAD)) {
|
||||
totalmass += getobweight(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
// destroy objects right away
|
||||
removedeadobs(targcell->lf->pack);
|
||||
}
|
||||
}
|
||||
|
||||
if (totalmass > 0) {
|
||||
if (hasmr(caster)) {
|
||||
if (isplayer(caster)) {
|
||||
msg("You feel momentarily healthier, but the feeling passes.");
|
||||
}
|
||||
} else {
|
||||
// heal 2 hp per kilo
|
||||
howmuch = floor(totalmass) * 2;
|
||||
gainhp(caster, howmuch);
|
||||
}
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_MINDSCAN) {
|
||||
cell_t *where;
|
||||
int failed = B_FALSE;
|
||||
|
@ -1175,34 +1433,44 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
fizzle(caster);
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_LEVTELEPORT) {
|
||||
} else if (spellid == OT_S_GATE) {
|
||||
int newdepth;
|
||||
// ask which level
|
||||
askstring("Teleport to which level", '?', buf, BUFLEN, NULL);
|
||||
askstring("Create a portal to which level", '?', buf, BUFLEN, NULL);
|
||||
newdepth = atoi(buf);
|
||||
if (newdepth <= 0) {
|
||||
fizzle(caster);
|
||||
} else if (hasmr(caster)) {
|
||||
if (isplayer(caster)) {
|
||||
msg("You flicker.");
|
||||
msg("You see a flicker nearby.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, caster->cell)) {
|
||||
getlfname(caster, buf);
|
||||
msg("%s flickers.",buf);
|
||||
msg("You see a flicker near %s.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
} else {
|
||||
map_t *newmap;
|
||||
cell_t *newcell;
|
||||
cell_t *newcell,*srccell;
|
||||
object_t *srcportal,*dstportal;
|
||||
|
||||
// announce
|
||||
// find adjacent cell for portal
|
||||
srccell = getrandomadjcell(caster->cell, WE_NOTSOLID);
|
||||
if (!srccell) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
}
|
||||
// create the source portal
|
||||
srcportal = addob(srccell->obpile, "magic portal");
|
||||
|
||||
// announce, because we might have a delay creating the level...
|
||||
if (isplayer(caster)) {
|
||||
msg("There is a blinding flash of light...");
|
||||
wrefresh(msgwin);
|
||||
}
|
||||
|
||||
// teleport there!
|
||||
// find new map !
|
||||
newmap = findmapofdepth(newdepth);
|
||||
if (!newmap) {
|
||||
// create new map
|
||||
|
@ -1210,19 +1478,40 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
createmap(newmap, newdepth, caster->cell->map->habitat, NULL, findot(OT_STAIRSUP));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// find a random cell there
|
||||
newcell = getrandomcell(newmap);
|
||||
while (!cellwalkable(caster, newcell, NULL)) {
|
||||
while (!cellwalkable(caster, newcell, NULL) || hasenterableobject(newcell)) {
|
||||
newcell = getrandomcell(newmap);
|
||||
}
|
||||
// add the dst portal
|
||||
dstportal = addob(newcell->obpile, "magic portal");
|
||||
// link the dst portal
|
||||
addflag_real(dstportal->flags, F_MAPLINK, caster->cell->map->id, srccell->x, srccell->y, NULL, PERMENANT, B_FALSE, -1);
|
||||
|
||||
// announce
|
||||
if (isplayer(caster)) {
|
||||
msg("You find yourself on level %d.", newcell->map->depth);
|
||||
// link the source portal
|
||||
addflag_real(srcportal->flags, F_MAPLINK, newmap->id, newcell->x, newcell->y, NULL, PERMENANT, B_FALSE, -1);
|
||||
|
||||
// make both gates temporary
|
||||
addflag(srcportal->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(srcportal->flags, F_OBHP, 6, 6, NA, NULL);
|
||||
addflag(srcportal->flags, F_OBHPDRAIN, 1, DT_DIRECT, NA, NULL);
|
||||
addflag(srcportal->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
||||
addflag(srcportal->flags, F_DIETEXT, B_TRUE, NA, NA, "vanishes");
|
||||
|
||||
addflag(dstportal->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(dstportal->flags, F_OBHP, 6, 6, NA, NULL);
|
||||
addflag(dstportal->flags, F_OBHPDRAIN, 1, DT_DIRECT, NA, NULL);
|
||||
addflag(dstportal->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
||||
addflag(dstportal->flags, F_DIETEXT, B_TRUE, NA, NA, "vanishes");
|
||||
|
||||
if (haslos(player, srccell)) {
|
||||
char obname[BUFLEN];
|
||||
getobname(srcportal, obname, 1);
|
||||
msg("%s appears!",obname);
|
||||
}
|
||||
|
||||
// go there!
|
||||
moveto(caster, newcell);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_INSCRIBE) {
|
||||
|
@ -1260,13 +1549,62 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else {
|
||||
// monsters can't cast
|
||||
}
|
||||
} else if (spellid == OT_S_KNOCK) {
|
||||
object_t *o;
|
||||
if (!validatespellcell(caster, &targcell,TT_DOOR, B_FALSE)) return B_TRUE;
|
||||
o = hasobwithflag(targcell->obpile, F_DOOR);
|
||||
if (o) {
|
||||
int dooropen;
|
||||
isdoor(o, &dooropen); // just check whether it's open, we know it's a door
|
||||
if (dooropen) {
|
||||
fizzle(caster);
|
||||
} else {
|
||||
if (haslos(player, targcell)) {
|
||||
getobname(o, buf, o->amt);
|
||||
msg("%s %s!",isplayer(caster) ? "You blast" : "Something blasts", buf);
|
||||
}
|
||||
takedamage(o, 999, DT_DIRECT);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_LIGHT) {
|
||||
lifeform_t *l;
|
||||
// centre light on the caster
|
||||
makelitradius(caster->cell, 10, B_PERM);
|
||||
if (isplayer(caster) || haslos(player, caster->cell)) {
|
||||
msg("The area is lit by a magical light!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
makelitradius(caster->cell, 10, B_PERM);
|
||||
|
||||
// blind anyone with nightvis who sees it
|
||||
// (player last)
|
||||
for (l = caster->cell->map->lf ; l ; l = l->next) {
|
||||
if (!isplayer(l) && haslos(l, caster->cell)) {
|
||||
if (lfhasflag(l, F_SEEINDARK)) {
|
||||
// if you don't have eyes, your'e safe!
|
||||
if (!lfhasflagval(l, F_NOBODYPART, BP_EYES, NA, NA, NULL)) {
|
||||
// blind for 5-10 turns
|
||||
addtempflag(l->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(5,10));
|
||||
}
|
||||
}
|
||||
// undead will flee from light
|
||||
if (lfhasflag(l, F_UNDEAD)) {
|
||||
// runs away from caster
|
||||
addtempflag(l->flags, F_FLEEFROM, caster->id, NA, NA, NULL, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isplayer(caster) || haslos(player, caster->cell)) {
|
||||
if (lfhasflag(player, F_SEEINDARK)) {
|
||||
msg("The light burns your eyes!");
|
||||
// blind for 5-10 turns
|
||||
addtempflag(player->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(5,10));
|
||||
}
|
||||
}
|
||||
|
||||
} else if (spellid == OT_S_GRAVBOOST) {
|
||||
// ask for target
|
||||
if (!target) {
|
||||
|
@ -1292,21 +1630,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
switch (blessed) {
|
||||
case B_BLESSED:
|
||||
howlong = 10;
|
||||
break;
|
||||
case B_UNCURSED:
|
||||
howlong = rnd(2,10);
|
||||
break;
|
||||
case B_CURSED:
|
||||
howlong = 2;
|
||||
break;
|
||||
}
|
||||
howlong = getspellduration(2,10,blessed);
|
||||
addtempflag(target->flags, F_GRAVBOOSTED, B_TRUE, NA, NA, NULL, howlong);
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_PASSWALL) {
|
||||
int howlong = 7;
|
||||
target = caster;
|
||||
if (hasmr(target)) {
|
||||
if (isplayer(target)) {
|
||||
msg("You feel momentarily insubstantial.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
howlong = getspellduration(5,10,blessed);
|
||||
addtempflag(target->flags, F_NONCORPOREAL, B_TRUE, NA, NA, NULL, howlong);
|
||||
} else if ((spellid == OT_S_POLYMORPHRND) || (spellid == OT_S_POLYMORPH)) {
|
||||
race_t *r;
|
||||
|
||||
|
@ -1344,6 +1685,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else {
|
||||
char buf2[BUFLEN];
|
||||
char targname[BUFLEN];
|
||||
getlfname(target, targname);
|
||||
sprintf(buf2, "What will you transform %s into", targname);
|
||||
askstring(buf2, '?', buf, BUFLEN, NULL);
|
||||
}
|
||||
|
@ -1352,7 +1694,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
// make sure race is valid:
|
||||
// - can't turn into monsters which aren't randomly generated.
|
||||
// - can't turn into unique monsters
|
||||
if (!appearsrandomly(r->id)) {
|
||||
if (r && !appearsrandomly(r->id)) {
|
||||
r = NULL;
|
||||
}
|
||||
} else {
|
||||
|
@ -1402,17 +1744,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
switch (blessed) {
|
||||
case B_BLESSED:
|
||||
howlong = 5;
|
||||
break;
|
||||
case B_UNCURSED:
|
||||
howlong = rnd(5,25);
|
||||
break;
|
||||
case B_CURSED:
|
||||
howlong = 25;
|
||||
break;
|
||||
}
|
||||
addtempflag(target->flags, F_SLOWACT, 5, NA, NA, NULL, howlong);
|
||||
addtempflag(target->flags, F_SLOWMOVE, 5, NA, NA, NULL, howlong);
|
||||
/*
|
||||
if (!isplayer(target) && haslos(player, target->cell)) {
|
||||
|
@ -1615,76 +1948,109 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
|
||||
if (target) {
|
||||
int howlong = 30;
|
||||
switch (blessed) {
|
||||
case B_BLESSED:
|
||||
howlong = 30;
|
||||
break;
|
||||
case B_UNCURSED:
|
||||
howlong = rnd(10,30);
|
||||
break;
|
||||
case B_CURSED:
|
||||
howlong = 10;
|
||||
break;
|
||||
}
|
||||
howlong = getspellduration(10,30,blessed);
|
||||
addtempflag(target->flags, F_ATTRMOD, A_STR, -6, NA, NULL, howlong);
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_WISH) {
|
||||
} else if ((spellid == OT_S_WISH) || (spellid == OT_S_GIFT)) {
|
||||
object_t *o;
|
||||
if (caster->controller == C_PLAYER) {
|
||||
if (isplayer(caster)) {
|
||||
char lfname[BUFLEN];
|
||||
char question[BUFLEN];
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
// ask for target
|
||||
if (spellid == OT_S_GIFT) {
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
} else {
|
||||
target = caster;
|
||||
}
|
||||
getlfname(target, lfname);
|
||||
|
||||
// ask for an object
|
||||
askstring("For what do you wish", '?', buf, BUFLEN, NULL);
|
||||
o = addob(caster->cell->obpile, buf);
|
||||
if (spellid == OT_S_GIFT) {
|
||||
sprintf(question, "What gift will %s receive",lfname);
|
||||
} else {
|
||||
sprintf(question, "For what do you wish");
|
||||
}
|
||||
askstring(question, '?', buf, BUFLEN, NULL);
|
||||
o = addob(target->cell->obpile, buf);
|
||||
if (o) {
|
||||
if (!hasflag(o->flags, F_IMPASSABLE) && canpickup(caster, o)) {
|
||||
relinkob(o, caster->pack); // move to pack
|
||||
getobname(o, buf, o->amt);
|
||||
msglower("%c - %s.", o->letter, buf);
|
||||
char obname[BUFLEN];
|
||||
getobname(o, obname, o->amt);
|
||||
if (!hasflag(o->flags, F_IMPASSABLE) && canpickup(target, o, ALL)) {
|
||||
relinkob(o, target->pack); // move to pack
|
||||
if (isplayer(target)) {
|
||||
msglower("%c - %s.", o->letter, obname);
|
||||
} else {
|
||||
msg("%s is gifted with %s.", lfname, obname);
|
||||
}
|
||||
} else {
|
||||
// couldn't pick it up - try to place on ground!
|
||||
// impassable?
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
cell_t *newloc;
|
||||
// if so, don't put it where the player is!
|
||||
newloc = getrandomadjcell(caster->cell, WE_NOTSOLID);
|
||||
newloc = getrandomadjcell(target->cell, WE_NOTSOLID);
|
||||
o = relinkob(o, newloc->obpile);
|
||||
}
|
||||
if (o) {
|
||||
if (isblind(caster)) {
|
||||
youhear(caster->cell, "something hitting the ground.");
|
||||
} else {
|
||||
getobname(o, buf, o->amt);
|
||||
msg("%s appear%s on the ground!", buf, (o->amt == 1) ? "s" : "");
|
||||
msg("%s appear%s on the ground!", obname, (o->amt == 1) ? "s" : "");
|
||||
}
|
||||
} else {
|
||||
// couldn't make it appear
|
||||
msg("The air in front of you seems to ripple for a moment.");
|
||||
msg("The air in front of %s seems to ripple for a while.", lfname);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// couldn't make it appear
|
||||
msg("The air in front of you seems to ripple for a moment.");
|
||||
// couldn't make it appear - ob doesn't exist
|
||||
msg("The air in front of %s seems to ripple for a moment.", lfname);
|
||||
}
|
||||
} else {
|
||||
// monsters can't wish
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void fizzle(lifeform_t *caster) {
|
||||
char buf[BUFLEN];
|
||||
if (isplayer(caster)) {
|
||||
if (lfhasflag(caster, F_CASTINGSPELL)) {
|
||||
msg("Your spell fizzles.");
|
||||
} else {
|
||||
nothinghappens();
|
||||
}
|
||||
/*
|
||||
} else if (haslos(player, caster->cell)) {
|
||||
getlfname(caster, buf);
|
||||
capitalise(buf);
|
||||
msg("%s's spell fizzles.", buf);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// returns a number between min & max
|
||||
// if blessed, always the max
|
||||
// if cursed, always the min
|
||||
int getspellduration(int min,int max,int blessed) {
|
||||
int howlong;
|
||||
switch (blessed) {
|
||||
case B_BLESSED:
|
||||
howlong = max; break;
|
||||
case B_CURSED:
|
||||
howlong = min; break;
|
||||
default:
|
||||
case B_UNCURSED:
|
||||
howlong = rnd(min,max); break;
|
||||
}
|
||||
return howlong;
|
||||
}
|
||||
|
||||
// magically propel an object into lf's hands.
|
||||
// if it's too big it'll hit them!
|
||||
void pullobto(object_t *o, lifeform_t *lf) {
|
||||
|
@ -1701,7 +2067,7 @@ void pullobto(object_t *o, lifeform_t *lf) {
|
|||
}
|
||||
|
||||
// can we pick up the object?
|
||||
if (hasflag(o->flags, F_NOPICKUP) || hasflag(o->flags, F_IMPASSABLE) || !canpickup(lf, o)) {
|
||||
if (hasflag(o->flags, F_NOPICKUP) || hasflag(o->flags, F_IMPASSABLE) || !canpickup(lf, o, ALL)) {
|
||||
char buf[BUFLEN];
|
||||
int dir;
|
||||
cell_t *obloc,*newcell;
|
||||
|
@ -1731,7 +2097,7 @@ void pullobto(object_t *o, lifeform_t *lf) {
|
|||
if (isplayer(lf) || haslos(player, lf->cell)) {
|
||||
msg("%s %s %s.", lfname, isplayer(lf) ? "catch" : "catches", obname);
|
||||
}
|
||||
pickup(lf, o, o->amt);
|
||||
pickup(lf, o, o->amt, B_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1778,6 +2144,25 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i
|
|||
return *targcell;
|
||||
}
|
||||
|
||||
// returns the amount if IQ needed to learn this spell
|
||||
// required intelligence is 9 + spelllevel
|
||||
// ie. spelllev1 needs 9+ intelligence
|
||||
// ie. spelllev7 needs 16+ intelligence
|
||||
int getiqreq(enum OBTYPE oid) {
|
||||
flag_t *f;
|
||||
objecttype_t *ot;
|
||||
int iqreq = 0;
|
||||
ot = findot(oid);
|
||||
if (!ot) {
|
||||
return 0;
|
||||
}
|
||||
f = hasflag(ot->flags, F_SPELLLEVEL);
|
||||
if (f) {
|
||||
iqreq = 9 + f->val[0];
|
||||
}
|
||||
return iqreq;
|
||||
}
|
||||
|
||||
int getmpcost(enum OBTYPE oid) {
|
||||
flag_t *f;
|
||||
objecttype_t *ot;
|
||||
|
|
2
spell.h
2
spell.h
|
@ -5,7 +5,9 @@
|
|||
int abilityeffects(lifeform_t *user, enum OBTYPE abilid);
|
||||
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer);
|
||||
void fizzle(lifeform_t *caster);
|
||||
int getiqreq(enum OBTYPE oid);
|
||||
int getmpcost(enum OBTYPE oid);
|
||||
int getspellduration(int min,int max,int blessed);
|
||||
void pullobto(object_t *o, lifeform_t *lf);
|
||||
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof);
|
||||
lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
|
||||
|
|
14
text.c
14
text.c
|
@ -16,6 +16,20 @@ char *capitalise(char *text) {
|
|||
return text;
|
||||
}
|
||||
|
||||
char *capitaliseall(char *text) {
|
||||
if (strlen(text) > 0) {
|
||||
char *p;
|
||||
for (p = text ; *p; p++) {
|
||||
if (p == text) { // first letter
|
||||
*p = toupper(*p);
|
||||
} else if (*(p-1) == ' ') { // first letter after a space
|
||||
*p = toupper(*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
char *getattrname(enum ATTRIB att) {
|
||||
switch (att) {
|
||||
case A_STR:
|
||||
|
|
Loading…
Reference in New Issue