* [+] goblins aren't opening doors...

- [+] xat shouldn't be able to open doors!
- [+] semicontrolled createmonster
* [+] implement semicontrolled teleport (can pick the general direction)
* [+] change how semicontrolled teleport works
- [+] make identify/remove curse more common
- [+] make minorheal/heal more common
* [+] NOTDONE. maybe reduce the amount of damage which AR blocks a bit?
      i got to 30ar very fast! (ie -45% dam)
* [+] make a special case for F_FLAKJACKET
- [+] BUG: glowbug is causing PERMENANT light, not temp!
- [+] diety ability - levelup
- [+] new damtype:  necrotic
- [+] drain life spell
- [+] make water evaporate
- [+] BUG in validating target cell. was asking a monster for input 
* [+] boots get wet if you walk in water
- [+] why does oil lamp and pil lantern make the same range of light?
- [+] fixed another vending maching crash
- [+] crash due to sprinting?
- [+] 2 blessed flask of battery acids
- [+] "This is a wand!" - don't use code for hiding names in the dark!
* [+] animals shouldn't eat their own race!
- [+] gem of seeing costs nothing!
- [+] frozen weapons do +1d4 cold damage
- [+] allomancy/psionics don't need spellcasting
- [+] poison isn't being announced on mosnters?
- [+] "you are full" only interrupt if we went < normal (ie peckish
      starving etc)
- [+] only F_HUMANOID creatures can wear armour / use weapons
* [+] what does a masterwork bow do?
- [+] implement strength requirements on weapons
- [+] UNDEAD cannot be poisoned by eating corpses!
- [+] ai lfs shoudlnt' eat tainted food
- [+] change how gravboost works wrt movement
- [+] smart ai lfs shouldnt move when in pain
- [+] don't stop walking if the only things there are non-pickupable
- [+] make mosnters swap places with each other if they are the same
      baseid
* [+] scroll of permenance
- [+] make more monsters have gold
* [+] can learn novice level weapon skills by using one a lot
* [+] finish hawks
* [+] add colour
* [+] job attribs aren't working
- [+] pile of ash has weird glyph!
* [+] when you learn the first rank of some magic skills, you get a
      spell with it
- [+] add colours to statbar
- [+] can only "stop on xxx" if you have feet
- [+] monsters shouldn't attack other to get to wanted objects.
* [+] "xat throws a knife"
- [+] manaspike doing no damage to giant newt
- [+] assign colours to rings
This commit is contained in:
Rob Pearce 2011-03-31 23:54:44 +00:00
parent e9f752dd2f
commit 69d14c05fe
22 changed files with 3153 additions and 899 deletions

186
ai.c
View File

@ -21,11 +21,21 @@ int wantdb = B_TRUE;
void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) { void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
int db = B_FALSE; int db = B_FALSE;
flag_t *f;
if (lfhasflag(lf, F_DEBUG)) { if (lfhasflag(lf, F_DEBUG)) {
db = B_TRUE; db = B_TRUE;
} }
// already targetting this lf?
f = lfhasflagval(lf, F_TARGET, victim->id, NA, NA, NULL);
if (f) {
if ((f->lifetime > 0) && (f->lifetime < timelimit)) {
f->lifetime = timelimit;
}
return;
}
if (db) { if (db) {
char lfname[BUFLEN],vicname[BUFLEN]; char lfname[BUFLEN],vicname[BUFLEN];
getlfname(lf, lfname); getlfname(lf, lfname);
@ -47,7 +57,6 @@ void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
makenoise(lf, N_GETANGRY); makenoise(lf, N_GETANGRY);
} }
// change allegience ? // change allegience ?
if (!areenemies(lf, victim)) { if (!areenemies(lf, victim)) {
if (getallegiance(victim) == AL_FRIENDLY) { if (getallegiance(victim) == AL_FRIENDLY) {
@ -347,7 +356,7 @@ void aimove(lifeform_t *lf) {
curarm = getarmour(lf, bp); curarm = getarmour(lf, bp);
// do we have a better one? // do we have a better one?
for (o = lf->pack->first ; o ; o = o->next) { for (o = lf->pack->first ; o ; o = o->next) {
if (isbetterarmourthan(o, curarm)) { if (canwear(lf, o, BP_NONE) && isbetterarmourthan(o, curarm)) {
// wear this armour instead // wear this armour instead
if (!wear(lf, o)) return; if (!wear(lf, o)) return;
} }
@ -480,7 +489,7 @@ void aimove(lifeform_t *lf) {
// if not adjacent, check for guns, wands, throwing // if not adjacent, check for guns, wands, throwing
if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell, B_FALSE, NULL)) { if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell, B_FALSE, NULL)) {
// can we attack by firing something? // can we attack by firing a weapon?
gun = getfirearm(lf); gun = getfirearm(lf);
if (goingtomove && gun && getammo(lf)) { if (goingtomove && gun && getammo(lf)) {
if (db) { if (db) {
@ -500,8 +509,7 @@ void aimove(lifeform_t *lf) {
} }
// can we attack by throwing something? // can we attack by throwing something?
if (goingtomove) { if (goingtomove && hasbp(lf, BP_HANDS)) {
//
o = getbestthrowmissile(lf); o = getbestthrowmissile(lf);
if (o) { if (o) {
if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name); if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name);
@ -516,37 +524,39 @@ void aimove(lifeform_t *lf) {
} }
// do we have a wand we can zap? // do we have a wand we can zap?
if (lfhasflag(lf, F_FLEEFROM)) { if (lfhasflag(lf, F_HUMANOID) || hasbp(lf, BP_HANDS)) {
o = aigetwand(lf, F_AICASTTOFLEE); if (lfhasflag(lf, F_FLEEFROM)) {
} else { o = aigetwand(lf, F_AICASTTOFLEE);
o = aigetwand(lf, F_AICASTTOATTACK);
}
if (o) {
objecttype_t *st;
cell_t *zapcell = NULL;
st = getlinkspell(o);
if (st) {
enum FLAG purpose;
if (lfhasflag(lf, F_FLEEFROM)) {
purpose = F_AICASTTOFLEE;
} else {
purpose = F_AICASTTOATTACK;
}
aigetspelltarget(lf, st, target, NULL, &zapcell, NULL, purpose);
} else { } else {
// no linkspell - just zap it. o = aigetwand(lf, F_AICASTTOATTACK);
zapcell = NULL;
} }
if (o) {
objecttype_t *st;
cell_t *zapcell = NULL;
// zap it st = getlinkspell(o);
if (db) dblog(".oO { will zap %s instead of moving }", o->type->name); if (st) {
enum FLAG purpose;
if (lfhasflag(lf, F_FLEEFROM)) {
purpose = F_AICASTTOFLEE;
} else {
purpose = F_AICASTTOATTACK;
}
aigetspelltarget(lf, st, target, NULL, &zapcell, NULL, purpose);
} else {
// no linkspell - just zap it.
zapcell = NULL;
}
if (!operate(lf, o, zapcell)) { // zap it
// succesful if (db) dblog(".oO { will zap %s instead of moving }", o->type->name);
goingtomove = B_FALSE;
} else { if (!operate(lf, o, zapcell)) {
if (db) dblog(".oO { zap failed! }"); // succesful
goingtomove = B_FALSE;
} else {
if (db) dblog(".oO { zap failed! }");
}
} }
} }
} }
@ -558,7 +568,7 @@ void aimove(lifeform_t *lf) {
} }
if (goingtomove) { if (goingtomove) {
if (!movetowards(lf, target->cell)) { if (!movetowards(lf, target->cell, DT_ORTH)) {
// success // success
return; return;
} else { } else {
@ -599,7 +609,7 @@ void aimove(lifeform_t *lf) {
if (db) dblog(".oO { walking from %d,%d towards f_targetcell (%d,%d) ... }", lf->cell->x, lf->cell->y, x, y); if (db) dblog(".oO { walking from %d,%d towards f_targetcell (%d,%d) ... }", lf->cell->x, lf->cell->y, x, y);
c = getcellat(lf->cell->map, x, y); c = getcellat(lf->cell->map, x, y);
if (c) { if (c) {
if (movetowards(lf, c)) { if (movetowards(lf, c, DT_ORTH)) {
// couldn't move towards it for some reason. // couldn't move towards it for some reason.
// so stop trying. // so stop trying.
if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }"); if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }");
@ -659,7 +669,7 @@ void aimove(lifeform_t *lf) {
if (db) dblog(".oO { moving towards my new target }"); if (db) dblog(".oO { moving towards my new target }");
if (curwep) { if (curwep) {
if (!movetowards(lf, c)) return; if (!movetowards(lf, c, DT_ORTH)) return;
} else { } else {
if (db) dblog(".oO { won't move towards target - i have no weapon. }"); if (db) dblog(".oO { won't move towards target - i have no weapon. }");
} }
@ -684,7 +694,7 @@ void aimove(lifeform_t *lf) {
addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME); addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME);
// then move towards them... // then move towards them...
if (db) dblog(".oO { moving towards my new target }"); if (db) dblog(".oO { moving towards my new target }");
if (!movetowards(lf, c)) return; if (!movetowards(lf, c, DT_ORTH)) return;
} }
} }
} }
@ -908,6 +918,25 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if ((ot->id == OT_S_BLINDNESS) && isblind(victim)) { if ((ot->id == OT_S_BLINDNESS) && isblind(victim)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
if ((ot->id == OT_S_DRAINLIFE) && isimmuneto(victim->flags, DT_NECROTIC)) {
specificcheckok = B_FALSE;
}
if (ot->id == OT_A_SWOOP) {
flag_t *srflag;
int srange = 5;
srflag = lfhasflag(lf, F_SWOOPRANGE);
if (srflag) {
srange = srflag->val[0];
}
if (!haslof(lf, victim->cell, LOF_NEED,NULL)) {
specificcheckok = B_FALSE;
} else if (isimmobile(lf) || !lfhasflag(lf, F_FLYING)) {
specificcheckok = B_FALSE;
} else if (getcelldist(lf->cell, victim->cell) > srange) {
specificcheckok = B_FALSE;
}
}
if ((ot->id == OT_S_HASTE) && lfhasflag(lf, F_FASTACT)) { if ((ot->id == OT_S_HASTE) && lfhasflag(lf, F_FASTACT)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
@ -1046,28 +1075,33 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
} }
} }
// current cell has better weapon? // current cell has better weapon?
f = hasflag(lf->flags, F_WANTSBETTERWEP); if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) {
if (f ) { f = hasflag(lf->flags, F_WANTSBETTERWEP);
if (!covetsonly || (f->val[1] == B_COVETS)) { if (f) {
o = hasbetterweapon(lf, lf->cell->obpile); if (!covetsonly || (f->val[1] == B_COVETS)) {
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { o = hasbetterweapon(lf, lf->cell->obpile);
if (db) dblog(".oO { current cell has better weapon (%s) }",o->type->name); if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
// try to pick it up if (db) dblog(".oO { current cell has better weapon (%s) }",o->type->name);
if (!aipickup(lf, o)) return B_TRUE; // try to pick it up
if (db) dblog(".oO { pickup of better wep %s failed! }",o->type->name); if (!aipickup(lf, o)) return B_TRUE;
if (db) dblog(".oO { pickup of better wep %s failed! }",o->type->name);
}
} }
} }
} }
// current cell has better armour?
f = hasflag(lf->flags, F_WANTSBETTERARM); if (lfhasflag(lf, F_HUMANOID)) {
if (f ) { // current cell has better armour?
if (!covetsonly || (f->val[1] == B_COVETS)) { f = hasflag(lf->flags, F_WANTSBETTERARM);
o = hasbetterarmour(lf, lf->cell->obpile); if (f ) {
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { if (!covetsonly || (f->val[1] == B_COVETS)) {
if (db) dblog(".oO { current cell has better armour (%s) }",o->type->name); o = hasbetterarmour(lf, lf->cell->obpile);
// try to pick it up if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
if (!aipickup(lf, o)) return B_TRUE; if (db) dblog(".oO { current cell has better armour (%s) }",o->type->name);
if (db) dblog(".oO { pickup of better armour %s failed! }",o->type->name); // try to pick it up
if (!aipickup(lf, o)) return B_TRUE;
if (db) dblog(".oO { pickup of better armour %s failed! }",o->type->name);
}
} }
} }
} }
@ -1079,7 +1113,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
int gothere = B_FALSE; int gothere = B_FALSE;
c = lf->los[i]; c = lf->los[i];
if (c != lf->ignorecell) { if (!c->lf && (c != lf->ignorecell)) {
o = hasobmulti(c->obpile, oid, noids); o = hasobmulti(c->obpile, oid, noids);
if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf,o)) ) { if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf,o)) ) {
if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name); if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name);
@ -1096,29 +1130,33 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
} }
} }
if (!gothere) { if (!gothere) {
// remote cell has better weapon? if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) {
f = hasflag(lf->flags, F_WANTSBETTERWEP); // remote cell has better weapon?
if (f) { f = hasflag(lf->flags, F_WANTSBETTERWEP);
if (!covetsonly || (f->val[1] == B_COVETS)) { if (f) {
if (!covetsonly || (f->val[1] == B_COVETS)) {
o = hasbetterweapon(lf, c->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { o = hasbetterweapon(lf, c->obpile);
if (db) dblog(".oO { remote cell has better weapon (%s). setting f_targetcell }",o->type->name); if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
gothere = B_TRUE; if (db) dblog(".oO { remote cell has better weapon (%s). setting f_targetcell }",o->type->name);
gothere = B_TRUE;
}
} }
} }
} }
} }
if (!gothere) { if (!gothere) {
// remote cell has better armour? if (lfhasflag(lf, F_HUMANOID)) {
f = hasflag(lf->flags, F_WANTSBETTERARM); // remote cell has better armour?
if (f) { f = hasflag(lf->flags, F_WANTSBETTERARM);
if (!covetsonly || (f->val[1] == B_COVETS)) { if (f) {
if (!covetsonly || (f->val[1] == B_COVETS)) {
o = hasbetterarmour(lf, c->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { o = hasbetterarmour(lf, c->obpile);
if (db) dblog(".oO { remote cell has better armour (%s). setting f_targetcell }",o->type->name); if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
gothere = B_TRUE; if (db) dblog(".oO { remote cell has better armour (%s). setting f_targetcell }",o->type->name);
gothere = B_TRUE;
}
} }
} }
} }

179
attack.c
View File

@ -18,20 +18,60 @@ extern lifeform_t *player;
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; object_t *armour = NULL;
int adam;
int damtaken = 0; int damtaken = 0;
if ((damtype == DT_ACID) || hasflag(wep->flags, F_ARMOURPIERCE)) {
// ALL of damage reduction goes towards armour // figure out what bit of armour was hit
adam = dam;
} else { // special case - missiles against flak jacket
// some of damage reduction goes towards armour if (damtype == DT_PROJECTILE) {
adam = (dam / 2); object_t *o;
o = getequippedob(lf->pack, BP_BODY);
if (o && (o->type->id == OT_FLAKJACKET)) {
// stop ALL missile damage
armour = o;
}
} }
// pick a random piece of armour
armour = getrandomarmour(lf); if (!armour) {
// pick a random piece of armour
armour = getrandomarmour(lf);
}
if (armour) { if (armour) {
damtaken = takedamage(armour,adam, damtype); int actualdam;
flag_t *rust;
// adjust how much damage to do to armour
if ( ((armour->type->id == OT_FLAKJACKET) && (damtype == DT_PROJECTILE)) ||
(damtype == DT_ACID) ||
hasflag(wep->flags, F_ARMOURPIERCE)) {
// ALL of damage reduction goes towards armour
actualdam = dam;
} else {
// half the damage reduction goes towards armour
actualdam = (dam / 2);
}
// modify for rust
rust = hasflag(armour->flags, F_RUSTED);
if (rust) {
int multiplier = 1;
switch (rust->val[0]) {
case R_RUSTY:
multiplier = 2;
case R_VRUSTY:
multiplier = 6;
case R_TRUSTY:
multiplier = 10;
}
actualdam *= multiplier;
}
// actually apply the damage to the armour
damtaken = takedamage(armour,actualdam, damtype);
} }
return damtaken; return damtaken;
} }
@ -268,9 +308,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
ndam = 1; ndam = 1;
// determine extra damage for flaming etc. // determine extra damage for flaming etc.
// getextradam from USER too
if (!willheal) { if (!willheal) {
getextradam(wep, &dam[0], &damtype[0], &ndam); getextradamwep(wep, &dam[0], &damtype[0], &ndam);
getextradamlf(lf, &dam[0], &damtype[0], &ndam);
} }
} else { } else {
hit = B_FALSE; hit = B_FALSE;
ndam = 0; ndam = 0;
@ -282,8 +325,8 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
flag_t *f; flag_t *f;
for (i = 0; i < ndam; i++) { for (i = 0; i < ndam; i++) {
int reduceamt; int reduceamt;
int backstab = B_FALSE; int backstab = B_FALSE;
flag_t *rust;
if (firstisbackstab && (i == 0)) backstab = B_TRUE; if (firstisbackstab && (i == 0)) backstab = B_TRUE;
dblog("initial dam[%d] = %d",i,dam[i]); dblog("initial dam[%d] = %d",i,dam[i]);
@ -293,6 +336,25 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
dblog("heavy blow makes dam[%d] = %d",i,dam[i]); dblog("heavy blow makes dam[%d] = %d",i,dam[i]);
} }
// modify for rust
rust = hasflag(wep->flags, F_RUSTED);
if (rust) {
switch (damtype[i]) {
case DT_PIERCE:
case DT_SLASH:
if (rust->val[0] >= R_TRUSTY) {
dam[i] -= (pctof(50, dam[i]));
} else if (rust->val[0] >= R_VRUSTY) {
dam[i] -= (pctof(25, dam[i]));
} else {
dam[i] -= (pctof(10, dam[i]));
}
break;
default:
break;
}
}
// modify based on resistances // modify based on resistances
adjustdamlf(victim, &dam[i], damtype[i]); adjustdamlf(victim, &dam[i], damtype[i]);
dblog("adjusted for lf to dam[%d] = %d",i,dam[i]); dblog("adjusted for lf to dam[%d] = %d",i,dam[i]);
@ -525,6 +587,16 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
fightback(victim, lf); fightback(victim, lf);
} }
// practice?
if (hit) {
skill_t *sk;
// extra damage for being skilled?
sk = getobskill(wep);
if (sk && !getskill(lf, sk->id)) {
practice(lf, sk->id);
}
}
// get rid of temp unarmed object pile // get rid of temp unarmed object pile
if (op) { if (op) {
killobpile(op); killobpile(op);
@ -624,7 +696,8 @@ int attackob(lifeform_t *lf, object_t *o) {
// don't need to check for blessed vs mosnters // don't need to check for blessed vs mosnters
// determine extra damage // determine extra damage
getextradam(wep, &dam[0], &damtype[0], &ndam); getextradamwep(wep, &dam[0], &damtype[0], &ndam);
getextradamlf(lf, &dam[0], &damtype[0], &ndam);
for (i = 0; i < ndam; i++) { for (i = 0; i < ndam; i++) {
@ -703,11 +776,22 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d
int reduceamt = 0; int reduceamt = 0;
float reducepct; float reducepct;
int ar; int ar;
object_t *o;
ar = getarmourrating(lf); ar = getarmourrating(lf);
reducepct = getdamreducepct(ar); reducepct = getdamreducepct(ar);
reduceamt = (int) ceil((reducepct / 100.0) * (float)dam); reduceamt = (int) ceil((reducepct / 100.0) * (float)dam);
// special case
if (damtype == DT_PROJECTILE) {
o = getequippedob(lf->pack, BP_BODY);
if (o && (o->type->id == OT_FLAKJACKET)) {
// stop ALL missile damage
reduceamt = dam;
}
}
if (reduceamt < 0) reduceamt = 0; if (reduceamt < 0) reduceamt = 0;
return reduceamt; return reduceamt;
} }
@ -891,13 +975,60 @@ enum DAMTYPE getdamtype(object_t *wep) {
return dt; return dt;
} }
int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) { int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam) {
flag_t *f;
// special case - EXTRADAM goes onto INITIAL dam[] if the same type, rather than
// adding a new one.
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_EXTRADAM) {
int *damwhere;
int *damtypewhere;
int doinc = B_FALSE;
if ((f->val[0] == NA) || (f->val[0] == *damtype)) {
damwhere = dam;
damtypewhere = damtype;
*(damwhere) += roll(f->text); // addition
} else {
damwhere = (dam + *ndam);
damtypewhere = (damtype + *ndam);
*(damwhere) = roll(f->text); // set
doinc = B_TRUE;
}
*(damtypewhere) = f->val[0];
if ((f->lifetime == FROMOBEQUIP) ||
(f->lifetime == FROMOBHOLD) ||
(f->lifetime == FROMOBACTIVATE) ) {
object_t *obfrom;
obfrom = findobbyid(lf->pack, f->obfrom);
if (obfrom) {
int bonusdam = 0;
sumflags(obfrom->flags, F_BONUS, &bonusdam, NULL, NULL);
*(damwhere) += bonusdam;
}
}
if (doinc) {
(*ndam)++;
}
}
}
return *dam;
}
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) { for (f = wep->flags->first ; f ; f = f->next) {
if (f->id == F_ONFIRE) { if (f->id == F_ONFIRE) {
*(dam + *ndam) = rolldie(2,8); *(dam + *ndam) = rolldie(2,6);
*(damtype + *ndam) = DT_FIRE; *(damtype + *ndam) = DT_FIRE;
(*ndam)++; (*ndam)++;
} else if (f->id == F_FROZEN) {
*(dam + *ndam) = rolldie(1,4);
*(damtype + *ndam) = DT_COLD;
(*ndam)++;
} }
} }
return *dam; return *dam;
@ -1019,6 +1150,7 @@ void getdamrangeunarmed(flag_t *f, int *min, int *max) {
// roll for damage // roll for damage
int getdamroll(object_t *o, lifeform_t *victim) { int getdamroll(object_t *o, lifeform_t *victim) {
int dam; int dam;
int bonusdam = 0;
flag_t *f; flag_t *f;
f = hasflag(o->flags, F_DAM); f = hasflag(o->flags, F_DAM);
if (f) { if (f) {
@ -1041,10 +1173,8 @@ int getdamroll(object_t *o, lifeform_t *victim) {
} }
// modify for bonus // modify for bonus
f = hasflag(o->flags, F_BONUS); sumflags(o->flags, F_BONUS, &bonusdam, NULL, NULL);
if (f) { dam += bonusdam;
dam += f->val[0];
}
if (dam < 0) dam = 0; if (dam < 0) dam = 0;
@ -1359,7 +1489,8 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
fid = f->val[0]; fid = f->val[0];
if (!lfhasflag(victim, fid)) { if (!lfhasflag(victim, fid)) {
int passedcheck = B_FALSE; int passedcheck = B_FALSE;
if (!f->val[1] == NA) { // do they get a saving throw?
if (f->val[1] != NA) {
int scdiff; int scdiff;
if (f->val[2] == NA) { if (f->val[2] == NA) {
scdiff = 20; // default scdiff = 20; // default
@ -1372,8 +1503,6 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
} }
if (!passedcheck) { if (!passedcheck) {
int val0;
val0 = f->val[1];
if (f->text) { if (f->text) {
char loctext[BUFLEN]; char loctext[BUFLEN];
char *word, *dummy; char *word, *dummy;
@ -1415,9 +1544,9 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
} else { } else {
strcpy(frombuf, "something unknown"); strcpy(frombuf, "something unknown");
} }
addtempflag(victim->flags, fid, val0, NA, NA, frombuf, howlong); addtempflag(victim->flags, fid, NA, NA, NA, frombuf, howlong);
} else { } else {
addtempflag(victim->flags, fid, val0, NA, NA, NULL, howlong); addtempflag(victim->flags, fid, NA, NA, NA, NULL, howlong);
} }
} // end if passedcheck } // end if passedcheck
} // end (if victim doesn't already have the flag) } // end (if victim doesn't already have the flag)

View File

@ -10,7 +10,8 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d
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);
int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam); int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam);
int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam);
char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp); char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp);
void getdamrange(flagpile_t *fp, int *min, int *max); void getdamrange(flagpile_t *fp, int *min, int *max);
void getdamrangeunarmed(flag_t *f, int *min, int *max); void getdamrangeunarmed(flag_t *f, int *min, int *max);

126
defs.h
View File

@ -4,6 +4,30 @@
// MACROS // MACROS
#define MAXOF(a,b) (a > b ? a : b) #define MAXOF(a,b) (a > b ? a : b)
#define PRACTICETIME 50 // #attempts it takes to learn new skill
#define WETTIME 10 // how long it takes for things to dry
// ncurses colours
enum COLOUR {
C_BLACK = 0,
C_RED = 1,
C_GREEN = 2,
C_BROWN = 3,
C_BLUE = 4,
C_MAGENTA = 5,
C_CYAN = 6,
C_GREY = 7,
// bolded colours
C_YELLOW = 8,
C_WHITE = 9,
C_BOLDCYAN = 10,
C_BOLDBLUE = 11,
C_BOLDMAGENTA = 12,
C_ORANGE = 13,
C_BOLDGREEN = 14,
};
// save/load // save/load
#define MAPDIR "data/maps" #define MAPDIR "data/maps"
#define SAVEDIR "data/save" #define SAVEDIR "data/save"
@ -169,7 +193,8 @@ enum LFCONDITION {
#define DEF_WINDOWPCT 5 #define DEF_WINDOWPCT 5
// //
#define ANIMDELAY (1000000 / 100) // 1/100 of a second //#define ANIMDELAY (1000000 / 100) // 1/100 of a second
#define ANIMDELAY (1000000 / 50) // 1/100 of a second
#define MAXVISRANGE 10 // max visible range in full light #define MAXVISRANGE 10 // max visible range in full light
@ -386,9 +411,10 @@ enum DAMTYPE {
DT_FALL = 23, DT_FALL = 23,
DT_PETRIFY = 24, DT_PETRIFY = 24,
DT_POISON = 25, DT_POISON = 25,
DT_NONE = 26, // for direclty dealt damage, not really any type DT_NECROTIC = 26,
DT_NONE = 27, // for direclty dealt damage, not really any type
}; };
#define MAXDAMTYPE 27 #define MAXDAMTYPE 28
// Object Classes // Object Classes
enum OBCLASS { enum OBCLASS {
@ -482,7 +508,8 @@ enum RACE {
R_ANT, R_ANT,
R_ANTS, R_ANTS,
R_BAT, R_BAT,
R_HAWK, R_HAWKBLOOD,
R_HAWKFROST,
R_NEWT, R_NEWT,
R_RAT, R_RAT,
R_SNAKE, R_SNAKE,
@ -507,6 +534,7 @@ enum JOB {
J_GOD, J_GOD,
J_ADVENTURER, J_ADVENTURER,
J_ALLOMANCER, J_ALLOMANCER,
J_BARBARIAN,
J_COMMANDO, J_COMMANDO,
J_PLUMBER, J_PLUMBER,
J_PRINCE, J_PRINCE,
@ -635,6 +663,7 @@ enum OBTYPE {
OT_SCR_LIGHT, OT_SCR_LIGHT,
OT_SCR_MAPPING, OT_SCR_MAPPING,
OT_SCR_MINDSCAN, OT_SCR_MINDSCAN,
OT_SCR_PERMENANCE,
OT_SCR_ENCHANT, OT_SCR_ENCHANT,
OT_SCR_FREEZEOB, OT_SCR_FREEZEOB,
OT_SCR_REMOVECURSE, OT_SCR_REMOVECURSE,
@ -678,8 +707,10 @@ enum OBTYPE {
// allomancy can't be learned from books // allomancy can't be learned from books
// -- death // -- death
OT_SB_ANIMATEDEAD, OT_SB_ANIMATEDEAD,
OT_SB_DRAINLIFE,
OT_SB_PAIN, OT_SB_PAIN,
OT_SB_PARALYZE, OT_SB_PARALYZE,
OT_SB_POISONBOLT,
OT_SB_INFINITEDEATH, OT_SB_INFINITEDEATH,
OT_SB_WEAKEN, OT_SB_WEAKEN,
OT_SB_BLINDNESS, OT_SB_BLINDNESS,
@ -749,11 +780,14 @@ enum OBTYPE {
OT_S_METALHEAL, OT_S_METALHEAL,
// -- death // -- death
OT_S_ANIMATEDEAD, OT_S_ANIMATEDEAD,
OT_S_DRAINLIFE,
OT_S_PAIN, OT_S_PAIN,
OT_S_PARALYZE, OT_S_PARALYZE,
OT_S_INFINITEDEATH, OT_S_INFINITEDEATH,
OT_S_WEAKEN, OT_S_WEAKEN,
OT_S_BLINDNESS, OT_S_BLINDNESS,
OT_S_POISONBOLT,
OT_S_POSSESSION,
// -- divination // -- divination
OT_S_DETECTAURA, OT_S_DETECTAURA,
OT_S_DETECTLIFE, OT_S_DETECTLIFE,
@ -772,6 +806,7 @@ enum OBTYPE {
OT_S_FLAMEBURST, OT_S_FLAMEBURST,
OT_S_BURNINGWAVE, OT_S_BURNINGWAVE,
// -- elemental - ice // -- elemental - ice
OT_S_COLDBURST,
OT_S_CONECOLD, OT_S_CONECOLD,
OT_S_FREEZEOB, OT_S_FREEZEOB,
// -- gravity // -- gravity
@ -824,11 +859,13 @@ enum OBTYPE {
OT_A_DEBUG, OT_A_DEBUG,
OT_A_ENHANCE, OT_A_ENHANCE,
OT_A_LEARN, OT_A_LEARN,
OT_A_LEVELUP,
// abilities // abilities
OT_A_GRAB, OT_A_GRAB,
OT_A_CRUSH, OT_A_CRUSH,
OT_A_JUMP, OT_A_JUMP,
OT_A_SPRINT, OT_A_SPRINT,
OT_A_SWOOP,
OT_A_EMPLOY, OT_A_EMPLOY,
OT_A_HEAVYBLOW, OT_A_HEAVYBLOW,
OT_A_INSPECT, OT_A_INSPECT,
@ -852,6 +889,7 @@ enum OBTYPE {
OT_BUGLAMP, OT_BUGLAMP,
OT_CANDLE, OT_CANDLE,
OT_GUNPOWDER, OT_GUNPOWDER,
OT_LAMPOIL,
OT_LANTERNOIL, OT_LANTERNOIL,
OT_LOCKPICK, OT_LOCKPICK,
OT_PICKAXE, OT_PICKAXE,
@ -881,6 +919,7 @@ enum OBTYPE {
OT_BROKENGLASS, OT_BROKENGLASS,
OT_ICECHUNK, OT_ICECHUNK,
OT_ICESHEET, OT_ICESHEET,
OT_SPLASHWATER,
OT_PUDDLEWATER, OT_PUDDLEWATER,
OT_PUDDLEWATERL, OT_PUDDLEWATERL,
OT_ACIDPUDDLE, OT_ACIDPUDDLE,
@ -953,11 +992,14 @@ enum OBTYPE {
// rings // rings
OT_RING_INVIS, OT_RING_INVIS,
OT_RING_INVULN, OT_RING_INVULN,
OT_RING_LUCK,
OT_RING_MANA,
OT_RING_MPREGEN, OT_RING_MPREGEN,
OT_RING_PROTFIRE, OT_RING_PROTFIRE,
OT_RING_REGENERATION, OT_RING_REGENERATION,
OT_RING_RESISTMAG, OT_RING_RESISTMAG,
OT_RING_SEEINVIS, OT_RING_SEEINVIS,
OT_RING_WOUNDING,
// animal weapons // animal weapons
OT_CLAWS, OT_CLAWS,
OT_FISTS, OT_FISTS,
@ -1018,6 +1060,7 @@ enum OBTYPE {
OT_SLING, OT_SLING,
OT_BOW, OT_BOW,
OT_LONGBOW, OT_LONGBOW,
OT_CROSSBOW,
OT_CROSSBOWHAND, OT_CROSSBOWHAND,
// holy weapons // holy weapons
OT_HANDOFGOD, OT_HANDOFGOD,
@ -1093,7 +1136,8 @@ enum FLAG {
F_BONUS, // val0=bonus/penalty to damage/armour. ie. +1 sword F_BONUS, // val0=bonus/penalty to damage/armour. ie. +1 sword
F_THROWMISSILE, // weapon would make a good thrown missle - used by AI F_THROWMISSILE, // weapon would make a good thrown missle - used by AI
F_UNIQUE, // only one may appear F_UNIQUE, // only one may appear
F_GLYPH, // override the glyph with the first char of text F_GLYPH, // override the glyph with the first char of text.
// v0 is either NA (white) or colourid (C_xxx).
F_NOPICKUP, // cannot pick this up F_NOPICKUP, // cannot pick this up
F_IMPASSABLE, // cannot walk past this if your size if v0 or smaller F_IMPASSABLE, // cannot walk past this if your size if v0 or smaller
F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it
@ -1179,6 +1223,11 @@ enum FLAG {
F_SLIPPERY, // you might slip when stepping on it. v0 is amt F_SLIPPERY, // you might slip when stepping on it. v0 is amt
F_SLIPMOVE, // if someone slips on this, it will move to an adj cell F_SLIPMOVE, // if someone slips on this, it will move to an adj cell
F_FLAMMABLE, // object will catch alight if burnt (ie fire damage) F_FLAMMABLE, // object will catch alight if burnt (ie fire damage)
F_CANGETWET, // object will get F_WET if hit by water
// v0 = enum WETNESS. v1 = how long
F_WET, // object is wet
F_RUSTED, // object is rusty
// v0 = enum RUSTINESS.
// object mods/effects // object mods/effects
F_ONFIRE, // burning, also deals extra fire damage F_ONFIRE, // burning, also deals extra fire damage
F_HEADLESS, // for corpses. can go on LFs too. F_HEADLESS, // for corpses. can go on LFs too.
@ -1189,6 +1238,7 @@ enum FLAG {
F_OBATTACKDELAY, // how long weapon takes to attack F_OBATTACKDELAY, // how long weapon takes to attack
F_USESSKILL, // weapon needs skill sk_v0 F_USESSKILL, // weapon needs skill sk_v0
F_CANHAVEOBMOD, // weapon can have obmod om_v0 applied F_CANHAVEOBMOD, // weapon can have obmod om_v0 applied
F_ATTREQ, // requires attrib v0 to be at least bracket v1
F_DAMTYPE, // val0 = damage type F_DAMTYPE, // val0 = damage type
F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod
F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier) F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier)
@ -1196,7 +1246,7 @@ enum FLAG {
F_ARMOURPIERCE, // goes through armour F_ARMOURPIERCE, // goes through armour
F_TWOHANDED, // weapon uses two hands to weild F_TWOHANDED, // weapon uses two hands to weild
F_FIREARM, // this weapon is equipped in bp_secweapon, not _weapon. F_FIREARM, // this weapon is equipped in bp_secweapon, not _weapon.
F_FIRESPEED, // how fast this weapon shoots projectimes F_FIRESPEED, // how fast this weapon shoots projectiles
F_AMMOOB, // what object this weapon fires F_AMMOOB, // what object this weapon fires
F_RANGE, // range of projectile firing weapon F_RANGE, // range of projectile firing weapon
F_FLAMESTRIKE, // causes fires where you hit F_FLAMESTRIKE, // causes fires where you hit
@ -1257,7 +1307,7 @@ enum FLAG {
// using their strength // using their strength
// player only flags // player only flags
F_DONEDARKMSG, // tells the game not to say 'it is very dark here' F_DONEDARKMSG, // tells the game not to say 'it is very dark here'
// lifeform flags // lifeform flags / lf flags
F_DEBUG, // debugging enabled F_DEBUG, // debugging enabled
F_ATTRMOD, // modify attribute val0 by val1. ie. 0=A_STR,1=-3 F_ATTRMOD, // modify attribute val0 by val1. ie. 0=A_STR,1=-3
F_ATTRSET, // forces attribute val0 to be val1. ie. 0=A_STR,1=18 F_ATTRSET, // forces attribute val0 to be val1. ie. 0=A_STR,1=18
@ -1283,9 +1333,10 @@ enum FLAG {
F_GUNTARGET, // current projectile weapon target F_GUNTARGET, // current projectile weapon target
F_CASTINGSPELL, // set while the player is casting a spell F_CASTINGSPELL, // set while the player is casting a spell
// v0 is spell id // v0 is spell id
// ABILITY/SPELL FLAGS // ABILITY/SPELL FLAGS / ability flags / spell flags
F_FAILEDINSPECT, // lf has failed an inspect check for item id v0 F_FAILEDINSPECT, // lf has failed an inspect check for item id v0
F_BOOSTSPELL, // v0 is active boost spell F_BOOSTSPELL, // v0 is active boost spell
F_SWOOPRANGE, // v0 = how far a flying creature can swoop
// MONSTER AI FLAGS // MONSTER AI FLAGS
F_XPVAL, // force xp val for killing this lf to v0 F_XPVAL, // force xp val for killing this lf to v0
F_HOSTILE, // lf will attack the player if in sight F_HOSTILE, // lf will attack the player if in sight
@ -1334,6 +1385,7 @@ enum FLAG {
// v0=slot (0-9) // v0=slot (0-9)
// text=spell text // text=spell text
// for monsters // for monsters
F_HUMANOID, // this race can wear armour / use weapons
F_INSECT, // this race is classed as an insect F_INSECT, // this race is classed as an insect
F_ANIMAL, // this race is classed as an animal F_ANIMAL, // this race is classed as an animal
F_UNDEAD, // this race is classed as undead F_UNDEAD, // this race is classed as undead
@ -1355,19 +1407,26 @@ enum FLAG {
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn) F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
F_BLIND, // cannot see anything F_BLIND, // cannot see anything
F_CANCAST, // can cast the spell val0 (need MP) F_CANCAST, // can cast the spell val0 (need MP)
F_CANWILL, // can cast the spell val0 without using MP F_CANWILL, // can cast the spell/ability val0 without using MP
// v1 is counter untiluse // v1 is counter untiluse
// v2 is what you need to use it // v2 is what you need to use it
// ie. when v1 == v2, ability is ready. // ie. when v1 == v2, ability is ready.
// text is other options, semicolon seperated: // text is other options, semicolon seperated:
// pw:xx; cast the spell at power xx // pw:xx; cast the spell at power xx
// dam:xdy+b; damage
// needgrab:xx; do you need to grab first?
F_CHARMEDBY,// you've been charmed by lf id v0 F_CHARMEDBY,// you've been charmed by lf id v0
F_DETECTAURAS, // autodetect bless/curse F_DETECTAURAS, // autodetect bless/curse
F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0 F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0
F_DETECTMAGIC, // autodetect magic/special objects F_DETECTMAGIC, // autodetect magic/special objects
F_DETECTMETAL, // autodetect nearby metal F_DETECTMETAL, // autodetect nearby metal
F_DETECTOBS, // autodetect nearby obs in orthog dist v0 F_DETECTOBS, // autodetect nearby obs in orthog dist v0
F_EXTRADAM, // do 'text' extra damage of damtype v0 when you hit
// if v1 is TRUE, also deal extra damage based on
// the flagpile's F_BONUS flag.
F_EXTRAINFO, // knows extra info F_EXTRAINFO, // knows extra info
F_EXTRALUCK, // lf gets +v0 to all skill checks!
F_EXTRAMP, // lf has +v0 % extra maxmp
F_FLYING, // lf is flying F_FLYING, // lf is flying
F_FASTACT, // modifier for action speed F_FASTACT, // modifier for action speed
F_FASTMOVE, // modifier for move speed F_FASTMOVE, // modifier for move speed
@ -1406,13 +1465,14 @@ enum FLAG {
F_SLOWMOVE, // modifier for move speed F_SLOWMOVE, // modifier for move speed
F_XRAYVIS, //val0=num of walls we can see through F_XRAYVIS, //val0=num of walls we can see through
F_CANSEETHROUGHMAT, //val0=kind of material you can see through F_CANSEETHROUGHMAT, //val0=kind of material you can see through
F_SPRINTING, // you are sprinting F_SPRINTING, // v0=true: you are sprinting. false=you are tired
F_TIRED, // you are too tired to sprint F_TIRED, // you are too tired to sprint
F_DODGES, // you dodge missed attacks F_DODGES, // you dodge missed attacks
F_NOTIME, // this lf's actions don't take time F_NOTIME, // this lf's actions don't take time
F_PERCEPTION, // v0 = 0-20. perception level. F_PERCEPTION, // v0 = 0-20. perception level.
// skills // skills
F_HASSKILL, // lf has skill v0 at level v1 F_HASSKILL, // lf has skill v0 at level v1
F_PRACTICINGSKILL, // lf is pract skill v0
// COMBAT // COMBAT
F_HASATTACK, // objecttype id to use when attacking unarmed F_HASATTACK, // objecttype id to use when attacking unarmed
// if val0-3 are filled in, they override the object's // if val0-3 are filled in, they override the object's
@ -1569,6 +1629,13 @@ enum ERROR {
E_NOTKNOWN = 35, E_NOTKNOWN = 35,
E_TOOPOWERFUL = 36, E_TOOPOWERFUL = 36,
E_NEEDGRAB = 37, E_NEEDGRAB = 37,
E_DOORINWAY = 38,
E_NOCANNIBUL = 39,
E_LOWCON = 40,
E_LOWDEX = 41,
E_LOWIQ = 42,
E_LOWSTR = 43,
E_WONT = 44,
}; };
@ -1657,9 +1724,18 @@ typedef struct cell_s {
int visited; int visited;
} cell_t; } cell_t;
typedef struct glyph_s {
char ch;
int colour;
} glyph_t;
typedef struct celltype_s { typedef struct celltype_s {
int id; // eg. dungeonfloor, wall, door int id; // eg. dungeonfloor, wall, door
struct glyph_s glyph;
/*
char glyph; // how to display it char glyph; // how to display it
int colour; // which colour?
*/
char *name; // name of cell type char *name; // name of cell type
int solid; // can you walk through it? int solid; // can you walk through it?
int transparent; // can you see through it? int transparent; // can you see through it?
@ -1676,7 +1752,7 @@ typedef struct race_s {
enum RACE baseid; enum RACE baseid;
struct material_s *material; struct material_s *material;
char *name; char *name;
char glyph; struct glyph_s glyph;
float weight; float weight;
struct flagpile_s *flags; struct flagpile_s *flags;
// speed modifiers // speed modifiers
@ -1853,7 +1929,7 @@ typedef struct objectclass_s {
enum OBCLASS id; enum OBCLASS id;
char *name; char *name;
char *desc; char *desc;
char glyph; glyph_t glyph;
struct flagpile_s *flags; struct flagpile_s *flags;
struct objectclass_s *next, *prev; struct objectclass_s *next, *prev;
} objectclass_t; } objectclass_t;
@ -1890,6 +1966,19 @@ typedef struct object_s {
struct object_s *next, *prev; struct object_s *next, *prev;
} object_t; } object_t;
// wetness
enum WETNESS {
W_DRY = 0,
W_DAMP = 1,
W_WET = 2,
W_SOAKED = 3,
};
enum RUSTINESS {
R_RUSTY = 1,
R_VRUSTY = 2,
R_TRUSTY = 3,
};
enum OBMOD { enum OBMOD {
OM_FLAMING, OM_FLAMING,
OM_FROZEN, OM_FROZEN,
@ -1897,17 +1986,24 @@ enum OBMOD {
OM_MASTERWORK, OM_MASTERWORK,
OM_POISONED, OM_POISONED,
OM_SHODDY, OM_SHODDY,
OM_WET1,
OM_WET2,
OM_WET3,
OM_RUSTY1,
OM_RUSTY2,
OM_RUSTY3,
}; };
#define MAXOBMODS 4 #define MAXOBMODS 4
enum BRAND { enum BRAND {
BR_BALANCE, BR_BALANCE,
BR_DEXTERITY, BR_NIMBLENESS,
BR_FEEBLENESS, BR_FEEBLENESS,
BR_FLIGHT, BR_FLIGHT,
BR_GIANTSTRENGTH, BR_GIANTSTRENGTH,
BR_HEALTH,
BR_IMPACT, BR_IMPACT,
BR_INTELLIGENCE, BR_THINKING,
BR_KNOWLEDGE, BR_KNOWLEDGE,
BR_LEVITATION, BR_LEVITATION,
BR_FEATHERFALL, BR_FEATHERFALL,
@ -1918,7 +2014,7 @@ enum BRAND {
BR_REVENGE, BR_REVENGE,
BR_SLOTH, BR_SLOTH,
BR_SPEED, BR_SPEED,
BR_STRENGTH, BR_POWER,
BR_SWIFTNESS, BR_SWIFTNESS,
BR_TELEKINESIS, BR_TELEKINESIS,
BR_TELEPATHY, BR_TELEPATHY,

95
flag.c
View File

@ -49,6 +49,13 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
} }
} }
// override values sometimes
/*
if ((id == F_WET) && (val2 == NA)) {
val2 = WETTIME;
}
*/
if (fp->first == NULL) { if (fp->first == NULL) {
fp->first = malloc(sizeof(flag_t)); fp->first = malloc(sizeof(flag_t));
f = fp->first; f = fp->first;
@ -165,6 +172,16 @@ flagpile_t *addflagpile(lifeform_t *owner, object_t *ob) {
return fp; return fp;
} }
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) {
flag_t *f;
for (f = src->first ; f ; f = f->next) {
if (f->id == id) {
addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text,
f->lifetime, f->known, -1);
}
}
}
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) { void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) {
flag_t *f; flag_t *f;
for (f = src->first ; f ; f = f->next) { for (f = src->first ; f ; f = f->next) {
@ -328,24 +345,6 @@ void killflag(flag_t *f) {
lf->polyrevert = B_TRUE; lf->polyrevert = B_TRUE;
} }
if (lf && (f->id == F_SPRINTING)) {
int howlong;
int slev;
// you get tired when you finish sprinting
howlong = 15;
// adjust for athletics skill. -2 per level.
slev = getskill(lf, SK_ATHLETICS);
if (slev != PR_INEPT) {
howlong -= (2*slev);
}
// adjust for constitution
howlong = howlong - (int) ((float)howlong * (getstatmod(lf, A_CON) / 100) );
// enforce minimum
if (howlong < 1) howlong = 1;
addtempflag(f->pile, F_TIRED, B_TRUE, NA, NA, NULL, howlong);
}
// free mem // free mem
// remove from list // remove from list
@ -419,6 +418,18 @@ void timeeffectsflag(flag_t *f, int howlong) {
break; break;
} }
} }
} else if (f->lifetime == 5) {
if (isplayer(f->pile->owner)) {
switch (f->id) {
case F_SPRINTING:
if (f->val[0]) {
warn("You will have to stop sprinting soon...");
}
break;
default:
break;
}
}
} else if (f->lifetime == 2) { } else if (f->lifetime == 2) {
if (isplayer(f->pile->owner)) { if (isplayer(f->pile->owner)) {
switch (f->id) { switch (f->id) {
@ -461,6 +472,38 @@ void timeeffectsflag(flag_t *f, int howlong) {
break; break;
} }
} }
// sprinting is special
if (f->id == F_SPRINTING) {
if (f->val[0]) {
enum SKILLLEVEL slev;
lifeform_t *who;
int tiredtime;
who = f->pile->owner;
// now you get slow
// you get tired when you finish sprinting
tiredtime = 15;
// adjust for athletics skill. -2 per level.
slev = getskill(who, SK_ATHLETICS);
if (slev != PR_INEPT) {
tiredtime -= (2*slev);
}
// adjust for constitution
tiredtime = tiredtime - (int) ((float)tiredtime * (getstatmod(who, A_CON) / 100) );
// enforce minimum
if (tiredtime < 1) tiredtime = 1;
f->val[0] = B_FALSE;
f->lifetime = tiredtime;
if (isplayer(who)) {
msg("You are exhausted.");
} else if (cansee(player, who)) {
char lfname[BUFLEN];
getlfname(who, lfname);
msg("%s looks exhausted.",lfname);
}
}
}
} }
} }
@ -473,6 +516,22 @@ void timeeffectsflag(flag_t *f, int howlong) {
} else { } else {
// stoning failed. stop being stoned. // stoning failed. stop being stoned.
killflag(f); killflag(f);
return;
}
}
}
if (f->id == F_WET) {
f->val[1]--;
if (f->val[1] <= 0) {
f->val[0]--;
if (f->val[0] <= W_DRY) {
killflag(f);
return;
} else {
// reset timer
f->val[1] = WETTIME;
// TODO: announce
} }
} }
} }

1
flag.h
View File

@ -6,6 +6,7 @@ flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char
flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft); flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft);
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid); flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid);
flagpile_t *addflagpile(lifeform_t *owner, object_t *o); flagpile_t *addflagpile(lifeform_t *owner, object_t *o);
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id);
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime); void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int flagcausesredraw(lifeform_t *lf, enum FLAG fid); int flagcausesredraw(lifeform_t *lf, enum FLAG fid);
int flagstacks(enum FLAG fid); int flagstacks(enum FLAG fid);

414
io.c
View File

@ -26,6 +26,8 @@ WINDOW *statwin;
int statdirty = B_TRUE; int statdirty = B_TRUE;
int hascolour = B_TRUE;
extern int needredraw; extern int needredraw;
extern int numdraws; extern int numdraws;
@ -117,7 +119,7 @@ void addpromptq(prompt_t *p, char *q) {
p->nqs++; p->nqs++;
} }
void anim(cell_t *src, cell_t *dst, char ch) { void anim(cell_t *src, cell_t *dst, char ch, int colour) {
int deltax, deltay; int deltax, deltay;
int numpixels; int numpixels;
int d; int d;
@ -127,6 +129,7 @@ void anim(cell_t *src, cell_t *dst, char ch) {
int x1,y1; int x1,y1;
int x; int x;
int y; int y;
glyph_t gl;
//int maxvisrange; //int maxvisrange;
//int modmaxvisrange; //int modmaxvisrange;
//int xray = B_FALSE; //int xray = B_FALSE;
@ -181,8 +184,13 @@ void anim(cell_t *src, cell_t *dst, char ch) {
yinc2 = - yinc2; yinc2 = - yinc2;
} }
x = x1; y = y1; x = x1; y = y1;
gl.ch = ch;
gl.colour = colour;
// hide cursor
curs_set(0);
for (i = 0; i < numpixels ; i++) { for (i = 0; i < numpixels ; i++) {
cell_t *cell; cell_t *cell;
@ -190,11 +198,12 @@ void anim(cell_t *src, cell_t *dst, char ch) {
cell = getcellat(src->map, x, y); cell = getcellat(src->map, x, y);
// update screen // update screen
updateviewfor(cell);
drawlevelfor(player);
if (haslos(player, cell)) { if (haslos(player, cell)) {
updateviewfor(cell);
drawlevelfor(player);
// draw char & cursor at its current pos... // draw char & cursor at its current pos...
mvwprintw(gamewin, cell->y - viewy, cell->x - viewx, "%c", ch); drawglyph(&gl, cell->x - viewx, cell->y - viewy);
//mvwprintw(gamewin, cell->y - viewy, cell->x - viewx, "%c", gl.ch);
wmove(gamewin, cell->y - viewy, cell->x - viewx); wmove(gamewin, cell->y - viewy, cell->x - viewx);
wrefresh(gamewin); wrefresh(gamewin);
usleep(ANIMDELAY); usleep(ANIMDELAY);
@ -215,13 +224,20 @@ void anim(cell_t *src, cell_t *dst, char ch) {
x += xinc; x += xinc;
y += yinc; y += yinc;
} }
// show cursor
curs_set(1);
} }
void animradial(cell_t *src, int radius, char ch) { void animradial(cell_t *src, int radius, char ch, int colour) {
glyph_t gl;
int i; int i;
int x,y; int x,y;
cell_t *c; cell_t *c;
gl.ch = ch;
gl.colour = colour;
// hide cursor
curs_set(0);
for (i = 0; i <= radius; i++) { for (i = 0; i <= radius; i++) {
int drawn = B_FALSE; int drawn = B_FALSE;
@ -234,7 +250,8 @@ void animradial(cell_t *src, int radius, char ch) {
c = getcellat(src->map, x, y); c = getcellat(src->map, x, y);
if (c && haslos(player, c) && (getcelldistorth(src, c) <= i)) { if (c && haslos(player, c) && (getcelldistorth(src, c) <= i)) {
// draw char & cursor at its current pos... // draw char & cursor at its current pos...
mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch); //mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch);
drawglyph(&gl, c->x - viewx, c->y - viewy);
drawn = B_TRUE; drawn = B_TRUE;
} }
} }
@ -245,14 +262,21 @@ void animradial(cell_t *src, int radius, char ch) {
usleep(ANIMDELAY); usleep(ANIMDELAY);
} }
} }
// show cursor
curs_set(1);
} }
void animradialorth(cell_t *src, int radius, char ch) { void animradialorth(cell_t *src, int radius, char ch,int colour) {
glyph_t gl;
int i; int i;
int x,y; int x,y;
cell_t *c; cell_t *c;
gl.ch = ch;
gl.colour = colour;
// hide cursor
curs_set(0);
for (i = 0; i <= radius; i++) { for (i = 0; i <= radius; i++) {
int drawn = B_FALSE; int drawn = B_FALSE;
@ -265,7 +289,8 @@ void animradialorth(cell_t *src, int radius, char ch) {
c = getcellat(src->map, x, y); c = getcellat(src->map, x, y);
if (c && haslos(player, c) && (getcelldist(src, c) <= i)) { if (c && haslos(player, c) && (getcelldist(src, c) <= i)) {
// draw char & cursor at its current pos... // draw char & cursor at its current pos...
mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch); //mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch);
drawglyph(&gl, c->x - viewx, c->y - viewy);
drawn = B_TRUE; drawn = B_TRUE;
} }
} }
@ -276,7 +301,8 @@ void animradialorth(cell_t *src, int radius, char ch) {
usleep(ANIMDELAY); usleep(ANIMDELAY);
} }
} }
// show cursor
curs_set(1);
} }
char askchar(char *prompt, char *validchars, char *def, int showchars) { char askchar(char *prompt, char *validchars, char *def, int showchars) {
@ -826,8 +852,24 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
} }
break; break;
case F_POISONED: case F_POISONED:
msg("%s %s very sick.", lfname, isplayer(lf) ? "feel" : "looks");
donesomething = B_TRUE;
break;
case F_EXTRADAM:
if (isplayer(lf)) { // don't know if monsters get it if (isplayer(lf)) { // don't know if monsters get it
msg("You feel very sick."); msg("You feel more dangerous!");
donesomething = B_TRUE;
}
break;
case F_EXTRAMP:
if (isplayer(lf)) { // don't know if monsters get it
msg("Your magical power feels boosted!");
donesomething = B_TRUE;
}
break;
case F_EXTRALUCK:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel lucky!");
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
@ -938,13 +980,13 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
msg("%s %s sprinting!",lfname, isplayer(lf) ? "start" : "starts"); msg("%s %s sprinting!",lfname, isplayer(lf) ? "start" : "starts");
donesomething = B_TRUE; donesomething = B_TRUE;
break; break;
case F_TIRED: case F_TIRED:
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You are exhausted."); msg("You are exhausted.");
} else { } else if (cansee(player, lf)) {
msg("%s looks exhausted.",lfname); msg("%s looks exhausted.",lfname);
} }
donesomething = B_TRUE;
break; break;
case F_VISRANGEMOD: case F_VISRANGEMOD:
if (isplayer(lf)) { // don't know if monsters get it if (isplayer(lf)) { // don't know if monsters get it
@ -1104,6 +1146,24 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
case F_EXTRADAM:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You no longer feel more dangerous.");
donesomething = B_TRUE;
}
break;
case F_EXTRALUCK:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel less lucky.");
donesomething = B_TRUE;
}
break;
case F_EXTRAMP:
if (isplayer(lf)) { // don't know if monsters get it
msg("Your magical power no longer feels boosted.");
donesomething = B_TRUE;
}
break;
case F_FASTACT: case F_FASTACT:
msg("%s %s",lfname, isplayer(lf) ? "are no longer accelerated." : "is no longer accelerated."); msg("%s %s",lfname, isplayer(lf) ? "are no longer accelerated." : "is no longer accelerated.");
donesomething = B_TRUE; donesomething = B_TRUE;
@ -1120,10 +1180,8 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
msg("%s no longer looks quite so friendly!", lfname); msg("%s no longer looks quite so friendly!", lfname);
break; break;
case F_POISONED: case F_POISONED:
if (isplayer(lf)) { // don't know if monsters lose it msg("%s %s less sick now.", lfname, isplayer(lf) ? "feel" : "looks");
msg("You feel less sick now."); donesomething = B_TRUE;
donesomething = B_TRUE;
}
break; break;
case F_DODGES: case F_DODGES:
if (isplayer(lf)) { // don't know if monsters lose it if (isplayer(lf)) { // don't know if monsters lose it
@ -1291,9 +1349,17 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
break; break;
case F_SPRINTING: case F_SPRINTING:
if (isplayer(lf)) { // don't know if monsters lose it (but you'll see them get exhausted) if (f->val[0]) {
msg("You stop sprinting."); if (isplayer(lf)) { // don't know if monsters lose it (but you'll see them get exhausted)
donesomething = B_TRUE; msg("You stop sprinting.");
donesomething = B_TRUE;
}
} else {
if (isplayer(lf)) { // don't know if monsters get it
msg("You are no longer exhausted.");
} else {
msg("%s looks less exhausted.",lfname);
}
} }
break; break;
case F_TIRED: case F_TIRED:
@ -1383,7 +1449,7 @@ int announceobflaggain(object_t *o, flag_t *f) {
break; break;
case F_PRODUCESLIGHT: case F_PRODUCESLIGHT:
donesomething = B_TRUE; donesomething = B_TRUE;
if (o->birthtime != curtime) msg("%s starts glowing!",prefix); if (o->birthtime != curtime) msg("%s start%s glowing!",prefix, (o->amt == 1) ? "s" : "");
break; break;
default: // no message default: // no message
break; break;
@ -1394,6 +1460,7 @@ int announceobflaggain(object_t *o, flag_t *f) {
void announceobflagloss(object_t *o, flag_t *f) { void announceobflagloss(object_t *o, flag_t *f) {
char obname[BUFLEN]; char obname[BUFLEN];
char prefix[BUFLEN]; char prefix[BUFLEN];
char isare[BUFLEN];
cell_t *loc; cell_t *loc;
loc = getoblocation(o); loc = getoblocation(o);
@ -1418,17 +1485,20 @@ void announceobflagloss(object_t *o, flag_t *f) {
} }
if (o->amt == 1) { if (o->amt == 1) {
strcat(prefix, " is"); strcat(isare, "is");
} else { } else {
strcat(prefix, " are"); strcat(isare, "are");
} }
switch (f->id) { switch (f->id) {
case F_ONFIRE: case F_ONFIRE:
msg("%s no longer on fire.",prefix); msg("%s %s no longer on fire.",prefix,isare);
break; break;
case F_PRODUCESLIGHT: case F_PRODUCESLIGHT:
msg("%s no longer glowing.",prefix); msg("%s %s no longer glowing.",prefix,isare);
break;
case F_WET:
msg("%s %s out.",prefix, (o->amt == 1) ? "dries" : "dry");
break; break;
default: // no message default: // no message
break; break;
@ -2195,6 +2265,13 @@ void describeob(object_t *o) {
sprintf(buf, "It inflicts %d-%d %s damage",mindam,maxdam, getdamname(damtype)); sprintf(buf, "It 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, dicebuf);
strcat(buf, ").");
/*
if (f->val[2] == NA) { if (f->val[2] == NA) {
sprintf(dicebuf, " (%dd%d).", f->val[0], f->val[1]); sprintf(dicebuf, " (%dd%d).", f->val[0], f->val[1]);
} else { } else {
@ -2203,6 +2280,7 @@ void describeob(object_t *o) {
abs(f->val[2])); abs(f->val[2]));
} }
strcat(buf,dicebuf); strcat(buf,dicebuf);
*/
mvwprintw(mainwin, y, 0, "%s",buf); mvwprintw(mainwin, y, 0, "%s",buf);
y++; y++;
} else { } else {
@ -2330,6 +2408,18 @@ void describeob(object_t *o) {
y++; y++;
} }
f = hasflag(o->flags, F_WET);
if (f) {
mvwprintw(mainwin, y, 0, "It is wet.");
y++;
}
f = hasflag(o->flags, F_RUSTED);
if (f) {
mvwprintw(mainwin, y, 0, "It is rusty.");
y++;
}
f = hasflag(o->flags, F_ACTIVATED); f = hasflag(o->flags, F_ACTIVATED);
if (f) { if (f) {
mvwprintw(mainwin, y, 0, "It is activated."); mvwprintw(mainwin, y, 0, "It is activated.");
@ -2366,7 +2456,7 @@ void describeob(object_t *o) {
mvwprintw(mainwin, y, 0, "%s will detect nearby objects.", buf); y++; mvwprintw(mainwin, y, 0, "%s will detect nearby objects.", buf); y++;
break; break;
case F_DETECTMAGIC: case F_DETECTMAGIC:
mvwprintw(mainwin, y, 0, "%s will detect magical enchantemnts on objects.", buf); y++; mvwprintw(mainwin, y, 0, "%s will detect magical enchantments on objects.", buf); y++;
break; break;
case F_DETECTMETAL: case F_DETECTMETAL:
mvwprintw(mainwin, y, 0, "%s will detect nearby metal.", buf); y++; mvwprintw(mainwin, y, 0, "%s will detect nearby metal.", buf); y++;
@ -2374,6 +2464,15 @@ void describeob(object_t *o) {
case F_EXTRAINFO: case F_EXTRAINFO:
mvwprintw(mainwin, y, 0, "%s provides enhanced knowledge to you.", buf); y++; mvwprintw(mainwin, y, 0, "%s provides enhanced knowledge to you.", buf); y++;
break; break;
case F_EXTRADAM:
mvwprintw(mainwin, y, 0, "%s will cause you to deal more damage.", buf); y++;
break;
case F_EXTRALUCK:
mvwprintw(mainwin, y, 0, "%s will give you a bonus to all skill checks.", buf); y++;
break;
case F_EXTRAMP:
mvwprintw(mainwin, y, 0, "%s will increase your mana pool by %d%%.", buf, f->val[0]); y++;
break;
case F_FASTACT: case F_FASTACT:
mvwprintw(mainwin, y, 0, "%s will speed up your actions.", buf); y++; mvwprintw(mainwin, y, 0, "%s will speed up your actions.", buf); y++;
break; break;
@ -2968,7 +3067,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm) {
ch = f->val[0]; ch = f->val[0];
if (strlen(f->text)) { if (strlen(f->text)) {
o = addob(op, f->text); o = addobject(op, f->text, B_FALSE); // no stacking!
// remember letter // remember letter
o->letter = ch; o->letter = ch;
// make object fully known // make object fully known
@ -3004,6 +3103,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm) {
strcat(choices, temp); strcat(choices, temp);
// construct string // construct string
o = hasobletter(op, ch); o = hasobletter(op, ch);
// get the name of the object
getobname(o, obname, o->amt); getobname(o, obname, o->amt);
sprintf(buf, "%c - %s", ch, obname); sprintf(buf, "%c - %s", ch, obname);
sprintf(buf2, "%-60s$%d",buf,getobvalue(o)); sprintf(buf2, "%-60s$%d",buf,getobvalue(o));
@ -3204,6 +3304,8 @@ void dolook(cell_t *where) {
seensomething = B_TRUE; seensomething = B_TRUE;
} }
// writing here? // writing here?
if (where->writing && !isblind(player)) { if (where->writing && !isblind(player)) {
msg("There is a magical inscription here:"); msg("There is a magical inscription here:");
@ -3886,7 +3988,7 @@ void dorest(void) {
// can we rest? // can we rest?
if (canrest(player)) { if (canrest(player)) {
int willtrain = B_FALSE; int willtrain = B_FALSE;
if (player->skillpoints) { if (player->skillpoints || lfhasflag(player, F_STATGAINREADY)) {
int ch; int ch;
ch = askchar("Would you like to train your skills?","yn","y", B_TRUE); ch = askchar("Would you like to train your skills?","yn","y", B_TRUE);
if (ch == 'y') { if (ch == 'y') {
@ -4016,6 +4118,11 @@ void dothrow(obpile_t *op) {
object_t *o; object_t *o;
char buf[BUFLEN],buf2[BUFLEN]; char buf[BUFLEN],buf2[BUFLEN];
if (!hasbp(player, BP_HANDS)) {
msg("You have no hands to throw with!");
return;
}
// ask which object to throw // ask which object to throw
o = askobject(op, "Throw what", NULL, AO_NONE); o = askobject(op, "Throw what", NULL, AO_NONE);
if (o) { if (o) {
@ -4131,48 +4238,58 @@ int downline(int *y, int h, char *heading, char *subheading, char *bottomstring,
// draw a cell which we remember, but can't see // draw a cell which we remember, but can't see
void drawunviscell(cell_t *cell, int x, int y) { void drawunviscell(cell_t *cell, int x, int y) {
char glyph; glyph_t glyph;
object_t *o; object_t *o;
if (cell->type->glyph == '.') {
glyph = ' '; // copy from cell
} else { glyph = cell->type->glyph;
glyph = cell->type->glyph;
if (glyph.ch == '.') {
glyph.ch = ' ';
} }
// show staircases... // show staircases...
o = hasobwithflag(cell->obpile, F_CLIMBABLE); o = hasobwithflag(cell->obpile, F_CLIMBABLE);
if (o) { if (o) {
glyph = getglyph(o); glyph = *(getglyph(o));
} }
// show dungeon features // show dungeon features
o = hasobofclass(cell->obpile, OC_DFEATURE); o = hasobofclass(cell->obpile, OC_DFEATURE);
if (o) { if (o) {
glyph = getglyph(o); glyph = *(getglyph(o));
} }
mvwprintw(gamewin, y, x, "%c", glyph); //mvwprintw(gamewin, y, x, "%c", glyph);
drawglyph(&glyph, x, y);
}
void drawglyph(glyph_t *g, int x, int y) {
int col;
col = g->colour;
setcol(gamewin, g->colour);
mvwprintw(gamewin, y, x, "%c", g->ch);
unsetcol(gamewin, g->colour);
} }
void drawcell(cell_t *cell, int x, int y) { void drawcell(cell_t *cell, int x, int y) {
// draw ground drawglyph(&cell->type->glyph, x, y);
mvwprintw(gamewin, y, x, "%c", cell->type->glyph);
} }
// draw a cell that we have LOS to. // draw a cell that we have LOS to.
void drawcellwithcontents(cell_t *cell, int x, int y) { void drawcellwithcontents(cell_t *cell, int x, int y) {
if (cell->lf && cansee(player, cell->lf)) { // lifeform here that we can see if (cell->lf && cansee(player, cell->lf)) { // lifeform here that we can see
char ch; glyph_t *gl;
// draw the lf's race glyph // draw the lf's race glyph
ch = getlfglyph(cell->lf); gl = getlfglyph(cell->lf);
mvwprintw(gamewin, y, x, "%c", ch); drawglyph(gl, x, y);
return; return;
} else { } else {
void *thing; void *thing;
char glyph; glyph_t glyph;
// scanned lf here? // scanned lf here?
if (isinscanrange(cell, &thing, NULL, &glyph) == TT_MONSTER) { if (isinscanrange(cell, &thing, NULL, &glyph) == TT_MONSTER) {
//mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph); //mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph);
mvwprintw(gamewin, y, x, "%c", glyph); drawglyph(&glyph, x, y);
return; return;
} }
} }
@ -4183,12 +4300,13 @@ void drawcellwithcontents(cell_t *cell, int x, int y) {
// draw highest object in sort order // draw highest object in sort order
o = gettopobject(cell); o = gettopobject(cell);
if (o) { if (o) {
mvwprintw(gamewin, y, x, "%c", getglyph(o)); drawglyph(getglyph(o), x, y);
} else { } else {
// should never happen. if it does, just show the // should never happen. if it does, just show the
// first object // first object
dblog("Warn: sorted object glyph drawing matching nothing!"); dblog("Warn: sorted object glyph drawing matching nothing!");
mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph); //mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph);
drawglyph(&cell->obpile->first->type->obclass->glyph, x, y);
} }
} else { } else {
// draw cell normally // draw cell normally
@ -4217,7 +4335,7 @@ void drawlevelfor(lifeform_t *lf) {
if (cell) { if (cell) {
void *thing; void *thing;
char desc[BUFLEN]; char desc[BUFLEN];
char glyph; glyph_t glyph;
if (haslos(lf, cell)) { if (haslos(lf, cell)) {
drawcellwithcontents(cell, x-viewx, y-viewy); drawcellwithcontents(cell, x-viewx, y-viewy);
} else { } else {
@ -4225,7 +4343,7 @@ void drawlevelfor(lifeform_t *lf) {
switch (isinscanrange(cell, &thing, desc, &glyph)) { switch (isinscanrange(cell, &thing, desc, &glyph)) {
case TT_MONSTER: case TT_MONSTER:
case TT_OBJECT: case TT_OBJECT:
mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph); drawglyph(&glyph, x, y);
break; break;
default: default:
if (cell->known) { if (cell->known) {
@ -4254,11 +4372,33 @@ void initgfx(void) {
int msgwinh = 2; int msgwinh = 2;
int statwinh = 2; int statwinh = 2;
mainwin = initscr(); mainwin = initscr();
// colour setup
if (!has_colors()) { if (!has_colors()) {
printf("Terminal does not support colour.\n"); printf("Terminal does not support colour.\n");
hascolour = B_FALSE;
exit(1); exit(1);
} }
start_color(); start_color();
init_pair(C_BLACK, COLOR_BLACK, COLOR_BLACK);
init_pair(C_RED, COLOR_RED, COLOR_BLACK);
init_pair(C_GREEN, COLOR_GREEN, COLOR_BLACK);
init_pair(C_BROWN, COLOR_YELLOW, COLOR_BLACK);
init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK);
init_pair(C_BLUE, COLOR_BLUE, COLOR_BLACK);
init_pair(C_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
init_pair(C_CYAN, COLOR_CYAN, COLOR_BLACK);
init_pair(C_GREY, COLOR_WHITE, COLOR_BLACK);
init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK);
init_pair(C_WHITE, COLOR_WHITE, COLOR_BLACK);
init_pair(C_BOLDCYAN, COLOR_CYAN, COLOR_BLACK);
init_pair(C_BOLDBLUE, COLOR_BLUE, COLOR_BLACK);
init_pair(C_BOLDMAGENTA, COLOR_MAGENTA, COLOR_BLACK);
init_pair(C_BOLDGREEN, COLOR_GREEN, COLOR_BLACK);
init_pair(C_ORANGE, COLOR_RED, COLOR_BLACK);
noecho(); noecho();
cbreak(); cbreak();
nodelay(mainwin, FALSE); nodelay(mainwin, FALSE);
@ -4709,10 +4849,21 @@ void handleinput(void) {
f = hasflag(player->flags, F_RUNNING); f = hasflag(player->flags, F_RUNNING);
if (f) { if (f) {
int dir; int dir;
int hasgettableobs = B_FALSE;
dir = f->val[0]; dir = f->val[0];
object_t *o;
for (o = player->cell->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP)) {
hasgettableobs = B_TRUE;
break;
}
}
// something here? // something here?
if (player->cell->obpile->first) { if (hasgettableobs) {
stoprunning(player); stoprunning(player);
} else if (!canmove(player, dir, NULL)) { // can't move anymore? } else if (!canmove(player, dir, NULL)) { // can't move anymore?
stoprunning(player); stoprunning(player);
@ -5152,6 +5303,8 @@ void msg_real(char *format, ... ) {
if (db) dblog("adding to msgbuf: [%s]",buf); if (db) dblog("adding to msgbuf: [%s]",buf);
assert(!strchr(buf, '#'));
// ie. can the message buffer fit: // ie. can the message buffer fit:
// what is already there + 2 spaces + the new text + '--more--' ? // what is already there + 2 spaces + the new text + '--more--' ?
//if (strlen(msgbuf) + 2 + strlen(buf) + strlen(MORESTRING) >= SCREENW) { //if (strlen(msgbuf) + 2 + strlen(buf) + strlen(MORESTRING) >= SCREENW) {
@ -5177,6 +5330,21 @@ void msg_real(char *format, ... ) {
} }
int needsbold(enum COLOUR col) {
switch (col) {
case C_YELLOW:
case C_WHITE:
case C_BOLDCYAN:
case C_BOLDBLUE:
case C_BOLDMAGENTA:
case C_BOLDGREEN:
case C_ORANGE:
return B_TRUE;
default:
break;
}
return B_FALSE;
}
void nothinghappens(void) { void nothinghappens(void) {
msg("Nothing seems to happen."); msg("Nothing seems to happen.");
@ -5198,40 +5366,78 @@ void drawstatus(void) {
wclear(statwin); wclear(statwin);
xpleft = getxpforlev(player->level + 1) - player->xp; xpleft = getxpforlev(player->level + 1) - player->xp;
sprintf(buf, "[%-26s] Lv:%d Next:%ld", pname, sprintf(buf, "[%-26s] Lv:%d", pname,
player->level, xpleft); player->level);
mvwprintw(statwin, 0, 0, buf);
if ((player->skillpoints == 0) && (getattpoints(player) == 0)) {
wprintw(statwin, " Next:%ld",xpleft);
} else {
setcol(statwin, C_BOLDGREEN);
wprintw(statwin, " LevUp",xpleft);
unsetcol(statwin, C_BOLDGREEN);
}
// blinded?
if (isblind(player)) {
setcol(statwin, C_RED);
wprintw(statwin, " Blind");
unsetcol(statwin, C_RED);
}
// paralysed somehow? // paralysed somehow?
if (isimmobile(player)) { if (isimmobile(player)) {
strcat(buf, " Immobile"); setcol(statwin, C_RED);
wprintw(statwin, " Immobile");
unsetcol(statwin, C_RED);
} else { } else {
// show player action speed // show player action speed
getspeedname(getactspeed(player), buf2); getspeedname(getactspeed(player), buf2);
if (strcmp(buf2, "normal")) { if (strcmp(buf2, "normal")) {
strcat(buf, " Act:"); enum COLOUR col;
if (getactspeed(player) < SP_NORMAL) {
col = C_GREEN;
} else {
col = C_RED;
}
setcol(statwin, col);
wprintw(statwin, " Act:");
capitaliseall(buf2); capitaliseall(buf2);
strcat(buf, buf2); wprintw(statwin, "%s", buf2);
unsetcol(statwin, col);
} }
// show player movement speed // show player movement speed
getspeedname(getmovespeed(player), buf2); getspeedname(getmovespeed(player), buf2);
if (strcmp(buf2, "normal")) { if (strcmp(buf2, "normal")) {
strcat(buf, " Mv:"); enum COLOUR col;
if (getmovespeed(player) < SP_NORMAL) {
col = C_GREEN;
} else {
col = C_RED;
}
setcol(statwin, col);
wprintw(statwin, " Mv:");
capitaliseall(buf2); capitaliseall(buf2);
strcat(buf, buf2); wprintw(statwin, "%s", buf2);
unsetcol(statwin, col);
} }
} }
// burdened somehow? // burdened somehow?
switch (isburdened(player)) { switch (isburdened(player)) {
case BR_BURDENED: case BR_BURDENED:
strcat(buf, " Burdened"); setcol(statwin, C_BROWN);
wprintw(statwin, " Burdened");
unsetcol(statwin, C_BROWN);
break; break;
case BR_STRAINED: case BR_STRAINED:
strcat(buf, " Strained"); setcol(statwin, C_RED);
wprintw(statwin, " Strained");
unsetcol(statwin, C_RED);
break; break;
case BR_OVERLOADED: case BR_OVERLOADED:
strcat(buf, " Overloaded"); setcol(statwin, C_YELLOW);
wprintw(statwin, " Overloaded");
unsetcol(statwin, C_YELLOW);
break; break;
default: default:
break; break;
@ -5239,11 +5445,12 @@ void drawstatus(void) {
// show certain flags // show certain flags
if (lfhasflag(player, F_POISONED)) { if (lfhasflag(player, F_POISONED)) {
strcat(buf, " Poisoned"); setcol(statwin, C_GREEN);
wprintw(statwin, " Poisoned");
unsetcol(statwin, C_GREEN);
} }
mvwprintw(statwin, 0, 0, buf); //mvwprintw(statwin, 0, 0, buf);
f = hasflag(player->flags, F_HUNGER); f = hasflag(player->flags, F_HUNGER);
if (f) { if (f) {
@ -5260,7 +5467,9 @@ void drawstatus(void) {
} }
if (strlen(buf2) > 0) { if (strlen(buf2) > 0) {
setcol(statwin, C_BROWN);
wprintw(statwin, " %s", buf2); wprintw(statwin, " %s", buf2);
unsetcol(statwin, C_BROWN);
} }
// construct waiting string // construct waiting string
@ -5419,6 +5628,19 @@ void redraw(void) {
wrefresh(gamewin); wrefresh(gamewin);
} }
void setcol(WINDOW *win, enum COLOUR col) {
if (needsbold(col)) {
wattron(win, A_BOLD);
}
wattron(win, COLOR_PAIR(col));
}
void unsetcol(WINDOW *win, enum COLOUR col) {
wattroff(win, COLOR_PAIR(col));
if (needsbold(col)) {
wattroff(win, A_BOLD);
}
}
void showlfarmour(lifeform_t *lf) { void showlfarmour(lifeform_t *lf) {
enum BODYPART bp; enum BODYPART bp;
object_t *o; object_t *o;
@ -5598,12 +5820,7 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
if (isplayer(lf)) { if (isplayer(lf)) {
int attpoints; int attpoints;
f = lfhasflag(lf, F_STATGAINREADY); attpoints = getattpoints(lf);
if (f) {
attpoints = f->val[2];
} else {
attpoints = 0;
}
mvwprintw(mainwin, y, 0, ftext, "Training"); mvwprintw(mainwin, y, 0, ftext, "Training");
if ((lf->skillpoints == 0) && (attpoints == 0)) { if ((lf->skillpoints == 0) && (attpoints == 0)) {
wprintw(mainwin, "n/a"); wprintw(mainwin, "n/a");
@ -6122,8 +6339,13 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
f = lfhasknownflag(lf, F_SPRINTING); f = lfhasknownflag(lf, F_SPRINTING);
if (f) { if (f) {
mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is"); if (f->val[0]) {
y++; mvwprintw(mainwin, y, 0, "%s %s sprinting.", you(lf), isplayer(lf) ? "are" : "is");
y++;
} else {
mvwprintw(mainwin, y, 0, "%s %s exhausted.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
} }
@ -6155,7 +6377,6 @@ void showlfstats(lifeform_t *lf, int showall) {
strcat(expirebuf, ",after grab"); strcat(expirebuf, ",after grab");
} }
if (strlen(expirebuf)) { if (strlen(expirebuf)) {
sprintf(eb2,"(%s)",expirebuf); sprintf(eb2,"(%s)",expirebuf);
} else { } else {
@ -6351,6 +6572,61 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s automatically detect nearby objects.", you(lf)); mvwprintw(mainwin, y, 0, "%s automatically detect nearby objects.", you(lf));
y++; y++;
} }
// extra dam - can have it multiple times
for (f = lf->flags->first ; f; f = f->next) {
if (f->id == F_EXTRADAM) {
int ndice,nsides,bonus;
char dicebuf[BUFLEN];
char mmbuf[BUFLEN];
char damtypebuf[BUFLEN];
int min = 0,max = 0;
texttodice(f->text, &ndice,&nsides,&bonus);
if ((f->lifetime == FROMOBEQUIP) ||
(f->lifetime == FROMOBHOLD) ||
(f->lifetime == FROMOBACTIVATE) ) {
object_t *obfrom;
obfrom = findobbyid(lf->pack, f->obfrom);
if (obfrom) {
int bonusdam;
sumflags(obfrom->flags, F_BONUS, &bonusdam, NULL, NULL);
bonus += bonusdam;
}
}
if (f->val[0] == NA) {
strcpy(damtypebuf, "damage");
} else {
sprintf(damtypebuf, "%s damage", getdamname(f->val[0]));
}
dicetotext(ndice, nsides, bonus, &min, &max, dicebuf, mmbuf);
if (strcmp(dicebuf, mmbuf)) {
mvwprintw(mainwin, y, 0, "%s deal%s %s (%s) extra %s each hit.", you(lf),
isplayer(lf) ? "" : "s", dicebuf, mmbuf, damtypebuf);
} else {
mvwprintw(mainwin, y, 0, "%s deal%s %s extra %s each hit.", you(lf),
isplayer(lf) ? "" : "s", dicebuf, damtypebuf);
}
y++;
}
}
f = lfhasknownflag(lf, F_EXTRALUCK);
if (f) {
mvwprintw(mainwin, y, 0, "Your luck is being boosted.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_EXTRAMP);
if (f) {
mvwprintw(mainwin, y, 0, "Your mana pool is being boosted.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_EXTRAINFO); f = lfhasknownflag(lf, F_EXTRAINFO);
if (f && (f->known)) { if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf)); mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf));

10
io.h
View File

@ -4,9 +4,9 @@ void addchoice(prompt_t *p, char ch, char *text, char *desc, void *data);
void addheading(prompt_t *p, char *text); void addheading(prompt_t *p, char *text);
void addmsghist(char *text); void addmsghist(char *text);
void addpromptq(prompt_t *p, char *q); void addpromptq(prompt_t *p, char *q);
void anim(cell_t *src, cell_t *dst, char ch); void anim(cell_t *src, cell_t *dst, char ch, int colour);
void animradial(cell_t *src, int radius, char ch); void animradial(cell_t *src, int radius, char ch, int colour);
void animradialorth(cell_t *src, int radius, char ch); void animradialorth(cell_t *src, int radius, char ch, int colour);
//void announceob(enum OBTYPE oid); //void announceob(enum OBTYPE oid);
int announceflaggain(lifeform_t *lf, flag_t *f); int announceflaggain(lifeform_t *lf, flag_t *f);
int announceflagloss(lifeform_t *lf, flag_t *f); int announceflagloss(lifeform_t *lf, flag_t *f);
@ -62,6 +62,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm);
int dowear(obpile_t *op); int dowear(obpile_t *op);
int doweild(obpile_t *op); int doweild(obpile_t *op);
int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar); int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar);
void drawglyph(glyph_t *g, int x, int y);
void drawunviscell(cell_t *cell, int x, int y); void drawunviscell(cell_t *cell, int x, int y);
void drawcellwithcontents(cell_t *cell, int x, int y); void drawcellwithcontents(cell_t *cell, int x, int y);
void drawcursor(void); void drawcursor(void);
@ -84,10 +85,13 @@ void warn(char *format, ... );
void msg(char *format, ... ); void msg(char *format, ... );
void msgnocap(char *format, ... ); void msgnocap(char *format, ... );
void msg_real(char *format, ... ); void msg_real(char *format, ... );
int needsbold(enum COLOUR col);
void nothinghappens(void); void nothinghappens(void);
void dblog(char *format, ... ); void dblog(char *format, ... );
void redraw(void); void redraw(void);
int savequit(void); int savequit(void);
void setcol(WINDOW *win, enum COLOUR col);
void unsetcol(WINDOW *win, enum COLOUR col);
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 tombstone(lifeform_t *lf); void tombstone(lifeform_t *lf);

693
lf.c

File diff suppressed because it is too large Load Diff

7
lf.h
View File

@ -3,7 +3,7 @@
lifeform_t *addlf(cell_t *cell, enum RACE rid, int level); lifeform_t *addlf(cell_t *cell, enum RACE rid, int level);
lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller); lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller);
job_t *addjob(enum JOB id, char *name); job_t *addjob(enum JOB id, char *name);
race_t *addrace(enum RACE id, char *name, float weight, char glyph, enum MATERIAL mat); race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat);
skill_t *addskill(enum SKILL id, char *name, char *desc); skill_t *addskill(enum SKILL id, char *name, char *desc);
void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype); void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype);
int areallies(lifeform_t *lf1, lifeform_t *lf2); int areallies(lifeform_t *lf1, lifeform_t *lf2);
@ -55,6 +55,7 @@ enum ALLEGIENCE getallegiance(lifeform_t *lf);
object_t *getarmour(lifeform_t *lf, enum BODYPART bp); object_t *getarmour(lifeform_t *lf, enum BODYPART bp);
int getarmourrating(lifeform_t *lf); int getarmourrating(lifeform_t *lf);
int getattackspeed(lifeform_t *lf); int getattackspeed(lifeform_t *lf);
int getattpoints(lifeform_t *lf);
int getattr(lifeform_t *lf, enum ATTRIB attr); int getattr(lifeform_t *lf, enum ATTRIB attr);
int getevasion(lifeform_t *lf); int getevasion(lifeform_t *lf);
object_t *getbestthrowmissile(lifeform_t *lf); object_t *getbestthrowmissile(lifeform_t *lf);
@ -79,7 +80,7 @@ enum LFCONDITION getlfcondition(lifeform_t *lf);
int getnightvisrange(lifeform_t *lf); int getnightvisrange(lifeform_t *lf);
char *getlfconditionname(enum LFCONDITION cond); char *getlfconditionname(enum LFCONDITION cond);
char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer); char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer);
char getlfglyph(lifeform_t *lf); glyph_t *getlfglyph(lifeform_t *lf);
enum MATERIAL getlfmaterial(lifeform_t *lf); enum MATERIAL getlfmaterial(lifeform_t *lf);
float getmaxcarryweight(lifeform_t *lf); float getmaxcarryweight(lifeform_t *lf);
float getmaxliftweight(lifeform_t *lf); float getmaxliftweight(lifeform_t *lf);
@ -100,6 +101,7 @@ float getlfweight(lifeform_t *lf, int withobs);
int getspellspeed(lifeform_t *lf); int getspellspeed(lifeform_t *lf);
char *getplayername(char *buf); char *getplayername(char *buf);
char *getplayernamefull(char *buf); char *getplayernamefull(char *buf);
int getracerarity(enum RACE rid);
object_t *getrandomarmour(lifeform_t *lf); object_t *getrandomarmour(lifeform_t *lf);
//int getrandommonlevel(int depth); //int getrandommonlevel(int depth);
race_t *getrandomrace(map_t *map); race_t *getrandomrace(map_t *map);
@ -173,6 +175,7 @@ float modifybystat(float num, lifeform_t *lf, enum ATTRIB att);
void noise(cell_t *c, lifeform_t *noisemaker, char *text, char *seetext); void noise(cell_t *c, lifeform_t *noisemaker, char *text, char *seetext);
void outfitlf(lifeform_t *lf); void outfitlf(lifeform_t *lf);
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground); int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground);
void practice(lifeform_t *lf, enum SKILL skid);
void precalclos(lifeform_t *lf); void precalclos(lifeform_t *lf);
int push(lifeform_t *lf, object_t *o, int dir); int push(lifeform_t *lf, object_t *o, int dir);
void relinklf(lifeform_t *src, map_t *dst); void relinklf(lifeform_t *src, map_t *dst);

589
log.txt
View File

@ -7,9 +7,13 @@ xxx
xxx xxx
xxx xxx
xxx xxx
xxx
xxx
xxx
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -18,10 +22,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -30,10 +35,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -42,10 +48,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -54,10 +61,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -66,10 +74,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -78,10 +87,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -90,10 +100,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -102,10 +113,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -114,10 +126,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -126,10 +139,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -138,10 +152,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -150,10 +165,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -162,10 +178,11 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
@ -174,124 +191,436 @@ finding random lf with rarity val 85-100
-> possibility: brown snake, rarity=85 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
rollhitdice() - rolling 2d4 + 2 rollhitdice() - rolling 2d4 + 2
rollhitdice() - mod is +-5% rollhitdice() - mod is +-5%
rollhitdice() ---- die 1/2 == 5 rollhitdice() ---- die 1/2 == 4
rollhitdice() ---- die 2/2 == 6 rollhitdice() ---- die 2/2 == 4
TOTAL: 11 TOTAL: 8
-> modified to: 11 -> modified to: 8
givejob() starting. givejob() starting.
processing normal flag: 186 processing normal flag: 191
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 145 processing normal flag: 149
processing normal flag: 146 processing normal flag: 150
processing normal flag: 146 processing normal flag: 150
processing normal flag: 146 processing normal flag: 150
processing normal flag: 146 processing normal flag: 150
processing normal flag: 146 processing normal flag: 150
processing normal flag: 213 processing normal flag: 150
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 213 processing normal flag: 219
processing normal flag: 212 processing normal flag: 219
processing normal flag: 212 processing normal flag: 219
processing normal flag: 212 processing normal flag: 219
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
processing normal flag: 212 processing normal flag: 218
fireat(): dam = throwdam(2) * speed(2) = 4 processing normal flag: 218
AIMOVE: something processing normal flag: 218
.oO { looking for covetted objects... } processing normal flag: 218
.oO { no targetcell, so looking for remote objects } processing normal flag: 218
.oO { didn't find any obs i want } processing normal flag: 218
.oO { i have a target... } processing normal flag: 218
.oO { my target is lfid 31 (human). } processing normal flag: 218
.oO { i cannot see my target. moving to last known loc 12/15 } nclasses is 0
.oO { something going to targecell: 12, 15 } nclasses is 0
.oO { walking from 12,17 towards f_targetcell (12,15) ... } nclasses is 0
.oO { successfully walked towards f_targetcell. } nclasses is 0
AIMOVE: something nclasses is 0
.oO { looking for covetted objects... } nclasses is 0
.oO { didn't find any obs i want } initial dam[0] = 1
.oO { walking from 11,18 towards f_targetcell (12,15) ... } adjusted for lf to dam[0] = 1
.oO { successfully walked towards f_targetcell. } reduced by armour to dam[0] = 0
initial dam[0] = 1
adjusted for lf to dam[0] = 1
reduced by armour to dam[0] = 0
initial dam[0] = 26
heavy blow makes dam[0] = 39
adjusted for lf to dam[0] = 39
reduced by armour to dam[0] = 39
initial dam[1] = 10
heavy blow makes dam[1] = 15
adjusted for lf to dam[1] = 15
reduced by armour to dam[1] = 15
nclasses is 0
nclasses is 0
initial dam[0] = 19
heavy blow makes dam[0] = 28
adjusted for lf to dam[0] = 28
reduced by armour to dam[0] = 23
initial dam[1] = 6
heavy blow makes dam[1] = 9
adjusted for lf to dam[1] = 4
reduced by armour to dam[1] = 3
nclasses is 0
nclasses is 0
initial dam[0] = 2
adjusted for lf to dam[0] = 2
reduced by armour to dam[0] = 1
initial dam[0] = 0
adjusted for lf to dam[0] = 0
reduced by armour to dam[0] = 0
initial dam[0] = 2
adjusted for lf to dam[0] = 2
reduced by armour to dam[0] = 1
initial dam[0] = 4
adjusted for lf to dam[0] = 4
reduced by armour to dam[0] = 2
initial dam[0] = 1
adjusted for lf to dam[0] = 1
reduced by armour to dam[0] = 0
initial dam[0] = 2
adjusted for lf to dam[0] = 2
reduced by armour to dam[0] = 1
initial dam[0] = 2
adjusted for lf to dam[0] = 2
reduced by armour to dam[0] = 1
initial dam[0] = 30
heavy blow makes dam[0] = 45
adjusted for lf to dam[0] = 45
reduced by armour to dam[0] = 45
initial dam[1] = 3
heavy blow makes dam[1] = 4
adjusted for lf to dam[1] = 4
reduced by armour to dam[1] = 4
rollhitdice() - rolling 49d4 + 0
rollhitdice() - mod is +22%
rollhitdice() ---- die 1/49 == 1
rollhitdice() ---- die 2/49 == 1
rollhitdice() ---- die 3/49 == 2
rollhitdice() ---- die 4/49 == 2
rollhitdice() ---- die 5/49 == 4
rollhitdice() ---- die 6/49 == 2
rollhitdice() ---- die 7/49 == 3
rollhitdice() ---- die 8/49 == 4
rollhitdice() ---- die 9/49 == 4
rollhitdice() ---- die 10/49 == 2
rollhitdice() ---- die 11/49 == 1
rollhitdice() ---- die 12/49 == 3
rollhitdice() ---- die 13/49 == 1
rollhitdice() ---- die 14/49 == 1
rollhitdice() ---- die 15/49 == 4
rollhitdice() ---- die 16/49 == 1
rollhitdice() ---- die 17/49 == 3
rollhitdice() ---- die 18/49 == 3
rollhitdice() ---- die 19/49 == 4
rollhitdice() ---- die 20/49 == 4
rollhitdice() ---- die 21/49 == 1
rollhitdice() ---- die 22/49 == 4
rollhitdice() ---- die 23/49 == 1
rollhitdice() ---- die 24/49 == 3
rollhitdice() ---- die 25/49 == 3
rollhitdice() ---- die 26/49 == 1
rollhitdice() ---- die 27/49 == 2
rollhitdice() ---- die 28/49 == 2
rollhitdice() ---- die 29/49 == 4
rollhitdice() ---- die 30/49 == 1
rollhitdice() ---- die 31/49 == 1
rollhitdice() ---- die 32/49 == 1
rollhitdice() ---- die 33/49 == 3
rollhitdice() ---- die 34/49 == 1
rollhitdice() ---- die 35/49 == 4
rollhitdice() ---- die 36/49 == 3
rollhitdice() ---- die 37/49 == 2
rollhitdice() ---- die 38/49 == 3
rollhitdice() ---- die 39/49 == 3
rollhitdice() ---- die 40/49 == 3
rollhitdice() ---- die 41/49 == 4
rollhitdice() ---- die 42/49 == 1
rollhitdice() ---- die 43/49 == 2
rollhitdice() ---- die 44/49 == 2
rollhitdice() ---- die 45/49 == 1
rollhitdice() ---- die 46/49 == 3
rollhitdice() ---- die 47/49 == 3
rollhitdice() ---- die 48/49 == 1
rollhitdice() ---- die 49/49 == 2
TOTAL: 115
-> modified to: 140
initial dam[0] = 0
adjusted for lf to dam[0] = 0
reduced by armour to dam[0] = 0
initial dam[0] = 19
heavy blow makes dam[0] = 28
adjusted for lf to dam[0] = 28
reduced by armour to dam[0] = 28
initial dam[1] = 11
heavy blow makes dam[1] = 16
adjusted for lf to dam[1] = 16
reduced by armour to dam[1] = 16
nclasses is 1

34
map.c
View File

@ -17,6 +17,8 @@ extern map_t *firstmap,*lastmap;
extern int viewx,viewy,vieww,viewh; extern int viewx,viewy,vieww,viewh;
extern lifeform_t *player; extern lifeform_t *player;
extern glyph_t tempglyph;
extern enum OBCLASS sortorder[]; extern enum OBCLASS sortorder[];
cell_t *addcell(map_t *m, int x, int y) { cell_t *addcell(map_t *m, int x, int y) {
@ -1493,7 +1495,7 @@ printf("dump of map '%s' (%d x %d):\n",map->name, map->w, map->h);
for (y = 0; y < map->h; y++) { for (y = 0; y < map->h; y++) {
for (x = 0; x < map->w; x++) { for (x = 0; x < map->w; x++) {
cell = getcellat(map, x, y); cell = getcellat(map, x, y);
printf("%c",cell->type->glyph); printf("%c",cell->type->glyph.ch);
} }
printf("\n"); printf("\n");
} }
@ -1501,7 +1503,8 @@ printf("dump of map '%s' (%d x %d):\n",map->name, map->w, map->h);
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int wantannounce) { void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int wantannounce) {
int x,y; int x,y;
animradial(c, range, '}');
animradial(c, range, '}', C_RED);
if (haslos(player, c)) { if (haslos(player, c)) {
if (wantannounce) { if (wantannounce) {
@ -1529,7 +1532,7 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int
if (cc && (getcelldist(c, cc) <= (range+1))) { if (cc && (getcelldist(c, cc) <= (range+1))) {
if (cc->lf && !isdead(cc->lf)) { if (cc->lf && !isdead(cc->lf)) {
// move away from centre of explosion // move away from centre of explosion
knockback(cc->lf, getdiraway(cc, c, B_FALSE, DT_COMPASS), 2, NULL); knockback(cc->lf, getdiraway(cc, c, NULL, B_FALSE, DT_COMPASS), 2, NULL);
} }
} }
} }
@ -1974,7 +1977,7 @@ int isempty(cell_t *c) {
} }
//returns TT_ based on what you can scan there //returns TT_ based on what you can scan there
int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) { int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
flag_t *f; flag_t *f;
// handle scanner // handle scanner
f = lfhasflag(player, F_DETECTLIFE); f = lfhasflag(player, F_DETECTLIFE);
@ -1989,7 +1992,8 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) {
} }
if (glyph) { if (glyph) {
// select glyph based on size // select glyph based on size
*glyph = '0' + ((int) getlfsize(c->lf)); glyph->ch = '0' + ((int) getlfsize(c->lf));
glyph->colour = C_GREY;
} }
return TT_MONSTER; return TT_MONSTER;
} }
@ -2000,7 +2004,10 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) {
if (getcelldistorth(player->cell, c) <= f->val[0]) { if (getcelldistorth(player->cell, c) <= f->val[0]) {
if (c->lf && ismetal(c->lf->race->material->id) ) { if (c->lf && ismetal(c->lf->race->material->id) ) {
*thing = c->lf; *thing = c->lf;
if (glyph) *glyph = '*'; if (glyph) {
glyph->ch = '*';
glyph->colour = C_GREY;
}
if (desc) sprintf(desc, "something metallic"); if (desc) sprintf(desc, "something metallic");
return TT_MONSTER; return TT_MONSTER;
} else { } else {
@ -2008,7 +2015,10 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) {
for (o = c->obpile->first ; o ; o = o->next) { for (o = c->obpile->first ; o ; o = o->next) {
if (ismetal(o->material->id)) { if (ismetal(o->material->id)) {
*thing = o; *thing = o;
if (glyph) *glyph = '*'; if (glyph) {
glyph->ch = '*';
glyph->colour = C_GREY;
}
if (desc) sprintf(desc, "something metallic"); if (desc) sprintf(desc, "something metallic");
return TT_OBJECT; return TT_OBJECT;
} }
@ -2023,7 +2033,10 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) {
for (o = c->obpile->first ; o ; o = o->next) { for (o = c->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP) && !hasflag(o->flags, F_DOOR)) { if (!hasflag(o->flags, F_NOPICKUP) && !hasflag(o->flags, F_DOOR)) {
*thing = o; *thing = o;
if (glyph) *glyph = '*'; if (glyph) {
glyph->ch = '*';
glyph->colour = C_GREY;
}
if (desc) sprintf(desc, "an object"); if (desc) sprintf(desc, "an object");
return TT_OBJECT; return TT_OBJECT;
} }
@ -2139,6 +2152,11 @@ void makelit(cell_t *c, enum LIGHTLEV how, int howlong) {
if (how == L_TEMP) { if (how == L_TEMP) {
//if ((c->lit == L_PERMLIGHT) || (c->lit == L_PERMDARK)) { //if ((c->lit == L_PERMLIGHT) || (c->lit == L_PERMDARK)) {
if (c->lit == L_PERMLIGHT) { if (c->lit == L_PERMLIGHT) {
// light sources can't override permenant light
return;
}
if (c->lit == L_PERMDARK) {
// light sources can't override darkness spell
return; return;
} }
} }

2
map.h
View File

@ -43,7 +43,7 @@ int isadjacent(cell_t *src, cell_t *dst);
int isdiggable(cell_t *c); int isdiggable(cell_t *c);
int isdoor(object_t *o, int *isopen); int isdoor(object_t *o, int *isopen);
int isempty(cell_t *c); int isempty(cell_t *c);
int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph); int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph);
int islit(cell_t *c); int islit(cell_t *c);
int isloopdirok(cell_t *cell, int dir); int isloopdirok(cell_t *cell, int dir);
int isnewcellok(cell_t *cell, char *err); int isnewcellok(cell_t *cell, char *err);

214
move.c
View File

@ -46,11 +46,6 @@ int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
rdata = NULL; rdata = NULL;
} }
if (lfhasflag(lf, F_GRAVBOOSTED)) {
if (error) *error = E_GRAVBOOSTED;
return B_FALSE;
}
if (isburdened(lf) >= BR_OVERLOADED) { if (isburdened(lf) >= BR_OVERLOADED) {
if (error) *error = E_TOOHEAVY; if (error) *error = E_TOOHEAVY;
return B_FALSE; return B_FALSE;
@ -122,7 +117,7 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
} }
// obvious things that you can see // obvious things that you can see
if (!onlyifknown || haslos(lf, cell)) { if (!onlyifknown || (haslos(lf, cell) && !lfhasflag(lf, F_UNDEAD))) {
for (o = cell->obpile->first ; o ; o = o->next) { for (o = cell->obpile->first ; o ; o = o->next) {
f = hasflag(o->flags, F_WALKDAM); f = hasflag(o->flags, F_WALKDAM);
if (f) { if (f) {
@ -144,7 +139,9 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
} else { } else {
iq = getiqname(getattr(lf, A_IQ), NULL); iq = getiqname(getattr(lf, A_IQ), NULL);
if ((iq >= IQ_AVERAGE) && haslos(lf, cell)) { if ((iq >= IQ_AVERAGE) && haslos(lf, cell)) {
include_nonobvious = B_TRUE; if (!lfhasflag(lf, F_UNDEAD)) {
include_nonobvious = B_TRUE;
}
} }
} }
if (include_nonobvious) { if (include_nonobvious) {
@ -201,12 +198,24 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
// ok // ok
} else { } else {
rdata = o; rdata = o;
if (error) *error = E_OBINWAY; if (error) {
if (isdoor(o, NULL)) {
*error = E_DOORINWAY;
} else {
*error = E_OBINWAY;
}
}
return B_FALSE; return B_FALSE;
} }
} else { } else {
rdata = o; rdata = o;
if (error) *error = E_OBINWAY; if (error) {
if (isdoor(o, NULL)) {
*error = E_DOORINWAY;
} else {
*error = E_OBINWAY;
}
}
return B_FALSE; return B_FALSE;
} }
} }
@ -297,13 +306,14 @@ void dorandommove(lifeform_t *lf, int badmovesok) {
// src is where something is // src is where something is
// dst is what we are going away from // dst is what we are going away from
// wantcheck is whether to check for dangerous things before considering a direction valid // wantcheck is whether to check for dangerous things before considering a direction valid
int getdiraway(cell_t *src, cell_t *dst, int wantcheck, int dirtype) { int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype) {
int d; int d;
cell_t *c; cell_t *c;
int maxdist=-1,bestdir=D_NONE; int maxdist=-1,bestdir=D_NONE;
int dist[MAXDIR_COMPASS]; int dist[MAXDIR_COMPASS];
int poss[MAXDIR_COMPASS]; int poss[MAXDIR_COMPASS];
int nposs; int nposs;
enum ERROR error;
for (d = DC_N; d <= DC_NW; d++) { for (d = DC_N; d <= DC_NW; d++) {
dist[d - DC_N] = -1; dist[d - DC_N] = -1;
@ -318,19 +328,30 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck, int dirtype) {
// destination is the thing we're fleeing from! // destination is the thing we're fleeing from!
thisdist = 0; thisdist = 0;
} else { } else {
if (wantcheck) { if (wantcheck) {
if (src->lf && canandwillmove(src->lf, d, NULL)) { if (srclf) {
ok = B_TRUE; if (canandwillmove(srclf, d, &error)) {
} else if (!src->lf) { ok = B_TRUE;
} else if (error == E_DOORINWAY) {
ok = B_TRUE;
}
} else {
ok = B_TRUE; ok = B_TRUE;
} }
} else { } else {
if (src->lf && cellwalkable(src->lf, c, NULL)) { if (srclf) {
ok = B_TRUE; if (cellwalkable(srclf, c, &error)) {
} else if (!src->lf) { ok = B_TRUE;
} else if (error == E_DOORINWAY) {
ok = B_TRUE;
}
} else {
ok = B_TRUE; ok = B_TRUE;
} }
} }
if (ok) { if (ok) {
if (dirtype == DT_ORTH) { if (dirtype == DT_ORTH) {
thisdist = getcelldistorth(c, dst); thisdist = getcelldistorth(c, dst);
@ -376,6 +397,7 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in
int dist[MAXDIR_COMPASS]; int dist[MAXDIR_COMPASS];
int poss[MAXDIR_COMPASS]; int poss[MAXDIR_COMPASS];
int nposs; int nposs;
enum ERROR error;
for (d = DC_N; d <= DC_NW; d++) { for (d = DC_N; d <= DC_NW; d++) {
dist[d - DC_N] = -1; dist[d - DC_N] = -1;
@ -393,15 +415,23 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in
} }
if (wantcheck) { if (wantcheck) {
if (srclf && canandwillmove(srclf, d, NULL)) { if (srclf) {
ok = B_TRUE; if (canandwillmove(srclf, d, &error)) {
} else if (!srclf) { ok = B_TRUE;
} else if (error == E_DOORINWAY) {
ok = B_TRUE;
}
} else {
ok = B_TRUE; ok = B_TRUE;
} }
} else { } else {
if (srclf && cellwalkable(srclf, c, NULL)) { if (srclf) {
ok = B_TRUE; if (cellwalkable(srclf, c, &error)) {
} else if (!srclf) { ok = B_TRUE;
} else if (error == E_DOORINWAY) {
ok = B_TRUE;
}
} else {
ok = B_TRUE; ok = B_TRUE;
} }
} }
@ -487,7 +517,8 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher) {
return B_FALSE; return B_FALSE;
} }
int moveawayfrom(lifeform_t *lf, cell_t *dst ) { // see 'movetowards' for description of dirtype
int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype ) {
int dir; int dir;
int rv = B_TRUE; int rv = B_TRUE;
@ -497,7 +528,7 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst ) {
} }
// move away from them // move away from them
dir = getdiraway(lf->cell, dst, B_TRUE, DT_COMPASS); dir = getdiraway(lf->cell, dst, lf, B_TRUE, dirtype);
if (dir == D_NONE) { if (dir == D_NONE) {
rv = B_TRUE; rv = B_TRUE;
} else { } else {
@ -589,7 +620,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
for (o = newcell->obpile->first ; o ; o = nexto ) { for (o = newcell->obpile->first ; o ; o = nexto ) {
nexto = o->next; nexto = o->next;
f = hasflag(o->flags, F_SHARP); f = hasflag(o->flags, F_SHARP);
if (f) { if (f && hasbp(lf, BP_FEET)) {
object_t *boots; object_t *boots;
// has boots on? // has boots on?
boots = getequippedob(lf->pack, BP_FEET); boots = getequippedob(lf->pack, BP_FEET);
@ -798,7 +829,17 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose) {
return B_FALSE; return B_FALSE;
} }
int movetowards(lifeform_t *lf, cell_t *dst) { // dirtype etermines whether to use compass or orthogonal direction to
// measure distance when determining which way is "towards"
//
// in general:
// use orthogonal for voluntary movement (eg. monster moving
// towards player), compass
//
// use compass for involuntary movement (eg. being knocked back by
// an explosion)
//
int movetowards(lifeform_t *lf, cell_t *dst, int dirtype) {
int dir; int dir;
int rv = B_TRUE; int rv = B_TRUE;
@ -808,7 +849,7 @@ int movetowards(lifeform_t *lf, cell_t *dst) {
} }
// move towards them // move towards them
dir = getdirtowards(lf->cell, dst, lf, B_TRUE, DT_COMPASS); dir = getdirtowards(lf->cell, dst, lf, B_TRUE, dirtype);
if (dir != D_NONE) { if (dir != D_NONE) {
rv = trymove(lf, dir, B_TRUE); rv = trymove(lf, dir, B_TRUE);
} }
@ -909,7 +950,14 @@ int opendoor(lifeform_t *lf, object_t *o) {
} }
where = getoblocation(o); where = getoblocation(o);
noise(where, lf, "a door opening", NULL); if (!haslos(player, where)) {
// don't anonuce this is we can see it.
// normally 'noise()' takes case of this by
// checking if we have LOS to the lifeform making
// sound, but in this case it's the door making
// the sound, not the lf.
noise(where, NULL, "a door opening.", NULL);
}
if (player && haslos(player, where)) { if (player && haslos(player, where)) {
needredraw = B_TRUE; needredraw = B_TRUE;
drawscreen(); drawscreen();
@ -1154,6 +1202,24 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
} }
} }
// gravboosted
if (lfhasflag(lf, F_GRAVBOOSTED)) {
// make a saving throw to move
if (!skillcheck(lf, SC_STR, 25, 0)) {
if (isplayer(lf)) {
msg("You try to move but are unable to lift your feet!");
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s tries to move but is unable to lift its feet!",lfname);
}
reason = E_OK;
taketime(lf, getmovespeed(lf));
return B_FALSE;
}
}
// move to new cell // move to new cell
reason = E_OK; reason = E_OK;
moveto(lf, cell, onpurpose); moveto(lf, cell, onpurpose);
@ -1188,7 +1254,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
} }
} }
break; break;
case E_OBINWAY: case E_DOORINWAY:
inway = (object_t *)rdata; inway = (object_t *)rdata;
door = isdoor(inway, &dooropen); door = isdoor(inway, &dooropen);
if (door && !dooropen) { if (door && !dooropen) {
@ -1221,36 +1287,38 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
reason = E_OK; reason = E_OK;
} }
} }
} else { }
// can we push this? break;
if (ispushable(inway)) { case E_OBINWAY:
if (canpush(lf, inway, dir)) { inway = (object_t *)rdata;
// push it! // can we push this?
push(lf, inway, dir); if (ispushable(inway)) {
} else { if (canpush(lf, inway, dir)) {
if (lf->controller == C_PLAYER) { // push it!
char obname[BUFLEN]; push(lf, inway, dir);
getobname(inway, obname, 1); } else {
switch (reason) {
case E_TOOHEAVY:
msg("The %s is too heavy to move.",strchr(obname, ' ')+1);
break;
case E_INSUBSTANTIAL:
msg("You cannot push %s without a physical body!",strchr(obname, ' ')+1);
break;
default:
msg("The %s won't move for some reason.",strchr(obname, ' ')+1);
break;
}
}
}
} else { // object is in the way
if (lf->controller == C_PLAYER) { if (lf->controller == C_PLAYER) {
char obname[BUFLEN]; char obname[BUFLEN];
getobname(inway, obname, 1); getobname(inway, obname, 1);
msg("There is %s in your way.",obname); switch (reason) {
case E_TOOHEAVY:
msg("The %s is too heavy to move.",strchr(obname, ' ')+1);
break;
case E_INSUBSTANTIAL:
msg("You cannot push %s without a physical body!",strchr(obname, ' ')+1);
break;
default:
msg("The %s won't move for some reason.",strchr(obname, ' ')+1);
break;
}
} }
} }
} else { // object is in the way
if (lf->controller == C_PLAYER) {
char obname[BUFLEN];
getobname(inway, obname, 1);
msg("There is %s in your way.",obname);
}
} }
break; break;
case E_LFINWAY: case E_LFINWAY:
@ -1285,16 +1353,6 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
return attacklf(lf, cell->lf); return attacklf(lf, cell->lf);
} }
break; break;
case E_GRAVBOOSTED:
if (isplayer(lf)) {
msg("You try to move but are unable to lift your feet!");
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s tries to move but is unable to lift its feet!",lfname);
}
taketime(lf, getmovespeed(lf));
break;
case E_CANTMOVE: case E_CANTMOVE:
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You cannot move!"); msg("You cannot move!");
@ -1347,7 +1405,9 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
int willmove(lifeform_t *lf, int dir, enum ERROR *error) { int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
cell_t *cell; cell_t *cell;
enum IQBRACKET iq;
//object_t *o; //object_t *o;
iq = getiqname(getattr(lf, A_IQ), NULL);
// default // default
if (error) { if (error) {
@ -1361,22 +1421,24 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
} }
// don't attack other monsters // don't attack other monsters
if (cell->lf) { if (cell->lf) { // if someone is in the way
if (!isplayer(lf)) { // if we are a monster if (!isplayer(lf)) { // if we are a monster
// friendly monsters: don't hit other friendlies // if the person in the way isn't our enemy...
if (!areenemies(lf, cell->lf)) { if (!areenemies(lf, cell->lf)) {
// TODO: swap places instead! // if they are an ally...
return B_FALSE; if (canswapwith(lf, cell->lf)) {
} return B_TRUE;
/*
} else if (ispeaceful(lf)) { // peaceful mosnters: don't hit anyone
return B_FALSE;
} else { // hostile/nonfriendly monsters - don't hit other monsters
if (!isplayer(cell->lf) && !isfriendly(cell->lf)) {
return B_FALSE;
} }
return B_FALSE;
} }
*/ }
}
// for intelligent things...
if (iq >= IQ_AVERAGE) {
// don't move if in pain
if (lfhasflag(lf, F_PAIN)) {
return B_FALSE;
} }
} }
return B_TRUE; return B_TRUE;

6
move.h
View File

@ -9,14 +9,14 @@ int closedoorat(lifeform_t *lf, cell_t *c);
int closedoor(lifeform_t *lf, object_t *o); int closedoor(lifeform_t *lf, object_t *o);
int diropposite(int dir); int diropposite(int dir);
void dorandommove(lifeform_t *lf, int badmovesok); void dorandommove(lifeform_t *lf, int badmovesok);
int getdiraway(cell_t *src, cell_t *dst, int wantcheck, int dirtype); int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype);
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype); int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype);
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher); int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher);
int moveawayfrom(lifeform_t *lf, cell_t *dst); int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype);
void moveeffects(lifeform_t *lf); void moveeffects(lifeform_t *lf);
int movelf(lifeform_t *lf, cell_t *newcell); int movelf(lifeform_t *lf, cell_t *newcell);
int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose); int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose);
int movetowards(lifeform_t *lf, cell_t *dst); int movetowards(lifeform_t *lf, cell_t *dst, int dirtype);
int opendoorat(lifeform_t *lf, cell_t *c); int opendoorat(lifeform_t *lf, cell_t *c);
int opendoor(lifeform_t *lf, object_t *o); int opendoor(lifeform_t *lf, object_t *o);
int pullnextto(lifeform_t *lf, cell_t *c); int pullnextto(lifeform_t *lf, cell_t *c);

24
nexus.c
View File

@ -31,6 +31,8 @@ map_t *firstmap = NULL,*lastmap = NULL;
knowledge_t *knowledge = NULL, *lastknowledge = NULL; knowledge_t *knowledge = NULL, *lastknowledge = NULL;
hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL; hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
glyph_t playerglyph,tempglyph;
// maintains unique lifeform ID numbers // maintains unique lifeform ID numbers
long nextlfid = 0; long nextlfid = 0;
@ -263,7 +265,7 @@ int main(int argc, char **argv) {
return B_FALSE; return B_FALSE;
} }
celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transparent, enum MATERIAL mat) { celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat) {
celltype_t *a; celltype_t *a;
// add to the end of the list // add to the end of the list
@ -284,7 +286,8 @@ celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transpare
// set props // set props
a->id = id; a->id = id;
a->name = strdup(name); a->name = strdup(name);
a->glyph = glyph; a->glyph.ch = glyph;
a->glyph.colour = colour;
a->solid = solid; a->solid = solid;
a->transparent = transparent; a->transparent = transparent;
a->material = findmaterial(mat); a->material = findmaterial(mat);
@ -537,6 +540,11 @@ int init(void) {
gamemode = GM_INIT; gamemode = GM_INIT;
playerglyph.ch = '@';
playerglyph.colour = C_GREY;
tempglyph.ch = '@';
tempglyph.colour = C_GREY;
initcommands(); initcommands();
initobjects(); initobjects();
@ -545,13 +553,11 @@ int init(void) {
initrace(); initrace();
// cell types // cell types
addcelltype(CT_WALL, "rock wall", '#', B_SOLID, B_OPAQUE, MT_STONE); addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE);
addcelltype(CT_ROOMWALL, "rock wall", '#', B_SOLID, B_OPAQUE, MT_STONE); addcelltype(CT_ROOMWALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE);
addcelltype(CT_CORRIDOR, "rock floor", '.', B_EMPTY, B_TRANS, MT_STONE); addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', B_EMPTY, B_TRANS, MT_STONE); addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
addcelltype(CT_ROOM, "rock floor", '.', B_EMPTY, B_TRANS, MT_STONE); addcelltype(CT_ROOM, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
//addcelltype(CT_DOOROPEN, "wooden door", '-', B_EMPTY, B_TRANS, MT_WOOD);
//addcelltype(CT_DOORCLOSED, "wooden door", '+', B_SOLID, B_OPAQUE, MT_WOOD);
gamemode = GM_VALIDATION; gamemode = GM_VALIDATION;
if (validateobs()) { if (validateobs()) {

View File

@ -1,6 +1,6 @@
#include "defs.h" #include "defs.h"
celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transparent, enum MATERIAL mat); celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat);
command_t *addcommand(enum COMMAND id, char c, char *desc); command_t *addcommand(enum COMMAND id, char c, char *desc);
void checkdeath(void); void checkdeath(void);
void checkendgame(void); void checkendgame(void);

733
objects.c

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ object_t *addemptyob(obpile_t *where, object_t *o);
hiddenname_t *addhiddenname(enum OBCLASS obclass, char *text); hiddenname_t *addhiddenname(enum OBCLASS obclass, char *text);
knowledge_t *addknowledge(enum OBCLASS id, char *hiddenname, int known); knowledge_t *addknowledge(enum OBCLASS id, char *hiddenname, int known);
material_t *addmaterial(enum MATERIAL id, char *name, float weightrating); material_t *addmaterial(enum MATERIAL id, char *name, float weightrating);
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph); objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int glyphcolour);
object_t *addob(obpile_t *where, char *name); object_t *addob(obpile_t *where, char *name);
object_t *addobject(obpile_t *where, char *name, int canstack); object_t *addobject(obpile_t *where, char *name, int canstack);
int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf); int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf);
@ -26,6 +26,7 @@ object_t *canstackob(obpile_t *op, object_t *match);
object_t *canstacknewot(obpile_t *op, objecttype_t *match); object_t *canstacknewot(obpile_t *op, objecttype_t *match);
int changemat(object_t *o, enum MATERIAL mat); int changemat(object_t *o, enum MATERIAL mat);
objecttype_t *checkobnames(char *haystack, char *needle); objecttype_t *checkobnames(char *haystack, char *needle);
void colourmatchob(object_t *o, lifeform_t *lf);
void copyobprops(object_t *dst, object_t *src); void copyobprops(object_t *dst, object_t *src);
int countnames(char **list); int countnames(char **list);
int countobs(obpile_t *op); int countobs(obpile_t *op);
@ -47,6 +48,7 @@ void genhiddennames(void);
int getcharges(object_t *o); int getcharges(object_t *o);
int geteffecttime(int min, int max, enum BLESSTYPE isblessed); int geteffecttime(int min, int max, enum BLESSTYPE isblessed);
objecttype_t *getlinkspell(object_t *o); objecttype_t *getlinkspell(object_t *o);
enum COLOUR getmaterialcolour(enum MATERIAL mat );
enum MATSTATE getmaterialstate(enum MATERIAL mat); enum MATSTATE getmaterialstate(enum MATERIAL mat);
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt); int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt);
int getobaccuracy(object_t *wep, lifeform_t *weilder); int getobaccuracy(object_t *wep, lifeform_t *weilder);
@ -62,7 +64,7 @@ char *getdamnamenoun(enum DAMTYPE damtype);
char *getfillingname(int nutrition); char *getfillingname(int nutrition);
int getfirearmrange(object_t *o); int getfirearmrange(object_t *o);
int getfirearmspeed(object_t *o); int getfirearmspeed(object_t *o);
char getglyph(object_t *o); glyph_t *getglyph(object_t *o);
char *genhiddenname(enum OBCLASS id); char *genhiddenname(enum OBCLASS id);
char *gethiddenname(object_t *o); char *gethiddenname(object_t *o);
int getobattackdelay(object_t *o); int getobattackdelay(object_t *o);
@ -146,6 +148,7 @@ int knockbackob(object_t *o, int dir, int howfar, int power, lifeform_t *pusher)
lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level); lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level);
void makeduller(object_t *o, int howmuch); void makeduller(object_t *o, int howmuch);
void makeknown(enum OBTYPE otid); void makeknown(enum OBTYPE otid);
void makewet(object_t *o, int amt);
object_t *moveob(object_t *src, obpile_t *dst, int howmany); object_t *moveob(object_t *src, obpile_t *dst, int howmany);
void modbonus(object_t *o, int amt); void modbonus(object_t *o, int amt);
//object_t *newobeffects(object_t *o); //object_t *newobeffects(object_t *o);
@ -161,7 +164,7 @@ int obpropsmatch(object_t *a, object_t *b);
int obotpropsmatch(object_t *a, objecttype_t *b); int obotpropsmatch(object_t *a, objecttype_t *b);
int operate(lifeform_t *lf, object_t *o, cell_t *where); int operate(lifeform_t *lf, object_t *o, cell_t *where);
int pilehasletter(obpile_t *op, char let); int pilehasletter(obpile_t *op, char let);
void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, int *seen); void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potlessed, int *seen);
int pour(lifeform_t *lf, object_t *o); int pour(lifeform_t *lf, object_t *o);
void quaff(lifeform_t *lf, object_t *o); void quaff(lifeform_t *lf, object_t *o);
int readsomething(lifeform_t *lf, object_t *o); int readsomething(lifeform_t *lf, object_t *o);

655
spell.c
View File

@ -73,7 +73,104 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
if (abilid == OT_A_GRAB) { if (abilid == OT_A_SWOOP) {
cell_t *adjcell = NULL,*origcell;
char targetname[BUFLEN];
int i;
cell_t *retcell[MAXRETCELLS];
int nretcell;
int srange = 5;
flag_t *srflag;
// get max range
srflag = lfhasflag(user, F_SWOOPRANGE);
if (srflag) {
srange = srflag->val[0];
}
if (isimmobile(user)) {
if (isplayer(user)) msg("You can't move!");
return B_TRUE;
} else if (!lfhasflag(user, F_FLYING)) {
if (isplayer(user)) msg("You are not flying, therefore cannot swoop.");
return B_TRUE;
}
if (!targcell) {
if (isplayer(user)) {
sprintf(buf, "Flyby who (max range %d)?",srange);
// TODO: ask for direction
targcell = askcoords("Flyby who?", TT_MONSTER);
if (!targcell) {
msg("Cancelled.");
return TRUE;
}
} else {
return B_FALSE;
}
}
if (getcelldist(user->cell, targcell) > srange) {
if (isplayer(user)) msg("You can't swoop that far!");
return B_TRUE;
}
// make sure we have LOF to there
target = targcell->lf;
if (!target) {
if (isplayer(user)) msg("There is nobody there!");
return TRUE;
} else if (!haslof(user, targcell, LOF_NEED, NULL)) {
if (isplayer(user)) msg("Your path there is blocked!");
return TRUE;
}
getlfname(target, targetname);
// find cell on the way...
calcbresnham(user->cell->map, user->cell->x, user->cell->y, targcell->x, targcell->y, retcell, &nretcell);
for (i = 1; i < nretcell; i++) {
if (retcell[i] == targcell) {
adjcell = retcell[i-1];
break;
}
}
if (!adjcell) {
if (isplayer(user)) {
msg("There is no space nearby for you to attack!");
}
return B_TRUE;
}
// take some time
taketime(user, getactspeed(user));
// remember orig cell
origcell = user->cell;
// teleport next to them
movelf(user, adjcell);
if (haslos(player, adjcell)) {
msg("%s swoop%s towards %s!",username,isplayer(user) ? "" : "s",targetname);
needredraw = B_TRUE;
drawlevelfor(player);
redraw();
//if (!isplayer(user)) {
more();
//}
}
// attack
attackcell(user, targcell);
// teleport back to initial pos
movelf(user, origcell);
if (haslos(player, origcell)) {
redraw();
}
} else if (abilid == OT_A_GRAB) {
char dirch; char dirch;
flag_t *f; flag_t *f;
@ -286,17 +383,28 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else if (abilid == OT_A_SPRINT) { } else if (abilid == OT_A_SPRINT) {
int howlong; int howlong;
int slev; int slev;
flag_t *f;
f = lfhasflag(user, F_SPRINTING);
if (f) {
if (f->val[0]) {
if (isplayer(user)) {
msg("You are already sprinting!");
}
} else {
if (isplayer(user)) {
msg("You are too tired to sprint right now.");
}
}
return B_TRUE;
}
if (lfhasflag(user, F_TIRED)) { if (lfhasflag(user, F_TIRED)) {
if (isplayer(user)) { if (isplayer(user)) {
msg("You are too tired to sprint right now."); msg("You are too tired to sprint right now.");
} }
return B_TRUE; return B_TRUE;
} else if (lfhasflag(user, F_SPRINTING)) {
if (isplayer(user)) {
msg("You are already sprinting!");
}
return B_TRUE;
} }
howlong = 5; howlong = 5;
// +2 for each athletics skill level // +2 for each athletics skill level
slev = getskill(user, SK_ATHLETICS); slev = getskill(user, SK_ATHLETICS);
@ -306,7 +414,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// modify for constitution // modify for constitution
howlong = modifybystat(howlong, user, A_CON); howlong = modifybystat(howlong, user, A_CON);
if (howlong <= 1) { if (howlong <= 0) {
if (isplayer(user)) { if (isplayer(user)) {
msg("You are too unfit to sprint."); msg("You are too unfit to sprint.");
} }
@ -357,6 +465,20 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
msg("Cancelled."); msg("Cancelled.");
} }
return B_FALSE; return B_FALSE;
} else if (abilid == OT_A_LEVELUP) {
char buf[BUFLEN];
int lev;
askstring("Which xp level will you attain", '?', buf, BUFLEN, NULL);
lev = atoi(buf);
if (lev <= user->level) {
msg("Cancelled.");
} else {
while (user->level < lev) {
gainlevel(user);
}
}
return B_FALSE;
} else if (abilid == OT_A_DEBUG) { } else if (abilid == OT_A_DEBUG) {
cell_t *where; cell_t *where;
where = askcoords("Debug who?", TT_MONSTER); where = askcoords("Debug who?", TT_MONSTER);
@ -595,17 +717,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// reverse some spells if cursed // reverse some spells if cursed
if (blessed == B_CURSED) {
switch (spellid) {
case OT_S_LIGHT:
spellid = OT_S_DARKNESS;
break;
default:
break;
}
}
if (hasflag(sp->flags, F_ONGOING)) { if (hasflag(sp->flags, F_ONGOING)) {
if (lfhasflagval(caster, F_BOOSTSPELL, spellid, NA, NA, NULL)) { if (lfhasflagval(caster, F_BOOSTSPELL, spellid, NA, NA, NULL)) {
// cancel it. // cancel it.
@ -938,12 +1049,41 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
addtempflag(target->flags, F_CHARMEDBY, caster->id, NA, NA, NULL, howlong); addtempflag(target->flags, F_CHARMEDBY, caster->id, NA, NA, NULL, howlong);
} }
} else if (spellid == OT_S_COLDBURST) {
int range = 1;
int x,y;
range = 1 + (power / 5);
// announce
if (isplayer(caster) || cansee(player, caster)) {
msg("%s emit%s a blast of icy cold!",castername,isplayer(caster) ? "" : "s");
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
animradialorth(caster->cell, range, '}', C_GREY);
for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) {
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y);
if (targcell && (getcelldistorth(caster->cell, targcell) <= range)) {
if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell, B_FALSE, NULL)) {
char lfname[BUFLEN];
// automatic hit
getlfname(targcell->lf, lfname);
if (haslos(caster, targcell)) {
msg("%s %s chilled!",lfname,isplayer(targcell->lf) ? "are" : "is");
}
losehp(targcell->lf, rolldie(1,8)+3, DT_COLD, caster, "a burst of coldness");
}
}
}
}
} else if (spellid == OT_S_CONECOLD) { } else if (spellid == OT_S_CONECOLD) {
char lfname[BUFLEN]; char lfname[BUFLEN];
int acc;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
// animation // animation
anim(caster->cell, targcell, '}'); anim(caster->cell, targcell, '}', C_GREY);
if (isplayer(caster) || cansee(player, caster)) { if (isplayer(caster) || cansee(player, caster)) {
msg("%s shoot%s a blast of coldness.",castername,isplayer(caster) ? "" : "s"); msg("%s shoot%s a blast of coldness.",castername,isplayer(caster) ? "" : "s");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -953,20 +1093,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (target) { if (target) {
getlfname(target, lfname); getlfname(target, lfname);
// target takes magical damage // target takes magical damage
// check if it hits
acc = getmissileaccuracy(caster, target->cell, NULL, NULL, A_IQ); if (skillcheck(target, SC_DODGE, 20 + (power*2), 0)) {
if (rnd(1,100) <= acc) { // miss
if (cansee(caster, target)) {
msg("A blast of coldness misses %s.",lfname);
}
} else {
// hit // hit
if (cansee(caster, target)) { if (cansee(caster, target)) {
msg("A blast of coldness ray hits %s.",lfname); msg("A blast of coldness ray hits %s.",lfname);
} }
losehp(target, rnd(2,6), DT_COLD, caster, "a blast of coldness"); losehp(target, rnd(2,6), DT_COLD, caster, "a blast of coldness");
} else {
// miss
if (cansee(caster, target)) {
msg("A blast of coldness misses %s.",lfname);
}
} }
} else { } else {
object_t *o, *nexto; object_t *o, *nexto;
for (o = targcell->obpile->first; o ; o = nexto) { for (o = targcell->obpile->first; o ; o = nexto) {
@ -975,14 +1115,33 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
} else if (spellid == OT_S_CREATEMONSTER) { } else if (spellid == OT_S_CREATEMONSTER) {
cell_t *where;
lifeform_t *newlf; lifeform_t *newlf;
job_t *forcejob = NULL; job_t *forcejob = NULL;
race_t *r = NULL; race_t *r = NULL;
int randomjobsok = B_TRUE; int randomjobsok = B_TRUE;
// create a monster nearby if (!targcell) {
if (blessed || (power >= 5)) { if (power >= 5) {
// control location
if (!validatespellcell(caster, &targcell, TT_NONE, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
// make sure it's empty
if (!cellwalkable(NULL, targcell, NULL)) {
targcell = NULL;
}
} else {
// get random adjacent cell
targcell = getrandomadjcell(caster->cell, WE_EMPTY);
}
}
if (!targcell) {
fizzle(caster);
return B_TRUE;
}
// determine type of mosnter
if (power >= 7) {
// ask what kind of monster // ask what kind of monster
askstring("Create what kind of monster", '?', buf, BUFLEN, NULL); askstring("Create what kind of monster", '?', buf, BUFLEN, NULL);
r = findracebyname(buf); r = findracebyname(buf);
@ -1008,39 +1167,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
if (!r) { if (!r) {
if (caster->controller == C_PLAYER) { fizzle(caster);
nothinghappens();
}
return B_TRUE; return B_TRUE;
} }
} else {
// random one
r = getreallyrandomrace();
} }
// get random adjacent cell
where = getrandomadjcell(caster->cell, WE_EMPTY);
if (!where) {
if (caster->controller == C_PLAYER) {
nothinghappens();
}
return B_TRUE;
}
// create random monster in cell
if (forcejob) { if (forcejob) {
randomjobsok = B_FALSE; randomjobsok = B_FALSE;
} else { } else {
randomjobsok = B_TRUE; randomjobsok = B_TRUE;
} }
if (!blessed) { // add the monster
r = getreallyrandomrace(); newlf = addmonster(targcell, r->id, randomjobsok, 1);
}
newlf = addmonster(where, r->id, randomjobsok, 1);
if (newlf) { if (newlf) {
// assign job if required // assign job if required
if (forcejob) { if (forcejob) {
givejob(newlf, forcejob->id); givejob(newlf, forcejob->id);
} }
if (haslos(player, where)) { if (haslos(player, targcell)) {
char *newbuf; char *newbuf;
getlfname(newlf, buf); getlfname(newlf, buf);
newbuf = strdup(buf); newbuf = strdup(buf);
@ -1223,7 +1372,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
target = targcell->lf; target = targcell->lf;
if (targcell->lf) { if (targcell->lf) {
if (skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) { int resisted = B_FALSE;
// if you cast this at yourself, only check for magic resistance if you have the
// flag.
// other people get a check anyway.
if (targcell->lf == caster) {
if (getmr(targcell->lf) && skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) {
resisted = B_TRUE;
}
} else {
if (skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) {
resisted = B_TRUE;
}
}
if (resisted) {
if (isplayer(targcell->lf)) { if (isplayer(targcell->lf)) {
msg("You flicker."); msg("You flicker.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -1272,6 +1435,46 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
nothinghappens(); nothinghappens();
} }
rv = B_FALSE; rv = B_FALSE;
} else if (spellid == OT_S_DRAINLIFE) {
char lfname[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
target = haslf(targcell);
if (target) {
getlfname(target, lfname);
} else {
fizzle(caster);
return B_FALSE;
}
if (!isimmuneto(target->flags, DT_NECROTIC)) {
// animation (opposite dir)
anim(targcell, caster->cell, '%', C_MAGENTA);
}
if (isplayer(caster) || cansee(player, caster)) {
if (isimmuneto(target->flags, DT_NECROTIC)) {
msg("%s suck%s death from %s!",castername,isplayer(caster) ? "" : "s", lfname);
} else {
msg("%s suck%s life from %s!",castername,isplayer(caster) ? "" : "s", lfname);
}
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
if (target) {
int amt;
if (isimmuneto(target->flags, DT_NECROTIC)) {
// target gains hp
amt = rnd(1,6) + power;
gainhp(target, amt);
// caster loses it
amt = losehp(caster, rnd(1,6) + power, DT_NECROTIC, caster, "lifeforce drain");
} else {
// target loses hp
amt = losehp(target, rnd(1,6) + power, DT_NECROTIC, caster, "lifeforce drain");
// caster gains it
gainhp(caster, amt);
}
}
} else if (spellid == OT_S_ENERGYBLAST) { } else if (spellid == OT_S_ENERGYBLAST) {
int range; int range;
int x,y; int x,y;
@ -1283,7 +1486,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
range = 2 + (power / 4); range = 2 + (power / 4);
animradial(caster->cell, range, '}'); animradial(caster->cell, range, '}', C_CYAN);
for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) { for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) {
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) { for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
@ -1313,7 +1516,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
numtotext(power, numbuf); numtotext(power, numbuf);
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
// animation // animation
anim(caster->cell, targcell, '}'); anim(caster->cell, targcell, '}', C_CYAN);
if (isplayer(caster) || cansee(player, caster)) { if (isplayer(caster) || cansee(player, caster)) {
if (power == 1) { if (power == 1) {
msg("%s fire%s a bolt of energy.",castername,isplayer(caster) ? "" : "s"); msg("%s fire%s a bolt of energy.",castername,isplayer(caster) ? "" : "s");
@ -1357,7 +1560,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("An enormous ball of fire explodes!"); msg("An enormous ball of fire explodes!");
} }
anim(caster->cell, targcell, '^'); anim(caster->cell, targcell, '^', C_RED);
// add fires as follows (3 = large, 2 = medium, 1 = smell) // add fires as follows (3 = large, 2 = medium, 1 = smell)
// //
@ -1416,10 +1619,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else if (spellid == OT_S_FIREDART) { } else if (spellid == OT_S_FIREDART) {
char lfname[BUFLEN]; char lfname[BUFLEN];
int acc;
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
// animation // animation
anim(caster->cell, targcell, '}'); anim(caster->cell, targcell, '}', C_RED);
if (isplayer(caster) || cansee(player, caster)) { if (isplayer(caster) || cansee(player, caster)) {
msg("%s shoot%s a dart of flame.",castername,isplayer(caster) ? "" : "s"); msg("%s shoot%s a dart of flame.",castername,isplayer(caster) ? "" : "s");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -1430,18 +1632,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
getlfname(target, lfname); getlfname(target, lfname);
// target takes magical damage // target takes magical damage
// check if it hits // check if it hits
acc = getmissileaccuracy(caster, target->cell, NULL, NULL, A_IQ); if (skillcheck(target, SC_DODGE, 20 + (power*2), 0)) {
if (rnd(1,100) <= acc) { // miss
msg("A dart of flame misses %s.",lfname);
} else {
// hit // hit
if (cansee(caster, target)) { if (cansee(caster, target)) {
msg("A dart of flame hits %s.",lfname); msg("A dart of flame hits %s.",lfname);
} }
losehp(target, rnd(2,6) + power, DT_FIRE, caster, "a dart of flame"); losehp(target, rnd(2,6) + power, DT_FIRE, caster, "a dart of flame");
} else {
// miss
if (cansee(caster, target)) {
msg("A dart of flame misses %s.",lfname);
}
} }
} else { } else {
object_t *o, *nexto; object_t *o, *nexto;
@ -1462,7 +1661,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
animradialorth(caster->cell, range, '}'); animradialorth(caster->cell, range, '}', C_RED);
for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) { for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) {
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) { for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
@ -1475,7 +1674,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (haslos(caster, targcell)) { if (haslos(caster, targcell)) {
msg("%s burn%s!",lfname,isplayer(targcell->lf) ? "" : "s"); msg("%s burn%s!",lfname,isplayer(targcell->lf) ? "" : "s");
} }
losehp(targcell->lf, rolldie(2,8)+3, DT_MAGIC, caster, "a burst of fire"); losehp(targcell->lf, rolldie(2,8)+3, DT_FIRE, caster, "a burst of fire");
} }
} }
} }
@ -1837,8 +2036,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
for (l = caster->cell->map->lf ; l ; l = l->next) { for (l = caster->cell->map->lf ; l ; l = l->next) {
if (l != caster) { if (l != caster) {
if (isimmuneto(l->flags, DT_NECROTIC) || skillcheck(l, SC_RESISTMAG, 20 + power, 0)) {
if (skillcheck(l, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(l)) { if (isplayer(l)) {
msg("Luckily, the evil doesn't seem to harm you."); msg("Luckily, the evil doesn't seem to harm you.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -1848,10 +2046,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char cname[BUFLEN]; char cname[BUFLEN];
real_getlfname(caster, cname, B_FALSE); real_getlfname(caster, cname, B_FALSE);
sprintf(dambuf, "%s%s infinite death spell", cname, getpossessive(cname)); sprintf(dambuf, "%s%s infinite death spell", cname, getpossessive(cname));
losehp(l, 9999, DT_DIRECT, NULL, dambuf); losehp(l, 500, DT_NECROTIC, NULL, dambuf);
} }
} }
} }
// now hit the caster!
if (isimmuneto(caster->flags, DT_NECROTIC) || skillcheck(caster, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(caster)) {
msg("Luckily, the evil doesn't seem to harm you.");
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
char dambuf[BUFLEN];
char cname[BUFLEN];
real_getlfname(caster, cname, B_FALSE);
sprintf(dambuf, "%s%s infinite death spell", cname, getpossessive(cname));
losehp(caster, 500, DT_NECROTIC, NULL, dambuf);
}
} else if (spellid == OT_S_MANASPIKE) { } else if (spellid == OT_S_MANASPIKE) {
char lfname[BUFLEN]; char lfname[BUFLEN];
char numbuf[BUFLEN]; char numbuf[BUFLEN];
@ -1859,7 +2071,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
numtotext(power, numbuf); numtotext(power, numbuf);
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
// animation // animation
anim(caster->cell, targcell, '}'); anim(caster->cell, targcell, '}', C_CYAN);
if (isplayer(caster) || cansee(player, caster)) { if (isplayer(caster) || cansee(player, caster)) {
if (power == 1) { if (power == 1) {
msg("%s fire%s a spike of mana.",castername,isplayer(caster) ? "" : "s"); msg("%s fire%s a spike of mana.",castername,isplayer(caster) ? "" : "s");
@ -2164,6 +2376,97 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
addflag(target->flags, F_BEINGSTONED, 2, NA, NA, NULL); addflag(target->flags, F_BEINGSTONED, 2, NA, NA, NULL);
} else if (spellid == OT_S_POISONBOLT) {
char lfname[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}', C_GREEN);
target = haslf(targcell);
if (target) {
getlfname(target, lfname);
// target gets saving throw to avoid...
if (skillcheck(target, SC_DODGE, 20 + (power*2), 0)) {
// miss
if (cansee(caster, target)) {
msg("A glob of venom misses %s.",lfname);
}
} else {
// hit
if (cansee(caster, target)) {
msg("A glob of venom hits %s.",lfname);
}
losehp(target, rnd(1,4), DT_POISON, caster, "a glob of poison");
if (!isimmuneto(target->flags, DT_POISON)) {
addtempflag(target->flags, F_POISONED, NA, NA, NA, castername, power*3);
}
}
} else {
object_t *o, *nexto;
for (o = targcell->obpile->first; o ; o = nexto) {
nexto = o->next;
takedamage(o, 0, DT_FIRE);
}
}
} else if (spellid == OT_S_POSSESSION) {
char targname[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
return B_FALSE;
}
getlfname(target, targname);
// saving throw....
if (skillcheck(target, SC_RESISTMAG, 20 + power*2, 0)) {
if (isplayer(caster) && cansee(player, target)) {
msg("%s%s mind fights off your intrusion!", targname, getpossessive(targname));
}
return B_FALSE;
}
// announce
if (cansee(player,target)) {
if (isplayer(caster)) {
msg("You take possession of %s%s mind!", targname, getpossessive(targname));
} else {
msg("%s takes possession of %s%s mind!",cansee(player, caster) ? castername : "Something",
targname, getpossessive(targname));
}
}
// possess!
if (isplayer(caster)) {
// player name
copyflag(target->flags, caster->flags, F_NAME);
// level
target->level = player->level;
player->controller = C_AI;
player = target;
target->controller = C_PLAYER;
} else {
switch (getallegiance(caster)) {
case AL_HOSTILE:
killflagsofid(target->flags, F_FRIENDLY);
addflag(target->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
break;
case AL_PEACEFUL:
killflagsofid(target->flags, F_FRIENDLY);
killflagsofid(target->flags, F_HOSTILE);
break;
case AL_FRIENDLY:
makefriendly(target, PERMENANT);
break;
}
}
// now kill the caster!
die(caster);
} else if (spellid == OT_S_PSYARMOUR) { } else if (spellid == OT_S_PSYARMOUR) {
flag_t *f; flag_t *f;
// always targetted at caster // always targetted at caster
@ -2787,6 +3090,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// target is always the caster // target is always the caster
target = caster; target = caster;
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(target)) { if (isplayer(target)) {
@ -2800,14 +3104,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE; return B_FALSE;
} }
if ((power < 5) || !isplayer(caster)) { if ((power < 5) || !isplayer(caster)) {
// random
while (!c || c->type->solid || haslf(c)) { while (!c || c->type->solid || haslf(c)) {
c = getrandomcell(target->cell->map); c = getrandomcell(target->cell->map);
} }
if (isplayer(target) || haslos(player, target->cell)) { } else if (power >= 8) {
if (seenbyplayer) *seenbyplayer = B_TRUE; // controlled
}
} else {
sprintf(buf, "Where will you teleport to?"); sprintf(buf, "Where will you teleport to?");
while (!c) { while (!c) {
int ch; int ch;
@ -2822,12 +3126,112 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (ch != 'y') c = NULL; if (ch != 'y') c = NULL;
} }
} }
} } else { // ie. if (power >= 5)
int dir;
char dirch;
cell_t *poss[MAX_MAPW * MAX_MAPH];
int nposs;
int x,y;
int xmin,ymin;
int xmax,ymax;
// semicontrolled
// ask for dir
dirch = askchar("Teleport in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE);
if ((dirch == '.') || (dir == '-')) {
fizzle(caster);
return B_TRUE;
} else {
dir = chartodir(dirch);
}
// make a list of all valid cells in that dir
nposs = 0;
switch (dir) {
case D_N:
case DC_N:
ymin = 0;
ymax = target->cell->y - 1;
xmin = target->cell->x - 5;
xmax = target->cell->x + 5;
break;
case DC_NE:
xmin = target->cell->x + 1;
ymin = 0;
xmax = target->cell->map->w - 1;
ymax = target->cell->y - 1;
break;
case D_E:
case DC_E:
xmin = target->cell->x + 1;
xmax = target->cell->map->w - 1;
ymin = target->cell->y - 5;;
ymax = target->cell->y + 5;;
break;
case DC_SE:
xmin = target->cell->x + 1;
ymin = target->cell->y + 1;
xmax = target->cell->map->w - 1;
ymax = target->cell->map->h - 1;
break;
case D_S:
case DC_S:
ymin = target->cell->y + 1;
ymax = target->cell->map->h - 1;
xmin = target->cell->x - 5;
xmax = target->cell->x + 5;
break;
case DC_SW:
xmin = 0;
ymin = target->cell->y + 1;
xmax = target->cell->x - 1;
ymax = target->cell->map->h - 1;
break;
case D_W:
case DC_W:
xmin = 0;
xmax = target->cell->x - 1;
ymin = target->cell->y - 5;
ymax = target->cell->y + 5;
break;
case DC_NW:
xmin = 0;
ymin = 0;
xmax = target->cell->x - 1;
ymax = target->cell->y - 1;
break;
}
if (xmin < 0) xmin = 0;
if (ymin < 0) ymin = 0;
if (xmax > target->cell->map->w-1) xmax = target->cell->map->w-1;
if (ymax > target->cell->map->h-1) ymax = target->cell->map->h-1;
for (y = ymin; y <= ymax ; y++) {
for (x = xmin; x <= xmax ; x++) {
c = getcellat(target->cell->map, x,y);
if (c && cellwalkable(target, c, NULL)) {
poss[nposs] = c;
nposs++;
}
}
}
if (nposs <= 0) {
fizzle(caster);
return B_FALSE;
}
c = poss[rnd(0,nposs-1)];
} // end if (semicontrolled | controlled | random )
targcell = c;
if (isplayer(target) || haslos(player, target->cell)) { if (isplayer(target) || haslos(player, target->cell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
teleportto(target, c, B_TRUE); teleportto(target, targcell, B_TRUE);
rv = B_FALSE; rv = B_FALSE;
} else if (spellid == OT_S_TELEKINESIS) { } else if (spellid == OT_S_TELEKINESIS) {
cell_t *where; cell_t *where;
@ -3151,28 +3555,33 @@ char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf) {
capitalise(buf); capitalise(buf);
power = getspellpower(lf, spellid); power = getspellpower(lf, spellid);
ss = getspellschool(spellid); ss = getspellschool(spellid);
if ((power > 1) && (ss != SS_ABILITY)) {
strcat(buf, " ");
strcat(buf, roman(power));
}
if (spellid == OT_S_TELEPORT) { if (spellid == OT_S_TELEPORT) {
if (power >= 5) { if (power >= 8) {
strcat(buf, "(controlled)"); strcat(buf, "(fullctrl)");
} else if (power >= 5) {
strcat(buf, "(semictrl)");
} }
} else if (spellid == OT_S_POLYMORPH) { } else if (spellid == OT_S_POLYMORPH) {
if (power >= 5) { if (power >= 5) {
strcat(buf, "(controlled)"); strcat(buf, "(ctrl)");
} }
} else if (spellid == OT_S_CREATEMONSTER) { } else if (spellid == OT_S_CREATEMONSTER) {
if (power >= 5) { if (power >= 7) {
strcat(buf, "(controlled)"); strcat(buf, "(fullctrl)");
} else if (power >= 5) {
strcat(buf, "(semictrl)");
} }
} else if (spellid == OT_S_LIGHT) { } else if (spellid == OT_S_LIGHT) {
if (power >= 8) { if (power >= 8) {
strcat(buf, "(perm,controlled)"); strcat(buf, "(perm,ctrl)");
} else if (power >= 3) { } else if (power >= 3) {
strcat(buf, "(controlled)"); strcat(buf, "(ctrl)");
}
} else {
if ((power > 1) && (ss != SS_ABILITY)) {
strcat(buf, " ");
strcat(buf, roman(power));
} }
} }
return buf; return buf;
@ -3182,7 +3591,8 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
int power = 0; int power = 0;
int statmod; int statmod;
int spelllev; int spelllev;
int skill; enum SKILLLEVEL spellskill,schoolskill;
enum SPELLSCHOOL school;
int max = 10; int max = 10;
flag_t *f; flag_t *f;
@ -3206,25 +3616,52 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
statmod = 0; statmod = 0;
} }
skill = getskill(lf, SK_SPELLCASTING); school = getspellschool(spellid);
if (skill == PR_INEPT) { spellskill = getskill(lf, SK_SPELLCASTING);
return 0; // dont need spellcasting skill for mental/allomancy
switch (school) {
case SS_ALLOMANCY:
case SS_MENTAL:
break;
default:
if (spellskill == PR_INEPT) {
return 0;
}
break;
} }
// every 6 levels you get 1 more power // every 6 levels you get 1 more power
// ie. at level 30 you get +5 power // ie. at level 30 you get +5 power
power = (lf->level/6) + statmod + skill; power = (lf->level/6) + statmod;
switch (school) {
case SS_ALLOMANCY:
case SS_MENTAL:
break;
default:
power += spellskill;
break;
}
spelllev = getspelllevel(spellid); spelllev = getspelllevel(spellid);
if (spelllev > 0) { if (spelllev > 0) {
power /= spelllev; int divamt;
if ((school == SS_ALLOMANCY) || (school == SS_MENTAL)) {
divamt = (spelllev/2);
} else {
divamt = spelllev;
}
if (divamt > 0) {
power /= divamt;
}
} }
// specialised spellcasting - apply this AFTER dividing by spell level? // specialised school skill - apply this AFTER dividing by spell level
skill = getskill(lf, getschoolskill(getspellschool(spellid))); schoolskill = getskill(lf, getschoolskill(getspellschool(spellid)));
if (skill != PR_INEPT) { if (schoolskill != PR_INEPT) {
power += skill; power += schoolskill;
} }
// enforce maximum // enforce maximum
@ -3274,8 +3711,11 @@ int getspellrange(enum OBTYPE spellid, int power) {
void pullobto(object_t *o, lifeform_t *lf) { void pullobto(object_t *o, lifeform_t *lf) {
char obname[BUFLEN]; char obname[BUFLEN];
char lfname[BUFLEN]; char lfname[BUFLEN];
glyph_t *gl;
anim(getoblocation(o), lf->cell, getglyph(o)); gl = getglyph(o);
anim(getoblocation(o), lf->cell, gl->ch, gl->colour);
getobname(o, obname, o->amt); getobname(o, obname, o->amt);
getlfname(lf, lfname); getlfname(lf, lfname);
@ -3404,20 +3844,23 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i
if (where) { if (where) {
cell_t *newwhere = NULL; cell_t *newwhere = NULL;
// validate it // validate it
if (where && needlos && !haslos(caster, where)) { if (where && needlos && !haslos(caster, where) && (where != caster->cell)) {
msg("You cannot see there!"); more(); msg("You cannot see there!"); more();
where = NULL; where = NULL;
} }
// line of fire interrupted?
if (where && needlof && !haslof(caster, where, needlof, &newwhere)) { if (where && needlof && !haslof(caster, where, needlof, &newwhere)) {
if (newwhere) { if (newwhere) {
// warn! if (isplayer(caster)) {
int ch; // warn!
ch = askchar("Your have no clear line of fire - really target here?","yn","n", B_TRUE); int ch;
if (ch == 'y') { ch = askchar("Your have no clear line of fire - really target here?","yn","n", B_TRUE);
where = newwhere; if (ch == 'y') {
} else { where = newwhere;
where = NULL; } else {
where = NULL;
}
} }
} else { } else {
where = NULL; where = NULL;
@ -3467,8 +3910,8 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i
if (!where) { if (!where) {
int ch; int ch;
ch = askchar("Abandon your spell?","yn","n", B_TRUE); ch = askchar("Abandon your spell?","yn","n", B_TRUE);
if (ch != 'y') { if (ch == 'y') {
where = NULL; return NULL;
} }
} }
} else { } else {

69
text.c
View File

@ -30,6 +30,49 @@ char *capitaliseall(char *text) {
return text; return text;
} }
char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf) {
int localmin, localmax;
if (ndice == NA) ndice = 0;
if (nsides == NA) nsides = 0;
if (bonus == NA) bonus = 0;
// ie. rolled a 1 on all dice
localmin = (ndice * 1) + bonus;
// ie. rolled max on all dice
localmax = (ndice * nsides) + bonus;
if (min) {
*min = localmin;
}
if (max) {
*max = localmax;
}
if (dicebuf) {
if ((ndice == 0) || (nsides == 0)) {
sprintf(dicebuf, "%d", bonus);
} else {
if (bonus) {
sprintf(dicebuf, "%dd%d%c%d", ndice, nsides,
(bonus > 0) ? '+' : '-',
abs(bonus));
} else {
sprintf(dicebuf, "%dd%d", ndice, nsides);
}
}
}
if (minmaxbuf) {
if (localmin == localmax) {
sprintf(minmaxbuf, "%d", localmin);
} else {
sprintf(minmaxbuf, "%d-%d", localmin, localmax);
}
}
return dicebuf;
}
char *getattrname(enum ATTRIB att) { char *getattrname(enum ATTRIB att) {
switch (att) { switch (att) {
case A_NONE: case A_NONE:
@ -171,6 +214,8 @@ char *makeplural(char *text) {
if (rv) return newtext; if (rv) return newtext;
newtext = strrep(newtext, "chunk ", "chunks ", &rv); newtext = strrep(newtext, "chunk ", "chunks ", &rv);
if (rv) return newtext; if (rv) return newtext;
newtext = strrep(newtext, "flask ", "flasks ", &rv);
if (rv) return newtext;
newtext = strrep(newtext, "gem ", "gems ", &rv); newtext = strrep(newtext, "gem ", "gems ", &rv);
if (rv) return newtext; if (rv) return newtext;
newtext = strrep(newtext, "loaf ", "loaves ", &rv); newtext = strrep(newtext, "loaf ", "loaves ", &rv);
@ -429,7 +474,7 @@ int strpixmatch(char *haystack, char *needle) {
int texttodice(char *text, int *ndice, int *nsides, int *bonus) { int texttodice(char *text, int *ndice, int *nsides, int *bonus) {
char *dummy; char *dummy;
char *localtext; char *localtext;
char *p; char *p,*plusloc;
localtext = strdup(text); localtext = strdup(text);
// number of dice // number of dice
p = strtok_r(localtext, "d", &dummy); p = strtok_r(localtext, "d", &dummy);
@ -444,16 +489,32 @@ int texttodice(char *text, int *ndice, int *nsides, int *bonus) {
if (!p) { if (!p) {
return B_TRUE; return B_TRUE;
} }
// strip out bonus
plusloc = strchr(p, '+');
if (plusloc) *plusloc = '\0';
plusloc = strchr(p, '-');
if (plusloc) *plusloc = '\0';
if (nsides) { if (nsides) {
*nsides = atoi(p); *nsides = atoi(p);
} }
free(localtext);
localtext = strdup(text);
// bonus/plus // bonus/plus
if (bonus) { if (bonus) {
p = strtok_r(NULL, "+", &dummy); p = strchr(localtext, '+');
if (p) { if (p) {
*bonus = atoi(p); *bonus = atoi(p+1);
} else { } else {
*bonus = 0; p = strchr(localtext, '-');
if (p) {
*bonus = -(atoi(p+1));
} else {
*bonus = 0;
}
} }
} }

1
text.h
View File

@ -2,6 +2,7 @@
char *capitalise(char *text); char *capitalise(char *text);
char *capitaliseall(char *text); char *capitaliseall(char *text);
char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf);
char *getattrname(enum ATTRIB att); char *getattrname(enum ATTRIB att);
char *getpossessive(char *text); char *getpossessive(char *text);
char *getsizetext(enum LFSIZE sz); char *getsizetext(enum LFSIZE sz);