This commit is contained in:
Rob Pearce 2011-08-17 20:57:43 +00:00
parent 907ed43e40
commit 16fb58c3cf
14 changed files with 518 additions and 179 deletions

6
ai.c
View File

@ -88,9 +88,9 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
} }
// become hostile? // become hostile?
if (!hasflag(lf->flags, F_HOSTILE)) { if (isplayer(victim) && !hasflag(lf->flags, F_HOSTILE) ) {
addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
innocentattack = 1; //innocentattack = 1;
} }
// change allegience ? // change allegience ?
@ -104,7 +104,7 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
// no longer a pet // no longer a pet
f = lfhasflagval(lf, F_PETOF, victim->id, NA, NA, NULL); f = lfhasflagval(lf, F_PETOF, victim->id, NA, NA, NULL);
if (f) { if (f) {
innocentattack = 3; if (isplayer(victim)) innocentattack = 3;
killflag(f); killflag(f);
} }

View File

@ -111,10 +111,26 @@ void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *
// figure out reduced damage value // figure out reduced damage value
if (dam) { if (dam) {
int ar;
newdam = *dam; newdam = *dam;
ar = getarmourrating(lf, NULL, NULL, NULL);
// if you did at least one damage...
if ((*dam >= 1) && (reduceamt >= 0)) { if ((*dam >= 1) && (reduceamt >= 0)) {
int lowerlimit = 0,divideby;
// reduce it.
newdam -= reduceamt; newdam -= reduceamt;
limit(&newdam, 1, NA); // don't reduce to <1 damage
// you will always take at least 1 hp of damage for every (ar/2) damage.
// ie. if you took ar/2 damage, you take at least 1.
// ie. if you took ar damage, you take at least 2.
// ie. if you took ar*2 damage, you take at least 3.
// stop at 3.
divideby = ar/2;
if (divideby <= 0) divideby = 1;
lowerlimit = (*dam / divideby);
limit(&lowerlimit, 0, 3);
limit(&newdam, lowerlimit, NA); // don't reduce too far.
} }
if (db) { if (db) {
@ -811,7 +827,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
strcpy(attackverb, getattackverb(lf, wep, damtype[i],dam[i],victim->maxhp)); strcpy(attackverb, getattackverb(lf, wep, damtype[i],dam[i],victim->maxhp));
if ((dam[i] == 0) && (damtype[i] != DT_TOUCH)) { if ((dam[i] == 0) && (damtype[i] != DT_TOUCH)) {
nodam = B_TRUE; nodam = B_TRUE;
strcpy(nodamstr, " but does no damage"); strcpy(nodamstr, " ineffectually");
} else { } else {
strcpy(nodamstr, ""); strcpy(nodamstr, "");
} }

Binary file not shown.

7
defs.h
View File

@ -2352,6 +2352,10 @@ enum PIETYLEV {
#define B_FALSE (0) #define B_FALSE (0)
#define B_TRUE (-1) #define B_TRUE (-1)
#define B_VIS (1)
#define B_UNKNOWN (0)
#define B_NOVIS (-1)
#define B_KEEPLOF (-1) #define B_KEEPLOF (-1)
#define B_MALE (0) #define B_MALE (0)
@ -2807,6 +2811,9 @@ typedef struct lifeform_s {
int nlos; int nlos;
cell_t **los; cell_t **los;
int *viscell;
int visw;
int visrange;
// set to TRUE after lf has being created // set to TRUE after lf has being created
int born; int born;

24
flag.c
View File

@ -3,6 +3,7 @@
#include <string.h> #include <string.h>
#include "defs.h" #include "defs.h"
#include "flag.h" #include "flag.h"
#include "god.h"
#include "io.h" #include "io.h"
#include "lf.h" #include "lf.h"
#include "map.h" #include "map.h"
@ -17,6 +18,9 @@ extern enum GAMEMODE gamemode;
extern int needredraw; extern int needredraw;
extern int statdirty; extern int statdirty;
extern lifeform_t *godlf[];
extern int ngodlfs;
extern lifeform_t *player; extern lifeform_t *player;
int flagdb = B_FALSE; int flagdb = B_FALSE;
@ -684,6 +688,11 @@ void killflag(flag_t *f) {
map_t *redolight = NULL; map_t *redolight = NULL;
int redostat = B_FALSE; int redostat = B_FALSE;
int redoscreen = B_FALSE; int redoscreen = B_FALSE;
int i,dopleasegod[MAXGODS];
for (i = 0; i < ngodlfs; i++) {
dopleasegod[i] = 0;
}
lf = f->pile->owner; lf = f->pile->owner;
@ -705,6 +714,16 @@ void killflag(flag_t *f) {
if (lf && (isplayer(lf) || cansee(player, lf))) { if (lf && (isplayer(lf) || cansee(player, lf))) {
redolight = lf->cell->map; redolight = lf->cell->map;
} }
} else if (f->id == F_FLEEFROM) {
if (lf && lf->cell) {
lifeform_t *fleefrom;
fleefrom = findlf(lf->cell->map, f->val[0]);
// ie. this lf was fleeing from the player, and
// got away.
if (isplayer(fleefrom) && !cansee(lf, fleefrom)) {
dopleasegod[R_GODMERCY] += 5;
}
}
} }
} }
@ -792,6 +811,11 @@ void killflag(flag_t *f) {
updatefpindex(f->pile); updatefpindex(f->pile);
if (gamemode == GM_GAMESTARTED) { if (gamemode == GM_GAMESTARTED) {
for (i = 0; i < ngodlfs; i++) {
if (dopleasegod[i]) {
pleasegodmaybe(godlf[i]->race->id, dopleasegod[i]);
}
}
if (redolight) { if (redolight) {
calclight(redolight); calclight(redolight);
precalclos(player); precalclos(player);

18
god.c
View File

@ -97,11 +97,20 @@ void angergod(enum RACE rid, int amt) {
// then... // then...
if (piety > -100) { if (piety > -100) {
int i,n; int i,n;
lifeform_t *l;
// minor bad stuff // minor bad stuff
switch (rid) { switch (rid) {
case R_GODDEATH: case R_GODDEATH:
castspell(god, OT_S_PAIN, player, NULL, player->cell); castspell(god, OT_S_PAIN, player, NULL, player->cell);
castspell(god, OT_S_DRAINLIFE, player, NULL, player->cell); castspell(god, OT_S_DRAINLIFE, player, NULL, player->cell);
// all undead in sight become hostile
for (l = player->cell->map->lf ; l ; l = l->next) {
if (!isplayer(l) && isundead(l) && cansee(l, player)) {
if (getallegiance(l) != AL_HOSTILE) {
aiattack(l, player, PERMENANT);
}
}
}
break; break;
case R_GODTHIEVES: case R_GODTHIEVES:
// take a random object // take a random object
@ -139,12 +148,21 @@ void angergod(enum RACE rid, int amt) {
} }
} else if (piety > -200) { } else if (piety > -200) {
object_t *o; object_t *o;
lifeform_t *l;
int n,i; int n,i;
// major bad stuff // major bad stuff
switch (god->race->id) { switch (god->race->id) {
case R_GODDEATH: case R_GODDEATH:
castspell(god, OT_S_PAIN, player, NULL, player->cell); castspell(god, OT_S_PAIN, player, NULL, player->cell);
castspell(god, OT_S_DRAINLIFE, player, NULL, player->cell); castspell(god, OT_S_DRAINLIFE, player, NULL, player->cell);
// all undead in sight become hostile
for (l = player->cell->map->lf ; l ; l = l->next) {
if (!isplayer(l) && isundead(l) && cansee(l, player)) {
if (getallegiance(l) != AL_HOSTILE) {
aiattack(l, player, PERMENANT);
}
}
}
switch (rnd(1,2)) { switch (rnd(1,2)) {
case 1: case 1:
msg("\"This will teach you some humility, mortal!\""); msg("\"This will teach you some humility, mortal!\"");

1
io.c
View File

@ -6037,6 +6037,7 @@ void drawlevelfor(lifeform_t *lf) {
if (db) dblog("ending DRAWLEVEL"); if (db) dblog("ending DRAWLEVEL");
sprintf(buf, "end. ndrawn was %d",ndrawn); sprintf(buf, "end. ndrawn was %d",ndrawn);
if (db) dblog("%s",buf);
//dbtimeend(buf); //dbtimeend(buf);
// move cursor to the player's position and blit // move cursor to the player's position and blit
if (ndrawn) { if (ndrawn) {

592
lf.c
View File

@ -195,32 +195,40 @@ void bleed(lifeform_t *lf) {
} }
} }
void breakallgrabs(lifeform_t *lf) { void breakgrabs(lifeform_t *lf, int fromme, int tome) {
flag_t *f; flag_t *f;
lifeform_t *alf; lifeform_t *alf;
f = lfhasflag(lf, F_GRABBING); if (fromme) {
if (f) { f = lfhasflag(lf, F_GRABBING);
lifeform_t *grabee; if (f) {
grabee = findlf(NULL, f->val[0]); lifeform_t *grabee;
assert(grabee); grabee = findlf(NULL, f->val[0]);
killflagsofid(grabee->flags, F_GRABBEDBY); assert(grabee);
killflagsofid(lf->flags, F_GRABBING); killflagsofid(grabee->flags, F_GRABBEDBY);
} killflagsofid(lf->flags, F_GRABBING);
f = lfhasflag(lf, F_GRABBEDBY); }
if (f) { f = lfhasflag(lf, F_ATTACHEDTO);
lifeform_t *graber;
graber = findlf(NULL, f->val[0]);
assert(graber);
killflagsofid(graber->flags, F_GRABBING);
killflagsofid(lf->flags, F_GRABBEDBY);
}
for (alf = lf->cell->map->lf ; alf ; alf = alf->next) {
f = lfhasflagval(alf, F_ATTACHEDTO, lf->id, NA, NA, NULL);
if (f) { if (f) {
killflag(f); killflag(f);
} }
} }
if (tome) {
f = lfhasflag(lf, F_GRABBEDBY);
if (f) {
lifeform_t *graber;
graber = findlf(NULL, f->val[0]);
assert(graber);
killflagsofid(graber->flags, F_GRABBING);
killflagsofid(lf->flags, F_GRABBEDBY);
}
for (alf = lf->cell->map->lf ; alf ; alf = alf->next) {
f = lfhasflagval(alf, F_ATTACHEDTO, lf->id, NA, NA, NULL);
if (f) {
killflag(f);
}
}
}
} }
long calcscore(lifeform_t *lf) { long calcscore(lifeform_t *lf) {
@ -3281,6 +3289,13 @@ int flee(lifeform_t *lf) {
flag_t *f; flag_t *f;
lifeform_t *fleefrom = NULL; lifeform_t *fleefrom = NULL;
int i; int i;
int db = B_FALSE;
char lfname[BUFLEN];
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
real_getlfname(lf, lfname, B_FALSE);
// mindless? // mindless?
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) == IQ_MINDLESS) { if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) == IQ_MINDLESS) {
@ -3304,16 +3319,16 @@ int flee(lifeform_t *lf) {
// if we can't see the person we're running from, and it's not enforced for // if we can't see the person we're running from, and it's not enforced for
// a certain time period (ie. f->lifetime == PERMENANT), we can now stop fleeing. // a certain time period (ie. f->lifetime == PERMENANT), we can now stop fleeing.
if (f->lifetime == PERMENANT) { if (f->lifetime == PERMENANT) {
// player let something flee?
if (isplayer(thisone)) {
pleasegodmaybe(R_GODMERCY, 5);
angergodmaybe(R_GODDEATH, 25);
}
killflag(f); killflag(f);
} else { } else {
// if the flag is temporary, keep fleeing and wait for it to time out normally // if the flag is temporary, keep fleeing and wait for it to time out normally
fleefrom = thisone; fleefrom = thisone;
} }
// player let something flee?
if (isplayer(thisone)) {
pleasegodmaybe(R_GODMERCY, 5);
angergodmaybe(R_GODDEATH, 25);
}
} }
} }
} }
@ -3323,7 +3338,9 @@ int flee(lifeform_t *lf) {
if (fleefrom) { if (fleefrom) {
object_t *stairs; object_t *stairs;
breakallgrabs(lf); if (db) dblog("%s - fleeing from %s", lfname, fleefrom->race->name);
breakgrabs(lf, B_TRUE, B_FALSE); // stop grabbing anyone
// ways of fleeing other than movement? // ways of fleeing other than movement?
if (!isplayer(lf)) { if (!isplayer(lf)) {
@ -3339,14 +3356,23 @@ int flee(lifeform_t *lf) {
aigetspelltarget(lf, findot(spell), fleefrom, &targlf, &targcell, &targob, F_AICASTTOFLEE); aigetspelltarget(lf, findot(spell), fleefrom, &targlf, &targcell, &targob, F_AICASTTOFLEE);
if (getschool(spell) == SS_ABILITY) { if (getschool(spell) == SS_ABILITY) {
return useability(lf, spell, targlf, targcell); if (db) dblog("%s - using ability %s to flee", sp->name);
if (!useability(lf, spell, targlf, targcell)) {
if (db) dblog("%s - success.", lfname);
return B_TRUE;
}
} else { } else {
return castspell(lf, spell, targlf, targob, targcell); if (db) dblog("%s - casting %s to flee", sp->name);
if (!castspell(lf, spell, targlf, targob, targcell)) {
if (db) dblog("%s - success.", lfname);
return B_TRUE;
}
} }
} }
// if AI, use helpful fleeing items // if AI, use helpful fleeing items
if (!useitemwithflag(lf, F_AIFLEEITEM)) { if (!useitemwithflag(lf, F_AIFLEEITEM)) {
return B_FALSE; if (db) dblog("%s - used an item to flee", lfname);
return B_TRUE;
} }
} }
@ -3362,13 +3388,16 @@ int flee(lifeform_t *lf) {
stairs = hasobwithflag(lf->cell->obpile, F_CLIMBABLE); stairs = hasobwithflag(lf->cell->obpile, F_CLIMBABLE);
if (stairs) { if (stairs) {
if (!usestairs(lf, stairs, B_TRUE)) { if (!usestairs(lf, stairs, B_TRUE)) {
if (db) dblog("%s - fleeing via %s", stairs->type->name);
return B_TRUE; return B_TRUE;
} }
} }
// move away from them // move away from them
if (!moveawayfrom(lf, fleefrom->cell, DT_ORTH, B_FALSE)) { if (!moveawayfrom(lf, fleefrom->cell, DT_ORTH, B_FALSE)) {
if (db) dblog("%s - fleeing by moving away", lfname);
return B_TRUE; return B_TRUE;
} }
if (db) dblog("%s - failed to flee!", lfname);
} }
// if we get here, it means we didn't need to or couldn't flee // if we get here, it means we didn't need to or couldn't flee
@ -3404,7 +3433,7 @@ void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong, int onpurpose) {
// already fleeing? // already fleeing?
f = hasflagval(lf->flags, F_FLEEFROM, enemy->id, NA, NA, NULL); f = hasflagval(lf->flags, F_FLEEFROM, enemy->id, NA, NA, NULL);
if (f) { if (f) {
// update time // just update time
if (f->lifetime != PERMENANT) { if (f->lifetime != PERMENANT) {
if (f->lifetime < howlong) { if (f->lifetime < howlong) {
f->lifetime = howlong; f->lifetime = howlong;
@ -3413,6 +3442,10 @@ void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong, int onpurpose) {
} else { } else {
addtempflag(lf->flags, F_FLEEFROM, enemy->id, NA, NA, NULL, howlong); addtempflag(lf->flags, F_FLEEFROM, enemy->id, NA, NA, NULL, howlong);
} }
// stop targetting anyone or going anywhere
killflagsofid(lf->flags, F_TARGETLF);
killflagsofid(lf->flags, F_TARGETCELL);
} }
int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong) { int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong) {
@ -7434,6 +7467,231 @@ int haslof(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest) {
return B_TRUE; return B_TRUE;
} }
void idxtoxy(lifeform_t *lf, int idx, int *x, int *y) {
int xoffset,yoffset;
// get the offset form the lf's position.
xoffset = (idx % lf->visw) - lf->visrange;
yoffset = (idx / lf->visw) - lf->visrange;
// return the actual cell there
*x = lf->cell->x + xoffset;
*y = lf->cell->y + yoffset;
}
// confirmed good!
int xytoidx(lifeform_t *lf, int x, int y) {
int idx;
int xd,yd;
if (abs(x - lf->cell->x) > lf->visrange) return -1;
if (abs(y - lf->cell->y) > lf->visrange) return -1;
xd = lf->cell->x - lf->visrange;
yd = lf->cell->y - lf->visrange;
idx = (y - yd) * lf->visw + (x - xd);
return idx;
}
void setviscell(lifeform_t *lf, cell_t *cell, int how) {
int idx;
int x,y;
cell_t *c;
idx = xytoidx(lf, cell->x, cell->y);
assert(idx >= 0);
assert(idx < (lf->visw * lf->visw));
lf->viscell[idx] = how;
// checks
if (how == B_VIS) {
assert (abs(lf->cell->x - cell->x) <= 10);
assert (abs(lf->cell->y - cell->y) <= 10);
}
idxtoxy(lf, idx, &x, &y);
c = getcellat(lf->cell->map, x, y);
assert(c);
}
int getviscell(lifeform_t *lf, cell_t *cell) {
int idx;
idx = xytoidx(lf, cell->x, cell->y);
if ((idx < 0) || (idx >= (lf->visw * lf->visw)) ) {
return B_NOVIS;
}
return lf->viscell[idx];
}
// find los, remembering cells on the way
void calclos(lifeform_t *viewer, cell_t *dest) {
int numpixels;
int i,n;
int x1,y1;
int maxvisrange;
int nightvisrange;
int xray = 0;
flag_t *f;
int x2,y2;
map_t *map;
object_t *o;
int currange;
cell_t *retcell[MAXRETCELLS];
int allbad = B_FALSE;
if (!viewer) return ;
if (!dest) return ;
if (!viewer->cell) return ;
if (viewer->cell->map != dest->map) return ;
map = dest->map;
x1 = viewer->cell->x;
y1 = viewer->cell->y;
x2 = dest->x;
y2 = dest->y;
// find the path of cells
calcbresnham(map, x1, y1, x2, y2, retcell, &numpixels);
// can't see if you're blind
if (isblind(viewer)) {
allbad = 1;
}
maxvisrange = getvisrange(viewer);
nightvisrange = getnightvisrange(viewer);
//origheight = getheight(x1,y1,z);
if (allbad) {
// mark all as bad
for (i = 0; i < numpixels; i++ ){
setviscell(viewer, retcell[i], B_VIS);
}
return;
}
f = hasflag(viewer->flags, F_XRAYVIS);
if (f) {
xray = f->val[0];
} else {
xray = 0;
}
//shopwall = B_FALSE;
currange = 0;
for (i = 0; i < numpixels ; i++) {
cell_t *cell;
int cellopaque = B_FALSE;
int celldark = B_FALSE;
cell = retcell[i];
//already can't see this one?
if (getviscell(viewer, cell) == B_NOVIS) {
break;
}
if ((cell->x == x2) && (cell->y == y2)) {
// made it to the last cell
setviscell(viewer, cell, B_VIS);
return;
}
if (i == 0) {
// you can always see your own cell
setviscell(viewer, cell, B_VIS);
continue;
}
currange++;
if (currange > maxvisrange) {
break;
}
// check cell type
if (!cell->type->transparent) {
cellopaque = -1; // fullblock
}
// now check lighting
if (!cellopaque) {
// outside the range of our light, and not lit
if (getcelldist(viewer->cell, cell) > nightvisrange) {
if (!islit(cell)) {
celldark = B_TRUE;
}
} else {
// inside our nightvis range and magically dark
if (cell->lit == L_PERMDARK) {
celldark = B_TRUE;
}
}
}
// check for objects which block view
if (!cellopaque && !celldark) {
for (o = cell->obpile->first ; o ; o = o->next) {
f = hasflag(o->flags, F_BLOCKSVIEW);
if (f) {
if (!lfhasflagval(viewer, F_CANSEETHROUGHMAT, o->material->id, NA, NA, NULL)) {
if (f->val[0] == B_TRUE) {
cellopaque = -1; // fullblock
break;
} else {
cellopaque += f->val[0];
}
}
}
}
}
if (cellopaque) {
if (xray) {
xray--;
} else {
if (cellopaque == -1) {
// can see this one but not the rest.
setviscell(viewer, cell, B_VIS);
i++;
break;
} else {
currange += cellopaque;
if (currange > maxvisrange) {
// can see this one but not the rest.
setviscell(viewer, cell, B_VIS);
i++;
break;
}
}
}
}
// xray vision decreases by one
if (xray) xray--;
// this cell is visible (unless it's dark)
if (celldark) {
setviscell(viewer, cell, B_NOVIS);
} else {
setviscell(viewer, cell, B_VIS);
}
}
// rest of cells are not visible.
for (n = i; n < numpixels; n++) {
setviscell(viewer, retcell[n], B_NOVIS);
}
}
int haslos(lifeform_t *viewer, cell_t *dest) { int haslos(lifeform_t *viewer, cell_t *dest) {
int numpixels; int numpixels;
int i; int i;
@ -7463,6 +7721,7 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
// can we use pre-calced los? // can we use pre-calced los?
// //
if ((viewer->cell->map->lf == viewer) && viewer->los) { if ((viewer->cell->map->lf == viewer) && viewer->los) {
for (i = 0;i < viewer->nlos; i++) { for (i = 0;i < viewer->nlos; i++) {
if (viewer->los[i] == dest) { if (viewer->los[i] == dest) {
@ -7626,7 +7885,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_SS_DIVINATION, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_DIVINATION, PR_MASTER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_MENTAL, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_MENTAL, PR_MASTER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_SUMMONING, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_SUMMONING, PR_MASTER, NA, NULL);
addflag(lastjob->flags, F_HASPET, NA, NA, NA, "young wolf"); //addflag(lastjob->flags, F_HASPET, NA, NA, NA, "young wolf");
for (i = 1; i < MAXSKILLS; i++) { for (i = 1; i < MAXSKILLS; i++) {
addflag(lastjob->flags, F_CANLEARN, i, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, i, NA, NA, NULL);
} }
@ -11378,7 +11637,10 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
// for precalcing line of sight // for precalcing line of sight
a->nlos = 0; a->nlos = 0;
a->los = NULL; //a->los = malloc(sizeof(cell_t *) * MAXVISRANGE);
a->los = malloc( sizeof(cell_t *) * ((MAXVISRANGE*2+1)*(MAXVISRANGE*2+1)));
//a->viscell = NULL;
a->viscell = malloc( sizeof(int) * ((MAXVISRANGE*2+1)*(MAXVISRANGE*2+1)));
// for ai // for ai
@ -12990,168 +13252,163 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha
// if anything nearby hears it, it might respond // if anything nearby hears it, it might respond
for (l = c->map->lf; l ; l = l->next) { for (l = c->map->lf; l ; l = l->next) {
int dist; int dist;
int difficulty;
int lbonus;
if (l == noisemaker) continue;
// ie. if this lf is in the process of swapping places // ie. if this lf is in the process of swapping places
if (!l->cell) continue; if (!l->cell) continue;
// if you make a noise while swapping position with
// something, its ->cell will be null here!
dist = getcelldist(l->cell, c); dist = getcelldist(l->cell, c);
if (l != noisemaker) { // listen check difficulty is based on sound distance vs max hearing distance
int difficulty; if (nt == NC_SPEECH) {
int lbonus; // you always hear it, as long as you're in range
//if (canhear(l, c) && haslos(l, c)) { difficulty = 0;
} else {
//difficulty = (int) ( ((float)getcelldist(l->cell, c) / (float)gethearingrange(l)) * 20);
difficulty = (int) ( ((float)getcelldist(l->cell, c) / ((float)gethearingrange(l) + volume)) * 20);
}
// listen bonus is the sound volume
lbonus = volume;
if (lfhasflag(l, F_ASLEEP)) {
lbonus -= 5;
limit(&lbonus, 0, NA);
}
// listen check difficulty is based on sound distance vs max hearing distance // skillcheck to hear this
if (nt == NC_SPEECH) { if ( (isplayer(l) && haslos(l, c)) || // only player can "hear by seeing"
// you always hear it, as long as you're in range (canhear(l, c, volume) && skillcheck(l, SC_LISTEN, difficulty, lbonus)) ) {
difficulty = 0; flag_t *f;
} else { // announce?
//difficulty = (int) ( ((float)getcelldist(l->cell, c) / (float)gethearingrange(l)) * 20); if (isplayer(l) && !lfhasflag(l, F_ASLEEP)) {
difficulty = (int) ( ((float)getcelldist(l->cell, c) / ((float)gethearingrange(l) + volume)) * 20); // never say "you hear xxx" if you can see the lf that caused the noise.
} if (noisemaker && cansee(l, noisemaker)) {
if (seetext) {
char lfname[BUFLEN];
getlfname(noisemaker, lfname);
msg("%s %s.", lfname, seetext);
rv = B_TRUE;
}
} else if (text && ((nt == NC_SPEECH) || !lfhasflag(l, F_DONELISTEN))) {
char textnopunc[BUFLEN];
char punc;
int dist;
// listen bonus is the sound volume //punc = text[strlen(text)-1];
lbonus = volume; //strncpy(textnopunc, text, strlen(text)-1);
if (lfhasflag(l, F_ASLEEP)) { strcpy(textnopunc, text);
lbonus -= 5; punc = textnopunc[strlen(textnopunc)-1];
limit(&lbonus, 0, NA); textnopunc[strlen(textnopunc)-1] = '\0';
}
// skillcheck to hear this dist = getcelldist(l->cell, c);
if ( (haslos(l, c) ||
(canhear(l, c, volume) && skillcheck(l, SC_LISTEN, difficulty, lbonus)))) { // listen skill gives you more info about monsters
flag_t *f; if (noisemaker) {
// announce? enum SKILLLEVEL slev;
if (isplayer(l) && !lfhasflag(l, F_ASLEEP)) { char lfname[BUFLEN];
// never say "you hear xxx" if you can see the lf that caused the noise. char distbuf[BUFLEN];
if (noisemaker && cansee(l, noisemaker)) { char dirbuf[BUFLEN];
if (seetext) { int dir;
char lfname[BUFLEN];
getlfname(noisemaker, lfname); real_getlfnamea(noisemaker, lfname, B_FALSE);
msg("%s %s.", lfname, seetext); if (dist >= 20) {
rv = B_TRUE; strcpy(distbuf, " far away");
} else if (dist >= 10) {
strcpy(distbuf, "");
} else if (dist >= 5) {
strcpy(distbuf, " nearby");
} else {
strcpy(distbuf, " very nearby");
} }
} else if (text && ((nt == NC_SPEECH) || !lfhasflag(l, F_DONELISTEN))) {
char textnopunc[BUFLEN];
char punc;
int dist;
//punc = text[strlen(text)-1]; dir = getdirtowards(l->cell, c, NULL, B_FALSE, DT_COMPASS);
//strncpy(textnopunc, text, strlen(text)-1); strcpy(dirbuf, getdirname(dir));
strcpy(textnopunc, text); dirbuf[0] = tolower(dirbuf[0]);
punc = textnopunc[strlen(textnopunc)-1];
textnopunc[strlen(textnopunc)-1] = '\0'; slev = getskill(l, SK_LISTEN);
//
dist = getcelldist(l->cell, c); // high listen skill lets you know more info.
//
// listen skill gives you more info about monsters // beginner = distance
if (noisemaker) { // adept = distance and direction
enum SKILLLEVEL slev; // expert = monstername and distance and direction
char lfname[BUFLEN]; // master = temporary scan of where they are!
char distbuf[BUFLEN]; if (slev >= PR_MASTER) {
char dirbuf[BUFLEN]; flag_t *f;
int dir; f = lfhasflagval(l, F_CANHEARLF, noisemaker->id, NA, NA, NULL);
if (f) {
real_getlfnamea(noisemaker, lfname, B_FALSE); if (f->lifetime > 0) f->lifetime = 2;
if (dist >= 20) {
strcpy(distbuf, " far away");
} else if (dist >= 10) {
strcpy(distbuf, "");
} else if (dist >= 5) {
strcpy(distbuf, " nearby");
} else { } else {
strcpy(distbuf, " very nearby"); addtempflag(l->flags, F_CANHEARLF, noisemaker->id, NA, NA, NULL, 2);
}
dir = getdirtowards(l->cell, c, NULL, B_FALSE, DT_COMPASS);
strcpy(dirbuf, getdirname(dir));
dirbuf[0] = tolower(dirbuf[0]);
slev = getskill(l, SK_LISTEN);
//
// high listen skill lets you know more info.
//
// beginner = distance
// adept = distance and direction
// expert = monstername and distance and direction
// master = temporary scan of where they are!
if (slev >= PR_MASTER) {
flag_t *f;
f = lfhasflagval(l, F_CANHEARLF, noisemaker->id, NA, NA, NULL);
if (f) {
if (f->lifetime > 0) f->lifetime = 2;
} else {
addtempflag(l->flags, F_CANHEARLF, noisemaker->id, NA, NA, NULL, 2);
}
} else if (slev >= PR_EXPERT) {
msg("You hear %s%s to the %s%c", lfname, distbuf, dirbuf, punc);
rv = B_TRUE;
} else if (slev >= PR_ADEPT) {
msg("You hear %s%s to the %s%c", textnopunc, distbuf, dirbuf, punc);
rv = B_TRUE;
} else if (slev >= PR_BEGINNER) {
msg("You hear %s%s%c", textnopunc, distbuf, punc);
rv = B_TRUE;
} else {
msg("You hear %s", text);
rv = B_TRUE;
} }
} else if (slev >= PR_EXPERT) {
msg("You hear %s%s to the %s%c", lfname, distbuf, dirbuf, punc);
rv = B_TRUE;
} else if (slev >= PR_ADEPT) {
msg("You hear %s%s to the %s%c", textnopunc, distbuf, dirbuf, punc);
rv = B_TRUE;
} else if (slev >= PR_BEGINNER) {
msg("You hear %s%s%c", textnopunc, distbuf, punc);
rv = B_TRUE;
} else { } else {
msg("You hear %s", text); msg("You hear %s", text);
rv = B_TRUE; rv = B_TRUE;
} }
// only hear one thing per turn. } else {
if (isplayer(l)) { msg("You hear %s", text);
addflag(l->flags, F_DONELISTEN, B_TRUE, NA, NA, NULL); rv = B_TRUE;
practice(l, SK_LISTEN, 1); }
} // only hear one thing per turn.
if (isplayer(l)) {
addflag(l->flags, F_DONELISTEN, B_TRUE, NA, NA, NULL);
practice(l, SK_LISTEN, 1);
} }
} }
// wake up a little }
f = lfhasflag(l, F_ASLEEP);
if (f) { // wake up a little
if (f->lifetime > 0) { // ie. temporary f = lfhasflag(l, F_ASLEEP);
timeeffectsflag(f, volume + rnd(1,3)); if (f) {
} else if (f->lifetime == PERMENANT) { if (f->lifetime > 0) { // ie. temporary
if (f->val[2] == NA) { // ie asleep rather than 'resting' timeeffectsflag(f, volume + rnd(1,3));
} else if (f->lifetime == PERMENANT) {
if (f->val[2] == NA) { // ie asleep rather than 'resting'
// wake up!
if (isplayer(l)) {
msg("^wA nearby noise awakens you!");
rv = B_TRUE;
}
killflag(f);
} else {
// ie resting on purpose via 'R'
// only wake up if the sound if very close
//if (getcelldist(c, l->cell) == 1) {
if (volume >= getcelldist(c, l->cell)) {
// wake up! // wake up!
if (isplayer(l)) { if (isplayer(l)) {
msg("^wA nearby noise awakens you!"); char wakenoise[BUFLEN];
strcpy(wakenoise, text);
wakenoise[strlen(wakenoise)-1] = '\0'; // omit punctuation
//msg("A nearby noise awakens you!");
msg("^wThe sound of %s awakens you!", wakenoise);
rv = B_TRUE; rv = B_TRUE;
} }
killflag(f); killflag(f);
} else {
// ie resting on purpose via 'R'
// only wake up if the sound if very close
//if (getcelldist(c, l->cell) == 1) {
if (volume >= getcelldist(c, l->cell)) {
// wake up!
if (isplayer(l)) {
char wakenoise[BUFLEN];
strcpy(wakenoise, text);
wakenoise[strlen(wakenoise)-1] = '\0'; // omit punctuation
//msg("A nearby noise awakens you!");
msg("^wThe sound of %s awakens you!", wakenoise);
rv = B_TRUE;
}
killflag(f);
}
} }
// make it temporary
//f->lifetime = rnd(1,10);
} }
// make it temporary
//f->lifetime = rnd(1,10);
}
// still asleep? // still asleep?
if (lfhasflag(l, F_ASLEEP) && cansee(player, l)) { if (lfhasflag(l, F_ASLEEP) && cansee(player, l)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
getlfname(l, lfname); getlfname(l, lfname);
msg("%s stir%s in %s slumber...", lfname, msg("%s stir%s in %s slumber...", lfname,
isplayer(l) ? "" : "s", isplayer(l) ? "" : "s",
isplayer(l) ? "your" : "its"); isplayer(l) ? "your" : "its");
}
} }
} }
} }
@ -14877,7 +15134,8 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
roll = rolldie(1, 20); roll = rolldie(1, 20);
if (db) { if (db) {
sprintf(mbuf, "%s skillcheck - need %d, got %d(rll)+%d(attr)+%d(lvm)+%d(othmod)+%d(mod)=",lf->race->name, diff, roll, attrib,levmod, othermod,mod); sprintf(mbuf, "%s skillcheck (%d) - need %d, got %d(rll)+%d(attr)+%d(lvm)+%d(othmod)+%d(mod)=",lf->race->name,
ct, diff, roll, attrib,levmod, othermod,mod);
} }
modroll = roll; modroll = roll;
modroll += attrib; modroll += attrib;

6
lf.h
View File

@ -22,7 +22,7 @@ void autoweild(lifeform_t *lf);
int appearsrandomly(enum RACE rid); int appearsrandomly(enum RACE rid);
void awardxpfor(lifeform_t *killed, float pct); void awardxpfor(lifeform_t *killed, float pct);
void bleed(lifeform_t *lf); void bleed(lifeform_t *lf);
void breakallgrabs(lifeform_t *lf); void breakgrabs(lifeform_t *lf, int fromme, int tome);
long calcscore(lifeform_t *lf); long calcscore(lifeform_t *lf);
int calcxp(lifeform_t *lf); int calcxp(lifeform_t *lf);
int calcxprace(enum RACE rid); int calcxprace(enum RACE rid);
@ -145,6 +145,10 @@ int getmaxmp(lifeform_t *lf);
float getmaxpushweight(lifeform_t *lf); float getmaxpushweight(lifeform_t *lf);
int getmr(lifeform_t *lf); int getmr(lifeform_t *lf);
int getvisrange(lifeform_t *lf); int getvisrange(lifeform_t *lf);
void idxtoxy(lifeform_t *lf, int idx, int *x, int *y);
void setviscell(lifeform_t *lf, cell_t *cell, int how);
int getviscell(lifeform_t *lf, cell_t *cell);
int xytoidx(lifeform_t *lf, int x, int y);
int getmovespeed(lifeform_t *lf); int getmovespeed(lifeform_t *lf);
char *getmoveverb(lifeform_t *lf); char *getmoveverb(lifeform_t *lf);
char *getmoveverbother(lifeform_t *lf); char *getmoveverbother(lifeform_t *lf);

4
map.c
View File

@ -2033,7 +2033,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
enum HABITAT habitat; enum HABITAT habitat;
regionthing_t *thing[MAXOUTLINETHINGS]; regionthing_t *thing[MAXOUTLINETHINGS];
int nthings = 0; int nthings = 0;
int db = B_TRUE; int db = B_FALSE;
// determine habitat based on region // determine habitat based on region
// note: we might override this later based on our region outline // note: we might override this later based on our region outline
@ -2505,7 +2505,7 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r
int w,h,x,y; int w,h,x,y;
int xmargin = 0,ymargin = 0; int xmargin = 0,ymargin = 0;
int minx,miny,maxx,maxy; int minx,miny,maxx,maxy;
int db = B_TRUE; int db = B_FALSE;
int rotation = 0; int rotation = 0;
flag_t *f; flag_t *f;

11
move.c
View File

@ -695,7 +695,7 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
howfar *= 2; howfar *= 2;
} }
breakallgrabs(lf); breakgrabs(lf, B_TRUE, B_TRUE);
for (i = 0; i < howfar; i++) { for (i = 0; i < howfar; i++) {
if (moveclear(lf, dir, &reason)) { if (moveclear(lf, dir, &reason)) {
@ -983,11 +983,18 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// update new cell // update new cell
newcell->lf = lf; newcell->lf = lf;
/*
// update light // update light
if (lfproduceslight(lf) || (changedlev && isplayer(lf))) { if (lfproduceslight(lf) || (changedlev && isplayer(lf))) {
calclight(lf->cell->map); calclight(lf->cell->map);
precalclos(lf); precalclos(lf);
} }
*/
// update light
if (lfproduceslight(lf)) {
calclight(lf->cell->map);
}
precalclos(lf);
if (isplayer(lf) || cansee(player, lf)) { if (isplayer(lf) || cansee(player, lf)) {
needredraw = B_TRUE; needredraw = B_TRUE;
@ -1150,6 +1157,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// ISNT a vault, reveal it. // ISNT a vault, reveal it.
// //
/*
if ((getskill(lf, SK_CARTOGRAPHY) >= PR_NOVICE) && (!lf->cell->vault)) { if ((getskill(lf, SK_CARTOGRAPHY) >= PR_NOVICE) && (!lf->cell->vault)) {
if ((postroom > 0) && (postroom != preroom)) { if ((postroom > 0) && (postroom != preroom)) {
cell_t *c[MAX_MAPW*MAX_MAPH]; cell_t *c[MAX_MAPW*MAX_MAPH];
@ -1176,6 +1184,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
} }
*/
} }
// does anyone else see you? // does anyone else see you?

View File

@ -379,6 +379,7 @@ int main(int argc, char **argv) {
// show level (if required) // show level (if required)
//if (haslos(player, curmap->lf->cell)) { //if (haslos(player, curmap->lf->cell)) {
drawscreen(); drawscreen();
//dblog("**** END of turn, numdraws = %d", numdraws); //dblog("**** END of turn, numdraws = %d", numdraws);

View File

@ -4028,7 +4028,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else if (spellid == OT_S_GASEOUSFORM) { } else if (spellid == OT_S_GASEOUSFORM) {
if (!target) target = caster; if (!target) target = caster;
if (hasmr(target) && (target->race->id != R_VAMPIRE) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (getmr(target) && (target->race->id != R_VAMPIRE) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You feel momentarily insubstantial."); msg("You feel momentarily insubstantial.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -5822,7 +5822,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = addtempflag(target->flags, F_NONCORPOREAL, B_TRUE, NA, NA, NULL, howlong); f = addtempflag(target->flags, F_NONCORPOREAL, B_TRUE, NA, NA, NULL, howlong);
f->obfrom = OT_S_PASSWALL; f->obfrom = OT_S_PASSWALL;
breakallgrabs(caster); breakgrabs(target, B_TRUE, B_TRUE);
} else if (spellid == OT_S_POLYMORPH) { } else if (spellid == OT_S_POLYMORPH) {
race_t *r = NULL; race_t *r = NULL;
flag_t *f; flag_t *f;
@ -5930,6 +5930,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (haslos(player, target->cell)) { if (haslos(player, target->cell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
breakgrabs(target, B_TRUE, B_TRUE);
} else { } else {
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;

View File

@ -1,7 +1,7 @@
! filled with random monsters ! filled with random monsters
@id:monsterzoo @id:monsterzoo
@map @map
random(4,4) random(3,3,5,5)
@end @end
@legend @legend