* [+] bug: secret doors revealed when we walk away from them.

- [+] make lamps last heaps longer
* [+] web spell
* [+] spider monstrer
* [+] funnelweb:
* [+] redback:
- [+] if you are wracked with pain, don't clear msg
- [+] check rarity for spiders
* [+] attack/defense mod if there is stickiness in your square
- [+] replace "sticky" with "restrictive"
* [+] make some mosnters start hidden
- [+] adjust spot checks basd on distance
- [+] ensure that attacking stops you hiding
- [+] casting spells stops you from being hidden
- [+] hidden mosnters shouldn't move unless their victim is ADJACENT.
- [+] hidden mosnters shouldn't cast spells, throw missiles, etc unless
      their victim is ADJACENT.
- [-] XP CALC
    - [+] funnelweb and redback are the same.
    - [+] check this is right...... i want funnel web to be worse.
    - [+] make hitconfer check in calcxpval take lifetime into account
        - [+] ALSO assign an xp rating to each hitconferred flag.
        - [+] hardcode this.
* [+] entangle spell
- [+] reveal secret doors if you see them get damaged.
* [+] make askcoords list restrivitce objects
- [+] ACTUALLY make vines not damaged by struggling
* [+] object descriptions, a/an needs to change if showing condition: 
      "a battered entangling vine"
- [+] wizard levelled up and was prompted for "WISH, GIFT"! shouldn't
      happen!
- [+] The human diety reads a blessed scroll of create monster! -- but
      nothing happens??
* [+] throw code
- [+] wizard:  ask for school specialty at start, from:  fire, ice, xxx
      ?  You get this + WILD.
- [+] describe varpower spells
- [+] fix mp cost for varpower spells
- [+] we're not stopping running at staircases anymore  for some reason.
- [+] CHARGE ability (like swoop but don't return to original positino)
- [+] need to honor f_canlearn when displaying new skills to learn!
- [+] ai:  if we are going to player's last known loc (via targetcell),
      abandon if we can SEE the player!
- [+] make shatter() into a function
- [+] oil potion makes oil puddle whan smashed
- [+] make flammable objects be able to convert to others
- [+] replace 'magic item usage' with 'channeling'
- [+] a cloud of darkness descends.  this is a *cursed* wand of light.
- [+] spiders shouldn't be able to be stuck in a web!
* [+] spells should be able to have MULTIPLE schools.
- [+] don't bleed into walls
- [+] in @M, use colours to show which spells are too hard so far (ie
      cost > maxmp)
* [+] in @M, use schools that you know
* [+] after loading game, barbarian is getting an extra attack?
          You miss the eyebat.  You punch the eyebat.
- [+] show objects on top of stairs
- [+] stuck mosnters must pass a saving throw to follow you up/down
      stairs
    - [+] genericise:  trytomove(lf)
* [+] add more snakes
- [+] undead can't eat or drink? or MOST undead can't.
* [+] why can MONSTERS shoot webs through things? (but I can't)
- [+] barkskin - doesn't reduce max mp enough?
- [+] The skeleton touches a fuming aqua potion [tried] then recoils in
      pain!
      The skeleton drops a blessed fuming aqua potion [tried].
      The skeleton drinks a fuming aqua potion!
- [+] why can't i use abilites anymore?
- [+] infinite loop bug due to ai only having one ignorecell.
- [+] make sleet storms rust all armour
- [+] make a kind of walkdam that hits armour
    - [+] add this as well as walkdam for: acid, fire, water
- [+] Takeoff isn't prompting properly. only showing weapons!
* [+] waterproof obs (ie cloak)
* [+] walkdambp doesn't hurt body if you have a cloak
NATURE SPELLS:
- [+] mending, heals 1d6 damage
- [+] spark
- [+] purify food
- [+] sticks to snakes
- [+] calm animals (power_d4 hd)
* [+] charm animal (works on one animal up to power hit dice, temporary)
- [+] airblast
- [+] barkskin (power +2 AR, firevuln, ongoing)
- [+] soften earth (makes ground into mud)
- [+] warp wood (damages wooden objects)
- [+] repel insects
- [+] reduce poison
- [+] web
- [+] windshield
- [+] call lightning, air
- [+] resist elements, ongoing
- [+] passwall
- [+] poisonbolt
- [+] quench (puts out a fire)
- [+] sleet storm (lowers movement, vision)
- [+] healing
- [+] cure poison
* [+] calming scent
- [+] dig
- [+] entangle
- [+] levitate
- [+] flamepillar
- [+] hailstorm.  like sleetstorm but hurts more. power d 6.
- [+] burning wave
- [+] gaseous form
* [+] knowledge skills:
* [+] force makespellchoicelist() to show spells in level order.
* [+] druid
- [+] check OBJECT rarity list (dumplev)
- [+] fix bug where heaps of books suddently appear from dlev 3 onwards
- [+] gain skills on level up for some jobs
    - [+] f_levspellschool, v0=lev, v1 = school or ANY - select one
          from that school
This commit is contained in:
Rob Pearce 2011-04-23 04:27:42 +00:00
parent 4f54fc0ef9
commit b18dea83a3
23 changed files with 4221 additions and 4968 deletions

370
ai.c
View File

@ -19,6 +19,12 @@ extern enum ERROR reason;
int wantdb = B_TRUE; int wantdb = B_TRUE;
void addignorecell(lifeform_t *lf, cell_t *c) {
if (c) {
addflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL);
}
}
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; flag_t *f;
@ -251,8 +257,10 @@ object_t *aigetwand(lifeform_t *lf, enum FLAG purpose) {
return NULL; return NULL;
} }
void aigoto(lifeform_t *lf, cell_t *c, int timelimit) { flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int timelimit) {
int db = B_FALSE; int db = B_FALSE;
char whybuf[BUFLEN];
flag_t *f = NULL;
if (lfhasflag(lf, F_DEBUG)) { if (lfhasflag(lf, F_DEBUG)) {
db = B_TRUE; db = B_TRUE;
@ -267,12 +275,22 @@ void aigoto(lifeform_t *lf, cell_t *c, int timelimit) {
killflagsofid(lf->flags, F_TARGET); killflagsofid(lf->flags, F_TARGET);
killflagsofid(lf->flags, F_TARGETCELL); killflagsofid(lf->flags, F_TARGETCELL);
if (why == MR_LF) {
sprintf(whybuf, "%d", ((lifeform_t *)data)->id);
} else if (why == MR_OB) {
sprintf(whybuf, "%ld", ((object_t *)data)->id);
} else {
strcpy(whybuf, "");
}
if ((timelimit == PERMENANT) || (timelimit == UNLIMITED)) { if ((timelimit == PERMENANT) || (timelimit == UNLIMITED)) {
addflag(lf->flags, F_TARGETCELL, c->x, c->y, NA, NULL); f = addflag(lf->flags, F_TARGETCELL, c->x, c->y, why, whybuf);
} else { } else {
addtempflag(lf->flags, F_TARGETCELL, c->x, c->y, NA, NULL,timelimit); f = addtempflag(lf->flags, F_TARGETCELL, c->x, c->y, why, whybuf,timelimit);
} }
return f;
} }
void aimovetotargetcell(lifeform_t *lf, flag_t *f) { void aimovetotargetcell(lifeform_t *lf, flag_t *f) {
@ -296,7 +314,7 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) {
if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }"); if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }");
killflag(f); killflag(f);
// remember NOT to target this one. // remember NOT to target this one.
lf->ignorecell = c; addignorecell(lf, c);
} else { } else {
if (db) dblog(".oO { successfully walked towards f_targetcell. arrived at %d,%d }",lf->cell->x, lf->cell->y); if (db) dblog(".oO { successfully walked towards f_targetcell. arrived at %d,%d }",lf->cell->x, lf->cell->y);
// moved towards it. // moved towards it.
@ -314,7 +332,7 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) {
// destination doesn't exist! // destination doesn't exist!
killflag(f); killflag(f);
// remember NOT to target this one. // remember NOT to target this one.
lf->ignorecell = c; addignorecell(lf, c);
} }
} }
@ -508,10 +526,12 @@ void aiturn(lifeform_t *lf) {
// look for any object which we _covet_. // look for any object which we _covet_.
// ie. if we covet something, we will pick it up // ie. if we covet something, we will pick it up
// instead of attacking our target. // instead of attacking our target.
if (db) dblog(".oO { looking for covetted objects... }"); if (!lfhasflag(lf, F_HIDING)) {
if (lookforobs(lf, B_COVETS)) { if (db) dblog(".oO { looking for covetted objects... }");
if (db) dblog(".oO { found covetted object. returning. }"); if (lookforobs(lf, B_COVETS)) {
return; if (db) dblog(".oO { found covetted object. returning. }");
return;
}
} }
/////////////////////////////////////////////// ///////////////////////////////////////////////
@ -552,154 +572,156 @@ void aiturn(lifeform_t *lf) {
if (goingtomove && (getcelldist(lf->cell, target->cell) == 1)) { if (goingtomove && (getcelldist(lf->cell, target->cell) == 1)) {
} }
// can we attack with spells (ie. ones which target the victim)? if (!lfhasflag(lf, F_HIDING)) {
// if target is adjacent, we will normally just attack rather than try a spell. // can we attack with spells (ie. ones which target the victim)?
spell = aigetattackspell(lf, target); // if target is adjacent, we will normally just attack rather than try a spell.
if ( (spell != OT_NONE) && // found a valid spell/ability to use spell = aigetattackspell(lf, target);
((getcelldist(lf->cell, target->cell) != 1) || (rnd(1,3) == 1)) if ( (spell != OT_NONE) && // found a valid spell/ability to use
) { ((getcelldist(lf->cell, target->cell) != 1) || (rnd(1,3) == 1))
int spellfailed = B_FALSE; ) {
lifeform_t *spelllf = NULL; int spellfailed = B_FALSE;
cell_t *spellcell = NULL; lifeform_t *spelllf = NULL;
object_t *spellob = NULL; cell_t *spellcell = NULL;
objecttype_t *st; object_t *spellob = NULL;
st = findot(spell); objecttype_t *st;
if (db) { st = findot(spell);
dblog(".oO { will cast attack spell: %s }", st->name);
}
// special cases: eg. spells like telekenesis
if (spell == OT_S_TELEKINESIS) {
float maxweight;
object_t *poss[MAXPILEOBS];
int nposs;
int i;
// find nearest object which can be picked up
// this is copied out of the telekenesis spell code!
maxweight = getlfweight(lf, B_NOOBS) +
(getlfweight(lf, B_NOOBS) * (getstatmod(lf, A_IQ) / 100));
nposs = 0;
for (i = 0; i < lf->nlos; i++) {
object_t *o;
for (o = lf->los[i]->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP) &&
getobweight(o) <= maxweight) {
poss[nposs] = o;
nposs++;
if (nposs >= MAXPILEOBS) break;
}
}
if (nposs >= MAXPILEOBS) break;
}
if (nposs > 0) {
spellob = poss[rnd(0,nposs-1)];
} else {
spellfailed = B_TRUE;
}
// cast spell at the player
spelllf = target;
spellcell = target->cell;
} else {
// pick targets based on spell flags
aigetspelltarget(lf, st, target, &spelllf, &spellcell, &spellob, F_AICASTTOATTACK);
}
if (spellfailed) {
if (db) dblog(".oO { cast spell/ability failed (1)! }");
} else {
if (getschool(spell) == SS_ABILITY) {
spellfailed = useability(lf, spell, spelllf, spellcell);
} else {
spellfailed = castspell(lf, spell, spelllf, spellob, spellcell);
}
}
if (spellfailed) {
if (db) dblog(".oO { cast spell/ability tried but failed (2)! reason = %d }", reason);
} else {
// spell succesful
return;
}
}
// if not adjacent, check for guns, wands, throwing
if (goingtomove && // if we are still planning on moving
(getcelldist(lf->cell, target->cell) > 1) && // and we're not adjacent to target
haslof(lf->cell, target->cell, LOF_NEED, NULL) && // and we have line of fire to them
(iqb > IQ_ANIMAL) ) { // and we are smarter than an animal
// can we attack by firing a weapon?
gun = getfirearm(lf);
if (goingtomove && gun && getammo(lf)) {
if (db) { if (db) {
char gunname[BUFLEN]; dblog(".oO { will cast attack spell: %s }", st->name);
getobname(gun, gunname, gun->amt);
dblog(".oO { will fire my gun (%s) at target. }",gunname);
} }
setguntarget(lf, target);
if (!shoot(lf)) {
// succesful
return;
} else {
if (db) dblog(".oO { shoot gun failed! reason = %d }", reason);
}
} else {
if (db) dblog(".oO { not firing out gun }");
}
// can we attack by throwing something? // special cases: eg. spells like telekenesis
if (goingtomove && hasbp(lf, BP_HANDS)) { if (spell == OT_S_TELEKINESIS) {
o = getbestthrowmissile(lf); float maxweight;
if (o) { object_t *poss[MAXPILEOBS];
if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name); int nposs;
// try to throw it! int i;
if (!throwat(lf, o, target->cell)) { // find nearest object which can be picked up
// succesful
goingtomove = B_FALSE;
} else {
if (db) dblog(".oO { throw failed! }");
}
}
}
// do we have a wand we can zap? // this is copied out of the telekenesis spell code!
if (lfhasflag(lf, F_HUMANOID) || hasbp(lf, BP_HANDS)) { maxweight = getlfweight(lf, B_NOOBS) +
if (lfhasflag(lf, F_FLEEFROM)) { (getlfweight(lf, B_NOOBS) * (getstatmod(lf, A_IQ) / 100));
o = aigetwand(lf, F_AICASTTOFLEE);
} else {
o = aigetwand(lf, F_AICASTTOATTACK);
}
if (o) {
objecttype_t *st;
cell_t *zapcell = NULL;
st = getlinkspell(o); nposs = 0;
if (st) { for (i = 0; i < lf->nlos; i++) {
enum FLAG purpose; object_t *o;
if (lfhasflag(lf, F_FLEEFROM)) { for (o = lf->los[i]->obpile->first ; o ; o = o->next) {
purpose = F_AICASTTOFLEE; if (!hasflag(o->flags, F_NOPICKUP) &&
} else { getobweight(o) <= maxweight) {
purpose = F_AICASTTOATTACK; poss[nposs] = o;
nposs++;
if (nposs >= MAXPILEOBS) break;
}
} }
aigetspelltarget(lf, st, target, NULL, &zapcell, NULL, purpose); if (nposs >= MAXPILEOBS) break;
}
if (nposs > 0) {
spellob = poss[rnd(0,nposs-1)];
} else { } else {
// no linkspell - just zap it. spellfailed = B_TRUE;
zapcell = NULL;
} }
// zap it // cast spell at the player
if (db) dblog(".oO { will zap %s instead of moving }", o->type->name); spelllf = target;
spellcell = target->cell;
} else {
// pick targets based on spell flags
aigetspelltarget(lf, st, target, &spelllf, &spellcell, &spellob, F_AICASTTOATTACK);
}
if (!operate(lf, o, zapcell)) { if (spellfailed) {
// succesful if (db) dblog(".oO { cast spell/ability failed (1)! }");
goingtomove = B_FALSE; } else {
if (getschool(spell) == SS_ABILITY) {
spellfailed = useability(lf, spell, spelllf, spellcell);
} else { } else {
if (db) dblog(".oO { zap failed! }"); spellfailed = castspell(lf, spell, spelllf, spellob, spellcell);
}
}
if (spellfailed) {
if (db) dblog(".oO { cast spell/ability tried but failed (2)! reason = %d }", reason);
} else {
// spell succesful
return;
}
}
// if not adjacent, check for guns, wands, throwing
if (goingtomove && // if we are still planning on moving
(getcelldist(lf->cell, target->cell) > 1) && // and we're not adjacent to target
haslof(lf->cell, target->cell, LOF_NEED, NULL) && // and we have line of fire to them
(iqb > IQ_ANIMAL) ) { // and we are smarter than an animal
// can we attack by firing a weapon?
gun = getfirearm(lf);
if (goingtomove && gun && getammo(lf)) {
if (db) {
char gunname[BUFLEN];
getobname(gun, gunname, gun->amt);
dblog(".oO { will fire my gun (%s) at target. }",gunname);
}
setguntarget(lf, target);
if (!shoot(lf)) {
// succesful
return;
} else {
if (db) dblog(".oO { shoot gun failed! reason = %d }", reason);
}
} else {
if (db) dblog(".oO { not firing out gun }");
}
// can we attack by throwing something?
if (goingtomove && hasbp(lf, BP_HANDS)) {
o = getbestthrowmissile(lf);
if (o) {
if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name);
// try to throw it!
if (!throwat(lf, o, target->cell)) {
// succesful
goingtomove = B_FALSE;
} else {
if (db) dblog(".oO { throw failed! }");
}
}
}
// do we have a wand we can zap?
if (lfhasflag(lf, F_HUMANOID) || hasbp(lf, BP_HANDS)) {
if (lfhasflag(lf, F_FLEEFROM)) {
o = aigetwand(lf, F_AICASTTOFLEE);
} else {
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 {
// no linkspell - just zap it.
zapcell = NULL;
}
// zap it
if (db) dblog(".oO { will zap %s instead of moving }", o->type->name);
if (!operate(lf, o, zapcell)) {
// succesful
goingtomove = B_FALSE;
} else {
if (db) dblog(".oO { zap failed! }");
}
} }
} }
} }
} } // end if !hiding
// do we have a valid melee attack? // do we have a valid melee attack?
if (!icanattack) { if (!icanattack) {
@ -707,6 +729,12 @@ void aiturn(lifeform_t *lf) {
goingtomove = B_FALSE; goingtomove = B_FALSE;
} }
// if we are hiding, only attack when adjacent to maximise damage
if (lfhasflag(lf, F_HIDING) &&
(getcelldist(lf->cell, target->cell) != 1)) {
goingtomove = B_FALSE;
}
if (goingtomove) { if (goingtomove) {
if (!movetowards(lf, target->cell, DT_ORTH)) { if (!movetowards(lf, target->cell, DT_ORTH)) {
// success // success
@ -723,7 +751,7 @@ void aiturn(lifeform_t *lf) {
// move towards their last known location instead // move towards their last known location instead
targcell = getcellat(lf->cell->map, lastx, lasty); targcell = getcellat(lf->cell->map, lastx, lasty);
if (targcell) { if (targcell) {
aigoto(lf, targcell, PERMENANT); aigoto(lf, targcell, MR_LF, target, PERMENANT);
} else { } else {
if (db) dblog(".oO { go to target's last known loc failed! }"); if (db) dblog(".oO { go to target's last known loc failed! }");
} }
@ -747,7 +775,38 @@ void aiturn(lifeform_t *lf) {
// do we have a target cell? // do we have a target cell?
f = hasflag(lf->flags, F_TARGETCELL); f = hasflag(lf->flags, F_TARGETCELL);
if (f) { if (f) {
aimovetotargetcell(lf, f); int valid = B_TRUE;
cell_t *c;
// is it still valid?
c = getcellat(lf->cell->map, f->val[0], f->val[1]);
if (!c) {
valid = B_FALSE;
} else if (f->val[2] == MR_LF) {
lifeform_t *who;
who = findlf(lf->cell->map, atoi(f->text));
// lf doesn't exist?
if (!who) {
valid = B_FALSE;
} else if (cansee(lf, who) && (lf->cell != c)) {
// can see them and they're not where we are going?
valid = B_FALSE;
}
} else if (f->val[2] == MR_OB) {
object_t *what;
what = findobidinmap(lf->cell->map, atol(f->text));
if (!what) {
valid = B_FALSE;
} else if (haslos(lf, c) && (what->pile->where != c)) {
// if you can see the cell and object isn't there anymore
valid = B_FALSE;
}
}
if (valid) {
aimovetotargetcell(lf, f);
} else {
killflag(f);
}
return; return;
} }
@ -870,8 +929,11 @@ void aiturn(lifeform_t *lf) {
} else { } else {
// try to move towards master's last known loc // try to move towards master's last known loc
if (mf->val[1] != NA) { if (mf->val[1] != NA) {
cell_t *newcell;
newcell = getcellat(lf->cell->map, mf->val[1], mf->val[2]);
if (db) dblog(".oO { cannot see my master - adding F_TARGETCELL for last known loc }"); if (db) dblog(".oO { cannot see my master - adding F_TARGETCELL for last known loc }");
f = addflag(lf->flags, F_TARGETCELL, mf->val[1], mf->val[2], NA, NULL); f = aigoto(lf, newcell, MR_LF, master, PERMENANT);
aimovetotargetcell(lf, f); aimovetotargetcell(lf, f);
} else { } else {
if (db) dblog(".oO { cannot see my master and dont have a last known location. randommove. }"); if (db) dblog(".oO { cannot see my master and dont have a last known location. randommove. }");
@ -1105,6 +1167,18 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if ((ot->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) { if ((ot->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
if ((ot->id == OT_S_WARPWOOD)) {
specificcheckok = B_FALSE;
if (victim) {
object_t *oo;
for (oo = victim->pack->first ; oo ; oo = oo->next) {
if ((oo->type->material->id == MT_WOOD) && isequipped(oo)) {
specificcheckok = B_TRUE;
break;
}
}
}
}
if ((ot->id == OT_S_WEAKEN)) { if ((ot->id == OT_S_WEAKEN)) {
flag_t *lff; flag_t *lff;
for (lff = lf->flags->first; lff ; lff = lff->next) { for (lff = lf->flags->first; lff ; lff = lff->next) {
@ -1254,7 +1328,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 && (c != lf->ignorecell)) { if (!c->lf && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) {
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);
@ -1306,7 +1380,7 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
if (gothere) { if (gothere) {
// start walking towards target cell // start walking towards target cell
aigoto(lf, c, AI_FOLLOWTIME); aigoto(lf, c, MR_OB, o, AI_FOLLOWTIME);
return B_TRUE; return B_TRUE;
} }
} }

3
ai.h
View File

@ -1,11 +1,12 @@
#include "defs.h" #include "defs.h"
void addignorecell(lifeform_t *lf, cell_t *c);
void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit); void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit);
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim); enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim);
enum OBTYPE aigetfleespell(lifeform_t *lf); enum OBTYPE aigetfleespell(lifeform_t *lf);
void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob, enum FLAG purpose); void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob, enum FLAG purpose);
object_t * aigetwand(lifeform_t *lf, enum FLAG purpose); object_t * aigetwand(lifeform_t *lf, enum FLAG purpose);
void aigoto(lifeform_t *lf, cell_t *c, int timelimit); flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int timelimit);
void aimovetotargetcell(lifeform_t *lf, flag_t *f); void aimovetotargetcell(lifeform_t *lf, flag_t *f);
int aipickup(lifeform_t *lf, object_t *o); int aipickup(lifeform_t *lf, object_t *o);
int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target); int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target);

View File

@ -183,6 +183,12 @@ int attackcell(lifeform_t *lf, cell_t *c) {
} }
} }
// stop sprinting
f = lfhasflag(lf, F_SPRINTING);
if (f && f->val[0]) {
killflag(f);
}
// take time // take time
attacktime = getattackspeed(lf); attacktime = getattackspeed(lf);
taketime(lf, attacktime); taketime(lf, attacktime);
@ -266,6 +272,9 @@ int attackcell(lifeform_t *lf, cell_t *c) {
if (op) { if (op) {
killobpile(op); killobpile(op);
} }
// now stop hiding
killflagsofid(lf->flags, F_HIDING);
return B_FALSE; return B_FALSE;
} }
@ -323,6 +332,18 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
getobname(wep, wepname, 1); getobname(wep, wepname, 1);
if (aidb) dblog(".oO { my weapon is %s }", wepname); if (aidb) dblog(".oO { my weapon is %s }", wepname);
if (lf->race->raceclass->id == RC_INSECT) {
if (hasactivespell(victim, OT_S_REPELINSECTS)) {
if (isplayer(lf)) {
msg("Something prevents you from attacking %s!", victimname);
} else if (cansee(player, lf)) {
msg("Something prevents %s from attacking %s!", attackername, victimname);
}
taketime(lf, getattackspeed(lf));
return B_FALSE;
}
}
// did you hit? // did you hit?
ndam = 0; ndam = 0;
@ -406,6 +427,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
dam[0] += pctof(pctextra, dam[0]); dam[0] += pctof(pctextra, dam[0]);
} }
} }
// bonus for knowledge about the other lf's race? applied LAST.
if (getlorelevel(lf, victim->race->raceclass->id) >= PR_MASTER) {
dam[0] = (int) ( (float)dam[0] * 1.5 );
} else if (getlorelevel(lf, victim->race->raceclass->id) >= PR_SKILLED) {
dam[0] = (int) ( (float)dam[0] * 1.25 );
}
} }
if (aidb) dblog(".oO { dealing %d %s damage }", dam[0], getdamname(damtype[0])); if (aidb) dblog(".oO { dealing %d %s damage }", dam[0], getdamname(damtype[0]));
@ -690,7 +717,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (adj) { if (adj) {
flag_t *f; flag_t *f;
f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL); f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL);
moveto(victim, adj, B_FALSE); moveto(victim, adj, B_FALSE, B_FALSE);
msg("%s dodge%s!",victimname,isplayer(victim) ? "" : "s"); msg("%s dodge%s!",victimname,isplayer(victim) ? "" : "s");
killflag(f); killflag(f);
} }
@ -1629,7 +1656,9 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
// only works if we did damage // only works if we did damage
if (dam) { if (dam) {
enum FLAG fid; enum FLAG fid;
int min,max,howlong; int howlong;
flag_t *valflag = NULL;
fid = f->val[0]; fid = f->val[0];
// the f_poisoned flag stacks, others don't. // the f_poisoned flag stacks, others don't.
if (!lfhasflag(victim, fid) || (fid == F_POISONED)) { if (!lfhasflag(victim, fid) || (fid == F_POISONED)) {
@ -1648,31 +1677,15 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
} }
if (!passedcheck) { if (!passedcheck) {
if (f->text) {
char loctext[BUFLEN]; howlong = gethitconferlifetime(f->text, NULL, NULL);
char *word, *dummy;
strcpy(loctext,f->text); // get conferred flag values
word = strtok_r(loctext, "-", &dummy); valflag = hasflag(f->pile, F_HITCONFERVALS);
if (word) {
min = atoi(word);
word = strtok_r(NULL, "-", &dummy);
if (word) {
max = atoi(word);
howlong = rnd(min,max);
} else {
howlong = PERMENANT;
}
} else {
howlong = PERMENANT;
}
} else {
howlong = PERMENANT;
}
if (fid == F_POISONED) { if (fid == F_POISONED) {
// need to fill in the name of what poisoned us // need to fill in the name of what poisoned us
char frombuf[BUFLEN]; char frombuf[BUFLEN];
flag_t *typeflag;
enum POISONTYPE ptype; enum POISONTYPE ptype;
int ppower; int ppower;
if (wep) { if (wep) {
@ -1692,13 +1705,14 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
} else { } else {
strcpy(frombuf, "something unknown"); strcpy(frombuf, "something unknown");
} }
typeflag = hasflag(f->pile, F_HITPOISONTYPE);
if (typeflag) {
ptype = typeflag->val[0]; if (valflag) {
if (typeflag->val[1] == NA) { ptype = valflag->val[0];
if (valflag->val[1] == NA) {
ppower = 1; ppower = 1;
} else { } else {
ppower = typeflag->val[1]; ppower = valflag->val[1];
} }
} else { } else {
// should never happen. // should never happen.
@ -1708,7 +1722,16 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
poison(victim, howlong, ptype, ppower, frombuf); poison(victim, howlong, ptype, ppower, frombuf);
} else { } else {
addtempflag(victim->flags, fid, NA, NA, NA, NULL, howlong); flag_t *conferredflag;
conferredflag = addtempflag(victim->flags, fid, NA, NA, NA, NULL, howlong);
// flag values
if (valflag) {
conferredflag->val[0] = valflag->val[0];
conferredflag->val[1] = valflag->val[1];
conferredflag->val[2] = valflag->val[2];
free(conferredflag->text);
conferredflag->text = strdup(valflag->text);
}
} }
} // end if passedcheck } // end if passedcheck
} // end (if victim doesn't already have the flag) } // end (if victim doesn't already have the flag)

248
defs.h
View File

@ -34,6 +34,64 @@ enum COLOUR {
C_BOLDGREEN = 14, C_BOLDGREEN = 14,
}; };
enum SKILL {
SK_NONE = 0,
SK_ARMOUR = 1,
SK_ATHLETICS,
SK_BACKSTAB,
SK_FIRSTAID,
SK_LISTEN,
SK_LOCKPICKING,
SK_CHANNELING,
SK_SHIELDS,
SK_SPELLCASTING,
SK_SPOTHIDDEN,
SK_STEALTH,
SK_TECHUSAGE,
// knowledge
SK_LORE_ARCANA,
SK_LORE_DEMONS,
SK_LORE_HUMANOID,
SK_LORE_NATURE,
SK_LORE_UNDEAD,
// weaponry
SK_AXES,
SK_CLUBS,
SK_LONGBLADES,
SK_POLEARMS,
SK_SHORTBLADES,
SK_STAVES,
SK_UNARMED,
// spell schools
SK_SS_ALLOMANCY,
SK_SS_AIR,
SK_SS_DEATH,
SK_SS_DIVINATION,
SK_SS_FIRE,
SK_SS_ICE,
SK_SS_GRAVITY,
SK_SS_LIFE,
SK_SS_MODIFICATION,
SK_SS_MENTAL,
SK_SS_NATURE,
SK_SS_SUMMONING,
SK_SS_TRANSLOCATION,
SK_SS_WILD,
};
#define MAXSKILLS 39
// proficiency levels
enum SKILLLEVEL {
PR_INEPT = 0,
PR_NOVICE = 1,
PR_BEGINNER = 2,
PR_ADEPT = 3,
PR_SKILLED = 4,
PR_EXPERT = 5,
PR_MASTER = 6,
};
// save/load // save/load
#define MAPDIR "data/maps" #define MAPDIR "data/maps"
#define SAVEDIR "data/save" #define SAVEDIR "data/save"
@ -161,6 +219,8 @@ enum LFCONDITION {
#define MAXPILEOBS 52 #define MAXPILEOBS 52
#define MAXSPELLLEV 9
#define MAXRETCELLS 80 #define MAXRETCELLS 80
#define MAXCHOICES 150 #define MAXCHOICES 150
@ -217,12 +277,14 @@ enum LFCONDITION {
#define AO_WEARABLE 16 #define AO_WEARABLE 16
#define AO_OPERABLE 32 #define AO_OPERABLE 32
#define AO_POURABLE 64 #define AO_POURABLE 64
#define AO_EQUIPPEDARMOUR 128 #define AO_EQUIPPEDNONWEAPON 128
#define AO_WEILDABLE 256 #define AO_WEILDABLE 256
#define AO_SPECIFIED 512 #define AO_SPECIFIED 512
#define AO_READABLE 1024 #define AO_READABLE 1024
#define AO_ARMOUR 2048 #define AO_ARMOUR 2048
#define AO_NOTKNOWN 4096 #define AO_NOTKNOWN 4096
#define AO_DAMAGED 8192
#define AO_DRINKABLE 16384
// askcoords target types // askcoords target types
#define TT_NONE 0 #define TT_NONE 0
@ -230,6 +292,7 @@ enum LFCONDITION {
#define TT_OBJECT 2 #define TT_OBJECT 2
#define TT_DOOR 4 #define TT_DOOR 4
#define TT_PLAYER 8 #define TT_PLAYER 8
#define TT_ALLY 16
// target requirements // target requirements
#define TR_NONE 0 #define TR_NONE 0
@ -326,13 +389,13 @@ enum SPELLSCHOOL {
SS_AIR, SS_AIR,
SS_DEATH, SS_DEATH,
SS_DIVINATION, SS_DIVINATION,
SS_EARTH,
SS_FIRE, SS_FIRE,
SS_ICE, SS_ICE,
SS_GRAVITY, SS_GRAVITY,
SS_LIFE, SS_LIFE,
SS_MODIFICATION, SS_MODIFICATION,
SS_MENTAL, SS_MENTAL,
SS_NATURE,
SS_SUMMONING, SS_SUMMONING,
SS_TRANSLOCATION, SS_TRANSLOCATION,
SS_WILD, SS_WILD,
@ -460,7 +523,8 @@ enum HABITAT {
H_ALL = 999 H_ALL = 999
}; };
#define RARITYVARIANCE (25) #define RARITYVARIANCELF (5)
#define RARITYVARIANCEOB (10)
/* /*
enum RARITY { enum RARITY {
@ -474,6 +538,16 @@ enum RARITY {
}; };
*/ */
enum RACECLASS {
RC_ANIMAL,
RC_DEMON,
RC_HUMANOID,
RC_INSECT,
RC_SLIME,
RC_MAGIC,
RC_OTHER,
RC_UNDEAD,
};
enum RACE { enum RACE {
R_NONE, R_RANDOM, R_NONE, R_RANDOM,
@ -524,7 +598,12 @@ enum RACE {
R_NEWT, R_NEWT,
R_RAT, R_RAT,
R_SNAKE, R_SNAKE,
R_SNAKECARPET,
R_SPIDER,
R_SPIDERFUNNELWEB,
R_SPIDERREDBACK,
R_WOLF, R_WOLF,
R_WOLFYOUNG,
// insects // insects
R_BUTTERFLY, R_BUTTERFLY,
R_CENTIPEDE, R_CENTIPEDE,
@ -549,6 +628,7 @@ enum JOB {
J_ALLOMANCER, J_ALLOMANCER,
J_BARBARIAN, J_BARBARIAN,
J_COMMANDO, J_COMMANDO,
J_DRUID,
J_PIRATE, J_PIRATE,
J_PLUMBER, J_PLUMBER,
J_PRINCE, J_PRINCE,
@ -589,6 +669,8 @@ enum MATERIAL {
MT_SLIME = 21, MT_SLIME = 21,
MT_WAX = 22, MT_WAX = 22,
MT_ACID = 23, MT_ACID = 23,
MT_SILK = 24,
MT_OIL = 25,
}; };
// Object Types // Object Types
@ -681,6 +763,7 @@ enum OBTYPE {
OT_SCR_KNOCK, OT_SCR_KNOCK,
OT_SCR_LIGHT, OT_SCR_LIGHT,
OT_SCR_MAPPING, OT_SCR_MAPPING,
OT_SCR_MENDING,
OT_SCR_MINDSCAN, OT_SCR_MINDSCAN,
OT_SCR_PERMENANCE, OT_SCR_PERMENANCE,
OT_SCR_ENCHANT, OT_SCR_ENCHANT,
@ -697,12 +780,17 @@ enum OBTYPE {
OT_MAN_LISTEN, OT_MAN_LISTEN,
OT_MAN_LOCKPICKING, OT_MAN_LOCKPICKING,
OT_MAN_MAGITEMUSAGE, OT_MAN_MAGITEMUSAGE,
OT_MAN_RESEARCH,
OT_MAN_SHIELDS, OT_MAN_SHIELDS,
OT_MAN_SPELLCASTING, OT_MAN_SPELLCASTING,
OT_MAN_SPOTHIDDEN, OT_MAN_SPOTHIDDEN,
OT_MAN_STEALTH, OT_MAN_STEALTH,
OT_MAN_TECHUSAGE, OT_MAN_TECHUSAGE,
// manuals of knowledge
OT_MAN_LORE_ARCANA,
OT_MAN_LORE_DEMONS,
OT_MAN_LORE_HUMANOID,
OT_MAN_LORE_NATURE,
OT_MAN_LORE_UNDEAD,
// manuals of weaponry // manuals of weaponry
OT_MAN_AXES, OT_MAN_AXES,
OT_MAN_CLUBS, OT_MAN_CLUBS,
@ -716,7 +804,7 @@ enum OBTYPE {
OT_MAN_SS_AIR, OT_MAN_SS_AIR,
OT_MAN_SS_DEATH, OT_MAN_SS_DEATH,
OT_MAN_SS_DIVINATION, OT_MAN_SS_DIVINATION,
OT_MAN_SS_EARTH, OT_MAN_SS_NATURE,
OT_MAN_SS_FIRE, OT_MAN_SS_FIRE,
OT_MAN_SS_ICE, OT_MAN_SS_ICE,
OT_MAN_SS_GRAVITY, OT_MAN_SS_GRAVITY,
@ -747,6 +835,7 @@ enum OBTYPE {
OT_SB_MAPPING, OT_SB_MAPPING,
// -- elemental - air // -- elemental - air
OT_SB_AIRBLAST, OT_SB_AIRBLAST,
OT_SB_CALLLIGHTNING,
OT_SB_CLOUDKILL, OT_SB_CLOUDKILL,
// -- elemental - fire // -- elemental - fire
OT_SB_SPARK, OT_SB_SPARK,
@ -786,9 +875,11 @@ enum OBTYPE {
OT_SB_INVISIBILITY, OT_SB_INVISIBILITY,
OT_SB_LIGHT, OT_SB_LIGHT,
OT_SB_DARKNESS, OT_SB_DARKNESS,
OT_SB_MENDING,
OT_SB_PASSWALL, OT_SB_PASSWALL,
OT_SB_PETRIFY, OT_SB_PETRIFY,
OT_SB_POLYMORPH, OT_SB_POLYMORPH,
OT_SB_STICKTOSNAKE,
// -- summoning // -- summoning
OT_SB_CREATEMONSTER, OT_SB_CREATEMONSTER,
// -- translocation // -- translocation
@ -840,8 +931,6 @@ enum OBTYPE {
OT_S_COLDBURST, OT_S_COLDBURST,
OT_S_CONECOLD, OT_S_CONECOLD,
OT_S_FREEZEOB, OT_S_FREEZEOB,
// -- elemental - earth
OT_S_DIG,
// -- gravity // -- gravity
OT_S_GRAVLOWER, OT_S_GRAVLOWER,
OT_S_GRAVBOOST, OT_S_GRAVBOOST,
@ -861,17 +950,39 @@ enum OBTYPE {
OT_S_PSYARMOUR, OT_S_PSYARMOUR,
OT_S_CHARM, OT_S_CHARM,
// -- modification // -- modification
OT_S_DARKNESS,
OT_S_ENCHANT, OT_S_ENCHANT,
OT_S_GASEOUSFORM, OT_S_GASEOUSFORM,
OT_S_INSCRIBE, OT_S_INSCRIBE,
OT_S_INVISIBILITY, OT_S_INVISIBILITY,
OT_S_KNOCK, OT_S_KNOCK,
OT_S_LIGHT, OT_S_LIGHT,
OT_S_DARKNESS, OT_S_MENDING,
OT_S_PASSWALL, OT_S_PASSWALL,
OT_S_PETRIFY, OT_S_PETRIFY,
OT_S_POLYMORPH, OT_S_POLYMORPH,
OT_S_POLYMORPHRND, OT_S_POLYMORPHRND,
// nature
OT_S_BARKSKIN,
OT_S_CALLLIGHTNING,
OT_S_CALMANIMALS,
OT_S_CALMINGSCENT,
OT_S_CHARMANIMAL,
OT_S_CUREPOISON,
OT_S_DETECTPOISON,
OT_S_DIG,
OT_S_WEB,
OT_S_ENDUREELEMENTS,
OT_S_ENTANGLE,
OT_S_HAILSTORM,
OT_S_PURIFYFOOD,
OT_S_QUENCH,
OT_S_LESSENPOISON,
OT_S_REPELINSECTS,
OT_S_SLEETSTORM,
OT_S_SOFTENEARTH,
OT_S_STICKTOSNAKE,
OT_S_WARPWOOD,
// -- summoning // -- summoning
OT_S_CREATEMONSTER, OT_S_CREATEMONSTER,
// -- translocation // -- translocation
@ -895,9 +1006,11 @@ enum OBTYPE {
OT_A_LEVELUP, OT_A_LEVELUP,
// abilities // abilities
OT_A_GRAB, OT_A_GRAB,
OT_A_CHARGE,
OT_A_CRUSH, OT_A_CRUSH,
OT_A_JUMP, OT_A_JUMP,
OT_A_SPRINT, OT_A_SPRINT,
OT_A_STINGACID, // need to define dam in f_canwill
OT_A_SWOOP, OT_A_SWOOP,
OT_A_EMPLOY, OT_A_EMPLOY,
OT_A_HEAVYBLOW, OT_A_HEAVYBLOW,
@ -905,7 +1018,6 @@ enum OBTYPE {
OT_A_INSPECT, OT_A_INSPECT,
OT_A_HURRICANESTRIKE, OT_A_HURRICANESTRIKE,
OT_A_POLYREVERT, OT_A_POLYREVERT,
OT_A_STINGACID, // need to define dam in f_canwill
OT_A_WARCRY, // uses F_NOISETEXT -> N_WARCRY if it is there. OT_A_WARCRY, // uses F_NOISETEXT -> N_WARCRY if it is there.
// otherwise 'shouts a blood-curdling war cry' // otherwise 'shouts a blood-curdling war cry'
// wands // wands
@ -959,6 +1071,8 @@ enum OBTYPE {
OT_BROKENGLASS, OT_BROKENGLASS,
OT_ICECHUNK, OT_ICECHUNK,
OT_ICESHEET, OT_ICESHEET,
OT_MUDPOOL,
OT_PUDDLEOIL,
OT_SPLASHWATER, OT_SPLASHWATER,
OT_PUDDLEWATER, OT_PUDDLEWATER,
OT_PUDDLEWATERL, OT_PUDDLEWATERL,
@ -977,13 +1091,17 @@ enum OBTYPE {
OT_FIRELARGE, OT_FIRELARGE,
OT_FIREMED, OT_FIREMED,
OT_FIRESMALL, OT_FIRESMALL,
OT_HAILSTORM,
OT_MAGICBARRIER, OT_MAGICBARRIER,
OT_STEAMCLOUD, OT_STEAMCLOUD,
OT_STEAMPUFF, OT_STEAMPUFF,
OT_SLEETSTORM,
OT_SMOKECLOUD, OT_SMOKECLOUD,
OT_SMOKEPUFF, OT_SMOKEPUFF,
OT_POISONCLOUD, OT_POISONCLOUD,
OT_POISONPUFF, OT_POISONPUFF,
OT_VINE,
OT_WEB,
// armour - body // armour - body
OT_ARMOURLEATHER, OT_ARMOURLEATHER,
OT_ARMOURRING, OT_ARMOURRING,
@ -1039,6 +1157,7 @@ enum OBTYPE {
OT_RING_CONTROL, OT_RING_CONTROL,
OT_RING_CON, OT_RING_CON,
OT_RING_DEX, OT_RING_DEX,
OT_RING_HUNGER,
OT_RING_IQ, OT_RING_IQ,
OT_RING_STR, OT_RING_STR,
OT_RING_MANA, OT_RING_MANA,
@ -1151,6 +1270,7 @@ enum BODYPART {
#define WE_WALKABLE 1 #define WE_WALKABLE 1
#define WE_EMPTY 2 #define WE_EMPTY 2
#define WE_PORTAL 3 #define WE_PORTAL 3
#define WE_NOTWALL 4
enum NOISETYPE { enum NOISETYPE {
N_GETANGRY, N_GETANGRY,
@ -1196,6 +1316,7 @@ enum FLAG {
F_CONTAINSOB, // for vending machiens. v0 is ob letter F_CONTAINSOB, // for vending machiens. v0 is ob letter
// text is an object it contains. // text is an object it contains.
F_IDWHENUSED, // fully identify an object when worn/weilded/operated/etc F_IDWHENUSED, // fully identify an object when worn/weilded/operated/etc
F_STARTBLESSED, // v0 = b_blessed or b_cursed
// for items in shops // for items in shops
F_SHOPITEM, // causes shops to show this item as identified F_SHOPITEM, // causes shops to show this item as identified
F_VALUE, // how much an item is worth (over its base weight+material) F_VALUE, // how much an item is worth (over its base weight+material)
@ -1213,7 +1334,9 @@ enum FLAG {
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
F_BLOCKSVIEW, // cannot see past this F_BLOCKSVIEW, // cannot see past this
F_BLOCKSTHROW, // cannot throw past this F_BLOCKSTHROW, // cannot throw past this
F_DIETEXT, // text when the object dies F_THEREISHERE, // announce "there is xx here!", not "you see xx here"
// text[0] is punctuation to use.
F_OBDIETEXT, // text when the object dies
F_DIECONVERTTEXT, // text when the object converts. eg. "melts" F_DIECONVERTTEXT, // text when the object converts. eg. "melts"
F_DIECONVERTTEXTPL, // text when the object converts, if there are more than 1. eg. "melt" F_DIECONVERTTEXTPL, // text when the object converts, if there are more than 1. eg. "melt"
F_DIECONVERT, // val0 = what this turns into when dying F_DIECONVERT, // val0 = what this turns into when dying
@ -1241,9 +1364,7 @@ enum FLAG {
F_HITCONFER, // hitting with this gives flagid=v0 F_HITCONFER, // hitting with this gives flagid=v0
// unless you pass a val1 skillcheck, diff val2 // unless you pass a val1 skillcheck, diff val2
// with timeleft = text ("min-max") // with timeleft = text ("min-max")
F_HITPOISONTYPE, // used when you have f_hitconfer->f_poisoned. F_HITCONFERVALS,// specifies values for conferred flag.
// v0 is type of poison.
// v1 is power (NA means 1)
F_ACTIVATED, // val0 = is this object turned on? F_ACTIVATED, // val0 = is this object turned on?
F_GRENADE, // this obkejct will drain charge when activated, then die F_GRENADE, // this obkejct will drain charge when activated, then die
F_EXPLODEONDEATH, // explodes when it dies, deals TEXT damage. F_EXPLODEONDEATH, // explodes when it dies, deals TEXT damage.
@ -1299,14 +1420,25 @@ enum FLAG {
// ob interaction flags // ob interaction flags
F_HARD, // object is hard (ie. punching it will hurt!) F_HARD, // object is hard (ie. punching it will hurt!)
F_REDUCEMOVEMENT, // time to move off here is multiplied by v0.
F_RESTRICTMOVEMENT, // must pass a diff=v0 STR check to move off it.
// if v1 is B_TRUE, then it takes 1 damage if you fail.
//
// for multiple objects, each one adds half its difficulty
F_RODSHAPED, // for sticks-to-snakes
F_SHARP, // does damage when you step on it. v0/1 are min/max dam F_SHARP, // does damage when you step on it. v0/1 are min/max dam
F_SCARY, // gives other lfs a penalty to morale checks against you, F_SCARY, // gives other lfs a penalty to morale checks against you,
// v0 = penalty amt. // v0 = penalty amt.
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)
// v0 = how long it will burn for
// text (optional) = what it will convert to
// instead of just being set alight
F_CANGETWET, // object will get F_WET if hit by water F_CANGETWET, // object will get F_WET if hit by water
// v0 = enum WETNESS. v1 = how long // v0 = enum WETNESS. v1 = how long
F_WATERPROOF, // object doesn't get wet. note: overrides CANGETWET!
F_WET, // object is wet F_WET, // object is wet
F_RUSTED, // object is rusty F_RUSTED, // object is rusty
// v0 = enum RUSTINESS. // v0 = enum RUSTINESS.
@ -1378,6 +1510,9 @@ enum FLAG {
F_IDENTIFIED, // whether this object is fully identified F_IDENTIFIED, // whether this object is fully identified
// bad flags // bad flags
F_WALKDAM, // val0 = damtype, text = dam per sec F_WALKDAM, // val0 = damtype, text = dam per sec
F_WALKDAMBP, // v0 = bodypart, v1 = damtype, text = dam per sec
// if v2 == FALLTHRU, damage falls through to lf if
// no armour is there.
// abilities // abilities
F_NEEDSGRAB, // this ability needs to to grab someone first. F_NEEDSGRAB, // this ability needs to to grab someone first.
F_NOANNOUNCE, // don't announce when you gain/lose this ability F_NOANNOUNCE, // don't announce when you gain/lose this ability
@ -1409,6 +1544,7 @@ enum FLAG {
// lifeform flags / lf flags // lifeform flags / lf flags
F_DEBUG, // debugging enabled F_DEBUG, // debugging enabled
F_ACCURACYMOD, // modify your accuracy by val0 F_ACCURACYMOD, // modify your accuracy by val0
F_VEGETARIAN, // this lf will not eat meat.
F_SHIELDPENALTY, // lower your accuracy by val0 due to a cumbersome F_SHIELDPENALTY, // lower your accuracy by val0 due to a cumbersome
// shield // shield
F_LEVRACE, // at level v0, this race is promoted to race v1 F_LEVRACE, // at level v0, this race is promoted to race v1
@ -1430,6 +1566,8 @@ enum FLAG {
F_STARTOBCLASS, // val0 = %chance of starting with obclass val1 F_STARTOBCLASS, // val0 = %chance of starting with obclass val1
F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid
F_STARTATT, // val0 = A_xxx, val0 = start bracket (ie. IQ_GENIUS) F_STARTATT, // val0 = A_xxx, val0 = start bracket (ie. IQ_GENIUS)
F_STARTHIDDENPCT, // val0 = pct chance auto-generated monster will
// start off hidden
F_CORPSETYPE, // text field specifies what corpse obtype to leave F_CORPSETYPE, // text field specifies what corpse obtype to leave
F_MYCORPSE, // text field contains obid of my corpse. F_MYCORPSE, // text field contains obid of my corpse.
// (for ghosts) // (for ghosts)
@ -1444,7 +1582,7 @@ enum FLAG {
// (text is a long) // (text is a long)
// ABILITY/SPELL FLAGS / ability flags / 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, v1 is ongoing mpcost, v2 is power
F_SWOOPRANGE, // v0 = how far a flying creature can swoop 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
@ -1466,7 +1604,10 @@ enum FLAG {
F_FLEEONHPPCT, // lf will run away if its hp drop to v0% or lower F_FLEEONHPPCT, // lf will run away if its hp drop to v0% or lower
F_NOFLEE, // lf will not run away F_NOFLEE, // lf will not run away
F_TARGET, // lf will attack lfid v0. lastknown x/y is v1/v2 F_TARGET, // lf will attack lfid v0. lastknown x/y is v1/v2
F_IGNORECELL, // won't accept targetcells of v0=x v1=y
// this is cleared at start of turn.
F_TARGETCELL, // lf will go towards this place. val0=x,val1=y F_TARGETCELL, // lf will go towards this place. val0=x,val1=y
// optional: v2 = mr_lf or mr_ob. text=lf or ob id.
F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed
// by them again until they go out of sight. // by them again until they go out of sight.
F_FLEEFROM, // lf will run away from this lf id F_FLEEFROM, // lf will run away from this lf id
@ -1479,6 +1620,8 @@ enum FLAG {
// text is "verb^noun" // text is "verb^noun"
// eg. "shouts^a shout" // eg. "shouts^a shout"
F_SPELLCASTTEXT, // text is announcement for spellcast F_SPELLCASTTEXT, // text is announcement for spellcast
// if text is empty, then don't announce
// this lf's spell casting at all.
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
F_BEHEADED, // use special corpse drop code F_BEHEADED, // use special corpse drop code
F_SILENTMOVE, // lf makes no noise when walking/flying F_SILENTMOVE, // lf makes no noise when walking/flying
@ -1523,6 +1666,7 @@ enum FLAG {
// INTRINSICS // INTRINSICS
F_MAGICARMOUR,// armour is magically boosted. f->text is the description F_MAGICARMOUR,// armour is magically boosted. f->text is the description
// ie 'magic armour', 'force field' // ie 'magic armour', 'force field'
// v0 is power left.
F_ASLEEP, // is asleep F_ASLEEP, // is asleep
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
@ -1557,6 +1701,8 @@ enum FLAG {
F_EXTRAMP, // lf has +v0 % extra maxmp 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_FASTMETAB, // hunger counter increases faster, poison cures faster.
// v0 is multiplier.
F_FASTMOVE, // modifier for move speed F_FASTMOVE, // modifier for move speed
F_FASTACTMOVE, // modifier for action and move speed F_FASTACTMOVE, // modifier for action and move speed
F_POISONED, // has poisoning. v0 = poison type, F_POISONED, // has poisoning. v0 = poison type,
@ -1573,6 +1719,7 @@ enum FLAG {
// (bypasses armour) // (bypasses armour)
F_GRAVBOOSTED,// cannot walk or throw stuff F_GRAVBOOSTED,// cannot walk or throw stuff
F_PAIN, // take damage if you walk. v0=damtype,text is damage (xdy+z). F_PAIN, // take damage if you walk. v0=damtype,text is damage (xdy+z).
// if text not set, default dam is 1d2
F_PARALYZED,// cannot do anything F_PARALYZED,// cannot do anything
F_FROZEN, // made of ice F_FROZEN, // made of ice
F_LEVITATING, // like flying but uncontrolled F_LEVITATING, // like flying but uncontrolled
@ -1655,6 +1802,13 @@ enum FLAG {
F_NULL = -1 F_NULL = -1
}; };
// move reasons
enum MOVEREASON {
MR_OTHER,
MR_LF,
MR_OB,
};
// hunger levels // hunger levels
enum HUNGER { enum HUNGER {
@ -1678,6 +1832,8 @@ enum HUNGER {
#define B_FALSE (0) #define B_FALSE (0)
#define B_TRUE (-1) #define B_TRUE (-1)
#define FALLTHRU (-8765)
//#define B_TEMP (-1) //#define B_TEMP (-1)
//#define B_PERM (-2) //#define B_PERM (-2)
//#define B_NOT (-3) //#define B_NOT (-3)
@ -1797,6 +1953,7 @@ enum ERROR {
E_DRUNK = 47, E_DRUNK = 47,
// //
E_NOBP = 48, E_NOBP = 48,
E_VEGETARIAN = 49,
}; };
@ -1908,9 +2065,18 @@ typedef struct celltype_s {
} celltype_t; } celltype_t;
typedef struct raceclass_s {
enum RACECLASS id;
char *name;
char *pluralname;
enum SKILL skill;
struct raceclass_s *next, *prev;
} raceclass_t;
typedef struct race_s { typedef struct race_s {
enum RACE id; enum RACE id;
enum RACE baseid; enum RACE baseid;
struct raceclass_s *raceclass;
struct material_s *material; struct material_s *material;
char *name; char *name;
struct glyph_s glyph; struct glyph_s glyph;
@ -1962,7 +2128,6 @@ typedef struct lifeform_s {
int born; int born;
// for ai movement - don't need to save. // for ai movement - don't need to save.
struct cell_s *ignorecell;
struct cell_s *cell; struct cell_s *cell;
struct lifeform_s *next, *prev; struct lifeform_s *next, *prev;
@ -2010,59 +2175,6 @@ typedef struct material_s {
} material_t; } material_t;
enum SKILL {
SK_NONE = 0,
SK_ARMOUR = 1,
SK_ATHLETICS,
SK_BACKSTAB,
SK_FIRSTAID,
SK_LISTEN,
SK_LOCKPICKING,
SK_MAGITEMUSAGE,
SK_RESEARCH,
SK_SHIELDS,
SK_SPELLCASTING,
SK_SPOTHIDDEN,
SK_STEALTH,
SK_TECHUSAGE,
// weaponry
SK_AXES,
SK_CLUBS,
SK_LONGBLADES,
SK_POLEARMS,
SK_SHORTBLADES,
SK_STAVES,
SK_UNARMED,
// spell schools
SK_SS_ALLOMANCY,
SK_SS_AIR,
SK_SS_DEATH,
SK_SS_DIVINATION,
SK_SS_EARTH,
SK_SS_FIRE,
SK_SS_ICE,
SK_SS_GRAVITY,
SK_SS_LIFE,
SK_SS_MODIFICATION,
SK_SS_MENTAL,
SK_SS_SUMMONING,
SK_SS_TRANSLOCATION,
SK_SS_WILD,
};
#define MAXSKILLS 35
// proficiency levels
enum SKILLLEVEL {
PR_INEPT = 0,
PR_NOVICE = 1,
PR_BEGINNER = 2,
PR_ADEPT = 3,
PR_SKILLED = 4,
PR_EXPERT = 5,
PR_MASTER = 6,
};
typedef struct skill_s { typedef struct skill_s {
enum SKILL id; enum SKILL id;
char *name; char *name;

View File

@ -9,3 +9,5 @@ objects.c:
lf.c: lf.c:
add addskill() add addskill()
if it is a lroe skill, update isloreskill()

10
flag.c
View File

@ -395,7 +395,17 @@ void killflagpile(flagpile_t *fp) {
void timeeffectsflag(flag_t *f, int howlong) { void timeeffectsflag(flag_t *f, int howlong) {
if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) { if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) {
// special case - fast metabolism speeds up poison too.
if (f->id == F_POISONED) {
int multiplier;
sumflags(f->pile, F_FASTMETAB, &multiplier, NULL, NULL);
if (multiplier > 0) {
howlong *= multiplier;
}
}
f->lifetime -= howlong; f->lifetime -= howlong;
if (f->lifetime <= 0) { if (f->lifetime <= 0) {
killflag(f); killflag(f);
return; return;

568
io.c
View File

@ -382,6 +382,8 @@ cell_t *askcoords(char *prompt, int targettype) {
int valid = B_FALSE; int valid = B_FALSE;
if ((targettype & TT_MONSTER) && haslf(c) && cansee(player, c->lf) && (c->lf->controller != C_PLAYER)) { if ((targettype & TT_MONSTER) && haslf(c) && cansee(player, c->lf) && (c->lf->controller != C_PLAYER)) {
valid = B_TRUE; valid = B_TRUE;
} else if ((targettype & TT_ALLY) && haslf(c) && cansee(player, c->lf) && areallies(c->lf, player)) {
valid = B_TRUE;
} else if ((targettype & TT_PLAYER) && haslf(c) && cansee(player, c->lf) && isplayer(c->lf)) { } else if ((targettype & TT_PLAYER) && haslf(c) && cansee(player, c->lf) && isplayer(c->lf)) {
valid = B_TRUE; valid = B_TRUE;
} else if ((targettype & TT_OBJECT) && hasobject(c)) { } else if ((targettype & TT_OBJECT) && hasobject(c)) {
@ -443,7 +445,7 @@ cell_t *askcoords(char *prompt, int targettype) {
if (c->lf) { if (c->lf) {
if (cansee(player, c->lf)) { if (cansee(player, c->lf)) {
flag_t *f; flag_t *f;
object_t *wep; object_t *wep,*o;
char extrainfo[BUFLEN]; char extrainfo[BUFLEN];
strcpy(extrainfo, ""); strcpy(extrainfo, "");
getlfnamea(c->lf, buf); getlfnamea(c->lf, buf);
@ -488,8 +490,47 @@ cell_t *askcoords(char *prompt, int targettype) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "asleep"); strcat(extrainfo, "asleep");
} }
if ((getallegiance(c->lf) == AL_HOSTILE) &&
(getlorelevel(player, c->lf->race->raceclass->id) >= PR_ADEPT)) {
char dangerbuf[BUFLEN];
float rating;
rating = comparelfs(player, c->lf);
if (rating >= 4) {
sprintf(dangerbuf, "trivial");
} else if (rating >= 3) {
sprintf(dangerbuf, "very easy");
} else if (rating >= 2) {
sprintf(dangerbuf, "easy");
} else if (rating >= 1) {
sprintf(dangerbuf, "average");
} else if (rating >= 0.5) {
sprintf(dangerbuf, "challenging");
} else if (rating >= 0.25) {
sprintf(dangerbuf, "formidable");
} else if (rating >= 0.125) {
sprintf(dangerbuf, "dangerous");
} else {
sprintf(dangerbuf, "very dangerous");
}
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, dangerbuf);
}
o = hasobwithflag(c->obpile, F_RESTRICTMOVEMENT);
if (o) {
char buf2[BUFLEN];
char obname[BUFLEN];
if (strlen(extrainfo)) strcat(extrainfo, ", ");
getobname(o, obname, o->amt);
sprintf(buf2, "stuck in %s", obname);
strcat(extrainfo, buf2);
}
// hp // hp
if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) ) { if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) ||
(getlorelevel(player, c->lf->race->raceclass->id) >= PR_ADEPT)
) {
char buf2[BUFLEN]; char buf2[BUFLEN];
// show actual hp // show actual hp
sprintf(buf2, "hp %d/%d",c->lf->hp, c->lf->maxhp); sprintf(buf2, "hp %d/%d",c->lf->hp, c->lf->maxhp);
@ -505,6 +546,7 @@ cell_t *askcoords(char *prompt, int targettype) {
} }
} }
wep = getweapon(c->lf); wep = getweapon(c->lf);
if (wep && (c->lf->race->id != R_DANCINGWEAPON)) { if (wep && (c->lf->race->id != R_DANCINGWEAPON)) {
object_t *secwep; object_t *secwep;
@ -957,6 +999,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
msg("%s %s",lfname, isplayer(lf) ? "feel accelerated!" : "looks accelerated!"); msg("%s %s",lfname, isplayer(lf) ? "feel accelerated!" : "looks accelerated!");
donesomething = B_TRUE; donesomething = B_TRUE;
break; break;
case F_FASTMETAB:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel ravenous!");
donesomething = B_TRUE;
}
break;
case F_FASTMOVE: case F_FASTMOVE:
msg("%s %s faster.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving"); msg("%s %s faster.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
donesomething = B_TRUE; donesomething = B_TRUE;
@ -1240,6 +1288,9 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
char buf[BUFLEN]; char buf[BUFLEN];
getlfname(lf2, buf); getlfname(lf2, buf);
msg("%s break%s free of %s%s control!",lfname, isplayer(lf) ? "" : "s", buf,getpossessive(buf)); msg("%s break%s free of %s%s control!",lfname, isplayer(lf) ? "" : "s", buf,getpossessive(buf));
if (isplayer(lf2)) {
more();
}
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
@ -1299,6 +1350,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
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;
break; break;
case F_FASTMETAB:
if (isplayer(lf)) { // don't know if monsters lose it
msg("Your metabolic rate has returned to normal.");
donesomething = B_TRUE;
}
break;
case F_FASTMOVE: case F_FASTMOVE:
msg("%s %s slower.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving"); msg("%s %s slower.",lfname, isplayer(lf) ? "feel yourself moving" : "is now moving");
donesomething = B_TRUE; donesomething = B_TRUE;
@ -1581,6 +1638,7 @@ int announceobflaggain(object_t *o, flag_t *f) {
int donesomething = B_FALSE; int donesomething = B_FALSE;
char obname[BUFLEN]; char obname[BUFLEN];
char prefix[BUFLEN]; char prefix[BUFLEN];
int wantpremods = B_TRUE;
cell_t *loc; cell_t *loc;
loc = getoblocation(o); loc = getoblocation(o);
@ -1590,7 +1648,14 @@ int announceobflaggain(object_t *o, flag_t *f) {
if (!haslos(player, loc)) { if (!haslos(player, loc)) {
return B_FALSE; return B_FALSE;
} }
real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE);
if (f->id == F_ONFIRE) {
// don't want "the flaming sword catches on fire"
wantpremods = B_FALSE;
}
real_getobname(o, obname, o->amt, wantpremods, B_FALSE, B_TRUE, B_TRUE);
if (o->pile->owner) { if (o->pile->owner) {
if (isplayer(o->pile->owner)) { if (isplayer(o->pile->owner)) {
@ -1608,8 +1673,6 @@ int announceobflaggain(object_t *o, flag_t *f) {
switch (f->id) { switch (f->id) {
case F_ONFIRE: case F_ONFIRE:
donesomething = B_TRUE; donesomething = B_TRUE;
// don't want "the flaming sword catches on fire"
real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_TRUE, B_TRUE);
if (o->birthtime != curtime) msg("%s catch%s on fire.",prefix, (o->amt == 1) ? "es" : ""); if (o->birthtime != curtime) msg("%s catch%s on fire.",prefix, (o->amt == 1) ? "es" : "");
break; break;
case F_PRODUCESLIGHT: case F_PRODUCESLIGHT:
@ -1626,6 +1689,7 @@ void announceobflagloss(object_t *o, flag_t *f) {
char obname[BUFLEN]; char obname[BUFLEN];
char prefix[BUFLEN]; char prefix[BUFLEN];
char isare[BUFLEN]; char isare[BUFLEN];
char *temp;
cell_t *loc; cell_t *loc;
loc = getoblocation(o); loc = getoblocation(o);
@ -1657,7 +1721,12 @@ void announceobflagloss(object_t *o, flag_t *f) {
switch (f->id) { switch (f->id) {
case F_ONFIRE: case F_ONFIRE:
msg("%s %s no longer on fire.",prefix,isare); // replace "the flaming xxx is no longer on fire"
// with "the xxx is no longer on fire"
temp = strdup(prefix);
temp = strrep(temp, "flaming ","",NULL);
msg("%s %s no longer on fire.",temp,isare);
free(temp);
break; break;
case F_PRODUCESLIGHT: case F_PRODUCESLIGHT:
msg("%s %s no longer glowing.",prefix,isare); msg("%s %s no longer glowing.",prefix,isare);
@ -2544,9 +2613,11 @@ void describeob(object_t *o) {
} }
// now special flags... // skip line
y++; y++;
// physical properties
f = hasflag(o->flags, F_MASTERWORK); f = hasflag(o->flags, F_MASTERWORK);
if (f && f->known) { if (f && f->known) {
mvwprintw(mainwin, y, 0, "It is extremely well crafted."); mvwprintw(mainwin, y, 0, "It is extremely well crafted.");
@ -2569,17 +2640,22 @@ 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); f = hasflag(o->flags, F_RUSTED);
if (f) { if (f) {
mvwprintw(mainwin, y, 0, "It is rusty."); mvwprintw(mainwin, y, 0, "It is rusty.");
y++; y++;
} }
f = hasflag(o->flags, F_WATERPROOF);
if (f) {
mvwprintw(mainwin, y, 0, "It is waterproof.");
y++;
}
f = hasflag(o->flags, F_WET);
if (f) {
mvwprintw(mainwin, y, 0, "It is wet.");
y++;
}
f = hasflag(o->flags, F_ACTIVATED); f = hasflag(o->flags, F_ACTIVATED);
if (f) { if (f) {
@ -2650,6 +2726,9 @@ void describeob(object_t *o) {
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;
case F_FASTMETAB:
mvwprintw(mainwin, y, 0, "%s will increase your metabolic rate.", buf); y++;
break;
case F_FASTMOVE: case F_FASTMOVE:
mvwprintw(mainwin, y, 0, "%s will speed up your movement.", buf); y++; mvwprintw(mainwin, y, 0, "%s will speed up your movement.", buf); y++;
break; break;
@ -2796,13 +2875,39 @@ void describeob(object_t *o) {
y++; y++;
} }
// requirements
i = B_FALSE;
for (f = o->flags->first ; f ; f = f->next) {
if (f->id == F_ATTREQ) {
int usable = B_TRUE;
if (!meetsattreq(player, f, o)) {
usable = B_FALSE;
}
if (!usable) setcol(mainwin, C_RED);
mvwprintw(mainwin, y, 0, "It requires at least %d %s to use.", f->val[1], getattrname(f->val[0]));
y++;
if (!usable) unsetcol(mainwin, C_RED);
i = B_TRUE;
}
}
// blank line
y++; y++;
// skill type? // skill type?
f = hasflag(o->flags, F_USESSKILL); f = hasflag(o->flags, F_USESSKILL);
if (f) { if (f) {
mvwprintw(mainwin, y, 0, "It falls into the '%s' category (your skill: %s).",getskillname(f->val[0]), enum SKILLLEVEL slev;
getskilllevelname(getskill(player, f->val[0])) ); enum COLOUR col;
slev = getskill(player, f->val[0]);
mvwprintw(mainwin, y, 0, "It falls into the '%s' category (your skill: ",getskillname(f->val[0]));
col = getskilllevelcolour(slev);
setcol(mainwin, col);
wprintw(mainwin, "%s", getskilllevelname(getskill(player, f->val[0])) );
unsetcol(mainwin, col);
wprintw(mainwin, ")");
y++; y++;
} }
@ -2839,7 +2944,6 @@ void describeob(object_t *o) {
void describespell(objecttype_t *ot) { void describespell(objecttype_t *ot) {
char buf[BUFLEN]; char buf[BUFLEN];
int y;
flag_t *f; flag_t *f;
int i; int i;
int power; int power;
@ -2851,36 +2955,31 @@ void describespell(objecttype_t *ot) {
capitalise(buf); capitalise(buf);
mvwprintw(mainwin, 0, 0, buf); mvwprintw(mainwin, 0, 0, buf);
sprintf(buf, "%s",ot->desc); mvwprintw(mainwin, 2, 0,"%s\n\n", ot->desc);
mvwprintw(mainwin, 2, 0, buf);
// properties // properties
y = 5;
f = hasflag(ot->flags, F_SPELLLEVEL); f = hasflag(ot->flags, F_SPELLLEVEL);
if (f) { if (f) {
flag_t *sf; flag_t *sf;
sf = hasflag(ot->flags, F_SPELLSCHOOL); sf = hasflag(ot->flags, F_SPELLSCHOOL);
assert(sf); assert(sf);
mvwprintw(mainwin, y, 0, "It is a level %d %s spell.",f->val[0], getschoolname(sf->val[0])); wprintw(mainwin, "It is a level %d %s spell.\n",f->val[0], getschoolname(sf->val[0]));
y++;
} }
i = getmpcost(NULL, ot->id); i = getmpcost(NULL, ot->id);
if (i > 0) { if (i > 0) {
if (hasflag(ot->flags, F_ONGOING)) { if (hasflag(ot->flags, F_ONGOING)) {
mvwprintw(mainwin, y, 0, "It takes %d MP to keep active - this is an ongoing cost.",i); wprintw(mainwin, "It takes %d MP to keep active - this is an ongoing cost.\n",i);
} else { } else {
mvwprintw(mainwin, y, 0, "It costs %d MP to cast.",i); wprintw(mainwin, "It costs %d MP to cast.\n",i);
} }
y++;
} }
y++; wprintw(mainwin, "\n");
power = getspellpower(player, ot->id); power = getspellpower(player, ot->id);
mvwprintw(mainwin, y, 0, "You can cast it at power level %d (maximum %d).",power, getspellmaxpower(ot->id)); wprintw(mainwin, "You can cast it at power level %d (maximum %d).\n",power, getspellmaxpower(ot->id));
y++;
wrefresh(mainwin); wrefresh(mainwin);
@ -3044,7 +3143,7 @@ void docomms(void) {
// find adjacent cell // find adjacent cell
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
if (c) { if (c) {
aigoto(lf, c, AI_FOLLOWTIME); aigoto(lf, c, MR_OTHER, NULL, AI_FOLLOWTIME);
} }
break; break;
case 'n': case 'n':
@ -3227,7 +3326,7 @@ void doeat(obpile_t *op) {
// edible objects here? // edible objects here?
for (o = player->cell->obpile->first; o ; o = o->next) { for (o = player->cell->obpile->first; o ; o = o->next) {
if (isedible(o)) { if (caneat(player, o)) {
getobname(o, obname, o->amt); getobname(o, obname, o->amt);
sprintf(buf, "There %s %s here. Eat %s", sprintf(buf, "There %s %s here. Eat %s",
(o->amt == 1) ? "is" : "are", (o->amt == 1) ? "is" : "are",
@ -3491,6 +3590,24 @@ void dolook(cell_t *where) {
char buf[BUFLEN]; char buf[BUFLEN];
char seeverb[BUFLEN]; char seeverb[BUFLEN];
int seensomething = B_FALSE; int seensomething = B_FALSE;
object_t *o,*firstob = NULL;
flag_t *f;
// first announce "there is xxx" objects
// (also count objects without this flag)
numobs = 0;
for (o = where->obpile->first ; o ; o = o->next) {
f = hasflag(o->flags, F_THEREISHERE);
if (f) {
// doens't matter if you're blind
getobname(o, buf, o->amt);
msg("There is %s here%c", buf, f->text[0]);
seensomething = B_TRUE;
} else {
if (!numobs) firstob = o;
numobs++;
}
}
//if (isblind(player)) { //if (isblind(player)) {
if (!haslos(player, player->cell)) { if (!haslos(player, player->cell)) {
@ -3499,11 +3616,12 @@ void dolook(cell_t *where) {
strcpy(seeverb, "see"); strcpy(seeverb, "see");
} }
numobs = countobs(where->obpile);
if (numobs > 0) { if (numobs > 0) {
if (numobs == 1) { if (numobs == 1) {
getobname(where->obpile->first, buf, where->obpile->first->amt); if (!hasflag(firstob->flags, F_THEREISHERE)) {
msg("You %s %s here.", seeverb, buf); getobname(firstob, buf, firstob->amt);
msg("You %s %s here.", seeverb, buf);
}
} else if ((numobs > 1) && (numobs <= 3)) { } else if ((numobs > 1) && (numobs <= 3)) {
msg("You %s a few objects here.", seeverb); msg("You %s a few objects here.", seeverb);
} else if ((numobs > 3) && (numobs <= 6)) { } else if ((numobs > 3) && (numobs <= 6)) {
@ -3514,8 +3632,6 @@ 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:");
@ -3523,7 +3639,6 @@ void dolook(cell_t *where) {
seensomething = B_TRUE; seensomething = B_TRUE;
} }
if (!seensomething) { if (!seensomething) {
// just clear the message buffer // just clear the message buffer
//clearmsg(); //clearmsg();
@ -3549,7 +3664,7 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
int validspell[MAXCANDIDATES]; int validspell[MAXCANDIDATES];
int deactspell[MAXCANDIDATES]; int deactspell[MAXCANDIDATES];
int nposs = 0; int nposs = 0;
int i,n; int i,n,lev;
enum SPELLSCHOOL lastschool; enum SPELLSCHOOL lastschool;
objecttype_t *ot; objecttype_t *ot;
@ -3559,91 +3674,99 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
if ((wantschool != SS_NONE) && (i != wantschool)) { if ((wantschool != SS_NONE) && (i != wantschool)) {
continue; continue;
} }
// only god gets divine ones
if ((i == SS_DIVINE) && !hasjob(lf, J_GOD)) {
continue;
}
// we can't cast spells from this school? // we can't cast spells from this school?
if (getschoolskill(i) != SK_NONE) { if (getschoolskill(i) != SK_NONE) {
if (!getskill(lf, getschoolskill(i))) { if (!getskill(lf, getschoolskill(i))) {
continue; continue;
} }
} }
// get list of spells/abilities we can cast at will for (lev = 0; lev <= MAXSPELLLEV; lev++) {
for (ot = objecttype ; ot ; ot = ot->next) { // get list of spells/abilities we can cast at will
if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) {
f = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
if (!wantunknown && f) {
if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) {
poss[nposs] = ot->id;
deactspell[nposs] = B_FALSE; // default
mpcost[nposs] = -1;
if (f->val[2] == NA) {
sprintf(mpdesc[nposs], "(ready)");
validspell[nposs] = B_TRUE;
} else {
if (f->val[1] == f->val[2]) {
sprintf(mpdesc[nposs], "(ready)");
validspell[nposs] = B_TRUE;
} else {
sprintf(mpdesc[nposs], "(%d/%d)",f->val[1],f->val[2]);
validspell[nposs] = B_FALSE;
}
}
nposs++;
}
}
}
}
if (!lfhasflag(lf, F_NOSPELLS)) {
// get list of spells we can cast using mp
for (ot = objecttype ; ot ; ot = ot->next) { for (ot = objecttype ; ot ; ot = ot->next) {
if (ot->obclass->id == OC_SPELL) { // is it a spell? if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) {
if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) { // from the current school? // doesn't match the current level?
// not using 'cancast' here because we want to list spells if (getspelllevel(ot->id) == lev) {
// even if we don't have enough mp f = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
f = lfhasflagval(lf, F_CANCAST, ot->id, NA, NA, NULL); if (!wantunknown && f) {
if ((f && !wantunknown) || (!f && wantunknown)) { if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) {
int cost;
int found = B_FALSE;
cost = getmpcost(lf, ot->id);
for (n = 0; n < nposs; n++) {
if (poss[n] == ot->id) {
found = B_TRUE;
break;
}
}
if (!found) {
int power;
// add to list
poss[nposs] = ot->id; poss[nposs] = ot->id;
mpcost[nposs] = cost;
deactspell[nposs] = B_FALSE; // default deactspell[nposs] = B_FALSE; // default
power = getspellpower(lf, ot->id); mpcost[nposs] = -1;
if (power > 0) { if (f->val[2] == NA) {
if (hasactivespell(lf, ot->id)) { sprintf(mpdesc[nposs], "(ready)");
cost = 0; validspell[nposs] = B_TRUE;
mpcost[nposs] = 0; } else {
strcpy(mpdesc[nposs], "(Deactivate, at will)"); if (f->val[1] == f->val[2]) {
deactspell[nposs] = B_TRUE; sprintf(mpdesc[nposs], "(ready)");
} else {
getspellcosttext(lf, ot->id, power, mpdesc[nposs]);
}
if (lf->mp >= mpcost[nposs]) {
validspell[nposs] = B_TRUE; validspell[nposs] = B_TRUE;
} else { } else {
sprintf(mpdesc[nposs], "(%d/%d)",f->val[1],f->val[2]);
validspell[nposs] = B_FALSE; validspell[nposs] = B_FALSE;
} }
} else {
sprintf(mpdesc[nposs], "(too hard)");
validspell[nposs] = B_FALSE;
} }
nposs++; nposs++;
} }
} }
} // end if level ok
} // end if spell/ability
} // end foreach objecttype
if (!lfhasflag(lf, F_NOSPELLS)) {
// get list of spells we can cast using mp
for (ot = objecttype ; ot ; ot = ot->next) {
if ((ot->obclass->id == OC_SPELL) && (getspelllevel(ot->id) == lev)) { // is it a spell?
if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) { // from the current school?
// not using 'cancast' here because we want to list spells
// even if we don't have enough mp
f = lfhasflagval(lf, F_CANCAST, ot->id, NA, NA, NULL);
if ((f && !wantunknown) || (!f && wantunknown)) {
int cost;
int found = B_FALSE;
cost = getmpcost(lf, ot->id);
for (n = 0; n < nposs; n++) {
if (poss[n] == ot->id) {
found = B_TRUE;
break;
}
}
if (!found) {
int power;
// add to list
poss[nposs] = ot->id;
mpcost[nposs] = cost;
deactspell[nposs] = B_FALSE; // default
power = getspellpower(lf, ot->id);
if (power > 0) {
if (hasactivespell(lf, ot->id)) {
cost = 0;
mpcost[nposs] = 0;
strcpy(mpdesc[nposs], "(Deactivate, at will)");
deactspell[nposs] = B_TRUE;
} else {
getspellcosttext(lf, ot->id, power, mpdesc[nposs]);
}
if (lf->mp >= mpcost[nposs]) {
validspell[nposs] = B_TRUE;
} else {
validspell[nposs] = B_FALSE;
}
} else {
sprintf(mpdesc[nposs], "(too hard)");
validspell[nposs] = B_FALSE;
}
nposs++;
}
}
}
} }
} }
} }
} } // end foreach spell level
} // end foreach spell school } // end foreach spell school
@ -3661,16 +3784,16 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
lastschool = SS_LAST; lastschool = SS_LAST;
for (i = 0; i < nposs; i++) { for (i = 0; i < nposs; i++) {
int power; int power;
enum SPELLSCHOOL thisschool = SS_NONE;
ot = findot(poss[i]); ot = findot(poss[i]);
assert(ot); assert(ot);
power = getspellpower(lf, poss[i]); power = getspellpower(lf, poss[i]);
// heading // heading
f = hasflag(ot->flags, F_SPELLSCHOOL); thisschool = getspellschoolknown(lf, poss[i]);
assert(f); if (thisschool != lastschool) {
if (f->val[0] != lastschool) { lastschool = thisschool;
lastschool = f->val[0];
addheading(pr, getschoolname(lastschool)); addheading(pr, getschoolname(lastschool));
} }
@ -4322,7 +4445,7 @@ int dotakeoff(obpile_t *op) {
int rv = B_TRUE; int rv = B_TRUE;
// ask which object to read // ask which object to read
o = askobject(op, "Take off what", NULL, AO_EQUIPPEDARMOUR ); o = askobject(op, "Take off what", NULL, AO_EQUIPPEDNONWEAPON );
if (o) { if (o) {
if (isarmour(o)) { if (isarmour(o)) {
f = hasflag(o->flags, F_EQUIPPED); f = hasflag(o->flags, F_EQUIPPED);
@ -5086,6 +5209,24 @@ int getkey(void) {
return keycodetokey(key_code); return keycodetokey(key_code);
} }
enum COLOUR getskilllevelcolour(enum SKILLLEVEL slev) {
switch (slev) {
case PR_INEPT:
return C_RED;
case PR_BEGINNER:
case PR_NOVICE:
return C_BROWN;
case PR_ADEPT:
return C_GREEN;
case PR_SKILLED:
case PR_EXPERT:
return C_BOLDGREEN;
case PR_MASTER:
return C_BOLDCYAN;
}
return C_GREY;
}
void handleinput(void) { void handleinput(void) {
int ch; int ch;
//char buf[BUFLEN]; //char buf[BUFLEN];
@ -5103,8 +5244,10 @@ void handleinput(void) {
object_t *o; object_t *o;
// certain objects will stop us from running.
for (o = player->cell->obpile->first ; o ; o = o->next) { for (o = player->cell->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP)) { if (!hasflag(o->flags, F_NOPICKUP) ||
hasflag(o->flags, F_CLIMBABLE) ) {
hasgettableobs = B_TRUE; hasgettableobs = B_TRUE;
break; break;
} }
@ -5503,7 +5646,6 @@ void warn(char *format, ... ) {
// like msg, but interrupts rest ect // like msg, but interrupts rest ect
interrupt(player); interrupt(player);
va_start(args, format); va_start(args, format);
vsprintf( buf, format, args ); vsprintf( buf, format, args );
@ -6012,16 +6154,26 @@ void showlfarmour(lifeform_t *lf) {
for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) { for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) {
char rhs[BUFLEN]; char rhs[BUFLEN];
// default // default
sprintf(rhs, "-"); strcpy(rhs, "");
if (!lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) { if (!lfhasflagval(lf, F_NOBODYPART, bp, NA, NA, NULL)) {
object_t *outerob;
sprintf(buf, "%15s:%3s",getbodypartname(bp), " "); sprintf(buf, "%15s:%3s",getbodypartname(bp), " ");
o = hasobwithflagval(lf->pack, F_EQUIPPED, bp, NA, NA, NULL); o = getequippedob(lf->pack, bp);
outerob = getouterequippedob(lf, bp);
if (o) { if (o) {
char obname[BUFLEN]; char obname[BUFLEN];
getobname(o, obname, o->amt); getobname(o, obname, o->amt);
strcpy(rhs, obname); strcpy(rhs, obname);
} else { }
if (outerob && (outerob != o)) {
char outerobname[BUFLEN];
getobname(outerob, outerobname, outerob->amt);
if (strlen(rhs)) strcat(rhs, " ");
strcat(rhs, "(covered) ");
}
if (!strlen(rhs)) {
strcpy(rhs, "-"); strcpy(rhs, "-");
} }
@ -6088,17 +6240,33 @@ void showlfstats(lifeform_t *lf, int showall) {
char prompt[BUFLEN]; char prompt[BUFLEN];
char cmdchars[BUFLEN]; char cmdchars[BUFLEN];
int done = B_FALSE; int done = B_FALSE;
enum SKILLLEVEL lorelev;
enum COLOUR lorecol;
h = getmaxy(mainwin); h = getmaxy(mainwin);
// determine knowledge about this monster
lorelev = getlorelevel(player, lf->race->raceclass->id);
if (isplayer(lf)) {
lorecol = C_GREY; // ie. no colour
} else if (lorelev == PR_MASTER) {
lorecol = C_GREY; // ie. no colour
} else {
lorecol = C_BROWN;
}
// override showall sometimes... // override showall sometimes...
// need 'player == lf' to cope with mind scans // need 'player == lf' to cope with mind scans
// where we update the player pointer, but don't // where we update the player pointer, but don't
// change the target's '->controller' setting (meaning // change the target's '->controller' setting (meaning
// that isplayer(target) still returns false). // that isplayer(target) still returns false).
if (isplayer(lf) || isgenius(player) || (player == lf)) { if (isplayer(lf) || isgenius(player) || (player == lf) || (lorelev >= PR_MASTER)) {
showall = B_TRUE; showall = B_TRUE;
} }
if (showall) { if (showall) {
sprintf(prompt, "[@=stats S=skills/abilities M=magic E=effects %sESC=quit]", isplayer(lf) ? "" : "I=items " ); sprintf(prompt, "[@=stats S=skills/abilities M=magic E=effects %sESC=quit]", isplayer(lf) ? "" : "I=items " );
@ -6140,7 +6308,8 @@ void showlfstats(lifeform_t *lf, int showall) {
j = getjob(lf); j = getjob(lf);
if (j) { if (j) {
mvwprintw(mainwin, y, 0, ftext, "Job"); mvwprintw(mainwin, y, 0, ftext, "Job");
wprintw(mainwin, "%-20s", j->name); y++; sprintf(buf, "Level %d %s", lf->level, j->name);
wprintw(mainwin, "%-20s", buf); y++;
} }
@ -6159,9 +6328,13 @@ void showlfstats(lifeform_t *lf, int showall) {
if (showall || (getseenlfconditioncutoff(player) == C_HEALTHY)) { if (showall ||
(getseenlfconditioncutoff(player) == C_HEALTHY) ||
(lorelev >= PR_ADEPT)) {
if (lorelev >= PR_ADEPT) setcol(mainwin, lorecol);
mvwprintw(mainwin, y, 0, ftext, "Hit Points"); mvwprintw(mainwin, y, 0, ftext, "Hit Points");
wprintw(mainwin, "%d / %d", lf->hp , lf->maxhp); y++; wprintw(mainwin, "%d / %d", lf->hp , lf->maxhp); y++;
if (lorelev >= PR_ADEPT) unsetcol(mainwin, lorecol);
} else { } else {
char hpinfo[BUFLEN]; char hpinfo[BUFLEN];
sprintf(hpinfo, "%s",getseenlfconditionname(lf, player)); sprintf(hpinfo, "%s",getseenlfconditionname(lf, player));
@ -6222,14 +6395,16 @@ void showlfstats(lifeform_t *lf, int showall) {
if (str != lf->baseatt[A_STR]) strcat(buf, "*"); if (str != lf->baseatt[A_STR]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "STR"); mvwprintw(mainwin, y, 0, ftext, "STR");
wprintw(mainwin, "%s", buf); y++; wprintw(mainwin, "%s", buf); y++;
} else if (!isplayer(lf)) { } else if (!isplayer(lf) && (lorelev >= PR_NOVICE)) {
int str; int str;
// just show name // just show name
str = getattr(lf, A_STR); str = getattr(lf, A_STR);
getstrname(str, buf); getstrname(str, buf);
if (str != lf->baseatt[A_STR]) strcat(buf, "*"); if (str != lf->baseatt[A_STR]) strcat(buf, "*");
setcol(mainwin, lorecol);
mvwprintw(mainwin, y, 0, ftext, "STR"); mvwprintw(mainwin, y, 0, ftext, "STR");
wprintw(mainwin, "%s", buf); y++; wprintw(mainwin, "%s", buf); y++;
unsetcol(mainwin, lorecol);
} }
if (showall) { if (showall) {
@ -6249,14 +6424,16 @@ void showlfstats(lifeform_t *lf, int showall) {
if (dex != lf->baseatt[A_DEX]) strcat(buf, "*"); if (dex != lf->baseatt[A_DEX]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "DEX"); mvwprintw(mainwin, y, 0, ftext, "DEX");
wprintw(mainwin, "%s", buf); y++; wprintw(mainwin, "%s", buf); y++;
} else if (!isplayer(lf)) { } else if (!isplayer(lf) && (lorelev >= PR_NOVICE)) {
int dex; int dex;
// just show name // just show name
dex = getattr(lf, A_DEX); dex = getattr(lf, A_DEX);
getdexname(dex, buf); getdexname(dex, buf);
if (dex != lf->baseatt[A_DEX]) strcat(buf, "*"); if (dex != lf->baseatt[A_DEX]) strcat(buf, "*");
setcol(mainwin, lorecol);
mvwprintw(mainwin, y, 0, ftext, "DEX"); mvwprintw(mainwin, y, 0, ftext, "DEX");
wprintw(mainwin, "%s", buf); y++; wprintw(mainwin, "%s", buf); y++;
unsetcol(mainwin, lorecol);
} }
if (showall) { if (showall) {
@ -6268,14 +6445,16 @@ void showlfstats(lifeform_t *lf, int showall) {
if (iq != lf->baseatt[A_IQ]) strcat(buf, "*"); if (iq != lf->baseatt[A_IQ]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "IQ"); mvwprintw(mainwin, y, 0, ftext, "IQ");
wprintw(mainwin, "%s", buf); y++; wprintw(mainwin, "%s", buf); y++;
} else if (!isplayer(lf)) { } else if (!isplayer(lf) && (lorelev >= PR_NOVICE)) {
int iq; int iq;
// just show name // just show name
iq = getattr(lf, A_IQ); iq = getattr(lf, A_IQ);
getiqname(iq, buf); getiqname(iq, buf);
if (iq != lf->baseatt[A_IQ]) strcat(buf, "*"); if (iq != lf->baseatt[A_IQ]) strcat(buf, "*");
setcol(mainwin, lorecol);
mvwprintw(mainwin, y, 0, ftext, "IQ"); mvwprintw(mainwin, y, 0, ftext, "IQ");
wprintw(mainwin, "%s", buf); y++; wprintw(mainwin, "%s", buf); y++;
unsetcol(mainwin, lorecol);
} }
if (showall) { if (showall) {
@ -6287,14 +6466,16 @@ void showlfstats(lifeform_t *lf, int showall) {
if (con != lf->baseatt[A_CON]) strcat(buf, "*"); if (con != lf->baseatt[A_CON]) strcat(buf, "*");
mvwprintw(mainwin, y, 0, ftext, "CON"); mvwprintw(mainwin, y, 0, ftext, "CON");
wprintw(mainwin, "%s", buf); y++; wprintw(mainwin, "%s", buf); y++;
} else if (!isplayer(lf)) { } else if (!isplayer(lf) && (lorelev >= PR_NOVICE)) {
int con; int con;
// just show name // just show name
con = getattr(lf, A_CON); con = getattr(lf, A_CON);
getconname(con, buf); getconname(con, buf);
if (con != lf->baseatt[A_CON]) strcat(buf, "*"); if (con != lf->baseatt[A_CON]) strcat(buf, "*");
setcol(mainwin, lorecol);
mvwprintw(mainwin, y, 0, ftext, "CON"); mvwprintw(mainwin, y, 0, ftext, "CON");
wprintw(mainwin, "%s", buf); y++; wprintw(mainwin, "%s", buf); y++;
unsetcol(mainwin, lorecol);
} }
//mvwprintw(mainwin, y, 0, ftext, "XP"); //mvwprintw(mainwin, y, 0, ftext, "XP");
@ -6357,6 +6538,14 @@ void showlfstats(lifeform_t *lf, int showall) {
acc = getlfaccuracy(lf, w); acc = getlfaccuracy(lf, w);
mvwprintw(mainwin, y2, x2, ftext, "Wep.Accuracy"); mvwprintw(mainwin, y2, x2, ftext, "Wep.Accuracy");
wprintw(mainwin, "%d%%", acc); y2++; wprintw(mainwin, "%d%%", acc); y2++;
// attack speed
speed = getattackspeed(lf);
getspeedname(speed, buf);
capitalise(buf);
mvwprintw(mainwin, y2, x2, ftext, "Attack Speed");
wprintw(mainwin, "%-20s", buf); y2++;
} }
} else { } else {
// no damage // no damage
@ -6386,10 +6575,11 @@ void showlfstats(lifeform_t *lf, int showall) {
ot = findot(f->val[0]); ot = findot(f->val[0]);
o = addob(op, ot->name); o = addob(op, ot->name);
if (o) { if (o) {
char dambuf[BUFLEN];
strcpy(dambuf, "");
sprintf(buf, "%s", o->type->name); sprintf(buf, "%s", o->type->name);
// damage // damage
if (showall) { if (showall || (lorelev >= PR_BEGINNER)) {
char dambuf[BUFLEN];
int mindam,maxdam; int mindam,maxdam;
getdamrange(f, &mindam, &maxdam); getdamrange(f, &mindam, &maxdam);
@ -6403,11 +6593,16 @@ void showlfstats(lifeform_t *lf, int showall) {
if (maxdam < 0) maxdam = 0; if (maxdam < 0) maxdam = 0;
sprintf(dambuf, " (%d-%d dmg)",(int)mindam,(int)maxdam); sprintf(dambuf, " (%d-%d dmg)",(int)mindam,(int)maxdam);
strcat(buf, dambuf);
} }
mvwprintw(mainwin, y2, x2, ftext, "Innate Attack"); mvwprintw(mainwin, y2, x2, ftext, "Innate Attack");
wprintw(mainwin, "%-20s", buf); y2++; wprintw(mainwin, "%s", buf);
if (strlen(dambuf)) {
if (lorelev >= PR_BEGINNER) setcol(mainwin, lorecol);
wprintw(mainwin, "%s", dambuf);
if (lorelev >= PR_BEGINNER) unsetcol(mainwin, lorecol);
}
y2++;
} // end if o } // end if o
} // end if fid == hasattack } // end if fid == hasattack
@ -6424,28 +6619,24 @@ void showlfstats(lifeform_t *lf, int showall) {
// skip line // skip line
y2++; y2++;
// attack speed
if (w || op->first) {
speed = getattackspeed(lf);
getspeedname(speed, buf);
capitalise(buf);
mvwprintw(mainwin, y2, x2, ftext, "Attack Speed");
wprintw(mainwin, "%-20s", buf); y2++;
}
killobpile(op); killobpile(op);
y2++; // skip line
// ARMOUR STUFF // ARMOUR STUFF
if (showall) { if (showall || (lorelev >= PR_NOVICE)) {
arating = getarmourrating(lf); arating = getarmourrating(lf);
mvwprintw(mainwin, y2, x2, ftext, "Armour");
if (lorelev >= PR_NOVICE) setcol(mainwin, lorecol);
mvwprintw(mainwin, y2, x2, ftext, "Armour Rating");
if (arating > 0) { if (arating > 0) {
wprintw(mainwin, "%d (-%0.0f%% dmg)", arating, getdamreducepct(arating)); y2++; wprintw(mainwin, "%d (-%0.0f%% dmg)", arating, getdamreducepct(arating)); y2++;
} else { } else {
wprintw(mainwin, "%d", arating); y2++; wprintw(mainwin, "%d", arating); y2++;
} }
if (lorelev >= PR_NOVICE) unsetcol(mainwin, lorecol);
}
if (showall) {
evasion = getevasion(lf); evasion = getevasion(lf);
mvwprintw(mainwin, y2, x2, ftext, "Evasion"); mvwprintw(mainwin, y2, x2, ftext, "Evasion");
wprintw(mainwin, "%d%%", evasion); y2++; wprintw(mainwin, "%d%%", evasion); y2++;
@ -6488,8 +6679,77 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
// back to first column // now show bottom information.
y++; if (y2 > y) {
y = y2 + 1;
} else {
y++;
}
// knowledge?
if (lf != player) {
char knowstring[BUFLEN];
switch (lorelev ){
case PR_NOVICE:
strcpy(knowstring, "You have heard of this creature.");
break;
case PR_BEGINNER:
strcpy(knowstring, "You know a little about this creature.");
break;
case PR_ADEPT:
strcpy(knowstring, "You are fairly knowledgable about this creature.");
break;
case PR_SKILLED:
strcpy(knowstring, "You have studied this creature in depth.");
break;
case PR_EXPERT:
strcpy(knowstring, "You are an expert on this creature.");
break;
case PR_MASTER:
strcpy(knowstring, "You are an absolute authority on this creature.");
break;
default:
strcpy(knowstring, "");
break;
}
if (strlen(knowstring)) {
setcol(mainwin, lorecol);
mvwprintw(mainwin, y, 0, "%s", knowstring);
unsetcol(mainwin, lorecol);
y++;
}
// extra info from lore?
if (lorelev >= PR_ADEPT) {
float rating;
// get threat rating
rating = comparelfs(player, lf);
setcol(mainwin, lorecol);
if (rating >= 4) {
sprintf(buf, "It is not a threat.");
} else if (rating >= 3) {
sprintf(buf, "You could defeat it very easily.");
} else if (rating >= 2) {
sprintf(buf, "You could defeat it quite easily.");
} else if (rating >= 1) {
sprintf(buf, "It would present an average challenge.");
} else if (rating >= 0.5) {
sprintf(buf, "It would be challenging to defeat.");
} else if (rating >= 0.25) {
sprintf(buf, "It would present a formidable opponent.");
} else if (rating >= 0.125) {
sprintf(buf, "It is very dangerous to you.");
} else {
sprintf(buf, "It is EXTREMELY dangerous to you.");
}
//mvwprintw(mainwin, y, 0, "Threat rating: %0.1f",comparelfs(player, lf));
mvwprintw(mainwin, y, 0, "%s", buf);
unsetcol(mainwin, lorecol);
y++;
}
}
// obvious physical effects here. // obvious physical effects here.
f = lfhasknownflag(lf, F_ASLEEP); f = lfhasknownflag(lf, F_ASLEEP);
@ -6875,6 +7135,7 @@ void showlfstats(lifeform_t *lf, int showall) {
char powerbuf[BUFLEN]; char powerbuf[BUFLEN];
int power; int power;
int mpcost; int mpcost;
int castable = B_TRUE;
// power // power
power = getspellpower(lf, ot->id); power = getspellpower(lf, ot->id);
@ -6907,10 +7168,15 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
} }
if ((mpcost > getmaxmp(lf)) || (power <= 0)) {
castable = B_FALSE;
}
getspellname(ot->id, lf, spellname); getspellname(ot->id, lf, spellname);
sprintf(buf, " %-4d%-26s%-15s%-13s%s",thislev, spellname, getschoolnameshort(getspellschool(ot->id)), powerbuf, mpbuf); if (!castable) setcol(mainwin, C_RED);
sprintf(buf, " %-4d%-26s%-15s%-13s%s",thislev, spellname, getschoolnameshort(getspellschoolknown(lf, ot->id)), powerbuf, mpbuf);
mvwprintw(mainwin, y, 0, "%s\n", buf); mvwprintw(mainwin, y, 0, "%s\n", buf);
if (!castable) unsetcol(mainwin, C_RED);
anyfound = B_TRUE; anyfound = B_TRUE;
if (downline(&y, h, "MAGIC", subheading, prompt, cmdchars, &ch)) { if (downline(&y, h, "MAGIC", subheading, prompt, cmdchars, &ch)) {
exitnow = B_TRUE; exitnow = B_TRUE;
@ -6925,6 +7191,7 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s cannot cast any spells.", you(lf)); mvwprintw(mainwin, y, 0, "%s cannot cast any spells.", you(lf));
} }
} else if (mode == 'e') { } else if (mode == 'e') {
int nfound = 0;
x = 0; // override x = 0; // override
// down a line. // down a line.
centre(mainwin, y, "EFFECTS"); centre(mainwin, y, "EFFECTS");
@ -6945,6 +7212,26 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; y++;
} }
// spells
nfound = 0;
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_BOOSTSPELL) {
objecttype_t *sp;
sp = findot(f->val[0]);
if (sp) {
if (nfound == 0) {
mvwprintw(mainwin, y, 0, "%s %s the following spells active:", you(lf),
isplayer(lf) ? "have" : "has");
y++;
}
mvwprintw(mainwin, y, 0, " - %s", sp->name);
y++;
nfound++;
}
}
}
if (nfound) y++;
// obvious physical effects first. // obvious physical effects first.
f = lfhasknownflag(lf, F_BEINGSTONED); f = lfhasknownflag(lf, F_BEINGSTONED);
if (f) { if (f) {
@ -6966,6 +7253,13 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; y++;
} }
// flags which aren't really intrinsics
if (lfhasflag(lf, F_VEGETARIAN)) {
mvwprintw(mainwin, y, 0, "%s %s a vegetarian.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
// show intrinsics // show intrinsics
f = lfhasknownflag(lf, F_ATTRSET); f = lfhasknownflag(lf, F_ATTRSET);
if (f && (f->known)) { if (f && (f->known)) {

1
io.h
View File

@ -74,6 +74,7 @@ int drop(object_t *o, int count);
char getchoice(prompt_t *prompt); char getchoice(prompt_t *prompt);
char getchoicestr(prompt_t *prompt, int useshortcuts, int showlallatstart); char getchoicestr(prompt_t *prompt, int useshortcuts, int showlallatstart);
int getkey(void); int getkey(void);
enum COLOUR getskilllevelcolour(enum SKILLLEVEL slev);
void handleinput(void); void handleinput(void);
void doheading(WINDOW *win, int *y, int x, char *what); void doheading(WINDOW *win, int *y, int x, char *what);
void initgfx(void); void initgfx(void);

1317
lf.c

File diff suppressed because it is too large Load Diff

16
lf.h
View File

@ -3,9 +3,11 @@
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, int glyphcolour, enum MATERIAL mat); race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat, enum RACECLASS raceclass);
raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill);
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);
void applywalkdam(lifeform_t *lf, int dam, enum DAMTYPE damtype, object_t *o);
int areallies(lifeform_t *lf1, lifeform_t *lf2); int areallies(lifeform_t *lf1, lifeform_t *lf2);
int areenemies(lifeform_t *lf1, lifeform_t *lf2); int areenemies(lifeform_t *lf1, lifeform_t *lf2);
void autoskill(lifeform_t *lf); void autoskill(lifeform_t *lf);
@ -30,10 +32,12 @@ int canweild(lifeform_t *lf, object_t *o);
int cantakeoff(lifeform_t *lf, object_t *o); int cantakeoff(lifeform_t *lf, object_t *o);
int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell); int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell);
void checkxp(enum RACE rid); void checkxp(enum RACE rid);
float comparelfs(lifeform_t *lf1, lifeform_t *lf2);
int countmoney(lifeform_t *lf); int countmoney(lifeform_t *lf);
int countnearbyallies(lifeform_t *lf); int countnearbyallies(lifeform_t *lf);
void debug(lifeform_t *lf); void debug(lifeform_t *lf);
void die(lifeform_t *lf); void die(lifeform_t *lf);
void dumplev(void);
void dumplf(void); void dumplf(void);
void dumpxp(void); void dumpxp(void);
int eat(lifeform_t *lf, object_t *o); int eat(lifeform_t *lf, object_t *o);
@ -46,6 +50,7 @@ job_t *findjobbyname(char *name);
lifeform_t *findlf(map_t *m, int lfid); lifeform_t *findlf(map_t *m, int lfid);
race_t *findrace(enum RACE id); race_t *findrace(enum RACE id);
race_t *findracebyname(char *name); race_t *findracebyname(char *name);
raceclass_t *findraceclass(enum RACECLASS id);
skill_t *findskill(enum SKILL id); skill_t *findskill(enum SKILL id);
skill_t *findskillbyname(char *name); skill_t *findskillbyname(char *name);
enum SKILLLEVEL findskilllevbyname(char *name); enum SKILLLEVEL findskilllevbyname(char *name);
@ -65,6 +70,7 @@ int getattackspeed(lifeform_t *lf);
int getattpoints(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 real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset); int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset);
int getavgdam(lifeform_t *lf, int forxp);
int getevasion(lifeform_t *lf); int getevasion(lifeform_t *lf);
object_t *getbestthrowmissile(lifeform_t *lf); object_t *getbestthrowmissile(lifeform_t *lf);
object_t *getbestweapon(lifeform_t *lf); object_t *getbestweapon(lifeform_t *lf);
@ -78,6 +84,8 @@ lifeform_t *getguntarget(lifeform_t *lf);
int getguntargetid(lifeform_t *lf); int getguntargetid(lifeform_t *lf);
//int gethealtime(lifeform_t *lf); //int gethealtime(lifeform_t *lf);
int gethearingrange(lifeform_t *lf); int gethearingrange(lifeform_t *lf);
int gethidemodifier(lifeform_t *lf);
int gethitdice(lifeform_t *lf);
int gethppct(lifeform_t *lf); int gethppct(lifeform_t *lf);
enum HUNGER gethungerlevel(int hunger); enum HUNGER gethungerlevel(int hunger);
char * gethungername(enum HUNGER hunger, char *buf); char * gethungername(enum HUNGER hunger, char *buf);
@ -87,10 +95,12 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep);
enum LFCONDITION getlfcondition(lifeform_t *lf); 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);
object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp);
enum LFCONDITION getseenlfconditioncutoff(lifeform_t *lf); enum LFCONDITION getseenlfconditioncutoff(lifeform_t *lf);
char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer); char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer);
glyph_t *getlfglyph(lifeform_t *lf); glyph_t *getlfglyph(lifeform_t *lf);
enum MATERIAL getlfmaterial(lifeform_t *lf); enum MATERIAL getlfmaterial(lifeform_t *lf);
enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid);
float getmaxcarryweight(lifeform_t *lf); float getmaxcarryweight(lifeform_t *lf);
float getmaxliftweight(lifeform_t *lf); float getmaxliftweight(lifeform_t *lf);
int getmaxmp(lifeform_t *lf); int getmaxmp(lifeform_t *lf);
@ -113,6 +123,7 @@ char *getplayernamefull(char *buf);
int getpoisondamchance(enum POISONTYPE ptype); int getpoisondamchance(enum POISONTYPE ptype);
char *getpoisondamverb(enum POISONTYPE ptype); char *getpoisondamverb(enum POISONTYPE ptype);
char *getpoisonname(enum POISONTYPE ptype); char *getpoisonname(enum POISONTYPE ptype);
int getraceclass(lifeform_t *lf);
int getracerarity(enum RACE rid); 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);
@ -169,6 +180,7 @@ int isgenius(lifeform_t *lf);
int isimmobile(lifeform_t *lf); int isimmobile(lifeform_t *lf);
flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt); flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt);
int isingunrange(lifeform_t *lf, cell_t *where); int isingunrange(lifeform_t *lf, cell_t *where);
int isloreskill(enum SKILL skid);
int ismaxedskill(lifeform_t *lf, enum SKILL skid); int ismaxedskill(lifeform_t *lf, enum SKILL skid);
int ispeaceful(lifeform_t *lf); int ispeaceful(lifeform_t *lf);
int ispetof(lifeform_t *lf, lifeform_t *owner); int ispetof(lifeform_t *lf, lifeform_t *owner);
@ -188,8 +200,10 @@ void losemp(lifeform_t *lf, int amt);
void makefriendly(lifeform_t *lf, int howlong); void makefriendly(lifeform_t *lf, int howlong);
void makenauseated(lifeform_t *lf, int amt, int howlong); void makenauseated(lifeform_t *lf, int amt, int howlong);
void makenoise(lifeform_t *lf, enum NOISETYPE nid); void makenoise(lifeform_t *lf, enum NOISETYPE nid);
void makepeaceful(lifeform_t *lf);
lifeform_t *makezombie(object_t *o); lifeform_t *makezombie(object_t *o);
void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how); void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how);
int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o);
int modattr(lifeform_t *lf, enum ATTRIB attr, int amt); int modattr(lifeform_t *lf, enum ATTRIB attr, int amt);
void modhunger(lifeform_t *lf, int amt); void modhunger(lifeform_t *lf, int amt);
float modifybystat(float num, lifeform_t *lf, enum ATTRIB att); float modifybystat(float num, lifeform_t *lf, enum ATTRIB att);

3615
log.txt

File diff suppressed because it is too large Load Diff

161
map.c
View File

@ -22,6 +22,8 @@ extern glyph_t tempglyph;
extern enum OBCLASS sortorder[]; extern enum OBCLASS sortorder[];
extern enum ERROR reason;
cell_t *addcell(map_t *m, int x, int y) { cell_t *addcell(map_t *m, int x, int y) {
cell_t *cell; cell_t *cell;
m->cell[(y*m->w)+x] = malloc(sizeof(cell_t)); m->cell[(y*m->w)+x] = malloc(sizeof(cell_t));
@ -80,7 +82,8 @@ map_t *addmap(void) {
} }
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) { // when monsters are made during level generation, autogen will be true. otherwise false;
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen) {
lifeform_t *lf = NULL; lifeform_t *lf = NULL;
race_t *r; race_t *r;
int db = B_FALSE; int db = B_FALSE;
@ -116,7 +119,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
} }
} }
if (lf->cell->map->beingcreated) { //if (lf->cell->map->beingcreated) {
if (autogen) {
// sometimes start off asleep in new maps // sometimes start off asleep in new maps
if (!lfhasflag(lf, F_DEAF)) { if (!lfhasflag(lf, F_DEAF)) {
// TODO: base this on the time, and whether monster is nocturnal // TODO: base this on the time, and whether monster is nocturnal
@ -124,64 +128,77 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
} }
} }
f = lfhasflag(lf, F_STARTHIDDENPCT);
if (f) {
if (rnd(1,100) <= f->val[0]) {
// note: if we start off hidden, we have no hide penalty.
// this is so we can have monsters which start hidden, but
// don't have the 'hide' skill.
addflag(lf->flags, F_HIDING, 0, NA, NA, NULL);
}
}
} }
// appears in groups? // appears in groups?
f = hasflag(lf->flags, F_NUMAPPEAR); if (autogen) {
if (f) { f = hasflag(lf->flags, F_NUMAPPEAR);
// override amount if (f) {
amt = rnd(f->val[0], f->val[1]); // override amount
} amt = rnd(f->val[0], f->val[1]);
if (amt > 1) { }
cell_t *adjcell; if (amt > 1) {
amt--; // we've already added one cell_t *adjcell;
amt--; // we've already added one
//adjcell = c; //adjcell = c;
for ( ; amt > 0; amt--) { for ( ; amt > 0; amt--) {
lifeform_t *newlf; lifeform_t *newlf;
// find an adjacent cell to one of the newly added monsters, // find an adjacent cell to one of the newly added monsters,
// starting with the first one // starting with the first one
adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND); adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
// did we find one? // did we find one?
if (!adjcell) break; if (!adjcell) break;
newlf = addlf(adjcell, r->id, 1);
if (!newlf) {
break;
}
newlf->born = B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
newlf->born = B_TRUE;
newlf = addlf(adjcell, r->id, 1);
if (!newlf) {
break;
} }
newlf->born = B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
newlf->born = B_TRUE;
} }
} }
// minons? // minons?
f = hasflag(lf->flags, F_MINIONS); if (autogen) {
if (f) { f = hasflag(lf->flags, F_MINIONS);
if (rnd(1,100) <= f->val[0]) { if (f) {
int n; if (rnd(1,100) <= f->val[0]) {
cell_t *adjcell; int n;
int nminions; cell_t *adjcell;
// override amount int nminions;
nminions = rnd(f->val[1], f->val[2]); // override amount
nminions = rnd(f->val[1], f->val[2]);
for (n = 0; n < nminions; n++) { for (n = 0; n < nminions; n++) {
lifeform_t *newlf; lifeform_t *newlf;
race_t *newr; race_t *newr;
adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND); adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
if (!adjcell) break; if (!adjcell) break;
newr = findracebyname(f->text); newr = findracebyname(f->text);
if (!newr) break; if (!newr) break;
newlf = addlf(adjcell, newr->id, 1); newlf = addlf(adjcell, newr->id, 1);
if (!newlf) break; if (!newlf) break;
newlf->born = B_FALSE; newlf->born = B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL); if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
newlf->born = B_TRUE; newlf->born = B_TRUE;
}
} }
} }
} }
@ -228,7 +245,7 @@ void addrandomthing(cell_t *c, int obchance) {
addrandomob(c); addrandomob(c);
} else { } else {
// monster // monster
addmonster(c, R_RANDOM, B_TRUE, 1); addmonster(c, R_RANDOM, B_TRUE, 1, B_TRUE);
} }
} }
@ -454,9 +471,12 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
*g = *(getglyph(o)); *g = *(getglyph(o));
} }
// show dungeon features // show dungeon features
o = hasobofclass(c->obpile, OC_DFEATURE); for (o = c->obpile->first ; o ; o = o->next) {
if (o) { if (o->type->obclass->id == OC_DFEATURE) {
*g = *(getglyph(o)); if (!issecretdoor(o)) {
*g = *(getglyph(o));
}
}
} }
} }
break; break;
@ -1938,6 +1958,10 @@ int getobchance(int habitat) {
} }
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) { cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) {
return real_getrandomadjcell(c, wantempty, allowexpand, NULL);
}
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum OBTYPE *dontwantob) {
int radius = 1; int radius = 1;
int x,y; int x,y;
cell_t *poss[MAXCANDIDATES]; cell_t *poss[MAXCANDIDATES];
@ -1951,24 +1975,44 @@ cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) {
for (x = c->x - radius ; x <= c->x + radius ; x++) { for (x = c->x - radius ; x <= c->x + radius ; x++) {
new = getcellat(c->map, x, y); new = getcellat(c->map, x, y);
if (new && (getcelldist(c,new) == radius) && haslof(c, new, LOF_WALLSTOP, NULL)) { if (new && (getcelldist(c,new) == radius) && haslof(c, new, LOF_WALLSTOP, NULL)) {
enum OBTYPE *badoid;
int ok = B_FALSE;
numwithlof++; numwithlof++;
if (wantempty == WE_EMPTY) { if (wantempty == WE_EMPTY) {
// make sure it's empty // make sure it's empty
if (isempty(new)) { if (isempty(new)) {
poss[nposs++] = new; ok = B_TRUE;
} }
} else if (wantempty == WE_WALKABLE) { } else if (wantempty == WE_WALKABLE) {
if (cellwalkable(NULL, new, NULL)) { if (cellwalkable(NULL, new, NULL)) {
poss[nposs++] = new; ok = B_TRUE;
} }
} else if (wantempty == WE_PORTAL) { } else if (wantempty == WE_PORTAL) {
if (cellwalkable(NULL, new, NULL) && !hasenterableobject(new) ) { if (cellwalkable(NULL, new, NULL) && !hasenterableobject(new) ) {
if (!hasobwithflag(new->obpile, F_DOOR)) { if (!hasobwithflag(new->obpile, F_DOOR)) {
poss[nposs++] = new; ok = B_TRUE;
} }
} }
} else if (wantempty == WE_NOTWALL) {
if (!new->type->solid){
ok = B_TRUE;
}
} else { } else {
// always ok // always ok
ok = B_TRUE;
}
// obs we dont want?
if (dontwantob) {
for (badoid = dontwantob; (*badoid != OT_NONE) ; badoid++) {
if (hasob(new->obpile, *badoid)) {
ok = B_FALSE;
break;
}
}
}
if (ok) {
poss[nposs++] = new; poss[nposs++] = new;
} }
} }
@ -2079,16 +2123,19 @@ void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells) {
} }
// returns how slippery this cell is // returns how slippery this cell is
// if slipob is set, return the most slippery object in it.
int getslipperyness(cell_t *c, object_t **slipob) { int getslipperyness(cell_t *c, object_t **slipob) {
object_t *o; object_t *o,*bestob = NULL;
int bestslip = 0;
int totalslip = 0; int totalslip = 0;
if (slipob) *slipob = NULL; if (slipob) *slipob = NULL;
for (o = c->obpile->first ; o ; o = o->next) { for (o = c->obpile->first ; o ; o = o->next) {
int thisslip; int thisslip;
sumflags(o->flags, F_SLIPPERY, &thisslip, NULL, NULL); sumflags(o->flags, F_SLIPPERY, &thisslip, NULL, NULL);
if (thisslip > 0) { if (thisslip > 0) {
if (slipob && (*slipob == NULL)) { if (thisslip > bestslip) {
*slipob = o; bestob = o;
bestslip = thisslip;
} }
} }
thisslip *= o->amt; thisslip *= o->amt;
@ -2097,6 +2144,10 @@ int getslipperyness(cell_t *c, object_t **slipob) {
totalslip *= 2; totalslip *= 2;
if (slipob) {
*slipob = bestob;
}
return totalslip; return totalslip;
} }

3
map.h
View File

@ -2,7 +2,7 @@
cell_t *addcell(map_t *map, int x, int y); cell_t *addcell(map_t *map, int x, int y);
map_t *addmap(void); map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt); lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen);
void addrandomob(cell_t *c); void addrandomob(cell_t *c);
void addrandomthing(cell_t *c, int obchance); void addrandomthing(cell_t *c, int obchance);
int cellhaslos(cell_t *c1, cell_t *dest); int cellhaslos(cell_t *c1, cell_t *dest);
@ -35,6 +35,7 @@ cell_t *getcellindir(cell_t *cell, int dir);
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved); int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
int getobchance(int habitat); int getobchance(int habitat);
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand); cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand);
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum OBTYPE *dontwantob);
cell_t *getrandomcell(map_t *map); cell_t *getrandomcell(map_t *map);
cell_t *getrandomcelloftype(map_t *map, int id); cell_t *getrandomcelloftype(map_t *map, int id);
int getrandomdir(int dirtype); int getrandomdir(int dirtype);

255
move.c
View File

@ -550,8 +550,11 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype ) {
// IMPORTANT: don't modify lf's flagpile during this code! // IMPORTANT: don't modify lf's flagpile during this code!
// particularly don't remove flags... // particularly don't remove flags...
void moveeffects(lifeform_t *lf) {
// returns TRUE if we displayed a message
int moveeffects(lifeform_t *lf) {
flag_t *f; flag_t *f;
int didmsg = B_FALSE;
if (isbleeding(lf)) { if (isbleeding(lf)) {
if (rnd(1,2) == 1) { if (rnd(1,2) == 1) {
@ -562,18 +565,29 @@ void moveeffects(lifeform_t *lf) {
f = lfhasflag(lf, F_PAIN); f = lfhasflag(lf, F_PAIN);
if (f) { if (f) {
if (!isdrunk(lf)) { if (!isdrunk(lf)) {
int dam;
if (isplayer(lf)) { if (isplayer(lf)) {
msg("Your body is wracked with pain!"); msg("Your body is wracked with pain!");
didmsg = B_TRUE;
} else if (cansee(player, lf)) { } else if (cansee(player, lf)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
getlfname(lf, lfname); getlfname(lf, lfname);
msg("%s convulses in pain!",lfname); msg("%s convulses in pain!",lfname);
didmsg = B_TRUE;
} }
losehp(lf, roll(f->text), f->val[0], NULL, "extreme pain");
if (strlen(f->text)) {
dam = roll(f->text);
} else {
dam = roll("1d2");
}
losehp(lf, dam, f->val[0], NULL, "extreme pain");
if (isdead(lf)) return didmsg;
} }
} }
if (isdead(lf)) return;
return didmsg;
} }
@ -586,6 +600,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
flag_t *f; flag_t *f;
int changedlev = B_FALSE; int changedlev = B_FALSE;
int preroom = -1, postroom = -1; int preroom = -1, postroom = -1;
int prespeed = B_FALSE, postspeed = B_FALSE;
getlfname(lf, lfname); getlfname(lf, lfname);
@ -594,8 +609,10 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
// update current cell + room id // update current cell + room id
lf->cell->lf = NULL; prespeed = getmovespeed(lf);
preroom = lf->cell->roomid; preroom = lf->cell->roomid;
lf->cell->lf = NULL;
// if required, relink lifeform to new map // if required, relink lifeform to new map
if (newcell->map != lf->cell->map) { if (newcell->map != lf->cell->map) {
@ -613,6 +630,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// remember new room... // remember new room...
postroom = lf->cell->roomid; postroom = lf->cell->roomid;
postspeed = getmovespeed(lf);
// update new cell // update new cell
newcell->lf = lf; newcell->lf = lf;
@ -622,7 +640,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
calclight(lf->cell->map); calclight(lf->cell->map);
} }
moveeffects(lf); didmsg = moveeffects(lf);
killflagsofid(lf->flags, F_HIDING); killflagsofid(lf->flags, F_HIDING);
@ -770,16 +788,20 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
} }
// status bar
if ((prespeed != postspeed) && isplayer(lf)) {
statdirty = B_TRUE;
}
return didmsg; return didmsg;
} }
// basically this is a warpper for 'movelf' which // basically this is a warpper for 'movelf' which
// does other game things like telling the player // does other game things like telling the player
// what is here. // what is here.
int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose) { int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
char lfname[BUFLEN]; char lfname[BUFLEN];
int didmsg; int didmsg;
int dontclearmsg = B_FALSE;
int predark = B_FALSE,postdark = B_FALSE; int predark = B_FALSE,postdark = B_FALSE;
if (!onpurpose || !isplayer(lf)) { if (!onpurpose || !isplayer(lf)) {
@ -1176,6 +1198,145 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
return B_FALSE; return B_FALSE;
} }
// do pre-move checks like slipping on stuff in your current cell,
// webs, etc.
// cell can be null if you're using stairs.
int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
object_t *o, *nexto;
char buf[BUFLEN];
flag_t *f;
// check for cursed objects in new cell + animals
// do this AFTER checking if we will move, so that
// they will actually try the move and fail (this lets
// the player find out about the cursed object).
//
// note however that if a monster is chasing a player (ie
// has F_TARGET,player) then they will simply avoid the cursed
// object rather than failing the movement.
if (cell) {
for (o = cell->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (!isplayer(lf)) {
if ((o->blessed == B_CURSED) && lfhasflag(lf, F_ANIMAL) && !isairborne(lf)) {
if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf,lfname);
getobname(o, buf, o->amt);
msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf);
o->blessknown = B_TRUE;
if (didmsg) *didmsg = B_TRUE;
}
taketime(lf, getmovespeed(lf));
reason = E_OK;
// avoid this object in future
sprintf(buf, "%ld",o->id);
addflag(lf->flags, F_AVOIDCURSEDOB, NA, NA, NA, buf);
return B_TRUE;
}
}
}
}
// 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!");
if (didmsg) *didmsg = B_TRUE;
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s tries to move but is unable to lift its feet!",lfname);
if (didmsg) *didmsg = B_TRUE;
}
reason = E_OK;
taketime(lf, getmovespeed(lf));
return B_TRUE;
}
}
// sticky objects in current cell?
for (o = lf->cell->obpile->first ; o ; o = nexto) {
nexto = o->next;
if ((o->type->id == OT_WEB) && (lf->race->baseid == R_SPIDER)) {
continue;
}
f = hasflag(o->flags, F_RESTRICTMOVEMENT);
if (f) {
char lfname[BUFLEN];
int diff;
int getsweaker;
getlfname(lf,lfname);
getobname(o, buf, o->amt);
// for stacks of sticky objects, each one after the first adds
// quarter its difficuly. ie:
// 1 x object with f_sticky:20, difficult is 20
// 2 x object with f_sticky:20, difficult is 25
// 3 x object with f_sticky:20, difficult is 30
// etc
// can you break free?
diff = f->val[0];
if (o->amt > 1) {
diff = (o->amt - 1) * ((float)f->val[0] / 4.0);
}
getsweaker = f->val[1];
if (skillcheck(lf, SC_STR, diff, 0)) {
if (isplayer(lf)) {
msg("You tear free from %s!", buf);
if (didmsg) *didmsg = B_TRUE;
} else if (cansee(player, lf)) {
msg("%s tears free from %s!", lfname, buf);
if (didmsg) *didmsg = B_TRUE;
}
killob(o);
continue;
} else {
// failed - object gets a little less sticky
if (isplayer(lf)) {
msg("You struggle in %s!", buf);
if (didmsg) *didmsg = B_TRUE;
} else if (cansee(player, lf)) {
msg("%s struggles in %s!", lfname, buf);
if (didmsg) *didmsg = B_TRUE;
}
if (getsweaker) {
takedamage(o, 1, DT_DIRECT);
}
taketime(lf, getmovespeed(lf));
reason = E_OK;
return B_TRUE;
}
}
}
// slipping on something before moving?
if (!isairborne(lf)) {
int slip;
object_t *slipob;
slip = getslipperyness(lf->cell, &slipob);
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
slipon(lf, slipob);
if (didmsg) *didmsg = B_TRUE;
// don't move
reason = E_OK;
return B_TRUE;
}
}
return B_FALSE;
}
// teleport somewhere, along with puffs of smoke etc // teleport somewhere, along with puffs of smoke etc
int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) { int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) {
char buf[BUFLEN]; char buf[BUFLEN];
@ -1226,6 +1387,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
cell_t *cell; cell_t *cell;
enum ERROR errcode; enum ERROR errcode;
char buf[BUFLEN]; char buf[BUFLEN];
int dontclearmsg = B_FALSE;
flag_t *f; flag_t *f;
f = isdrunk(lf); f = isdrunk(lf);
@ -1240,73 +1402,13 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
cell = getcellindir(lf->cell, dir); cell = getcellindir(lf->cell, dir);
if (canandwillmove(lf, dir, &errcode)) { if (canandwillmove(lf, dir, &errcode)) {
object_t *o,*slipob; if (initiatemove(lf, cell, &dontclearmsg)) {
int slip; // failed?
return B_FALSE;
// check for cursed objects + animals
// do this AFTER checking if we will move, so that
// they will actually try the move and fail (this lets
// the player find out about the cursed object).
//
// note however that if a monster is chasing a player (ie
// has F_TARGET,player) then they will simply avoid the cursed
// object rather than failing the movement.
for (o = cell->obpile->first ; o ; o = o->next) {
if (!isplayer(lf)) {
if (o->blessed == B_CURSED) {
if (lfhasflag(lf, F_ANIMAL)) {
if (!isairborne(lf)) {
if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf,lfname);
getobname(o, buf, o->amt);
msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf);
o->blessknown = B_TRUE;
}
taketime(lf, getmovespeed(lf));
reason = E_OK;
// avoid this object in future
sprintf(buf, "%ld",o->id);
addflag(lf->flags, F_AVOIDCURSEDOB, NA, NA, NA, buf);
return B_FALSE;
}
}
}
}
} }
// slipping on blood before moving?
if (!isairborne(lf)) {
slip = getslipperyness(lf->cell, &slipob);
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
slipon(lf, slipob);
// don't move
reason = E_OK;
return B_FALSE;
}
}
// 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, dontclearmsg);
taketime(lf, getmovespeed(lf)); taketime(lf, getmovespeed(lf));
} else { } else {
object_t *inway = NULL; object_t *inway = NULL;
@ -1428,7 +1530,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
oldcell = lf->cell; oldcell = lf->cell;
// move you.. // move you..
moveto(lf, cell, onpurpose); moveto(lf, cell, onpurpose, B_FALSE);
taketime(lf, getmovespeed(lf)); taketime(lf, getmovespeed(lf));
// move them... // move them...
@ -1463,7 +1565,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
killflagsofid(lf->flags, F_GRABBEDBY); killflagsofid(lf->flags, F_GRABBEDBY);
killflagsofid(grabbedby->flags, F_GRABBING); killflagsofid(grabbedby->flags, F_GRABBING);
// move - don't clear the 'you break free from' msg // move - don't clear the 'you break free from' msg
moveto(lf, cell, B_TRUE); moveto(lf, cell, B_TRUE, B_TRUE);
} else { } else {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You cannot get away from %s!",gbname); msg("You cannot get away from %s!",gbname);
@ -1523,6 +1625,13 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
// don't attack other monsters // don't attack other monsters
if (cell->lf) { // if someone is in the way if (cell->lf) { // if someone is in the way
if (lf->race->raceclass->id == RC_INSECT) {
if (hasactivespell(cell->lf, OT_S_REPELINSECTS)) {
if (error) *error = E_WONT;
return B_FALSE;
}
}
if (!isplayer(lf)) { // if we are a monster if (!isplayer(lf)) { // if we are a monster
// if the person in the way isn't our enemy... // if the person in the way isn't our enemy...
if (!areenemies(lf, cell->lf)) { if (!areenemies(lf, cell->lf)) {

5
move.h
View File

@ -13,13 +13,14 @@ int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int d
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 dirtype); int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype);
void moveeffects(lifeform_t *lf); int 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 dontclearmsg);
int movetowards(lifeform_t *lf, cell_t *dst, int dirtype); 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);
int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg);
int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke); int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke);
int trymove(lifeform_t *lf, int dir, int onpurpose); int trymove(lifeform_t *lf, int dir, int onpurpose);
int tryrun(lifeform_t *lf, int dir); int tryrun(lifeform_t *lf, int dir);

16
nexus.c
View File

@ -25,6 +25,7 @@ obmod_t *firstobmod = NULL,*lastobmod = NULL;
celltype_t *firstcelltype = NULL,*lastcelltype = NULL; celltype_t *firstcelltype = NULL,*lastcelltype = NULL;
command_t *firstcommand = NULL,*lastcommand = NULL; command_t *firstcommand = NULL,*lastcommand = NULL;
race_t *firstrace = NULL,*lastrace = NULL; race_t *firstrace = NULL,*lastrace = NULL;
raceclass_t *firstraceclass = NULL,*lastraceclass = NULL;
job_t *firstjob = NULL,*lastjob = NULL; job_t *firstjob = NULL,*lastjob = NULL;
skill_t *firstskill = NULL,*lastskill = NULL; skill_t *firstskill = NULL,*lastskill = NULL;
map_t *firstmap = NULL,*lastmap = NULL; map_t *firstmap = NULL,*lastmap = NULL;
@ -160,6 +161,7 @@ int main(int argc, char **argv) {
} }
} }
// find staircase // find staircase
where = findobinmap(firstmap, OT_STAIRSUP); where = findobinmap(firstmap, OT_STAIRSUP);
assert(where); assert(where);
@ -177,14 +179,26 @@ int main(int argc, char **argv) {
addflag(player->flags, F_NAME, NA, NA, NA, "Anonymous"); addflag(player->flags, F_NAME, NA, NA, NA, "Anonymous");
} }
givejob(player, j->id); givejob(player, j->id);
// special case: // special cases for jobs:
if (j->id == J_PIRATE) { if (j->id == J_PIRATE) {
flag_t *f; flag_t *f;
f = lfhasflagval(player, F_HASATTACK, OT_FISTS, NA, NA, NULL); f = lfhasflagval(player, F_HASATTACK, OT_FISTS, NA, NA, NULL);
assert(f); assert(f);
f->val[0] = OT_HOOKHAND; f->val[0] = OT_HOOKHAND;
sprintf(f->text, "1d4"); sprintf(f->text, "1d4");
} else if (j->id == J_WIZARD) {
skill_t *sk;
initprompt(&prompt, "Select your spell specialty:");
addchoice(&prompt, 'a', getskillname(SK_SS_AIR), NULL, findskill(SK_SS_AIR));
addchoice(&prompt, 'i', getskillname(SK_SS_ICE), NULL, findskill(SK_SS_ICE));
addchoice(&prompt, 'f', getskillname(SK_SS_FIRE), NULL, findskill(SK_SS_FIRE));
getchoice(&prompt);
sk = (skill_t *) prompt.result;
giveskill(player, sk->id);
} }
// read cheat info from player file // read cheat info from player file
if (playerfile) { if (playerfile) {
if (parseplayerfile(playerfile, player)) { if (parseplayerfile(playerfile, player)) {

1440
objects.c

File diff suppressed because it is too large Load Diff

View File

@ -125,6 +125,7 @@ int isblessknown(object_t *o);
int iscorpse(object_t *o); int iscorpse(object_t *o);
int iscursed(object_t *o); int iscursed(object_t *o);
int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown); int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown);
int isdeadob(object_t *o);
int isdrinkable(object_t *o); int isdrinkable(object_t *o);
int isedible(object_t *o); int isedible(object_t *o);
flag_t *isequipped(object_t *o); flag_t *isequipped(object_t *o);
@ -188,6 +189,7 @@ object_t *relinkob(object_t *src, obpile_t *dst);
void setblessed(object_t *o, enum BLESSTYPE wantbless); void setblessed(object_t *o, enum BLESSTYPE wantbless);
void setinscription(object_t *o, char *text); void setinscription(object_t *o, char *text);
void setobcreatedby(object_t *o, lifeform_t *lf); void setobcreatedby(object_t *o, lifeform_t *lf);
void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf);
void shufflehiddennames(void); void shufflehiddennames(void);
object_t *splitob(object_t *o); object_t *splitob(object_t *o);
int takedamage(object_t *o, unsigned int howmuch, int damtype); int takedamage(object_t *o, unsigned int howmuch, int damtype);

6
save.c
View File

@ -199,7 +199,11 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted); if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted);
// lf flags // clear existing flags from addlf
while (l->flags->first) {
killflag(l->flags->first);
}
// load lf flags
loadflagpile(f, l->flags); loadflagpile(f, l->flags);
if (db) dblog("--> now loading objects"); if (db) dblog("--> now loading objects");

1029
spell.c

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,9 @@ int getspellmaxpower(enum OBTYPE spellid);
char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf); char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf);
int getspellpower(lifeform_t *lf, enum OBTYPE spellid); int getspellpower(lifeform_t *lf, enum OBTYPE spellid);
enum SPELLSCHOOL getspellschool(enum OBTYPE spellid); enum SPELLSCHOOL getspellschool(enum OBTYPE spellid);
enum SPELLSCHOOL getspellschoolknown(lifeform_t *lf, enum OBTYPE spellid);
int getspellrange(enum OBTYPE spellid, int power); int getspellrange(enum OBTYPE spellid, int power);
char *getvarpowerspelldesc(enum OBTYPE spellid, int power, char *buf);
void pullobto(object_t *o, lifeform_t *lf); void pullobto(object_t *o, lifeform_t *lf);
void stopspell(lifeform_t *caster, enum OBTYPE spellid); void stopspell(lifeform_t *caster, enum OBTYPE spellid);
void stopallspells(lifeform_t *lf); void stopallspells(lifeform_t *lf);

37
text.c
View File

@ -4,6 +4,7 @@
#include <string.h> #include <string.h>
#include "defs.h" #include "defs.h"
#include "lf.h" #include "lf.h"
#include "nexus.h"
#include "objects.h" #include "objects.h"
#include "text.h" #include "text.h"
@ -113,6 +114,38 @@ char *getattrname(enum ATTRIB att) {
return "?badattrib?"; return "?badattrib?";
} }
int gethitconferlifetime(char *text, int *min, int *max) {
int howlong;
int localmin,localmax;
if (text) {
char loctext[BUFLEN];
char *word, *dummy;
strcpy(loctext,text);
word = strtok_r(loctext, "-", &dummy);
if (word) {
localmin = atoi(word);
word = strtok_r(NULL, "-", &dummy);
if (word) {
localmax = atoi(word);
howlong = rnd(localmin,localmax);
} else {
howlong = PERMENANT;
}
} else {
localmin = -1;
localmax = -1;
howlong = PERMENANT;
}
} else {
localmin = -1;
localmax = -1;
howlong = PERMENANT;
}
if (min) *min = localmin;
if (max) *max = localmax;
return howlong;
}
char *getpossessive(char *text) { char *getpossessive(char *text) {
char lastchar; char lastchar;
// you -> your // you -> your
@ -406,6 +439,10 @@ char *roman(int num) {
return ""; return "";
} }
int speedtokph(int speed) {
return speed * speed * speed;
}
void splittime(int *hours, int *mins, int *secs) { void splittime(int *hours, int *mins, int *secs) {
long left; long left;
left = curtime; left = curtime;

2
text.h
View File

@ -6,6 +6,7 @@ char *capitaliseall(char *text);
char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf); char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf);
char *getattrabbrev(enum ATTRIB att); char *getattrabbrev(enum ATTRIB att);
char *getattrname(enum ATTRIB att); char *getattrname(enum ATTRIB att);
int gethitconferlifetime(char *text, int *min, int *max);
char *getpossessive(char *text); char *getpossessive(char *text);
char *getdrunktext(flag_t *drunkflag); char *getdrunktext(flag_t *drunkflag);
char *getsizetext(enum LFSIZE sz); char *getsizetext(enum LFSIZE sz);
@ -19,6 +20,7 @@ int needses(char *text);
char *noprefix(char *obname); char *noprefix(char *obname);
char *numtotext(int num, char *buf); char *numtotext(int num, char *buf);
char *roman(int num); char *roman(int num);
int speedtokph(int speed);
void splittime(int *hours, int *mins, int *secs); void splittime(int *hours, int *mins, int *secs);
char *strrep(char *text, char *oldtok, char *newtok, int *rv); char *strrep(char *text, char *oldtok, char *newtok, int *rv);
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv); char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv);