- [+] Redo precalclos() code!

- [+] more haslos() improvements
* [+] fix god pleaseing when fleefrom expires
* [+] bug with pet running away
- [+] instead of "You hit xxx but do no damage", say "You hit xx
      ineffectually."
- [+] if you do  >half someone's AR, they always take at least 1 damage
- [+] initial objects aren't worth any points
This commit is contained in:
Rob Pearce 2011-08-20 04:14:39 +00:00
parent 16fb58c3cf
commit 9a3c2c69ba
11 changed files with 345 additions and 82 deletions

Binary file not shown.

5
defs.h
View File

@ -386,6 +386,7 @@ enum MODTYPE {
#define ANIMDELAY (1000000 / 50) // 1/100 of a second
#define MAXVISRANGE 10 // max visible range in full light
#define MAXVISLIMIT (MAXVISRANGE*8)
// askobject options
@ -1589,6 +1590,8 @@ enum FLAG {
// causes shops to show (worth $xx) after the ob's name.
// also used for detecting theft!
F_VALUE, // how much an item is worth (over its base weight+material)
F_NOPOINTS, // object is worth 0 points (but might still have a
// monetary value)
// weapon/armour flags
F_EQUIPPED, // val0 = where it is equipped. CLEAR WHEN OB MOVED!
F_GOESON, // val0 = where it can be equipped.
@ -2078,6 +2081,8 @@ enum FLAG {
F_ORIGRACE, // original player race (if you polymorphed)
F_ORIGJOB, // original player job (if you polymorphed)
F_POLYMORPHED, // lf has been polymorphed
F_RETAINHPMPONPOLY, // don't take on hp/mp of what you polymorph
// into
F_SHORTCUT, // spell keyboard shortcut.
// v0=slot (0-9)
// text=spell text

1
flag.c
View File

@ -17,6 +17,7 @@ int nretflags;
extern enum GAMEMODE gamemode;
extern int needredraw;
extern int statdirty;
extern void (*precalclos)(lifeform_t *);
extern lifeform_t *godlf[];
extern int ngodlfs;

2
io.c
View File

@ -2319,7 +2319,7 @@ void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int fi
if (showpoints && (mylist[i]->type->id != OT_GOLD)) {
long points;
points = getobvalue(mylist[i]);
points = getobpoints(mylist[i]);
sprintf(pointsbuf, " [%ld points]", points);
} else {
strcpy(pointsbuf, "");

369
lf.c
View File

@ -18,8 +18,12 @@
#include "spell.h"
#include "text.h"
extern double presin[];
extern double precos[];
extern FILE *logfile;
extern void (*precalclos)(lifeform_t *);
extern map_t *firstmap;
extern race_t *firstrace, *lastrace;
@ -239,7 +243,7 @@ long calcscore(lifeform_t *lf) {
}
// objects
for (o = lf->pack->first ; o ; o = o->next) {
points += getobvalue(o);
points += getobpoints(o);
}
// points for xp
points += (lf->xp / 10);
@ -1324,6 +1328,63 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
return rv;
}
int celllitfor(lifeform_t *lf, cell_t *c, int maxvisrange, int nightvisrange) {
// too far away
if (maxvisrange != UNLIMITED) {
if (getcelldist(lf->cell, c) > maxvisrange) {
return B_FALSE;
}
}
// outside the range of our light, and not lit
if (nightvisrange != UNLIMITED) {
if (getcelldist(lf->cell, c) > nightvisrange) {
if (!islit(c)) {
return B_FALSE;
}
} else {
// inside our nightvis range and magically dark
if (c->lit == L_PERMDARK) {
return B_FALSE;
}
}
}
return B_TRUE;
}
int celltransparentfor(lifeform_t *lf, cell_t *c, int *xray, int *rangemod) {
object_t *o;
flag_t *f;
if (rangemod) *rangemod = 0;
// solid cells stop los
if (!c->type->transparent) {
if (xray && *xray) (*xray)--;
else return B_FALSE;
}
// check for objects which block view
for (o = c->obpile->first ; o ; o = o->next) {
f = hasflag(o->flags, F_BLOCKSVIEW);
if (f) {
if (!lfhasflagval(lf, F_CANSEETHROUGHMAT, o->material->id, NA, NA, NULL)) {
if (xray && *xray) {
(*xray)--;
} else {
if (f->val[0] == B_TRUE) {
return B_FALSE;
} else {
if (rangemod) *rangemod += f->val[0];
}
}
}
}
}
return B_TRUE;
}
// returns TRUE if something happened.
int checkfordrowning(lifeform_t *lf, object_t *o) {
int depth,i;
@ -1708,6 +1769,7 @@ void die(lifeform_t *lf) {
}
}
if ((lf->race->id == R_VAMPIRE) && !hasflag(lf->flags, F_ORIGRACE)) {
// if are asleep or killed by running water/sunlight, we will die normally
if (lfhasflag(lf, F_ASLEEP) || (lf->lastdamtype == DT_DIRECT)) {
@ -1738,7 +1800,6 @@ void die(lifeform_t *lf) {
}
}
if (!willbecomeghost) {
lf->alive = B_FALSE;
}
@ -6796,6 +6857,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
object_t *o;
// give that weapon
o = addobfast(lf->pack, ot->id);
if (isplayer(lf)) addflag(o->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
// give one extra rank of skill in this weapon
sk = getobskill(o);
@ -6920,6 +6982,10 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
if (isplayer(lf) || (o->pile->parentob && isplayer(o->pile->parentob->pile->owner))) {
identify(o);
}
if (isplayer(lf)) {
// not worth any points
addflag(o->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
}
}
}
}
@ -7697,7 +7763,6 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
int i;
int x1,y1;
int maxvisrange;
int nightvisrange;
int xray = 0;
//int wentuphill = B_FALSE;
//int origheight;
@ -7705,7 +7770,6 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
flag_t *f;
int x2,y2;
map_t *map;
object_t *o;
int currange;
cell_t *retcell[MAXRETCELLS];
@ -7722,7 +7786,8 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
// can we use pre-calced los?
//
if ((viewer->cell->map->lf == viewer) && viewer->los) {
//if ((viewer->cell->map->lf == viewer) && viewer->los) {
if (viewer->los) {
for (i = 0;i < viewer->nlos; i++) {
if (viewer->los[i] == dest) {
return B_TRUE;
@ -7754,32 +7819,12 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
calcbresnham(map, x1, y1, x2, y2, retcell, &numpixels);
maxvisrange = getvisrange(viewer);
nightvisrange = getnightvisrange(viewer);
//origheight = getheight(x1,y1,z);
// too far away
if (maxvisrange != UNLIMITED) {
if (getcelldist(viewer->cell, dest) > maxvisrange) {
return B_FALSE;
}
if (!celllitfor(viewer, dest, maxvisrange, getnightvisrange(viewer))) {
return B_FALSE;
}
// outside the range of our light, and not lit
if (nightvisrange != UNLIMITED) {
if (getcelldist(viewer->cell, dest) > nightvisrange) {
if (!islit(dest)) {
return B_FALSE;
}
} else {
// inside our nightvis range and magically dark
if (dest->lit == L_PERMDARK) {
return B_FALSE;
}
}
}
//shopwall = B_FALSE;
currange = 0;
for (i = 0; i < numpixels ; i++) {
@ -7793,6 +7838,8 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
// you can always see your own cell
if (i != 0) {
int rangemod;
currange++;
if (currange > maxvisrange) {
return B_FALSE;
@ -7804,39 +7851,12 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
}
*/
/*
if (debug) {
printf("checking LOS at %d,%d going (%d,%d)\n",x,y,xinc,yinc);
fflush(stdout);
if (!celltransparentfor(viewer, cell, &xray, &rangemod)) {
return B_FALSE;
}
*/
// solid cells stop los - but if you are standing on a solid
// cell you can still see out.
if (!cell->type->transparent) {
if (xray) xray--;
else return B_FALSE;
}
currange += rangemod;
// check for objects which block view
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 (xray) {
xray--;
} else {
if (f->val[0] == B_TRUE) {
return B_FALSE;
} else {
currange += f->val[0];
}
}
}
}
}
// xray vision decreases by one
if (xray) xray--;
@ -11014,6 +11034,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+4");
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d4+3");
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_RETAINHPMPONPOLY, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_CANWILL, OT_S_CHARM, 3, 3, "pw:6;");
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, 5, 5, "range:3;");
addflag(lastrace->flags, F_CANWILL, OT_S_STUN, 5, 5, "pw:1;");
@ -11021,6 +11042,7 @@ void initrace(void) {
addflag(lastrace->flags, F_FORCEPOLY, R_BATVAMPIRE, 20, 20, "pw:3;");
addflag(lastrace->flags, F_DETECTOBS, 10, OT_COFFIN, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pile of ash");
addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "gestures");
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "hisses angrily^an angry hiss");
// special: change to gas cloud with 1 hp on death, if not asleep
@ -13684,7 +13706,8 @@ void practice(lifeform_t *lf, enum SKILL skid, int amt) {
}
}
void precalclos(lifeform_t *lf) {
/*
void precalclos_old(lifeform_t *lf) {
int x,y;
cell_t *c;
cell_t **los;
@ -13694,7 +13717,6 @@ void precalclos(lifeform_t *lf) {
los = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
// free existing structures
if (lf->los) {
free(lf->los); lf->los = NULL;
@ -13722,6 +13744,189 @@ void precalclos(lifeform_t *lf) {
lf->nlos = nlos;
free(los);
}
*/
void precalclos_new(lifeform_t *lf) {
cell_t *c;
int startxray,rangemod;
int maxvisrange,nightvisrange;
cell_t **los;
int *blocker;
int nlos = 0,i,nn;
int ix,iy;
flag_t *f;
cell_t *endcell[MAXVISLIMIT];
int nendcells = 0;
cell_t *retcell[MAXRETCELLS];
int numpixels;
int db = B_FALSE;
int start,end;
f = hasflag(lf->flags, F_XRAYVIS);
if (f) {
startxray = f->val[0];
} else {
startxray = 0;
}
los = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
blocker = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
nlos = 0;
if (lf->los) {
free(lf->los); lf->los = NULL;
}
maxvisrange = getvisrange(lf);
nightvisrange = getnightvisrange(lf);
// find all cells at max fov
nendcells = 0;
// n
iy = lf->cell->y - maxvisrange;
limit(&iy,0,lf->cell->map->h-1);
start = lf->cell->x - maxvisrange;
end = lf->cell->x + maxvisrange;
limit(&start,0,lf->cell->map->w-1);
limit(&end,0,lf->cell->map->w-1);
if (db) dblog("North::%d,%d - %d,%d",start,iy,end,iy);
for (ix = start; ix < end; ix++) {
c = getcellat(lf->cell->map, ix, iy);
if (c) {
if (db) dblog("N:endcell[%d] = %d,%d",nn,c->x, c->y);
endcell[nendcells++] = c;
}
assert(nendcells < MAXVISLIMIT);
}
// e
ix = lf->cell->x + maxvisrange;
limit(&ix,0,lf->cell->map->w-1);
start = lf->cell->y - maxvisrange;
end = lf->cell->y + maxvisrange;
limit(&start,0,lf->cell->map->h-1);
limit(&end,0,lf->cell->map->h-1);
if (db) dblog("East::%d,%d - %d,%d",ix,start,ix,end);
for (iy = start; iy < end; iy++) {
c = getcellat(lf->cell->map, ix, iy);
if (c) {
if (db) dblog("E:endcell[%d] = %d,%d",nn,c->x, c->y);
endcell[nendcells++] = c;
}
assert(nendcells < MAXVISLIMIT);
}
// s
iy = lf->cell->y + maxvisrange;
limit(&iy,0,lf->cell->map->h-1);
start = lf->cell->x + maxvisrange;
end = lf->cell->x - maxvisrange;
limit(&start,0,lf->cell->map->w-1);
limit(&end,0,lf->cell->map->w-1);
if (db) dblog("South::%d,%d - %d,%d",start,iy,end,iy);
for (ix = start; ix > end; ix--) {
c = getcellat(lf->cell->map, ix, iy);
if (c) {
if (db) dblog("S:endcell[%d] = %d,%d",nn,c->x, c->y);
endcell[nendcells++] = c;
}
assert(nendcells < MAXVISLIMIT);
}
// w
ix = lf->cell->x - maxvisrange;
limit(&ix,0,lf->cell->map->w-1);
start = lf->cell->y + maxvisrange;
end = lf->cell->y - maxvisrange;
limit(&start,0,lf->cell->map->h-1);
limit(&end,0,lf->cell->map->h-1);
if (db) dblog("West::%d,%d - %d,%d",ix,start,ix,end);
for (iy = start; iy > end; iy--) {
c = getcellat(lf->cell->map, ix, iy);
if (c) {
if (db) dblog("W:endcell[%d] = %d,%d",nn,c->x, c->y);
endcell[nendcells++] = c;
}
assert(nendcells < MAXVISLIMIT);
}
assert(nendcells < MAXVISLIMIT);
// look in circle around lf
//for (ang = 0; ang < 360; ang += 30) {
for (nn = 0; nn < nendcells; nn++) {
int keepgoing = B_TRUE;
int currange,xray;
int n;
// start at lf's cell
//c = lf->cell;
//x = c->x;
//y = c->y;
xray = startxray;
currange = 0;
// calc path to end cell
calcbresnham(lf->cell->map, lf->cell->x, lf->cell->y, endcell[nn]->x, endcell[nn]->y, retcell, &numpixels );
// keep going until we lose los
for (n = 0; keepgoing && (n < numpixels); n++) {
/*
// calc x/y change
xd = precos[ang];
yd = presin[ang];
//limitd(&xd, -1, 1);
//limitd(&yd, -1, 1);
// get new cell
x += xd;
y += yd;
*/
c = retcell[n];
if (n != 0) currange++;
if (currange > maxvisrange) c = NULL;
if (c) {
int found = B_FALSE;
// have we already marked it as seen?
for (i = 0; i < nlos; i++) {
if (los[i] == c) {
if (blocker[i]) {
keepgoing = B_FALSE;
}
found = B_TRUE;
break;
}
}
if (!found) {
// can we see it?
if (!celllitfor(lf, c, maxvisrange, nightvisrange)) {
keepgoing = B_FALSE;
}
if (!celltransparentfor(lf, c, &xray, &rangemod)) {
keepgoing = B_FALSE;
}
currange += rangemod;
if (currange > maxvisrange) keepgoing = B_FALSE;
// if keepgoing was false, still count it
// BUT then stop looking.
los[nlos] = c;
blocker[nlos] = keepgoing ? B_FALSE : B_TRUE;
nlos++;
}
} else { // ie. if !c
keepgoing = B_FALSE;
}
} // end foreach cell and while keepgoing
}
assert(nlos < (MAX_MAPW * MAX_MAPH));
// now fill in lifeform structure
lf->los = malloc(sizeof(cell_t *) * nlos);
for (i = 0; i < nlos; i++) {
lf->los[i] = los[i];
}
lf->nlos = nlos;
free(los);
free(blocker);
}
int push(lifeform_t *lf, object_t *o, int dir) {
cell_t *obcell, *dstcell;
@ -14345,7 +14550,7 @@ void setguntarget(lifeform_t *lf, lifeform_t *targ) {
void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
flag_t *f,*nextf;
int i;
int i,retainhpmp = B_FALSE;
int nkilled = 0;
race_t *newrace;
char buf[BUFLEN];
@ -14356,6 +14561,10 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
statdirty = B_TRUE;
}
if (lfhasflag(lf, F_RETAINHPMPONPOLY)) {
retainhpmp = B_TRUE;
}
if (frompolymorph && (gamemode == GM_GAMESTARTED) && lf->race) {
race_t *origrace;
@ -14436,7 +14645,6 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
killflagsofid(lf->flags, F_RARITY);
// certain other flags are rnadom
getflags(lf->flags, F_RNDHOSTILE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
@ -14454,27 +14662,28 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
lf->baseatt[i] = lf->att[i];
}
// generate hp/maxhp from hit dice
lf->maxhp = 0;
for (i = 0; i < lf->level; i++) {
lf->maxhp += rollhitdice(lf);
assert(lf->maxhp > 0);
}
lf->hp = lf->maxhp;
// generate mp, if you have it.
f = hasflag(lf->flags, F_MPDICE);
if (f) {
lf->maxmp = f->val[0] * 4;
if (f->val[1] != NA) lf->maxmp += f->val[1];
for (i = 0; i < lf->level-1; i++) {
lf->maxmp += rollmpdice(lf);
if (!retainhpmp) {
// generate hp/maxhp from hit dice
lf->maxhp = 0;
for (i = 0; i < lf->level; i++) {
lf->maxhp += rollhitdice(lf);
assert(lf->maxhp > 0);
}
} else {
lf->maxmp = 0;
}
lf->mp = lf->maxmp;
lf->hp = lf->maxhp;
// generate mp, if you have it.
f = hasflag(lf->flags, F_MPDICE);
if (f) {
lf->maxmp = f->val[0] * 4;
if (f->val[1] != NA) lf->maxmp += f->val[1];
for (i = 0; i < lf->level-1; i++) {
lf->maxmp += rollmpdice(lf);
}
} else {
lf->maxmp = 0;
}
lf->mp = lf->maxmp;
}
lf->born = B_TRUE;

5
lf.h
View File

@ -43,6 +43,8 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where);
int canweild(lifeform_t *lf, object_t *o);
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);
int celllitfor(lifeform_t *lf, cell_t *c, int maxvisrange, int nightvisrange);
int celltransparentfor(lifeform_t *lf, cell_t *c, int *xray, int *rangemod);
int checkfordrowning(lifeform_t *lf, object_t *o);
//void checkxp(enum RACE rid);
float comparelfs(lifeform_t *lf1, lifeform_t *lf2);
@ -283,7 +285,8 @@ void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char
int poisoncausesvomit(enum POISONTYPE ptype);
int poisonthreatenslife(lifeform_t *lf, flag_t *f);
void practice(lifeform_t *lf, enum SKILL skid, int amt);
void precalclos(lifeform_t *lf);
void precalclos_old(lifeform_t *lf);
void precalclos_new(lifeform_t *lf);
int push(lifeform_t *lf, object_t *o, int dir);
int readytotrain(lifeform_t *lf);
int recruit(lifeform_t *lf);

2
move.c
View File

@ -23,6 +23,8 @@ extern int needredraw;
extern enum GAMEMODE gamemode;
extern void (*precalclos)(lifeform_t *);
extern enum ERROR reason;
extern void *rdata;

33
nexus.c
View File

@ -42,6 +42,11 @@ hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
npcname_t *npcname;
int numnpcnames;
double presin[360];
double precos[360];
void (*precalclos)(lifeform_t *) = NULL;
extern vault_t *firstvault;
extern flag_t *retflag[];
@ -853,9 +858,20 @@ void getrarityrange(int depth, int *min, int *max, int range, int oodok) {
}
int init(void) {
int i;
// random numbers
srand(time(NULL));
// precalc sin/cos
for (i = 0; i < 360; i++) {
double rads;
rads = i * (M_PI / 180);
presin[i] = sin(rads);
precos[i] = cos(rads);
}
precalclos = precalclos_new;
gamemode = GM_INIT;
playerglyph.ch = '@';
@ -1042,6 +1058,23 @@ int limitf(float *what, float min, float max) {
return limited;
}
int limitd(double *what, double min, double max) {
int limited = B_FALSE;
if (min != NA) {
if (*what < min) {
*what = min;
limited = B_TRUE;
}
}
if (max != NA) {
if (*what > max) {
*what = max;
limited = B_TRUE;
}
}
return limited;
}
int loadnpcnames(void) {
FILE *f;
char buf[BUFLEN];

View File

@ -20,6 +20,7 @@ void initcommands(void);
int isplayerturn(void);
int limit(int *what, int min, int max);
int limitf(float *what, float min, float max);
int limitd(double *what, double min, double max);
int loadnpcnames(void);
int onein(int howmany);
int parseplayerfile(FILE *f, lifeform_t *lf);

View File

@ -29,6 +29,7 @@ extern skill_t *firstskill, *lastskill;
extern flag_t *retflag[];
extern int nretflags;
void (*precalclos)(lifeform_t *);
extern object_t *retobs[MAXPILEOBS+1];
extern int retobscount[MAXPILEOBS+1];
@ -3064,6 +3065,13 @@ int getobbonus(object_t *o) {
return bonus;
}
int getobpoints(object_t *o) {
if (hasflag(o->flags, F_NOPOINTS)) {
return 0;
}
return getobvalue(o);
}
// returns the skill associated with this object
skill_t *getobskill(object_t *o) {
flag_t *f;

View File

@ -65,6 +65,7 @@ enum MATSTATE getmaterialstate(enum MATERIAL mat);
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt);
int getobaccuracy(object_t *wep, lifeform_t *weilder);
int getobbonus(object_t *o);
int getobpoints(object_t *o);
skill_t *getobskill(object_t *o);
enum LFSIZE getobsize(object_t *o);
int getobspellpower(object_t *o, lifeform_t *lf);