* [+] hiscores

- [+] limit name length
* [+] The fire titan is burnt by a flaming greatsword!
- [+] make ar slightly less effective.
- [+] don't prompt "really walk into xxxdangerousthingxxx" when
      carefully walking.
- [+] allow dodge check for web spell.
- [+] speedups in attack.c
- [+] "the centipede bites you" "the centipede hits you"
    - [+] how did it get "hit"? it should only have a teeth attack!
- [+] after looking at skills, bottom line of status bar isn't redrawn.
    - [+] anything with a --more--
- [+] druids regenerate mana based on nearby plants
- [+] bug: "your young wolf starts casting a spell" when sprinting.
- [+] bug with AI follow code - now fixed.
- [+] make ai pets be able to "smell" the player.
- [+] unarmed adept: break wood (no "ow!" and extra dam to wood/doors)
- [+] automatically give all player pets the ability to see footprints!
* [+] monsters not following properly! fixed now i think.
- [+] mark fountain potiontypes as "tried" after you drink
- [+] replace barbarian with warrior.  make it armour-based.
- [+] bug: "A Jimbo comes into view" should be "Jimbo coes into view"
- [+] more findlfags() calls needed in lf.c.
- [+] give jimbo f_dontleaveroom!
HELP SYSTEM
 - [+] ?? for commands
- [+] ?s for skills
This commit is contained in:
Rob Pearce 2011-07-28 22:45:34 +00:00
parent 9481e41701
commit 94ed133ace
19 changed files with 942 additions and 394 deletions

View File

@ -1,2 +1,2 @@
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h vault.c vault.h nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h vault.c vault.h
gcc -Wall -g -pg -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c vault.c vault.h -lncurses gcc -Wall -g -pg -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c vault.c vault.h -lncurses -lsqlite3

22
ai.c
View File

@ -405,6 +405,7 @@ object_t *aigetwand(lifeform_t *lf, enum FLAG purpose) {
return NULL; return NULL;
} }
// returns targetcell flag on success
flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int timelimit) { flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int timelimit) {
int db = B_FALSE; int db = B_FALSE;
char whybuf[BUFLEN]; char whybuf[BUFLEN];
@ -429,6 +430,9 @@ flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int t
dblog(".oO { %s going to targecell: %d, %d }", lfname, c->x, c->y); dblog(".oO { %s going to targecell: %d, %d }", lfname, c->x, c->y);
} }
// kill previous target flags.
killflagsofid(lf->flags, F_TARGETLF); killflagsofid(lf->flags, F_TARGETLF);
killflagsofid(lf->flags, F_TARGETCELL); killflagsofid(lf->flags, F_TARGETCELL);
@ -737,7 +741,11 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
} else { } else {
// not already at their last known cell. try to go there. // not already at their last known cell. try to go there.
if (db) dblog(".oO { i cannot see my target. moving to last known loc %d/%d }",lastx,lasty); if (db) dblog(".oO { i cannot see my target. moving to last known loc %d/%d }",lastx,lasty);
if (!aigoto(lf, targcell, MR_LF, target, PERMENANT)) { if (aigoto(lf, targcell, MR_LF, target, PERMENANT)) {
if (db) dblog(".oO { successfuly moved towards LKL. }");
// success
return B_FALSE;
} else {
if (db) dblog(".oO { aigoto target's last known loc failed! }"); if (db) dblog(".oO { aigoto target's last known loc failed! }");
} }
} }
@ -783,7 +791,19 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) {
// are we there yet? // are we there yet?
if (lf->cell == c) { if (lf->cell == c) {
// yes. remove target cell
if (db) dblog(".oO { arrived at f_targetcell. removing. }"); if (db) dblog(".oO { arrived at f_targetcell. removing. }");
if (f->val[2] == MR_LF) {
lifeform_t *targlf;
// if we were chasing someone, keep looking
// for them.
targlf = findlf(lf->cell->map, atoi(f->text));
if (targlf) {
if (db) dblog(".oO { resuming pursuit of %s }", targlf->race->name);
addflag(lf->flags, F_TARGETLF, targlf->id, NA, NA, NULL);
}
}
killflag(f); killflag(f);
} }
} }

107
attack.c
View File

@ -16,6 +16,8 @@
extern lifeform_t *player; extern lifeform_t *player;
extern flag_t *retflag[];
extern int nretflags;
int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) { int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) {
object_t *armour = NULL; object_t *armour = NULL;
@ -250,7 +252,10 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
} }
// then use all our innate attacks.. // then use all our innate attacks..
for (f = lf->flags->first ; f; f = f->next) {
getflags(lf->flags, F_HASATTACK, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_HASATTACK) { if (f->id == F_HASATTACK) {
objecttype_t *ot; objecttype_t *ot;
@ -458,7 +463,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_NONCORPOREAL, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
// ie. you have been made noncorporeal // ie. you have been made noncorporeal
if ((f->id == F_NONCORPOREAL) && (f->lifetime != FROMRACE)) { if ((f->id == F_NONCORPOREAL) && (f->lifetime != FROMRACE)) {
if (isplayer(lf)) { if (isplayer(lf)) {
@ -760,6 +767,9 @@ 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 (strstr(attackverb, "hit")) {
dblog("xxx");
}
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, " but does no damage");
@ -922,7 +932,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
// retaliation happens even if victim died // retaliation happens even if victim died
for (f = victim->flags->first ; f ; f = f->next) { getflags(victim->flags, F_RETALIATE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_RETALIATE) { if (f->id == F_RETALIATE) {
int rdam; int rdam;
char damstring[BUFLEN]; char damstring[BUFLEN];
@ -1119,15 +1131,30 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
} }
if ((i == 0) && (wep->type->id == OT_FISTS) && hasflag(o->flags, F_HARDNESS)) { if ((i == 0) && (wep->type->id == OT_FISTS) && hasflag(o->flags, F_HARDNESS)) {
char buf[BUFLEN]; object_t *gloves;
sprintf(buf, "punching %s", obname); gloves = getequippedob(lf->pack, BP_HANDS);
if ( losehp(lf, 1, DT_BASH, lf, buf)) { if (gloves && hasflag(gloves->flags, F_HARDNESS)) {
if (isplayer(lf)) { // ok
msg("^bOw!"); } else if ((o->material->id == MT_WOOD) && (getskill(lf, SK_UNARMED) >= PR_ADEPT)) {
// ok
} else {
char buf[BUFLEN];
sprintf(buf, "punching %s", obname);
if ( losehp(lf, 1, DT_BASH, lf, buf)) {
if (isplayer(lf)) {
msg("^bOw!");
}
} }
} }
} }
// smash wood bonus
if ((wep->type->id == OT_FISTS) &&
(o->material->id == MT_WOOD) &&
(getskill(lf, SK_UNARMED) >= PR_ADEPT)) {
dam[i] += rnd(1,6);
}
// object loses hp // object loses hp
takedamage(o, dam[i], damtype[i]); takedamage(o, dam[i], damtype[i]);
@ -1175,7 +1202,7 @@ int damtypecausesbleed(enum DAMTYPE dt) {
// returns the amount of damage the armour blocked... // returns the amount of damage the armour blocked...
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) { int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) {
int reduceamt = 0; int reduceamt = 0;
int ar,min; int ar,min,max;
//int pctrange; //int pctrange;
object_t *o; object_t *o;
@ -1186,9 +1213,9 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d
//pctrange = rnd(25,75); //pctrange = rnd(25,75);
//reduceamt = pctof(pctrange, ar); //reduceamt = pctof(pctrange, ar);
// between ar/5 and AR getarrange(ar, &min, &max);
min = ar/5;
reduceamt = rnd(min, ar); reduceamt = rnd(min, max);
// special case // special case
@ -1204,6 +1231,11 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d
return reduceamt; return reduceamt;
} }
// for a given ArmourRating (AR), return range of damage which it might reduce
void getarrange(int arating, int *min, int *max) {
*min = pctof(20,arating);
*max = pctof(60, arating);
}
// returns a const char * // returns a const char *
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) { char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
@ -1217,24 +1249,25 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
pct = (int)(((float) dam / (float) maxhp) * 100.0); pct = (int)(((float) dam / (float) maxhp) * 100.0);
if (wep) { if (wep) {
int i;
flag_t *f; flag_t *f;
for (f = wep->flags->first ; f ; f = f->next) { getflags(wep->flags, F_ATTACKVERB, F_NONE);
if (f->id == F_ATTACKVERB) { for (i = 0; i < nretflags; i++) {
if ((f->val[0] == NA) && (f->val[1] == NA)) { f = retflag[i];
return f->text; if ((f->val[0] == NA) && (f->val[1] == NA)) {
} else if (f->val[0]) { return f->text;
if (pct >= f->val[0]) { } else if (f->val[0]) {
if (f->val[1] == NA) { if (pct >= f->val[0]) {
return f->text; if (f->val[1] == NA) {
} else if (pct <= f->val[1]) { return f->text;
return f->text; } else if (pct <= f->val[1]) {
}
}
} else if (f->val[1]) {
if (pct <= f->val[1]) {
return f->text; return f->text;
} }
} }
} else if (f->val[1]) {
if (pct <= f->val[1]) {
return f->text;
}
} }
} }
} }
@ -1259,7 +1292,7 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
if (lf && (ownersize <= SZ_SMALL)) { if (lf && (ownersize <= SZ_SMALL)) {
if (pct <= 5) { if (pct <= 5) {
return "nip"; return "nip";
} else if (pct <= 30) { } else {
return "bite"; return "bite";
} }
} else { } else {
@ -1393,9 +1426,12 @@ enum DAMTYPE getdamtype(object_t *wep) {
int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam) { int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam) {
flag_t *f; flag_t *f;
int i;
// special case - EXTRADAM goes onto INITIAL dam[] if the same type, rather than // special case - EXTRADAM goes onto INITIAL dam[] if the same type, rather than
// adding a new one. // adding a new one.
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_EXTRADAM, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_EXTRADAM) { if (f->id == F_EXTRADAM) {
int *damwhere; int *damwhere;
int *damtypewhere; int *damtypewhere;
@ -1436,7 +1472,10 @@ int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam) {
int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) { int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) {
flag_t *f; flag_t *f;
for (f = wep->flags->first ; f ; f = f->next) { int i;
getflags(wep->flags, F_FROZEN, F_ONFIRE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_ONFIRE) { if (f->id == F_ONFIRE) {
if (strlen(f->text)) { if (strlen(f->text)) {
*(dam + *ndam) = roll(f->text); *(dam + *ndam) = roll(f->text);
@ -1468,7 +1507,10 @@ char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int d
if (wep) { if (wep) {
flag_t *f; flag_t *f;
for (f = wep->flags->first ; f ; f = f->next) { int i;
getflags(wep->flags, F_KILLVERB, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_KILLVERB) { if (f->id == F_KILLVERB) {
if ((f->val[0] == NA) && (f->val[1] == NA)) { if ((f->val[0] == NA) && (f->val[1] == NA)) {
return f->text; return f->text;
@ -1852,6 +1894,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
lifeform_t *victim; lifeform_t *victim;
lifeform_t *owner = NULL; lifeform_t *owner = NULL;
object_t *wep; object_t *wep;
int i;
if (!where) return; if (!where) return;
@ -1867,7 +1910,9 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
} }
victim = where->lf; victim = where->lf;
for (f = fp->first ; f ; f = f->next) { getflags(fp, F_DISARMATTACK, F_FLAMESTRIKE, F_HEAVYBLOW, F_HITCONFER, F_REVENGE, F_TRIPATTACK, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_FLAMESTRIKE) { if (f->id == F_FLAMESTRIKE) {
if (!hasob(where->obpile, OT_FIRESMALL)) { if (!hasob(where->obpile, OT_FIRESMALL)) {
// ignite! // ignite!

View File

@ -8,6 +8,7 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag);
void confereffects(flagpile_t *fp, lifeform_t *victim); void confereffects(flagpile_t *fp, lifeform_t *victim);
int damtypecausesbleed(enum DAMTYPE dt); int damtypecausesbleed(enum DAMTYPE dt);
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype); int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype);
void getarrange(int arating, int *min, int *max);
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp); char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp);
//object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag); //object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag);
enum DAMTYPE getdamtype(object_t *wep); enum DAMTYPE getdamtype(object_t *wep);

BIN
data/hiscores.db Normal file

Binary file not shown.

21
defs.h
View File

@ -16,6 +16,9 @@
#define SHOPIDENTPRICE 50 // cost to identify a just-purchased item #define SHOPIDENTPRICE 50 // cost to identify a just-purchased item
// rank, score, name, job, killer
#define HISCOREFORMAT "%-6s%-7s%-14s%-18s%s"
// ncurses colours // ncurses colours
#define C_NONE (-1) #define C_NONE (-1)
enum COLOUR { enum COLOUR {
@ -145,6 +148,7 @@ enum SKILLLEVEL {
// save/load // save/load
#define DATADIR "data"
#define MAPDIR "data/maps" #define MAPDIR "data/maps"
#define SAVEDIR "data/save" #define SAVEDIR "data/save"
#define VAULTDIR "vaults" #define VAULTDIR "vaults"
@ -236,7 +240,7 @@ enum SENSE {
// AI defs // AI defs
// if target lf is out of view for this many turns, abandon chase // if target lf is out of view for this many turns, abandon chase
#define AI_FOLLOWTIME (30) #define AI_FOLLOWTIME (50)
#define DEFAULTRESTHEALTIME (3) #define DEFAULTRESTHEALTIME (3)
@ -293,8 +297,11 @@ enum FLAGCONDITION {
#define BUFLENTINY 10 #define BUFLENTINY 10
#define BUFLENSMALL 64 #define BUFLENSMALL 64
#define BUFLEN 128 #define BUFLEN 128
#define BIGBUFLEN 512
#define HUGEBUFLEN 1024 #define HUGEBUFLEN 1024
#define MAXPNAMELEN 12
#define MORESTRING "--More--" #define MORESTRING "--More--"
#define MSGMORESTRING "^n--More--" #define MSGMORESTRING "^n--More--"
@ -659,6 +666,7 @@ enum RACE {
R_JAILER, R_JAILER,
// human monsters // human monsters
R_HUMAN, R_HUMAN,
R_BANDITLDR,
R_BANDIT, R_BANDIT,
R_BEGGAR, R_BEGGAR,
R_DRUNK, R_DRUNK,
@ -721,6 +729,7 @@ enum RACE {
R_ANTLION, R_ANTLION,
R_BAT, R_BAT,
R_BEAR, R_BEAR,
R_BEARCUB,
R_BEARGRIZZLY, R_BEARGRIZZLY,
R_CHICKEN, R_CHICKEN,
R_DOG, R_DOG,
@ -770,7 +779,7 @@ enum JOB {
J_GOD, J_GOD,
J_ADVENTURER, J_ADVENTURER,
J_ALLOMANCER, J_ALLOMANCER,
J_BARBARIAN, J_WARRIOR,
J_COMMANDO, J_COMMANDO,
J_DRUID, J_DRUID,
J_MONK, J_MONK,
@ -1271,12 +1280,14 @@ enum OBTYPE {
OT_BELTLEATHER, OT_BELTLEATHER,
// armour - legs // armour - legs
OT_CLOTHTROUSERS, OT_CLOTHTROUSERS,
OT_RIDINGTROUSERS,
OT_COMBATPANTS, OT_COMBATPANTS,
OT_GREAVES,
OT_RIDINGTROUSERS,
// armour - feet // armour - feet
OT_SANDALS, OT_SANDALS,
OT_SHOESLEATHER, OT_SHOESLEATHER,
OT_BOOTSLEATHER, OT_BOOTSLEATHER,
OT_BOOTSMETAL,
OT_BOOTSRUBBER, OT_BOOTSRUBBER,
OT_BOOTSSPIKED, OT_BOOTSSPIKED,
// armour - hands // armour - hands
@ -1886,7 +1897,7 @@ enum FLAG {
// text can be: // text can be:
// x (single number) // x (single number)
// x-y (range) // x-y (range)
F_DONTSTARTASLEEP, // this mosnter never starts off asleep F_STARTASLEEPPCT, // v0=pct chance this mosnter starts off asleep
F_STARTHIDDENPCT, // val0 = pct chance auto-generated monster will F_STARTHIDDENPCT, // val0 = pct chance auto-generated monster will
// start off hidden // start off hidden
F_CORPSETYPE, // text field specifies what corpse obtype to leave F_CORPSETYPE, // text field specifies what corpse obtype to leave
@ -1931,6 +1942,8 @@ enum FLAG {
// 1 and its map dificulty/depth. // 1 and its map dificulty/depth.
// if v0 is set, this is the max level. // if v0 is set, this is the max level.
F_MINION, // v0=lfid of minion F_MINION, // v0=lfid of minion
F_NOSCORE, // denotes that the player received 0 points.
// ie. cheating or they quit.
F_XPVAL, // force xp val for killing this lf to v0 F_XPVAL, // force xp val for killing this lf to v0
// ...OR if applied to an ability... // ...OR if applied to an ability...
// monsters with this abil/spell are worth // monsters with this abil/spell are worth

302
io.c
View File

@ -2924,7 +2924,7 @@ void cls(void) {
} }
void describeob(object_t *o) { void describeob(object_t *o) {
char buf[BUFLEN]; char buf[BIGBUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
int y; int y;
flag_t *f; flag_t *f;
@ -3082,12 +3082,15 @@ void describeob(object_t *o) {
ff2->val[0], (ff2->val[0] == 1) ? "" : "s"); ff2->val[0], (ff2->val[0] == 1) ? "" : "s");
y++; y++;
} else if (o->type->obclass->id == OC_WEAPON) { } else if (o->type->obclass->id == OC_WEAPON) {
flag_t *damflag;
int delay; int delay;
mvwprintw(mainwin, y, 0, "It is a %s weapon.", hasflag(o->flags, F_TWOHANDED) ? "two-handed" : "single handed"); sprintf(buf, "It is a %s weapon", hasflag(o->flags, F_TWOHANDED) ? "two-handed" : "single handed");
y++; damflag = hasflag(o->flags, F_DAM);
if (hasflag(o->flags, F_DAM)) { if (damflag) {
int bonus = 0; int bonus = 0;
char buf2[BUFLEN];
int mindam,maxdam;
enum DAMTYPE damtype;
f = hasflag(o->flags, F_BONUS); f = hasflag(o->flags, F_BONUS);
if (f && f->known) { if (f && f->known) {
@ -3095,33 +3098,28 @@ void describeob(object_t *o) {
bonus = f->val[0]; bonus = f->val[0];
} }
f = hasflag(o->flags, F_DAM); damtype = damflag->val[0];
if (f) { getdamrange(damflag, &mindam, &maxdam);
char buf[BUFLEN]; mindam += bonus;
int mindam,maxdam; maxdam += bonus;
enum DAMTYPE damtype; if (mindam < 0) mindam = 0;
damtype = f->val[0]; if (maxdam < 0) maxdam = 0;
getdamrange(f, &mindam, &maxdam);
mindam += bonus;
maxdam += bonus;
if (mindam < 0) mindam = 0;
if (maxdam < 0) maxdam = 0;
if (mindam == maxdam) { if (mindam == maxdam) {
sprintf(buf, " It inflicts %d %s damage",maxdam, getdamname(damtype)); sprintf(buf2, " which inflicts %d %s damage",maxdam, getdamname(damtype));
} else { } else {
sprintf(buf, " It inflicts %d-%d %s damage",mindam,maxdam, getdamname(damtype)); sprintf(buf2, " which inflicts %d-%d %s damage",mindam,maxdam, getdamname(damtype));
}
//dicetotext(f->val[0], f->val[1], f->val[2], NULL, NULL, dicebuf, NULL);
strcat(buf, " (");
strcat(buf, f->text);
strcat(buf, ").");
mvwprintw(mainwin, y, 0, "%s",buf);
y++;
} }
strcat(buf, buf2);
//dicetotext(f->val[0], f->val[1], f->val[2], NULL, NULL, dicebuf, NULL);
strcat(buf, " (");
strcat(buf, damflag->text); // ie. 2d6
strcat(buf, ").");
mvwprintw(mainwin, y, 0, "%s",buf);
y++;
// other extra damage or effects? // other extra damage or effects?
f = hasflag(o->flags, F_ONFIRE); f = hasflag(o->flags, F_ONFIRE);
@ -3133,6 +3131,9 @@ void describeob(object_t *o) {
} }
y++; y++;
} }
} else {
mvwprintw(mainwin, y, 0, "%s.", buf);
y++;
} }
delay = 100; delay = 100;
@ -3206,8 +3207,8 @@ void describeob(object_t *o) {
f = hasflag(o->flags, F_ACCURACYMOD); f = hasflag(o->flags, F_ACCURACYMOD);
if (f) { if (f) {
mvwprintw(mainwin, y, 0, " It will %s your evasion chance by %d%%.", buf, mvwprintw(mainwin, y, 0, " It will %s your evasion chance by %d%%.",
(f->val[0] < 0) ? "lower" : "raise", abs(f->val[0])); y++; (f->val[0] < 0) ? "lower" : "raise", abs(f->val[0]));
y++; y++;
} }
@ -3245,7 +3246,9 @@ void describeob(object_t *o) {
sprintf(buf, "It is in perfect condition."); sprintf(buf, "It is in perfect condition.");
} }
if (showfullhp) { if (showfullhp) {
sprintf(hpbuf, " [%d/%d hp]", f->val[0], f->val[1]); int pct;
pct = (int)(((float)f->val[0] / (float)f->val[1]) * 100.0);
sprintf(hpbuf, " [%d%%, %d/%d hp]", pct, f->val[0], f->val[1]);
} else if (isdamaged(o)) { } else if (isdamaged(o)) {
int pct; int pct;
pct = (int)(((float)f->val[0] / (float)f->val[1]) * 100.0); pct = (int)(((float)f->val[0] / (float)f->val[1]) * 100.0);
@ -3789,9 +3792,10 @@ void describeskill(enum SKILL skid) {
if (!sk) return; if (!sk) return;
// title // title
sprintf(buf, "Skill - %s",sk->name); sprintf(buf, "Skill::%s",sk->name);
capitalise(buf); wattron(mainwin, A_BOLD);
mvwprintw(mainwin, 0, 0, buf); mvwprintw(mainwin, 0, 0, buf);
wattroff(mainwin, A_BOLD);
mvwprintw(mainwin, 2, 0,"%s\n\n", sk->desc); mvwprintw(mainwin, 2, 0,"%s\n\n", sk->desc);
@ -5164,25 +5168,72 @@ void dohelp(void) {
int y; int y;
command_t *c; command_t *c;
char *ftext= "%c %s"; char *ftext= "%c %s";
enum {
HM_COMMANDS,
HM_MAIN,
HM_SKILLS,
} helpmode = HM_MAIN;
int done = B_FALSE;
int ch;
h = getmaxy(mainwin); h = getmaxy(mainwin);
cls(); while (!done) {
centre(mainwin,C_WHITE, 0, "COMMAND REFERENCE"); cls();
y = 2; if (helpmode == HM_MAIN) {
initprompt(&prompt, "What would you like help with (ESC when done)?");
addchoice(&prompt, '?', "Keyboard Commands", NULL, NULL);
addchoice(&prompt, 's', "Skill Descriptions", NULL, NULL);
addchoice(&prompt, '-', "(done)", NULL, NULL);
prompt.maycancel = B_TRUE;
ch = getchoice(&prompt);
switch (ch) {
case '?':
helpmode = HM_COMMANDS;
break;
case 's':
helpmode = HM_SKILLS;
break;
default:
done = B_TRUE;
break;
}
} else if (helpmode == HM_COMMANDS) {
centre(mainwin,C_WHITE, 0, "KEYBOARD COMMAND REFERENCE");
y = 2;
for (c = firstcommand ; c ; c = c->next) { for (c = firstcommand ; c ; c = c->next) {
mvwprintw(mainwin, y, 0, ftext, c->ch, c->desc); y++; mvwprintw(mainwin, y, 0, ftext, c->ch, c->desc); y++;
if (y >= (h-2)) { if (y >= (h-2)) {
centre(mainwin,C_WHITE, h-1, "--More--");
getch();
cls();
y = 2;
}
}
centre(mainwin,C_WHITE, h-1, "[Press any key]"); centre(mainwin,C_WHITE, h-1, "[Press any key]");
getch(); getch();
cls(); helpmode = HM_MAIN;
} else if (helpmode == HM_SKILLS) {
skill_t *sk;
centre(mainwin,C_WHITE, 0, "SKILL REFERENCE");
y = 2; y = 2;
initprompt(&prompt, "Describe which skill (ESC when done)?");
for (sk = firstskill ; sk ; sk = sk->next) {
addchoice(&prompt, 'a', sk->name, NULL, sk);
}
addchoice(&prompt, '\0', "(done)", NULL, NULL);
prompt.maycancel = B_TRUE;
ch = getchoicestr(&prompt, B_FALSE, B_TRUE);
if (!ch) {
helpmode = HM_MAIN;
} else {
sk = (skill_t *)prompt.result;
describeskill(sk->id);
}
} }
} }
centre(mainwin,C_WHITE, h-1, "[Press any key]");
getch();
restoregamewindows(); restoregamewindows();
} }
@ -5373,6 +5424,7 @@ void doquit(void) {
char ch; char ch;
ch = askchar("Really quit", "yn","n", B_TRUE); ch = askchar("Really quit", "yn","n", B_TRUE);
if (ch == 'y') { if (ch == 'y') {
addflag(player->flags, F_NOSCORE, B_TRUE, NA, NA, NULL);
setlastdam(player, "quitting"); setlastdam(player, "quitting");
player->alive = B_FALSE; player->alive = B_FALSE;
} }
@ -6350,7 +6402,9 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
wrefresh(mainwin); wrefresh(mainwin);
} }
curs_set(0); curs_set(0);
restoregamewindows(); if ((gamemode == GM_GAMESTARTED)) {
restoregamewindows();
}
// return NUL or result char // return NUL or result char
if (ch == 27) { if (ch == 27) {
return '\0'; return '\0';
@ -7353,9 +7407,12 @@ void redrawresume(void) {
void restoregamewindows(void) { void restoregamewindows(void) {
needredraw = B_TRUE; needredraw = B_TRUE;
statdirty = B_TRUE; statdirty = B_TRUE;
wclear(mainwin);
wrefresh(mainwin);
clearmsg(); clearmsg();
wclear(gamewin); wclear(gamewin);
drawscreen(); drawscreen();
redraw();
} }
int screenglyphmatches(int x, int y, glyph_t *g) { int screenglyphmatches(int x, int y, glyph_t *g) {
@ -7431,6 +7488,29 @@ void setobcolour(WINDOW *win, object_t *o, int set) {
} }
// dump out a single hiscore line
int showhiscoreline(void *hilitescore, int ncols, char **argv, char **colname) {
int i;
char *rank, *score, *name, *job, *killer;
for (i = 0; i < ncols; i++) {
if (streq(colname[i], "rank")) rank = strdup(argv[i]);
else if (streq(colname[i], "score")) score = strdup(argv[i]);
else if (streq(colname[i], "name")) name = strdup(argv[i]);
else if (streq(colname[i], "job")) job = strdup(argv[i]);
else if (streq(colname[i], "killedby")) killer = strdup(argv[i]);
}
if (streq(score, (char *)hilitescore)) setcol(mainwin, C_BOLDGREEN);
wprintw(mainwin, HISCOREFORMAT, rank, score, name, job, killer);
if (streq(score, (char *)hilitescore)) unsetcol(mainwin, C_BOLDGREEN);
wprintw(mainwin, "\n");
free(score);
free(name);
free(job);
free(killer);
return B_FALSE;
}
void showlfarmour(lifeform_t *lf) { void showlfarmour(lifeform_t *lf) {
enum BODYPART bp; enum BODYPART bp;
object_t *o; object_t *o;
@ -7457,23 +7537,29 @@ void showlfarmour(lifeform_t *lf) {
o = getequippedob(lf->pack, bp); o = getequippedob(lf->pack, bp);
outerob = getouterequippedob(lf, bp); outerob = getouterequippedob(lf, bp);
if (o) { if (o) {
flag_t *f;
char obname[BUFLEN]; char obname[BUFLEN];
getobname(o, obname, o->amt); getobname(o, obname, o->amt);
strcpy(rhs, obname); strcpy(rhs, obname);
}
if (outerob && (outerob != o)) { if (outerob && (outerob != o)) {
char outerobname[BUFLEN]; char outerobname[BUFLEN];
getobname(outerob, outerobname, outerob->amt); getobname(outerob, outerobname, outerob->amt);
if (strlen(rhs)) strcat(rhs, " "); if (strlen(rhs)) strcat(rhs, " ");
strcat(rhs, "(covered) "); strcat(rhs, "(covered) ");
} }
if (strlen(rhs)) {
flag_t *f;
f = hasflag(o->flags, F_ARMOURRATING); f = hasflag(o->flags, F_ARMOURRATING);
if (f) { if (f) {
char numbuf[BUFLENSMALL]; char numbuf[BUFLENSMALL];
sprintf(numbuf, " [AR:%d]",f->val[0]); sprintf(numbuf, " ^g[AR:%d]^n",f->val[0]);
strcat(rhs, numbuf);
}
f = hasflag(o->flags, F_OBHP);
if (f && (f->val[0] != f->val[1])) {
char numbuf[BUFLENSMALL];
int pct;
pct = (int)(((float)f->val[0] / (float)f->val[1]) * 100.0);
sprintf(numbuf, " ^w[%d%%]^n",pct);
strcat(rhs, numbuf); strcat(rhs, numbuf);
} }
} else { } else {
@ -7481,36 +7567,16 @@ void showlfarmour(lifeform_t *lf) {
} }
mvwprintw(mainwin, y, 0, "%s", buf); mvwprintw(mainwin, y, 0, "%s", buf);
setobcolour(mainwin, o, B_TRUE); if (o) setobcolour(mainwin, o, B_TRUE);
wprintw(mainwin, "%s", rhs); //wprintw(mainwin, "%s", rhs);
setobcolour(mainwin, o, B_FALSE); textwithcol(mainwin, rhs);
if (o) setobcolour(mainwin, o, B_FALSE);
y++; y++;
} }
} }
y = getmaxy(mainwin); y = getmaxy(mainwin);
centre(mainwin, C_WHITE, y-1, "[Press any key]"); centre(mainwin, C_WHITE, y-1, "[Press any key]");
/*
f = hasflag(mylist[i]->flags,F_EQUIPPED);
if (f) {
if (f->val[0] == BP_WEAPON) {
if (hasflag(mylist[i]->flags, F_TWOHANDED)) {
strcat(buf2, " (two-handed weapon)");
} else {
strcat(buf2, " (weapon)");
}
} else {
strcat(buf2, " (");
strcat(buf2, getbodypartequipname(f->val[0]));
strcat(buf2, " ");
strcat(buf2, getbodypartname(f->val[0]));
strcat(buf2, ")");
}
}
*/
getch(); getch();
restoregamewindows(); restoregamewindows();
@ -7942,7 +8008,9 @@ void showlfstats(lifeform_t *lf, int showall) {
if (arating == 0) { if (arating == 0) {
wprintw(mainwin, "%d (no dmgreduce)", arating); y2++; wprintw(mainwin, "%d (no dmgreduce)", arating); y2++;
} else { } else {
wprintw(mainwin, "%d (dmgreduce %d-%d)", arating, arating/5, arating); y2++; int min,max;
getarrange(arating, &min, &max);
wprintw(mainwin, "%d (dmgreduce %d-%d)", arating, min, max); y2++;
} }
if (lorelev >= PR_NOVICE) unsetcol(mainwin, lorecol); if (lorelev >= PR_NOVICE) unsetcol(mainwin, lorecol);
} }
@ -8648,7 +8716,9 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; y++;
} }
if (hasjob(lf, J_DRUID)) { if (hasjob(lf, J_DRUID)) {
mvwprintw(mainwin, y, 0, "%s spells are boosted by nearby plants.", isplayer(lf) ? "Your" : "Its"); mvwprintw(mainwin, y, 0, "%s spell power is boosted by nearby plants.", isplayer(lf) ? "Your" : "Its");
y++;
mvwprintw(mainwin, y, 0, "%s regenerate mana when plants are nearby.", you(lf));
y++; y++;
} }
@ -8951,7 +9021,7 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
f = lfhasflag(lf, F_RAGE); f = lfhasflag(lf, F_RAGE);
if (f && (f->known)) { if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s enraged, gaining temporary strength and hit points.", you(lf), is(lf)); mvwprintw(mainwin, y, 0, "%s %s enraged, gaining accuracy, damage and hit point bonuses.", you(lf), is(lf));
y++; y++;
} }
f = lfhasknownflag(lf, F_REGENERATES); f = lfhasknownflag(lf, F_REGENERATES);
@ -9163,8 +9233,13 @@ void textwithcol(WINDOW *win, char *buf) {
void tombstone(lifeform_t *lf) { void tombstone(lifeform_t *lf) {
char pname[BUFLEN]; char pname[BUFLEN];
char buf[BUFLEN]; char buf[BUFLEN];
char killer[BUFLEN];
int y; int y;
char *p, *dummy; int rank,minrank,maxrank;
char *p;
long playerscore;
playerscore = calcscore(lf);
getplayernamefull(pname); getplayernamefull(pname);
@ -9174,7 +9249,7 @@ void tombstone(lifeform_t *lf) {
y = 1; y = 1;
centre(mainwin, C_GREY, y, "R.I.P."); y++; centre(mainwin, C_GREY, y, "R.I.P."); y++;
//printf("%s\n",lf->name); //printf("%s\n",lf->name);
centre(mainwin, C_GREY, y, "%s (%ld points)",pname, calcscore(lf)); y++; centre(mainwin, C_GREY, y, "%s (%ld points)",pname, playerscore); y++;
if (player->cell->map->region->rtype->id == RG_WORLDMAP) { if (player->cell->map->region->rtype->id == RG_WORLDMAP) {
getregionname(buf, player->cell->map, B_TRUE); getregionname(buf, player->cell->map, B_TRUE);
@ -9184,27 +9259,52 @@ void tombstone(lifeform_t *lf) {
centre(mainwin, C_GREY, y, "Died on level %d of %s.", player->cell->map->depth, buf); y++; centre(mainwin, C_GREY, y, "Died on level %d of %s.", player->cell->map->depth, buf); y++;
} }
p = strtok_r(lf->lastdam,"^", &dummy); makekillertext(killer, lf->lastdam, B_TRUE);
if (p) {
if (!strcmp(p, "you")) { p = readuntil(buf, killer, '\n');
centre(mainwin, C_GREY, y, "Committed suicide.",p); y++; while (strlen(buf)) {
} else { centre(mainwin, C_GREY, y, buf); y++;
centre(mainwin, C_GREY, y, "Killed by %s.",p); y++; p = readuntil(buf, p, '\n');
}
p = strtok_r(NULL, "^", &dummy);
while (p) {
centre(mainwin, C_GREY, y, "(%s)",p); y++;
p = strtok_r(NULL, "^", &dummy);
}
} else {
centre(mainwin, C_GREY, y, "Killed by something unknown."); y++;
} }
wrefresh(mainwin); wrefresh(mainwin);
// write hiscores and calculate player's rank
writehiscore(player, &rank);
// wait for key... // wait for key...
getch(); getch();
cls();
y = 0;
if (rank == -1) {
mvwprintw(mainwin, y, 0, "Since you were cheating, your score will not be listed."); y++;
minrank = 1;
maxrank = 10;
} else if (rank > 100) {
mvwprintw(mainwin, y, 0, "You didn't make the top 100 list."); y++;
minrank = 1;
maxrank = 10;
} else {
setcol(mainwin, C_BOLDGREEN);
mvwprintw(mainwin, y, 0, "You made rank #%d on the high score table!", rank); y++;
unsetcol(mainwin, C_BOLDGREEN);
minrank = rank - 4;
maxrank = rank + 4;
limit(&minrank, 0, NA);
limit(&maxrank, NA, 100);
}
centre(mainwin, C_GREY, y, "High Scores"); y += 2;
wattron(mainwin, A_BOLD);
mvwprintw(mainwin, y, 0, HISCOREFORMAT, "Rank", "Score", "Name", "Job", "Method of death"); y++;
wmove(mainwin, y, 0);
wattroff(mainwin, A_BOLD);
showhiscores(player, minrank, maxrank);
getch();
// close down graphics ready to quit // close down graphics ready to quit
// clear windows // clear windows

1
io.h
View File

@ -108,6 +108,7 @@ int screenglyphmatches(int x, int y, glyph_t *g);
void setcol(WINDOW *win, enum COLOUR col); void setcol(WINDOW *win, enum COLOUR col);
void unsetcol(WINDOW *win, enum COLOUR col); void unsetcol(WINDOW *win, enum COLOUR col);
void setobcolour(WINDOW *win, object_t *o, int set); void setobcolour(WINDOW *win, object_t *o, int set);
int showhiscoreline(void *hilitescore, int ncols, char **argv, char **colname);
void showlfarmour(lifeform_t *lf); void showlfarmour(lifeform_t *lf);
void showlfstats(lifeform_t *lf, int showall); void showlfstats(lifeform_t *lf, int showall);
void textwithcol(WINDOW *win, char *buf); void textwithcol(WINDOW *win, char *buf);

559
lf.c
View File

@ -224,6 +224,9 @@ void breakallgrabs(lifeform_t *lf) {
long calcscore(lifeform_t *lf) { long calcscore(lifeform_t *lf) {
long points = 0; long points = 0;
object_t *o; object_t *o;
if (lfhasflag(lf, F_NOSCORE)) {
return 0;
}
// objects // objects
for (o = lf->pack->first ; o ; o = o->next) { for (o = lf->pack->first ; o ; o = o->next) {
points += getobvalue(o); points += getobvalue(o);
@ -245,7 +248,7 @@ int calcxp(lifeform_t *lf) {
float avgdam = 0; float avgdam = 0;
int db = B_FALSE; int db = B_FALSE;
int maxhdroll; int maxhdroll;
int i;
float xpconstant = 1; float xpconstant = 1;
if (lfhasflag(lf, F_DEBUG)) { if (lfhasflag(lf, F_DEBUG)) {
@ -303,7 +306,9 @@ int calcxp(lifeform_t *lf) {
// spells // spells
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_CANCAST, F_CANWILL, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_CANCAST) { if (f->id == F_CANCAST) {
objecttype_t *ot; objecttype_t *ot;
int power,level; int power,level;
@ -920,6 +925,7 @@ int cansleep(lifeform_t *lf) {
// where == BP_NONE means "can i wear it anywhere?' // where == BP_NONE means "can i wear it anywhere?'
int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) { int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) {
int i;
object_t *oo; object_t *oo;
flag_t *f; flag_t *f;
@ -946,7 +952,9 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) {
} }
// other flags to check // other flags to check
for (f = o->flags->first ; f ; f = f->next) { getflags(o->flags, F_ATTREQ, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_ATTREQ) { if (f->id == F_ATTREQ) {
// meetsattreq will set 'reason' for us. // meetsattreq will set 'reason' for us.
if (!meetsattreq(lf, f, o)) { if (!meetsattreq(lf, f, o)) {
@ -961,7 +969,9 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) {
enum BODYPART possbp[MAXBODYPARTS]; enum BODYPART possbp[MAXBODYPARTS];
int nparts = 0; int nparts = 0;
int i; int i;
for (f = o->flags->first ; f ; f = f->next) { getflags(o->flags, F_GOESON, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_GOESON) { if (f->id == F_GOESON) {
possbp[nparts] = f->val[0]; possbp[nparts] = f->val[0];
nparts++; nparts++;
@ -1044,7 +1054,10 @@ int canweild(lifeform_t *lf, object_t *o) {
} }
if (o) { if (o) {
for (f = o->flags->first ; f; f = f->next) { int i;
getflags(o->flags, F_ATTREQ, F_TWOHANDED, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_ATTREQ) { if (f->id == F_ATTREQ) {
// meetsattreq will set 'reason' for us. // meetsattreq will set 'reason' for us.
if (!meetsattreq(lf, f, o)) { if (!meetsattreq(lf, f, o)) {
@ -1214,16 +1227,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
// boost power? // boost power?
if (hasjob(lf, J_DRUID)) { if (hasjob(lf, J_DRUID)) {
int n; power += countplantsinsight(lf);
int boost = 0;
for (n = 0; n < lf->nlos; n++) {
if (lf->los[n]->lf && getraceclass(lf->los[n]->lf) == RC_PLANT) {
boost++;
} else if (hasobofclass(lf->los[n]->obpile, OC_FLORA)) {
boost++;
}
}
power += boost;
limit(&power, NA, 10); limit(&power, NA, 10);
} }
@ -1449,9 +1453,11 @@ float comparelfs(lifeform_t *lf1, lifeform_t *lf2) {
} }
int countinnateattacks(lifeform_t *lf) { int countinnateattacks(lifeform_t *lf) {
int count = 0; int count = 0,i;
flag_t *f; flag_t *f;
for (f = lf->flags->first ; f; f = f->next) { getflags(lf->flags, F_HASATTACK, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_HASATTACK) count++; if (f->id == F_HASATTACK) count++;
} }
return count; return count;
@ -1495,6 +1501,18 @@ int countnearbyhurtallies(lifeform_t *lf) {
return count; return count;
} }
int countplantsinsight(lifeform_t *lf) {
int n, boost = 0;
for (n = 0; n < lf->nlos; n++) {
if (lf->los[n]->lf && getraceclass(lf->los[n]->lf) == RC_PLANT) {
boost++;
} else if (hasobofclass(lf->los[n]->obpile, OC_FLORA)) {
boost++;
}
}
return boost;
}
// toggle debugging // toggle debugging
void debug(lifeform_t *lf) { void debug(lifeform_t *lf) {
char lfname[BUFLEN]; char lfname[BUFLEN];
@ -1608,7 +1626,7 @@ void die(lifeform_t *lf) {
flag_t *f; flag_t *f;
cell_t *where; cell_t *where;
//int dropobs = B_TRUE; //int dropobs = B_TRUE;
int vaporised = B_FALSE; int vaporised = B_FALSE, i;
int willbecomeghost = B_FALSE; int willbecomeghost = B_FALSE;
object_t *corpse = NULL; object_t *corpse = NULL;
@ -1799,7 +1817,9 @@ void die(lifeform_t *lf) {
} }
// add extra flags ? // add extra flags ?
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_CORPSEFLAG, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_CORPSEFLAG) { if (f->id == F_CORPSEFLAG) {
addflag(corpse->flags, f->val[0], f->val[1], f->val[2], NA, f->text); addflag(corpse->flags, f->val[0], f->val[1], f->val[2], NA, f->text);
} }
@ -3190,8 +3210,9 @@ enum SKILLLEVEL findskilllevbyname(char *name) {
// anyone we are fleeing from. // anyone we are fleeing from.
// returns TRUE if we ran away from something // returns TRUE if we ran away from something
int flee(lifeform_t *lf) { int flee(lifeform_t *lf) {
flag_t *f, *nextf; flag_t *f;
lifeform_t *fleefrom = NULL; lifeform_t *fleefrom = NULL;
int i;
// mindless? // mindless?
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) == IQ_MINDLESS) { if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) == IQ_MINDLESS) {
@ -3199,8 +3220,10 @@ int flee(lifeform_t *lf) {
} }
// are we fleeing? // are we fleeing?
for (f = lf->flags->first ; f ; f = nextf) {
nextf = f->next; getflags(lf->flags, F_FLEEFROM, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_FLEEFROM) { if (f->id == F_FLEEFROM) {
lifeform_t *thisone; lifeform_t *thisone;
thisone = findlf(lf->cell->map, f->val[0]); thisone = findlf(lf->cell->map, f->val[0]);
@ -3239,9 +3262,15 @@ int flee(lifeform_t *lf) {
lifeform_t *targlf; lifeform_t *targlf;
cell_t *targcell; cell_t *targcell;
object_t *targob; object_t *targob;
objecttype_t *sp;
sp = findot(spell);
aigetspelltarget(lf, findot(spell), fleefrom, &targlf, &targcell, &targob, F_AICASTTOFLEE); aigetspelltarget(lf, findot(spell), fleefrom, &targlf, &targcell, &targob, F_AICASTTOFLEE);
return castspell(lf, spell, targlf, targob, targcell);
if (getschool(spell) == SS_ABILITY) {
return useability(lf, spell, targlf, targcell);
} else {
return castspell(lf, spell, targlf, targob, targcell);
}
} }
// if AI, use helpful fleeing items // if AI, use helpful fleeing items
if (!useitemwithflag(lf, F_AIFLEEITEM)) { if (!useitemwithflag(lf, F_AIFLEEITEM)) {
@ -3510,6 +3539,7 @@ void gainxp(lifeform_t *lf, long amt) {
int getactspeed(lifeform_t *lf) { int getactspeed(lifeform_t *lf) {
int speed = 0; int speed = 0;
flag_t *f; flag_t *f;
int i;
f = lfhasflag(lf, F_ACTIONSPEED); f = lfhasflag(lf, F_ACTIONSPEED);
if (f) { if (f) {
@ -3519,7 +3549,9 @@ int getactspeed(lifeform_t *lf) {
} }
// modifier? // modifier?
for (f = lf->flags->first ; f ; f = f->next ){ getflags(lf->flags, F_SLOWACT, F_SLOWACTMOVE, F_FASTACT, F_FASTACTMOVE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if ((f->id == F_SLOWACT) || (f->id == F_SLOWACTMOVE)) { if ((f->id == F_SLOWACT) || (f->id == F_SLOWACTMOVE)) {
speed += f->val[0]; speed += f->val[0];
} else if ((f->id == F_FASTACT) || (f->id == F_FASTACTMOVE)) { } else if ((f->id == F_FASTACT) || (f->id == F_FASTACTMOVE)) {
@ -3661,13 +3693,15 @@ int getarmournoise(lifeform_t *lf) {
int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, int *narms) { int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, int *narms) {
object_t *o; object_t *o;
flag_t *f; flag_t *f;
int ar = 0; int ar = 0, i;
if (narms) { if (narms) {
(*narms) = 0; (*narms) = 0;
} }
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_ARMOURRATING, F_MAGICARMOUR, F_PHALANX, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_ARMOURRATING) { if (f->id == F_ARMOURRATING) {
ar += f->val[0]; ar += f->val[0];
if (hitob) { if (hitob) {
@ -3798,7 +3832,7 @@ int getattr(lifeform_t *lf, enum ATTRIB attr) {
} }
int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) { int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) {
int val = 0; int val = 0, i;
flag_t *f; flag_t *f;
// override? // override?
@ -3812,7 +3846,9 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) {
// base attribute // base attribute
val = lf->att[attr]; val = lf->att[attr];
// modified? // modified?
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_ATTRMOD, F_DRUNK, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if ((f->id == F_ATTRMOD) && (f->val[0] == attr)) { if ((f->id == F_ATTRMOD) && (f->val[0] == attr)) {
val += f->val[1]; val += f->val[1];
} }
@ -3833,7 +3869,7 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) {
// returns average damage per turn, modified by accuracy // returns average damage per turn, modified by accuracy
int getavgdam(lifeform_t *lf, int forxp) { int getavgdam(lifeform_t *lf, int forxp) {
obpile_t *op; obpile_t *op;
int avgdam = 0; int avgdam = 0,i;
int db = B_FALSE; int db = B_FALSE;
flag_t *f; flag_t *f;
@ -3842,7 +3878,9 @@ int getavgdam(lifeform_t *lf, int forxp) {
} }
op = addobpile(NULL, NULL, NULL); op = addobpile(NULL, NULL, NULL);
for (f = lf->race->flags->first ; f ; f = f->next) { getflags(lf->race->flags, F_HASATTACK, F_STARTOB, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_HASATTACK) { if (f->id == F_HASATTACK) {
int min,max; int min,max;
float thisavg; float thisavg;
@ -3889,43 +3927,45 @@ int getavgdam(lifeform_t *lf, int forxp) {
getobname(o,obname,1); getobname(o,obname,1);
if (db) dblog("getavgdam: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg); if (db) dblog("getavgdam: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg);
} }
} else if (forxp && (f->id == F_STARTOB)) { } else if (forxp && (f->id == F_STARTOB)) { // starting weapons...
object_t *o; objecttype_t *ot;
int min,max;
float thisavg;
float acc;
flag_t *of;
obpile_t *op2;
op2 = addobpile(NULL,NULL, NULL); ot = findotn(f->text);
if (ot && (ot->obclass->id == OC_WEAPON)) {
obpile_t *op2;
object_t *o;
op2 = addobpile(NULL,NULL, NULL);
o = addob(op2, f->text);
if (o) {
int min,max;
float thisavg;
float acc;
flag_t *of;
o = addob(op2, f->text); getdamrange(hasflag(o->flags, F_DAM), &min,&max);
thisavg = ((float)min + (float)max) / 2.0;
if (o) {
getdamrange(hasflag(o->flags, F_DAM), &min,&max);
thisavg = ((float)min + (float)max) / 2.0;
// confers anything? // confers anything?
for (of = o->flags->first ; of ; of = of->next) { for (of = o->flags->first ; of ; of = of->next) {
if (of->id == F_HITCONFER) { if (of->id == F_HITCONFER) {
thisavg += 10; thisavg += 10;
}
}
// modify for accuracy
acc = getlfaccuracy(lf, o);
thisavg = pctof(acc, thisavg);
avgdam += thisavg;
if (db) {
char obname[BUFLEN];
getobname(o,obname,1);
if (db) dblog("getavgdam: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg);
} }
} }
killobpile(op2);
// modify for accuracy
acc = getlfaccuracy(lf, o);
thisavg = pctof(acc, thisavg);
avgdam += thisavg;
if (db) {
char obname[BUFLEN];
getobname(o,obname,1);
if (db) dblog("getavgdam: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg);
}
} }
killobpile(op2);
} }
} }
@ -3994,7 +4034,7 @@ float getequippedweight(lifeform_t *lf) {
int getevasion(lifeform_t *lf) { int getevasion(lifeform_t *lf) {
flag_t *f; flag_t *f;
int ev = 0; int ev = 0,i;
// no evasion if you can't move! // no evasion if you can't move!
if (isimmobile(lf)) { if (isimmobile(lf)) {
@ -4034,7 +4074,9 @@ int getevasion(lifeform_t *lf) {
*/ */
// adjust for bulky armour/shield // adjust for bulky armour/shield
for (f = lf->flags->first ;f ; f = f->next) { getflags(lf->flags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_ARMOURPENALTY) { if (f->id == F_ARMOURPENALTY) {
ev -= adjustarmourpenalty(lf, f->val[1]); ev -= adjustarmourpenalty(lf, f->val[1]);
} else if (f->id == F_SHIELDPENALTY) { } else if (f->id == F_SHIELDPENALTY) {
@ -4431,7 +4473,7 @@ int getlastdir(lifeform_t *lf) {
int getlfaccuracy(lifeform_t *lf, object_t *wep) { int getlfaccuracy(lifeform_t *lf, object_t *wep) {
flag_t *f; flag_t *f;
object_t *o; object_t *o;
int acc = 0; int acc = 0,i;
// get weapon // get weapon
if (wep) { if (wep) {
@ -4458,7 +4500,9 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
} }
// adjust for bulky armour/shield // adjust for bulky armour/shield
for (f = lf->flags->first ;f ; f = f->next) { getflags(lf->flags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_SHIELDPENALTY) { if (f->id == F_SHIELDPENALTY) {
acc -= adjustshieldpenalty(lf, f->val[0]); acc -= adjustshieldpenalty(lf, f->val[0]);
} else if (f->id == F_ARMOURPENALTY) { } else if (f->id == F_ARMOURPENALTY) {
@ -4595,7 +4639,11 @@ int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions) {
flag_t *f; flag_t *f;
lifeform_t *min; lifeform_t *min;
*nminions = 0; *nminions = 0;
for (f = lf->flags->first ; f ; f = f->next) { int i;
getflags(lf->flags, F_MINION, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_MINION) { if (f->id == F_MINION) {
min = findlf(lf->cell->map, f->val[0]); min = findlf(lf->cell->map, f->val[0]);
if (min) { if (min) {
@ -4848,7 +4896,7 @@ float getmaxcarryweight(lifeform_t *lf) {
int getmaxmp(lifeform_t *lf) { int getmaxmp(lifeform_t *lf) {
flag_t *f; flag_t *f;
int activemp = 0; int activemp = 0;
int maxmp; int maxmp,i;
int extrapct = 0; int extrapct = 0;
// base // base
@ -4860,7 +4908,9 @@ int getmaxmp(lifeform_t *lf) {
// losses // losses
activemp = 0; activemp = 0;
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_BOOSTSPELL, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_BOOSTSPELL) { if (f->id == F_BOOSTSPELL) {
activemp += f->val[1]; activemp += f->val[1];
} }
@ -4887,7 +4937,7 @@ int getmr(lifeform_t *lf) {
int getvisrange(lifeform_t *lf) { int getvisrange(lifeform_t *lf) {
int range; int range,i;
flag_t *f; flag_t *f;
if (isblind(lf)) { if (isblind(lf)) {
@ -4921,7 +4971,9 @@ int getvisrange(lifeform_t *lf) {
} }
// modifications? // modifications?
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_VISRANGEMOD, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_VISRANGEMOD) { if (f->id == F_VISRANGEMOD) {
range += f->val[0]; range += f->val[0];
} }
@ -4932,7 +4984,7 @@ int getvisrange(lifeform_t *lf) {
} }
int getmovespeed(lifeform_t *lf) { int getmovespeed(lifeform_t *lf) {
int speed = 0; int speed = 0,i;
flag_t *f; flag_t *f;
object_t *o; object_t *o;
@ -4944,7 +4996,9 @@ int getmovespeed(lifeform_t *lf) {
} }
// modifier? // modifier?
for (f = lf->flags->first ; f ; f = f->next ){ getflags(lf->flags, F_FASTMOVE, F_FASTACTMOVE, F_SLOWMOVE, F_SLOWACTMOVE, F_SPRINTING, F_TIRED, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if ((f->id == F_SLOWMOVE) || (f->id == F_SLOWACTMOVE)) { if ((f->id == F_SLOWMOVE) || (f->id == F_SLOWACTMOVE)) {
speed += f->val[0]; speed += f->val[0];
} else if ((f->id == F_FASTMOVE) || (f->id == F_FASTACTMOVE)) { } else if ((f->id == F_FASTMOVE) || (f->id == F_FASTACTMOVE)) {
@ -6707,7 +6761,12 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
void givestartskills(lifeform_t *lf, flagpile_t *fp) { void givestartskills(lifeform_t *lf, flagpile_t *fp) {
flag_t *f; flag_t *f;
for (f = fp->first ; f ; f = f->next) { int i;
getflags(fp, F_STARTSKILL, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_STARTSKILL) { if (f->id == F_STARTSKILL) {
int wantval; int wantval;
wantval = f->val[1]; wantval = f->val[1];
@ -7396,6 +7455,7 @@ void initjobs(void) {
//mayusespellschool(lastjob->flags, i, F_CANWILL); //mayusespellschool(lastjob->flags, i, F_CANWILL);
} }
} }
addflag(lastjob->flags, F_NOSCORE, B_TRUE, NA, NA, NULL);
addjob(J_ADVENTURER, "Adventurer"); addjob(J_ADVENTURER, "Adventurer");
// stats // stats
@ -7462,57 +7522,6 @@ void initjobs(void) {
addflag(lastjob->flags, F_DETECTMETAL, B_TRUE, NA, NA, NULL); addflag(lastjob->flags, F_DETECTMETAL, B_TRUE, NA, NA, NULL);
mayusespellschool(lastjob->flags, SS_ALLOMANCY, F_CANCAST); mayusespellschool(lastjob->flags, SS_ALLOMANCY, F_CANCAST);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL); addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addjob(J_BARBARIAN, "Barbarian");
// stats
addflag(lastjob->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_DEX, AT_GTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_CON, AT_GTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_CHA, AT_LTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_WIS, AT_LTAVERAGE, NA, NULL);
// initial objects
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "buckler");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather armour");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 gold coins");
// initial skills
addflag(lastjob->flags, F_STARTSKILL, SK_AXES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CLUBS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_TRACKING, PR_NOVICE, NA, NULL);
// learnable skills
addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LOCKPICKING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_STEALTH, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SWIMMING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_AXES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CLUBS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LONGBLADES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_THROWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TWOWEAPON, NA, NA, NULL);
// abilities
addflag(lastjob->flags, F_HITDICE, 1, 6, NA, NULL);
addflag(lastjob->flags, F_SELECTWEAPON, B_TRUE, NA, NA, NULL);
addflag(lastjob->flags, F_LEVABIL, 3, OT_A_HEAVYBLOW, 3, NULL);
addflag(lastjob->flags, F_LEVABIL, 4, OT_A_WARCRY, 4, NULL);
addflag(lastjob->flags, F_LEVABIL, 5, OT_A_CHARGE, 5, NULL);
addflag(lastjob->flags, F_LEVABIL, 6, OT_A_RAGE, 50, NULL);
addflag(lastjob->flags, F_LEVABIL, 10, OT_A_HURRICANESTRIKE, 5, NULL);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addjob(J_COMMANDO, "Commando"); addjob(J_COMMANDO, "Commando");
// stats // stats
addflag(lastjob->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL); addflag(lastjob->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
@ -7808,6 +7817,60 @@ void initjobs(void) {
// abilities // abilities
addflag(lastjob->flags, F_MPDICE, 1, NA, NA, NULL); addflag(lastjob->flags, F_MPDICE, 1, NA, NA, NULL);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL); addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addjob(J_WARRIOR, "Warrior");
// stats
addflag(lastjob->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_DEX, AT_GTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_CON, AT_GTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_CHA, AT_LTAVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_WIS, AT_LTAVERAGE, NA, NULL);
// initial objects
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "helmet");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "suit of ring mail");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of gauntlets");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "set of greaves");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of metal boots");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "buckler");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10-20 gold coins");
// initial skills
addflag(lastjob->flags, F_STARTSKILL, SK_AXES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CLUBS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SEWING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_METALWORK, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_TRACKING, PR_NOVICE, NA, NULL);
// learnable skills
addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SWIMMING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_AXES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CLUBS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LONGBLADES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_THROWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TWOWEAPON, NA, NA, NULL);
// abilities
addflag(lastjob->flags, F_HITDICE, 1, 4, NA, NULL);
addflag(lastjob->flags, F_SELECTWEAPON, B_TRUE, NA, NA, NULL);
addflag(lastjob->flags, F_LEVABIL, 3, OT_A_HEAVYBLOW, 3, NULL);
addflag(lastjob->flags, F_LEVABIL, 4, OT_A_WARCRY, 4, NULL);
addflag(lastjob->flags, F_LEVABIL, 5, OT_A_CHARGE, 5, NULL);
addflag(lastjob->flags, F_LEVABIL, 6, OT_A_RAGE, 50, NULL);
addflag(lastjob->flags, F_LEVABIL, 10, OT_A_HURRICANESTRIKE, 5, NULL);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addjob(J_WIZARD, "Wizard"); addjob(J_WIZARD, "Wizard");
// stats // stats
addflag(lastjob->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL); addflag(lastjob->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL);
@ -7903,8 +7966,10 @@ void initrace(void) {
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d4"); addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d4");
addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "11-13"); addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "11-13");
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_VLOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STAYINROOM, NA, NA, NA, NULL); // stay in our maze
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "50-100 gold coins"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "50-100 gold coins");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "+2 halberd"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "+2 halberd");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "gas mask"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "gas mask");
@ -7948,14 +8013,13 @@ void initrace(void) {
addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL);
// human monsters... // human monsters...
addrace(R_BANDIT, "bandit", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID); addrace(R_BANDITLDR, "bandit leader", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_RARITY, H_FOREST, 80, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 80, NA, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL); addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_DEMANDSBRIBE, NA, NA, NA, NULL); addflag(lastrace->flags, F_DEMANDSBRIBE, NA, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 2, 2, NA, NULL); addflag(lastrace->flags, F_HITDICE, 2, 2, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 1, 3, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2"); addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2");
@ -7967,7 +8031,28 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_SCROLL, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_SCROLL, NA, NULL);
//addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "shouts^a shout"); addflag(lastrace->flags, F_WANTS, OT_GOLD, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSBETTERARM, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MINIONS, 100, 1, 3, "bandit");
addrace(R_BANDIT, "bandit", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_RARITY, H_FOREST, 80, NA, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 1, 3, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "1-100 gold coins");
addflag(lastrace->flags, F_STARTOBCLASS, 100, OC_WEAPON, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 100, OC_ARMOUR, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_ARMOUR, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 15, OC_POTION, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 15, OC_SCROLL, NA, NULL);
addflag(lastrace->flags, F_WANTS, OT_GOLD, B_COVETS, NA, NULL); addflag(lastrace->flags, F_WANTS, OT_GOLD, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSBETTERARM, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSBETTERARM, B_TRUE, NA, NA, NULL);
@ -8026,7 +8111,7 @@ void initrace(void) {
addrace(R_TOWNGUARD, "town guard", 100, '@', C_GREY, MT_FLESH, RC_HUMANOID); addrace(R_TOWNGUARD, "town guard", 100, '@', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "12-18"); addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "12-18");
addflag(lastrace->flags, F_DONTSTARTASLEEP, NA, NA, NA, NULL); addflag(lastrace->flags, F_STARTASLEEPPCT, 0, NA, NA, NULL);
addflag(lastrace->flags, F_STAYINHABITAT, NA, NA, NA, NULL); addflag(lastrace->flags, F_STAYINHABITAT, NA, NA, NA, NULL);
addflag(lastrace->flags, F_GUARD, NA, NA, NA, NULL); addflag(lastrace->flags, F_GUARD, NA, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_VILLAGE, 80, NA, NULL); addflag(lastrace->flags, F_RARITY, H_VILLAGE, 80, NA, NULL);
@ -8057,7 +8142,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "10"); addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "10");
addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "8"); addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "8");
addflag(lastrace->flags, F_STARTATT, A_CHA, NA, NA, "6"); addflag(lastrace->flags, F_STARTATT, A_CHA, NA, NA, "6");
addflag(lastrace->flags, F_DONTSTARTASLEEP, NA, NA, NA, NULL); addflag(lastrace->flags, F_STARTASLEEPPCT, 0, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 30, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_UNIQUE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_UNIQUE, B_TRUE, NA, NA, NULL);
@ -9311,6 +9396,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 73, NA, ""); addflag(lastrace->flags, F_RARITY, H_FOREST, 73, NA, "");
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_STARTASLEEPPCT, 80, NA, NA, NULL); // hibernating
addflag(lastrace->flags, F_HITDICE, 3, 3, NA, NULL); addflag(lastrace->flags, F_HITDICE, 3, 3, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
@ -9326,11 +9412,14 @@ void initrace(void) {
addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:2d4;"); addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:2d4;");
addrace(R_BEARGRIZZLY, "grizzly bear", 200, 'q', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_MINIONS, 25, 1, 2, "bear cub");
addrace(R_BEARGRIZZLY, "grizzly bear", 200, 'q', C_YELLOW, MT_FLESH, RC_ANIMAL);
lastrace->baseid = R_BEAR;
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 52, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 52, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 62, NA, ""); addflag(lastrace->flags, F_RARITY, H_FOREST, 62, NA, "");
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTASLEEPPCT, 80, NA, NA, NULL); // hibernating
addflag(lastrace->flags, F_HITDICE, 5, 5, NA, NULL); addflag(lastrace->flags, F_HITDICE, 5, 5, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
@ -9348,6 +9437,27 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:2d6;"); addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:2d6;");
addflag(lastrace->flags, F_CRITKNOCKDOWN, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CRITKNOCKDOWN, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_BLEEDABIL, OT_A_RAGE, NA, NA, NULL); addflag(lastrace->flags, F_BLEEDABIL, OT_A_RAGE, NA, NA, NULL);
addflag(lastrace->flags, F_MINIONS, 25, 1, 2, "bear cub");
addrace(R_BEARCUB, "bear cub", 60, 'q', C_BROWN, MT_FLESH, RC_ANIMAL);
lastrace->baseid = R_BEAR;
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 73, NA, "");
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 3, 3, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4");
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d3");
addflag(lastrace->flags, F_MAXATTACKS, 2, 2, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 4, NA, "roars^a roars");
addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL);
addflag(lastrace->flags, F_CRITKNOCKDOWN, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, "");
addrace(R_ANT, "giant ant", 20, 'a', C_BROWN, MT_FLESH, RC_ANIMAL); addrace(R_ANT, "giant ant", 20, 'a', C_BROWN, MT_FLESH, RC_ANIMAL);
lastrace->baseid = R_ANT; lastrace->baseid = R_ANT;
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -9451,6 +9561,7 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining");
addflag(lastrace->flags, F_FLEEONHPPCT, 60, NA, NA, "");
addrace(R_DOGBLINK, "blink dog", 35, 'd', C_BLUE, MT_FLESH, RC_ANIMAL); addrace(R_DOGBLINK, "blink dog", 35, 'd', C_BLUE, MT_FLESH, RC_ANIMAL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 2, 4, NA, ""); addflag(lastrace->flags, F_NUMAPPEAR, 2, 4, NA, "");
@ -9954,6 +10065,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 8, 8, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 8, 8, NULL);
addflag(lastrace->flags, F_LEVRACE, 5, R_WOLF, NA, NULL); addflag(lastrace->flags, F_LEVRACE, 5, R_WOLF, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining");
addflag(lastrace->flags, F_FLEEONHPPCT, 75, NA, NA, "");
addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL); addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
@ -9977,6 +10089,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 5, 5, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, 5, 5, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining");
addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, "");
// insects // insects
addrace(R_BUTTERFLY, "butterfly", 0.01, 'i', C_YELLOW, MT_FLESH, RC_ANIMAL); addrace(R_BUTTERFLY, "butterfly", 0.01, 'i', C_YELLOW, MT_FLESH, RC_ANIMAL);
@ -10652,13 +10765,15 @@ int isplayer(lifeform_t *lf) {
// returns poison flag with longest remaining lifetime // returns poison flag with longest remaining lifetime
flag_t *ispoisoned(lifeform_t *lf) { flag_t *ispoisoned(lifeform_t *lf) {
flag_t *f,*max = NULL; flag_t *f,*max = NULL;
for (f = lf->flags->first ;f ; f = f->next) { int i;
if (f->id == F_POISONED) {
if (f->lifetime == PERMENANT) { getflags(lf->flags, F_POISONED, F_NONE);
return f; for (i = 0; i < nretflags; i++) {
} else if ((max == NULL) || (f->lifetime > max->lifetime)) { f = retflag[i];
max = f; if (f->lifetime == PERMENANT) {
} return f;
} else if ((max == NULL) || (f->lifetime > max->lifetime)) {
max = f;
} }
} }
@ -11602,10 +11717,13 @@ void killrace(race_t *race) {
flag_t *levelabilityready(lifeform_t *lf) { flag_t *levelabilityready(lifeform_t *lf) {
flag_t *f; flag_t *f;
int i;
if (!lfhasflag(lf, F_HASNEWLEVEL)) return NULL; if (!lfhasflag(lf, F_HASNEWLEVEL)) return NULL;
for (f = lf->flags->first ; f ; f = f->next) { getflags(lf->flags, F_LEVABIL, F_LEVFLAG, F_LEVSPELL, F_LEVSPELLSCHOOL, F_LEVSKILL, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
// we'll set lifetime to -1 while actually assigning these. // we'll set lifetime to -1 while actually assigning these.
if (f->lifetime == FROMJOB) { if (f->lifetime == FROMJOB) {
switch (f->id) { switch (f->id) {
@ -11777,35 +11895,38 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
// check for psychic armour etc // check for psychic armour etc
if (amt > 0) { if (amt > 0) {
if (isphysicaldam(damtype)) { if (isphysicaldam(damtype)) {
for (f = lf->flags->first ; f ; f = f->next) { int i;
if (f->id == F_MAGICARMOUR) {
int damtaken;
damtaken = amt;
if (damtaken > f->val[0]) {
damtaken = f->val[0];
}
f->val[0] -= damtaken;
if (f->val[0] <= 0) {
// from a spell?
if (f->lifetime == FROMSPELL) {
flag_t *spellflag;
spellflag = hasactivespell(lf, f->obfrom);
if (spellflag) {
killflag(spellflag);
}
}
killflag(f);
} else {
if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s%s %s pulses!", lfname, getpossessive(lfname), f->text);
}
}
// reduce damage getflags(lf->flags, F_MAGICARMOUR, F_NONE);
amt -= damtaken; for (i = 0; i < nretflags; i++) {
int damtaken;
f = retflag[i];
damtaken = amt;
if (damtaken > f->val[0]) {
damtaken = f->val[0];
} }
f->val[0] -= damtaken;
if (f->val[0] <= 0) {
// from a spell?
if (f->lifetime == FROMSPELL) {
flag_t *spellflag;
spellflag = hasactivespell(lf, f->obfrom);
if (spellflag) {
killflag(spellflag);
}
}
killflag(f);
} else {
if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s%s %s pulses!", lfname, getpossessive(lfname), f->text);
}
}
// reduce damage
amt -= damtaken;
} }
} }
} }
@ -12709,7 +12830,7 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int want
void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char *fromwhat) { void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char *fromwhat) {
flag_t *f; flag_t *f;
int found = B_FALSE; int found = B_FALSE,i;
enum POISONSEVERITY psev; enum POISONSEVERITY psev;
// are you immune to disease? // are you immune to disease?
@ -12724,7 +12845,11 @@ void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char
return; return;
} }
for (f = lf->flags->first ; f ; f = f->next) {
getflags(lf->flags, F_POISONED, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if ( (f->id == F_POISONED) && (f->val[0] == ptype) && if ( (f->id == F_POISONED) && (f->val[0] == ptype) &&
(f->lifetime > 0) ) { (f->lifetime > 0) ) {
// extend duration // extend duration
@ -13000,7 +13125,10 @@ int recruit(lifeform_t *lf) {
void refreshlevelabilities(lifeform_t *lf) { void refreshlevelabilities(lifeform_t *lf) {
flag_t *f; flag_t *f;
for (f = lf->flags->first ; f ; f = f->next) { int i;
getflags(lf->flags, F_LEVABIL, F_LEVFLAG, F_LEVSPELL, F_LEVSPELLSCHOOL, F_LEVSKILL, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
// we'll set timeleft to -1 while actually assigning these. // we'll set timeleft to -1 while actually assigning these.
switch (f->id) { switch (f->id) {
case F_LEVFLAG: case F_LEVFLAG:
@ -13563,8 +13691,10 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
killflagsofid(lf->flags, F_RARITY); killflagsofid(lf->flags, F_RARITY);
// certain other flags are rnadom // certain other flags are rnadom
for (f = lf->flags->first ; f ; f = nextf) {
nextf = f->next; getflags(lf->flags, F_RNDHOSTILE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_RNDHOSTILE) { if (f->id == F_RNDHOSTILE) {
if (pctchance(f->val[0])) { if (pctchance(f->val[0])) {
addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -13742,10 +13872,10 @@ void initskills(void) {
addskill(SK_LOCKPICKING, "Lockpicking", "Enhances your ability to pick locks.", 50); addskill(SK_LOCKPICKING, "Lockpicking", "Enhances your ability to pick locks.", 50);
addskill(SK_METALWORK, "Metalwork", "Lets you repair metal objects.", 100); addskill(SK_METALWORK, "Metalwork", "Lets you repair metal objects.", 100);
addskilldesc(SK_METALWORK, PR_NOVICE, "^gYou can repair metal items up to 33% condition.", B_FALSE); addskilldesc(SK_METALWORK, PR_NOVICE, "^gYou can repair metal items up to 33% condition.", B_FALSE);
addskilldesc(SK_METALWORK, PR_BEGINNER, "^gYou can repair metal items up to 50% condition", B_FALSE); addskilldesc(SK_METALWORK, PR_BEGINNER, "^gYou can repair metal items up to 50% condition.", B_FALSE);
addskilldesc(SK_METALWORK, PR_ADEPT, "^gYou can repair metal items up to 60% condition", B_FALSE); addskilldesc(SK_METALWORK, PR_ADEPT, "^gYou can repair metal items up to 60% condition.", B_FALSE);
addskilldesc(SK_METALWORK, PR_SKILLED, "^gYou can repair metal items up to 70% condition", B_FALSE); addskilldesc(SK_METALWORK, PR_SKILLED, "^gYou can repair metal items up to 70% condition.", B_FALSE);
addskilldesc(SK_METALWORK, PR_EXPERT, "^gYou can repair metal items up to 85% condition", B_FALSE); addskilldesc(SK_METALWORK, PR_EXPERT, "^gYou can repair metal items up to 85% condition.", B_FALSE);
addskilldesc(SK_METALWORK, PR_MASTER, "^gYou can fully repair metal items.", B_FALSE); addskilldesc(SK_METALWORK, PR_MASTER, "^gYou can fully repair metal items.", B_FALSE);
addskill(SK_RANGED, "Ranged Weapons", "Your ability to aim a ranged weapon like a bow or gun.", 50); addskill(SK_RANGED, "Ranged Weapons", "Your ability to aim a ranged weapon like a bow or gun.", 50);
addskilldesc(SK_RANGED, PR_NOVICE, "^gYou suffer a -20% accuracy penalty when using ranged weapons.", B_FALSE); addskilldesc(SK_RANGED, PR_NOVICE, "^gYou suffer a -20% accuracy penalty when using ranged weapons.", B_FALSE);
@ -13859,6 +13989,7 @@ void initskills(void) {
addskill(SK_SHORTBLADES, "Short Blades", "Helps you use daggers, short swords, etc.", 50); addskill(SK_SHORTBLADES, "Short Blades", "Helps you use daggers, short swords, etc.", 50);
addskill(SK_STAVES, "Staves", "Helps you use quarterstaffs, staffs, etc.", 50); addskill(SK_STAVES, "Staves", "Helps you use quarterstaffs, staffs, etc.", 50);
addskill(SK_UNARMED, "Unarmed Combat", "Helps you fight using your bare hands.", 50); addskill(SK_UNARMED, "Unarmed Combat", "Helps you fight using your bare hands.", 50);
addskilldesc(SK_UNARMED, PR_ADEPT, "^gYour unarmed attacks can now smash wooden objects.", B_TRUE);
addskilldesc(SK_UNARMED, PR_SKILLED, "^gYou can now make melee attacks with your off-hand.", B_TRUE); addskilldesc(SK_UNARMED, PR_SKILLED, "^gYou can now make melee attacks with your off-hand.", B_TRUE);
// spell schools // spell schools
addskill(SK_SS_ALLOMANCY, "Allomancy", "Boosts casting of spells from this school.", 50); addskill(SK_SS_ALLOMANCY, "Allomancy", "Boosts casting of spells from this school.", 50);
@ -14636,7 +14767,7 @@ void stopsprinting(lifeform_t *lf) {
} }
// very much like addmonster(), but announce that it appears // wrapper for addmonster(), but announce that it appears
// and make it worth zero xp. // and make it worth zero xp.
// //
// for unique monsters, they move from their current position. // for unique monsters, they move from their current position.
@ -15064,6 +15195,15 @@ void turneffectslf(lifeform_t *lf) {
gainmp(lf, f->val[0]); gainmp(lf, f->val[0]);
} }
} }
// druid gains mp from plants
if (hasjob(lf, J_DRUID)) {
int chance = 0;
// 5% per plant in sight of gaining mp
chance = countplantsinsight(lf) * 5;
if (pctchance(chance)) {
gainmp(lf, 1);
}
}
if (hasactivespell(lf, OT_S_SUMMONWEAPON)) { if (hasactivespell(lf, OT_S_SUMMONWEAPON)) {
@ -16576,7 +16716,7 @@ int rest(lifeform_t *lf, int onpurpose) {
} }
int wear(lifeform_t *lf, object_t *o) { int wear(lifeform_t *lf, object_t *o) {
int rv = B_FALSE; int rv = B_FALSE,i;
char buf[BUFLEN],obname[BUFLEN]; char buf[BUFLEN],obname[BUFLEN];
flag_t *f; flag_t *f;
enum BODYPART possbp[MAXBODYPARTS]; enum BODYPART possbp[MAXBODYPARTS];
@ -16614,7 +16754,10 @@ int wear(lifeform_t *lf, object_t *o) {
nparts = 0; nparts = 0;
for (f = o->flags->first ; f ; f = f->next) {
getflags(o->flags, F_GOESON, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_GOESON) { if (f->id == F_GOESON) {
possbp[nparts] = f->val[0]; possbp[nparts] = f->val[0];
nparts++; nparts++;
@ -16666,20 +16809,24 @@ int wear(lifeform_t *lf, object_t *o) {
if (isplayer(lf)) { if (isplayer(lf)) {
int ch; int ch;
char buf2[BUFLEN]; char buf2[BUFLEN];
// take offending item off first - this takes extra time. if (inway->blessknown && iscursed(inway)) {
sprintf(buf2, "Remove your %s",noprefix(buf)); msg("You cannot remove your %s.", noprefix(buf));
ch = askchar(buf2, "yn","y", B_TRUE); } else {
if (ch == 'y') { // take offending item off first - this takes extra time.
if (isarmour(inway)) { sprintf(buf2, "Remove your %s",noprefix(buf));
if (!takeoff(player, inway)) { ch = askchar(buf2, "yn","y", B_TRUE);
// took it off! if (ch == 'y') {
errresolved = B_TRUE; if (isarmour(inway)) {
} if (!takeoff(player, inway)) {
} else { // weapon // took it off!
if (!unweild(player, inway)) { errresolved = B_TRUE;
// took it off! }
errresolved = B_TRUE; } else { // weapon
} if (!unweild(player, inway)) {
// took it off!
errresolved = B_TRUE;
}
}
} }
} }
} }
@ -16919,10 +17066,15 @@ int weild(lifeform_t *lf, object_t *o) {
char buf2[BUFLEN]; char buf2[BUFLEN];
char ch; char ch;
if (isplayer(lf)) { if (isplayer(lf)) {
getobname(oo, inwayname, oo->amt); if (oo->blessknown && iscursed(oo)) {
// prompt before taking it off. msg("You cannot remove your %s.", noprefix(inwayname));
sprintf(buf2, "Remove your %s",noprefix(inwayname)); ch = 'n';
ch = askchar(buf2, "yn","y", B_TRUE); } else {
getobname(oo, inwayname, oo->amt);
// prompt before taking it off.
sprintf(buf2, "Remove your %s",noprefix(inwayname));
ch = askchar(buf2, "yn","y", B_TRUE);
}
} else { } else {
ch = 'y'; ch = 'y';
} }
@ -16978,10 +17130,15 @@ int weild(lifeform_t *lf, object_t *o) {
char inwayname[BUFLEN]; char inwayname[BUFLEN];
char ch; char ch;
if (isplayer(lf)) { if (isplayer(lf)) {
// prompt before taking it off. if (oo->blessknown && iscursed(oo)) {
getobname(oo, inwayname, oo->amt); msg("You cannot remove your %s.", noprefix(inwayname));
sprintf(buf2, "Remove your %s",noprefix(inwayname)); ch = 'n';
ch = askchar(buf2, "yn","y", B_TRUE); } else {
// prompt before taking it off.
getobname(oo, inwayname, oo->amt);
sprintf(buf2, "Remove your %s",noprefix(inwayname));
ch = askchar(buf2, "yn","y", B_TRUE);
}
} else { } else {
ch = 'y'; ch = 'y';
} }

1
lf.h
View File

@ -49,6 +49,7 @@ int countinnateattacks(lifeform_t *lf);
int countmoney(lifeform_t *lf); int countmoney(lifeform_t *lf);
int countnearbyallies(lifeform_t *lf); int countnearbyallies(lifeform_t *lf);
int countnearbyhurtallies(lifeform_t *lf); int countnearbyhurtallies(lifeform_t *lf);
int countplantsinsight(lifeform_t *lf);
void debug(lifeform_t *lf); void debug(lifeform_t *lf);
int demandbribe(lifeform_t *lf); int demandbribe(lifeform_t *lf);
void die(lifeform_t *lf); void die(lifeform_t *lf);

22
map.c
View File

@ -212,7 +212,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
} }
if (autogen) { if (autogen) {
// sometimes start off asleep in new maps // sometimes start off hiding/asleep in new maps
f = lfhasflag(lf, F_STARTHIDDENPCT); f = lfhasflag(lf, F_STARTHIDDENPCT);
if (f) { if (f) {
if (rnd(1,100) <= f->val[0]) { if (rnd(1,100) <= f->val[0]) {
@ -222,10 +222,14 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
addflag(lf->flags, F_HIDING, 0, NA, NA, NULL); addflag(lf->flags, F_HIDING, 0, NA, NA, NULL);
} }
} }
if (!lfhasflag(lf, F_HIDING) && !lfhasflag(lf, F_DEAF) && cansleep(lf) && if (!lfhasflag(lf, F_HIDING) && !lfhasflag(lf, F_DEAF) && cansleep(lf) ) {
!lfhasflag(lf, F_DONTSTARTASLEEP)) { int asleepchance = 50;
f = lfhasflag(lf, F_STARTASLEEPPCT);
if (f) {
asleepchance = f->val[0];
}
// TODO: base this on the time, and whether monster is nocturnal // TODO: base this on the time, and whether monster is nocturnal
if (rnd(1,2) == 1) { if (pctchance(asleepchance)) {
addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
} }
} }
@ -3632,11 +3636,13 @@ object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tfl
if ((oid == NA) || (o->type->id == oid)) { if ((oid == NA) || (o->type->id == oid)) {
f = hasflag(o->flags, F_TRAIL); f = hasflag(o->flags, F_TRAIL);
// raceid and lfid must match // raceid and lfid must match
if (f && (f->val[0] == lf->race->id) && (atoi(f->text) == lf->id)) { if (f) {
if (tflag) { if ((f->val[0] == lf->race->id) && (atoi(f->text) == lf->id)) {
*tflag = f; if (tflag) {
*tflag = f;
}
return o;
} }
return o;
} }
} }
} }

8
move.c
View File

@ -1183,10 +1183,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if (cansee(l, lf) && areenemies(lf, l)) { if (cansee(l, lf) && areenemies(lf, l)) {
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_TRAINING)) { if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_TRAINING)) {
// TODO: also check for isresting(l), if we have allies standing watch // TODO: also check for isresting(l), if we have allies standing watch
char lfname2[BUFLEN]; getlfnamea(lf, lfname);
getlfname(lf, lfname); msg("%s comes into view.", lfname);
sprintf(lfname2, "%s",noprefix(lfname));
msg("%s %s comes into view.",isvowel(lfname2[0]) ? "An" : "A", lfname2);
} }
dointerrupt = B_TRUE; dointerrupt = B_TRUE;
} }
@ -2052,7 +2050,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
cell = getcellindir(lf->cell, dir); cell = getcellindir(lf->cell, dir);
if (isplayer(lf)) { if (isplayer(lf) && !lfhasflag(lf, F_SNEAK)) {
if (cell && celldangerous(lf, cell, B_TRUE, &errcode)) { if (cell && celldangerous(lf, cell, B_TRUE, &errcode)) {
char ques[BUFLEN]; char ques[BUFLEN];
char ch; char ch;

View File

@ -216,7 +216,9 @@ int main(int argc, char **argv) {
user = getenv("USER"); user = getenv("USER");
if (user) { if (user) {
addflag(player->flags, F_NAME, NA, NA, NA, getenv("USER")); char pname[MAXPNAMELEN];
snprintf(pname, MAXPNAMELEN, "%s", getenv("USER"));
addflag(player->flags, F_NAME, NA, NA, NA, pname);
} else { } else {
addflag(player->flags, F_NAME, NA, NA, NA, "Anonymous"); addflag(player->flags, F_NAME, NA, NA, NA, "Anonymous");
} }

View File

@ -1876,8 +1876,8 @@ void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) {
// adjust damage // adjust damage
if (o->blessed == B_BLESSED) { if (o->blessed == B_BLESSED) {
// chance of no hp loss // high chance of no hp loss
if (onein(2)) { if (pctchance(90)) {
lifeform_t *owner; lifeform_t *owner;
owner = o->pile->owner; owner = o->pile->owner;
if (owner && isplayer(owner)) { if (owner && isplayer(owner)) {
@ -1893,7 +1893,7 @@ void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) {
return; return;
} }
} else if (o->blessed == B_CURSED) { } else if (o->blessed == B_CURSED) {
// chance of double damage! // 50% chance of double damage!
if (onein(2)) { if (onein(2)) {
lifeform_t *owner; lifeform_t *owner;
(*dam) *= 2; (*dam) *= 2;
@ -2195,6 +2195,15 @@ int canseeob(lifeform_t *lf, object_t *o) {
} }
} else { } else {
// ie. SCENT // ie. SCENT
// special case: if lf is the player's pet, they can always "smell" the player
if (ispetof(lf, player) && strlen(f->text)) {
// scent belongs to the player?
if (atoi(f->text) == player->id) {
return B_TRUE;
}
}
// can't smell your own race... // can't smell your own race...
if ((f->val[0] != lf->race->id) && lfhasflag(lf, F_ENHANCESMELL)) { if ((f->val[0] != lf->race->id) && lfhasflag(lf, F_ENHANCESMELL)) {
return B_TRUE; return B_TRUE;
@ -2489,7 +2498,7 @@ int doobtraps(object_t *o, lifeform_t *lf) {
// announce... // announce...
if (isplayer(lf)) { if (isplayer(lf)) {
msg("^wA trap goes off!"); msg("^wA trap goes off!"); more();
} }
trapid = f->val[0]; trapid = f->val[0];
@ -6684,7 +6693,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
addot(OT_S_JOLT, "jolt", "Jolts an adjacent enemy with a short pulse of electricity.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_JOLT, "jolt", "Jolts an adjacent enemy with a short pulse of electricity, dealing 1-^bpower^n damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 4, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 4, NA, NA, NULL);
@ -6713,7 +6722,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
addot(OT_S_WINDSHIELD, "cyclonic shield", "Surrounds the caster with a whirling cyclone to repel missiles.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_WINDSHIELD, "cyclonic shield", "Surrounds the caster with a whirling cyclone to repel missiles. Spell power determines the speed of missile which can be repelled.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
@ -6721,7 +6730,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
// l4 // l4
addot(OT_S_CLOUDKILL, "cloudkill", "Creates a cloud of poisonous gas.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_CLOUDKILL, "cloudkill", "Creates a cloud of poisonous gas. The cloud's size is 1-3 cells, depending on the spell power.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
@ -8506,13 +8515,13 @@ void initobjects(void) {
addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL);
addflag(lastot->flags, F_OBHP, 60, 60, NA, NULL); addflag(lastot->flags, F_OBHP, 60, 60, NA, NULL);
addot(OT_FLAKJACKET, "flak jacket", "Heavy metal body armour, designed to stop a bullet.", MT_METAL, 30, OC_ARMOUR, SZ_MEDIUM); addot(OT_FLAKJACKET, "flak jacket", "Heavy metal body armour. Designed to stop a bullet, but only once.", MT_METAL, 30, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 10, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 10, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 10, 10, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 10, 10, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 10, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 10, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
addot(OT_OVERALLS, "pair of overalls", "Well-made, brightly coloured workman overalls.", MT_CLOTH, 1, OC_ARMOUR, SZ_MEDIUM); addot(OT_OVERALLS, "pair of overalls", "Well-made, brightly coloured workman overalls.", MT_CLOTH, 1, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
@ -8566,12 +8575,20 @@ void initobjects(void) {
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL); addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_DEX, 3, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_DEX, 3, NA, NULL);
addot(OT_COMBATPANTS, "pair of combat pants", "An armoured pair of camoflauged trousers.", MT_CLOTH, 2, OC_ARMOUR, SZ_MEDIUM); addot(OT_COMBATPANTS, "pair of combat pants", "An lightly-armoured pair of camoflauged trousers.", MT_CLOTH, 2, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 3, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 3, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL); addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_DEX, 3, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_DEX, 3, NA, NULL);
addot(OT_GREAVES, "set of greaves", "A set of heavy metal greaves.", MT_METAL, 4, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 25, 25, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 15, 15, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 9, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_DEX, 3, NA, NULL);
// armour - feet // armour - feet
addot(OT_SANDALS, "pair of sandals", "Comfortable pair of open leather sandals.", MT_LEATHER, 1, OC_ARMOUR, SZ_SMALL); addot(OT_SANDALS, "pair of sandals", "Comfortable pair of open leather sandals.", MT_LEATHER, 1, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
@ -8608,6 +8625,13 @@ void initobjects(void) {
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_DEX, 7, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_DEX, 7, NA, NULL);
addot(OT_BOOTSMETAL, "pair of metal boots", "A strong pair of metal boots.", MT_METAL, 5, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_RARE, NULL);
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_DEX, 7, NA, NULL);
// armour - gloves // armour - gloves
addot(OT_GLOVESCLOTH, "pair of cloth gloves", "A pair of soft cloth gloves.", MT_CLOTH, 0.15, OC_ARMOUR, SZ_SMALL); addot(OT_GLOVESCLOTH, "pair of cloth gloves", "A pair of soft cloth gloves.", MT_CLOTH, 0.15, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
@ -8682,7 +8706,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SCARY, 4, NA, NA, NULL); addflag(lastot->flags, F_SCARY, 4, NA, NA, NULL);
// armour - eyes // armour - eyes
addot(OT_SUNGLASSES, "pair of sunglasses", "Tinted eyewear to protect against sunlight.", MT_PLASTIC, 0.01, OC_ARMOUR, SZ_SMALL); addot(OT_SUNGLASSES, "pair of sunglasses", "Tinted eyewear to protect against sunlight.", MT_GLASS, 0.01, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
@ -12047,7 +12071,7 @@ void quaff(lifeform_t *lf, object_t *o) {
int seen; int seen;
int killobwhendone = B_TRUE; int killobwhendone = B_TRUE;
flag_t *drinkflag; flag_t *drinkflag;
enum OBTYPE fountainobid = OT_NONE; enum OBTYPE realobid = OT_NONE;
getobname(o, obname, 1); getobname(o, obname, 1);
@ -12059,7 +12083,16 @@ void quaff(lifeform_t *lf, object_t *o) {
taketime(lf, getactspeed(lf)); taketime(lf, getactspeed(lf));
maketried(o->type->id); if (o->type->id == OT_FOUNTAIN) {
flag_t *f;
// ie if not already identified...
f = hasflag(o->flags, F_LINKOB);
realobid = f->val[0];
} else {
realobid = o->type->id;
}
maketried(realobid);
if (touch(lf, o)) { if (touch(lf, o)) {
return; return;
@ -12086,21 +12119,15 @@ void quaff(lifeform_t *lf, object_t *o) {
if (playercansee) { if (playercansee) {
if (o->type->id == OT_FOUNTAIN) { if (o->type->id == OT_FOUNTAIN) {
flag_t *f; flag_t *f;
// ie if not already identified...
f = hasflag(o->flags, F_LINKOB); f = hasflag(o->flags, F_LINKOB);
if (f->val[2] == B_TRUE) { if (f->val[2] == B_TRUE) {
// already identified // fountain which is already identified
willid = B_FALSE; willid = B_FALSE;
fountainobid = OT_NONE; }
} else { // otherwise identify based on potion effects...
// then identify based on potion effects... }
fountainobid = f->val[0];
}
} else {
fountainobid = o->type->id;
}
switch (fountainobid) { switch (realobid) {
case OT_NONE: case OT_NONE:
willid = B_FALSE; willid = B_FALSE;
break; break;
@ -12119,9 +12146,9 @@ void quaff(lifeform_t *lf, object_t *o) {
} }
if (willid) { if (willid) {
makeknown(realobid);
if (o->type->id == OT_FOUNTAIN) { if (o->type->id == OT_FOUNTAIN) {
// id the linked potion
makeknown(fountainobid);
// refresh fountain name // refresh fountain name
getobname(o, obname, 1); getobname(o, obname, 1);
if (isplayer(lf)) { if (isplayer(lf)) {
@ -12131,8 +12158,6 @@ void quaff(lifeform_t *lf, object_t *o) {
drawmsg(); drawmsg();
} }
} else if (!isknown(o)) { } else if (!isknown(o)) {
// id the potion
makeknown(o->type->id);
real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE, B_FALSE); // don't adjust for blindness real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE, B_FALSE); // don't adjust for blindness
if (isplayer(lf)) { if (isplayer(lf)) {
// tell the player // tell the player
@ -13615,9 +13640,13 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno
int lfdam = 0; int lfdam = 0;
owner = o->pile->owner; owner = o->pile->owner;
f = hasflag(o->flags, F_EQUIPPED); f = hasflag(o->flags, F_EQUIPPED);
if (f && (f->val[0] != BP_WEAPON) && (f->val[0] != BP_SECWEAPON)) { if (f) {
// ob equipped? 1.5x damage. // no damage from equipped _weapons_
lfdam = pctof(150,howmuch); if ((f->val[0] != BP_WEAPON) || (f->val[0] != BP_SECWEAPON)) {
} else {
// equipped clothes/armour? 1.5x damage.
lfdam = pctof(150,howmuch);
}
} else { } else {
// otherwise normal. // otherwise normal.
lfdam = howmuch; lfdam = howmuch;

121
save.c
View File

@ -4,6 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sqlite3.h>
#include "defs.h" #include "defs.h"
#include "flag.h" #include "flag.h"
#include "io.h" #include "io.h"
@ -1005,3 +1006,123 @@ int saveregions(void) {
return B_FALSE; return B_FALSE;
} }
int showhiscores(lifeform_t *lf, int min, int max) {
sqlite3 *db;
int rc;
char filename[BUFLEN],*cmd;
char *errmsg = NULL;
char hilitescoretext[BUFLEN];
long hilitescore = -1;
if (lf && !lfhasflag(lf, F_NOSCORE)) {
hilitescore = calcscore(lf);
} else {
hilitescore = -1;
}
// open database
sprintf(filename, "%s/hiscores.db", DATADIR);
rc = sqlite3_open(filename, &db);
if (rc) {
msg("error opening hiscore file '%s'.\n",filename);
dblog("error opening hiscore file '%s'.\n",filename);
return B_TRUE;
}
// show top ten
//sprintf(cmd, "select * from hiscores order by score desc limit 10;");
asprintf(&cmd, "select (select count(*) from hiscores b where b.score > a.score) + 1 as rank, score,name,job,killedby from hiscores a where (rank >= %d) and (rank <= %d) order by score desc limit 10;", min, max);
sprintf(hilitescoretext, "%ld",hilitescore);
rc = sqlite3_exec(db, cmd, showhiscoreline, hilitescoretext, &errmsg);
free(cmd);
if (rc != SQLITE_OK) {
msg("error writing hiscores: '%s'", errmsg);
dblog("error writing hiscores: '%s'", errmsg);
sqlite3_free(errmsg);
}
sqlite3_close(db);
return B_FALSE;
}
// returns player's rank in 'rank'
int writehiscore(lifeform_t *lf, int *rank) {
sqlite3 *db;
int rc;
char filename[BUFLEN],*cmd;
char pname[BUFLEN];
char jobname[BUFLEN];
char killedby[BUFLEN];
char *errmsg = NULL;
sqlite3_stmt *smt;
job_t *j;
long minscore;
long score;
score = calcscore(lf);
// open database
sprintf(filename, "%s/hiscores.db", DATADIR);
rc = sqlite3_open(filename, &db);
if (rc) {
msg("error opening hiscore file '%s'.\n",filename);
dblog("error opening hiscore file '%s'.\n",filename);
return B_TRUE;
}
getplayername(pname);
j = getjob(player);
sprintf(jobname, "Lv%d %s", player->level, j->name);
makekillertext(killedby, lf->lastdam, B_FALSE);
if (!lfhasflag(lf, F_NOSCORE)) {
asprintf(&cmd, "insert into 'hiscores' (score,name,job,killedby) VALUES (%ld, '%s', '%s', '%s')", score, pname, jobname, killedby);
rc = sqlite3_exec(db, cmd, NULL, NULL, &errmsg);
free(cmd);
if (rc != SQLITE_OK) {
msg("error writing hiscores: '%s'", errmsg);
dblog("error writing hiscores: '%s'", errmsg);
sqlite3_free(errmsg);
}
}
if (rank) {
if (lfhasflag(lf, F_NOSCORE)) {
*rank = -1;
} else {
// find out the player's rank
asprintf(&cmd, "select (select count(*) from hiscores b where b.score > a.score) + 1 as rank from hiscores a where score = %ld;",score);
rc = sqlite3_prepare_v2(db, cmd, -1, &smt, 0);
free(cmd);
rc = sqlite3_step(smt);
while (rc == SQLITE_ROW) {
const char *p;
p = (const char *)sqlite3_column_text(smt, 0);
*rank = atoi(p);
rc = sqlite3_step(smt);
}
}
}
// now delete all hiscore entries after 100
// find score number 100...
asprintf(&cmd, "select score from hiscores order by score desc limit 100;");
rc = sqlite3_prepare_v2(db, cmd, -1, &smt, 0);
free(cmd);
rc = sqlite3_step(smt);
while (rc == SQLITE_ROW) {
const char *p;
p = (const char *)sqlite3_column_text(smt, 0);
minscore = atol(p);
rc = sqlite3_step(smt);
}
// we now have a minimum score - delete everything lower than it.
asprintf(&cmd, "delete from hiscores where score < %ld;", minscore);
rc = sqlite3_exec(db, cmd, NULL, NULL, &errmsg);
free(cmd);
sqlite3_close(db);
return 0;
}

2
save.h
View File

@ -15,3 +15,5 @@ int savegame(void);
int savemap(map_t *m); int savemap(map_t *m);
int saveob(FILE *f, object_t *o); int saveob(FILE *f, object_t *o);
int saveregions(void); int saveregions(void);
int showhiscores(lifeform_t *lf, int min, int max);
int writehiscore(lifeform_t *lf, int *rank);

41
spell.c
View File

@ -786,6 +786,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
howlong = 10; howlong = 10;
addtempflag(user->flags, F_RAGE, B_TRUE, NA, NA, NULL, howlong); addtempflag(user->flags, F_RAGE, B_TRUE, NA, NA, NULL, howlong);
needredraw = B_TRUE;
statdirty = B_TRUE;
} else if (abilid == OT_A_REPAIR) { } else if (abilid == OT_A_REPAIR) {
enum SKILLLEVEL slev; enum SKILLLEVEL slev;
object_t *o; object_t *o;
@ -1601,10 +1603,18 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
taketime(user, getactspeed(user)*2); taketime(user, getactspeed(user)*2);
// all in range must pass a morale check or flee // all in range must pass a morale check or flee
for (target = user->cell->map->lf ; target ; target = target->next) { for (target = user->cell->map->lf ; target ; target = target->next) {
if ((target != user) && cansee(target, user) && areenemies(target, user)) { if ((target != user) && cansee(target, user) && areenemies(target, user)) {
if (canhear(target, user->cell, 4)) { int ok = B_FALSE;
switch (target->race->raceclass->id) {
case RC_ANIMAL:
case RC_HUMANOID:
ok = B_TRUE;
break;
default:
break;
}
if (ok && canhear(target, user->cell, 4)) {
scare(target, user, rnd(5,10), 0); scare(target, user, rnd(5,10), 0);
} }
} }
@ -3794,6 +3804,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
amt = 1; amt = 1;
} }
modbonus(o, amt); modbonus(o, amt);
if (iscursed(o)) {
setblessed(o, B_UNCURSED);
}
} }
} else { } else {
// monsters can't id things! // monsters can't id things!
@ -7184,14 +7197,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND); c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND);
} }
if (c) { if (c) {
addob(c->obpile, "web");
if (c->lf && (c->lf->race->baseid != R_SPIDER)) { if (c->lf && (c->lf->race->baseid != R_SPIDER)) {
if (isplayer(c->lf)) { if (skillcheck(c->lf, SC_DODGE, 20+power, 0)) {
msg("You are stuck in a web!"); if (isplayer(c->lf)) {
} else if (cansee(player, c->lf)) { msg("You dodge a web.");
char lfname[BUFLEN]; } else if (cansee(player, c->lf)) {
getlfname(c->lf, lfname); char lfname[BUFLEN];
msg("%s is stuck in a web!", lfname); getlfname(c->lf, lfname);
msg("%s dodges a web!", lfname);
}
} else {
addob(c->obpile, "web");
if (isplayer(c->lf)) {
msg("You are stuck in a web!");
} else if (cansee(player, c->lf)) {
char lfname[BUFLEN];
getlfname(c->lf, lfname);
msg("%s is stuck in a web!", lfname);
}
} }
} }
} }

30
text.c
View File

@ -62,6 +62,8 @@ enum COLOUR chartocol(char ch) {
return C_GREEN; return C_GREEN;
case 'G': // v.good case 'G': // v.good
return C_CYAN; return C_CYAN;
case 'h': // 'hilite'
return C_WHITE;
case 'n': // normal case 'n': // normal
default: default:
break; break;
@ -389,6 +391,30 @@ int isvowel (char c) {
return B_FALSE; return B_FALSE;
} }
char *makekillertext(char *retbuf, char *lastdam, int wantextra) {
char *p, *dummy;
p = strtok_r(lastdam,"^", &dummy);
if (p) {
if (!strcmp(p, "you")) {
strcpy(retbuf, "Committed suicide.");
} else {
sprintf(retbuf, "Killed by %s.",p);
}
if (wantextra) {
p = strtok_r(NULL, "^", &dummy);
while (p) {
strcat(retbuf, "\n(");
strcat(retbuf, p);
strcat(retbuf, ")");
p = strtok_r(NULL, "^", &dummy);
}
}
} else {
strcpy(retbuf, "Killed by something unknown.");
}
return retbuf;
}
// allocates and returns new string // allocates and returns new string
char *makeplural(char *text) { char *makeplural(char *text) {
char lastlet; char lastlet;
@ -552,8 +578,10 @@ char *readuntil(char *retbuf, char *src, char delim) {
*bp = *p; *bp = *p;
bp++; bp++;
} }
p++; // go past delimiter
*bp = '\0'; // nul-terminate buffer *bp = '\0'; // nul-terminate buffer
if (*p == delim) {
p++; // go past delimiter
}
return p; return p;
} }

1
text.h
View File

@ -19,6 +19,7 @@ char *getwaterdepthname(enum DEPTH d);
char *getweighttext(float weight, char *buf); char *getweighttext(float weight, char *buf);
char *is(lifeform_t *lf); char *is(lifeform_t *lf);
int isvowel(char c); int isvowel(char c);
char *makekillertext(char *retbuf, char *lastdam, int wantextra);
char *makeplural(char *text); char *makeplural(char *text);
char *makeuppercase(char *text); char *makeuppercase(char *text);
int needses(char *text); int needses(char *text);