#include #include #include #include "defs.h" #include "flag.h" #include "god.h" #include "io.h" #include "lf.h" #include "map.h" #include "objects.h" #include "spell.h" #include "text.h" extern enum GAMEMODE gamemode; extern int needredraw; extern int statdirty; extern void (*precalclos)(lifeform_t *); extern lifeform_t *godlf[]; extern int ngodlfs; extern lifeform_t *player; int flagdb = B_FALSE; altflagval_t *addaltval(flag_t *f, enum FLAG id, int val1, int val2, int val3, char *text) { f->altval = malloc(sizeof(altflagval_t)); f->altval->id = id; f->altval->val[0] = val1; f->altval->val[1] = val2; f->altval->val[2] = val3; if (text) { f->altval->text = strdup(text); } else { f->altval->text = strdup(""); } return f->altval; } void addcondition(flag_t *f, enum FLAGCONDITION fc, int chance) { f->condition = fc; f->chance = chance; } 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, -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, -1); } flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid) { lifeform_t *lf; flag_t *f; map_t *redolight = NULL; int redrawscreenatend = B_FALSE; int redrawstatatend = B_FALSE; int i; // identified things mean all new flags are autmaticlaly known. if (hasflag(fp, F_IDENTIFIED)) { known = B_KNOWN; } if (id == F_INTERRUPTED) { if (fp->owner == player) { dblog("player got interrupted"); } } if ((id == F_POISONED) && isimmuneto(fp, DT_POISON)) { return NULL; } lf = fp->owner; if (gamemode == GM_GAMESTARTED) { if (id == F_PRODUCESLIGHT) { if (lf && lf->cell && (lf->cell->map == player->cell->map)) { // someone started producing light redolight = lf->cell->map; } else if (fp->ob) { cell_t *obloc; obloc = getoblocation(fp->ob); if (obloc && (obloc->map == player->cell->map)) { // an object started producing light redolight = obloc->map; } } } else if (id == F_ASLEEP) { // someone fell asleep - ie their glyph will turn upsidedown if (lf && (isplayer(lf) || cansee(player, lf))) { redolight = lf->cell->map; } } } //////////////////////////////// // ACTUAL FLAG ADDITION IS HERE //////////////////////////////// if (fp->first == NULL) { fp->first = malloc(sizeof(flag_t)); f = fp->first; f->prev = NULL; // also the last fp->last = f; f->next = NULL; } else { flag_t *ff; // we will keep flags sorted. // find correct position in list... ff = fp->first; while (ff && (ff->id < id)) { ff = ff->next; } if (ff) { // start or middle of list // insert BEFORE this one flag_t *prev; prev = ff->prev; // link to previous element if (prev) { prev->next = malloc(sizeof(flag_t)); f = prev->next; } else { // first one fp->first = malloc(sizeof(flag_t)); f = fp->first; } f->prev = prev; // link to next element f->next = ff; ff->prev = f; } else { // last one. insert at end of list. f = fp->last; f->next = malloc(sizeof(flag_t)); f->next->prev = f; f = f->next; fp->last = f; f->next = NULL; } /* // go to end of list f = fp->last; f->next = malloc(sizeof(flag_t)); f->next->prev = f; f = f->next; */ } // fill in props f->id = id; f->lifetime = lifetime; f->known = known; f->obfrom = obfromid; f->altval = NULL; f->condition = FC_NOCONDITION; f->chance = 100; // first blank values for (i = 0; i < 3; i++) { f->val[i] = NA; } f->val[0] = val1; f->nvals = 1; if (val2 != NA) { f->val[1] = val2; f->nvals++; } if (val3 != NA) { f->val[2] = val3; f->nvals++; } if (text) { f->text = strdup(text); } else { f->text = strdup(""); } f->pile = fp; updatefpindex(fp); // notify if ((gamemode == GM_GAMESTARTED)) { if (f->pile->owner) { if (announceflaggain(f->pile->owner, f)) { // don't include flags which interrupt will kill! switch (f->id) { case F_RUNNING: case F_TRAINING: case F_AUTOCMD: break; case F_ASLEEP: if (f->val[2] == NA) { // ie. sleeping, not resting addflag(f->pile, F_INTERRUPTED, B_TRUE, NA, NA, NULL); } break; default: addflag(f->pile, F_INTERRUPTED, B_TRUE, NA, NA, NULL); break; } f->known = B_TRUE; if (f->obfrom) { 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; } } } } // player flags which cause a redraw if (flagcausesredraw(f->pile->owner, f->id)) redrawscreenatend = B_TRUE; if (flagcausesstatredraw(f->pile->owner, f->id)) redrawstatatend = B_TRUE; } else if (f->pile->ob) { if (announceobflaggain(f->pile->ob, f)) { f->known = B_TRUE; } } } if (flagcausesloscalc(f->id)) { cell_t *where = NULL; // everyone who can see this cell recalcs their los where = getflagpilelocation(f->pile); if (where) { lifeform_t *l; for (l = where->map->lf ; l ; l = l->next) { if (haslos(l, where)) { precalclos(l); if (isplayer(l)) { redrawscreenatend = B_TRUE; } } } } } // special effects if (f->pile->owner) { float pct; switch (f->id) { case F_ASLEEP: stopallspellsexcept(f->pile->owner, OT_S_ALARM, OT_NONE); break; case F_NONCORPOREAL: killflagsofid(f->pile->owner->flags, F_BEINGSTONED); break; case F_RAGE: f->val[0] = f->pile->owner->hp; // remember old maxhp f->val[1] = f->pile->owner->maxhp; // remember old maxhp pct = (float)f->pile->owner->hp / (float)f->pile->owner->maxhp; f->pile->owner->maxhp = (float)f->pile->owner->maxhp * 1.5; f->pile->owner->hp = pct * (float)f->pile->owner->maxhp; break; default: break; } } if ((gamemode == GM_GAMESTARTED) && (redrawscreenatend || redrawstatatend || redolight)) { if (redolight) { //dblog("CALCINGLIGHT from flag\n"); redrawscreenatend = B_TRUE; calclight(redolight); precalclos(player); } //dblog("DRAWINGSCREEN from flag\n"); if (redrawscreenatend) needredraw = B_TRUE; if (redrawstatatend) statdirty = B_TRUE; drawscreen(); } return f; } flagpile_t *addflagpile(lifeform_t *owner, object_t *ob) { flagpile_t *fp; fp = malloc(sizeof(flagpile_t)); fp->first = NULL; fp->last = NULL; fp->owner = owner; fp->ob = ob; fp->nitems = 0; return fp; } void changeflagtext(flag_t *f, char *newtext) { free(f->text); if (newtext) { f->text = strdup(newtext); } else { f->text = strdup(""); } } void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) { flag_t *f; for (f = src->first ; f ; f = f->next) { // gone past the requrested id's number - ie. it's not there. if (f->id > id) break; if (f->id == id) { addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text, f->lifetime, f->known, -1); } } } 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, -1); } } int countflags(flagpile_t *fp) { flag_t *f; int count = 0; for (f = fp->first ; f ; f = f->next) { count++; } return count; } int flagcausesloscalc(enum FLAG fid) { switch (fid) { case F_BLOCKSVIEW: return B_TRUE; default: break; } return B_FALSE; } int flagcausesredraw(lifeform_t *lf, enum FLAG fid) { if (!lf) return B_FALSE; if (isplayer(lf)) { // player switch (fid) { case F_ASLEEP: case F_BLIND: case F_DETECTLIFE: case F_DETECTOBS: case F_ENHANCESMELL: case F_FASTMOVE: case F_HIDING: case F_INVISIBLE: case F_PRODUCESLIGHT: case F_PRONE: case F_RAGE: case F_SECRET: case F_SEEINDARK: case F_SEEINVIS: case F_SPRINTING: case F_SLOWMOVE: case F_TIRED: return B_TRUE; default: break; } } else if (haslos(player, lf->cell)) { switch (fid) { case F_ASLEEP: case F_HIDING: case F_INVISIBLE: case F_PRODUCESLIGHT: case F_PRONE: return B_TRUE; default: break; } // nonplayer } return B_FALSE; } int flagcausesstatredraw(lifeform_t *lf, enum FLAG fid) { if (!lf || !isplayer(lf)) return B_FALSE; switch (fid) { case F_ASLEEP: case F_ATTRMOD: case F_BLIND: case F_EATING: case F_FASTMOVE: case F_FLYING: case F_HASNEWLEVEL: case F_HIDING: case F_INVISIBLE: case F_LEVITATING: case F_PARALYZED: case F_POISONED: case F_PRODUCESLIGHT: case F_PRONE: case F_RAGE: case F_SPRINTING: case F_SLOWMOVE: case F_TIRED: case F_TRAINING: return B_TRUE; default: break; } return B_FALSE; } flag_t *hasflag(flagpile_t *fp, int id) { return hasflag_real(fp, id, NA, NULL); } flag_t *hasflagknown(flagpile_t *fp, int id) { return hasflag_real(fp, id, B_TRUE, NULL); } flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) { flag_t *f,*foundflag = NULL, *searchfrom = NULL; lifeform_t *owner; owner = fp->owner; int pos; int l,r; int iter = 0,subiter = 0; int db = B_FALSE; if (flagdb) db = B_TRUE; if (db) dblog("hasflag %d in flagpile with %d entries", id, fp->nitems); // binary search for this flag id. l = 0; r = fp->nitems-1; while (!searchfrom) { //if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r); if (r < l) { // NOT FOUND. //if (db) dblog(" r < l: not found!"); break; } else if (fp->item[l]->id > id) { // NOT FOUND. //if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id); break; } else if (fp->item[r]->id < id) { // NOT FOUND. //if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id); break; } // half way inbetween l and r pos = ((l+r)/2); f = fp->item[pos]; //if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id); if (f->id == id) { // go back to first occurence while (f->prev && (f->prev->id == id)) { f = f->prev; iter++; } searchfrom = f; break; } else if (f->id > id) { // go left r = pos-1; } else { // go right l = pos+1; } iter++; } // now find a valid one f = searchfrom; while (f && (f->id == id)) { int valid = B_TRUE; if (f == exception) valid = B_FALSE; if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE; if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) valid = B_FALSE; //if (owner && (f->lifetime == FROMSKILL) && !getskill(owner, xxx)) valid = B_FALSE; if (valid) { foundflag = f; break; } else { f = f->next; subiter++; } } if (db) dblog("finished - %s - iter=%d, subiter=%d", foundflag ? "found it" : "NOT FOUND",iter,subiter); return foundflag; /* for (f = fp->first ; f ; f = f->next) { // gone past the requrested id's number - ie. it's not there. if (f->id > id) break; if ((f->id == id) && (f != exception)) { int valid = B_TRUE; if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE; if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) { valid = B_FALSE; } if (valid) { return f; } } } */ return NULL; } flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text) { return hasflagval_real(fp, id, val1, val2, val3, text, B_FALSE); // doesn't have to be known } flag_t *hasflagvalknown(flagpile_t *fp, int id, int val1, int val2, int val3, char *text) { return hasflagval_real(fp, id, val1, val2, val3, text, B_TRUE); // must be known } int getcounter(flagpile_t *fp) { flag_t *f; f = hasflag(fp, F_COUNTER); if (f) { return f->val[0]; } return 0; } flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown) { flag_t *f,*foundflag = NULL, *searchfrom = NULL; lifeform_t *owner; owner = fp->owner; int pos; int l,r; int iter = 0; int db = B_FALSE; if (flagdb) db = B_TRUE; //if (db) dblog("hasflag %d in flagpile with %d entries", id, fp->nitems); // binary search for this flag id. l = 0; r = fp->nitems-1; while (!searchfrom) { //if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r); if (r < l) { // NOT FOUND. //if (db) dblog(" r < l: not found!"); break; } else if (fp->item[l]->id > id) { // NOT FOUND. //if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id); break; } else if (fp->item[r]->id < id) { // NOT FOUND. //if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id); break; } // half way inbetween l and r pos = ((l+r)/2); f = fp->item[pos]; //if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id); if (f->id == id) { // go back to first occurence while (f->prev && (f->prev->id == id)) { iter++; f = f->prev; } searchfrom = f; break; } else if (f->id > id) { // go left r = pos-1; } else { // go right l = pos+1; } iter++; } // now find a valid one f = searchfrom; while (f && (f->id == id)) { if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) { // invalid } else if ( ((val1 == NA) || (f->val[0] == val1)) && ((val2 == NA) || (f->val[1] == val2)) && ((val3 == NA) || (f->val[2] == val3)) && ((text == NULL) || strstr(f->text, text))) { if (!wantknown || f->known) { foundflag = f; break; } } f = f->next; } if (db) dblog("finished - %s - iter=%d", foundflag ? "found it" : "NOT FOUND", iter ); return foundflag; /* for (f = fp->first ; f ; f = f->next) { // gone past the requrested id's number - ie. it's not there. if (f->id > id) break; if (f->id == id) { if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) { // invalid } else { if ( ((val1 == NA) || (f->val[0] == val1)) && ((val2 == NA) || (f->val[1] == val2)) && ((val3 == NA) || (f->val[2] == val3)) && ((text == NULL) || strstr(f->text, text))) { if (!wantknown || f->known) { return f; } } } } } return NULL; */ } int istransitoryflag(flag_t *f) { if ((f->lifetime >= FROMEXTERNAL_LOW) && (f->lifetime <= FROMEXTERNAL_HIGH)) { return B_FALSE; } return B_TRUE; } // returns true if we did something int killflagsofid(flagpile_t *fp, enum FLAG fid) { flag_t *f,*nextf; int donesomething = B_FALSE; for (f = fp->first ; f ; f = nextf) { nextf = f->next; // gone past the requrested id's number - ie. it's not there. if (f->id > fid) break; if (f->id == fid) { killflag(f); donesomething = B_TRUE; } } return donesomething; } void killflag(flag_t *f) { flag_t *nextone, *lastone; lifeform_t *lf; map_t *redolight = NULL; cell_t *redolos = NULL; int redostat = B_FALSE; int redoscreen = B_FALSE; int i,dopleasegod[MAXGODS]; for (i = 0; i < ngodlfs; i++) { dopleasegod[i] = 0; } lf = f->pile->owner; if (gamemode == GM_GAMESTARTED) { if (f->id == F_PRODUCESLIGHT) { if (lf && lf->cell && (lf->cell->map == player->cell->map)) { // someone stopped producing light redolight = lf->cell->map; } else if (f->pile->ob) { cell_t *obloc; obloc = getoblocation(f->pile->ob); if (obloc && (obloc->map == player->cell->map)) { // an object stopped producing light redolight = obloc->map; } } } else if (f->id == F_ASLEEP) { // someone woke up - ie their glyph will turn upsidedown if (lf && (isplayer(lf) || cansee(player, lf))) { 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)) { for (i = 0; i < ngodlfs; i++) { if (godlf[i]->race->id == R_GODMERCY) dopleasegod[i] += 5; } } } } } // flags which cause a redraw if (flagcausesredraw(f->pile->owner, f->id)) redoscreen = B_TRUE; if (flagcausesstatredraw(f->pile->owner, f->id)) redostat = B_TRUE; if (flagcausesloscalc(f->id)) { redolos = getflagpilelocation(f->pile); } // notify if (gamemode == GM_GAMESTARTED) { if (lf) { // special cases if (f->id == F_FLEEFROM) { // once you recover from fleeing from something, // you don't find it scary for a little while. if (!lfhasflagval(lf, F_NOFLEEFROM, f->val[0], NA, NA, NULL)) { addtempflag(lf->flags, F_NOFLEEFROM, f->val[0], NA, NA, NULL, 10); } } else if (f->id == F_RAGE) { if (!isdead(lf)) { // restore original maxhp float pct; pct = (float)lf->hp / (float)lf->maxhp; lf->maxhp = f->val[1]; lf->hp = pct * (float)lf->maxhp; if (lf->hp < 1) lf->hp = 1; } } // announce if (announceflagloss(lf, f)) { // don't include flags which interrupt will kill! switch (f->id) { case F_RUNNING: case F_TRAINING: case F_AUTOCMD: break; case F_ASLEEP: if (f->val[2] != NA) { // ie. resting addflag(lf->flags, F_INTERRUPTED, B_TRUE, NA, NA, NULL); } break; default: addflag(lf->flags, F_INTERRUPTED, B_TRUE, NA, NA, NULL); break; } } } else if (f->pile->ob) { announceobflagloss(f->pile->ob, f); } } // we will revert to our original form at the end of timeeffectslf(). if (lf && (f->id == F_POLYMORPHED)) { if (lfhasflag(lf, F_ORIGRACE)) { lf->polyrevert = B_TRUE; } } // free mem if (f->text) free(f->text); if (f->altval) { if (f->altval->text) free(f->altval->text); free(f->altval); } // remove from list nextone = f->next; if (nextone != NULL) { nextone->prev = f->prev; } else { /* last */ f->pile->last = f->prev; } if (f->prev == NULL) { /* first */ nextone = f->next; f->pile->first = nextone; free(f); } else { lastone = f->prev; free (lastone->next ); lastone->next = nextone; } updatefpindex(f->pile); if (gamemode == GM_GAMESTARTED) { for (i = 0; i < ngodlfs; i++) { if (dopleasegod[i]) { pleasegodmaybe(godlf[i]->race->id, dopleasegod[i]); } } if (redolos) { // everyone who can see this cell recalcs their los lifeform_t *l; for (l = redolos->map->lf ; l ; l = l->next) { if (haslos(l, redolos)) { precalclos(l); if (isplayer(l)) redoscreen = B_TRUE; } } } if (redolight) { calclight(redolight); precalclos(player); needredraw = B_TRUE; } if (redoscreen) { needredraw = B_TRUE; } if (redostat) { statdirty = B_TRUE; } if (statdirty || needredraw ) { drawscreen(); } } } void killflagpile(flagpile_t *fp) { while (fp->first) { killflag(fp->first); } free(fp); } int killtransitoryflags(flagpile_t *fp, enum FLAG fid) { flag_t *f,*nextf; int nkilled = 0; for (f = fp->first ; f ; f = nextf) { nextf = f->next; // gone past the requrested id's number - ie. it's not there. if (f->id > fid) break; if (istransitoryflag(f) && (f->id == fid)) { killflag(f); nkilled++; } } return nkilled; } int killtransitoryflagvals(flagpile_t *fp, enum FLAG fid, int val1, int val2, int val3, char *text) { flag_t *f, *nextf; int nkilled = 0; for (f = fp->first ; f ; f = nextf) { nextf = f->next; // gone past the requrested id's number - ie. it's not there. if (f->id > fid) break; if (istransitoryflag(f) && (f->id == fid)) { if ( ((val1 == NA) || (f->val[0] == val1)) && ((val2 == NA) || (f->val[1] == val2)) && ((val3 == NA) || (f->val[2] == val3)) && ((text == NULL) || strstr(f->text, text))) { killflag(f); nkilled++; } } } return nkilled; } void timeeffectsflag(flag_t *f, int howlong) { // special case: if (f->id == F_TRAIL) { return; } if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) { // special case - fast metabolism speeds up poison too. if (f->id == F_POISONED) { int multiplier; sumflags(f->pile, F_FASTMETAB, &multiplier, NULL, NULL); if (multiplier > 0) { howlong *= multiplier; } } f->lifetime -= howlong; if (f->lifetime <= 0) { killflag(f); return; } else if (f->lifetime == 5) { // warn about certain flags...... if (isplayer(f->pile->owner)) { switch (f->id) { case F_CANWILL: switch (f->val[0]) { case OT_A_JUMP: warn("Your ability to jump is starting to run out...");; break; default: break; } break; case F_DTIMMUNE: warn("Your %s immunity is starting to run out...", getdamname(f->val[0])); break; case F_DTRESIST: warn("Your %s resistance is starting to run out...", getdamname(f->val[0])); break; case F_DTVULN: warn("You feel a little less vulnerable to %s...", getdamname(f->val[0])); break; case F_MAGSHIELD: warn("Your magnetic shield is weakening..."); break; case F_POLYMORPHED: warn("You are starting to revert to your original form..."); break; case F_LEVITATING: warn("Your levitation is starting to expire..."); break; case F_FLYING: warn("Your ability to fly is starting to expire..."); break; default: // no message break; } } } else if (f->lifetime == 3) { if (isplayer(f->pile->owner)) { switch (f->id) { case F_SPRINTING: if (f->val[0]) { warn("You will have to stop sprinting soon..."); } break; default: 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)) { switch (f->id) { case F_CANWILL: switch (f->val[0]) { case OT_A_JUMP: warn("Your ability to jump is about to expire!");; break; default: break; } break; case F_DTIMMUNE: warn("Your %s immunity is about to expire!", getdamname(f->val[0])); break; case F_DTRESIST: warn("Your %s resistance is about to expire!", getdamname(f->val[0])); break; case F_DTVULN: warn("You feel a little less vulnerable to %s...", getdamname(f->val[0])); break; case F_MAGSHIELD: warn("Your magnetic shield is about to expire!"); break; case F_LEVITATING: warn("Your levitation is about to expire!"); break; case F_POLYMORPHED: warn("You are about to revert to your original form!"); break; case F_FLYING: warn("Your ability to fly is about to expire!"); break; default: // no message break; } } // sprinting is special if (f->id == F_SPRINTING) { if (f->val[0]) { enum SKILLLEVEL slev; lifeform_t *who; int tiredtime; who = f->pile->owner; // now you get slow // you get tired when you finish sprinting tiredtime = 15; // adjust for athletics skill. -2 per level. slev = getskill(who, SK_ATHLETICS); if (slev != PR_INEPT) { tiredtime -= (2*slev); } // adjust for constitution tiredtime = tiredtime - (int) ((float)tiredtime * (getstatmod(who, A_CON) / 100) ); // enforce minimum if (tiredtime < 1) tiredtime = 1; f->val[0] = B_FALSE; f->lifetime = tiredtime; if (isplayer(who)) { msg("You are exhausted."); } else if (cansee(player, who)) { char lfname[BUFLEN]; getlfname(who, lfname); msg("%s looks exhausted.",lfname); } needredraw = B_TRUE; statdirty = B_TRUE; } } } } if (f->id == F_BEINGSTONED) { f->val[0]--; if (f->val[0] == 0) { if (!stone(f->pile->owner)) { // lf turned to stone! return; } else { // stoning failed. stop being stoned. killflag(f); return; } } } if (f->id == F_WET) { f->val[1]--; if (f->val[1] <= 0) { f->val[0]--; if (f->val[0] <= W_DRY) { killflag(f); return; } else { // reset timer f->val[1] = TM_WETTIME; // TODO: announce } } } } cell_t *getflagpilelocation(flagpile_t *fp) { cell_t *where = NULL; // everyone who can see this cell recalcs their los if (fp->owner) { where = fp->owner->cell; } else if (fp->ob) { where = getoblocation(fp->ob); } return where; } // populates retflag & nretflags with matching flags int getflags(flagpile_t *fp, flag_t **retflag, int *nretflags, ... ) { va_list flags; enum FLAG wantflag[MAXCANDIDATES]; int nwantflags,i; flag_t *f; va_start(flags, nretflags); nwantflags = 0; wantflag[nwantflags] = va_arg(flags, enum FLAG); while (wantflag[nwantflags] != F_NONE) { nwantflags++; wantflag[nwantflags] = va_arg(flags, enum FLAG); } va_end(flags); // now populate retflag[] with matches flags *nretflags = 0; for (i = 0; i < nwantflags; i++) { f = hasflag(fp, wantflag[i]); while (f && (f->id == wantflag[i])) { retflag[(*nretflags)++] = f; f = f->next; } } return *nretflags; } int modcounter(flagpile_t *fp, int amt) { flag_t *f; f = hasflag(fp, F_COUNTER); if (f) { f->val[0] += amt; } else { f = addflag(fp, F_COUNTER, amt, NA, NA, NULL); } return f->val[0]; } flag_t *modflag(flagpile_t *fp, enum FLAG fid, int val1, int val2, int val3, char *text) { flag_t *f; f = hasflag(fp, fid); if (!f) { return addflag(fp, fid, val1, val1, val3, text); } // make sure there is only one! if (f->next && (f->next->id == fid)) { if (gamemode == GM_GAMESTARTED) msg("WARNING: modflag() found multiple flag instances"); dblog("WARNING: modflag() found multiple flag instances (fid=%d)", (int)fid); } if (val1 != NA) f->val[0] = val1; if (val2 != NA) f->val[1] = val2; if (val3 != NA) f->val[2] = val3; if (text) { free(f->text); f->text = strdup(text); } return f; } void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2) { flag_t *f; if (val0) *val0 = 0; if (val1) *val1 = 0; if (val2) *val2 = 0; for (f = fp->first ; f ; f = f->next) { // gone past the requrested id's number - ie. it's not there. if (f->id > id) break; if (f->id == id) { if (val0) *val0 = *val0 + f->val[0]; if (val1) *val1 = *val1 + f->val[1]; if (val2) *val2 = *val2 + f->val[2]; } } } void timeeffectsflags(flagpile_t *fp) { flag_t *f,*nextf; for (f = fp->first ; f ; f = nextf) { nextf = f->next; timeeffectsflag(f, 1); } } // generate an index void updatefpindex(flagpile_t *fp) { flag_t *f; fp->nitems = 0; for (f = fp->first ;f ; f = f->next) { fp->item[fp->nitems] = f; fp->nitems++; } }